test(data): per-scenario state isolation to bound the read fan-out
@data oscillated 15-20/21 because the persistent test wallet accumulated data across scenarios, growing the read fan-out. Add a cheap per-scenario reset (resetDataState): a single SPARQL DELETE on the shim anchor graph clears the account records, so allAccounts() collapses and the fan-out is bounded to what the current scenario re-provisions (accounts recreated lazily). O(1) on one graph — not a fan-out delete (which saturated the browser before). Called in the @data Before hook, time-boxed so it can't starve the broker login budget. Test-infra only — product model, boundary and app read path untouched. Note: not yet re-measured to stable-green — the broker was degraded during the bounded validation window (DNS/timeout flakiness). To re-measure when the broker is stable. knowledge_data-layer-broker updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -366,6 +366,55 @@ function ConnectedHarness() {
|
||||
return { cleared: all.length };
|
||||
},
|
||||
|
||||
/**
|
||||
* PER-SCENARIO STATE ISOLATION (T03.j). The @data suite runs against ONE
|
||||
* persistent broker-backed wallet, so the emulated account registry (the
|
||||
* `urn:ng-eventually:shim:Account` triples in the private-store anchor
|
||||
* graph) ACCUMULATES every account any scenario/run ever provisioned. The
|
||||
* read path is a fan-out: `allAccounts()` → one SPARQL SELECT per account
|
||||
* for `listEntityDocs`. As the registry grows unbounded across runs, that
|
||||
* fan-out gets slow and flaky (same class as the T03.d Chromium saturation).
|
||||
*
|
||||
* This gives each @data scenario a CLEAN registry: a SINGLE SPARQL DELETE
|
||||
* on the ONE private-store anchor graph removes every accumulated Account
|
||||
* record, so `allAccounts()` collapses to empty and the fan-out is bounded
|
||||
* to whatever the CURRENT scenario re-provisions (accounts are lazily
|
||||
* re-created by `ensureAccount` on first use). It is O(1) on ONE graph — NOT
|
||||
* a fan-out delete (which saturated the browser before, see T03.i's removed
|
||||
* `authClearParticipation`). Orphaned per-entity docs are simply never
|
||||
* enumerated once their owning Account record is gone.
|
||||
*
|
||||
* Test-infra ONLY: touches the emulation's registry anchor, never the
|
||||
* product model, the app read path, or the boundary. The lib is untouched;
|
||||
* this reuses the same anchor NURI (`did:ng:${private_store_id}`) and shim
|
||||
* vocabulary the lib's `loadShim`/`ensureAccount` use.
|
||||
*/
|
||||
async resetDataState() {
|
||||
const reg = await import('../utils/storeRegistry');
|
||||
const priv = `did:ng:${session.private_store_id}`;
|
||||
const SHIM = 'urn:ng-eventually:shim';
|
||||
const t0 = Date.now();
|
||||
// Delete every Account record (and its username/doc* predicates) from the
|
||||
// anchor graph. `?p ?o` with the `a shim:Account` guard scopes the delete
|
||||
// strictly to registry triples, leaving anything else in the private
|
||||
// store intact.
|
||||
const del = `
|
||||
DELETE { GRAPH <${priv}> { ?acc ?p ?o } }
|
||||
WHERE {
|
||||
GRAPH <${priv}> {
|
||||
?acc a <${SHIM}:Account> ;
|
||||
?p ?o .
|
||||
}
|
||||
}`;
|
||||
try {
|
||||
await docs.sparqlUpdate(session.session_id, del, priv);
|
||||
} catch { /* best-effort — a broker flake must not fail the scenario */ }
|
||||
// Drop the in-memory account cache so the next registry call re-reads the
|
||||
// now-empty anchor (else a stale cache would keep the old accounts alive).
|
||||
reg.resetRegistryCache();
|
||||
return { resetMs: Date.now() - t0 };
|
||||
},
|
||||
|
||||
/** ONE-TIME CLEANUP (T03.i): the private store accumulated thousands of
|
||||
* historical inbox-deposit triples across test runs (the old inbox anchor
|
||||
* = private store), making `loadShim` a 60s+ full-graph scan. Delete every
|
||||
|
||||
Reference in New Issue
Block a user