Skip to main content

pagesift_store/
items.rs

1//! Explicit item identity for incremental collectors. Callers supply a stable
2//! source/item key and a version token (or empty bytes for identity-only mode).
3//! Commit AFTER successful delivery. This is not a lease or an atomic reservation:
4//! concurrent consumers still need coordination or an idempotent destination.
5use crate::engine::{group_key, ns};
6use crate::{Result, Store, to_ms};
7use std::time::SystemTime;
8
9pub struct Items<'a> {
10    store: &'a Store,
11}
12
13impl<'a> Items<'a> {
14    pub(crate) fn new(store: &'a Store) -> Self {
15        Self { store }
16    }
17
18    /// Whether this exact source/item revision was successfully committed.
19    /// URLs are deliberately not part of the key. No missing-page deletion is
20    /// inferred: absence from a listing is not proof an item was deleted.
21    pub fn matches(&self, source: &[u8], item: &[u8], revision: &[u8]) -> Result<bool> {
22        Ok(self
23            .store
24            .get(ns::ITEM, &group_key(source, item)?)?
25            .is_some_and(|(_, value)| value == revision))
26    }
27
28    /// Save completion in a single CRC-protected record. Durability follows the
29    /// Store's SyncPolicy; process termination and power loss are different risks.
30    pub fn commit(&self, source: &[u8], item: &[u8], revision: &[u8]) -> Result<()> {
31        self.store
32            .put(
33                ns::ITEM,
34                &group_key(source, item)?,
35                revision,
36                to_ms(SystemTime::now()),
37            )
38            .map(drop)
39    }
40
41    /// Explicitly forget a completed identity so it will be processed again.
42    pub fn forget(&self, source: &[u8], item: &[u8]) -> Result<bool> {
43        self.store.delete(ns::ITEM, &group_key(source, item)?)
44    }
45}