Familiarizing yourself with concepts in the Architecture Reference is recommended prior to starting development on the backend.
Components consist primarily of a
Name string for registration purposes and a
New factory method, which returns an implementation of the interface required for that component.
New methods for components have the following signature:
Configuration must be unmarshaled from the Any type into the native protobuf type for further consumption using
References to the logger and scope can be saved in the component implementation's
struct for later use. Note that the gateway adds a component namespace for the logger and stats scope so it does not have to be added by the developer.
The gateway is extensible via middleware, which operates on the incoming request and the outgoing response in a single context.
Currently the gateway only supports unary requests (as opposed to streaming). Therefore middleware returns a server unary interceptor.
Modules are implementations of API stubs generated from proto. The
Register method is a callback used by the gateway to add the gRPC and JSON servers to the main gateway server.
Resolvers abstract resource location into an extensible framework. Finding resources is different at almost every organization. Changing the first step of locating a resource should not require wholesale replacement of a feature. That's where resolvers come in.
Resolvers start in protobuf with an object definition representing the user input needed to locate a resource. The fields are additionally annotated with schema information (such as
display_name) at the object and field level so that the frontend knows how to render the appropriate form.
The resolver has two ways of locating resources,
Search takes a free-form text query and locates resources by interpreting the query and making the appropriate call.
Resolve takes the filled-out schemas and makes a query based on that structured information.
One additional nicety in the resolver is the
FanoutHandler which makes managing concurrent requests easier. It has
limit handling to return early once the limit is satisfied, cancelling any remaining outstanding requests.
In the future, the resolver will handle autocomplete and asynchronous validation of form input for the frontend.
More docs are coming on developing resolvers. For now look at other resolvers as an example.
Interactions with third-party services or networked dependencies such as a database should always hide behind a service. Services have no other restrictions and the underlying type is simply an empty
All services are placed in a registry for use by other components. Other components that depend on services fetch them in their factory method. For example,
Because services return interfaces, it is easy to substitute in a custom implementation by creating a new custom component that implements the interface type.
It is also possible to override specific methods of a service.