runtime

package
v0.710.6 Latest Latest
Warning

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

Go to latest
Published: Sep 11, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package runtime encapsulates the unified IPC bootstrap sequence that every Pando entrypoint must follow: derive ports, try the lock, open RW or RO DB, and wire services accordingly.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewPrimaryBus added in v0.710.6

func NewPrimaryBus(instanceID string) *ipc.Bus

NewPrimaryBus creates the Bus a primary serves on, with the ipc.ping liveness handler registered, so a freshly started secondary can tell a healthy primary apart from a suspended one (see killStalePrimary). Used by Bootstrap and by failover promotion, so a promoted primary answers the probe exactly like one that started as primary.

Types

type BootstrapResult

type BootstrapResult struct {
	Role Role

	// Querier is the db.Querier callers should use for all DB operations.
	// Primary: direct db.New(SQLDB). Secondary: a DBProxy that forwards writes
	// to the primary via ZMQ RPC and serves reads from the local RO connection.
	Querier db.Querier

	// SQLDB is the underlying *sql.DB. Primary holds a RW pool with WAL
	// pragmas applied and migrations run. Secondary holds a 1-connection RW
	// pool with a short busy_timeout (db.ConnectRWSecondary); on failover
	// promotion that same pool is upgraded in place (db.PromoteToPrimaryPool).
	SQLDB *sql.DB

	// Bus is non-nil only on the primary instance.
	Bus *ipc.Bus

	// IPCClient is non-nil only on the secondary instance.
	IPCClient *ipc.Client

	InstanceID string
	PubPort    int
	RPCPort    int

	// LockFile is the open flock file held by the primary, nil on secondary.
	LockFile *os.File

	// Watcher monitors primary liveness. Non-nil on a primary and on a
	// secondary with a working IPC client. Automatic failover is enabled by
	// default (failover.DefaultConfig); Watcher.SetEnabled(false) turns it off.
	// A secondary watcher never takes the IPC lock until a promotion callback
	// is registered with Watcher.SetPromoteCallback.
	Watcher *failover.Watcher

	// Cleanup releases all resources acquired during Bootstrap. On a primary
	// it follows the ordered handover: release the lock, announce
	// instance.shutdown, close the bus, then close the DB. It is idempotent;
	// the caller should call it on shutdown (typically deferred).
	Cleanup func()
	// contains filtered or unexported fields
}

BootstrapResult carries everything a caller needs after Bootstrap returns. Call Cleanup() on shutdown to release resources in correct order.

func Bootstrap

func Bootstrap(ctx context.Context, workdir, instanceID string) (*BootstrapResult, error)

Bootstrap runs the unified startup sequence for the given workdir using DefaultOptions. See BootstrapWithOptions for the full sequence and for entrypoints that need a different stale-primary policy.

func BootstrapWithOptions added in v0.710.6

func BootstrapWithOptions(ctx context.Context, workdir, instanceID string, opts Options) (*BootstrapResult, error)

BootstrapWithOptions runs the unified startup sequence for the given workdir.

  1. Derive deterministic PUB/RPC ports from the path.
  2. Attempt to acquire the exclusive IPC lock.
  3. Primary: open RW DB (with migrations), create Bus, create direct Querier.
  4. Secondary: open RO DB, create IPC Client, create DBProxy Querier.

On lock error the function continues as primary so the caller does not lose functionality — consistent with the existing root.go behaviour.

opts controls the stale-primary probe timeout and whether an unresponsive primary is killed (see Options). A zero opts.ProbeTimeout falls back to stalePrimaryProbeTimeout.

func (*BootstrapResult) ReleaseLock added in v0.710.6

func (r *BootstrapResult) ReleaseLock()

ReleaseLock releases the primary's IPC lock now, ahead of Cleanup, so a shutting-down primary can hand the lock over before it finishes its own (possibly slow) shutdown. Idempotent, and a no-op on a secondary; Cleanup calls it too.

type Options added in v0.710.6

type Options struct {
	// ProbeTimeout bounds how long a freshly started secondary waits for the
	// existing primary to answer ipc.ping before treating it as unresponsive.
	// Zero falls back to stalePrimaryProbeTimeout (10s).
	ProbeTimeout time.Duration

	// AllowKillStalePrimary, when true, SIGKILLs an unresponsive primary so
	// this instance can take over — Bootstrap's long-standing behaviour, and
	// correct for a TUI/ACP/serve/desktop/app instance where the previous
	// occupant of this workdir is presumed to be another one of the same kind.
	//
	// When false, an unresponsive primary is left alone: this instance
	// continues as a (degraded) secondary instead. Direct-first sqlc writes
	// still work as normal (DBProxy always tries them locally before
	// forwarding), but every remembrances write (which always proxies, never
	// direct) fails loudly once its forward times out, because there is
	// nobody alive to answer it. Intended for short-lived, low-trust
	// entrypoints (P2's ephemeral mcp-server) that must never kill a user's
	// long-running TUI/desktop/serve instance just because it is slow, under a
	// debugger, or SIGSTOPped to answer one probe.
	AllowKillStalePrimary bool
}

Options customizes Bootstrap's stale-primary handling. Use DefaultOptions (what Bootstrap itself uses) unless an entrypoint needs a different policy — see BootstrapWithOptions.

func DefaultOptions added in v0.710.6

func DefaultOptions() Options

DefaultOptions returns Bootstrap's long-standing policy: the 10s probe timeout (stalePrimaryProbeTimeout) and permission to kill an unresponsive primary.

type Role

type Role string

Role describes the IPC role that this instance took during bootstrap.

const (
	RolePrimary   Role = "primary"
	RoleSecondary Role = "secondary"
)

Jump to

Keyboard shortcuts

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