moonleasekit

Deterministic leases, fencing tokens and leader election primitives for MoonBit.

lease
fencing-token
leader-election
distributed-systems
deterministic
moon add dxh8888/moonleasekit@0.1.0
Download zip
Author
Version
0.1.0
License
Apache-2.0
Last updated
last month
Downloads
12
README

#MoonLeaseKit

Deterministic leases, fencing tokens, and leader-election primitives for MoonBit.

MoonLeaseKit models distributed ownership as pure state transitions. Callers supply logical time explicitly, so the core does not depend on wall clocks, threads, networking, databases, or service discovery.

#Features

  • Acquire, renew, release, transfer, and reap leases
  • Monotonic fencing tokens and revision preconditions
  • Storage-side stale-writer rejection
  • Multi-resource tables, batches, metrics, and audit events
  • Deterministic candidate selection and quorum certificates
  • Duplicate-vote handling and equivocation detection
  • Validation for state restored from external storage
  • Stable JSON and reproducible failover simulation

#Install

moon add dxh8888/moonleasekit

#Example

let acquired = @moonleasekit.LeaseState::new("jobs/leader").apply(
Acquire("worker-a", 10, None),
100,
)

guard acquired.lease is Some(lease) else { return }

let write = lease.fenced_write("commit-job-42", 101).unwrap()
let checked = @moonleasekit.FenceGuard::new().check(write)
assert_true(checked.accepted)

When a later lease receives token 2, a delayed write carrying token 1 is rejected by FenceGuard.

#Verify

moon check --target all moon test --target wasm moon test --target wasm-gc moon test --target js moon run cmd/main --target js moon run bench/main --target js

The benchmark performs 50,000 deterministic failovers and verifies that every old writer after the first takeover is rejected.

#Scope

This library provides embeddable coordination primitives. It intentionally does not implement transport, storage drivers, failure detection, or a full consensus protocol.

Apache-2.0 licensed.

#
AuditFinding

pub(all) struct AuditFinding {
code : String
resource : String
event_index : Int
message : String
} derive(Eq,
Debug
)

One invariant violation found in an event trace.

#
AuditReport

pub(all) struct AuditReport {
valid : Bool
checked_events : Int
findings : Array[AuditFinding]
} derive(Eq,
Debug
)

Deterministic safety audit result.

#
AuditReport::to_json

fn AuditReport::to_json(self : AuditReport) -> String

Encodes a safety audit as stable JSON.

#
BatchResult

pub(all) struct BatchResult {
table : LeaseTable
decisions : Array[LeaseDecision]
accepted : Int
rejected : Int
} derive(Eq,
Debug
)

Summary for a deterministic command batch.

#
Candidate

pub(all) struct Candidate {
id : String
priority : Int
} derive(Eq,
Debug
)

Candidate used by deterministic local election policy.

#
DecisionKind

pub(all) enum DecisionKind {
Acquired
Renewed
Released
Transferred
Reaped
Rejected
} derive(Eq,
Debug
)

Administrative outcome of a lease command.

#
ElectionVote

pub(all) struct ElectionVote {
voter : String
candidate : String
term : Int
granted : Bool
} derive(Eq,
Debug
)

One cluster member's vote for a term.

#
FenceDecision

pub(all) struct FenceDecision {
next_guard : FenceGuard
accepted : Bool
highest_token : Int
message : String
} derive(Eq,
Debug
)

Result of validating a fenced write.

#
FenceGuard

pub(all) struct FenceGuard {
marks : Array[FenceMark]
} derive(Eq,
Debug
)

Storage-independent fencing state.

#
FenceGuard::check

fn FenceGuard::check(self : FenceGuard, write : FencedWrite) -> FenceDecision

Validates a storage operation against the highest observed fencing token.

#
FenceGuard::highest_token

fn FenceGuard::highest_token(self : FenceGuard, resource : String) -> Int

Returns the highest accepted token for a resource, or zero if unseen.

#
FenceGuard::new

fn FenceGuard::new() -> FenceGuard

Creates an empty storage-side fencing guard.

#
FenceMark

pub(all) struct FenceMark {
resource : String
token : Int
holder : String
} derive(Eq,
Debug
)

Highest fencing token observed for one resource.

#
FencedWrite

pub(all) struct FencedWrite {
resource : String
holder : String
token : Int
operation : String
} derive(Eq,
Debug
)

A write request protected by a lease fencing token.

#
Lease

pub(all) struct Lease {
resource : String
holder : String
token : Int
revision : Int
issued_at : Int
expires_at : Int
} derive(Eq,
Debug
)

A granted lease. token is a monotonically increasing fencing token.

#
Lease::fenced_write

fn Lease::fenced_write(self : Lease, operation : String, now : Int) -> FencedWrite?

Builds a write request directly from an active lease.

#
Lease::is_active

fn Lease::is_active(self : Lease, now : Int) -> Bool

Returns whether this lease is valid at the supplied logical time.

#
Lease::remaining

fn Lease::remaining(self : Lease, now : Int) -> Int

Remaining logical ticks, clamped to zero.

#
Lease::to_json

fn Lease::to_json(self : Lease) -> String

Encodes a lease as stable JSON.

#
LeaseCommand

pub(all) enum LeaseCommand {
Acquire(String, Int, Int?)
Renew(String, Int, Int)
Release(String, Int)
Transfer(String, Int, String, Int)
Reap
} derive(Eq,
Debug
)

Commands accepted by the pure lease state machine.

#
LeaseDecision

pub(all) struct LeaseDecision {
state : LeaseState
accepted : Bool
kind : DecisionKind
lease : Lease?
event : LeaseEvent?
message : String
} derive(Eq,
Debug
)

Result returned for every command, including rejected commands.

#
LeaseEvent

