Documentation
¶
Index ¶
- Constants
- Variables
- func GetControlSocketPath() string
- func InheritedListeners() (map[string]*os.File, error)
- func IsWorker() bool
- func NotifySystemdReady()
- func SetProcessName(name string) error
- type CommandRunner
- type ControlMessage
- type ControlPlane
- func (cp *ControlPlane) Accept(ctx context.Context) error
- func (cp *ControlPlane) Close() error
- func (cp *ControlPlane) Listen() error
- func (cp *ControlPlane) ReceiveFDsFromConn(conn net.Conn) ([]*os.File, error)
- func (cp *ControlPlane) SendMessage(workerPID int, msg *ControlMessage) error
- func (cp *ControlPlane) SetFDHandler(handler func(fds []*os.File, keys []string))
- func (cp *ControlPlane) SetMessageHandler(handler func(conn net.Conn, msg *ControlMessage))
- func (cp *ControlPlane) SocketPath() string
- type ControlPlaneClient
- type ControlPlaneOptions
- type EnvGetter
- type FDHandler
- type FileOpener
- type KeepAlive
- type KeepAliveOptions
- type ListenerOptions
- type Master
- type MasterOptions
- type MasterState
- type MessageType
- type Options
- type ProcessFinder
- type State
- type WorkerControlPlane
- func (wcp *WorkerControlPlane) Close() error
- func (wcp *WorkerControlPlane) Connect() error
- func (wcp *WorkerControlPlane) NotifyReady() error
- func (wcp *WorkerControlPlane) Register() error
- func (wcp *WorkerControlPlane) SendFDs(files []*os.File, keys []string) error
- func (wcp *WorkerControlPlane) Start(ctx context.Context, fdHandler FDHandler) error
- type WorkerFDHandler
- type ZeroDownTime
- func (z *ZeroDownTime) Close(ctx context.Context) error
- func (z *ZeroDownTime) GetListeners() []*listenInfo
- func (z *ZeroDownTime) IsUpgraded() bool
- func (z *ZeroDownTime) IsWaiting() bool
- func (z *ZeroDownTime) Listener(ctx context.Context, options *ListenerOptions) (net.Listener, error)
- func (z *ZeroDownTime) WaitForUpgrade(ctx context.Context) error
Constants ¶
const EnvBifrostRole = "BIFROST_ROLE"
Environment variable used to identify worker processes.
const RoleWorker = "worker"
RoleWorker is the value of BIFROST_ROLE for worker processes.
Variables ¶
var ErrMasterShuttingDown = errors.New("master is shutting down")
ErrMasterShuttingDown is returned when operations are attempted during shutdown.
var ErrRestartLimitExceeded = errors.New("restart limit exceeded: too many restarts in the last minute")
ErrRestartLimitExceeded is returned when the maximum restart rate is exceeded.
Functions ¶
func GetControlSocketPath ¶ added in v0.8.0
func GetControlSocketPath() string
GetControlSocketPath returns the control socket path from environment. The path is base64 encoded to handle Abstract Namespace NUL bytes.
func InheritedListeners ¶ added in v0.8.0
InheritedListeners returns the listener FDs and their keys inherited from Master. Worker calls this on startup when UPGRADE=1.
func IsWorker ¶ added in v0.8.0
func IsWorker() bool
IsWorker returns true if the current process is a worker.
func NotifySystemdReady ¶ added in v0.8.0
func NotifySystemdReady()
NotifySystemdReady notifies systemd that the service is ready. This should be called after the Worker has confirmed it is ready. If not running under systemd (NOTIFY_SOCKET not set), this is a no-op.
func SetProcessName ¶ added in v0.8.0
SetProcessName sets the process name visible in /proc/[pid]/comm. This name appears in tools like top, htop, and ps -o comm. Maximum 15 characters (Linux kernel limitation for PR_SET_NAME).
Types ¶
type CommandRunner ¶ added in v0.8.0
CommandRunner is an interface for creating exec.Cmd instances. It allows for dependency injection in testing scenarios.
type ControlMessage ¶ added in v0.8.0
type ControlMessage struct {
// Type is the message type.
Type MessageType `json:"type"`
// WorkerPID is the PID of the Worker sending the message.
WorkerPID int `json:"worker_pid,omitempty"`
// Payload contains optional additional data.
Payload []byte `json:"payload,omitempty"`
}
ControlMessage represents a message exchanged between Master and Worker.
type ControlPlane ¶ added in v0.8.0
type ControlPlane struct {
// contains filtered or unexported fields
}
ControlPlane provides Unix Domain Socket communication between Master and Worker. It uses Linux Abstract Namespace to avoid filesystem issues.
func NewControlPlane ¶ added in v0.8.0
func NewControlPlane(opts *ControlPlaneOptions) *ControlPlane
NewControlPlane creates a new ControlPlane instance. The Master calls this to create the UDS server.
Socket path priority:
- If opts.SocketPath is provided (from config.UpgradeSock), use it as file socket
- On Linux: use Abstract Namespace (no filesystem cleanup needed)
- On macOS/BSD: use file socket in /tmp
func (*ControlPlane) Accept ¶ added in v0.8.0
func (cp *ControlPlane) Accept(ctx context.Context) error
Accept accepts incoming Worker connections and handles messages. This blocks and should be run in a goroutine.
func (*ControlPlane) Close ¶ added in v0.8.0
func (cp *ControlPlane) Close() error
Close shuts down the ControlPlane.
func (*ControlPlane) Listen ¶ added in v0.8.0
func (cp *ControlPlane) Listen() error
Listen starts the UDS server (Master side). For file-based sockets, it cleans up any stale socket files first. Note: Go 1.12+ automatically sets CLOEXEC on all FDs, preventing leak to child processes.
func (*ControlPlane) ReceiveFDsFromConn ¶ added in v0.8.0
ReceiveFDsFromConn extracts FDs from the given connection using SCM_RIGHTS.
func (*ControlPlane) SendMessage ¶ added in v0.8.0
func (cp *ControlPlane) SendMessage(workerPID int, msg *ControlMessage) error
SendMessage sends a control message to a specific Worker.
func (*ControlPlane) SetFDHandler ¶ added in v0.8.0
func (cp *ControlPlane) SetFDHandler(handler func(fds []*os.File, keys []string))
SetFDHandler sets the callback for handling incoming FDs.
func (*ControlPlane) SetMessageHandler ¶ added in v0.8.0
func (cp *ControlPlane) SetMessageHandler(handler func(conn net.Conn, msg *ControlMessage))
SetMessageHandler sets the callback for handling incoming messages.
func (*ControlPlane) SocketPath ¶ added in v0.8.0
func (cp *ControlPlane) SocketPath() string
SocketPath returns the socket path used by this ControlPlane.
type ControlPlaneClient ¶ added in v0.8.0
ControlPlaneClient defines the methods required by WorkerFDHandler to communicate with Master.
type ControlPlaneOptions ¶ added in v0.8.0
type ControlPlaneOptions struct {
// SocketPath is the UDS path. If empty, uses Abstract Namespace.
// Abstract Namespace format: "\x00bifrost-{pid}.sock"
SocketPath string
}
ControlPlaneOptions contains configuration for the ControlPlane.
type FDHandler ¶ added in v0.8.0
type FDHandler interface {
HandleFDRequest() error
}
FDHandler is an interface for handling file descriptor requests.
type FileOpener ¶ added in v0.8.0
FileOpener is a function type for opening files.
type KeepAlive ¶ added in v0.8.0
type KeepAlive struct {
// contains filtered or unexported fields
}
KeepAlive implements exponential backoff restart strategy for Worker processes. It prevents restart storms when a Worker has a fatal bug.
func NewKeepAlive ¶ added in v0.8.0
func NewKeepAlive(opts *KeepAliveOptions) *KeepAlive
NewKeepAlive creates a new KeepAlive instance.
func (*KeepAlive) CurrentBackoff ¶ added in v0.8.0
CurrentBackoff returns the current backoff duration.
func (*KeepAlive) RecordRestart ¶ added in v0.8.0
func (k *KeepAlive) RecordRestart()
RecordRestart records a restart event and updates backoff.
func (*KeepAlive) Reset ¶ added in v0.8.0
func (k *KeepAlive) Reset()
Reset resets the backoff to initial value. Called when Worker has been running stably for a period.
func (*KeepAlive) RestartsInLastMinute ¶ added in v0.8.0
RestartsInLastMinute returns the number of restarts in the last minute.
func (*KeepAlive) ShouldRestart ¶ added in v0.8.0
ShouldRestart determines if a Worker should be restarted. Returns:
- shouldRestart: true if restart is allowed
- backoffDuration: how long to wait before restarting
- error: non-nil if restart limit exceeded (Master should exit)
type KeepAliveOptions ¶ added in v0.8.0
type KeepAliveOptions struct {
// InitialBackoff is the initial backoff duration (default: 1s).
InitialBackoff time.Duration
// MaxBackoff is the maximum backoff duration (default: 32s).
MaxBackoff time.Duration
// MaxRestartsPerMinute is the maximum restarts allowed per minute (default: 5).
MaxRestartsPerMinute int
}
KeepAliveOptions contains configuration for the KeepAlive strategy.
func DefaultKeepAliveOptions ¶ added in v0.8.0
func DefaultKeepAliveOptions() *KeepAliveOptions
DefaultKeepAliveOptions returns the default KeepAlive configuration.
type ListenerOptions ¶ added in v0.8.0
type ListenerOptions struct {
// Config is an optional net.ListenConfig for customizing the listener.
Config *net.ListenConfig
// Network specifies the network type (e.g., "tcp", "tcp4", "tcp6").
Network string
// Address is the address to listen on (e.g., ":8080", "localhost:3000").
Address string
// ProxyProtocol enables PROXY protocol support for the listener.
ProxyProtocol bool
}
ListenerOptions contains configuration for creating a network listener.
type Master ¶ added in v0.8.0
type Master struct {
// contains filtered or unexported fields
}
Master manages the lifecycle of Worker processes. It provides PID stability for process managers (Systemd, Supervisor) and handles signal forwarding, hot reload, and worker monitoring.
func NewMaster ¶ added in v0.8.0
func NewMaster(opts *MasterOptions) *Master
NewMaster creates a new Master instance with the given options.
func (*Master) ControlPlane ¶ added in v0.8.0
func (m *Master) ControlPlane() *ControlPlane
ControlPlane returns the control plane instance.
func (*Master) Run ¶ added in v0.8.0
Run starts the Master's main loop. It spawns the initial Worker and waits for signals:
- SIGHUP: triggers hot reload (spawn new Worker, gracefully stop old)
- SIGTERM/SIGINT: triggers graceful shutdown of Worker and Master
This method blocks until shutdown is complete.
func (*Master) State ¶ added in v0.8.0
func (m *Master) State() MasterState
State returns the current state of the Master.
type MasterOptions ¶ added in v0.8.0
type MasterOptions struct {
// ConfigPath is the path to the configuration file passed to Worker.
ConfigPath string
// Binary is the path to the executable (defaults to os.Args[0]).
Binary string
// Args are additional arguments passed to the Worker process.
Args []string
// GracefulTimeout is the maximum time to wait for Worker graceful shutdown.
GracefulTimeout time.Duration
// KeepAlive is the KeepAlive strategy configuration.
KeepAlive *KeepAliveOptions
}
MasterOptions contains configuration for the Master process.
type MasterState ¶ added in v0.8.0
type MasterState int8
MasterState represents the current state of the Master process.
const ( // MasterStateIdle indicates the master is idle and ready to spawn a worker. MasterStateIdle MasterState = iota // MasterStateRunning indicates the master has an active worker. MasterStateRunning // MasterStateReloading indicates a hot reload is in progress. MasterStateReloading // MasterStateShuttingDown indicates graceful shutdown is in progress. MasterStateShuttingDown )
func (MasterState) String ¶ added in v0.8.0
func (s MasterState) String() string
String returns the string representation of MasterState.
type MessageType ¶ added in v0.8.0
type MessageType string
MessageType represents the type of control message sent via UDS.
const ( // MessageTypeRegister is sent by Worker to Master upon startup. MessageTypeRegister MessageType = "register" // MessageTypeReady is sent by Worker to Master when ready to serve traffic. MessageTypeReady MessageType = "ready" // MessageTypeFDRequest is sent by Master to Worker to request listener FDs. MessageTypeFDRequest MessageType = "fd_request" // MessageTypeFDTransferStart is sent by Worker to Master on a DEDICATED connection to start FD transfer. MessageTypeFDTransferStart MessageType = "fd_transfer_start" // MessageTypeAck is sent by Master to Worker to acknowledge readiness for raw data. MessageTypeAck MessageType = "ack" // MessageTypeShutdown is sent by Master to Worker to request graceful shutdown. MessageTypeShutdown MessageType = "shutdown" )
type Options ¶ added in v0.8.0
type Options struct {
// QuitTimout is the maximum time to wait for the old process to terminate.
QuitTimout time.Duration
}
Options contains configuration for the ZeroDownTime instance.
type ProcessFinder ¶ added in v0.8.0
ProcessFinder is an interface for finding processes by PID. It allows for dependency injection in testing scenarios.
type State ¶ added in v0.8.0
type State int8
State represents the current state of the ZeroDownTime instance.
type WorkerControlPlane ¶ added in v0.8.0
type WorkerControlPlane struct {
// contains filtered or unexported fields
}
WorkerControlPlane is the Worker-side control plane client.
func NewWorkerControlPlane ¶ added in v0.8.0
func NewWorkerControlPlane(socketPath string) *WorkerControlPlane
NewWorkerControlPlane creates a Worker-side control plane client.
func (*WorkerControlPlane) Close ¶ added in v0.8.0
func (wcp *WorkerControlPlane) Close() error
Close closes the connection to Master.
func (*WorkerControlPlane) Connect ¶ added in v0.8.0
func (wcp *WorkerControlPlane) Connect() error
Connect connects to the Master's ControlPlane.
func (*WorkerControlPlane) NotifyReady ¶ added in v0.8.0
func (wcp *WorkerControlPlane) NotifyReady() error
NotifyReady sends a ready message to Master.
func (*WorkerControlPlane) Register ¶ added in v0.8.0
func (wcp *WorkerControlPlane) Register() error
Register sends a register message to Master.
type WorkerFDHandler ¶ added in v0.8.0
type WorkerFDHandler struct {
// contains filtered or unexported fields
}
WorkerFDHandler handles FD requests from Master in Worker processes. It collects listener file descriptors and sends them to Master via ControlPlane.
func NewWorkerFDHandler ¶ added in v0.8.0
func NewWorkerFDHandler(wcp ControlPlaneClient) *WorkerFDHandler
NewWorkerFDHandler creates a new WorkerFDHandler.
func (*WorkerFDHandler) HandleFDRequest ¶ added in v0.8.0
func (h *WorkerFDHandler) HandleFDRequest() error
HandleFDRequest handles an FD request from Master. It collects all listener FDs and keys, then sends them via the control plane.
func (*WorkerFDHandler) ListenerCount ¶ added in v0.8.0
func (h *WorkerFDHandler) ListenerCount() int
ListenerCount returns the number of registered listeners.
func (*WorkerFDHandler) RegisterListener ¶ added in v0.8.0
func (h *WorkerFDHandler) RegisterListener(listener net.Listener, key string)
RegisterListener registers a listener for FD transfer. Call this for each listener the Worker creates or inherits.
type ZeroDownTime ¶ added in v0.8.0
ZeroDownTime provides zero-downtime restart functionality for server processes. It manages PID files, upgrade sockets, and listener inheritance to enable seamless process upgrades without dropping connections.
func New ¶ added in v0.8.0
func New(opts Options) *ZeroDownTime
New creates a new ZeroDownTime instance with the given options. If QuitTimeout is not specified, it defaults to 10 seconds.
func (*ZeroDownTime) Close ¶ added in v0.8.0
func (z *ZeroDownTime) Close(ctx context.Context) error
Close shuts down the ZeroDownTime instance by closing all listeners and stopping the upgrade waiting goroutine if active.
func (*ZeroDownTime) GetListeners ¶ added in v0.8.0
func (z *ZeroDownTime) GetListeners() []*listenInfo
GetListeners returns the list of active listeners.
func (*ZeroDownTime) IsUpgraded ¶ added in v0.8.0
func (z *ZeroDownTime) IsUpgraded() bool
IsUpgraded returns true if this process was spawned as part of an upgrade. It checks for the presence of the UPGRADE environment variable.
func (*ZeroDownTime) IsWaiting ¶ added in v0.8.0
func (z *ZeroDownTime) IsWaiting() bool
IsWaiting returns true if the instance is in the waitingState.
func (*ZeroDownTime) Listener ¶ added in v0.8.0
func (z *ZeroDownTime) Listener(ctx context.Context, options *ListenerOptions) (net.Listener, error)
Listener returns a network listener for the given options. If this is an upgraded process, it attempts to inherit the listener from the parent process. Otherwise, it creates a new listener. The listener is cached for reuse.
func (*ZeroDownTime) WaitForUpgrade ¶ added in v0.8.0
func (z *ZeroDownTime) WaitForUpgrade(ctx context.Context) error
WaitForUpgrade blocks until a SIGHUP signal is received. When an upgrade is triggered, it spawns a new process with inherited file descriptors and waits for the Close method to be called before returning.