Skip to content

Models

Immutable value types returned across the public API.

Every result object is frozen and slotted: a value handed to an application is owned by that application and never mutates underneath it. This mirrors the core's own discipline, where a host copies a borrowed effect value out of the ledger before the node's next transition invalidates the pointer.

Slot

Slot = int

A one-based position in the global decree log. Zero means "no slot".

NodeId

NodeId = int

A stable, non-zero identity for one member. Zero is reserved as a sentinel.

Message

Message = (
    Prepare
    | Promise
    | PromiseRange
    | Accept
    | Accepted
    | Commit
    | Learn
    | Nack
    | Heartbeat
)

One of the nine protocol messages. Match on the class, not on a tag.

Example

from paxodin import Accept, Commit def describe(message: Message) -> str: ... match message: ... case Accept(slot=slot): ... return f"vote requested for slot {slot}" ... case Commit(slot=slot): ... return f"slot {slot} decided" ... case _: ... return type(message).name

EntryKind

Bases: IntEnum

What a log entry actually is.

The distinction is load bearing. An application that treated all three as opaque bytes would apply a recovery filler as if it were a command, and mistake a reconfiguration for data.

COMMAND class-attribute instance-attribute

COMMAND = 1

An application command. Its payload may legitimately be empty.

NOOP class-attribute instance-attribute

NOOP = 2

A filler a leader chose into a hole during recovery. Never a command.

STOP_SIGN class-attribute instance-attribute

STOP_SIGN = 3

A sealing reconfiguration record, not application data.

WriteKind

Bases: IntEnum

Which durable record the host must journal.

MessageKind

Bases: IntEnum

Which protocol message an envelope carries.

Role

Bases: IntEnum

Proposer status. A follower still acts as acceptor and learner.

CellState

Bases: IntEnum

What an acceptor holds for one decree.

BatchPhase

Bases: IntEnum

Where a pending batch has got to.

A batch with no writes is born CONFIRMED: there is nothing to persist, so requiring a confirmation would assert a durability fact about no records.

NodeOptions

Bases: TypedDict

Tuning for one participant, at the level of the effect machine.

Timers here are counted in logical ticks, because that is how the engine counts them and Node does not own a clock. :class:paxodin.Session takes seconds instead and converts. Zero selects the default for everything.

SessionOptions

Bases: TypedDict

Tuning for a session, in seconds.

These are the same knobs as :class:NodeOptions with the engine's tick unit converted away: a developer reasons about how long failover takes, not how many ticks it is.

Profile dataclass

The capacities the loaded native library was compiled with.

The Odin core is fully parametric, but a shared library fixes its capacities at compile time because values are stored inline in the ledger. A profile therefore describes this build, not a limit of the algorithm.

Attributes:

Name Type Description
max_members int

Largest voting membership this build accepts.

window_slots int

Size of the sliding decree window. Always a power of two.

chunk_slots int

Recovery chunk size, and the largest proposal batch.

max_value_bytes int

Largest command payload this build accepts.

max_metadata_bytes int

Largest reconfiguration metadata blob.

gate_enforced bool

True for the test-only library that compiles the core's own durability gate in, where a violation ends the process.

node_bytes int

Measured static footprint of one node.

effects_bytes int

Measured static footprint of one effects batch.

max_writes_per_batch int

Most durable records one transition can produce.

max_messages_per_batch int

Most envelopes one transition can produce.

max_committed_per_batch int

Most entries one transition can release.

max_requests_per_batch int

Most host requests one transition can produce.

capabilities int

Bitmask of optional features this build supports.

fingerprint int

Identifies this profile in journal headers and handshakes, so a mismatch is caught before a node reads foreign state.

StopSign dataclass

A sealing record that ends one configuration and names the next.

LogEntry dataclass

One decoded log entry.

Attributes:

Name Type Description
kind EntryKind

Which of the three things this entry is.

body bytes

The command payload. Empty for a no-op or a stop sign, and also legitimately empty for a command that carried no bytes -- read kind to tell them apart.

stop_sign StopSign | None

The sealing record when kind is STOP_SIGN.

is_command property

is_command: bool

True when this entry is application data the caller submitted.

Committed dataclass

One entry released to the application, contiguous with everything before.

Release is not application: receiving this means the participant knows the decision in order, not that the application has acted on it.

WriteRecord dataclass

One durable record the host must append, in order, before sending.

Attributes:

Name Type Description
requires_barrier bool

True for a promise or a vote -- the indelible ink whose loss lets a crash choose twice. A decision or trim record is derived state a host may persist behind a cheaper barrier.

PrepareScope

Bases: IntEnum

What a prepare asks an acceptor to promise.

GLOBAL class-attribute instance-attribute

GLOBAL = 0

Every decree from first on: the Multi-Paxos takeover.

BOUNDED class-attribute instance-attribute

BOUNDED = 1

Only the decrees in [first, last]: a revocation under ownership.

Prepare dataclass

Phase one: promise ballot for the decrees in scope and report votes.

Promise dataclass

One reported vote or decision for one decree, in answer to a prepare.

PromiseRange dataclass

The manifest that closes a phase-one answer for one chunk.

Accept dataclass

Phase two: vote for entry in slot under ballot.

Accepted dataclass

An acceptor's vote, with how far it has decided.

Commit dataclass

A decision. It carries no ballot because a chosen value is final.

Learn dataclass

A catch-up request for decided slots starting at from_slot.

Nack dataclass

A refusal: rejected lost to promised.

Heartbeat dataclass

A leader's liveness signal, with how far it has decided.

Envelope dataclass

One protocol message with its addressing and configuration stamp.

The stamp is what lets a receiver refuse traffic from another epoch instead of relabelling it. Everything else about the message lives in message, which is one of the nine classes above.

ServeRange dataclass

History a peer asked for that has fallen below this node's memory floor.

The core no longer holds it; the host serves it from retained history.

NodeState dataclass

A read-only view of one participant, gathered in a single call.

is_leader property

is_leader: bool

True when this participant is running phase two for its own slots.

Receipt dataclass

Where a submitted command ended up.

Attributes:

Name Type Description
configuration_id int

The configuration that holds the slot.

slot Slot

The position the command occupies.

entry LogEntry

What was actually decided there.

Note

A receipt reports agreement and release at this participant. It does not say every peer received the command, and it never says the application applied it.

value property

value: bytes

The decided payload.