Documentation
¶
Overview ¶
Package rpc is the ZAP call envelope: the msgType + method + capability framing that carries an interface method call and its response over a ZAP transport.
This is the canonical wire contract; the TypeScript runtime's envelope.ts mirrors these exact offsets and sizes byte-for-byte, so a request built here is decoded by the TS ParseRequest and a response built by the TS BuildResponse is decoded by ParseResponse here (and vice versa). The generated typed Client and abstract Server (zapgen `interface` emission) are thin wrappers over BuildRequest / ParseRequest / BuildResponse / ParseResponse.
Request object (fixed size 28):
Method u32 @0 which interface method (the .zap ordinal, 1-based) PromiseID u32 @4 caller-assigned id this call's answer resolves to Target u32 @8 promise this call pipelines off (0 = root) Cap bytes @12 opaque capability buffer (cap.Cap bytes; may be empty) Payload bytes @20 ZAP-encoded method params
Response object (fixed size 20):
Status u32 @0 200 ok, else an error code PromiseID u32 @4 echoes the request's PromiseID Body bytes @12 ZAP-encoded results (empty for a void method)
Both envelopes are finished with header flags = MsgTypeRouterBase << 8 so a ZAP transport routes them to this service's handler (msgType = flags >> 8).
Index ¶
Constants ¶
const ( StatusOK uint32 = 200 StatusBadRequest uint32 = 400 StatusForbidden uint32 = 403 StatusNotFound uint32 = 404 StatusInternal uint32 = 500 )
Status codes carried in a Response.
const MsgTypeRouterBase uint16 = 200
MsgTypeRouterBase is this service's ZAP message-type slot, carried in the high byte of the header flags word.
const NoTarget uint32 = 0
NoTarget is the Target value for a call that does not pipeline off an earlier promise (the call targets the bootstrap object).
Variables ¶
var ErrUnresolvedTarget = fmt.Errorf("rpc: pipeline target never resolves")
ErrUnresolvedTarget is returned when a dependent call names a Target that can never resolve on this session — it was never in flight, or its answer already failed (a non-OK status produces no usable result to pipeline on). Surfaced to the client as StatusBadRequest.
Functions ¶
func BuildRequest ¶
BuildRequest encodes a Call into a router-tagged ZAP message. The header is v2 to match the transport default; the flags carry the router msgType so the transport dispatches it to this service.
func BuildResponse ¶
BuildResponse encodes a status + body into a router-tagged response.
Types ¶
type Call ¶
Call is one outbound request's fields.
func ParseRequest ¶
ParseRequest decodes a router-tagged request message into a Call. The returned Cap and Payload slices alias the input buffer; copy them if you retain them past the buffer's lifetime.
type DispatchFunc ¶ added in v1.4.0
DispatchFunc is the generated server entry point (Dispatch<Iface>): it decodes a Call envelope, routes by ordinal to a handler, and returns the response envelope bytes. A Pipeliner wraps one of these.
type Pipeliner ¶ added in v1.4.0
type Pipeliner struct {
// contains filtered or unexported fields
}
Pipeliner is a server-side promise table for one session (one transport connection). It serializes dispatch (matching a ZAP connection's strict FIFO handler) while resolving Target references and queuing dependents whose target has not yet resolved.
Lifecycle: construct with NewPipeliner(dispatch); feed each inbound request envelope to Handle, which returns the response envelope (or holds the dependent until its target resolves and then returns its response). A Pipeliner is safe for concurrent Handle calls — a transport that reads frames on multiple goroutines may call it from each.
func NewPipeliner ¶ added in v1.4.0
func NewPipeliner(dispatch DispatchFunc) *Pipeliner
NewPipeliner returns a Pipeliner that routes resolved calls through dispatch.
func (*Pipeliner) Finish ¶ added in v1.4.0
Finish drops the cached answer for id once the client knows no further call will pipeline on it (the ZAP analogue of capnp's Finish message). Calling Finish is optional: without it, a Pipeliner retains each OK answer for the session's lifetime so a dependent that arrives after its target resolves still finds it. A long-lived connection that pipelines heavily should Finish each promise it is done with to bound the table.
After Finish, id is terminal: any dependent that targets it — whether already parked or arriving later — is refused (StatusBadRequest) rather than hung, since the answer is gone and will never be re-produced.
func (*Pipeliner) Handle ¶ added in v1.4.0
Handle processes one inbound request envelope and returns its response envelope. A request with Target = NoTarget dispatches straight through. Otherwise the request is a dependent call and its Target decides what happens:
- resolved (OK): the resolved Body is substituted for the request's Payload and it dispatches immediately.
- failed (non-OK) or Finished: refused with StatusBadRequest — the Target can never produce a result to pipeline on.
- unknown: parked until a later Handle on the same Pipeliner resolves it (the dependent legitimately arrived before its origin), or a Finish on the Target refuses it.
type Promise ¶ added in v1.4.0
type Promise struct {
// ID is the PromiseID the originating call's answer resolves to (never
// NoTarget). A dependent call sets Target = ID.
ID uint32
}
Promise is a handle to the answer of an in-flight call. Use its ID as the Target of a dependent Call to pipeline on it.
type Response ¶
Response is a decoded response envelope.
func ParseResponse ¶
ParseResponse decodes a router-tagged response message. The returned Body slice aliases the input buffer.
type Session ¶ added in v1.4.0
type Session struct {
// contains filtered or unexported fields
}
Session is the client half of pipelining: a monotonic PromiseID allocator scoped to one transport connection. The first call of a pipeline takes a fresh PromiseID via Next; a dependent call sets Target to that PromiseID, so the two ship back-to-back and the server's Pipeliner chains them.
A Promise is a typed handle to a not-yet-resolved answer: pass it as the Target of the next Call instead of threading raw u32s by hand. PromiseIDs must be unique and non-zero within a session (0 is NoTarget); Session guarantees both.
func NewSession ¶ added in v1.4.0
func NewSession() *Session
NewSession returns a Session whose first allocated PromiseID is 1.
func (*Session) Next ¶ added in v1.4.0
Next allocates a fresh, unique, non-zero PromiseID for a new call and returns a Promise handle to its eventual answer.
func (*Session) Origin ¶ added in v1.4.0
Origin builds the originating Call of a pipeline: it carries a fresh PromiseID (from p) and Target = NoTarget. cap and payload are this call's own arguments. The returned Call is ready for BuildRequest.
func (*Session) Pipeline ¶ added in v1.4.0
Pipeline builds a dependent Call that pipelines on target's answer: it carries its own fresh PromiseID (from p) and Target = target.ID. The server substitutes target's resolved Body for this call's Payload before dispatch, so payload here is only the part of the request NOT supplied by the upstream answer (often nil — the whole input is the upstream result).