refactor(export): share the visibility filter between the row query and the estimate
`query_uploads` selects the rows the archives are built from; `estimate_export_bytes` sizes them for the disk preflight. They stated the same WHERE clause separately, and the direction of drift matters: an estimate that MISSES rows the archive writes under-reserves, which is precisely the ENOSPC the preflight exists to prevent. The integration test claimed to guard this and cannot. Both sides of `the_estimate_sums_exactly_the_rows_the_archive_will_contain` are `SRC:`-marked hand-copies in tests/common/mod.rs -- neither is production code -- so drift means production moved while both copies sat still, and the test goes on passing. The convention is sound for pinning behaviour; it is structurally incapable of detecting divergence from the thing it copies. So fix it where it can be fixed. One `export_visibility_where!()` fragment, `concat!`-ed into both queries at compile time (still `&'static str`, no allocation), with the `u`/`usr` alias contract stated. Divergence is now impossible by construction rather than watched for. The tests keep their value and lose the overclaim: the docstrings now say they pin WHICH uploads may be counted -- each excluded row in the fixture is excluded by a different predicate, so weakening any one of them still fails here -- and say plainly that they do not detect drift, with a pointer to what does. No behaviour change. The filters were verified identical before the hoist (`u.event_id = $1 AND u.deleted_at IS NULL AND usr.uploads_hidden = FALSE AND usr.is_banned = FALSE`); 99 backend tests still pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,10 +16,18 @@
|
||||
//!
|
||||
//! What these tests pin is the ESTIMATE — the part that decides. The arithmetic on top of it lives
|
||||
//! in `services/export.rs`'s unit tests; the filesystem selection lives in `is_superseded_archive`.
|
||||
//! The risk here is drift: if `query_uploads` ever gains or loses a visibility predicate and
|
||||
//! `estimate_export_bytes` doesn't, the preflight silently sizes the wrong gallery. So rather than
|
||||
//! restating the filter, these assert the estimate against the row set the archive actually
|
||||
//! contains.
|
||||
//!
|
||||
//! ON DRIFT, precisely, because it is easy to overclaim here. The hazard is that `query_uploads`
|
||||
//! (which selects the rows the archives are built from) and `estimate_export_bytes` (which sizes
|
||||
//! them) could disagree — and an estimate missing rows the archive writes UNDER-reserves, the one
|
||||
//! direction that reintroduces the ENOSPC. **These tests cannot catch that**, and neither can any
|
||||
//! test in this harness: both sides here are `SRC:`-marked hand-copies in `tests/common/mod.rs`,
|
||||
//! so if production moved and the copies didn't, they would sit still and keep passing.
|
||||
//!
|
||||
//! That is fixed where it can be — the two queries now share one `export_visibility_where!()`
|
||||
//! fragment in `services/export.rs`, so they cannot diverge by construction. What is left for
|
||||
//! these tests is what the convention is genuinely good at: pinning the BEHAVIOUR, so a change
|
||||
//! that deliberately alters the filter has to come here and say so.
|
||||
|
||||
mod common;
|
||||
|
||||
@@ -29,9 +37,10 @@ use sqlx::PgPool;
|
||||
/// The estimate must equal the sum over EXACTLY the rows `query_uploads` returns — computed from
|
||||
/// that row set, not from a restatement of its WHERE clause.
|
||||
///
|
||||
/// PREVENTS: the two queries drifting apart. An estimate that counts rows the archive skips is
|
||||
/// merely pessimistic; one that MISSES rows the archive writes under-reserves, which is the whole
|
||||
/// failure being guarded against.
|
||||
/// PINS: which uploads the preflight is allowed to count. Each excluded row below is excluded by a
|
||||
/// DIFFERENT predicate, so a change that drops or weakens any one of them fails here and has to be
|
||||
/// argued for. (It does not detect production drifting away from these copies — see the file
|
||||
/// header; `export_visibility_where!()` is what makes that impossible.)
|
||||
#[sqlx::test]
|
||||
async fn the_estimate_sums_exactly_the_rows_the_archive_will_contain(pool: PgPool) {
|
||||
let event_id = seed_event(&pool, "wedding").await;
|
||||
|
||||
Reference in New Issue
Block a user