moontracekit

Logical clocks, vector clocks, happens-before analysis, and causal buffers for MoonBit.

causality
vector-clock
lamport-clock
distributed
happens-before
moon add SCL-NN/moontracekit@0.2.0
Download zip
Author
Version
0.2.0
License
Apache-2.0
Last updated
29 days ago
Downloads
3
README

#MoonTraceKit

MoonTraceKit is a MoonBit foundation library for causal reasoning in distributed systems.

It provides Lamport clocks, vector clocks, happens-before comparison, concurrent event detection, causal frontier calculation, and a causal delivery buffer for out-of-order messages.

#Highlights

  • LamportClock: local tick, remote observation, and event creation.
  • VectorClock: set, tick, merge, compare, happens-before, concurrency.
  • CausalEvent: event id, origin node, payload, and vector clock.
  • CausalBuffer: hold messages until their dependencies are delivered.
  • Bounded CausalBuffer: capacity control and explicit dropped-event metrics.
  • Analysis helpers: concurrent-pair discovery and frontier calculation.
  • JSON export: stable summaries for demos, logs, and tests.
  • Backend-neutral: no networking, database, browser, or IO dependency.

#Example

let events = sample_out_of_order_events()
let buffer = CausalBuffer::new().push(events[0]).push(events[1]).flush_ready()
println(buffer.to_json())

MoonTraceKit is not a CRDT implementation and not a message queue. It provides the reusable causality semantics that those higher-level systems can compose.

#Install

moon add SCL-NN/moontracekit

For the full project overview, scenarios, boundaries, and run commands, see README.md.

#
CausalBuffer

pub(all) struct CausalBuffer {
delivered : VectorClock
pending : Array[CausalEvent]
max_pending : Int
dropped : Int
}

#
CausalBuffer::deliver

fn CausalBuffer::deliver(self : CausalBuffer, event : CausalEvent) -> CausalBuffer

#
CausalBuffer::dropped_count

fn CausalBuffer::dropped_count(self : CausalBuffer) -> Int

#
CausalBuffer::flush_ready

fn CausalBuffer::flush_ready(self : CausalBuffer) -> CausalBuffer

#
CausalBuffer::new

#
CausalBuffer::pending_count

fn CausalBuffer::pending_count(self : CausalBuffer) -> Int

#
CausalBuffer::push

fn CausalBuffer::push(self : CausalBuffer, event : CausalEvent) -> CausalBuffer

#
CausalBuffer::ready

fn CausalBuffer::ready(self : CausalBuffer, event : CausalEvent) -> Bool

#
CausalBuffer::to_json

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

#
CausalBuffer::with_capacity

fn CausalBuffer::with_capacity(max_pending : Int) -> CausalBuffer

Creates a bounded buffer. When full, a newly pending event is rejected and dropped_count records the overflow; callers can use it for backpressure.

#
CausalBuffer::with_delivered

fn CausalBuffer::with_delivered(delivered : VectorClock) -> CausalBuffer

#
CausalEvent

pub(all) struct CausalEvent {
id : String
origin : String
clock : VectorClock
payload : String
}

#
CausalEvent::new

fn CausalEvent::new(id : String, origin : String, clock : VectorClock, payload : String) -> CausalEvent

#
CausalEvent::to_json

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

#
CausalOrder

pub(all) enum CausalOrder {
Equal
Before
After
Concurrent
} derive(Eq,
Debug
)

#
CausalOrder::name

fn CausalOrder::name(self : CausalOrder) -> String

#
CausalPair

pub(all) struct CausalPair {
left : String
right : String
order : CausalOrder
}

#
CausalPair::new

fn CausalPair::new(left : String, right : String, order : CausalOrder) -> CausalPair

#
CausalPair::to_json

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

#
ClockEntry

pub(all) struct ClockEntry {
node : String
counter : Int
}

#
ClockEntry::new

fn ClockEntry::new(node : String, counter : Int) -> ClockEntry

#
ClockEntry::to_json

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

#
LamportClock

pub(all) struct LamportClock {
node : String
counter : Int
}

#
LamportClock::event

fn LamportClock::event(self : LamportClock, id : String, payload : String) -> CausalEvent

#
LamportClock::new

fn LamportClock::new(node : String) -> LamportClock

#
LamportClock::observe

fn LamportClock::observe(self : LamportClock, remote_counter : Int) -> LamportClock

#
LamportClock::tick

#
VectorClock

pub(all) struct VectorClock {
entries : Array[ClockEntry]
}

#
VectorClock::compare

fn VectorClock::compare(self : VectorClock, other : VectorClock) -> CausalOrder

#
VectorClock::concurrent_with

fn VectorClock::concurrent_with(self : VectorClock, other : VectorClock) -> Bool

#
VectorClock::from_entries

fn VectorClock::from_entries(entries : Array[ClockEntry]) -> VectorClock

#
VectorClock::get

fn VectorClock::get(self : VectorClock, node : String) -> Int

#
VectorClock::happens_before

fn VectorClock::happens_before(self : VectorClock, other : VectorClock) -> Bool

#
VectorClock::merge

fn VectorClock::merge(self : VectorClock, other : VectorClock) -> VectorClock

#
VectorClock::new

#
VectorClock::set

fn VectorClock::set(self : VectorClock, node : String, counter : Int) -> VectorClock

#
VectorClock::tick

fn VectorClock::tick(self : VectorClock, node : String) -> VectorClock

#
VectorClock::to_json

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

#
causal_frontier

fn causal_frontier(events : Array[CausalEvent]) -> VectorClock

#
compare_events

fn compare_events(left : CausalEvent, right : CausalEvent) -> CausalPair

#
find_concurrent_pairs

fn find_concurrent_pairs(events : Array[CausalEvent]) -> Array[CausalPair]

#
sample_concurrent_events

fn sample_concurrent_events() -> Array[CausalEvent]

#
sample_linear_events

fn sample_linear_events() -> Array[CausalEvent]

#
sample_out_of_order_events

fn sample_out_of_order_events() -> Array[CausalEvent]

Powered by MoonBit

Site sourceReport issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io