pub(all) struct LeaseEvent {
resource : String
kind : DecisionKind
at : Int
holder : String
token : Int
revision : Int
detail : String
} derive(Eq,
Debug
)

An auditable state transition record.

#
LeaseEvent::to_json

fn LeaseEvent::to_json(self : LeaseEvent) -> String

Encodes an audit event as stable JSON.

#
LeaseMetrics

pub(all) struct LeaseMetrics {
resources : Int
stored_leases : Int
active_leases : Int
expired_leases : Int
highest_token : Int
events : Int
accepted_commands : Int
rejected_commands : Int
} derive(Eq,
Debug
)

Point-in-time table metrics.

#
LeaseMetrics::to_json

fn LeaseMetrics::to_json(self : LeaseMetrics) -> String

Encodes metrics as stable JSON.

#
LeaseState

pub(all) struct LeaseState {
resource : String
lease : Lease?
next_token : Int
revision : Int
} derive(Eq,
Debug
)

Complete deterministic state for one leased resource.

#
LeaseState::active_lease

fn LeaseState::active_lease(self : LeaseState, now : Int) -> Lease?

Returns the active lease, treating expired or not-yet-issued records as absent.

#
LeaseState::apply

fn LeaseState::apply(self : LeaseState, command : LeaseCommand, now : Int) -> LeaseDecision

Applies one command at an explicit logical time.

#
LeaseState::new

fn LeaseState::new(resource : String) -> LeaseState

Creates an empty resource state. Token zero is never issued.

#
LeaseTable

pub(all) struct LeaseTable {
states : Array[LeaseState]
events : Array[LeaseEvent]
accepted_commands : Int
rejected_commands : Int
} derive(Eq,
Debug
)

Multi-resource lease coordinator state.

#
LeaseTable::acquire_leadership

fn LeaseTable::acquire_leadership(self : LeaseTable, resource : String, certificate : QuorumCertificate, ttl : Int, now : Int) -> TableDecision

Acquires a leadership lease only when a quorum certificate is valid.

#
LeaseTable::active_leases

fn LeaseTable::active_leases(self : LeaseTable, now : Int) -> Array[Lease]

Returns all leases active at an explicit logical time.

#
LeaseTable::apply

fn LeaseTable::apply(self : LeaseTable, resource : String, command : LeaseCommand, now : Int) -> TableDecision

Applies one resource command and records accepted transitions.

#
LeaseTable::apply_batch

fn LeaseTable::apply_batch(self : LeaseTable, commands : Array[TimedCommand]) -> BatchResult

Applies commands in input order and preserves every decision.

#
LeaseTable::get

fn LeaseTable::get(self : LeaseTable, resource : String) -> LeaseState?

Returns the state for a resource.

#
LeaseTable::metrics

fn LeaseTable::metrics(self : LeaseTable, now : Int) -> LeaseMetrics

Computes point-in-time table metrics.

#
LeaseTable::new

fn LeaseTable::new() -> LeaseTable

Creates an empty multi-resource lease table.

#
LeaseTable::reap_expired

fn LeaseTable::reap_expired(self : LeaseTable, now : Int) -> BatchResult

Reaps every expired stored lease in deterministic table order.

#
QuorumCertificate

pub(all) struct QuorumCertificate {
valid : Bool
leader : String
term : Int
quorum : Int
voters : Array[String]
equivocations : Array[String]
message : String
} derive(Eq,
Debug
)

Evidence that one candidate reached quorum in a term.

#
SimulationReport

pub(all) struct SimulationReport {
cycles : Int
leases_acquired : Int
writes_accepted : Int
stale_writes_rejected : Int
final_token : Int
audit_valid : Bool
evidence : Int
} derive(Eq,
Debug
)

Reproducible failover simulation evidence.

#
SimulationReport::to_json

fn SimulationReport::to_json(self : SimulationReport) -> String

Encodes reproducible simulation evidence as stable JSON.

#
StateIssue

pub(all) struct StateIssue {
code : String
message : String
} derive(Eq,
Debug
)

Validation issue for state restored from external storage.

#
TableDecision

pub(all) struct TableDecision {
table : LeaseTable
decision : LeaseDecision
} derive(Eq,
Debug
)

Result of applying a command to a resource table.

#
TimedCommand

pub(all) struct TimedCommand {
resource : String
command : LeaseCommand
at : Int
} derive(Eq,
Debug
)

A command with its resource and deterministic logical timestamp.

#
audit_events

fn audit_events(events : Array[LeaseEvent]) -> AuditReport

Checks monotonic token, revision, and logical-time invariants.

#
certify_votes

fn certify_votes(votes : Array[ElectionVote], cluster_size : Int, term : Int) -> QuorumCertificate

Validates a term's votes and returns deterministic quorum evidence.

#
decision_kind_name

fn decision_kind_name(kind : DecisionKind) -> String

Stable snake-case name for a decision kind.

#
json_escape

fn json_escape(value : String) -> String

Escapes a string for JSON output.

#
quorum_size

fn quorum_size(cluster_size : Int) -> Int

Returns the strict majority required by a cluster size.

#
run_failover_simulation

fn run_failover_simulation(cycles : Int, ttl? : Int) -> SimulationReport

Runs repeated expiry, takeover, and stale-writer scenarios.

#
select_candidate

fn select_candidate(candidates : Array[Candidate]) -> Candidate?

Selects highest priority and resolves ties by lexicographically smaller id.

#
state_is_valid

fn state_is_valid(state : LeaseState) -> Bool

Returns whether restored state is safe to apply.

#
validate_state

fn validate_state(state : LeaseState) -> Array[StateIssue]

Validates invariants before using state loaded from external storage.

Powered by MoonBit

Site sourceReport issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io