moontracekit

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

    causality
    vector-clock
    lamport-clock
    distributed
    happens-before
    Download zip
    Author
    Version
    0.2.0
    License
    Apache-2.0
    Last updated
    3 months ago
    Downloads
    34

    No dependencies

    #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]