gRPC
In addition to running Reboot servicers, a Reboot application can also run
"legacy" gRPC servicers, i.e., classes that implement a gRPC service
. This is a particularly useful setup
during a multi-service migration from gRPC to Reboot or when needing
to pull in pre-existing service implementations that do not use Reboot.
This feature is not yet implemented for TypeScript. Please reach out if it would be important for you!
To include a gRPC servicer in a Reboot application, pass its class into a
Reboot Application
with the legacy_grpc_servicers
parameter.
await Application(
servicers=[RebootGreeterServicer] + reboot.aio.memoize.servicers(),
legacy_grpc_servicers=[
DeprecatedGreeterServicer, ProxyGreeterServicer
],
initialize=initialize,
).run()
google.api.http
Reboot exposes support for the google.api.http
annotations on legacy gRPC methods allowing you to expose them
as arbitrary HTTP endpoints.
To expose a legacy gRPC method as an HTTP endpoint, annotate it
with google.api.http
options:
// Return the current time once.
rpc CurrentTime(google.protobuf.Empty) returns (Time) {
option (google.api.http) = {
// Also make this method available via GET, at a custom path.
get: "/current_time"
};
}
...and then call it using any HTTP client:
$ curl -XGET localhost:9991/current_time
...
Calling a legacy gRPC servicer from a Reboot servicer
Reboot readers
, writers
, transactions
, and workflows
can use their passed-in
context
to
construct gRPC channels and
call methods on legacy gRPC servicers. Here is an example:
async with context.legacy_grpc_channel() as channel:
# Now that we have a channel for our legacy servicer, we can call
# its gRPC methods in the standard gRPC fashion.
deprecated_greeter_stub = greeter_pb2_grpc.DeprecatedGreeterStub(
channel
)
salutation_response = await deprecated_greeter_stub.GetSalutation(
Empty()
)
Calling a Reboot servicer from a legacy gRPC servicer
When you run a legacy gRPC servicer using Reboot we will pass a
LegacyGrpcContext
instead of a grpc.ServicerContext
to each of the legacy
gRPC servicers methods.
LegacyGrpcContext
is a custom subclass of grpc.ServicerContext
that adds the ability to construct a
Reboot ExternalContext
. The servicer can then use the ExternalContext
to act as a client for Reboot servicers.
For example, here is a Greet
method of a legacy gRPC servicer getting an
ExternalContext
to make a call:
async def Greet(
self,
request: greeter_pb2.GreetRequest,
legacy_context: LegacyGrpcContext,
) -> greeter_pb2.GreetResponse:
# As part of a migration, one may want to slowly ramp up traffic to the
# new Reboot service. This proxy servicer will forward traffic to
# either the RebootGreeter or the DeprecatedGreeter with a 50/50
# ratio.
context = legacy_context.external_context(
name="Call into `RebootGreeter`"
)
if random.random() < 0.5:
# Route to RebootGreeter.
reboot_greeter = RebootGreeter.ref("my-greeter")
return await reboot_greeter.Greet(context, name=request.name)
else:
# Route to DeprecatedGreeter.
async with context.legacy_grpc_channel() as channel:
deprecated_greeter_stub = greeter_pb2_grpc.DeprecatedGreeterStub(
channel
)
return await deprecated_greeter_stub.Greet(request)