Documentation
¶
Overview ¶
Package dwp implements the Dispatch Wire Protocol (DWP) — a message-based protocol for client↔server and server↔server communication. DWP is transported over WebSocket (primary), SSE (read-only fallback), and HTTP (one-shot RPC).
Index ¶
- Constants
- Variables
- func GenerateFrameID() string
- func RequiredScope(method string) string
- type APIKeyAuthenticator
- type APIKeyEntry
- type AuthRequest
- type AuthResponse
- type Authenticator
- type Codec
- type CompositeAuthenticator
- type Connection
- type ConnectionManager
- type ErrorDetail
- type Federation
- func (f *Federation) AddPeer(ctx context.Context, peerID, url, token string, metadata map[string]string) error
- func (f *Federation) BroadcastEvent(ctx context.Context, name string, payload json.RawMessage) []error
- func (f *Federation) BroadcastJob(ctx context.Context, name string, payload json.RawMessage, opts ...job.Option) []error
- func (f *Federation) ForwardEvent(ctx context.Context, peerID, name string, payload json.RawMessage) error
- func (f *Federation) ForwardJob(ctx context.Context, peerID, name string, payload json.RawMessage, ...) error
- func (f *Federation) GetPeer(peerID string) (*Peer, bool)
- func (f *Federation) HandleFederationEnqueue(ctx context.Context, frame *Frame) *Frame
- func (f *Federation) HandleFederationEvent(ctx context.Context, frame *Frame, conn *Connection) *Frame
- func (f *Federation) HandleFederationHeartbeat(frame *Frame) *Frame
- func (f *Federation) Peers() []*Peer
- func (f *Federation) RemovePeer(peerID string)
- func (f *Federation) Start(ctx context.Context)
- func (f *Federation) Stats() FederationStats
- func (f *Federation) Stop()
- type FederationEnqueueRequest
- type FederationEventRequest
- type FederationHeartbeatRequest
- type FederationOption
- type FederationStats
- type ForgeAuthenticator
- type Frame
- type FrameType
- type Handler
- type Identity
- type JSONCodec
- type JobCancelRequest
- type JobEnqueueRequest
- type JobEnqueueResponse
- type JobGetRequest
- type MsgpackCodec
- type NoopAuthenticator
- type Option
- type Peer
- type PeerState
- type RejectAuthenticator
- type Server
- type SubscribeRequest
- type UnsubscribeRequest
- type WorkflowCancelRequest
- type WorkflowEventRequest
- type WorkflowGetRequest
- type WorkflowStartRequest
- type WorkflowStartResponse
- type WorkflowTimelineRequest
Constants ¶
const ( ScopeJobRead = "job:read" ScopeJobWrite = "job:write" ScopeWorkflowRead = "workflow:read" ScopeWorkflowWrite = "workflow:write" ScopeEventWrite = "event:write" ScopeCronRead = "cron:read" ScopeDLQRead = "dlq:read" ScopeDLQWrite = "dlq:write" ScopeStatsRead = "stats:read" ScopeSubscribe = "subscribe" ScopeAdmin = "admin" ScopeAll = "*" )
const ( CodecNameJSON = "json" CodecNameMsgpack = "msgpack" CodecNameProtobuf = "protobuf" )
CodecName constants for format negotiation.
const ( // Auth methods. MethodAuth = "auth" // Job methods. MethodJobEnqueue = "job.enqueue" MethodJobGet = "job.get" MethodJobCancel = "job.cancel" MethodJobList = "job.list" // Workflow methods. MethodWorkflowStart = "workflow.start" MethodWorkflowGet = "workflow.get" MethodWorkflowEvent = "workflow.event" MethodWorkflowCancel = "workflow.cancel" MethodWorkflowTimeline = "workflow.timeline" MethodWorkflowReplay = "workflow.replay" // Subscription methods. MethodSubscribe = "subscribe" MethodUnsubscribe = "unsubscribe" // Admin methods. MethodCronList = "cron.list" MethodDLQList = "dlq.list" MethodDLQReplay = "dlq.replay" MethodStats = "stats" // Federation methods (server-to-server). MethodFederationEnqueue = "federation.enqueue" MethodFederationEvent = "federation.event" MethodFederationHeartbeat = "federation.heartbeat" )
const ( ErrCodeBadRequest = 400 ErrCodeForbidden = 403 ErrCodeNotFound = 404 ErrCodeMethodNotFound = 405 ErrCodeConflict = 409 ErrCodeInternal = 500 )
Variables ¶
ErrUnauthorized indicates authentication failure.
Functions ¶
func GenerateFrameID ¶
func GenerateFrameID() string
GenerateFrameID returns a new unique frame ID. Uses a simple timestamp + counter approach for performance.
func RequiredScope ¶
RequiredScope describes the legacy scope vocabulary. It does not grant installation authority; remote operations require the security boundary.
Types ¶
type APIKeyAuthenticator ¶
type APIKeyAuthenticator struct {
// contains filtered or unexported fields
}
APIKeyAuthenticator validates API keys against a static list.
func NewAPIKeyAuthenticator ¶
func NewAPIKeyAuthenticator(entries ...APIKeyEntry) *APIKeyAuthenticator
NewAPIKeyAuthenticator creates an API key authenticator.
func (*APIKeyAuthenticator) Authenticate ¶
type APIKeyEntry ¶
APIKeyEntry maps a token to an identity.
type AuthRequest ¶
type AuthRequest struct {
Token string `json:"token"`
Format string `json:"format,omitempty"` // "json" (default), "msgpack", "protobuf"
}
AuthRequest is sent by clients to authenticate.
type AuthResponse ¶
AuthResponse is returned after successful authentication.
type Authenticator ¶
Authenticator validates credentials and returns an identity.
type Codec ¶
type Codec interface {
// Encode serializes a frame to bytes.
Encode(frame *Frame) ([]byte, error)
// Decode deserializes bytes into a frame.
Decode(data []byte) (*Frame, error)
// Name returns the codec identifier (e.g., "json", "msgpack", "protobuf").
Name() string
}
Codec defines the serialization contract for DWP frames. Implementations handle encoding/decoding frames to/from bytes.
type CompositeAuthenticator ¶
type CompositeAuthenticator struct {
// contains filtered or unexported fields
}
CompositeAuthenticator tries multiple authenticators in order. The first successful authentication wins.
func NewCompositeAuthenticator ¶
func NewCompositeAuthenticator(auths ...Authenticator) *CompositeAuthenticator
NewCompositeAuthenticator chains multiple authenticators.
func (*CompositeAuthenticator) Authenticate ¶
type Connection ¶
type Connection struct {
// ID uniquely identifies this connection.
ID string
// Identity is the authenticated identity for this connection.
Identity *Identity
// Codec is the negotiated wire format.
Codec Codec
// ConnectedAt records when the connection was established.
ConnectedAt time.Time
// LastActivity tracks the most recent frame received.
LastActivity atomic.Value // time.Time
// contains filtered or unexported fields
}
Connection represents an authenticated DWP connection.
func NewConnection ¶
func NewConnection(id string, identity *Identity, codec Codec) *Connection
NewConnection creates a connection with the given ID and identity.
func (*Connection) AddSubscription ¶
func (c *Connection) AddSubscription(channel string)
AddSubscription records a channel subscription.
func (*Connection) RemoveSubscription ¶
func (c *Connection) RemoveSubscription(channel string)
RemoveSubscription removes a channel subscription.
func (*Connection) Subscriptions ¶
func (c *Connection) Subscriptions() []string
Subscriptions returns a copy of active subscription channels.
type ConnectionManager ¶
type ConnectionManager struct {
// contains filtered or unexported fields
}
ConnectionManager tracks active DWP connections.
func NewConnectionManager ¶
func NewConnectionManager() *ConnectionManager
NewConnectionManager creates an empty connection manager.
func (*ConnectionManager) Add ¶
func (cm *ConnectionManager) Add(conn *Connection)
Add registers a new connection.
func (*ConnectionManager) All ¶
func (cm *ConnectionManager) All() []*Connection
All returns a snapshot of all connections.
func (*ConnectionManager) Count ¶
func (cm *ConnectionManager) Count() int
Count returns the number of active connections.
func (*ConnectionManager) Get ¶
func (cm *ConnectionManager) Get(connID string) (*Connection, bool)
Get returns a connection by ID.
func (*ConnectionManager) Remove ¶
func (cm *ConnectionManager) Remove(connID string)
Remove unregisters a connection.
type ErrorDetail ¶
type ErrorDetail struct {
Code int `json:"code" msgpack:"code"`
Message string `json:"message" msgpack:"message"`
Details string `json:"details,omitempty" msgpack:"details,omitempty"`
}
ErrorDetail describes an error in a response or error frame.
type Federation ¶
type Federation struct {
// contains filtered or unexported fields
}
Federation manages server-to-server communication between Dispatch instances. It maintains a mesh of authenticated WebSocket connections to peers and provides methods for forwarding jobs and events.
func NewFederation ¶
func NewFederation(eng *engine.Engine, broker *stream.Broker, logger log.Logger, opts ...FederationOption) *Federation
NewFederation creates a new federation manager.
func (*Federation) AddPeer ¶
func (f *Federation) AddPeer(ctx context.Context, peerID, url, token string, metadata map[string]string) error
AddPeer registers and connects to a remote peer.
func (*Federation) BroadcastEvent ¶
func (f *Federation) BroadcastEvent(ctx context.Context, name string, payload json.RawMessage) []error
BroadcastEvent sends an event to all connected peers.
func (*Federation) BroadcastJob ¶
func (f *Federation) BroadcastJob(ctx context.Context, name string, payload json.RawMessage, opts ...job.Option) []error
BroadcastJob sends a job to all connected peers.
func (*Federation) ForwardEvent ¶
func (f *Federation) ForwardEvent(ctx context.Context, peerID, name string, payload json.RawMessage) error
ForwardEvent sends an event to a specific peer.
func (*Federation) ForwardJob ¶
func (f *Federation) ForwardJob(ctx context.Context, peerID, name string, payload json.RawMessage, opts ...job.Option) error
ForwardJob sends a job enqueue request to a specific peer.
func (*Federation) GetPeer ¶
func (f *Federation) GetPeer(peerID string) (*Peer, bool)
GetPeer returns a peer by ID.
func (*Federation) HandleFederationEnqueue ¶
func (f *Federation) HandleFederationEnqueue(ctx context.Context, frame *Frame) *Frame
HandleFederationEnqueue processes an incoming federation.enqueue from a peer. This is called by the DWP handler for federation methods.
func (*Federation) HandleFederationEvent ¶
func (f *Federation) HandleFederationEvent(ctx context.Context, frame *Frame, conn *Connection) *Frame
HandleFederationEvent processes an incoming federation.event from a peer.
func (*Federation) HandleFederationHeartbeat ¶
func (f *Federation) HandleFederationHeartbeat(frame *Frame) *Frame
HandleFederationHeartbeat processes an incoming federation.heartbeat.
func (*Federation) Peers ¶
func (f *Federation) Peers() []*Peer
Peers returns a snapshot of all peers.
func (*Federation) RemovePeer ¶
func (f *Federation) RemovePeer(peerID string)
RemovePeer disconnects and removes a peer.
func (*Federation) Start ¶
func (f *Federation) Start(ctx context.Context)
Start begins heartbeat monitoring and peer health checks.
func (*Federation) Stats ¶
func (f *Federation) Stats() FederationStats
Stats returns federation metrics.
func (*Federation) Stop ¶
func (f *Federation) Stop()
Stop gracefully shuts down all peer connections.
type FederationEnqueueRequest ¶
type FederationEnqueueRequest struct {
Name string `json:"name"`
Payload json.RawMessage `json:"payload"`
Queue string `json:"queue,omitempty"`
Priority int `json:"priority,omitempty"`
SourceID string `json:"source_id"` // ID of the originating peer
}
FederationEnqueueRequest is sent by a peer to enqueue a job remotely.
type FederationEventRequest ¶
type FederationEventRequest struct {
Name string `json:"name"`
Payload json.RawMessage `json:"payload,omitempty"`
SourceID string `json:"source_id"`
}
FederationEventRequest is sent by a peer to publish an event remotely.
type FederationHeartbeatRequest ¶
type FederationHeartbeatRequest struct {
PeerID string `json:"peer_id"`
}
FederationHeartbeatRequest is a periodic liveness signal.
type FederationOption ¶
type FederationOption func(*Federation)
FederationOption configures a Federation.
func WithFederationAuth ¶
func WithFederationAuth(auth Authenticator) FederationOption
WithFederationAuth sets the authenticator for incoming peer connections.
func WithHeartbeatInterval ¶
func WithHeartbeatInterval(d time.Duration) FederationOption
WithHeartbeatInterval sets how often heartbeats are sent to peers.
func WithHeartbeatTimeout ¶
func WithHeartbeatTimeout(d time.Duration) FederationOption
WithHeartbeatTimeout sets how long to wait before considering a peer dead.
func WithLocalID ¶
func WithLocalID(id string) FederationOption
WithLocalID sets the local peer ID for outgoing connections.
func WithLocalToken ¶
func WithLocalToken(token string) FederationOption
WithLocalToken sets the auth token used when connecting to peers.
type FederationStats ¶
type FederationStats struct {
TotalPeers int `json:"total_peers"`
ConnectedPeers int `json:"connected_peers"`
JobsForwarded int64 `json:"jobs_forwarded"`
EventsForwarded int64 `json:"events_forwarded"`
}
FederationStats contains federation metrics.
type ForgeAuthenticator ¶
type ForgeAuthenticator struct{ Auth security.Authenticator }
ForgeAuthenticator carries the actual HTTP request so proof validation retains the original method, URL and context. Token-only callers fail closed.
func (*ForgeAuthenticator) Authenticate ¶
func (*ForgeAuthenticator) AuthenticateRequest ¶
type Frame ¶
type Frame struct {
// ID uniquely identifies this frame (ULID or UUID).
ID string `json:"id" msgpack:"id"`
// Type categorizes the frame.
Type FrameType `json:"type" msgpack:"type"`
// Method names the operation for request frames (e.g., "job.enqueue").
Method string `json:"method,omitempty" msgpack:"method,omitempty"`
// CorrelID links a response to its originating request.
CorrelID string `json:"correl_id,omitempty" msgpack:"correl_id,omitempty"`
// Token carries auth credentials (typically only on the auth frame).
Token string `json:"token,omitempty" msgpack:"token,omitempty"`
// AppID scopes the request to a tenant application.
AppID string `json:"app_id,omitempty" msgpack:"app_id,omitempty"`
// OrgID scopes the request to a tenant organization.
OrgID string `json:"org_id,omitempty" msgpack:"org_id,omitempty"`
// Data carries the method-specific payload.
Data json.RawMessage `json:"data,omitempty" msgpack:"data,omitempty"`
// Error carries error details for error frames.
Error *ErrorDetail `json:"error,omitempty" msgpack:"error,omitempty"`
// Channel identifies the subscription channel for event/subscribe frames.
Channel string `json:"channel,omitempty" msgpack:"channel,omitempty"`
// Credits replenishes flow-control credits (backpressure).
Credits int `json:"credits,omitempty" msgpack:"credits,omitempty"`
// Timestamp records when this frame was created.
Timestamp time.Time `json:"ts" msgpack:"ts"`
}
Frame is the DWP message envelope. Every message exchanged over the protocol is a Frame.
func NewErrorFrame ¶
NewErrorFrame creates an error response to a request.
func NewEventFrame ¶
NewEventFrame creates an event frame for a subscription channel.
func NewRequestFrame ¶
NewRequestFrame creates a new request frame.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler dispatches DWP frames to engine operations.
func NewHandler ¶
func NewHandler(eng *engine.Engine, broker *stream.Broker, logger log.Logger, boundaries ...security.Boundary) *Handler
NewHandler creates a new DWP method handler.
func (*Handler) SetFederation ¶
func (h *Handler) SetFederation(f *Federation)
SetFederation attaches a federation manager for handling server-to-server methods.
type Identity ¶
type Identity struct {
Kind string `json:"kind,omitempty"`
// Subject is the authenticated user/service ID.
Subject string `json:"subject"`
// AppID scopes to a tenant application.
AppID string `json:"app_id,omitempty"`
// OrgID scopes to a tenant organization.
OrgID string `json:"org_id,omitempty"`
// Scopes defines what operations are permitted.
// Examples: "job:write", "workflow:read", "admin", "*"
Scopes []string `json:"scopes,omitempty"`
}
Identity represents an authenticated caller.
type JobCancelRequest ¶
type JobCancelRequest struct {
JobID string `json:"job_id"`
}
JobCancelRequest cancels a job.
type JobEnqueueRequest ¶
type JobEnqueueRequest struct {
Name string `json:"name"`
Payload json.RawMessage `json:"payload"`
Queue string `json:"queue,omitempty"`
Priority int `json:"priority,omitempty"`
}
JobEnqueueRequest submits a new job.
type JobEnqueueResponse ¶
type JobEnqueueResponse struct {
JobID string `json:"job_id"`
Queue string `json:"queue"`
State string `json:"state"`
}
JobEnqueueResponse confirms job creation.
type JobGetRequest ¶
type JobGetRequest struct {
JobID string `json:"job_id"`
}
JobGetRequest retrieves a job by ID.
type MsgpackCodec ¶
type MsgpackCodec struct{}
MsgpackCodec encodes/decodes DWP frames as MessagePack.
func (*MsgpackCodec) Name ¶
func (c *MsgpackCodec) Name() string
type NoopAuthenticator ¶
type NoopAuthenticator struct{}
NoopAuthenticator accepts all tokens with a wildcard identity. Use for development only.
func (*NoopAuthenticator) Authenticate ¶
type Option ¶
type Option func(*Server)
Option configures a DWP Server.
func WithAuth ¶
func WithAuth(auth Authenticator) Option
WithAuth sets the authenticator for the DWP server. If not set, all requests are rejected.
func WithCodec ¶
WithCodec sets the default codec for the DWP server. Clients can override via the auth frame's format field.
func WithFederation ¶
func WithFederation(f *Federation) Option
WithFederation attaches a federation manager to the server, enabling server-to-server DWP methods (federation.enqueue, federation.event, federation.heartbeat).
func WithLogger ¶
WithLogger sets the logger for the DWP server.
func WithSecurity ¶
WithSecurity configures a policy boundary shared by admission, direct dispatch and event forwarding. Scope strings do not grant operator access.
type Peer ¶
type Peer struct {
// ID uniquely identifies this peer (typically hostname:port).
ID string
// URL is the WebSocket endpoint for the peer's DWP server.
URL string
// Token is the authentication token for the peer.
Token string
// State tracks the connection state.
State PeerState
// LastSeen is the timestamp of the last heartbeat.
LastSeen time.Time
// Metadata carries arbitrary peer information.
Metadata map[string]string
// contains filtered or unexported fields
}
Peer represents a remote Dispatch instance in the federation.
type PeerState ¶
type PeerState string
PeerState represents the connection state of a federated peer.
type RejectAuthenticator ¶
type RejectAuthenticator struct{}
func (*RejectAuthenticator) Authenticate ¶
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the DWP server that handles WebSocket, SSE, and HTTP RPC connections. It integrates with the Dispatch engine via the stream broker and handles frame-based communication with clients.
func (*Server) Connections ¶
func (s *Server) Connections() *ConnectionManager
Connections returns the connection manager.
func (*Server) RegisterRoutes ¶
RegisterRoutes mounts DWP endpoints on a Forge router.
type SubscribeRequest ¶
type SubscribeRequest struct {
Channel string `json:"channel"`
Credits int `json:"credits,omitempty"` // Initial credits (0 = use default)
}
SubscribeRequest subscribes to a topic channel.
type UnsubscribeRequest ¶
type UnsubscribeRequest struct {
Channel string `json:"channel"`
}
UnsubscribeRequest removes a subscription.
type WorkflowCancelRequest ¶
type WorkflowCancelRequest struct {
RunID string `json:"run_id"`
}
WorkflowCancelRequest cancels a workflow run.
type WorkflowEventRequest ¶
type WorkflowEventRequest struct {
Name string `json:"name"`
Payload json.RawMessage `json:"payload,omitempty"`
}
WorkflowEventRequest publishes an event to trigger workflow continuation.
type WorkflowGetRequest ¶
type WorkflowGetRequest struct {
RunID string `json:"run_id"`
}
WorkflowGetRequest retrieves a workflow run.
type WorkflowStartRequest ¶
type WorkflowStartRequest struct {
Name string `json:"name"`
Input json.RawMessage `json:"input"`
}
WorkflowStartRequest starts a new workflow.
type WorkflowStartResponse ¶
type WorkflowStartResponse struct {
RunID string `json:"run_id"`
Name string `json:"name"`
State string `json:"state"`
}
WorkflowStartResponse confirms workflow start.
type WorkflowTimelineRequest ¶
type WorkflowTimelineRequest struct {
RunID string `json:"run_id"`
}
WorkflowTimelineRequest gets the step timeline for a run.