# txn-db v0.5.0 — Garbage collection & feature freeze

**The engine is feature-complete.** v0.5.0 adds watermark-driven garbage
collection, makes the custom-store seam genuinely usable, and declares the
feature freeze. From here to 1.0 the work is hardening — optimization and
adversarial testing — not new surface.

## What is txn-db?

A multi-version concurrency control (MVCC) transaction engine: the layer that
turns a key-value store into a transactional database. Every write produces a new
version tagged with a commit timestamp, so readers get a stable snapshot without
ever blocking writers, and writers detect conflicts at commit time. The version
store is a trait, so the engine composes on top of any backend that can keep
timestamped versions.

## What's new in 0.5.0

### Garbage collection

Because every write keeps the previous version, versions accumulate.
`Db::collect_garbage` reclaims the ones no live transaction or snapshot can
observe and returns how many it removed.

```rust
use txn_db::Db;

let db = Db::new();
for v in 0..100u8 {
    let mut tx = db.begin();
    tx.put(b"k".to_vec(), vec![v]);
    tx.commit()?;
}

let reclaimed = db.collect_garbage();   // no reader held: keeps only the newest
assert!(reclaimed > 0);
assert_eq!(db.begin().get(b"k")?.as_deref(), Some(&[99u8][..]));
# Ok::<(), txn_db::TxnError>(())
```

Collection is driven by an **oldest-live-reader watermark**. Every transaction
and snapshot registers its read timestamp with the database for as long as the
handle is alive; the smallest registered timestamp is the oldest snapshot still
in use, and only versions older than what *that* snapshot can observe are
reclaimed. A held snapshot therefore pins the versions it can see — collection
never removes data a live reader still needs. The read timestamp is taken under
the registry lock, so a reader that is registering concurrently with a collection
can never be undercut.

### A backing-store seam you can actually use

`txn-db` is the transaction layer; the version store is pluggable. v0.5 makes
that seam real in two ways. `TxnError::conflict` is now public, so a custom
`VersionStore` can signal a write-write or read-set conflict from `try_commit`;
and `VersionStore::collect_garbage` is a provided method (default no-op) so a
store that keeps history can prune it without every store having to.

A new integration test backs the engine with a *complete, independent* store — a
single-locked `BTreeMap` of version chains that shares no code with the shipped
`MemoryStore` — and runs the full transaction semantics over it: snapshot
isolation, read-your-own-writes, write-write conflict detection, and serializable
read-set validation. The lsm-db-specific store remains a consumer concern (the
1.0 scope keeps the version store out of this crate), but the trait is proven
sufficient to build one.

### Feature freeze

With garbage collection in place the engine is feature-complete. The public
surface is frozen against new features; the remaining 0.x releases are
optimization (0.6) and hardening with the API formally frozen (0.7).

## Testing

- **Garbage-collection property test** — across arbitrary interleavings of
  writes, deletes, snapshot captures, and collections, every held snapshot keeps
  reading exactly what it saw. If collection ever reclaimed a version a snapshot
  needed, a read would change.
- **Backing-store integration test** — the full transaction semantics over an
  independent `VersionStore`.
- All prior suites continue to pass: snapshot-isolation and serializable
  property tests, crash-recovery tests, and the `loom` concurrent-commit checks.

## Breaking changes

**None.** `Db::collect_garbage`, `VersionStore::collect_garbage` (a provided
method), and the now-public `TxnError::conflict` are all additive. Existing code
is unchanged.

## Verification

Run on Windows x86_64 (Rust stable 1.95.x and MSRV 1.85) and on Linux (WSL2
Ubuntu); the configured CI matrix runs the same on Linux, macOS, and Windows:

```bash
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-features
cargo test                       # default features
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
cargo +1.85 clippy --all-targets --all-features -- -D warnings
cargo +1.85 test --all-features
RUSTFLAGS="--cfg loom" cargo test --test loom_txn --release
cargo build --examples --all-features
cargo deny check
cargo audit
```

All green. Counts at this tag (`--all-features`): 43 unit + 23 integration
(5 backing-store + 6 durability + 2 garbage-collection + 4 serializable property
+ 6 snapshot-isolation) + 33 doctests, plus 2 `loom` model checks.

## What's next

- **0.6.0 — Optimization.** Profile the commit path, conflict checks, and version
  lookup; tighten allocation and the reader-registry / watermark bookkeeping;
  document contention-scaling benchmarks (1/4/16/64 concurrent writers).
- **0.7.0 — Hardening + API freeze.** Adversarial schedules, edge cases,
  cross-platform re-verification; the API formally frozen.

## Installation

```toml
[dependencies]
txn-db = "0.5"

# Opt into serializable isolation and/or a durable commit log:
txn-db = { version = "0.5", features = ["serializable", "durability"] }
```

MSRV: Rust 1.85 (the 2024 edition).

## Documentation

- [README](https://github.com/jamesgober/txn-db/blob/main/README.md)
- [API Reference](https://github.com/jamesgober/txn-db/blob/main/docs/API.md)
- [CHANGELOG](https://github.com/jamesgober/txn-db/blob/main/CHANGELOG.md)

---

**Full diff:** [`v0.4.0...v0.5.0`](https://github.com/jamesgober/txn-db/compare/v0.4.0...v0.5.0).
**Changelog:** [`CHANGELOG.md`](https://github.com/jamesgober/txn-db/blob/main/CHANGELOG.md#050---2026-06-07).
