fix: un dépôt est délivré une fois et retiré, comme en amont
This commit is contained in:
@@ -97,6 +97,19 @@ function makeFakeNg(faults: Faults) {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
// Retiring a DEPOSIT: every triple of one subject, whatever predicates it carries
|
||||
// (`emulated-verifier/inbox-consume.removeDeposit`). Modelled rather than ignored — a
|
||||
// fake that let this delete fall through would leave every deposit in place, and a
|
||||
// suite asserting convergence would pass on a queue that never shrinks.
|
||||
const delDeposit = query.match(/^\s*DELETE\s+WHERE\s*\{\s*<([^>]+)>\s+\?\w+\s+\?\w+\s*\}/);
|
||||
if (delDeposit) {
|
||||
const subject = delDeposit[1]!;
|
||||
for (let i = quads.length - 1; i >= 0; i--) {
|
||||
const q = quads[i]!;
|
||||
if (q.s === subject) quads.splice(i, 1);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
const gm = query.match(/GRAPH\s+<([^>]+)>\s*\{([\s\S]*)\}/);
|
||||
const body = gm ? gm[2]! : query.replace(/^\s*INSERT DATA\s*\{/, "").replace(/\}\s*$/, "");
|
||||
const sm = body.match(/<([^>]+)>/);
|
||||
@@ -160,6 +173,8 @@ function makeFakeNg(faults: Faults) {
|
||||
for (const q of quads) {
|
||||
if (q.g !== anchor) continue;
|
||||
const rec = bySubject.get(q.s) ?? {};
|
||||
// The deposit's own subject — the key a drain names to retire it.
|
||||
rec.d = q.s;
|
||||
if (q.p === `${INBOX}:payload`) rec.payload = q.o;
|
||||
if (q.p === `${INBOX}:ts`) rec.ts = q.o;
|
||||
if (q.p === `${INBOX}:from`) rec.from = q.o;
|
||||
@@ -171,6 +186,7 @@ function makeFakeNg(faults: Faults) {
|
||||
.filter((r) => r.payload !== undefined && r.ts !== undefined)
|
||||
.map((r) => {
|
||||
const row: Record<string, { value: string }> = {
|
||||
d: { value: r.d! },
|
||||
payload: { value: r.payload! },
|
||||
ts: { value: r.ts! },
|
||||
};
|
||||
@@ -338,14 +354,15 @@ test("what the drain filed for the owner is DURABLE: he restores it with his inb
|
||||
await share(aliceDoc, "bob");
|
||||
await runScheduledInboxProcessingNow();
|
||||
|
||||
// EMPTY the inbox, as a consumed queue would be, and drop every in-memory cap — so what
|
||||
// Bob recovers below can only have come from his own User branch, where the drain filed
|
||||
// it. Without that, he would simply be draining the queue himself on connection, which
|
||||
// is the behaviour this service exists to get ahead of.
|
||||
// The inbox is ALREADY empty — the drain consumed the deposit as it applied it. Until
|
||||
// 2026-08-26 this test had to empty the queue by hand to reach that state, which is
|
||||
// exactly the shortcut that fabricates a state the system never produced; now it is
|
||||
// asserted instead. It matters here because what Bob recovers below must come from his
|
||||
// own User branch, where the drain filed it: with the deposit still in the queue he
|
||||
// would simply be draining it himself on connection, which is the behaviour this
|
||||
// service exists to get ahead of.
|
||||
const bobInbox = await userInbox("bob", "protected");
|
||||
for (let k = fake.quads.length - 1; k >= 0; k--) {
|
||||
if (fake.quads[k]!.g === bobInbox) fake.quads.splice(k, 1);
|
||||
}
|
||||
expect(fake.quads.filter((q) => q.g === bobInbox && q.p === `${INBOX}:payload`)).toEqual([]);
|
||||
resetCaps();
|
||||
setCurrentUser("alice");
|
||||
await createEntityDoc("alice", "private"); // re-arms the emulation: a cap exists again
|
||||
@@ -436,8 +453,10 @@ test("a drain that fails says so in the package's log, and rejects into nobody",
|
||||
|
||||
// The wording is the SHARED reporter's since 2026-08-17 (`emulated-verifier/inbox-drain.ts`):
|
||||
// the timer is no longer the only thing that drains an inbox — the continuous observation
|
||||
// does too, through the same queue — so the line names the act and not the schedule.
|
||||
const reported = errors.filter((line) => /could not apply what is in this inbox/.test(line));
|
||||
// does too, through the same queue — so the line names the act and not the schedule. Since
|
||||
// 2026-08-26 it also stops promising a retry it cannot make: a deposit already taken is
|
||||
// consumed, and only what is STILL QUEUED waits for the next attempt.
|
||||
const reported = errors.filter((line) => /could not finish draining this inbox/.test(line));
|
||||
expect(reported.length).toBe(1);
|
||||
// Prefixed by the CONNECTED identity, like every other polyfill-layer line — which is
|
||||
// what makes a drain running under someone else's session legible in a live trace.
|
||||
|
||||
Reference in New Issue
Block a user