rpc

package
v1.8.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2026 License: BSD-3-Clause Imports: 3 Imported by: 0

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

View Source
const (
	StatusOK           uint32 = 200
	StatusBadRequest   uint32 = 400
	StatusUnauthorized uint32 = 401
	StatusForbidden    uint32 = 403
	StatusNotFound     uint32 = 404
	StatusInternal     uint32 = 500
)

Status codes carried in a Response.

View Source
const MsgTypeRouterBase uint16 = 200

MsgTypeRouterBase is this service's ZAP message-type slot, carried in the high byte of the header flags word.

View Source
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

View Source
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

func BuildRequest(c Call) []byte

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

func BuildResponse(status, promiseID uint32, body []byte) []byte

BuildResponse encodes a status + body into a router-tagged response.

Types

type Call

type Call struct {
	Method    uint32
	PromiseID uint32
	Target    uint32
	Cap       []byte
	Payload   []byte
}

Call is one outbound request's fields.

func ParseRequest

func ParseRequest(msg []byte) (Call, error)

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

type DispatchFunc func(envelope []byte) ([]byte, error)

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

func (p *Pipeliner) Finish(id uint32)

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

func (p *Pipeliner) Handle(envelope []byte) ([]byte, error)

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

type Response struct {
	Status    uint32
	PromiseID uint32
	Body      []byte
}

Response is a decoded response envelope.

func ParseResponse

func ParseResponse(msg []byte) (Response, error)

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

func (s *Session) Next() Promise

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

func (s *Session) Origin(p Promise, method uint32, cap, payload []byte) Call

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

func (s *Session) Pipeline(p, target Promise, method uint32, cap, payload []byte) Call

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).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL