# iqdb-cache v0.5.0 — Concurrency Model Checks + API Freeze
**The surface settles.** v0.4.0 completed the feature set; v0.5.0 proves the shared cache is correct under concurrency and **freezes the public API**. The `Mutex`-guarded result cache is now verified with `loom` across every interleaving of two threads, `cargo audit` and `cargo deny` are clean, and the surface is committed for the 1.x series — no breaking changes until 2.0.
## What is iqdb-cache?
An in-process caching layer between the database and an index. It wraps any `iqdb_index::IndexCore` as a `CachedIndex` — itself an `IndexCore` — and memoizes search results, turning a repeated query into a memory read. It is opt-in and transparent: a database is correct with no cache, and wrapping one never changes what a search returns.
## What's new in 0.5.0
### Loom model checks for the shared cache
`CachedIndex::search` takes `&self` and guards the cache behind a `Mutex`, releasing it across the wrapped search so concurrent misses run in parallel. That interleaving is exactly where a subtle bug would hide, so it is now model-checked: under `--cfg loom` the cache `Mutex` and the hit/miss/eviction counters become loom's instrumented types (via a small `src/sync.rs` shim), and `tests/loom_iqdb_cache.rs` explores **every** schedule of two threads searching one cache.
The checks pin the contract:
- Concurrent searches of the same query always return the one stored result — never corrupt, never empty — whatever the interleaving.
- Lookups are accounted for exactly: `hits + misses` equals the number of searches, and the cache settles on the right number of distinct entries.
- No deadlock and no lost update across any schedule.
Normal builds are untouched: without `--cfg loom` the cache is the plain `std::sync::Mutex` with zero overhead, and `loom` is pulled only when model-checking.
### API freeze
The public surface is now **committed for the 1.x series** — only additive, non-breaking changes until 2.0. The frozen surface (recorded in `dev/ROADMAP.md`) is:
- `VERSION`
- `CachedIndex<I>`: `new`, `with_capacity`, `with_config`, `capacity`, `ttl`, `policy`, `is_enabled`, `get_ref`, `into_inner`, `clear_cache`, `cache_stats`, and `impl IndexCore`
- `CacheConfig`: `new`, `capacity`, `ttl`, `no_ttl`, `policy`, `Default`
- `EvictionPolicy`: `Lru` (default), `Lfu`, `Fifo`, `Arc` (`#[non_exhaustive]`)
- `CacheStats`: fields `hits`, `misses`, `evictions`, `len`, `capacity`; methods `lookups`, `hit_rate`
The `#[doc(hidden)]` `doc_stub` module is documentation scaffolding and explicitly **not** part of the stable API.
### Supply-chain checks green
`cargo audit` reports no advisories against the dependency tree, and `cargo deny check` passes advisories, bans, licenses, and sources. Both run in CI on every push.
## Breaking changes
**None.** Every change is internal or additive. The only mechanical change is that mutation invalidation now clears through the cache lock instead of `Mutex::get_mut`, so the identical path is exercised under loom — behaviour is unchanged.
## Verification
The loom suite runs under `RUSTFLAGS="--cfg loom" cargo test --test loom_iqdb_cache`; the standard suite (transparency, no-stale-after-mutation, per-policy bounds and transparency, TTL, concurrency smoke) and the benchmarks are unchanged from 0.4. The full gate runs across the CI matrix (Linux, macOS, Windows) on stable and the 1.87 MSRV, plus the dedicated loom and security jobs:
```bash
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-features
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
RUSTFLAGS="--cfg loom" cargo test --test loom_iqdb_cache
cargo audit
cargo deny check
```
MSRV: Rust 1.87.
## What's next
- **v0.6.0 → 0.9.x — alpha / beta / rc.** Integration against real consumers (the `iqdb` database builder), broader testing, final benchmarks, and doc polish, with only MINOR-compatible additions — leading to the stable **1.0.0**.
## Installation
```toml
[dependencies]
iqdb-cache = "0.5"
```
## Documentation
- [README](https://github.com/jamesgober/iqdb-cache/blob/main/README.md)
- [API reference](https://github.com/jamesgober/iqdb-cache/blob/main/docs/API.md)
- [ROADMAP](https://github.com/jamesgober/iqdb-cache/blob/main/dev/ROADMAP.md)
- [Standards (REPS)](https://github.com/jamesgober/iqdb-cache/blob/main/REPS.md)
- [CHANGELOG](https://github.com/jamesgober/iqdb-cache/blob/main/CHANGELOG.md)
---
**Full diff:** [`v0.4.0...v0.5.0`](https://github.com/jamesgober/iqdb-cache/compare/v0.4.0...v0.5.0).
**Changelog:** [`CHANGELOG.md`](https://github.com/jamesgober/iqdb-cache/blob/main/CHANGELOG.md).