grpc / grpc-swift

The Swift language implementation of gRPC.
Apache License 2.0
2.04k stars 420 forks source link

Develop code generation for gRPC Services. #2

Closed timburks closed 7 years ago

timburks commented 8 years ago

Currently there is no code generation for gRPC services. This needs to be added either to the swift-proto plugin or to a separate plugin.

jcanizales commented 8 years ago

As a separate plugin, per Thomas' reasoning in https://github.com/apple/swift-protobuf/issues/118 :)

johndpope commented 8 years ago

From the look of objective-c generator / it's intermingled into visual studio at some point. https://github.com/grpc/grpc/blob/master/vsprojects/grpc_objective_c_plugin/grpc_objective_c_plugin.vcxproj

objective-c generator https://github.com/bazelbuild/bazel/blob/master/third_party/grpc/src/compiler/objective_c_plugin.cc

Part 1) Need to choose language to spit out swift service class Does it make most sense to use swift? or cpp? Could we cherry pick from Apple's implementation? https://github.com/jcanizales/swift-protobuf-plugin/blob/master/Sources/FileGenerator.swift thoughts?

Part 2) create a canonical gist with http2 service layer to plug into this various protobuf swift files. https://github.com/grpc/grpc/blob/master/src/objective-c/examples/SwiftSample/ViewController.swift

screen shot 2016-11-04 at 13 26 48

https://github.com/nathanborror/swift-grpc

screen shot 2016-11-04 at 19 32 53
johndpope commented 8 years ago

I've been looking into different widgets to get job done - I'd say we'd need a protobuf parser as first step - which led me to this grammar file https://raw.githubusercontent.com/notak/tinyproto/36e44b3c04a55d754bf1125d4e527423c659fe9b/src/main/antlr4/me/taks/proto/Protobuf.g4

so - if we throw this at antlr-swift https://github.com/janyou/ANTLR-Swift-Target we'd have a protobuf parser/lexar/tokenizer in swift - which would spit out a full AST from there we'd expose all the methods / service calls for respective proto file

I think biting the bullet and going Swift is nice scenic route. c++ while it will work - will be hard(er) for future offshoot libraries to hot wire. (like Alamofire swapping in their libraries) The other alternative is to cherry pick Apple's protobuf source code.

We can then plug into antlr swift runtime https://github.com/janyou/Antlr-Swift-Runtime.git

DRAFTED https://github.com/johndpope/Antlr-Swift-Runtime/tree/master/Test/Test

jcanizales commented 8 years ago

Oh, but protoc will parse the .proto files for us already. The usual setup is protoc executes your plugin in a separate process, writes a serialized CodeGeneratorRequest to its stdin, and then reads a serialized CodeGeneratorResponse from its stdout.

So the plugin can be written in Swift alright, and just needs to conform to that protocol to get the parsing for free.

johndpope commented 8 years ago

then cherry picking Apple's work is best option. https://github.com/apple/swift-protobuf/blob/bf53b0b56ca611c8fa634006c846a87bb6f2d079/Sources/protoc-gen-swift/Context.swift

https://github.com/apple/swift-protobuf/blob/bf53b0b56ca611c8fa634006c846a87bb6f2d079/Reference/google/protobuf/compiler/plugin.pb.swift

Then we just need the canonical example. IF proto file looks like this

service MasterService {
  // Creates a session.
  rpc CreateSession(CreateSessionRequest) returns (CreateSessionResponse);

  // Extends a session.
  rpc ExtendSession(ExtendSessionRequest) returns (ExtendSessionResponse);

  // Prepares future partial run calls.
  rpc PartialRunSetup(PartialRunSetupRequest) returns (PartialRunSetupResponse);

  // Drives the graph computation.
  rpc RunStep(RunStepRequest) returns (RunStepResponse);

  // Closes a session.
  rpc CloseSession(CloseSessionRequest) returns (CloseSessionResponse);

  // List the devices usable by the master.
  rpc ListDevices(ListDevicesRequest) returns (ListDevicesResponse);

  // Close all existing sessions.
  rpc Reset(ResetRequest) returns (ResetResponse);
}

then ....

fill in the gaps

....

johndpope commented 7 years ago

This Edge framework for server side swift seems like nice path forward (albeit not suitable for ios) https://github.com/SwiftOnEdge/Edge

johndpope commented 7 years ago

So - need to commit to specific interoperable network library. https://www.reddit.com/r/swift/comments/57m49o/how_to_make_a_network_request_on_linux/ Presumably - the limitations of urlsession across different platforms is still the case?

I found this - a swifty version of libcurl wrapped around IBMs' swift libcurl. https://github.com/dmcyk/SwiftyCurl/

@jcanizales - did you envisage the RxLibrary having a life beyond objective-c? I read in comments - you said it should eventually be separated from grpc library. or should a swifty alternative be sought? rxswift ? I'm thinking the use case being swift server to server communications for microservices.

jcanizales commented 7 years ago

RxLibrary, like many others, is nicer to use from Swift than ObjC. And it can be used standalone by just depending on the gRPC-RxLibrary cocoapod. But Swift's generics can be used to create a still nicer Swift version of the library.

I've had in my mind, for a while, to create a doc comparing proposed surfaces for Swift gRPC: one using RxSwift, the other ReactiveSwift, and what we have today from importing the ObjC library.

Between RxSwift and ReactiveSwift, I personally think having different types for "hot" and "cold" streams is a better idea. But from the POV of the user, it's best if it matches whatever rx library you're already using in your app. That means that either:

johndpope commented 7 years ago

fyi https://github.com/IBM-Swift/CCurl/issues/10 IBM's banking on fully deprecating ccurl as a result of Apple presumably getting around to rewriting nsurlsession for server side (hopefully by swift4?) - we could lock that in and cross fingers it will be future proof (in the future).
The only reservation I have with using rxlibrary is it's introducing objective-c which we superseded in the design up until this point. I've heard good things about rxswift. Whereas reactiveswift has reactivecocoa dependencies (& with carthage it is a bit of pain) https://github.com/KevinVitale/ReactiveJSON/issues/7 for the document with pros + cons - you could throw a gist up or share google sheet doc.

timburks commented 7 years ago

With this commit, there's a code generating plugin in the Plugins directory that generates client and server stubs for all four API types (Unary, Server Streaming, Client Streaming, Bidi Streaming). The plugin uses templates in the Plugins/templates directory and currently these must be in the same directory where the plugin is run. Templates use Kyle Fuller's Stencil package and will hopefully be easy to modify with improvements or for other calling styles. The current generated code surface closely follows the Go grpc generator.

johndpope commented 7 years ago

@timburks - thanks for your efforts here - pleased to say I got the service classes spat out (untested) for tensorflow. https://github.com/nubbel/swift-tensorflow/