fix: une tentative dépassée n'ouvre plus rien, et libère ce qu'elle avait ouvert
This commit is contained in:
@@ -545,3 +545,88 @@ describe("listing the inboxes when one of the two registers cannot be read", ()
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Bob shares TWO documents with Alice, each held back separately, so a test has two
|
||||
* independent arrivals to drive the observation with rather than one.
|
||||
*/
|
||||
async function bobSharesTwiceWithAlice(): Promise<Quad[][]> {
|
||||
await signIn("alice");
|
||||
await storeRegistry.createEntityDoc("protected"); // her first visit — now she exists
|
||||
await signIn("bob");
|
||||
const aliceInbox = await userInbox("alice", "protected");
|
||||
const batches: Quad[][] = [];
|
||||
for (let round = 0; round < 2; round += 1) {
|
||||
const doc = await storeRegistry.createEntityDoc("protected");
|
||||
await inboxSurface.share(doc, "alice");
|
||||
batches.push(heldByTheBroker(aliceInbox));
|
||||
}
|
||||
return batches;
|
||||
}
|
||||
|
||||
describe("a register that stays unreadable", () => {
|
||||
/**
|
||||
* The retry that would repair the shortfall is also what re-reads it.
|
||||
*
|
||||
* Every signal the observation listens to runs a full cycle, and each cycle re-discovers a
|
||||
* condition that never stopped holding — so ONE deposit put three copies of the same line
|
||||
* in the log. A report that repeats on its own is not more information; it is what buries
|
||||
* the report that means something, and it invites reading a persistent fault as a
|
||||
* recurring one.
|
||||
*/
|
||||
test("is reported ONCE, not once per enumeration", async () => {
|
||||
const { inTransit } = await bobSharesWithAlice();
|
||||
const store = (await resolveAccount("alice"))?.docPrivate;
|
||||
if (store === undefined) throw new Error("the fixture did not give Alice a private store");
|
||||
fake._failReadsOn.add(store);
|
||||
|
||||
const reported = await whileWatchingTheLog(async () => {
|
||||
try {
|
||||
await signIn("alice");
|
||||
} catch {
|
||||
// The restore rejects on the unreadable store; she is connected regardless.
|
||||
}
|
||||
await converge();
|
||||
fake._deliver(inTransit);
|
||||
await converge();
|
||||
await converge();
|
||||
});
|
||||
fake._failReadsOn.delete(store);
|
||||
|
||||
expect(reported.filter((l) => /could not all be listed/.test(l))).toHaveLength(1);
|
||||
});
|
||||
|
||||
/**
|
||||
* Once per OCCURRENCE, and a second occurrence is a real one.
|
||||
*
|
||||
* Silencing the repeat by remembering "already said" and never forgetting it would trade a
|
||||
* noisy log for a mute one: the register breaking again, after a spell of working, is news
|
||||
* — and it is exactly the case the retry exists for.
|
||||
*/
|
||||
test("is reported AGAIN once the list has come back WHOLE in between", async () => {
|
||||
const [first, second] = await bobSharesTwiceWithAlice();
|
||||
const store = (await resolveAccount("alice"))?.docPrivate;
|
||||
if (store === undefined) throw new Error("the fixture did not give Alice a private store");
|
||||
|
||||
fake._failReadsOn.add(store);
|
||||
const reported = await whileWatchingTheLog(async () => {
|
||||
try {
|
||||
await signIn("alice");
|
||||
} catch {
|
||||
// As above: the restore rejects, the connection stands.
|
||||
}
|
||||
await converge(); // the shortfall, first occurrence
|
||||
|
||||
fake._failReadsOn.delete(store); // the register is readable again…
|
||||
fake._deliver(first ?? []); // …and an arrival makes the observation re-enumerate
|
||||
await converge(); // the list comes back WHOLE
|
||||
|
||||
fake._failReadsOn.add(store); // and then it breaks a second time
|
||||
fake._deliver(second ?? []);
|
||||
await converge(); // the shortfall, second occurrence
|
||||
});
|
||||
fake._failReadsOn.delete(store);
|
||||
|
||||
expect(reported.filter((l) => /could not all be listed/.test(l))).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user