The GET
, POST
, Request
and Publish
methods of the Connector
allow an upstream microservice to make requests over the messaging bus. These methods provide HTTP-like semantics: the caller needs to explicitly designate the URL, headers and payload in HTTP form. This approach is broadly applicable but suffers from lack of forward compatibility and type safety. If the downstream microservice changes the signature of its endpoints, the upstream’s requests may start failing. It is also somewhat inconvenience to work at the HTTP level, especially when dealing with marshaling.
To address these challenges, the code generator creates a client stub for each of the endpoints of the downstream microservice. A stub is a type-safe function that wraps the call to the Connector
’s low-level publishing methods. It is customized for each endpoint based on its type and signature. In the code, the stubs almost appear to be regular function calls.
Client stubs are defined in a sub-package of the microservice named after the package of the service with an api
suffix added. For example, the clients of the calculator
microservice are defined in calculator/calculatorapi
. This naming convention is intended to facilitate with type-ahead code completion.
The standard Client
is used to make unicast requests and is the more commonly used.
sum, err := calculatorapi.NewClient(svc).Add(ctx, x, y)
The aptly-named MulticastClient
is used to make multicast requests.
for ri := range providerapi.NewMulticastClient(svc).Discover(ctx) {
name, err := ri.Get()
// ...
}
The MulticastTrigger
is to be used by the microservice itself to fire its own events.
for ri := range userstoreapi.NewMulticastTrigger(svc).OnCanDelete(ctx, id) {
allowed, err := ri.Get()
// ...
}
The Hook
facilitate registration of event sinks by downstream microservices. The code generator utilizes this Hook
automatically when an event sink is defined in service.yaml
.
userstoreapi.NewHook(svc).OnCanDelete(svc.OnCanDelete)
The API package also includes all objects uses by the endpoints that are owned by the downstream microservice. For example, a user store microservice will likely define a type User struct
. When a microservice refers to an object owned by another microservice, an alias to it is defined. For example, if the registration microservice accepts a User
object in any of its endpoints, it defines type User = userstoreapi.User
to alias the original definition.