scheduler

package
v0.3.0-rc.1 Latest Latest
Warning

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

Go to latest
Published: Oct 6, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// MaxModuleBytes is a decoded WASM limit. HTTP's separate 32 MiB envelope
	// includes base64 and JSON overhead; gRPC's message ceiling includes protobuf.
	MaxModuleBytes    = uploadsize.MaxModuleBytes
	MaxStoredRunBytes = uploadsize.MaxStoredRunBytes
	// QueueRowCharge accounts for fixed row metadata independently of payloads.
	QueueRowCharge = uploadsize.RowCharge
)
View Source
const CleanupTimeout = 5 * time.Second

CleanupTimeout bounds an individual resource-cleanup/report operation or SQL statement after connection admission. Owned finalization may wait longer for a connection; caller deadlines separately bound Cancel and Shutdown joins.

Variables

View Source
var (
	ErrClosed          = errors.New("scheduler is shut down")
	ErrBindingMismatch = errors.New("debuglet belongs to another control session")
	// ErrDebugletAlreadyStarted is returned when a debuglet has already started, but the executor was restarted before it could finish.
	ErrDebugletAlreadyStarted = errors.New("debuglet has already started. won't restart")
)
View Source
var (
	ErrUploadLimit = uploadsize.ErrLimit
	ErrQueueLimit  = errors.New("executor retained queue limit reached")
)
View Source
var ErrTerminalNotRetained = errors.New("terminal event is not retained under this control binding")

ErrTerminalNotRetained reports that no retained event with the requested identity belongs to the supplied binding. A replaced session therefore cannot alter or release the events of the session it replaced.

Functions

func StoredRunBytes added in v0.3.0

func StoredRunBytes(spec Spec) (int64, error)

StoredRunBytes counts the bytes the queue stores: decoded WASM, encoded list columns, text columns and a fixed per-row charge. It checks lengths before serializing argument/address lists, and does not allocate payload copies.

Types

type Admission

type Admission struct {
	Insert AdmissionGuard
	Start  AdmissionGuard
}

Admission supplies construction-fixed authority for new persistence reservations and queue promotion. Every constructor requires both, so a core always commits under a guard; a caller whose subject is not admission supplies guards that always commit.

type AdmissionGuard

type AdmissionGuard func(controlsession.Binding, func()) error

AdmissionGuard commits a bounded in-memory core transition only while its original control binding is eligible. The core holds its mutex before the session guard; commit must never do I/O, cancel, close or wait for work.

type Completion

type Completion struct {
	CleanupErr error
}

Completion records local resource cleanup after an owned callback joins its execution and workers. Execution/reporting outcomes are separate.

type Disposition

type Disposition struct {
	// Retained is every stored execution row, whatever its binding.
	Retained int64 `json:"retained"`
	// Started counts retained rows that carry a start marker. This build
	// never re-runs one: a restarted executor refuses a row it already
	// started instead of executing it a second time.
	Started int64 `json:"started"`
	// Queued counts retained rows that were accepted and persisted but
	// never started. They stay in the database; nothing replays them.
	Queued int64 `json:"queued"`
	// Quarantined counts unarchived execution rows the next start will
	// refuse to restore because their control session ended.
	Quarantined int64 `json:"quarantined"`
	// Archived counts explicit local operator dispositions. Original evidence
	// stays retained, but these runs cannot return to the execution queue.
	Archived int64 `json:"archived"`
	// Bindings counts the distinct control sessions the retained rows came
	// from, so an operator can see whether retained work accumulated over
	// several sessions.
	Bindings int `json:"bindings"`
	// RetainedTerminal counts terminal results this executor still holds
	// because it has not observed a durable acknowledgement for them.
	RetainedTerminal int64 `json:"retained_terminal"`
	// UnsentTerminal counts retained results no delivery attempt ever left
	// the executor for. The dispatcher cannot hold these.
	UnsentTerminal int64 `json:"unsent_terminal"`
	// RejectedTerminal counts retained results the dispatcher refused
	// permanently. They stay as evidence and are never retried.
	RejectedTerminal int64 `json:"rejected_terminal"`
	// Truncated reports that the retained rows come from more control
	// sessions than the inspection counts, so Bindings is a lower bound.
	// The counts of rows and results above are always exact.
	Truncated bool `json:"truncated"`
}

