Require an atomic push_all from every Rust backing store

The default CacheBackingStore::push_all deleted every row and then pushed
one by one, so a failing push left the store emptied or partial while
put_prepared_batch claimed all-or-nothing. The default is deleted:
push_all is a required method documented as one atomic replace, and a
compile_fail doctest pins that a store without it does not compile.
Every in-tree implementor (single-file, both redb stores, the test store,
Epiphany's runtime store) already supplies its own.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-09-14 12:28:07 +02:00
commit 9c3c92634a

View file

@ -309,16 +309,31 @@ pub trait CacheBackingStore: Send {
fn push(&mut self, entry: &CultCacheEnvelope) -> Result<()>;
fn delete(&mut self, entry: &CultCacheEnvelope) -> Result<()>;
fn push_all(&mut self, entries: &[CultCacheEnvelope], _options: PushAllOptions) -> Result<()> {
let existing = self.pull_all()?;
for entry in existing {
self.delete(&entry)?;
}
for entry in entries {
self.push(entry)?;
}
Ok(())
}
/// Replaces everything the store holds with `entries` in one atomic step:
/// on `Err` the store still holds exactly what it held before. A cache
/// batch (`put_prepared_batch`) is all-or-nothing only through this. There
/// is no default, because a replace assembled from `delete` and `push`
/// calls leaves the store emptied or partial when one of them fails; a
/// store without an atomic replace does not compile:
///
/// ```compile_fail,E0046
/// use cultcache_rs::{CacheBackingStore, CultCacheEnvelope};
///
/// struct PerRecordStore;
///
/// impl CacheBackingStore for PerRecordStore {
/// fn pull_all(&self) -> anyhow::Result<Vec<CultCacheEnvelope>> {
/// Ok(Vec::new())
/// }
/// fn push(&mut self, _entry: &CultCacheEnvelope) -> anyhow::Result<()> {
/// Ok(())
/// }
/// fn delete(&mut self, _entry: &CultCacheEnvelope) -> anyhow::Result<()> {
/// Ok(())
/// }
/// }
/// ```
fn push_all(&mut self, entries: &[CultCacheEnvelope], options: PushAllOptions) -> Result<()>;
}
#[derive(Clone, Debug, PartialEq, Eq)]