Documentation
¶
Overview ¶
Package zaprpc carries the netrunner control-plane RPC over luxfi/zap.
One MsgType per RPC method; payloads are JSON inside a ZAP envelope:
envelope := zap.NewBuilder(...) root := envelope.StartObject(envelopeSize) root.SetBytes(FieldPayload, payloadJSON) // request or response body root.SetText(FieldError, errMsg) // empty on success root.FinishAsRoot() wire := envelope.FinishWithFlags(MsgType << 8)
JSON is the body format so any rpcpb.* struct round-trips via its existing `json:` tags — no extra schema to maintain and no `google.golang.org/protobuf` on the wire (per the project rule: ZAP internal, ZIP edge).
Index ¶
- Constants
- func Bind[Req, Resp any](d *Dispatcher, msgType MsgType, h func(context.Context, *Req) (*Resp, error))
- func Call[Req, Resp any](ctx context.Context, c *Client, msgType MsgType, req *Req) (*Resp, error)
- func CallVoid[Resp any](ctx context.Context, c *Client, msgType MsgType) (*Resp, error)
- func Decode(msg *zap.Message, dest any) error
- func Encode(msgType MsgType, body any, errStr string) ([]byte, error)
- type Client
- type ClientConfig
- type Dispatcher
- type MsgType
- type Server
- type ServerConfig
Constants ¶
const ( FieldPayload int = 0 // bytes — JSON-encoded request or response body FieldError int = 8 // text — non-empty on RPC-level error )
Envelope field layout — keep the size 16 (multiple of 8 for alignment).
Variables ¶
This section is empty.
Functions ¶
func Bind ¶
func Bind[Req, Resp any](d *Dispatcher, msgType MsgType, h func(context.Context, *Req) (*Resp, error))
Bind registers a typed handler for the given MsgType. The handler signature is `func(ctx, *Req) (*Resp, error)`; JSON encode/decode and ZAP framing happen here, so handlers stay business-logic-only.
func Call ¶
Call sends a typed request and waits for the typed response. ctx bounds the round trip. JSON encode/decode + ZAP framing happen inside.
func CallVoid ¶
CallVoid is Call's sibling for methods whose request struct is empty — avoids forcing the caller to type `&rpcpb.HealthRequest{}` for every ping.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a typed RPC client against a netrunner ZAP server.
Wire layer only — domain-specific methods live in netrunner/client.
func NewClient ¶
func NewClient(cfg ClientConfig) (*Client, error)
NewClient connects to the netrunner ZAP server at cfg.ServerAddr.
func (*Client) Done ¶
func (c *Client) Done() <-chan struct{}
Done returns a channel closed when the client is shut down.
type ClientConfig ¶
type ClientConfig struct {
// NodeID is this client's identifier (sent during handshake).
NodeID string
// ServerAddr is "host:port" of the netrunner ZAP server.
ServerAddr string
// DialTimeout bounds the initial TCP+handshake.
DialTimeout time.Duration
Logger *slog.Logger
}
ClientConfig configures a netrunner ZAP client.
type Dispatcher ¶
type Dispatcher struct {
// contains filtered or unexported fields
}
Dispatcher routes incoming ZAP messages by MsgType to typed handlers.
func (*Dispatcher) AttachTo ¶
func (d *Dispatcher) AttachTo(n *zap.Node)
AttachTo registers every bound handler onto the given ZAP node.
func (*Dispatcher) HandlerFor ¶
func (d *Dispatcher) HandlerFor(msgType MsgType) zap.Handler
HandlerFor returns the ZAP handler for the given MsgType, or nil if unbound. The returned function plugs straight into zap.Node.Handle.
func (*Dispatcher) MsgTypes ¶
func (d *Dispatcher) MsgTypes() []MsgType
MsgTypes returns the set of method IDs bound on this dispatcher.
type MsgType ¶
type MsgType uint16
MsgType identifies a netrunner RPC method on the ZAP wire.
Stable wire IDs: never renumber, append-only. Bumping changes the wire protocol and forces clients to upgrade in lockstep with the server.
Constraint: ZAP carries the method tag in the upper 8 bits of its 16-bit flags header, so MsgType values must fit in uint8 (0..255). 1..26 are the current netrunner control-plane methods; 27..255 are free for future additions; 0 is reserved (unused).
const ( MsgPing MsgType = 1 MsgRPCVersion MsgType = 2 MsgStart MsgType = 3 MsgCreateBlockchains MsgType = 4 MsgTransformElasticChains MsgType = 5 MsgAddPermissionlessValidator MsgType = 6 MsgRemoveChainValidator MsgType = 7 MsgCreateChains MsgType = 8 MsgHealth MsgType = 9 MsgURIs MsgType = 10 MsgWaitForHealthy MsgType = 11 MsgStatus MsgType = 12 MsgRemoveNode MsgType = 13 MsgAddNode MsgType = 14 MsgRestartNode MsgType = 15 MsgPauseNode MsgType = 16 MsgResumeNode MsgType = 17 MsgStop MsgType = 18 MsgAttachPeer MsgType = 19 MsgSendOutboundMessage MsgType = 20 MsgSaveSnapshot MsgType = 21 MsgSaveHotSnapshot MsgType = 22 MsgLoadSnapshot MsgType = 23 MsgRemoveSnapshot MsgType = 24 MsgGetSnapshotNames MsgType = 25 MsgStreamStatus MsgType = 26 // server→client status push, one msg per tick )
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is a thin wrapper around zap.Node that hosts a Dispatcher.
func NewServer ¶
func NewServer(cfg ServerConfig, disp *Dispatcher) *Server
NewServer constructs a ZAP server that will dispatch to the handlers registered on the given Dispatcher.
func (*Server) Node ¶
Node returns the underlying ZAP node — primarily for tests and for server-side pushes to subscribed clients.
func (*Server) Start ¶
Start binds the listener. Run inside its own goroutine — call Stop to wind down.