Disposition is what an executor's retained storage holds once no session owns it any more: the evidence an operator needs before deciding whether a drained node may be upgraded, deleted or rebuilt.

It is a count of stored rows, not a claim about remote state. A retained terminal event in particular says only that this executor selected a result and does not know whether the dispatcher recorded it; a delivered but unacknowledged result and an undelivered one are indistinguishable here, and both are reported as still retained.

func (Disposition) Empty

func (d Disposition) Empty() bool

Empty reports storage that holds no retained execution row and no retained terminal result: nothing local is left that an operator has to preserve.

func (Disposition) Summary

func (d Disposition) Summary() string

Summary describes the disposition in one line of operator-facing text.

type FailedFunc

type FailedFunc func(context.Context, Spec, error) Completion

type Policy

type Policy struct {
	FloorBW     int64
	CeilBW      int64
	Timeout     time.Duration
	Addresses   []string
	RequireICMP bool
	ListenUDP   bool
	ListenTCP   bool
	ListenSCION bool
}

type QueueLimits added in v0.3.0

type QueueLimits struct {
	Bytes int64
	Runs  int64
}

QueueLimits bounds retained execution rows, including started and quarantined rows. Output spools have a separate budget. Limits are fixed on construction.

func DefaultQueueLimits added in v0.3.0

func DefaultQueueLimits() QueueLimits

func (QueueLimits) Validate added in v0.3.0

func (l QueueLimits) Validate() error

type RestoreEligibility

type RestoreEligibility func(controlsession.Binding) bool

RestoreEligibility is an explicit startup policy. Invalid bindings and a nil policy always quarantine a stored row before any execution/failure callback.

type RetainedRun

type RetainedRun struct {
	Status        RetainedRunStatus
	DebugletID    uuid.UUID
	Binding       controlsession.Binding
	TransactionID string
	StartTime     time.Time
	StartedAt     time.Time
}

RetainedRun is the identity half of a stored run: who owned it, whether it was ever started, and when it was due. It never carries the guest program.

func (RetainedRun) Started

func (r RetainedRun) Started() bool

Started reports whether the stored row carries a start marker.

type RetainedRunStatus

type RetainedRunStatus uint8

RetainedRunStatus classifies a retained-run point lookup. A miss caused by the current-binding filter is deliberately distinct from proof that no stored row with that identity exists.

const (
	// RetainedRunUnknown is never returned by a successful lookup.
	RetainedRunUnknown RetainedRunStatus = iota
	// RetainedRunFound reports validated metadata for a retained row.
	RetainedRunFound
	// RetainedRunFiltered reports that a stored row exists but belongs to the
	// caller's current control binding, so it is not retained work.
	RetainedRunFiltered
	// RetainedRunAbsent reports that no stored row has this identity.
	RetainedRunAbsent
)

func (RetainedRunStatus) String

func (s RetainedRunStatus) String() string

type RunInspection

type RunInspection interface {
	// InspectRetainedRun reads one stored row, excluding rows that belong to
	// the supplied current binding. The reader is owned for the whole call:
	// caller cancellation bounds the caller's wait, never the backend's use of
	// its connection.
	InspectRetainedRun(ctx context.Context, id uuid.UUID, current controlsession.Binding) (RetainedRun, error)
}

RunInspection is implemented by backends that can answer a bounded point lookup for one retained run without scheduling, finalizing or deleting it.

type Scheduler

