diff --git a/packages/automerge-repo/src/DocHandle.ts b/packages/automerge-repo/src/DocHandle.ts index d0f46a654..6acec2322 100644 --- a/packages/automerge-repo/src/DocHandle.ts +++ b/packages/automerge-repo/src/DocHandle.ts @@ -43,12 +43,13 @@ export class DocHandle // * Internally we use a state machine to orchestrate document loading and/or syncing, in order to * avoid requesting data we already have, or surfacing intermediate values to the consumer. * - * ┌─────────┐ ┌────────────┐ - * ┌───────┐ ┌──FIND──┤ loading ├─REQUEST──►│ requesting ├─UPDATE──┐ + * ┌─────────────────────┬─────────TIMEOUT────►┌────────┐ + * ┌───┴─────┐ ┌───┴────────┐ │ failed │ + * ┌───────┐ ┌──FIND──┤ loading ├─REQUEST──►│ requesting ├─UPDATE──┐ └────────┘ * │ idle ├──┤ └───┬─────┘ └────────────┘ │ - * └───────┘ │ │ └─►┌─────────┐ - * │ └───────LOAD───────────────────────────────►│ ready │ - * └──CREATE───────────────────────────────────────────────►└─────────┘ + * └───────┘ │ │ └─►┌────────┐ + * │ └───────LOAD───────────────────────────────►│ ready │ + * └──CREATE───────────────────────────────────────────────►└────────┘ */ this.#machine = interpret( createMachine, DocHandleEvent>( @@ -77,6 +78,12 @@ export class DocHandle // REQUEST: { target: REQUESTING }, DELETE: { actions: "onDelete", target: DELETED }, }, + after: [ + { + delay: this.#timeoutDelay, + target: FAILED, + }, + ], }, requesting: { on: { @@ -86,6 +93,12 @@ export class DocHandle // REQUEST_COMPLETE: { target: READY }, DELETE: { actions: "onDelete", target: DELETED }, }, + after: [ + { + delay: this.#timeoutDelay, + target: FAILED, + }, + ], }, ready: { on: { @@ -94,8 +107,12 @@ export class DocHandle // DELETE: { actions: "onDelete", target: DELETED }, }, }, - error: {}, - deleted: {}, + failed: { + type: "final", + }, + deleted: { + type: "final", + }, }, }, @@ -196,8 +213,8 @@ export class DocHandle // * @returns true if the document has been marked as deleted */ isDeleted = () => this.inState([HandleState.DELETED]) - inState = (awaitStates: HandleState[]) => - awaitStates.some(state => this.#machine?.getSnapshot().matches(state)) + inState = (states: HandleState[]) => + states.some(state => this.#machine?.getSnapshot().matches(state)) /** * Use this to block until the document handle has finished loading. @@ -352,7 +369,7 @@ export const HandleState = { LOADING: "loading", REQUESTING: "requesting", READY: "ready", - ERROR: "error", + FAILED: "failed", DELETED: "deleted", } as const export type HandleState = (typeof HandleState)[keyof typeof HandleState] @@ -425,7 +442,7 @@ type DocHandleXstateMachine = Interpreter< // CONSTANTS -export const { IDLE, LOADING, REQUESTING, READY, ERROR, DELETED } = HandleState +export const { IDLE, LOADING, REQUESTING, READY, FAILED, DELETED } = HandleState const { CREATE, LOAD, diff --git a/packages/automerge-repo/test/DocHandle.test.ts b/packages/automerge-repo/test/DocHandle.test.ts index 0879cf051..1cc607e85 100644 --- a/packages/automerge-repo/test/DocHandle.test.ts +++ b/packages/automerge-repo/test/DocHandle.test.ts @@ -248,7 +248,7 @@ describe("DocHandle", () => { it("should not time out if the document is updated in time", async () => { // set docHandle time out after 5 ms - const handle = new DocHandle(TEST_ID, { timeoutDelay: 5 }) + const handle = new DocHandle(TEST_ID, { timeoutDelay: 1 }) // simulate requesting from the network handle.request() @@ -259,6 +259,8 @@ describe("DocHandle", () => { }) // now it should not time out + await pause(5) + const doc = await handle.doc() assert.equal(doc.foo, "bar") }) diff --git a/packages/automerge-repo/test/Repo.test.ts b/packages/automerge-repo/test/Repo.test.ts index c07810fba..a2f4ec7c6 100644 --- a/packages/automerge-repo/test/Repo.test.ts +++ b/packages/automerge-repo/test/Repo.test.ts @@ -53,7 +53,7 @@ describe("Repo", () => { assert.equal(handle.isReady(), false) return assert.rejects( - rejectOnTimeout(handle.doc(), 100), + rejectOnTimeout(handle.doc(), 10), "This document should not exist" ) }) @@ -292,7 +292,7 @@ describe("Repo", () => { assert.equal(handle.isReady(), false) return assert.rejects( - rejectOnTimeout(handle.doc(), 100), + rejectOnTimeout(handle.doc(), 10), "This document should not exist" ) })