Skip to content

Derive catalog cache keys from the filter (#207) - #212

Closed
deverman wants to merge 1 commit into
masterfrom
issue-207-cache-key-derivation
Closed

Derive catalog cache keys from the filter (#207)#212
deverman wants to merge 1 commit into
masterfrom
issue-207-cache-key-derivation

Conversation

@deverman

@deverman deverman commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Closes #207.

The problem

CacheKey listed its fields by hand and stayed correct only because a separate shouldBypassCache expression happened to name every field the key omitted. Nothing connected the two — they agreed by inspection, not construction.

The gap was already widening:

The change

The key is now a fingerprint of the filter's own sorted-key encoding, so any new filter field changes the identity automatically. Page limit, cursor, and requested fields stay explicit, because they are not part of the filter.

Cacheability is decided from that same encoding. "Do not cache" stays an explicit field-name list — it is a judgement about semantics (time-relative review and completion windows, live batch resolution), not something derivable — but it is now checked against the encoded filter rather than duplicated as a boolean expression that can drift from it.

Fixed while here: the tags path consulted the cache conditionally but wrote to it unconditionally, so an uncacheable tag result would still have been stored.

Tests

Existing key-separation tests are preserved and migrated rather than replaced — they pin real behaviour and all still pass. Added:

One honest note on the acceptance criteria: the issue asked for a test that fails when a filter gains a field the derivation cannot see. That test cannot be written directly, because derivation sees every field by construction — which is the point. The invariant is covered instead by asserting that representative field changes each alter the fingerprint.

Validation

Impact: query. 345 tests pass; all semantic gates pass. Verified live that a rootOnly query and an unscoped query return different result sets (73 vs 150 items) with no cross-contamination.

CacheKey listed its fields by hand and stayed correct only because a
separate shouldBypassCache list happened to name every field the key
omitted. Nothing connected the two.

The gap was already widening. #88 nearly shipped a rootOnly omission that
would have served filed projects to a request for unfiled ones -- no
error, no warning, a plausible answer. #171 then added searches and
matchLimitPerSearch to both filters, and neither appeared in the key; that
was harmless only because the batch path bypasses the cache entirely, a
property nothing enforced.

The key is now a fingerprint of the filter's own sorted-key encoding, so
any new filter field changes the identity automatically. Page limit,
cursor, and requested fields stay explicit because they are not part of
the filter.

Cacheability is decided from that same encoding. "Do not cache" remains a
judgement about semantics -- time-relative review and completion windows,
and live batch resolution -- so it stays an explicit field-name list, but
it is now checked against the encoded filter rather than duplicated as a
boolean expression that could drift from it.

Fixed while here: the tags path consulted the cache conditionally but
wrote to it unconditionally, so an uncacheable tag result would still have
been stored.

Existing key-separation tests are preserved and migrated, with new
coverage for rootOnly and searches separation, and for the invariant that
any field change alters the fingerprint.

Validation impact: query. 345 tests pass; all semantic gates pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@deverman

deverman commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Closing unmerged. This fixed no reachable bug: the rootOnly gap was already fixed in #88 with a regression test, and the batch path bypasses the cache entirely, so the searches omission and the unconditional tags write were both unreachable. 233 lines for no user-visible benefit is not a good trade, and the unwritable acceptance criterion was a signal the issue was mis-specified rather than something to work around.

@deverman deverman closed this Aug 2, 2026
@deverman
deverman deleted the issue-207-cache-key-derivation branch August 2, 2026 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Derive catalog cache keys from the filter instead of a hand-maintained list

1 participant