runtime

package
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Jan 21, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const EnvBifrostRole = "BIFROST_ROLE"

Environment variable used to identify worker processes.

View Source
const RoleWorker = "worker"

RoleWorker is the value of BIFROST_ROLE for worker processes.

Variables

View Source
var ErrMasterShuttingDown = errors.New("master is shutting down")

ErrMasterShuttingDown is returned when operations are attempted during shutdown.

View Source
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

func InheritedListeners() (map[string]*os.File, error)

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

func SetProcessName(name string) error

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

type CommandRunner interface {
	Command(name string, arg ...string) *exec.Cmd
}

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:

  1. If opts.SocketPath is provided (from config.UpgradeSock), use it as file socket
  2. On Linux: use Abstract Namespace (no filesystem cleanup needed)
  3. 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

func (cp *ControlPlane) ReceiveFDsFromConn(conn net.Conn) ([]*os.File, error)

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

type ControlPlaneClient interface {
	SendFDs(files []*os.File, keys []string) error
}

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 EnvGetter added in v0.8.0

type EnvGetter func(string) string

EnvGetter is a function type for retrieving environment variables.

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

type FileOpener func(name string) (*os.File, error)

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

func (k *KeepAlive) CurrentBackoff() time.Duration

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

func (k *KeepAlive) RestartsInLastMinute() int

RestartsInLastMinute returns the number of restarts in the last minute.

func (*KeepAlive) ShouldRestart added in v0.8.0

func (k *KeepAlive) ShouldRestart() (shouldRestart bool, backoffDuration time.Duration, err error)

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

func (m *Master) Run(ctx context.Context) error

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) Shutdown added in v0.8.0

func (m *Master) Shutdown(ctx context.Context) error

Shutdown gracefully stops the Master and its Worker.

func (*Master) State added in v0.8.0

func (m *Master) State() MasterState

State returns the current state of the Master.

func (*Master) WorkerPID added in v0.8.0

func (m *Master) WorkerPID() int

WorkerPID returns the PID of the current Worker process. Returns 0 if no Worker is running.

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

type ProcessFinder interface {
	FindProcess(pid int) (process, error)
}

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.

func (*WorkerControlPlane) SendFDs added in v0.8.0

func (wcp *WorkerControlPlane) SendFDs(files []*os.File, keys []string) error

SendFDs opens a dedicated connection to Master and sends listener FDs.

func (*WorkerControlPlane) Start added in v0.8.0

func (wcp *WorkerControlPlane) Start(ctx context.Context, fdHandler FDHandler) error

Start starts the worker control plane loop to handle messages from Master. It blocks until the context is cancelled or the connection is closed.

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

type ZeroDownTime struct {
	QuitTimeout time.Duration
	// contains filtered or unexported fields
}

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.

Jump to

Keyboard shortcuts

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