Skip to main content

Other interfaces

Reboot clients can interface with an application in a variety of ways, including Reboot native gRPC, Websockets, Standard gRPC, and HTTP.

info

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 address
  • hello.v1.HelloMethods - service name
  • Messages - method name
  • hello.v1.Hello - state message name
  • reboot-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
...
note

Exposing methods at the root path (e.g. get: "/") is not supported, because Reboot needs to host standard gRPC endpoints within that namespace.