type Scheduler interface {
	Insert(context.Context, Spec) error
	// CancelBound compares immutable run ownership atomically before cancellation.
	// It never cancels a later admission after observing an absent owner.
	CancelBound(context.Context, uuid.UUID, controlsession.Binding, error) (bool, error)
	// RegisterOnStart sets the callback function for when a debuglet should be started.
	RegisterOnStart(StartFunc)
	// RegisterFailed sets the callback function for when a debuglet fails to start or is not allowed to start anymore.
	RegisterFailed(FailedFunc)
	// StartLoop starts the loop that checks if any jobs are to be started and correspondingly calls the registered onStart function
	StartLoop(ctx context.Context) error
	// Shutdown closes new admission and joins owned active operations. Accepted
	// queued rows remain recoverable; existing insertion reservations complete.
	Shutdown(context.Context) error
}

Scheduler is what one session may ask of its storage. Cancellation is offered only as CancelBound, so no request can reach a run whose control binding it does not name; the unbound and queue-only deletions stay on the backends for their own tests.

type Spec

type Spec struct {
	OutputVersion uint32
	Binding       controlsession.Binding
	DebugletID    uuid.UUID
	StartTime     *time.Time
	Args          []string
	Wasm          []byte
	Policy        Policy
	TransactionID string
}

type StartFunc

type StartFunc func(context.Context, Spec) Completion

type TerminalAttempt

type TerminalAttempt struct {
	// Attempts counts the requests this pass actually sent.
	Attempts int64
	// Rejected reports a permanent refusal rather than a transient failure.
	Rejected bool
	Failure  error
}

TerminalAttempt records what one delivery pass learned about an event.

type TerminalEvent

type TerminalEvent struct {
	DebugletID   uuid.UUID
	Binding      controlsession.Binding
	ExitCode     int32
	ErrorMessage *string
	RecordedAt   time.Time
	// Attempts counts completed delivery attempts. Zero means the event was
	// retained but never sent; a positive count means the dispatcher may
	// already hold the same result, which its duplicate handling absorbs.
	Attempts      int64
	LastAttemptAt time.Time
	LastError     string
	// Rejected marks a cause the dispatcher will not accept on any retry. The
	// event stays as evidence and leaves the reconciliation set.
	Rejected bool
}

TerminalEvent is the terminal result an executor selected for one run, retained under that run's immutable identity and its original control binding. It is written before execution storage is deleted, so a lost response or connection still leaves evidence of what the executor decided and of how far delivery got.

type TerminalRetention

type TerminalRetention interface {
	// RecordTerminal retains the chosen result. It is idempotent under the run
	// identity and never rewrites an already retained result.
	RecordTerminal(context.Context, TerminalEvent) error
	// NoteTerminalFailure records what one failed delivery pass learned,
	// including its bounded cause. Zero attempts means the pass never reached
	// the dispatcher at all.
	NoteTerminalFailure(ctx context.Context, id uuid.UUID, binding controlsession.Binding, attempt TerminalAttempt) error
	// ReleaseTerminal ends retention after an acknowledgement was observed.
	ReleaseTerminal(ctx context.Context, id uuid.UUID, binding controlsession.Binding) error
	// ListRetainedTerminals reads at most limit events the given binding can
	// still deliver, oldest first. Rejected events and the events of other
	// sessions are excluded, so work no session can finish cannot crowd out
	// work that a session can.
	ListRetainedTerminals(ctx context.Context, binding controlsession.Binding, limit int64) ([]TerminalEvent, error)
}

TerminalRetention is implemented by backends that retain terminal results across restarts. Retention ends exactly when a durable acknowledgement is known: the delivery that observed it releases the event, and everything that is still retained is unreconciled and inspectable.

Recording, noting and releasing are single statements which do not reserve a backend operation, so a caller must keep the storage alive across them: the reporting path runs inside the owned callback Shutdown joins, and the reconciliation path runs inside a session worker joined before its transport and database are closed. ListRetainedTerminals reserves a backend operation of its own and is therefore joined by Shutdown without such a caller.

Directories

Path Synopsis
Package memory is the in-memory admission core both executor schedulers use.
Package memory is the in-memory admission core both executor schedulers use.
Package sqlite keeps one executor's persisted work and terminal results across restarts without silently running stored work again.
Package sqlite keeps one executor's persisted work and terminal results across restarts without silently running stored work again.

Jump to

Keyboard shortcuts

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