Help us shape the future of Go! Take the 2026 Go Developer Survey

dwp

package
v1.9.3 Latest Latest
Warning

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

Go to latest
Published: Oct 26, 2026 License: MIT Imports: 25 Imported by: 0

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

View Source
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           = "*"
)
View Source
const (
	CodecNameJSON     = "json"
	CodecNameMsgpack  = "msgpack"
	CodecNameProtobuf = "protobuf"
)

CodecName constants for format negotiation.

View Source
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"
)
View Source
const (
	ErrCodeBadRequest     = 400
	ErrCodeUnauthorized   = 401
	ErrCodeForbidden      = 403
	ErrCodeNotFound       = 404
	ErrCodeMethodNotFound = 405
	ErrCodeConflict       = 409
	ErrCodeInternal       = 500
)

Variables

View Source
var ErrUnauthorized = fmt.Errorf("dwp: unauthorized")

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

func RequiredScope(method string) string

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

func (a *APIKeyAuthenticator) Authenticate(_ context.Context, token string) (*Identity, error)

type APIKeyEntry

type APIKeyEntry struct {
	Token    string
	Identity Identity
}

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

type AuthResponse struct {
	Format    string `json:"format"`
	SessionID string `json:"session_id"`
}

AuthResponse is returned after successful authentication.

type Authenticator

type Authenticator interface {
	Authenticate(ctx context.Context, token string) (*Identity, error)
}

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.

func GetCodec

func GetCodec(name string) Codec

GetCodec returns a codec by name. Defaults to JSON.

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

func (c *CompositeAuthenticator) Authenticate(ctx context.Context, token string) (*Identity, error)

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.

func (*Connection) Touch

func (c *Connection) Touch()

Touch updates the last activity timestamp.

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 (a *ForgeAuthenticator) Authenticate(context.Context, string) (*Identity, error)

func (*ForgeAuthenticator) AuthenticateRequest

func (a *ForgeAuthenticator) AuthenticateRequest(ctx context.Context, r *http.Request, token string) (*Identity, error)

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

func NewErrorFrame(correlID string, code int, message string) *Frame

NewErrorFrame creates an error response to a request.

func NewEventFrame

func NewEventFrame(channel string, data any) (*Frame, error)

NewEventFrame creates an event frame for a subscription channel.

func NewRequestFrame

func NewRequestFrame(id, method string, data any) (*Frame, error)

NewRequestFrame creates a new request frame.

func NewResponseFrame

func NewResponseFrame(correlID string, data any) (*Frame, error)

NewResponseFrame creates a response to a request.

type FrameType

type FrameType string

FrameType identifies the frame category.

const (
	FrameRequest  FrameType = "request"
	FrameResponse FrameType = "response"
	FrameEvent    FrameType = "event"
	FrameErr      FrameType = "error"
	FramePing     FrameType = "ping"
	FramePong     FrameType = "pong"
)

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

func (h *Handler) Handle(ctx context.Context, frame *Frame, conn *Connection) (response *Frame)

Handle processes a single DWP request frame and returns a response.

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.

func (*Identity) HasScope

func (id *Identity) HasScope(scope string) bool

HasScope returns true if the identity has the given scope. A wildcard "*" scope grants all permissions.

type JSONCodec

type JSONCodec struct{}

JSONCodec encodes/decodes DWP frames as JSON.

func (*JSONCodec) Decode

func (c *JSONCodec) Decode(data []byte) (*Frame, error)

func (*JSONCodec) Encode

func (c *JSONCodec) Encode(frame *Frame) ([]byte, error)

func (*JSONCodec) Name

func (c *JSONCodec) Name() string

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

func (c *MsgpackCodec) Decode(data []byte) (*Frame, error)

func (*MsgpackCodec) Encode

func (c *MsgpackCodec) Encode(frame *Frame) ([]byte, error)

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

func (a *NoopAuthenticator) Authenticate(_ context.Context, _ string) (*Identity, error)

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

func WithCodec(codec Codec) Option

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

func WithLogger(logger log.Logger) Option

WithLogger sets the logger for the DWP server.

func WithPath

func WithPath(path string) Option

WithPath sets the base path for DWP endpoints. Default is "/dwp".

func WithSecurity

func WithSecurity(boundary security.Boundary) Option

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.

const (
	PeerStateConnected    PeerState = "connected"
	PeerStateDisconnected PeerState = "disconnected"
	PeerStateConnecting   PeerState = "connecting"
)

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 NewServer

func NewServer(broker *stream.Broker, handler *Handler, opts ...Option) *Server

NewServer creates a new DWP server.

func (*Server) Broker

func (s *Server) Broker() *stream.Broker

Broker returns the underlying stream broker.

func (*Server) Connections

func (s *Server) Connections() *ConnectionManager

Connections returns the connection manager.

func (*Server) RegisterRoutes

func (s *Server) RegisterRoutes(router forge.Router)

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.

Jump to

Keyboard shortcuts

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