Other interfaces
Reboot clients can interface with an application in a variety of ways, including Reboot native gRPC, Websockets, Standard gRPC, and HTTP.
Reboot has special affordances for calling standard gRPC from Python. TypeScript support coming soon.
Reboot native gRPC
Reboot relies on gRPC internally, but adds some additional features and syntax to tie gRPC services and implementations to state data types.
There are a handful of headers (gRPC metadata) that have to be set in order to call methods on your state, but you shouldn't ever need to set these manually if you are using the generated code.
Websockets
Calling standard gRPC methods from a web frontend involves complicated request translation and transcoding to convert between HTTP/JSON and gRPC/protobuf requests and responses.
In contrast, Reboot provides convenient builtin utilities for calling Reboot states from frontend code. To learn more, see Reboot and React.
JSON transcoding
A Reboot application's native methods are also exposed with JSON transcoding, which allows easier access from non-native clients.
JSON transcoding uses the gRPC service
and method
name for your state, and is routed based on its state ID.
For example, calling a Reboot native method using curl
:
curl -XPOST http://localhost:9991/hello.v1.HelloMethods/Messages \
-H "x-reboot-state-ref:hello.v1.Hello:reboot-hello"
...incorporates:
localhost:9991
- gateway addresshello.v1.HelloMethods
-service
nameMessages
- method namehello.v1.Hello
- statemessage
namereboot-hello
- state ID
Standard gRPC
In addition to running Reboot servicers, a Reboot application can also run
legacy servicers that implement a gRPC service
. This is a particularly useful setup
during a multi-service migration from standard gRPC to Reboot or when trying
to pull in pre-existing service implementations that do not use Reboot.
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()
Standard gRPC from Reboot native
Reboot methods can use passed-in Contexts to construct channels and call methods on standard gRPC services in the application.
For example, a RebootGreeter
service might call the GetSalutation
method
of a DeprecatedGreeter
gRPC service:
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()
)
Reboot native from standard gRPC
In place of a standard grpc.ServicerContext
, Reboot will pass a
LegacyGrpcContext
to each method in the standard gRPC servicers it runs.
This custom subclass of grpc.ServicerContext
adds the ability to construct a
Reboot ExternalContext
. The servicer can then use the ExternalContext
to act as a client for other services in the Reboot application.
For example, a ProxyGreeter
written in standard gRPC would be able to route
traffic to either the RebootGreeter
(a Reboot state machine) or the
DeprecatedGreeter
(another standard gRPC service running on Reboot) as
follows:
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=self.Greet.__name__)
if random.random() < 0.5:
# Route to RebootGreeter.
reboot_greeter = RebootGreeter.lookup("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)
HTTP
Reboot implements support for the google.api.http
annotations enabling you to expose standard gRPC methods
as arbitrary HTTP endpoints.
To expose a standard 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
...
Exposing methods at the root path (e.g. get: "/"
) is not supported,
because Reboot needs to host standard gRPC endpoints within that namespace.