@earendil-works/pi-durable 1.1.0 → 1.2.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/CHANGELOG.md +40 -0
- package/README.md +147 -11
- package/dist/codemode/codemode.d.ts +173 -0
- package/dist/codemode/codemode.d.ts.map +1 -0
- package/dist/codemode/codemode.js +886 -0
- package/dist/codemode/codemode.js.map +1 -0
- package/dist/codemode/describe.d.ts +38 -0
- package/dist/codemode/describe.d.ts.map +1 -0
- package/dist/codemode/describe.js +119 -0
- package/dist/codemode/describe.js.map +1 -0
- package/dist/codemode/index.d.ts +3 -0
- package/dist/codemode/index.d.ts.map +1 -0
- package/dist/codemode/index.js +3 -0
- package/dist/codemode/index.js.map +1 -0
- package/dist/codemode/models.d.ts +28 -0
- package/dist/codemode/models.d.ts.map +1 -0
- package/dist/codemode/models.js +231 -0
- package/dist/codemode/models.js.map +1 -0
- package/dist/codemode/output.d.ts +41 -0
- package/dist/codemode/output.d.ts.map +1 -0
- package/dist/codemode/output.js +167 -0
- package/dist/codemode/output.js.map +1 -0
- package/dist/env/index.d.ts +42 -0
- package/dist/env/index.d.ts.map +1 -1
- package/dist/env/index.js.map +1 -1
- package/dist/errors.d.ts +20 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +34 -5
- package/dist/errors.js.map +1 -1
- package/dist/harness/agent.d.ts +5 -2
- package/dist/harness/agent.d.ts.map +1 -1
- package/dist/harness/agent.js +69 -25
- package/dist/harness/agent.js.map +1 -1
- package/dist/harness/compaction.d.ts +6 -1
- package/dist/harness/compaction.d.ts.map +1 -1
- package/dist/harness/compaction.js +10 -7
- package/dist/harness/compaction.js.map +1 -1
- package/dist/harness/events.d.ts +35 -15
- package/dist/harness/events.d.ts.map +1 -1
- package/dist/harness/events.js +77 -23
- package/dist/harness/events.js.map +1 -1
- package/dist/harness/generation.d.ts +2 -0
- package/dist/harness/generation.d.ts.map +1 -1
- package/dist/harness/generation.js +31 -8
- package/dist/harness/generation.js.map +1 -1
- package/dist/harness/harness.d.ts +7 -0
- package/dist/harness/harness.d.ts.map +1 -1
- package/dist/harness/harness.js +53 -26
- package/dist/harness/harness.js.map +1 -1
- package/dist/harness/inbox.d.ts +16 -4
- package/dist/harness/inbox.d.ts.map +1 -1
- package/dist/harness/inbox.js +26 -3
- package/dist/harness/inbox.js.map +1 -1
- package/dist/harness/live.d.ts +74 -17
- package/dist/harness/live.d.ts.map +1 -1
- package/dist/harness/live.js +66 -14
- package/dist/harness/live.js.map +1 -1
- package/dist/harness/scheduler.d.ts +18 -5
- package/dist/harness/scheduler.d.ts.map +1 -1
- package/dist/harness/scheduler.js +696 -163
- package/dist/harness/scheduler.js.map +1 -1
- package/dist/harness/submissions.d.ts +7 -4
- package/dist/harness/submissions.d.ts.map +1 -1
- package/dist/harness/submissions.js +32 -13
- package/dist/harness/submissions.js.map +1 -1
- package/dist/harness/task-graph.d.ts +1 -1
- package/dist/harness/task-graph.d.ts.map +1 -1
- package/dist/harness/task-graph.js +15 -10
- package/dist/harness/task-graph.js.map +1 -1
- package/dist/harness/tool.d.ts +45 -5
- package/dist/harness/tool.d.ts.map +1 -1
- package/dist/harness/tool.js +377 -62
- package/dist/harness/tool.js.map +1 -1
- package/dist/harness/types.d.ts +153 -13
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/util.d.ts +6 -1
- package/dist/harness/util.d.ts.map +1 -1
- package/dist/harness/util.js +5 -2
- package/dist/harness/util.js.map +1 -1
- package/dist/harness/view.d.ts +6 -2
- package/dist/harness/view.d.ts.map +1 -1
- package/dist/harness/view.js +22 -12
- package/dist/harness/view.js.map +1 -1
- package/dist/images/cloudflare.d.ts +4 -0
- package/dist/images/cloudflare.d.ts.map +1 -0
- package/dist/images/cloudflare.js +9 -0
- package/dist/images/cloudflare.js.map +1 -0
- package/dist/images/exif.d.ts +3 -0
- package/dist/images/exif.d.ts.map +1 -0
- package/dist/images/exif.js +71 -0
- package/dist/images/exif.js.map +1 -0
- package/dist/images/index.d.ts +18 -0
- package/dist/images/index.d.ts.map +1 -0
- package/dist/images/index.js +125 -0
- package/dist/images/index.js.map +1 -0
- package/dist/images/node-worker.d.ts +17 -0
- package/dist/images/node-worker.d.ts.map +1 -0
- package/dist/images/node-worker.js +16 -0
- package/dist/images/node-worker.js.map +1 -0
- package/dist/images/node.d.ts +21 -0
- package/dist/images/node.d.ts.map +1 -0
- package/dist/images/node.js +121 -0
- package/dist/images/node.js.map +1 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/search.d.ts +13 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +85 -0
- package/dist/search.js.map +1 -0
- package/dist/session/observation.d.ts +10 -3
- package/dist/session/observation.d.ts.map +1 -1
- package/dist/session/observation.js +24 -34
- package/dist/session/observation.js.map +1 -1
- package/dist/session/session.d.ts +68 -5
- package/dist/session/session.d.ts.map +1 -1
- package/dist/session/session.js +461 -49
- package/dist/session/session.js.map +1 -1
- package/dist/session/transaction.d.ts.map +1 -1
- package/dist/session/transaction.js +1 -0
- package/dist/session/transaction.js.map +1 -1
- package/dist/storage/jsonl/storage.d.ts +4 -0
- package/dist/storage/jsonl/storage.d.ts.map +1 -1
- package/dist/storage/jsonl/storage.js +2 -1
- package/dist/storage/jsonl/storage.js.map +1 -1
- package/dist/storage/memory.d.ts.map +1 -1
- package/dist/storage/memory.js +8 -10
- package/dist/storage/memory.js.map +1 -1
- package/dist/storage/scan.d.ts.map +1 -1
- package/dist/storage/scan.js +5 -4
- package/dist/storage/scan.js.map +1 -1
- package/dist/storage/sqlite/storage.d.ts.map +1 -1
- package/dist/storage/sqlite/storage.js +10 -12
- package/dist/storage/sqlite/storage.js.map +1 -1
- package/dist/testing/env-conformance.d.ts.map +1 -1
- package/dist/testing/env-conformance.js +100 -0
- package/dist/testing/env-conformance.js.map +1 -1
- package/dist/testing/runner.d.ts +1 -1
- package/dist/testing/runner.d.ts.map +1 -1
- package/dist/testing/runner.js.map +1 -1
- package/dist/testing/storage-conformance.d.ts.map +1 -1
- package/dist/testing/storage-conformance.js +3 -2
- package/dist/testing/storage-conformance.js.map +1 -1
- package/dist/testing/types.d.ts +2 -0
- package/dist/testing/types.d.ts.map +1 -1
- package/dist/testing/types.js.map +1 -1
- package/dist/tool-search/index.d.ts +2 -0
- package/dist/tool-search/index.d.ts.map +1 -0
- package/dist/tool-search/index.js +2 -0
- package/dist/tool-search/index.js.map +1 -0
- package/dist/tool-search/tool-search.d.ts +23 -0
- package/dist/tool-search/tool-search.d.ts.map +1 -0
- package/dist/tool-search/tool-search.js +84 -0
- package/dist/tool-search/tool-search.js.map +1 -0
- package/dist/tools/bash.d.ts +10 -2
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +27 -9
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit.js +1 -1
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/image-processor.d.ts +47 -0
- package/dist/tools/image-processor.d.ts.map +1 -0
- package/dist/tools/image-processor.js +30 -0
- package/dist/tools/image-processor.js.map +1 -0
- package/dist/tools/image.d.ts +8 -0
- package/dist/tools/image.d.ts.map +1 -1
- package/dist/tools/image.js +47 -0
- package/dist/tools/image.js.map +1 -1
- package/dist/tools/index.d.ts +25 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +13 -5
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/read.d.ts +10 -2
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +87 -28
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/write.js +1 -1
- package/dist/tools/write.js.map +1 -1
- package/dist/types.d.ts +59 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +43 -4
package/dist/search.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BM25 tool search for code mode's `searchTools()` and the `tool_search` tool, a copy of the coding agent's tool search
|
|
3
|
+
* ranking: durable keeps its own copy of what it needs from the coding agent.
|
|
4
|
+
*/
|
|
5
|
+
const STOP_WORDS = new Set([
|
|
6
|
+
"a",
|
|
7
|
+
"an",
|
|
8
|
+
"and",
|
|
9
|
+
"are",
|
|
10
|
+
"as",
|
|
11
|
+
"at",
|
|
12
|
+
"be",
|
|
13
|
+
"by",
|
|
14
|
+
"for",
|
|
15
|
+
"from",
|
|
16
|
+
"in",
|
|
17
|
+
"is",
|
|
18
|
+
"it",
|
|
19
|
+
"of",
|
|
20
|
+
"on",
|
|
21
|
+
"or",
|
|
22
|
+
"that",
|
|
23
|
+
"the",
|
|
24
|
+
"this",
|
|
25
|
+
"to",
|
|
26
|
+
"with",
|
|
27
|
+
]);
|
|
28
|
+
/** Naive singular form, so `issues` matches `issue` and `searches` matches `search`. */
|
|
29
|
+
function stem(term) {
|
|
30
|
+
if (term.length > 4 && term.endsWith("ies"))
|
|
31
|
+
return `${term.slice(0, -3)}y`;
|
|
32
|
+
if (term.length > 4 && /(ches|shes|sses|xes|zes)$/.test(term))
|
|
33
|
+
return term.slice(0, -2);
|
|
34
|
+
if (term.length > 3 && term.endsWith("s") && !term.endsWith("ss"))
|
|
35
|
+
return term.slice(0, -1);
|
|
36
|
+
return term;
|
|
37
|
+
}
|
|
38
|
+
/** Lowercase terms, split at camelCase boundaries and non-alphanumerics, without stop words. */
|
|
39
|
+
export function tokenize(text) {
|
|
40
|
+
return text
|
|
41
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
42
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2")
|
|
43
|
+
.toLowerCase()
|
|
44
|
+
.split(/[^a-z0-9]+/)
|
|
45
|
+
.filter((term) => term.length > 0 && !STOP_WORDS.has(term))
|
|
46
|
+
.map(stem);
|
|
47
|
+
}
|
|
48
|
+
/** Okapi BM25 (k1 1.2, b 0.75): the names of the best matches, best first; ties keep document order. */
|
|
49
|
+
export function rankDocuments(query, documents, limit) {
|
|
50
|
+
const k1 = 1.2;
|
|
51
|
+
const b = 0.75;
|
|
52
|
+
const queryTerms = [...new Set(tokenize(query))];
|
|
53
|
+
if (queryTerms.length === 0 || documents.length === 0 || limit <= 0)
|
|
54
|
+
return [];
|
|
55
|
+
const termCounts = documents.map((document) => {
|
|
56
|
+
const counts = new Map();
|
|
57
|
+
for (const term of tokenize(document.text))
|
|
58
|
+
counts.set(term, (counts.get(term) ?? 0) + 1);
|
|
59
|
+
return counts;
|
|
60
|
+
});
|
|
61
|
+
const lengths = termCounts.map((counts) => [...counts.values()].reduce((sum, count) => sum + count, 0));
|
|
62
|
+
const averageLength = lengths.reduce((sum, length) => sum + length, 0) / documents.length || 1;
|
|
63
|
+
const idf = new Map(queryTerms.map((term) => {
|
|
64
|
+
const frequency = termCounts.filter((counts) => counts.has(term)).length;
|
|
65
|
+
return [term, Math.log(1 + (documents.length - frequency + 0.5) / (frequency + 0.5))];
|
|
66
|
+
}));
|
|
67
|
+
const matches = [];
|
|
68
|
+
documents.forEach((document, index) => {
|
|
69
|
+
let score = 0;
|
|
70
|
+
for (const term of queryTerms) {
|
|
71
|
+
const count = termCounts[index].get(term);
|
|
72
|
+
if (!count)
|
|
73
|
+
continue;
|
|
74
|
+
const norm = k1 * (1 - b + (b * lengths[index]) / averageLength);
|
|
75
|
+
score += (idf.get(term) ?? 0) * ((count * (k1 + 1)) / (count + norm));
|
|
76
|
+
}
|
|
77
|
+
if (score > 0)
|
|
78
|
+
matches.push({ name: document.name, score });
|
|
79
|
+
});
|
|
80
|
+
return matches
|
|
81
|
+
.sort((left, right) => right.score - left.score)
|
|
82
|
+
.slice(0, limit)
|
|
83
|
+
.map((match) => match.name);
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * BM25 tool search for code mode's `searchTools()` and the `tool_search` tool, a copy of the coding agent's tool search\n * ranking: durable keeps its own copy of what it needs from the coding agent.\n */\n\nexport type SearchDocument = { readonly name: string; readonly text: string };\n\nconst STOP_WORDS: ReadonlySet<string> = new Set([\n\t\"a\",\n\t\"an\",\n\t\"and\",\n\t\"are\",\n\t\"as\",\n\t\"at\",\n\t\"be\",\n\t\"by\",\n\t\"for\",\n\t\"from\",\n\t\"in\",\n\t\"is\",\n\t\"it\",\n\t\"of\",\n\t\"on\",\n\t\"or\",\n\t\"that\",\n\t\"the\",\n\t\"this\",\n\t\"to\",\n\t\"with\",\n]);\n\n/** Naive singular form, so `issues` matches `issue` and `searches` matches `search`. */\nfunction stem(term: string): string {\n\tif (term.length > 4 && term.endsWith(\"ies\")) return `${term.slice(0, -3)}y`;\n\tif (term.length > 4 && /(ches|shes|sses|xes|zes)$/.test(term)) return term.slice(0, -2);\n\tif (term.length > 3 && term.endsWith(\"s\") && !term.endsWith(\"ss\")) return term.slice(0, -1);\n\treturn term;\n}\n\n/** Lowercase terms, split at camelCase boundaries and non-alphanumerics, without stop words. */\nexport function tokenize(text: string): string[] {\n\treturn text\n\t\t.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n\t\t.replace(/([A-Z]+)([A-Z][a-z])/g, \"$1 $2\")\n\t\t.toLowerCase()\n\t\t.split(/[^a-z0-9]+/)\n\t\t.filter((term) => term.length > 0 && !STOP_WORDS.has(term))\n\t\t.map(stem);\n}\n\n/** Okapi BM25 (k1 1.2, b 0.75): the names of the best matches, best first; ties keep document order. */\nexport function rankDocuments(query: string, documents: readonly SearchDocument[], limit: number): string[] {\n\tconst k1 = 1.2;\n\tconst b = 0.75;\n\tconst queryTerms = [...new Set(tokenize(query))];\n\tif (queryTerms.length === 0 || documents.length === 0 || limit <= 0) return [];\n\tconst termCounts = documents.map((document) => {\n\t\tconst counts = new Map<string, number>();\n\t\tfor (const term of tokenize(document.text)) counts.set(term, (counts.get(term) ?? 0) + 1);\n\t\treturn counts;\n\t});\n\tconst lengths = termCounts.map((counts) => [...counts.values()].reduce((sum, count) => sum + count, 0));\n\tconst averageLength = lengths.reduce((sum, length) => sum + length, 0) / documents.length || 1;\n\tconst idf = new Map(\n\t\tqueryTerms.map((term) => {\n\t\t\tconst frequency = termCounts.filter((counts) => counts.has(term)).length;\n\t\t\treturn [term, Math.log(1 + (documents.length - frequency + 0.5) / (frequency + 0.5))] as const;\n\t\t}),\n\t);\n\tconst matches: { name: string; score: number }[] = [];\n\tdocuments.forEach((document, index) => {\n\t\tlet score = 0;\n\t\tfor (const term of queryTerms) {\n\t\t\tconst count = termCounts[index]!.get(term);\n\t\t\tif (!count) continue;\n\t\t\tconst norm = k1 * (1 - b + (b * lengths[index]!) / averageLength);\n\t\t\tscore += (idf.get(term) ?? 0) * ((count * (k1 + 1)) / (count + norm));\n\t\t}\n\t\tif (score > 0) matches.push({ name: document.name, score });\n\t});\n\treturn matches\n\t\t.sort((left, right) => right.score - left.score)\n\t\t.slice(0, limit)\n\t\t.map((match) => match.name);\n}\n"]}
|
|
@@ -13,6 +13,7 @@ export declare class CommittedStateSource<T = ObservedDocumentValue> implements
|
|
|
13
13
|
constructor(value: T, release: () => void);
|
|
14
14
|
attach(): ReplicatedStateSourceAttachment<T>;
|
|
15
15
|
advance(value: T, ops: readonly Op[], context: Context): void;
|
|
16
|
+
/** Stop publishing; the attached states keep their last value. A failure ends them the same way. */
|
|
16
17
|
closeSession(): void;
|
|
17
18
|
}
|
|
18
19
|
/**
|
|
@@ -21,15 +22,21 @@ export declare class CommittedStateSource<T = ObservedDocumentValue> implements
|
|
|
21
22
|
*/
|
|
22
23
|
export declare class CommittedWatch<T = ObservedDocumentValue> implements WatchHandle<T> {
|
|
23
24
|
#private;
|
|
24
|
-
/**
|
|
25
|
-
|
|
25
|
+
/**
|
|
26
|
+
* `report` gets a listener's throw, which also ends the watch. `replace` gives the value an overflow delivers; by
|
|
27
|
+
* default the newest value.
|
|
28
|
+
*/
|
|
29
|
+
constructor(value: T, detach: () => void, report: (error: unknown) => void, replace?: () => T);
|
|
26
30
|
get value(): T;
|
|
27
31
|
get closed(): Promise<WatchEnd>;
|
|
28
32
|
start(listener: (value: T, ops: readonly Op[], context: Context) => Promise<void>): void;
|
|
29
33
|
stop(): Promise<WatchEnd>;
|
|
30
34
|
observeCancellation(signal: AbortSignal): void;
|
|
31
35
|
cancel(): void;
|
|
32
|
-
|
|
36
|
+
/** End with `session_closed`, or with `session_failed` and the error when the Session failed. */
|
|
37
|
+
closeSession(failure?: {
|
|
38
|
+
readonly error: unknown;
|
|
39
|
+
}): void;
|
|
33
40
|
advance(value: T, ops: readonly Op[], context: Context): void;
|
|
34
41
|
}
|
|
35
42
|
//# sourceMappingURL=observation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../../src/session/observation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,OAAO,EAEP,qBAAqB,EACrB,+BAA+B,EAE/B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../../src/session/observation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,OAAO,EAEP,qBAAqB,EACrB,+BAA+B,EAE/B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AAEtD,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;;;GAGG;AACH,qBAAa,oBAAoB,CAAC,CAAC,GAAG,qBAAqB,CAAE,YAAW,qBAAqB,CAAC,CAAC,CAAC;;IAS/F,YAAY,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,IAAI,EAGxC;IAED,MAAM,IAAI,+BAA+B,CAAC,CAAC,CAAC,CAQ3C;IAED,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAY5D;IAED,oGAAoG;IACpG,YAAY,IAAI,IAAI,CAInB;CAUD;AA2ED;;;GAGG;AACH,qBAAa,cAAc,CAAC,CAAC,GAAG,qBAAqB,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;;IAiB/E;;;OAGG;IACH,YAAY,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAK5F;IAED,IAAI,KAAK,IAAI,CAAC,CAEb;IAED,IAAI,MAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,CAE9B;IAED,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAMvF;IAED,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,CAGxB;IAED,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAO7C;IAED,MAAM,IAAI,IAAI,CAEb;IAED,iGAAiG;IACjG,YAAY,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAIxD;IAED,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAW5D;CAmDD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { withoutAbortSignal } from "@earendil-works/chord/context";
|
|
2
|
+
import { errorMessage } from "../errors.js";
|
|
2
3
|
/** Maximum exact committed frames retained behind one unavailable watch listener. */
|
|
3
4
|
const MAX_PENDING_WATCH_FRAMES = 100;
|
|
4
5
|
/** Canonical terminal update for a retired document incarnation. */
|
|
@@ -46,6 +47,7 @@ export class CommittedStateSource {
|
|
|
46
47
|
for (const attachment of [...this.#attachments])
|
|
47
48
|
attachment.publish(frame);
|
|
48
49
|
}
|
|
50
|
+
/** Stop publishing; the attached states keep their last value. A failure ends them the same way. */
|
|
49
51
|
closeSession() {
|
|
50
52
|
if (this.#closed)
|
|
51
53
|
return;
|
|
@@ -140,35 +142,35 @@ class SessionSourceAttachment {
|
|
|
140
142
|
*/
|
|
141
143
|
export class CommittedWatch {
|
|
142
144
|
#detach;
|
|
145
|
+
#report;
|
|
143
146
|
#replace;
|
|
144
|
-
#
|
|
147
|
+
#closed = Promise.withResolvers();
|
|
145
148
|
#pending = [];
|
|
146
|
-
#resolveClosed;
|
|
147
149
|
#value;
|
|
148
150
|
#listener;
|
|
149
151
|
#started = false;
|
|
150
152
|
#scheduled = false;
|
|
151
153
|
#running = false;
|
|
152
|
-
#detached = false;
|
|
153
154
|
#retired = false;
|
|
155
|
+
/** Set once, by `#terminate()`. */
|
|
154
156
|
#end;
|
|
155
|
-
#resolved = false;
|
|
156
157
|
#cancellationSignal;
|
|
157
158
|
#cancellationListener;
|
|
158
|
-
/**
|
|
159
|
-
|
|
159
|
+
/**
|
|
160
|
+
* `report` gets a listener's throw, which also ends the watch. `replace` gives the value an overflow delivers; by
|
|
161
|
+
* default the newest value.
|
|
162
|
+
*/
|
|
163
|
+
constructor(value, detach, report, replace) {
|
|
160
164
|
this.#value = value;
|
|
161
165
|
this.#detach = detach;
|
|
166
|
+
this.#report = report;
|
|
162
167
|
this.#replace = replace;
|
|
163
|
-
this.#closedPromise = new Promise((resolve) => {
|
|
164
|
-
this.#resolveClosed = resolve;
|
|
165
|
-
});
|
|
166
168
|
}
|
|
167
169
|
get value() {
|
|
168
170
|
return this.#value;
|
|
169
171
|
}
|
|
170
172
|
get closed() {
|
|
171
|
-
return this.#
|
|
173
|
+
return this.#closed.promise;
|
|
172
174
|
}
|
|
173
175
|
start(listener) {
|
|
174
176
|
if (this.#started)
|
|
@@ -182,7 +184,7 @@ export class CommittedWatch {
|
|
|
182
184
|
}
|
|
183
185
|
stop() {
|
|
184
186
|
this.#terminate({ reason: "stopped" });
|
|
185
|
-
return this.#
|
|
187
|
+
return this.#closed.promise;
|
|
186
188
|
}
|
|
187
189
|
observeCancellation(signal) {
|
|
188
190
|
if (this.#cancellationSignal !== undefined)
|
|
@@ -198,8 +200,9 @@ export class CommittedWatch {
|
|
|
198
200
|
cancel() {
|
|
199
201
|
this.#terminate({ reason: "cancelled" });
|
|
200
202
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
+
/** End with `session_closed`, or with `session_failed` and the error when the Session failed. */
|
|
204
|
+
closeSession(failure) {
|
|
205
|
+
this.#terminate(failure === undefined ? { reason: "session_closed" } : { reason: "session_failed", error: failure.error });
|
|
203
206
|
}
|
|
204
207
|
advance(value, ops, context) {
|
|
205
208
|
if (this.#end !== undefined || this.#retired)
|
|
@@ -227,10 +230,8 @@ export class CommittedWatch {
|
|
|
227
230
|
});
|
|
228
231
|
}
|
|
229
232
|
async #drain() {
|
|
230
|
-
if (this.#running || this.#end !== undefined || !this.#started)
|
|
231
|
-
this.#finishIfReady();
|
|
233
|
+
if (this.#running || this.#end !== undefined || !this.#started)
|
|
232
234
|
return;
|
|
233
|
-
}
|
|
234
235
|
this.#running = true;
|
|
235
236
|
try {
|
|
236
237
|
while (this.#end === undefined) {
|
|
@@ -244,6 +245,7 @@ export class CommittedWatch {
|
|
|
244
245
|
}
|
|
245
246
|
catch (error) {
|
|
246
247
|
if (this.#end === undefined) {
|
|
248
|
+
this.#report(error);
|
|
247
249
|
this.#terminate({ reason: "listener_error", error: toError(error) });
|
|
248
250
|
}
|
|
249
251
|
break;
|
|
@@ -258,34 +260,22 @@ export class CommittedWatch {
|
|
|
258
260
|
this.#running = false;
|
|
259
261
|
if (this.#end === undefined && this.#pending.length > 0)
|
|
260
262
|
this.#schedule();
|
|
261
|
-
this.#finishIfReady();
|
|
262
263
|
}
|
|
263
264
|
}
|
|
265
|
+
/** End the watch, once: detach, drop pending frames, and settle `closed`. A callback already running keeps running. */
|
|
264
266
|
#terminate(end) {
|
|
265
267
|
if (this.#end !== undefined)
|
|
266
268
|
return;
|
|
267
269
|
this.#end = end;
|
|
268
|
-
this.#detachNow();
|
|
269
|
-
this.#pending.length = 0;
|
|
270
|
-
this.#finishIfReady();
|
|
271
|
-
}
|
|
272
|
-
#detachNow() {
|
|
273
|
-
if (this.#detached)
|
|
274
|
-
return;
|
|
275
|
-
this.#detached = true;
|
|
276
270
|
this.#detach();
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
return;
|
|
281
|
-
this.#resolved = true;
|
|
282
|
-
if (this.#cancellationSignal !== undefined && this.#cancellationListener !== undefined) {
|
|
283
|
-
this.#cancellationSignal.removeEventListener("abort", this.#cancellationListener);
|
|
271
|
+
this.#pending.length = 0;
|
|
272
|
+
if (this.#cancellationListener !== undefined) {
|
|
273
|
+
this.#cancellationSignal?.removeEventListener("abort", this.#cancellationListener);
|
|
284
274
|
}
|
|
285
|
-
this.#
|
|
275
|
+
this.#closed.resolve(end);
|
|
286
276
|
}
|
|
287
277
|
}
|
|
288
278
|
function toError(error) {
|
|
289
|
-
return error instanceof Error ? error : new Error(
|
|
279
|
+
return error instanceof Error ? error : new Error(errorMessage(error));
|
|
290
280
|
}
|
|
291
281
|
//# sourceMappingURL=observation.js.map
|
|
@@ -1 +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\tJsonValue,\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/**\n * Session-to-Chord bridge owned one-to-one by one attached state: a document, or a conversation view. A `null` value\n * retires it. @internal\n */\nexport class CommittedStateSource<T = ObservedDocumentValue> implements ReplicatedStateSource<T> {\n\treadonly #attachments = new Set<SessionSourceAttachment<T>>();\n\t#release: (() => void) | undefined;\n\t/** Released on disposal. */\n\t#value: T | undefined;\n\t#cursor = 0;\n\t#retired = false;\n\t#closed = false;\n\n\tconstructor(value: T, release: () => void) {\n\t\tthis.#value = value;\n\t\tthis.#release = release;\n\t}\n\n\tattach(): ReplicatedStateSourceAttachment<T> {\n\t\tif (this.#closed) throw new Error(\"State source is closed\");\n\t\tconst attachment = new SessionSourceAttachment({ value: this.#value as T, 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: T, 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<T> = {\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 = undefined;\n\t\tconst release = this.#release;\n\t\tthis.#release = undefined;\n\t\trelease?.();\n\t}\n}\n\nclass SessionSourceAttachment<T> implements ReplicatedStateSourceAttachment<T> {\n\treadonly snapshot: { readonly value: T; readonly cursor: number };\n\t#release: (() => void) | undefined;\n\treadonly #frames: ReplicatedStateSourceFrame<T>[] = [];\n\t#listener: ((frame: ReplicatedStateSourceFrame<T>) => void) | undefined;\n\t#activated = false;\n\t#disposed = false;\n\t#scheduled = false;\n\t#delivering = false;\n\n\tconstructor(snapshot: { readonly value: T; readonly cursor: number }, release: () => void) {\n\t\tthis.snapshot = snapshot;\n\t\tthis.#release = release;\n\t}\n\n\tactivate(listener: (frame: ReplicatedStateSourceFrame<T>) => void): void {\n\t\tif (this.#activated) throw new Error(\"State attachment is already active\");\n\t\tif (this.#disposed) throw new Error(\"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<T>): 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<T> = {\n\treadonly value: T;\n\treadonly ops: readonly Op[];\n\treadonly context: Context;\n};\n\n/**\n * Serialized exact-frame watch bound to one document incarnation or conversation view. A `null` value retires it.\n * @internal\n */\nexport class CommittedWatch<T = ObservedDocumentValue> implements WatchHandle<T> {\n\treadonly #detach: () => void;\n\treadonly #replace: (() => T) | undefined;\n\treadonly #closedPromise: Promise<WatchEnd>;\n\treadonly #pending: WatchFrame<T>[] = [];\n\t#resolveClosed!: (end: WatchEnd) => void;\n\t#value: T;\n\t#listener: ((value: T, 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\t/** `replace` gives the value an overflow delivers; by default the newest value. */\n\tconstructor(value: T, detach: () => void, replace?: () => T) {\n\t\tthis.#value = value;\n\t\tthis.#detach = detach;\n\t\tthis.#replace = replace;\n\t\tthis.#closedPromise = new Promise((resolve) => {\n\t\t\tthis.#resolveClosed = resolve;\n\t\t});\n\t}\n\n\tget value(): T {\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: T, ops: readonly Op[], context: Context) => Promise<void>): void {\n\t\tif (this.#started) throw new Error(\"Watch is already started\");\n\t\tif (this.#end !== undefined) throw new Error(\"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(\"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: T, 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\tconst replacement = this.#replace?.() ?? value;\n\t\t\tthis.#pending.push({ value: replacement, ops: [[\"r\", replacement as JsonValue]], 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"]}
|
|
1
|
+
{"version":3,"file":"observation.js","sourceRoot":"","sources":["../../src/session/observation.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tContext,\n\tJsonValue,\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 { errorMessage } from \"../errors.ts\";\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/**\n * Session-to-Chord bridge owned one-to-one by one attached state: a document, or a conversation view. A `null` value\n * retires it. @internal\n */\nexport class CommittedStateSource<T = ObservedDocumentValue> implements ReplicatedStateSource<T> {\n\treadonly #attachments = new Set<SessionSourceAttachment<T>>();\n\t#release: (() => void) | undefined;\n\t/** Released on disposal. */\n\t#value: T | undefined;\n\t#cursor = 0;\n\t#retired = false;\n\t#closed = false;\n\n\tconstructor(value: T, release: () => void) {\n\t\tthis.#value = value;\n\t\tthis.#release = release;\n\t}\n\n\tattach(): ReplicatedStateSourceAttachment<T> {\n\t\tif (this.#closed) throw new Error(\"State source is closed\");\n\t\tconst attachment = new SessionSourceAttachment({ value: this.#value as T, 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: T, 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<T> = {\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\t/** Stop publishing; the attached states keep their last value. A failure ends them the same way. */\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 = undefined;\n\t\tconst release = this.#release;\n\t\tthis.#release = undefined;\n\t\trelease?.();\n\t}\n}\n\nclass SessionSourceAttachment<T> implements ReplicatedStateSourceAttachment<T> {\n\treadonly snapshot: { readonly value: T; readonly cursor: number };\n\t#release: (() => void) | undefined;\n\treadonly #frames: ReplicatedStateSourceFrame<T>[] = [];\n\t#listener: ((frame: ReplicatedStateSourceFrame<T>) => void) | undefined;\n\t#activated = false;\n\t#disposed = false;\n\t#scheduled = false;\n\t#delivering = false;\n\n\tconstructor(snapshot: { readonly value: T; readonly cursor: number }, release: () => void) {\n\t\tthis.snapshot = snapshot;\n\t\tthis.#release = release;\n\t}\n\n\tactivate(listener: (frame: ReplicatedStateSourceFrame<T>) => void): void {\n\t\tif (this.#activated) throw new Error(\"State attachment is already active\");\n\t\tif (this.#disposed) throw new Error(\"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<T>): 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<T> = {\n\treadonly value: T;\n\treadonly ops: readonly Op[];\n\treadonly context: Context;\n};\n\n/**\n * Serialized exact-frame watch bound to one document incarnation or conversation view. A `null` value retires it.\n * @internal\n */\nexport class CommittedWatch<T = ObservedDocumentValue> implements WatchHandle<T> {\n\treadonly #detach: () => void;\n\treadonly #report: (error: unknown) => void;\n\treadonly #replace: (() => T) | undefined;\n\treadonly #closed = Promise.withResolvers<WatchEnd>();\n\treadonly #pending: WatchFrame<T>[] = [];\n\t#value: T;\n\t#listener: ((value: T, ops: readonly Op[], context: Context) => Promise<void>) | undefined;\n\t#started = false;\n\t#scheduled = false;\n\t#running = false;\n\t#retired = false;\n\t/** Set once, by `#terminate()`. */\n\t#end: WatchEnd | undefined;\n\t#cancellationSignal: AbortSignal | undefined;\n\t#cancellationListener: (() => void) | undefined;\n\n\t/**\n\t * `report` gets a listener's throw, which also ends the watch. `replace` gives the value an overflow delivers; by\n\t * default the newest value.\n\t */\n\tconstructor(value: T, detach: () => void, report: (error: unknown) => void, replace?: () => T) {\n\t\tthis.#value = value;\n\t\tthis.#detach = detach;\n\t\tthis.#report = report;\n\t\tthis.#replace = replace;\n\t}\n\n\tget value(): T {\n\t\treturn this.#value;\n\t}\n\n\tget closed(): Promise<WatchEnd> {\n\t\treturn this.#closed.promise;\n\t}\n\n\tstart(listener: (value: T, ops: readonly Op[], context: Context) => Promise<void>): void {\n\t\tif (this.#started) throw new Error(\"Watch is already started\");\n\t\tif (this.#end !== undefined) throw new Error(\"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.#closed.promise;\n\t}\n\n\tobserveCancellation(signal: AbortSignal): void {\n\t\tif (this.#cancellationSignal !== undefined) throw new Error(\"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\t/** End with `session_closed`, or with `session_failed` and the error when the Session failed. */\n\tcloseSession(failure?: { readonly error: unknown }): void {\n\t\tthis.#terminate(\n\t\t\tfailure === undefined ? { reason: \"session_closed\" } : { reason: \"session_failed\", error: failure.error },\n\t\t);\n\t}\n\n\tadvance(value: T, 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\tconst replacement = this.#replace?.() ?? value;\n\t\t\tthis.#pending.push({ value: replacement, ops: [[\"r\", replacement as JsonValue]], 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) return;\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.#report(error);\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}\n\t}\n\n\t/** End the watch, once: detach, drop pending frames, and settle `closed`. A callback already running keeps running. */\n\t#terminate(end: WatchEnd): void {\n\t\tif (this.#end !== undefined) return;\n\t\tthis.#end = end;\n\t\tthis.#detach();\n\t\tthis.#pending.length = 0;\n\t\tif (this.#cancellationListener !== undefined) {\n\t\t\tthis.#cancellationSignal?.removeEventListener(\"abort\", this.#cancellationListener);\n\t\t}\n\t\tthis.#closed.resolve(end);\n\t}\n}\n\nfunction toError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(errorMessage(error));\n}\n"]}
|
|
@@ -1,20 +1,56 @@
|
|
|
1
1
|
import { type Context, type JsonValue } from "@earendil-works/chord";
|
|
2
|
-
import type { CommitPublication, ConversationDocFamilyToken, ConversationDocToken, ConversationId, ConversationRecord, DocumentRecord, DocumentState, DocumentWatch, EntryId, JsonObject, RewindableConversationDocFamilyToken, RewindableConversationDocToken, Session, SessionDocFamilyToken, SessionDocToken, Storage, TaskDocFamilyToken, TaskDocToken, TaskId, Tx } from "../types.ts";
|
|
2
|
+
import type { CommitPublication, ConversationDocFamilyToken, ConversationDocToken, ConversationId, ConversationRecord, DocumentRecord, DocumentState, DocumentWatch, EntryId, JsonObject, RewindableConversationDocFamilyToken, RewindableConversationDocToken, Session, SessionDocFamilyToken, SessionDocToken, SessionEnd, Storage, TaskDocFamilyToken, TaskDocToken, TaskId, Tx } from "../types.ts";
|
|
3
3
|
import { Transaction, type TransactionScope } from "./transaction.ts";
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Open a Session kernel over one storage backend. `now` is the wall clock for task times; default `Date.now`. The first
|
|
6
|
+
* error a Storage method throws fails the Session (`SessionFailed`); see `SessionImpl`.
|
|
7
|
+
*/
|
|
5
8
|
export declare function createSession(storage: Storage, options?: {
|
|
6
9
|
readonly now?: () => number;
|
|
10
|
+
readonly documentRetentionMs?: number;
|
|
7
11
|
}): Session;
|
|
12
|
+
/** Internal, for tests: the retention of every Session that keeps the default, as a suite run with eviction at once. */
|
|
13
|
+
export declare function setDefaultDocumentRetention(ms: number): void;
|
|
14
|
+
/**
|
|
15
|
+
* A retention as given, when it is a number of milliseconds, `0` or more (`Infinity` keeps documents); otherwise the
|
|
16
|
+
* default.
|
|
17
|
+
*/
|
|
18
|
+
export declare function documentRetention(ms: number | undefined): number;
|
|
8
19
|
/**
|
|
9
20
|
* Session kernel: one mutation line, the loaded document tracker cache, and committed publication.
|
|
10
21
|
*
|
|
22
|
+
* The cache is bounded by use: a document with no watch or document state attached leaves it once it was not read or
|
|
23
|
+
* written for the retention period, and the next access loads it from Storage. Eviction runs as a job on the mutation
|
|
24
|
+
* line, so no transaction ever holds a tracker that leaves.
|
|
25
|
+
*
|
|
11
26
|
* Only committed state is observable. Every commit callback, preparation, Storage settlement, adoption, and
|
|
12
27
|
* publication enqueue runs while the line is held; listeners run later.
|
|
28
|
+
*
|
|
29
|
+
* Storage failures are final. Every Storage call goes through one guard: the first error a Storage method throws, other
|
|
30
|
+
* than for a cancelled caller, fails the Session, as does a commit it cannot adopt. That call gets the error; every later
|
|
31
|
+
* call and every Storage call still underway gets `SessionFailed`; close listeners run at once with the error, and the
|
|
32
|
+
* Session then closes itself, Storage included, and `closed` settles. Nothing retries: transient errors are the
|
|
33
|
+
* Storage's to retry. Reopening recovers from what was committed.
|
|
13
34
|
*/
|
|
14
35
|
export declare class SessionImpl implements Session {
|
|
15
36
|
#private;
|
|
16
|
-
|
|
37
|
+
get closed(): Promise<SessionEnd>;
|
|
38
|
+
/** Internal: the error that failed the Session, if one did. */
|
|
39
|
+
get failure(): {
|
|
40
|
+
readonly error: unknown;
|
|
41
|
+
} | undefined;
|
|
42
|
+
/** Internal: rejects with `SessionFailed` the moment the Session fails, before work underway has ended; never resolves. */
|
|
43
|
+
get failed(): Promise<never>;
|
|
44
|
+
constructor(storage: Storage, now?: () => number, documentRetentionMs?: () => number | undefined);
|
|
45
|
+
/** The Storage behind the failure guard; every component reads and writes through it. */
|
|
46
|
+
protected get storage(): Storage;
|
|
17
47
|
commit<T>(change: (tx: Tx) => T | Promise<T>, context: Context): Promise<T>;
|
|
48
|
+
/**
|
|
49
|
+
* Internal: fail the Session with `error`, the first wins, and report it once. Admission ends, and close listeners run
|
|
50
|
+
* now; they read the error from `failure`. The Storage guard calls this; the Harness also calls it for a throw in its
|
|
51
|
+
* scheduler's own commits.
|
|
52
|
+
*/
|
|
53
|
+
fail(error: unknown): void;
|
|
18
54
|
/**
|
|
19
55
|
* Internal commit exposing the concrete transaction and its internal operations, such as the reserved-ID root
|
|
20
56
|
* bootstrap and task replacement. `scope` sets the default `tx.createTask()` conversation and the task attributed to
|
|
@@ -53,6 +89,8 @@ export declare class SessionImpl implements Session {
|
|
|
53
89
|
snapshotAsOf<T extends JsonObject>(token: RewindableConversationDocToken<T>, conversationId: ConversationId, at: EntryId, context: Context): Promise<Readonly<T> | undefined>;
|
|
54
90
|
snapshotAsOf<T extends JsonObject, I extends JsonValue>(token: RewindableConversationDocFamilyToken<T, I>, conversationId: ConversationId, key: string, at: EntryId, context: Context): Promise<Readonly<T> | undefined>;
|
|
55
91
|
close(context: Context): Promise<void>;
|
|
92
|
+
/** Internal: the Session's failure, and errors of listeners, which never fail what ran them. A plain Session drops them. */
|
|
93
|
+
report(_error: unknown): void;
|
|
56
94
|
/**
|
|
57
95
|
* Runs inside every transaction that creates or forks a conversation, after the conversation record is staged. A
|
|
58
96
|
* plain Session stages nothing; a Harness stages its built-in documents.
|
|
@@ -60,11 +98,36 @@ export declare class SessionImpl implements Session {
|
|
|
60
98
|
protected conversationCreated(_tx: Transaction, _record: ConversationRecord): Promise<void>;
|
|
61
99
|
/** Runs after close seals admission and before the line closes Storage; must not reject. */
|
|
62
100
|
protected beforeClose(): Promise<void>;
|
|
63
|
-
/** Register a synchronous post-adoption listener. It must not
|
|
101
|
+
/** Register a synchronous post-adoption listener. It must not block or call Session operations; a throw is reported. */
|
|
64
102
|
subscribeCommits(listener: (publication: CommitPublication, context: Context) => void): () => void;
|
|
65
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* Internal: `subscribeCommits()` for the Session's own components, whose state follows each commit. A throw leaves
|
|
105
|
+
* that state behind storage, so it fails the Session instead of being reported. They run before host listeners.
|
|
106
|
+
*/
|
|
107
|
+
observeCommits(listener: (publication: CommitPublication, context: Context) => void): () => void;
|
|
108
|
+
/**
|
|
109
|
+
* Register a listener called synchronously when close begins, also when a failure closes the Session (`failure` is
|
|
110
|
+
* then set). It must not block or call Session operations; a throw is reported.
|
|
111
|
+
*/
|
|
66
112
|
subscribeClose(listener: () => void): () => void;
|
|
67
113
|
/** Drop every loaded tracker on the mutation line; later access cold-loads from Storage. */
|
|
68
114
|
unloadDocuments(): Promise<void>;
|
|
115
|
+
/**
|
|
116
|
+
* Internal, for tests: how many documents the cache holds, how many are idle, how many incarnations are pinned, and how
|
|
117
|
+
* many sweep jobs were queued on the line so far.
|
|
118
|
+
*/
|
|
119
|
+
get documentCacheSizes(): {
|
|
120
|
+
readonly cached: number;
|
|
121
|
+
readonly idle: number;
|
|
122
|
+
readonly attached: number;
|
|
123
|
+
readonly sweeps: number;
|
|
124
|
+
};
|
|
125
|
+
/** Internal: throw `SessionFailed` when failed, else an error when closing. */
|
|
126
|
+
assertUsable(): void;
|
|
69
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Run a host callback that must not fail its caller: a throw, or a promise it returns that rejects, goes to `onError`,
|
|
130
|
+
* which is not awaited.
|
|
131
|
+
*/
|
|
132
|
+
export declare function contained(callback: () => unknown, onError: (error: unknown) => void): void;
|
|
70
133
|
//# sourceMappingURL=session.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAmB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session/session.ts"],"names":[],"mappings":"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"}
|