Documentation
¶
Index ¶
- Variables
- func MustOpcode(name string) uint16
- func ProcedureOpcode(name string) (uint16, error)
- type AllowListVerifier
- type Client
- func (c *Client) Broadcast(ctx context.Context, procedure string, req *zap.Message) map[string]error
- func (c *Client) Call(ctx context.Context, procedure string, req *zap.Message) (*zap.Message, error)
- func (c *Client) Close() error
- func (c *Client) Peers() []Peer
- func (c *Client) Send(ctx context.Context, procedure string, req *zap.Message) error
- type ClientOption
- func WithBrowseInterval(d time.Duration) ClientOption
- func WithCallTimeout(d time.Duration) ClientOption
- func WithDiscoverTimeout(d time.Duration) ClientOption
- func WithDiscovery(d Discovery) ClientOption
- func WithLogger(l *slog.Logger) ClientOption
- func WithMinPeers(n int) ClientOption
- func WithNodeID(id string) ClientOption
- func WithPicker(p Picker) ClientOption
- func WithTLS(cfg *tls.Config) ClientOption
- type ClientOptions
- type Discovery
- type LocalTrustVerifier
- type Peer
- type PeerInfo
- type PeerVerifier
- type Picker
- type ProcedureHandler
- type RoundRobinPicker
- type Server
- type ServerOption
- type ServerOptions
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNoPeers is returned when discovery has no live peer for the // requested service type. ErrNoPeers = errors.New("zapclient: no peers discovered") // ErrUnknownProcedure is returned by the server when an incoming // opcode does not match any Register call. ErrUnknownProcedure = errors.New("zapclient: unknown procedure") // incoming peer. Maps to a transport-layer reject. ErrPeerUnauthorized = errors.New("zapclient: peer unauthorized") // ErrCallTimeout is returned by Call when the per-call deadline // elapses before the response arrives. ErrCallTimeout = errors.New("zapclient: call timed out") )
Sentinel errors. Callers branch via errors.Is.
var ErrReservedOpcode = errors.New("zapclient: procedure name hashes to a reserved opcode")
ErrReservedOpcode is returned when ProcedureOpcode collides with a reserved value. The procedure must be re-named to avoid the conflict.
Functions ¶
func MustOpcode ¶
MustOpcode is ProcedureOpcode that panics on error. Use in package-level var initialisers where a bad procedure name is a build-time bug.
func ProcedureOpcode ¶
ProcedureOpcode returns the uint16 opcode for a procedure name. The lower 8 bits are zero (matching the existing MsgType<<8 shape in lux/zap); the upper 8 bits are FNV-1a(name) modulo 254 + 1.
Returns ErrReservedOpcode if the hash lands on 0x00 or 0xFF.
Types ¶
type AllowListVerifier ¶
type AllowListVerifier struct {
// Allowed maps procedure name → set of NodeIDs permitted to call
// it. Empty set = procedure disabled.
Allowed map[string]map[string]struct{}
}
AllowListVerifier accepts only peers whose NodeID appears in Allowed[procedure]. Empty Allowed[procedure] means the procedure is not exposed.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a native ZAP RPC client. Created by Connect; closed by Close (or returned stop function from MustConnect).
func Connect ¶
Connect resolves a service via Discovery and returns a Client. Always defer Close on the returned client.
func MustConnect ¶
func MustConnect(ctx context.Context, serviceType string, opts ...ClientOption) *Client
MustConnect is Connect that panics on error.
func (*Client) Broadcast ¶
func (c *Client) Broadcast(ctx context.Context, procedure string, req *zap.Message) map[string]error
Broadcast sends procedure to every current peer. Returns a map of peer NodeID → error so the caller can re-try the failures.
func (*Client) Call ¶
func (c *Client) Call(ctx context.Context, procedure string, req *zap.Message) (*zap.Message, error)
Call invokes procedure on the picked peer and waits for a response. Respects the client-level CallTimeout in addition to ctx.
type ClientOption ¶
type ClientOption func(*ClientOptions)
ClientOption is the functional-option constructor knob.
func WithBrowseInterval ¶
func WithBrowseInterval(d time.Duration) ClientOption
WithBrowseInterval sets the default mDNS browse interval.
func WithCallTimeout ¶
func WithCallTimeout(d time.Duration) ClientOption
WithCallTimeout caps each Call's wait for a response.
func WithDiscoverTimeout ¶
func WithDiscoverTimeout(d time.Duration) ClientOption
WithDiscoverTimeout caps the initial peer-discovery wait.
func WithDiscovery ¶
func WithDiscovery(d Discovery) ClientOption
WithDiscovery overrides the peer-discovery backend (mDNS by default). Useful for tests + non-mDNS environments (Consul, etcd, static).
func WithLogger ¶
func WithLogger(l *slog.Logger) ClientOption
WithLogger sets the structured logger.
func WithMinPeers ¶
func WithMinPeers(n int) ClientOption
WithMinPeers blocks Connect until N peers are discovered.
func WithNodeID ¶
func WithNodeID(id string) ClientOption
WithNodeID names the caller in mDNS announcements.
func WithPicker ¶
func WithPicker(p Picker) ClientOption
WithPicker overrides the per-Call peer selector.
func WithTLS ¶
func WithTLS(cfg *tls.Config) ClientOption
WithTLS configures mutual TLS for the underlying ZAP connection. Required for the local-trust authorisation model on the server side (the server's PeerVerifier reads the peer cert).
type ClientOptions ¶
type ClientOptions struct {
// NodeID is the caller's identity in mDNS announcements. Empty
// auto-generates a short suffix.
NodeID string
// MinPeers blocks Connect until at least N peers are discovered
// (or DiscoverTimeout elapses). Default 1.
MinPeers int
// DiscoverTimeout caps the initial peer-discovery wait. Default
// 10 * BrowseInterval.
DiscoverTimeout time.Duration
// BrowseInterval is how often the default mDNS Discovery
// re-browses. Default 5 seconds.
BrowseInterval time.Duration
// CallTimeout caps each Call. Zero = no timeout. Default 30s.
CallTimeout time.Duration
// TLS configures mutual TLS. Nil = plaintext (dev only — local-
// trust mode requires mTLS against the cluster CA).
TLS *tls.Config
// Logger for ZAP node + client. Defaults to slog.Default().
Logger *slog.Logger
// Pluggable wiring. nil means "use default for this concern."
Discovery Discovery
Picker Picker
}
ClientOptions configure Connect. Construct via WithX options.
type Discovery ¶
type Discovery interface {
// Peers returns the current peer snapshot. The returned slice is
// freshly allocated; callers may retain it.
Peers() []Peer
// PeerCount returns len(Peers()) cheaply.
PeerCount() int
// ServiceType reports the service the Discovery is browsing.
ServiceType() string
// Start begins the discovery loop. Calling Start twice on the
// same Discovery is a programmer error.
Start() error
// Stop releases all resources. Idempotent.
Stop()
}
Discovery is the peer-enumeration contract.
Implementations MUST be goroutine-safe; the client may call Peers() from every in-flight Call and Send.
type LocalTrustVerifier ¶
type LocalTrustVerifier struct{}
LocalTrustVerifier accepts any peer presenting a valid mTLS cert from the cluster CA. The underlying TLS handshake already verified the chain; this verifier returns nil for every authenticated peer.
Use when:
- the peer is on the cluster-private network
- the listener was constructed with the cluster CA in ClientCAs
- all in-cluster services should be allowed to call all procedures (apply per-procedure RBAC in the handler if needed)
type Peer ¶
type Peer struct {
NodeID string
ServiceType string
Address string
Metadata map[string]string
LastSeen time.Time
}
Peer is the discovery view of one reachable instance of a service.
NodeID uniquely identifies the peer within ServiceType across discovery cycles. Address is the dial target (host:port). For in-cluster peers under mTLS, the authenticated peer identity comes from the TLS session — NodeID is a hint, not a trust anchor.
type PeerInfo ¶
type PeerInfo struct {
NodeID string
ServiceType string
// TLSCertSubject is the Subject CN of the mTLS peer cert, when
// the listener was configured with TLS. Empty under plaintext
// (local-dev) transport.
TLSCertSubject string
// TLSCertSANs are the Subject Alternative Names from the peer
// cert. Authorisation should prefer SANs over the legacy CN.
TLSCertSANs []string
}
PeerInfo is the authenticated peer identity surfaced to server-side handlers and PeerVerifier.
type PeerVerifier ¶
type PeerVerifier interface {
// Verify returns nil on accept, ErrPeerUnauthorized (or wrapping
// error) on reject. Implementations MUST NOT block — refer to
// pre-built decision tables, not network calls.
Verify(ctx context.Context, peer PeerInfo, procedure string) error
}
PeerVerifier is the server-side authorisation hook. Runs on every inbound message before procedure dispatch — return non-nil to reject the call.
The PeerInfo carries the authenticated peer identity (NodeID + mTLS cert chain if present). Procedure is the procedure name the caller requested. PeerVerifier should compare the (peer, procedure) pair against the service's authorisation policy.
type Picker ¶
type Picker interface {
// Pick returns the chosen peer. ErrNoPeers if peers is empty.
Pick(peers []Peer) (Peer, error)
}
Picker selects one peer from a Discovery snapshot for a single Call or Send. Implementations MUST be cheap (sub-microsecond) and goroutine-safe; the client invokes Pick from every concurrent op.
type ProcedureHandler ¶
type ProcedureHandler func(ctx context.Context, peer PeerInfo, req *zap.Message) (*zap.Message, error)
ProcedureHandler runs server-side for one inbound procedure call. Return nil + nil-err to ack a fire-and-forget Send. Return a response + nil-err to reply to a Call. Return nil + non-nil err to signal failure; the client side observes the err on its Call.
type RoundRobinPicker ¶
type RoundRobinPicker struct {
// contains filtered or unexported fields
}
RoundRobinPicker rotates through peers in registration order. Zero-value is ready to use; goroutine-safe.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the native ZAP server side: procedure-name dispatch on top of *zap.Node. Construct with NewServer, Register procedures, Start to begin accepting, Stop to release.
func NewServer ¶
func NewServer(serviceType string, opts ...ServerOption) (*Server, error)
NewServer constructs a server for the given service type + port. The returned Server is not yet listening — call Start.
func (*Server) Register ¶
func (s *Server) Register(procedure string, h ProcedureHandler) error
Register binds a procedure name to a handler.
Refuses to register if the procedure's opcode collides with an already-registered procedure — the caller MUST rename. With the 8-bit codespace, occasional collisions are expected; the build fails clearly rather than silently routing to the wrong handler.
type ServerOption ¶
type ServerOption func(*ServerOptions)
ServerOption is a functional-option knob.
func WithNoDiscovery ¶
func WithNoDiscovery() ServerOption
WithNoDiscovery disables mDNS advertisement (test-only).
func WithServerLogger ¶
func WithServerLogger(l *slog.Logger) ServerOption
WithServerLogger sets the structured logger.
func WithServerMetadata ¶
func WithServerMetadata(m map[string]string) ServerOption
WithServerMetadata sets the mDNS TXT-record metadata.
func WithServerNodeID ¶
func WithServerNodeID(id string) ServerOption
WithServerNodeID names this server in mDNS announcements.
func WithServerTLS ¶
func WithServerTLS(cfg *tls.Config) ServerOption
WithServerTLS configures mutual TLS on the listener.
func WithVerifier ¶
func WithVerifier(v PeerVerifier) ServerOption
WithVerifier installs the server-side PeerVerifier. Default is LocalTrustVerifier, which accepts any authenticated peer. Set to AllowListVerifier or a custom impl for stricter policy.
type ServerOptions ¶
type ServerOptions struct {
NodeID string
Port int
TLS *tls.Config
Verifier PeerVerifier
Logger *slog.Logger
// Metadata is the mDNS TXT-record metadata advertised to peers.
Metadata map[string]string
// NoDiscovery disables mDNS advertisement entirely. Use for
// stdio / unix-socket tests.
NoDiscovery bool
}
ServerOptions configure NewServer.