Eviction no longer reads a whole table while requests wait on the database (closes #227) #228

Merged
clawbot merged 1 commits from issue-227-size-total into next 2026-10-08 07:12:03 +02:00
Collaborator

Fixes #227.

  • A new one-row table, cache_usage, holds the total cache usage. Triggers on source_content and variant_content (insert, delete, update of size_bytes) keep it current in the statement that changes a row. UsageBytes, which every eviction pass calls, reads that row instead of summing both tables.
  • The reconciliation pass reads the content tables 1000 rows per query, for its row checks and for a full sum, and sets the total to the sum when they differ. It does so only if change_count, which each trigger raises, has not moved since the sum began; otherwise a store during the sum could be missed and the total set wrong.
  • source_content.last_accessed_at now defaults to the time the row is added, as in variant_content. The source eviction candidates were ordered by a COALESCE expression, so SQLite read and sorted the whole table on every eviction batch; they now come from the column's index. The issue did not list this query, but its definition of done covers it.
  • README.md loses the sentence saying requests wait for eviction's queries.

Disclosures:

  • Judgement call: while stores keep arriving, a wrong total can stay uncorrected until a pass in which no store lands during its sum.
  • Stats still sums the tables, now in pages: TestStats_LogsFailedCountQueries drops both tables and expects that sum to fail, and changing an existing test needs owner approval. No request calls Stats.
  • A database created before this change lacks cache_usage and the triggers, since 001_schema.sql is not applied to it again (pre-1.0 rule).

Model: opus-5-5

Fixes https://git.eeqj.de/sneak/pixa/issues/227. - A new one-row table, `cache_usage`, holds the total cache usage. Triggers on `source_content` and `variant_content` (insert, delete, update of `size_bytes`) keep it current in the statement that changes a row. `UsageBytes`, which every eviction pass calls, reads that row instead of summing both tables. - The reconciliation pass reads the content tables 1000 rows per query, for its row checks and for a full sum, and sets the total to the sum when they differ. It does so only if `change_count`, which each trigger raises, has not moved since the sum began; otherwise a store during the sum could be missed and the total set wrong. - `source_content.last_accessed_at` now defaults to the time the row is added, as in `variant_content`. The source eviction candidates were ordered by a `COALESCE` expression, so SQLite read and sorted the whole table on every eviction batch; they now come from the column's index. The issue did not list this query, but its definition of done covers it. - `README.md` loses the sentence saying requests wait for eviction's queries. Disclosures: - Judgement call: while stores keep arriving, a wrong total can stay uncorrected until a pass in which no store lands during its sum. - `Stats` still sums the tables, now in pages: `TestStats_LogsFailedCountQueries` drops both tables and expects that sum to fail, and changing an existing test needs owner approval. No request calls `Stats`. - A database created before this change lacks `cache_usage` and the triggers, since `001_schema.sql` is not applied to it again (pre-1.0 rule). Model: opus-5-5
clawbot added the needs-review label 2026-10-08 05:30:03 +02:00
clawbot self-assigned this 2026-10-08 05:30:04 +02:00
Author
Collaborator
  1. internal/imgcache/cache_usage_internal_test.go:156 (TestReconciliationReadsAPageAtATime): the definition of done in #227 asks for a test that a request's query does not wait for a whole reconciliation read. This test checks that variantKeysAfter and sourceContentHashesAfter each return one page, and that the pass still reaches every row, but not that the pass reads in pages: no test fails if reconcileVariantRows (internal/imgcache/eviction.go:674), reconcileSourceRows (eviction.go:821) or sumSizeBytesInPages (eviction.go:899) reads or sums a whole table in one query. Acceptable: a test that runs the reconciliation pass over more than one page of rows in each content table and fails if any one of its reads, the row checks and the sum alike, covers more than one page.

  2. internal/imgcache/cachesize.go:75: the nolint reason still says UsageBytes sums file sizes; it now reads the total kept in cache_usage. Acceptable: a reason that describes what UsageBytes now returns.

Model: opus-5-5

1. `internal/imgcache/cache_usage_internal_test.go:156` (`TestReconciliationReadsAPageAtATime`): the definition of done in https://git.eeqj.de/sneak/pixa/issues/227 asks for a test that a request's query does not wait for a whole reconciliation read. This test checks that `variantKeysAfter` and `sourceContentHashesAfter` each return one page, and that the pass still reaches every row, but not that the pass reads in pages: no test fails if `reconcileVariantRows` (`internal/imgcache/eviction.go:674`), `reconcileSourceRows` (`eviction.go:821`) or `sumSizeBytesInPages` (`eviction.go:899`) reads or sums a whole table in one query. Acceptable: a test that runs the reconciliation pass over more than one page of rows in each content table and fails if any one of its reads, the row checks and the sum alike, covers more than one page. 2. `internal/imgcache/cachesize.go:75`: the `nolint` reason still says `UsageBytes` sums file sizes; it now reads the total kept in `cache_usage`. Acceptable: a reason that describes what `UsageBytes` now returns. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-08 05:59:39 +02:00
clawbot force-pushed issue-227-size-total from 0dfb2e9651 to 7cbcd3957f 2026-10-08 06:28:35 +02:00 Compare
clawbot added 1 commit 2026-10-08 06:29:16 +02:00
UsageBytes now reads the new cache_usage row, which triggers on
source_content and variant_content keep up to date in the statement
that adds, removes or resizes a row. The reconciliation pass reads both
tables 1000 rows per query, sums them, and corrects the total when it
differs, unless a row changed while it summed. Source rows now get
last_accessed_at when added, so choosing source images to evict reads
that column's index instead of sorting the whole table. Stats still
sums the tables, now in pages: an existing test drops both tables and
expects that sum to fail.

Model: opus-5-5
clawbot force-pushed issue-227-size-total from 7cbcd3957f to 160335724e 2026-10-08 06:29:17 +02:00 Compare
clawbot added needs-review and removed needs-rework labels 2026-10-08 06:50:10 +02:00
Author
Collaborator

Review passed.

Model: opus-5-5

Review passed. Model: opus-5-5
clawbot merged commit d2944aa891 into next 2026-10-08 07:12:03 +02:00
clawbot deleted branch issue-227-size-total 2026-10-08 07:12:06 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/pixa#228