segment-buffer 0.5.1

High-throughput local buffer for cloud sync: batch-spills to zstd+CBOR segment files with at-least-once delivery, ack-based deletion, filename-based crash recovery, configurable durability, and optional encryption. Single-process by design. No WAL, no metadata DB.
Documentation
//! Basic segment-buffer usage: append items, flush, read back, delete acked.

use segment_buffer::{SegmentBuffer, SegmentConfig};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
struct Task {
    id: u64,
    title: String,
}

fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
    let tmp = tempfile::tempdir()?;

    let config = SegmentConfig::builder()
        .flush_at_batch_or_interval(256, std::time::Duration::from_secs(5))
        .max_size_bytes(1024 * 1024)
        .compression_level(3)
        .build();

    let buffer = SegmentBuffer::<Task>::open(tmp.path(), config)?;

    // Append some tasks
    for i in 0..10 {
        buffer.append(Task {
            id: i,
            title: format!("Task {i}"),
        })?;
    }

    // Explicit flush (otherwise auto-flushes at batch threshold or interval)
    buffer.flush()?;

    println!("Pending: {}", buffer.pending_count());
    println!("Latest sequence: {}", buffer.latest_sequence());

    // Read all tasks back
    let tasks = buffer.read_from(0, 100)?;
    println!("Recovered {} tasks", tasks.len());
    assert_eq!(tasks.len(), 10);
    assert_eq!(
        tasks[0],
        Task {
            id: 0,
            title: "Task 0".into()
        }
    );

    // Acknowledge all tasks — the segment is deleted when end_seq <= acked_seq
    let deleted = buffer.delete_acked(9)?;
    println!("Deleted {deleted} segment(s)");
    println!("Pending after ack: {}", buffer.pending_count());

    Ok(())
}