Skip to content

JusSchw/atomic-log

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

atomic-log

atomic-log is a Rust library for sharing a recent rolling window of values from one writer to many readers with very little coordination.

It is built for in-process streaming workloads where readers care more about a stable, recent view than about guaranteed delivery of every historical update. The log is append-only, segmented, zero-copy on the read side, and uses atomics for publication.

At a glance

  • Single writer, many readers
  • Low-coordination publication and atomics-only observation on the read path
  • No reader registration
  • Generic over T
  • Fixed-size segmented storage
  • Zero-copy snapshots backed by stable segment allocations
  • Automatic reclamation of old segments
  • Reclaimable write access after a writer is dropped
  • Flat iteration and per-segment chunk iteration

When to use it

atomic-log is a good fit when:

  • one thread publishes and many threads observe
  • readers mainly care about the latest retained state
  • stale history may be dropped
  • readers should not block the writer
  • zero-copy reads are valuable
  • bounded retention matters more than full replay

Typical examples:

  • market data
  • telemetry
  • service health and status propagation
  • real-time monitoring
  • replicated in-memory state views

When not to use it

Do not use atomic-log when:

  • every message must be delivered
  • readers must never miss an update
  • commands or events must be processed exactly once
  • multiple writers need to append concurrently without external synchronization
  • data must survive restarts

For those cases, a channel, queue, or durable log is usually the right tool.

Model

The writer appends values into a fixed-capacity head segment. When that segment fills, a new head segment is allocated and published. Readers build Snapshot<T> values from the current head and iterate over immutable published prefixes of the retained segments. The log owns the retained segment chain; a Writer<T> is an exclusive append capability that can be dropped and later reacquired from the log.

Snapshots are stable:

  • readers only observe fully published values
  • published values are never mutated again
  • holding a snapshot keeps its backing segments alive
  • readers access &T directly from segment storage without copying
  • dropping a writer does not discard retained history

Refreshing a snapshot replaces it with a newer captured view. If a reader falls behind beyond the retained history, continuity across refreshes may be lost.

Retention semantics

The constructor takes:

  • retained_capacity: target logical retention in elements
  • segment_capacity: fixed elements per segment

The current implementation retains whole segments, not exact element counts, so the visible live window is rounded to segment boundaries and may exceed retained_capacity. That tradeoff keeps publication and reclamation simple while preserving stable zero-copy snapshots.

Example

use atomic_log::AtomicLog;

let (mut writer, log) = AtomicLog::new_claimed(8, 4);

for value in 0..6 {
    writer.append(value);
}

let mut snapshot = log.snapshot();
assert_eq!(
    snapshot.iter().copied().collect::<Vec<_>>(),
    vec![0, 1, 2, 3, 4, 5]
);

writer.append(6);
writer.append(7);
snapshot.refresh();

assert_eq!(
    snapshot.iter().copied().collect::<Vec<_>>(),
    vec![0, 1, 2, 3, 4, 5, 6, 7]
);

let chunks: Vec<_> = snapshot
    .chunks()
    .map(|chunk| (chunk.sequence(), chunk.values().len()))
    .collect();

assert_eq!(chunks, vec![(0, 4), (1, 4)]);

API summary

  • AtomicLog::new(retained_capacity, segment_capacity) creates an unclaimed log
  • AtomicLog::new_claimed(retained_capacity, segment_capacity) creates a writer and read handle
  • AtomicLog::try_claim_writer() recreates a writer if no writer currently exists
  • Writer::append(value) publishes one value
  • AtomicLog::snapshot() captures a stable read view
  • Snapshot::refresh() updates an existing snapshot in place
  • Snapshot::iter() yields &T
  • Snapshot::chunks() yields per-segment slices plus sequence numbers

License

Licensed under either of:

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

No description, website, or topics provided.

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages