pub struct CacheManager { /* private fields */ }Expand description
SHA-256 content-hash deduplication cache backed by SessionStore,
with delta encoding for near-duplicate content and compaction awareness.
§Freshness model
A dedup ref is considered fresh (safe to serve instead of the full
content) when the cache entry’s accessed_at timestamp in SQLite is
within max_ref_age of now. When sqz is invoked from shell hooks each
invocation is a short-lived process, so the freshness check must be
persistent — in-memory state is gone the moment the process exits.
The previous turn-counter heuristic was in-memory only and therefore never registered freshness across hook invocations, which silently disabled the dedup feature in production. Issue found April 18 2026.
Default TTL: 30 minutes. Empirically matches a typical active coding
session before a context compaction. Use [with_ref_age] to tune.
Implementations§
Source§impl CacheManager
impl CacheManager
Sourcepub fn new(store: SessionStore, max_size_bytes: u64) -> Self
pub fn new(store: SessionStore, max_size_bytes: u64) -> Self
Create a new cache manager backed by the given session store.
max_size_bytes controls when LRU eviction kicks in. A good default
is 512 MB (512 * 1024 * 1024). Dedup refs go stale after 30 minutes
of wall-clock time by default — use [with_ref_age] to tune.
Sourcepub fn with_ref_age_duration(
store: SessionStore,
max_size_bytes: u64,
max_ref_age: Duration,
) -> Self
pub fn with_ref_age_duration( store: SessionStore, max_size_bytes: u64, max_ref_age: Duration, ) -> Self
Create a CacheManager with an explicit wall-clock ref-age cap.
Sourcepub fn advance_turn(&self)
pub fn advance_turn(&self)
Advance the turn counter. Retained for API compatibility; not used
for freshness. The context_evictor still reads current_turn for
LRU scoring during sqz compact.
Sourcepub fn current_turn(&self) -> u64
pub fn current_turn(&self) -> u64
Get the current turn number. Used by the context_evictor for scoring.
Sourcepub fn notify_compaction(&self)
pub fn notify_compaction(&self)
Notify the cache that a context compaction has occurred.
Persists a compaction timestamp into the session store so any cache
entry whose accessed_at predates the marker is considered stale
by every subsequent sqz process, not just this one. The shell-
hook invocation model means this method is typically called from a
short-lived sqz hook precompact process, and the check runs in a
different sqz compress process milliseconds later.
Call this when:
- The harness signals a compaction event (PreCompact hook)
- A session is resumed after being idle
- The user runs
sqz compact
Sourcepub fn get_or_compress(
&self,
_path: &Path,
content: &[u8],
pipeline: &CompressionPipeline,
) -> Result<CacheResult>
pub fn get_or_compress( &self, _path: &Path, content: &[u8], pipeline: &CompressionPipeline, ) -> Result<CacheResult>
Look up content in the cache with compaction awareness.
- On exact dedup with fresh ref: return
CacheResult::Dedup(~13 tokens). - On exact dedup with stale ref: re-compress and return
CacheResult::Fresh(the original content may have been compacted out of the LLM’s context). - On near-duplicate: return
CacheResult::Deltawith a compact diff. - On cache miss: compress via
pipeline, persist, returnCacheResult::Fresh.
Sourcepub fn check_dedup(&self, content: &[u8]) -> Result<Option<String>>
pub fn check_dedup(&self, content: &[u8]) -> Result<Option<String>>
Check if content is already in the persistent cache (dedup lookup only).
Returns Some(inline_ref) if cached AND the ref is still fresh,
None if the content is not cached or the ref is stale.
Unlike [get_or_compress], this method does not touch accessed_at
until after the freshness check — otherwise every read would make
itself “fresh.”
Sourcepub fn store_compressed(
&self,
original_content: &[u8],
compressed: &CompressedContent,
) -> Result<()>
pub fn store_compressed( &self, original_content: &[u8], compressed: &CompressedContent, ) -> Result<()>
Store a compressed result in the persistent cache, keyed by the SHA-256 hash of the original content.
Also records the ref as sent at the current turn for compaction tracking.
Persists original_content alongside compressed so that
sqz expand <prefix> can recover the raw bytes for agents that
cannot parse §ref:…§ dedup tokens.
Sourcepub fn expand_prefix(&self, prefix: &str) -> Result<Option<ExpandResult>>
pub fn expand_prefix(&self, prefix: &str) -> Result<Option<ExpandResult>>
Resolve a hex prefix (the 16-char tail of a §ref:<prefix>§ token,
or any longer hex string pasted by a user) to the cached content.
Designed for the sqz expand <prefix> CLI: the agent sees a ref
token it can’t parse, runs sqz expand a1b2c3d4e5f6g7h8, and gets
back the raw bytes that produced the ref. This is the
user-visible escape hatch SquireNed asked for.
Three outcomes:
Ok(Some(Original))— the original bytes were captured when the entry was stored (new cache entries from v0.10.0+ always capture the original). Writebytesto stdout.Ok(Some(CompressedOnly))— the entry exists but itsoriginalcolumn isNULL(pre-migration data). We still return the compressed form — always legible, always useful — and the CLI surfaces a note that tells the user to re-run their original command with--no-cacheto capture a truly uncompressed copy.Ok(None)— no entry matches. Usually means the ref was truncated from a different sqz database (a different machine, a wiped~/.sqz/sessions.db, etc.).Err(_)— prefix was ambiguous or the DB is broken. The error carries a user-readable message explaining what went wrong.
Touches accessed_at on hit (consistent with get_cache_entry).
Sourcepub fn invalidate(&self, path: &Path) -> Result<()>
pub fn invalidate(&self, path: &Path) -> Result<()>
Invalidate the cache entry for path if its current content is known.
Reads the file at path, computes its hash, and removes the matching
entry from the store. If the file does not exist the call is a no-op.