fix!: le registre d-ouverture n-a plus qu-un seul sens, et il cesse de mentir
Trois constats, un seul defaut sous trois visages : un etat enregistre comme vrai qui ne l'est pas, sans moyen de se corriger. Deux des trois vivaient dans `open-repo.ts`. Cinq tours sont alles dans l'appelant ; c'est le teneur de registre qui mentait. CE QUE LE REGISTRE VEUT DIRE, ecrit dans l'en-tete. `held` est le SEUL registre d'ouverture : cette session detient un abonnement vivant a ce document. Il y avait a cote un `opened` voulant dire « on a appele `doc_subscribe` une fois et on a cesse d'attendre », et ce sens plus lache mentait de trois facons : il survivait a un abonnement REFUSE par le courtier (donc la reprise que `subscribe.ts` offre etait bloquee a jamais), il survivait a une reinitialisation (donc une nouvelle session court-circuitait sur l'enregistrement de la precedente), et il laissait un document annoncer une barriere jamais franchie. `opened` est supprime. Les trois consequences, desormais vraies par construction : - un abonnement qui a ECHOUE n'enregistre rien - `onSetupFailed`, le canal que `subscribe.ts` offre exactement pour cela, est enfin branche - donc l'appelant suivant s'abonne a nouveau ; - une reinitialisation efface l'enregistrement ET DECLASSE l'etat de synchro : une barriere franchie dans la session qui vient de disparaitre n'en est pas une que celle-ci a franchie ; - `"unknown"` ne veut plus dire qu'une chose : aucune barriere n'etait attendue ici (jamais demande, ou un `ng` sans `doc_subscribe`). Jamais « on a oublie ». Cote appelant, un seul changement, et c'est le troisieme constat : quand un document nomme n'a pas repondu, `publish` PUBLIE « la question reste ouverte » au lieu de sortir en laissant en place l'instantane precedent. Sortir laissait un refus DEJA LEVE a l'affichage : l'application lisait « vous ne detenez pas la capacite de ce document » a propos d'un document qu'elle detient desormais. Deux tests portaient l'ancien sens et sont corriges avec leur raison : celui du `ng` sans `doc_subscribe` (le compteur d'ids du faux courtier redemarrait a chaque test, donc deux tests aliasaient leurs depots - la lecon de `wallet-fake` a l'echelle du fichier), et celui de la lecture froide, ou « timed-out » est desormais ce que dit « cette page ne l'a pas confirme ».
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
import { describe, it, expect, mock, beforeEach, afterAll } from "bun:test";
|
||||
import { ensureRepoOpen, getSyncState, resetOpenedRepos } from "../src/emulated-verifier/open-repo";
|
||||
import { ensureRepoOpen, getSyncState, resetOpenedRepos, setOpenTimeoutForTests } from "../src/emulated-verifier/open-repo";
|
||||
import { readDocumentSubjects } from "../src/surface/read-document";
|
||||
import { configure } from "../src/index";
|
||||
import { configureStoreRegistry, setCurrentUser } from "../src/shared-wallet/bootstrap";
|
||||
@@ -55,7 +55,7 @@ const FP = "http://festipod.org/";
|
||||
|
||||
function makeFakeNgWithSubscribe(
|
||||
triplesByDoc: Record<string, Array<[string, string]>>,
|
||||
options: { pushState?: boolean } = {},
|
||||
options: { pushState?: boolean; subscribeFails?: boolean } = {},
|
||||
) {
|
||||
// A broker that accepts the subscription and never pushes is the state the bounded
|
||||
// fallback exists for, and the only way to hold an open genuinely IN FLIGHT.
|
||||
@@ -67,6 +67,9 @@ function makeFakeNgWithSubscribe(
|
||||
const doc_subscribe = mock(async (nuri: string, _sid: string, cb: (r: unknown) => void) => {
|
||||
subscribed.add(nuri);
|
||||
subscribeCallOrder.push(nuri);
|
||||
// A broker that REFUSES the subscription - a real failure, and one `subscribe.ts`
|
||||
// deliberately makes retryable by offering `onSetupFailed`.
|
||||
if (options.subscribeFails) throw new Error("BrokerError: cannot subscribe");
|
||||
// Simulate initial State push (synchronously deferred so the subscription
|
||||
// setup promise path in ensureRepoOpen can resolve it).
|
||||
if (pushState) setTimeout(() => cb({ V0: { State: {} } }), 0);
|
||||
@@ -237,6 +240,27 @@ describe("ensureRepoOpen", () => {
|
||||
await reopened;
|
||||
});
|
||||
|
||||
// A subscribe the broker REFUSED leaves nothing behind, so it can be tried again.
|
||||
//
|
||||
// `subscribe.ts` reports a failed establish through `onSetupFailed` precisely so a
|
||||
// caller can retry; `open-repo` ignored it, waited out the bounded fallback, and then
|
||||
// recorded the repo as OPEN. Every later open short-circuited on that record, so
|
||||
// `refetch()` issued no new subscribe and the read had no exit at all.
|
||||
it("a subscribe the broker REFUSED is not recorded as open, so it can be retried", async () => {
|
||||
const ng = makeFakeNgWithSubscribe({}, { subscribeFails: true });
|
||||
inject(ng);
|
||||
setOpenTimeoutForTests(30);
|
||||
|
||||
await ensureRepoOpen("did:ng:o:refused-sub");
|
||||
expect(ng.doc_subscribe).toHaveBeenCalledTimes(1);
|
||||
// Not authoritative: no `State` was ever going to arrive.
|
||||
expect(getSyncState("did:ng:o:refused-sub")).toBe("timed-out");
|
||||
|
||||
// The retry a caller is entitled to make.
|
||||
await ensureRepoOpen("did:ng:o:refused-sub");
|
||||
expect(ng.doc_subscribe).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("the anchored document read triggers doc_subscribe then returns data (integration path)", async () => {
|
||||
const ng = makeFakeNgWithSubscribe({
|
||||
"did:ng:o:p": [[TYPE, `${FP}Participation`], [`${FP}event`, "did:ng:o:e"]],
|
||||
|
||||
Reference in New Issue
Block a user