@earendil-works/pi-durable 0.87.0 → 0.99.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -1
- package/dist/documents.d.ts +66 -0
- package/dist/documents.d.ts.map +1 -0
- package/dist/documents.js +98 -0
- package/dist/documents.js.map +1 -0
- package/dist/entries.d.ts +13 -0
- package/dist/entries.d.ts.map +1 -0
- package/dist/entries.js +18 -0
- package/dist/entries.js.map +1 -0
- package/dist/env/index.d.ts +131 -0
- package/dist/env/index.d.ts.map +1 -0
- package/dist/env/index.js +45 -0
- package/dist/env/index.js.map +1 -0
- package/dist/env/node.d.ts +45 -0
- package/dist/env/node.d.ts.map +1 -0
- package/dist/env/node.js +908 -0
- package/dist/env/node.js.map +1 -0
- package/dist/env/utils/adaptive-publisher.d.ts +24 -0
- package/dist/env/utils/adaptive-publisher.d.ts.map +1 -0
- package/dist/env/utils/adaptive-publisher.js +79 -0
- package/dist/env/utils/adaptive-publisher.js.map +1 -0
- package/dist/env/utils/output-capture.d.ts +31 -0
- package/dist/env/utils/output-capture.d.ts.map +1 -0
- package/dist/env/utils/output-capture.js +238 -0
- package/dist/env/utils/output-capture.js.map +1 -0
- package/dist/env/utils/truncate.d.ts +71 -0
- package/dist/env/utils/truncate.d.ts.map +1 -0
- package/dist/env/utils/truncate.js +294 -0
- package/dist/env/utils/truncate.js.map +1 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +24 -0
- package/dist/errors.js.map +1 -0
- package/dist/harness/config.d.ts +20 -0
- package/dist/harness/config.d.ts.map +1 -0
- package/dist/harness/config.js +18 -0
- package/dist/harness/config.js.map +1 -0
- package/dist/harness/context.d.ts +27 -0
- package/dist/harness/context.d.ts.map +1 -0
- package/dist/harness/context.js +109 -0
- package/dist/harness/context.js.map +1 -0
- package/dist/harness/generation.d.ts +36 -0
- package/dist/harness/generation.d.ts.map +1 -0
- package/dist/harness/generation.js +266 -0
- package/dist/harness/generation.js.map +1 -0
- package/dist/harness/harness.d.ts +10 -0
- package/dist/harness/harness.d.ts.map +1 -0
- package/dist/harness/harness.js +266 -0
- package/dist/harness/harness.js.map +1 -0
- package/dist/harness/live.d.ts +40 -0
- package/dist/harness/live.d.ts.map +1 -0
- package/dist/harness/live.js +41 -0
- package/dist/harness/live.js.map +1 -0
- package/dist/harness/prompt.d.ts +24 -0
- package/dist/harness/prompt.d.ts.map +1 -0
- package/dist/harness/prompt.js +88 -0
- package/dist/harness/prompt.js.map +1 -0
- package/dist/harness/registry.d.ts +7 -0
- package/dist/harness/registry.d.ts.map +1 -0
- package/dist/harness/registry.js +309 -0
- package/dist/harness/registry.js.map +1 -0
- package/dist/harness/scheduler.d.ts +63 -0
- package/dist/harness/scheduler.d.ts.map +1 -0
- package/dist/harness/scheduler.js +605 -0
- package/dist/harness/scheduler.js.map +1 -0
- package/dist/harness/submissions.d.ts +24 -0
- package/dist/harness/submissions.d.ts.map +1 -0
- package/dist/harness/submissions.js +133 -0
- package/dist/harness/submissions.js.map +1 -0
- package/dist/harness/types.d.ts +358 -0
- package/dist/harness/types.d.ts.map +1 -0
- package/dist/harness/types.js +2 -0
- package/dist/harness/types.js.map +1 -0
- package/dist/harness/util.d.ts +14 -0
- package/dist/harness/util.d.ts.map +1 -0
- package/dist/harness/util.js +55 -0
- package/dist/harness/util.js.map +1 -0
- package/dist/ids.d.ts +6 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +9 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/session/forks.d.ts +10 -0
- package/dist/session/forks.d.ts.map +1 -0
- package/dist/session/forks.js +42 -0
- package/dist/session/forks.js.map +1 -0
- package/dist/session/observation.d.ts +28 -0
- package/dist/session/observation.d.ts.map +1 -0
- package/dist/session/observation.js +280 -0
- package/dist/session/observation.js.map +1 -0
- package/dist/session/session.d.ts +59 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/session/session.js +380 -0
- package/dist/session/session.js.map +1 -0
- package/dist/session/transaction.d.ts +105 -0
- package/dist/session/transaction.d.ts.map +1 -0
- package/dist/session/transaction.js +718 -0
- package/dist/session/transaction.js.map +1 -0
- package/dist/storage/jsonl/index.d.ts +2 -0
- package/dist/storage/jsonl/index.d.ts.map +1 -0
- package/dist/storage/jsonl/index.js +2 -0
- package/dist/storage/jsonl/index.js.map +1 -0
- package/dist/storage/jsonl/node.d.ts +6 -0
- package/dist/storage/jsonl/node.d.ts.map +1 -0
- package/dist/storage/jsonl/node.js +8 -0
- package/dist/storage/jsonl/node.js.map +1 -0
- package/dist/storage/jsonl/storage.d.ts +115 -0
- package/dist/storage/jsonl/storage.d.ts.map +1 -0
- package/dist/storage/jsonl/storage.js +681 -0
- package/dist/storage/jsonl/storage.js.map +1 -0
- package/dist/storage/memory.d.ts +60 -0
- package/dist/storage/memory.d.ts.map +1 -0
- package/dist/storage/memory.js +681 -0
- package/dist/storage/memory.js.map +1 -0
- package/dist/storage/sqlite/database.d.ts +30 -0
- package/dist/storage/sqlite/database.d.ts.map +1 -0
- package/dist/storage/sqlite/database.js +2 -0
- package/dist/storage/sqlite/database.js.map +1 -0
- package/dist/storage/sqlite/index.d.ts +4 -0
- package/dist/storage/sqlite/index.d.ts.map +1 -0
- package/dist/storage/sqlite/index.js +3 -0
- package/dist/storage/sqlite/index.js.map +1 -0
- package/dist/storage/sqlite/migrations.d.ts +11 -0
- package/dist/storage/sqlite/migrations.d.ts.map +1 -0
- package/dist/storage/sqlite/migrations.js +111 -0
- package/dist/storage/sqlite/migrations.js.map +1 -0
- package/dist/storage/sqlite/node.d.ts +25 -0
- package/dist/storage/sqlite/node.d.ts.map +1 -0
- package/dist/storage/sqlite/node.js +97 -0
- package/dist/storage/sqlite/node.js.map +1 -0
- package/dist/storage/sqlite/storage.d.ts +51 -0
- package/dist/storage/sqlite/storage.d.ts.map +1 -0
- package/dist/storage/sqlite/storage.js +628 -0
- package/dist/storage/sqlite/storage.js.map +1 -0
- package/dist/tasks.d.ts +6 -0
- package/dist/tasks.d.ts.map +1 -0
- package/dist/tasks.js +5 -0
- package/dist/tasks.js.map +1 -0
- package/dist/testing/assertions.d.ts +5 -0
- package/dist/testing/assertions.d.ts.map +1 -0
- package/dist/testing/assertions.js +25 -0
- package/dist/testing/assertions.js.map +1 -0
- package/dist/testing/index.d.ts +6 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/runner.d.ts +10 -0
- package/dist/testing/runner.d.ts.map +1 -0
- package/dist/testing/runner.js +14 -0
- package/dist/testing/runner.js.map +1 -0
- package/dist/testing/storage-benchmark.d.ts +41 -0
- package/dist/testing/storage-benchmark.d.ts.map +1 -0
- package/dist/testing/storage-benchmark.js +351 -0
- package/dist/testing/storage-benchmark.js.map +1 -0
- package/dist/testing/storage-conformance.d.ts +4 -0
- package/dist/testing/storage-conformance.d.ts.map +1 -0
- package/dist/testing/storage-conformance.js +1122 -0
- package/dist/testing/storage-conformance.js.map +1 -0
- package/dist/testing/types.d.ts +19 -0
- package/dist/testing/types.d.ts.map +1 -0
- package/dist/testing/types.js +2 -0
- package/dist/testing/types.js.map +1 -0
- package/dist/types.d.ts +525 -78
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/docs/chord-delta-findings.md +1 -1
- package/docs/pico-v5-chord-usage.md +90 -102
- package/docs/pico-v5-handoff.md +493 -253
- package/docs/pico-v5.md +1901 -848
- package/package.json +47 -5
- package/dist/memory-storage.d.ts +0 -37
- package/dist/memory-storage.d.ts.map +0 -1
- package/dist/memory-storage.js +0 -322
- package/dist/memory-storage.js.map +0 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { addressId } from "../documents.js";
|
|
2
|
+
const SCAN_PAGE_SIZE = 256;
|
|
3
|
+
/** Select every persisted conversation document copied by one fork. */
|
|
4
|
+
export async function prepareForkDocumentCopies(storage, parentConversationId, at, childConversationId, context) {
|
|
5
|
+
const entry = await storage.entry(parentConversationId, at, context);
|
|
6
|
+
if (entry === undefined)
|
|
7
|
+
throw new Error(`Entry ${at} is not visible from conversation ${parentConversationId}`);
|
|
8
|
+
const copies = [];
|
|
9
|
+
const copiedAddresses = new Set();
|
|
10
|
+
await collectCopies(storage, { kind: "conversation", conversationId: entry.entry.conversationId }, entry.commitSeq, "asOf", childConversationId, copies, copiedAddresses, context);
|
|
11
|
+
await collectCopies(storage, { kind: "conversation", conversationId: parentConversationId }, "current", "current", childConversationId, copies, copiedAddresses, context);
|
|
12
|
+
return copies;
|
|
13
|
+
}
|
|
14
|
+
async function collectCopies(storage, scope, at, policy, childConversationId, copies, copiedAddresses, context) {
|
|
15
|
+
let cursor;
|
|
16
|
+
do {
|
|
17
|
+
const page = await storage.scanDocuments({ scope, at }, SCAN_PAGE_SIZE, cursor, context);
|
|
18
|
+
for (const source of page.items) {
|
|
19
|
+
if (source.scope.kind !== "conversation" || source.fork !== policy)
|
|
20
|
+
continue;
|
|
21
|
+
const id = await storage.mintId();
|
|
22
|
+
const identity = {
|
|
23
|
+
id,
|
|
24
|
+
kind: source.kind,
|
|
25
|
+
...(source.key === undefined ? {} : { key: source.key }),
|
|
26
|
+
scope: { kind: "conversation", conversationId: childConversationId },
|
|
27
|
+
};
|
|
28
|
+
const record = source.history === "latest"
|
|
29
|
+
? { ...identity, history: "latest", fork: source.fork }
|
|
30
|
+
: { ...identity, history: "rewindable", fork: source.fork };
|
|
31
|
+
const copyAddress = addressId(record);
|
|
32
|
+
if (copiedAddresses.has(copyAddress)) {
|
|
33
|
+
const member = record.key === undefined ? record.kind : `${record.kind}/${record.key}`;
|
|
34
|
+
throw new Error(`Fork selects multiple source documents for ${member}`);
|
|
35
|
+
}
|
|
36
|
+
copiedAddresses.add(copyAddress);
|
|
37
|
+
copies.push({ record, source: { id: source.id, at } });
|
|
38
|
+
}
|
|
39
|
+
cursor = page.next;
|
|
40
|
+
} while (cursor !== undefined);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=forks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forks.js","sourceRoot":"","sources":["../../src/session/forks.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Context } from \"@earendil-works/chord\";\nimport { addressId } from \"../documents.ts\";\nimport type {\n\tConversationId,\n\tCursor,\n\tDocumentCopySource,\n\tDocumentCreate,\n\tDocumentId,\n\tDocumentPoint,\n\tDocumentRecord,\n\tEntryId,\n\tStorage,\n} from \"../types.ts\";\n\nconst SCAN_PAGE_SIZE = 256;\n\ntype ForkPolicy = \"asOf\" | \"current\";\n\n/** One definition-free document copy to create with a forked conversation. */\nexport type ForkDocumentCopy = {\n\treadonly record: DocumentCreate;\n\treadonly source: DocumentCopySource;\n};\n\n/** Select every persisted conversation document copied by one fork. */\nexport async function prepareForkDocumentCopies(\n\tstorage: Storage,\n\tparentConversationId: ConversationId,\n\tat: EntryId,\n\tchildConversationId: ConversationId,\n\tcontext: Context,\n): Promise<readonly ForkDocumentCopy[]> {\n\tconst entry = await storage.entry(parentConversationId, at, context);\n\tif (entry === undefined) throw new Error(`Entry ${at} is not visible from conversation ${parentConversationId}`);\n\n\tconst copies: ForkDocumentCopy[] = [];\n\tconst copiedAddresses = new Set<string>();\n\tawait collectCopies(\n\t\tstorage,\n\t\t{ kind: \"conversation\", conversationId: entry.entry.conversationId },\n\t\tentry.commitSeq,\n\t\t\"asOf\",\n\t\tchildConversationId,\n\t\tcopies,\n\t\tcopiedAddresses,\n\t\tcontext,\n\t);\n\tawait collectCopies(\n\t\tstorage,\n\t\t{ kind: \"conversation\", conversationId: parentConversationId },\n\t\t\"current\",\n\t\t\"current\",\n\t\tchildConversationId,\n\t\tcopies,\n\t\tcopiedAddresses,\n\t\tcontext,\n\t);\n\treturn copies;\n}\n\nasync function collectCopies(\n\tstorage: Storage,\n\tscope: Extract<DocumentRecord[\"scope\"], { readonly kind: \"conversation\" }>,\n\tat: DocumentPoint,\n\tpolicy: ForkPolicy,\n\tchildConversationId: ConversationId,\n\tcopies: ForkDocumentCopy[],\n\tcopiedAddresses: Set<string>,\n\tcontext: Context,\n): Promise<void> {\n\tlet cursor: Cursor | undefined;\n\tdo {\n\t\tconst page = await storage.scanDocuments({ scope, at }, SCAN_PAGE_SIZE, cursor, context);\n\t\tfor (const source of page.items) {\n\t\t\tif (source.scope.kind !== \"conversation\" || source.fork !== policy) continue;\n\t\t\tconst id = await storage.mintId<DocumentId>();\n\t\t\tconst identity = {\n\t\t\t\tid,\n\t\t\t\tkind: source.kind,\n\t\t\t\t...(source.key === undefined ? {} : { key: source.key }),\n\t\t\t\tscope: { kind: \"conversation\" as const, conversationId: childConversationId },\n\t\t\t};\n\t\t\tconst record: DocumentCreate =\n\t\t\t\tsource.history === \"latest\"\n\t\t\t\t\t? { ...identity, history: \"latest\", fork: source.fork }\n\t\t\t\t\t: { ...identity, history: \"rewindable\", fork: source.fork };\n\t\t\tconst copyAddress = addressId(record);\n\t\t\tif (copiedAddresses.has(copyAddress)) {\n\t\t\t\tconst member = record.key === undefined ? record.kind : `${record.kind}/${record.key}`;\n\t\t\t\tthrow new Error(`Fork selects multiple source documents for ${member}`);\n\t\t\t}\n\t\t\tcopiedAddresses.add(copyAddress);\n\t\t\tcopies.push({ record, source: { id: source.id, at } });\n\t\t}\n\t\tcursor = page.next;\n\t} while (cursor !== undefined);\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Context, ReplicatedStateSource, ReplicatedStateSourceAttachment } from "@earendil-works/chord";
|
|
2
|
+
import type { Op } from "@earendil-works/chord/delta";
|
|
3
|
+
import type { JsonObject, WatchEnd, WatchHandle } from "../types.ts";
|
|
4
|
+
export type ObservedDocumentValue = Readonly<JsonObject> | null;
|
|
5
|
+
/** Canonical terminal update for a retired document incarnation. */
|
|
6
|
+
export declare const RETIREMENT_OPERATIONS: readonly Op[];
|
|
7
|
+
/** Session-to-Chord bridge owned one-to-one by one attached document state. @internal */
|
|
8
|
+
export declare class SessionDocumentSource implements ReplicatedStateSource<ObservedDocumentValue> {
|
|
9
|
+
#private;
|
|
10
|
+
constructor(value: Readonly<JsonObject>, release: () => void);
|
|
11
|
+
attach(): ReplicatedStateSourceAttachment<ObservedDocumentValue>;
|
|
12
|
+
advance(value: ObservedDocumentValue, ops: readonly Op[], context: Context): void;
|
|
13
|
+
closeSession(): void;
|
|
14
|
+
}
|
|
15
|
+
/** Serialized exact-frame watch bound to one concrete document incarnation. @internal */
|
|
16
|
+
export declare class SessionDocumentWatch implements WatchHandle<ObservedDocumentValue> {
|
|
17
|
+
#private;
|
|
18
|
+
constructor(value: Readonly<JsonObject>, detach: () => void);
|
|
19
|
+
get value(): ObservedDocumentValue;
|
|
20
|
+
get closed(): Promise<WatchEnd>;
|
|
21
|
+
start(listener: (value: ObservedDocumentValue, ops: readonly Op[], context: Context) => Promise<void>): void;
|
|
22
|
+
stop(): Promise<WatchEnd>;
|
|
23
|
+
observeCancellation(signal: AbortSignal): void;
|
|
24
|
+
cancel(): void;
|
|
25
|
+
closeSession(): void;
|
|
26
|
+
advance(value: ObservedDocumentValue, ops: readonly Op[], context: Context): void;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=observation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../../src/session/observation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,OAAO,EACP,qBAAqB,EACrB,+BAA+B,EAE/B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAErE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;AAKhE,oEAAoE;AACpE,eAAO,MAAM,qBAAqB,EAAE,SAAS,EAAE,EAAkB,CAAC;AAElE,yFAAyF;AACzF,qBAAa,qBAAsB,YAAW,qBAAqB,CAAC,qBAAqB,CAAC;;IAQzF,YAAY,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,MAAM,IAAI,EAG3D;IAED,MAAM,IAAI,+BAA+B,CAAC,qBAAqB,CAAC,CAQ/D;IAED,OAAO,CAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAYhF;IAED,YAAY,IAAI,IAAI,CAInB;CAUD;AA2ED,yFAAyF;AACzF,qBAAa,oBAAqB,YAAW,WAAW,CAAC,qBAAqB,CAAC;;IAiB9E,YAAY,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,IAAI,EAM1D;IAED,IAAI,KAAK,IAAI,qBAAqB,CAEjC;IAED,IAAI,MAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,CAE9B;IAED,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAM3G;IAED,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,CAGxB;IAED,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAO7C;IAED,MAAM,IAAI,IAAI,CAEb;IAED,YAAY,IAAI,IAAI,CAEnB;IAED,OAAO,CAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAUhF;CAiED"}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { withoutAbortSignal } from "@earendil-works/chord/context";
|
|
2
|
+
/** Maximum exact committed frames retained behind one unavailable watch listener. */
|
|
3
|
+
const MAX_PENDING_WATCH_FRAMES = 100;
|
|
4
|
+
/** Canonical terminal update for a retired document incarnation. */
|
|
5
|
+
export const RETIREMENT_OPERATIONS = [["r", null]];
|
|
6
|
+
/** Session-to-Chord bridge owned one-to-one by one attached document state. @internal */
|
|
7
|
+
export class SessionDocumentSource {
|
|
8
|
+
#attachments = new Set();
|
|
9
|
+
#release;
|
|
10
|
+
#value;
|
|
11
|
+
#cursor = 0;
|
|
12
|
+
#retired = false;
|
|
13
|
+
#closed = false;
|
|
14
|
+
constructor(value, release) {
|
|
15
|
+
this.#value = value;
|
|
16
|
+
this.#release = release;
|
|
17
|
+
}
|
|
18
|
+
attach() {
|
|
19
|
+
if (this.#closed)
|
|
20
|
+
throw new Error("Document state source is closed");
|
|
21
|
+
const attachment = new SessionSourceAttachment({ value: this.#value, cursor: this.#cursor }, () => {
|
|
22
|
+
this.#attachments.delete(attachment);
|
|
23
|
+
if (this.#attachments.size === 0)
|
|
24
|
+
this.#finishDisposal();
|
|
25
|
+
});
|
|
26
|
+
this.#attachments.add(attachment);
|
|
27
|
+
return attachment;
|
|
28
|
+
}
|
|
29
|
+
advance(value, ops, context) {
|
|
30
|
+
if (this.#closed || this.#retired)
|
|
31
|
+
return;
|
|
32
|
+
this.#value = value;
|
|
33
|
+
this.#cursor += 1;
|
|
34
|
+
if (value === null)
|
|
35
|
+
this.#retired = true;
|
|
36
|
+
const frame = {
|
|
37
|
+
cursor: this.#cursor,
|
|
38
|
+
value,
|
|
39
|
+
ops,
|
|
40
|
+
context,
|
|
41
|
+
};
|
|
42
|
+
for (const attachment of [...this.#attachments])
|
|
43
|
+
attachment.publish(frame);
|
|
44
|
+
}
|
|
45
|
+
closeSession() {
|
|
46
|
+
if (this.#closed)
|
|
47
|
+
return;
|
|
48
|
+
for (const attachment of [...this.#attachments])
|
|
49
|
+
attachment.dispose();
|
|
50
|
+
this.#finishDisposal();
|
|
51
|
+
}
|
|
52
|
+
#finishDisposal() {
|
|
53
|
+
if (this.#closed)
|
|
54
|
+
return;
|
|
55
|
+
this.#closed = true;
|
|
56
|
+
this.#value = null;
|
|
57
|
+
const release = this.#release;
|
|
58
|
+
this.#release = undefined;
|
|
59
|
+
release?.();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
class SessionSourceAttachment {
|
|
63
|
+
snapshot;
|
|
64
|
+
#release;
|
|
65
|
+
#frames = [];
|
|
66
|
+
#listener;
|
|
67
|
+
#activated = false;
|
|
68
|
+
#disposed = false;
|
|
69
|
+
#scheduled = false;
|
|
70
|
+
#delivering = false;
|
|
71
|
+
constructor(snapshot, release) {
|
|
72
|
+
this.snapshot = snapshot;
|
|
73
|
+
this.#release = release;
|
|
74
|
+
}
|
|
75
|
+
activate(listener) {
|
|
76
|
+
if (this.#activated)
|
|
77
|
+
throw new Error("Document state attachment is already active");
|
|
78
|
+
if (this.#disposed)
|
|
79
|
+
throw new Error("Document state attachment is disposed");
|
|
80
|
+
this.#activated = true;
|
|
81
|
+
this.#listener = listener;
|
|
82
|
+
this.#drain();
|
|
83
|
+
}
|
|
84
|
+
publish(frame) {
|
|
85
|
+
if (this.#disposed)
|
|
86
|
+
return;
|
|
87
|
+
this.#frames.push(frame);
|
|
88
|
+
if (!this.#activated || this.#delivering || this.#scheduled)
|
|
89
|
+
return;
|
|
90
|
+
this.#scheduled = true;
|
|
91
|
+
queueMicrotask(() => {
|
|
92
|
+
this.#scheduled = false;
|
|
93
|
+
if (this.#disposed)
|
|
94
|
+
return;
|
|
95
|
+
try {
|
|
96
|
+
this.#drain();
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Chord's frame listener contains source-contract failures. Isolate an
|
|
100
|
+
// unexpected direct listener failure to this attachment as well.
|
|
101
|
+
this.dispose();
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
dispose() {
|
|
106
|
+
if (this.#disposed)
|
|
107
|
+
return;
|
|
108
|
+
this.#disposed = true;
|
|
109
|
+
this.#frames.length = 0;
|
|
110
|
+
this.#listener = undefined;
|
|
111
|
+
const release = this.#release;
|
|
112
|
+
this.#release = undefined;
|
|
113
|
+
release?.();
|
|
114
|
+
}
|
|
115
|
+
#drain() {
|
|
116
|
+
const listener = this.#listener;
|
|
117
|
+
if (listener === undefined || this.#delivering || this.#disposed)
|
|
118
|
+
return;
|
|
119
|
+
this.#delivering = true;
|
|
120
|
+
try {
|
|
121
|
+
while (!this.#disposed) {
|
|
122
|
+
const frame = this.#frames.shift();
|
|
123
|
+
if (frame === undefined)
|
|
124
|
+
break;
|
|
125
|
+
listener(frame);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
this.#delivering = false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Serialized exact-frame watch bound to one concrete document incarnation. @internal */
|
|
134
|
+
export class SessionDocumentWatch {
|
|
135
|
+
#detach;
|
|
136
|
+
#closedPromise;
|
|
137
|
+
#pending = [];
|
|
138
|
+
#resolveClosed;
|
|
139
|
+
#value;
|
|
140
|
+
#listener;
|
|
141
|
+
#started = false;
|
|
142
|
+
#scheduled = false;
|
|
143
|
+
#running = false;
|
|
144
|
+
#detached = false;
|
|
145
|
+
#retired = false;
|
|
146
|
+
#end;
|
|
147
|
+
#resolved = false;
|
|
148
|
+
#cancellationSignal;
|
|
149
|
+
#cancellationListener;
|
|
150
|
+
constructor(value, detach) {
|
|
151
|
+
this.#value = value;
|
|
152
|
+
this.#detach = detach;
|
|
153
|
+
this.#closedPromise = new Promise((resolve) => {
|
|
154
|
+
this.#resolveClosed = resolve;
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
get value() {
|
|
158
|
+
return this.#value;
|
|
159
|
+
}
|
|
160
|
+
get closed() {
|
|
161
|
+
return this.#closedPromise;
|
|
162
|
+
}
|
|
163
|
+
start(listener) {
|
|
164
|
+
if (this.#started)
|
|
165
|
+
throw new Error("Document watch is already started");
|
|
166
|
+
if (this.#end !== undefined)
|
|
167
|
+
throw new Error("Document watch is stopped");
|
|
168
|
+
this.#started = true;
|
|
169
|
+
this.#listener = listener;
|
|
170
|
+
if (this.#pending.length > 0)
|
|
171
|
+
this.#schedule();
|
|
172
|
+
}
|
|
173
|
+
stop() {
|
|
174
|
+
this.#terminate({ reason: "stopped" });
|
|
175
|
+
return this.#closedPromise;
|
|
176
|
+
}
|
|
177
|
+
observeCancellation(signal) {
|
|
178
|
+
if (this.#cancellationSignal !== undefined)
|
|
179
|
+
throw new Error("Document watch cancellation is already installed");
|
|
180
|
+
if (this.#end !== undefined)
|
|
181
|
+
return;
|
|
182
|
+
this.#cancellationSignal = signal;
|
|
183
|
+
this.#cancellationListener = () => this.cancel();
|
|
184
|
+
signal.addEventListener("abort", this.#cancellationListener, { once: true });
|
|
185
|
+
if (signal.aborted)
|
|
186
|
+
this.cancel();
|
|
187
|
+
}
|
|
188
|
+
cancel() {
|
|
189
|
+
this.#terminate({ reason: "cancelled" });
|
|
190
|
+
}
|
|
191
|
+
closeSession() {
|
|
192
|
+
this.#terminate({ reason: "session_closed" });
|
|
193
|
+
}
|
|
194
|
+
advance(value, ops, context) {
|
|
195
|
+
if (this.#end !== undefined || this.#retired)
|
|
196
|
+
return;
|
|
197
|
+
if (value === null)
|
|
198
|
+
this.#retired = true;
|
|
199
|
+
if (this.#pending.length >= MAX_PENDING_WATCH_FRAMES) {
|
|
200
|
+
this.#pending.length = 0;
|
|
201
|
+
this.#pending.push({ value, ops: [["r", value]], context });
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
this.#pending.push({ value, ops, context });
|
|
205
|
+
}
|
|
206
|
+
if (this.#started)
|
|
207
|
+
this.#schedule();
|
|
208
|
+
}
|
|
209
|
+
#schedule() {
|
|
210
|
+
if (this.#scheduled || this.#running || this.#end !== undefined)
|
|
211
|
+
return;
|
|
212
|
+
this.#scheduled = true;
|
|
213
|
+
queueMicrotask(() => {
|
|
214
|
+
this.#scheduled = false;
|
|
215
|
+
void this.#drain();
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
async #drain() {
|
|
219
|
+
if (this.#running || this.#end !== undefined || !this.#started) {
|
|
220
|
+
this.#finishIfReady();
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
this.#running = true;
|
|
224
|
+
try {
|
|
225
|
+
while (this.#end === undefined) {
|
|
226
|
+
const frame = this.#pending.shift();
|
|
227
|
+
if (frame === undefined)
|
|
228
|
+
break;
|
|
229
|
+
this.#value = frame.value;
|
|
230
|
+
const deliveryContext = withoutAbortSignal(frame.context);
|
|
231
|
+
try {
|
|
232
|
+
await this.#listener(frame.value, frame.ops, deliveryContext);
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
if (this.#end === undefined) {
|
|
236
|
+
this.#terminate({ reason: "listener_error", error: toError(error) });
|
|
237
|
+
}
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
if (frame.value === null) {
|
|
241
|
+
this.#terminate({ reason: "retired" });
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
finally {
|
|
247
|
+
this.#running = false;
|
|
248
|
+
if (this.#end === undefined && this.#pending.length > 0)
|
|
249
|
+
this.#schedule();
|
|
250
|
+
this.#finishIfReady();
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
#terminate(end) {
|
|
254
|
+
if (this.#end !== undefined)
|
|
255
|
+
return;
|
|
256
|
+
this.#end = end;
|
|
257
|
+
this.#detachNow();
|
|
258
|
+
this.#pending.length = 0;
|
|
259
|
+
this.#finishIfReady();
|
|
260
|
+
}
|
|
261
|
+
#detachNow() {
|
|
262
|
+
if (this.#detached)
|
|
263
|
+
return;
|
|
264
|
+
this.#detached = true;
|
|
265
|
+
this.#detach();
|
|
266
|
+
}
|
|
267
|
+
#finishIfReady() {
|
|
268
|
+
if (this.#resolved || this.#end === undefined)
|
|
269
|
+
return;
|
|
270
|
+
this.#resolved = true;
|
|
271
|
+
if (this.#cancellationSignal !== undefined && this.#cancellationListener !== undefined) {
|
|
272
|
+
this.#cancellationSignal.removeEventListener("abort", this.#cancellationListener);
|
|
273
|
+
}
|
|
274
|
+
this.#resolveClosed(this.#end);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
function toError(error) {
|
|
278
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=observation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observation.js","sourceRoot":"","sources":["../../src/session/observation.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tContext,\n\tReplicatedStateSource,\n\tReplicatedStateSourceAttachment,\n\tReplicatedStateSourceFrame,\n} from \"@earendil-works/chord\";\nimport { withoutAbortSignal } from \"@earendil-works/chord/context\";\nimport type { Op } from \"@earendil-works/chord/delta\";\nimport type { JsonObject, WatchEnd, WatchHandle } from \"../types.ts\";\n\nexport type ObservedDocumentValue = Readonly<JsonObject> | null;\n\n/** Maximum exact committed frames retained behind one unavailable watch listener. */\nconst MAX_PENDING_WATCH_FRAMES = 100;\n\n/** Canonical terminal update for a retired document incarnation. */\nexport const RETIREMENT_OPERATIONS: readonly Op[] = [[\"r\", null]];\n\n/** Session-to-Chord bridge owned one-to-one by one attached document state. @internal */\nexport class SessionDocumentSource implements ReplicatedStateSource<ObservedDocumentValue> {\n\treadonly #attachments = new Set<SessionSourceAttachment>();\n\t#release: (() => void) | undefined;\n\t#value: ObservedDocumentValue;\n\t#cursor = 0;\n\t#retired = false;\n\t#closed = false;\n\n\tconstructor(value: Readonly<JsonObject>, release: () => void) {\n\t\tthis.#value = value;\n\t\tthis.#release = release;\n\t}\n\n\tattach(): ReplicatedStateSourceAttachment<ObservedDocumentValue> {\n\t\tif (this.#closed) throw new Error(\"Document state source is closed\");\n\t\tconst attachment = new SessionSourceAttachment({ value: this.#value, cursor: this.#cursor }, () => {\n\t\t\tthis.#attachments.delete(attachment);\n\t\t\tif (this.#attachments.size === 0) this.#finishDisposal();\n\t\t});\n\t\tthis.#attachments.add(attachment);\n\t\treturn attachment;\n\t}\n\n\tadvance(value: ObservedDocumentValue, ops: readonly Op[], context: Context): void {\n\t\tif (this.#closed || this.#retired) return;\n\t\tthis.#value = value;\n\t\tthis.#cursor += 1;\n\t\tif (value === null) this.#retired = true;\n\t\tconst frame: ReplicatedStateSourceFrame<ObservedDocumentValue> = {\n\t\t\tcursor: this.#cursor,\n\t\t\tvalue,\n\t\t\tops,\n\t\t\tcontext,\n\t\t};\n\t\tfor (const attachment of [...this.#attachments]) attachment.publish(frame);\n\t}\n\n\tcloseSession(): void {\n\t\tif (this.#closed) return;\n\t\tfor (const attachment of [...this.#attachments]) attachment.dispose();\n\t\tthis.#finishDisposal();\n\t}\n\n\t#finishDisposal(): void {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tthis.#value = null;\n\t\tconst release = this.#release;\n\t\tthis.#release = undefined;\n\t\trelease?.();\n\t}\n}\n\nclass SessionSourceAttachment implements ReplicatedStateSourceAttachment<ObservedDocumentValue> {\n\treadonly snapshot: { readonly value: ObservedDocumentValue; readonly cursor: number };\n\t#release: (() => void) | undefined;\n\treadonly #frames: ReplicatedStateSourceFrame<ObservedDocumentValue>[] = [];\n\t#listener: ((frame: ReplicatedStateSourceFrame<ObservedDocumentValue>) => void) | undefined;\n\t#activated = false;\n\t#disposed = false;\n\t#scheduled = false;\n\t#delivering = false;\n\n\tconstructor(snapshot: { readonly value: ObservedDocumentValue; readonly cursor: number }, release: () => void) {\n\t\tthis.snapshot = snapshot;\n\t\tthis.#release = release;\n\t}\n\n\tactivate(listener: (frame: ReplicatedStateSourceFrame<ObservedDocumentValue>) => void): void {\n\t\tif (this.#activated) throw new Error(\"Document state attachment is already active\");\n\t\tif (this.#disposed) throw new Error(\"Document state attachment is disposed\");\n\t\tthis.#activated = true;\n\t\tthis.#listener = listener;\n\t\tthis.#drain();\n\t}\n\n\tpublish(frame: ReplicatedStateSourceFrame<ObservedDocumentValue>): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#frames.push(frame);\n\t\tif (!this.#activated || this.#delivering || this.#scheduled) return;\n\t\tthis.#scheduled = true;\n\t\tqueueMicrotask(() => {\n\t\t\tthis.#scheduled = false;\n\t\t\tif (this.#disposed) return;\n\t\t\ttry {\n\t\t\t\tthis.#drain();\n\t\t\t} catch {\n\t\t\t\t// Chord's frame listener contains source-contract failures. Isolate an\n\t\t\t\t// unexpected direct listener failure to this attachment as well.\n\t\t\t\tthis.dispose();\n\t\t\t}\n\t\t});\n\t}\n\n\tdispose(): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#disposed = true;\n\t\tthis.#frames.length = 0;\n\t\tthis.#listener = undefined;\n\t\tconst release = this.#release;\n\t\tthis.#release = undefined;\n\t\trelease?.();\n\t}\n\n\t#drain(): void {\n\t\tconst listener = this.#listener;\n\t\tif (listener === undefined || this.#delivering || this.#disposed) return;\n\t\tthis.#delivering = true;\n\t\ttry {\n\t\t\twhile (!this.#disposed) {\n\t\t\t\tconst frame = this.#frames.shift();\n\t\t\t\tif (frame === undefined) break;\n\t\t\t\tlistener(frame);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.#delivering = false;\n\t\t}\n\t}\n}\n\ntype WatchFrame = {\n\treadonly value: ObservedDocumentValue;\n\treadonly ops: readonly Op[];\n\treadonly context: Context;\n};\n\n/** Serialized exact-frame watch bound to one concrete document incarnation. @internal */\nexport class SessionDocumentWatch implements WatchHandle<ObservedDocumentValue> {\n\treadonly #detach: () => void;\n\treadonly #closedPromise: Promise<WatchEnd>;\n\treadonly #pending: WatchFrame[] = [];\n\t#resolveClosed!: (end: WatchEnd) => void;\n\t#value: ObservedDocumentValue;\n\t#listener: ((value: ObservedDocumentValue, ops: readonly Op[], context: Context) => Promise<void>) | undefined;\n\t#started = false;\n\t#scheduled = false;\n\t#running = false;\n\t#detached = false;\n\t#retired = false;\n\t#end: WatchEnd | undefined;\n\t#resolved = false;\n\t#cancellationSignal: AbortSignal | undefined;\n\t#cancellationListener: (() => void) | undefined;\n\n\tconstructor(value: Readonly<JsonObject>, detach: () => void) {\n\t\tthis.#value = value;\n\t\tthis.#detach = detach;\n\t\tthis.#closedPromise = new Promise((resolve) => {\n\t\t\tthis.#resolveClosed = resolve;\n\t\t});\n\t}\n\n\tget value(): ObservedDocumentValue {\n\t\treturn this.#value;\n\t}\n\n\tget closed(): Promise<WatchEnd> {\n\t\treturn this.#closedPromise;\n\t}\n\n\tstart(listener: (value: ObservedDocumentValue, ops: readonly Op[], context: Context) => Promise<void>): void {\n\t\tif (this.#started) throw new Error(\"Document watch is already started\");\n\t\tif (this.#end !== undefined) throw new Error(\"Document watch is stopped\");\n\t\tthis.#started = true;\n\t\tthis.#listener = listener;\n\t\tif (this.#pending.length > 0) this.#schedule();\n\t}\n\n\tstop(): Promise<WatchEnd> {\n\t\tthis.#terminate({ reason: \"stopped\" });\n\t\treturn this.#closedPromise;\n\t}\n\n\tobserveCancellation(signal: AbortSignal): void {\n\t\tif (this.#cancellationSignal !== undefined) throw new Error(\"Document watch cancellation is already installed\");\n\t\tif (this.#end !== undefined) return;\n\t\tthis.#cancellationSignal = signal;\n\t\tthis.#cancellationListener = () => this.cancel();\n\t\tsignal.addEventListener(\"abort\", this.#cancellationListener, { once: true });\n\t\tif (signal.aborted) this.cancel();\n\t}\n\n\tcancel(): void {\n\t\tthis.#terminate({ reason: \"cancelled\" });\n\t}\n\n\tcloseSession(): void {\n\t\tthis.#terminate({ reason: \"session_closed\" });\n\t}\n\n\tadvance(value: ObservedDocumentValue, ops: readonly Op[], context: Context): void {\n\t\tif (this.#end !== undefined || this.#retired) return;\n\t\tif (value === null) this.#retired = true;\n\t\tif (this.#pending.length >= MAX_PENDING_WATCH_FRAMES) {\n\t\t\tthis.#pending.length = 0;\n\t\t\tthis.#pending.push({ value, ops: [[\"r\", value]], context });\n\t\t} else {\n\t\t\tthis.#pending.push({ value, ops, context });\n\t\t}\n\t\tif (this.#started) this.#schedule();\n\t}\n\n\t#schedule(): void {\n\t\tif (this.#scheduled || this.#running || this.#end !== undefined) return;\n\t\tthis.#scheduled = true;\n\t\tqueueMicrotask(() => {\n\t\t\tthis.#scheduled = false;\n\t\t\tvoid this.#drain();\n\t\t});\n\t}\n\n\tasync #drain(): Promise<void> {\n\t\tif (this.#running || this.#end !== undefined || !this.#started) {\n\t\t\tthis.#finishIfReady();\n\t\t\treturn;\n\t\t}\n\t\tthis.#running = true;\n\t\ttry {\n\t\t\twhile (this.#end === undefined) {\n\t\t\t\tconst frame = this.#pending.shift();\n\t\t\t\tif (frame === undefined) break;\n\t\t\t\tthis.#value = frame.value;\n\t\t\t\tconst deliveryContext = withoutAbortSignal(frame.context);\n\t\t\t\ttry {\n\t\t\t\t\tawait this.#listener!(frame.value, frame.ops, deliveryContext);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (this.#end === undefined) {\n\t\t\t\t\t\tthis.#terminate({ reason: \"listener_error\", error: toError(error) });\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (frame.value === null) {\n\t\t\t\t\tthis.#terminate({ reason: \"retired\" });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.#running = false;\n\t\t\tif (this.#end === undefined && this.#pending.length > 0) this.#schedule();\n\t\t\tthis.#finishIfReady();\n\t\t}\n\t}\n\n\t#terminate(end: WatchEnd): void {\n\t\tif (this.#end !== undefined) return;\n\t\tthis.#end = end;\n\t\tthis.#detachNow();\n\t\tthis.#pending.length = 0;\n\t\tthis.#finishIfReady();\n\t}\n\n\t#detachNow(): void {\n\t\tif (this.#detached) return;\n\t\tthis.#detached = true;\n\t\tthis.#detach();\n\t}\n\n\t#finishIfReady(): void {\n\t\tif (this.#resolved || this.#end === undefined) return;\n\t\tthis.#resolved = true;\n\t\tif (this.#cancellationSignal !== undefined && this.#cancellationListener !== undefined) {\n\t\t\tthis.#cancellationSignal.removeEventListener(\"abort\", this.#cancellationListener);\n\t\t}\n\t\tthis.#resolveClosed(this.#end);\n\t}\n}\n\nfunction toError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n"]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type Context, type JsonValue } from "@earendil-works/chord";
|
|
2
|
+
import type { CommitPublication, ConversationDocFamilyToken, ConversationDocToken, ConversationId, ConversationRecord, DocumentState, DocumentWatch, EntryId, JsonObject, RewindableConversationDocFamilyToken, RewindableConversationDocToken, Session, SessionDocFamilyToken, SessionDocToken, Storage, TaskDocFamilyToken, TaskDocToken, TaskId, Tx } from "../types.ts";
|
|
3
|
+
import { Transaction, type TransactionScope } from "./transaction.ts";
|
|
4
|
+
/** Open a Session kernel over one storage backend. */
|
|
5
|
+
export declare function createSession(storage: Storage): Session;
|
|
6
|
+
/**
|
|
7
|
+
* Session kernel: one mutation line, the loaded document tracker cache, and committed publication.
|
|
8
|
+
*
|
|
9
|
+
* Only committed state is observable. Every commit callback, preparation, Storage settlement, adoption, and
|
|
10
|
+
* publication enqueue runs while the line is held; listeners run later.
|
|
11
|
+
*/
|
|
12
|
+
export declare class SessionImpl implements Session {
|
|
13
|
+
#private;
|
|
14
|
+
constructor(storage: Storage);
|
|
15
|
+
commit<T>(change: (tx: Tx) => T | Promise<T>, context: Context): Promise<T>;
|
|
16
|
+
/**
|
|
17
|
+
* Internal commit exposing the concrete transaction and its internal operations, such as the reserved-ID root
|
|
18
|
+
* bootstrap and task replacement. `scope` sets the default `tx.createTask()` conversation and the task attributed to
|
|
19
|
+
* appended entries.
|
|
20
|
+
*/
|
|
21
|
+
commitWith<T>(change: (tx: Transaction) => T | Promise<T>, context: Context, scope?: TransactionScope): Promise<T>;
|
|
22
|
+
/** Internal: run a read-only job on the mutation line so multi-read derivations observe one committed state. */
|
|
23
|
+
readOnLine<T>(job: () => Promise<T>): Promise<T>;
|
|
24
|
+
snapshot<T extends JsonObject>(token: SessionDocToken<T>, context: Context): Promise<Readonly<T> | undefined>;
|
|
25
|
+
snapshot<T extends JsonObject>(token: ConversationDocToken<T>, conversationId: ConversationId, context: Context): Promise<Readonly<T> | undefined>;
|
|
26
|
+
snapshot<T extends JsonObject>(token: TaskDocToken<T>, taskId: TaskId, context: Context): Promise<Readonly<T> | undefined>;
|
|
27
|
+
snapshot<T extends JsonObject, I extends JsonValue>(token: SessionDocFamilyToken<T, I>, key: string, context: Context): Promise<Readonly<T> | undefined>;
|
|
28
|
+
snapshot<T extends JsonObject, I extends JsonValue>(token: ConversationDocFamilyToken<T, I>, conversationId: ConversationId, key: string, context: Context): Promise<Readonly<T> | undefined>;
|
|
29
|
+
snapshot<T extends JsonObject, I extends JsonValue>(token: TaskDocFamilyToken<T, I>, taskId: TaskId, key: string, context: Context): Promise<Readonly<T> | undefined>;
|
|
30
|
+
documentState<T extends JsonObject>(token: SessionDocToken<T>, context: Context): Promise<DocumentState<T> | undefined>;
|
|
31
|
+
documentState<T extends JsonObject>(token: ConversationDocToken<T>, conversationId: ConversationId, context: Context): Promise<DocumentState<T> | undefined>;
|
|
32
|
+
documentState<T extends JsonObject>(token: TaskDocToken<T>, taskId: TaskId, context: Context): Promise<DocumentState<T> | undefined>;
|
|
33
|
+
documentState<T extends JsonObject, I extends JsonValue>(token: SessionDocFamilyToken<T, I>, key: string, context: Context): Promise<DocumentState<T> | undefined>;
|
|
34
|
+
documentState<T extends JsonObject, I extends JsonValue>(token: ConversationDocFamilyToken<T, I>, conversationId: ConversationId, key: string, context: Context): Promise<DocumentState<T> | undefined>;
|
|
35
|
+
documentState<T extends JsonObject, I extends JsonValue>(token: TaskDocFamilyToken<T, I>, taskId: TaskId, key: string, context: Context): Promise<DocumentState<T> | undefined>;
|
|
36
|
+
watchDoc<T extends JsonObject>(token: SessionDocToken<T>, context: Context): Promise<DocumentWatch<T> | undefined>;
|
|
37
|
+
watchDoc<T extends JsonObject>(token: ConversationDocToken<T>, conversationId: ConversationId, context: Context): Promise<DocumentWatch<T> | undefined>;
|
|
38
|
+
watchDoc<T extends JsonObject>(token: TaskDocToken<T>, taskId: TaskId, context: Context): Promise<DocumentWatch<T> | undefined>;
|
|
39
|
+
watchDoc<T extends JsonObject, I extends JsonValue>(token: SessionDocFamilyToken<T, I>, key: string, context: Context): Promise<DocumentWatch<T> | undefined>;
|
|
40
|
+
watchDoc<T extends JsonObject, I extends JsonValue>(token: ConversationDocFamilyToken<T, I>, conversationId: ConversationId, key: string, context: Context): Promise<DocumentWatch<T> | undefined>;
|
|
41
|
+
watchDoc<T extends JsonObject, I extends JsonValue>(token: TaskDocFamilyToken<T, I>, taskId: TaskId, key: string, context: Context): Promise<DocumentWatch<T> | undefined>;
|
|
42
|
+
snapshotAsOf<T extends JsonObject>(token: RewindableConversationDocToken<T>, conversationId: ConversationId, at: EntryId, context: Context): Promise<Readonly<T> | undefined>;
|
|
43
|
+
snapshotAsOf<T extends JsonObject, I extends JsonValue>(token: RewindableConversationDocFamilyToken<T, I>, conversationId: ConversationId, key: string, at: EntryId, context: Context): Promise<Readonly<T> | undefined>;
|
|
44
|
+
close(context: Context): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Runs inside every transaction that creates or forks a conversation, after the conversation record is staged. A
|
|
47
|
+
* plain Session stages nothing; a Harness stages its built-in documents.
|
|
48
|
+
*/
|
|
49
|
+
protected conversationCreated(_tx: Transaction, _record: ConversationRecord): Promise<void>;
|
|
50
|
+
/** Runs after close seals admission and before the line closes Storage; must not reject. */
|
|
51
|
+
protected beforeClose(): Promise<void>;
|
|
52
|
+
/** Register a synchronous post-adoption listener. It must not throw, block, or call Session operations. */
|
|
53
|
+
subscribeCommits(listener: (publication: CommitPublication, context: Context) => void): () => void;
|
|
54
|
+
/** Register a listener called synchronously when close begins. It must not throw, block, or call Session operations. */
|
|
55
|
+
subscribeClose(listener: () => void): () => void;
|
|
56
|
+
/** Drop every loaded tracker on the mutation line; later access cold-loads from Storage. */
|
|
57
|
+
unloadDocuments(): Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session/session.ts"],"names":[],"mappings":"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"}
|