Documentation
¶
Overview ¶
Package modcall is how one module calls another (docs/decisions/0071 D93 a): a typed request and response over one of three transports, behind one Go interface chosen by configuration.
- Local calls a Server in the same process: tests, and every deployment that has not split the callee out.
- HTTPCaller posts to the callee's Service on Kubernetes, with a bearer the callee verifies (Server.Handler).
- internal/modcall/lambdacall invokes the callee's function through one alias per caller class (`live-issuer`, `live-console`, ...) on Lambda; it is a package of its own so that a Kubernetes build does not carry the Lambda client.
A call is a module name, a method name and a JSON payload. The callee answers a JSON result or a coded Error; anything else a handler returns is reported as an internal error with no detail, since the caller is another module's trust domain.
Who is calling is the transport's to say, never the payload's: Local knows it from its constructor (Local.As), HTTP from the verified token, Lambda from the alias the function was invoked through. A method that registers Allow answers only those caller classes and refuses the rest with CodeForbidden.
The envelope also carries the caller's trace (`traceparent`, `tracestate`), its deadline, and is bounded in size; a callee answers a request of the previous version in that version. See Request and [Dispatch].
Index ¶
- Constants
- Variables
- func Begin(ctx context.Context, module, method string, payload []byte, maxBytes int) (context.Context, Request, *Pending, error)
- func CallerOf(ctx context.Context) string
- func ClassOfSubject(subject string) string
- func Coded(code, message string) error
- func Do[Req, Resp any](ctx context.Context, c Caller, module, method string, req Req) (Resp, error)
- func Handle[Req, Resp any](s *Server, method string, fn func(ctx context.Context, req Req) (Resp, error), ...)
- func Result(r Response) ([]byte, error)
- func WithCaller(ctx context.Context, class string) context.Context
- type Caller
- type Config
- type Error
- type HTTPCaller
- type HandlerOption
- type Local
- type Option
- type Pending
- type Request
- type Response
- type Router
- type Server
- type Target
- type TokenSource
- type Verifier
Constants ¶
const ( DefaultMaxBytes = 256 << 10 HardMaxBytes = 5 << 20 )
The size bounds of a call. A method answers requests and responses of at most DefaultMaxBytes unless it registers MaxBytes; no method may exceed HardMaxBytes, which keeps a call under Lambda's 6 MB synchronous payload.
const ( CodeInternal = "internal" CodeBadRequest = "bad_request" CodeNoSuchMethod = "no_such_method" CodeForbidden = "forbidden" // CodeDeadlineExceeded is a call whose deadline had passed when it arrived, // or passed while the method ran. CodeDeadlineExceeded = "deadline_exceeded" )
Codes of an Error. A module may define more for its own methods.
const Kind = "rpc"
Kind is the `kind` of a Lambda event that carries a module call, beside the scheduler's ticks.
const MinVersion = Version - 1
MinVersion is the oldest version a callee still answers (N-1).
const RPCPath = "/rpc"
RPCPath is where a module's Service answers calls.
const Version = 2
Version is the protocol version a caller writes in Request.V. Version 1, which wrote none, is read as 1. A callee answers versions MinVersion to Version, each in the caller's own version: a release is deployed one function at a time, so for a while the two sides differ by one.
Variables ¶
var ( // ErrNoRoute is a call to a module no transport is configured for. ErrNoRoute = errors.New("module call: no route") // ErrTransport is a call that did not get an answer from the callee. ErrTransport = errors.New("module call: transport failed") )
Functions ¶
func Begin ¶
func Begin(ctx context.Context, module, method string, payload []byte, maxBytes int) (context.Context, Request, *Pending, error)
Begin prepares an outgoing call for a transport: it refuses a payload over maxBytes (DefaultMaxBytes when 0) and a context already done, starts the client span, and builds the envelope with the trace and the deadline of the returned context. Every transport calls it, so that they carry the same fields; the caller class is never one of them.
func CallerOf ¶
CallerOf is the caller class the transport authenticated the call as; empty for a call the transport cannot name.
func ClassOfSubject ¶
ClassOfSubject is the caller class of a verified subject: the ServiceAccount's name for `system:serviceaccount:<namespace>:<name>`, the subject itself otherwise.
Types ¶
type Caller ¶
type Caller interface {
Call(ctx context.Context, module, method string, payload []byte) ([]byte, error)
}
Caller sends one call to a module and returns its raw result.
type Error ¶
Error is a failure the callee chose to tell: a code a caller can switch on and a message that is safe to show another module.
type HTTPCaller ¶
type HTTPCaller struct {
// URLs maps a module to its Service's base URL; Audiences to the audience of
// the bearer it verifies (the module's name when absent).
URLs map[string]string
Audiences map[string]string
Token TokenSource
Client *http.Client
// MaxBytes bounds a request payload and a result ([DefaultMaxBytes] when 0);
// raise it only for a callee that registered a larger [MaxBytes].
MaxBytes int
}
HTTPCaller calls modules' Services.
type HandlerOption ¶
type HandlerOption func(*handlerConfig)
HandlerOption configures Server.Handler.
func WithClasses ¶
func WithClasses(classes map[string]string) HandlerOption
WithClasses maps verified subjects to caller classes, for a subject whose ServiceAccount is not named for its class.
type Local ¶
Local calls servers in this process, through the same JSON the other transports carry, so what works here works across a boundary. Called as itself it has no caller class, so a method with Allow refuses it; Local.As names the class the caller is.
type Option ¶
type Option func(*handler)
Option configures a method at registration.
func Allow ¶
Allow limits a method to the named caller classes. A call from any other class, or from one the transport cannot name, is refused with CodeForbidden before the method runs.
func MaxBytes ¶
MaxBytes sets the bound, in bytes, of a method's request payload and of its result, in place of DefaultMaxBytes. A value over HardMaxBytes is a programming error and panics at registration. A caller of such a method sets the same bound on its transport.
type Pending ¶
type Pending struct {
// contains filtered or unexported fields
}
Pending is one outgoing call between Begin and Pending.Finish.
type Request ¶
type Request struct {
// V is the protocol version; absent is 1.
V int `json:"v,omitempty"`
Kind string `json:"kind"`
Module string `json:"module"`
Method string `json:"method"`
Payload json.RawMessage `json:"payload,omitempty"`
// Version 2 and later. A version 1 request has none of them, and a callee
// ignores them on one.
//
// Traceparent and Tracestate are the caller's W3C trace context; the callee
// continues the trace with a span of its own.
Traceparent string `json:"traceparent,omitempty"`
Tracestate string `json:"tracestate,omitempty"`
// Deadline is the caller's deadline as Unix milliseconds. The callee bounds
// its work by it, and refuses a call that arrives after it. It is read
// against the callee's clock, so hosts need ordinary time sync.
Deadline int64 `json:"deadline,omitempty"`
}
Request is one call on the wire. A reader ignores fields it does not know, so a later version can add some without breaking this one.
type Response ¶
type Response struct {
V int `json:"v,omitempty"`
Result json.RawMessage `json:"result,omitempty"`
Error *Error `json:"error,omitempty"`
}
Response is its answer: a result, or an error. V is the version the callee answered in, the caller's own; version 1 wrote none.
type Router ¶
type Router struct {
// contains filtered or unexported fields
}
Router sends each call by the configuration: to the server in this process unless the module has a Function or a URL.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server dispatches calls to the methods a module registered.
func (*Server) Dispatch ¶
Dispatch answers one request. It never returns a Go error: a failure is the response's.
It answers version MinVersion to Version in the request's own version; a newer one is refused. The caller's trace continues in a server span, the caller's deadline bounds the method's context, and a payload or a result over the method's bound is refused without being echoed.
func (*Server) Handler ¶
func (s *Server) Handler(verify Verifier, opts ...HandlerOption) http.Handler
Handler serves the module's calls at RPCPath. A call with no bearer, or one verify refuses, is a 401 and reaches no method. The caller class is the verified subject's (ClassOfSubject, or WithClasses); the request body has no say in it.
type Target ¶
type Target struct {
Function string `json:"function,omitempty"`
URL string `json:"url,omitempty"`
Audience string `json:"audience,omitempty"`
}
Target is where one module is reached when it is not in this process. Set Function for a Lambda function (the alias of the caller's class), URL for a Kubernetes Service. Neither: the module is in this process.
type TokenSource ¶
TokenSource yields the bearer for a call to the module whose audience is given (internal/consoleauth.Source, one per audience).
Directories
¶
| Path | Synopsis |
|---|---|
|
Package lambdacall is the Lambda transport of internal/modcall: a call is a synchronous lambda:InvokeFunction of the callee's `live-<class>` alias for the caller class with the JSON envelope as payload, and a function answers one with Serve.
|
Package lambdacall is the Lambda transport of internal/modcall: a call is a synchronous lambda:InvokeFunction of the callee's `live-<class>` alias for the caller class with the JSON envelope as payload, and a function answers one with Serve. |