SmolBox.Execution (SmolBox v0.1.0)

Copy Markdown View Source

Versioned persisted execution evidence, independent of caller processes.

State, execution evidence, collection, and cleanup are separate dimensions. Versioned store operations are the authority; this module only validates and transforms records. A transition never sends a worker request. Dispatching may advance directly to collecting when buffered exec returns a known exit.

Absolute stage deadlines are set on first entry and never reset by observation or restart. Uncertain execution can have confirmed termination and completed cleanup while its original command outcome remains unknown.

Summary

Functions

Atomic store acceptance must call this before admission; queue expiry never dispatches.

States that require no further command dispatch or outcome observation.

Validate a store patch; immutable identity, claims and reservations cannot be patched.

Validate a persisted record after decoding it, including shapes that could contain BEAM resources.

Types

key()

@type key() :: {String.t(), String.t()}

state()

@type state() ::
  :accepted
  | :preparing
  | :ready
  | :dispatching
  | :running
  | :collecting
  | :completed
  | :collection_failed
  | :failed
  | :cancelled
  | :expired
  | :unknown
  | :cancelling

t()

@type t() :: %SmolBox.Execution{
  absence_at_ms: non_neg_integer() | nil,
  accepted_at_ms: non_neg_integer(),
  artifacts: [map()],
  cancel_requested_at_ms: non_neg_integer() | nil,
  claim_owner: String.t() | nil,
  claim_until_ms: non_neg_integer() | nil,
  cleanup: :pending | :in_progress | :complete | :failed,
  cleanup_attempts: non_neg_integer(),
  collection: :pending | :complete | :partial | :failed,
  created_machine: SmolBox.Machine.t() | nil,
  deadlines: %{required(atom()) => non_neg_integer()},
  errors: [%{at_ms: non_neg_integer(), error: SmolBox.Error.t()}],
  evidence: atom(),
  fingerprint: String.t(),
  generation: non_neg_integer(),
  id: String.t(),
  last_error: SmolBox.Error.t() | nil,
  machine_name: String.t() | nil,
  next_due_at_ms: non_neg_integer(),
  reservation: %{required(atom()) => pos_integer()} | nil,
  result: SmolBox.Result.t() | nil,
  schema: 1,
  scope: String.t(),
  spec: SmolBox.ExecutionSpec.t(),
  state: state(),
  updated_at_ms: non_neg_integer(),
  version: pos_integer(),
  worker_generation: non_neg_integer() | nil,
  worker_id: String.t() | nil
}

Functions

expired?(record, now)

@spec expired?(t(), non_neg_integer()) :: boolean()

Atomic store acceptance must call this before admission; queue expiry never dispatches.

key(record)

@spec key(t()) :: key()

new(spec, fingerprint, now)

@spec new(SmolBox.ExecutionSpec.t(), String.t(), non_neg_integer()) ::
  {:ok, t()} | {:error, SmolBox.Error.t()}

terminal?(record)

@spec terminal?(t()) :: boolean()

States that require no further command dispatch or outcome observation.

transition(record, changes, now)

@spec transition(t(), keyword(), non_neg_integer()) ::
  {:ok, t()} | {:error, SmolBox.Error.t()}

Validate a store patch; immutable identity, claims and reservations cannot be patched.

validate(record)

@spec validate(term()) :: :ok | {:error, SmolBox.Error.t()}

Validate a persisted record after decoding it, including shapes that could contain BEAM resources.