runnerplane

package
v0.0.11 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package runnerplane is the runner half of a Rainier control plane: the WebSocket endpoint runners dial, the connection registry behind it, the generation mint and its two fences, capability acceptance, reconciliation, event translation, and the dispatch correlation that makes control.RunnerTransport work.

It is composed, not configured. A host supplies the Host interface — who a connection is (Identify), where its generations come from (NextGeneration), the fleet service and repository the plane reports to, the scheduler wake, and the two hooks for what the plane deliberately does not decide: the events that transition no session (Aside) and the requests a sandbox sends upward (SessionRequest). Everything else — the socket, the announce, the registry, the fences, the retries — is here, once, for the self-hosted controld and a hosted cell alike.

The package imports only the standard library, coder/websocket, and the public control and protocol/runner contracts. It has no store, no HTTP routing of its own (Handler is mounted by the host), no SQL, and no provider.

Index

Constants

View Source
const MaxCapabilities = 32

MaxCapabilities is the most capabilities any one claim may carry.

Variables

This section is empty.

Functions

func ValidCapability

func ValidCapability(s string) bool

ValidCapability reports whether s is a well-formed portable capability. It is the one token rule, exported once so a host applies exactly the same one to the capabilities an operator writes on an environment.

Types

type Binding

type Binding struct {
	WorkspaceID control.WorkspaceID
	PoolID      control.PoolID
	RunnerID    control.RunnerID
}

Binding is the authoritative scope a connection acts in. The host derives it from the connection's credentials; the plane never decodes it from the announce, with the single exception noted on Host.Identify.

type Host

type Host interface {
	// Identify authenticates an inbound runner connection and names the scope
	// it acts in. It runs BEFORE the WebSocket upgrade — a refusal answers the
	// HTTP request with 401 and the announce is never read — so name is the
	// runner's name only when the request itself carries one, and empty on a
	// protocol like this one whose name arrives in the announce. A host that
	// binds identity to a credential returns its own RunnerID and the plane
	// refuses an announce naming anything else; a host whose credential is
	// fleet-wide leaves RunnerID empty and the plane fills it from the
	// announce.
	Identify(ctx context.Context, r *http.Request, name string) (Binding, error)
	// NextGeneration opens a new generation for the runner (the store's).
	NextGeneration(ctx context.Context, b Binding) (uint64, error)
	// Fleet is the application's fleet service: Register/Reconcile/ApplyRunnerEvent.
	Fleet() control.Fleet
	// FleetRepository is the heartbeat's and the disconnect's port.
	FleetRepository() control.FleetRepository
	// Wake asks the scheduler for a placement pass on the pool.
	Wake(pool control.PoolID)
	// Aside receives the events that transition no session — a finished setup
	// is news about the ENVIRONMENT, a rejected credential news about its
	// OWNER — after the plane has fenced them. gen is the generation the
	// message was produced under.
	Aside(ctx context.Context, b Binding, gen uint64, m runner.FromRunner)
	// SessionRequest answers an upward session RPC (a session_req) for the
	// session named; the answer is sent back down by the plane, which sets
	// its id and method. It runs off the connection's reader, so it may read
	// a store.
	SessionRequest(ctx context.Context, b Binding, sessionID control.SessionID, env runner.RPCEnvelope) runner.RPCEnvelope
}

Host is what a plane needs from its host. Every method is one dependency.

type Options

type Options struct {
	// OpTimeout is one dispatch round trip; zero means 60s.
	OpTimeout time.Duration
	// ReadLimit is the per-message read limit on a runner socket; zero means
	// 16 MiB, runnerd's own.
	ReadLimit int64
	// Logf is where the plane's diagnostics go; zero means log.Printf. A host
	// that prefixes its own program name supplies a wrapper.
	Logf func(string, ...any)
}

Options configures a plane. Every field has a working default.

type Plane

type Plane struct {
	// contains filtered or unexported fields
}

Plane is one replica's runner plane: the endpoint, the connections it holds, and the transport over them. Its zero value is not usable — construct it with New.

func New

func New(h Host, o Options) *Plane

New returns a plane over h.

func (*Plane) Broadcast

func (p *Plane) Broadcast(pool control.PoolID, m runner.ToRunner, except control.RunnerID)

Broadcast queues m for every runner of pool connected to this replica except the one named (pass "" to reach all of them) — how a fact one runner just produced reaches the rest of the fleet, which is the prepull of a freshly built environment snapshot.

Fire-and-forget by nature: there is no aggregate result worth waiting for, and a runner that misses the message loses nothing but a head start. The connection set is snapshotted under p.mu and the sends happen after it is released, so one wedged runner never stalls registration for the fleet.

func (*Plane) Close

func (p *Plane) Close()

Close hangs up on every connection this plane holds. Each handler then retires its own connection on the way out, exactly as a runner's own disconnect does.

func (*Plane) Handler

func (p *Plane) Handler() http.Handler

Handler is the runner WebSocket endpoint. The host mounts it at whatever path its API names (self-hosted: GET /v0/runners/connect).

func (*Plane) Send

func (p *Plane) Send(pool control.PoolID, id control.RunnerID, m runner.ToRunner) error

Send queues a command whose result nobody waits for (attach dial-backs and best-effort broadcasts). It reports only whether the command was queued for delivery. Orphan destroys use the transport instead: a driver failure must be visible so it can be retried without another reconnect.

func (*Plane) Transport

func (p *Plane) Transport() control.RunnerTransport

Transport is control.RunnerTransport over this plane's connections: the one downward path every application service takes to a runner.

Jump to

Keyboard shortcuts

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