@milaboratories/pl-client 3.17.6 → 3.18.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/dist/core/client.cjs +5 -3
- package/dist/core/client.cjs.map +1 -1
- package/dist/core/client.d.ts +5 -2
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +6 -4
- package/dist/core/client.js.map +1 -1
- package/dist/core/final.cjs +203 -68
- package/dist/core/final.cjs.map +1 -1
- package/dist/core/final.d.ts +15 -13
- package/dist/core/final.d.ts.map +1 -1
- package/dist/core/final.js +200 -68
- package/dist/core/final.js.map +1 -1
- package/dist/core/finality.cjs +84 -0
- package/dist/core/finality.cjs.map +1 -0
- package/dist/core/finality.d.ts +81 -0
- package/dist/core/finality.d.ts.map +1 -0
- package/dist/core/finality.js +82 -0
- package/dist/core/finality.js.map +1 -0
- package/dist/core/transaction.cjs +4 -4
- package/dist/core/transaction.cjs.map +1 -1
- package/dist/core/transaction.d.ts +7 -3
- package/dist/core/transaction.d.ts.map +1 -1
- package/dist/core/transaction.js +4 -4
- package/dist/core/transaction.js.map +1 -1
- package/dist/index.cjs +7 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/package.json +4 -4
- package/src/core/client.test.ts +38 -0
- package/src/core/client.ts +6 -4
- package/src/core/final.test.ts +175 -0
- package/src/core/final.ts +264 -113
- package/src/core/finality.test.ts +298 -0
- package/src/core/finality.ts +162 -0
- package/src/core/transaction.ts +3 -2
- package/src/index.ts +1 -0
package/dist/core/final.cjs
CHANGED
|
@@ -1,80 +1,215 @@
|
|
|
1
1
|
const require_types = require("./types.cjs");
|
|
2
|
+
const require_finality = require("./finality.cjs");
|
|
2
3
|
let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
|
|
3
4
|
//#region src/core/final.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
5
|
+
const earlyOnFieldErrors = {
|
|
6
|
+
approx: "readyOrDuplicateOrError",
|
|
7
|
+
reason: "HAS_ERRORS is set by an error on any field, the predicate reads the resource error only; an early stop is followed up with a plain fetch"
|
|
8
|
+
};
|
|
9
|
+
const earlyOnFieldErrorsWithOutputs = {
|
|
10
|
+
approx: "readyAndAllOutputsFilled",
|
|
11
|
+
reason: "HAS_ERRORS is set by an error on any field, the predicate reads the resource error only; ALL_OUTPUTS_FINAL, like the predicate, checks every retained field; an early stop is followed up with a plain fetch"
|
|
12
|
+
};
|
|
13
|
+
const value = (name) => ({
|
|
14
|
+
match: { name },
|
|
15
|
+
rule: "always",
|
|
16
|
+
why: "a value, written once at creation"
|
|
17
|
+
});
|
|
18
|
+
const settledAtReady = (name, why) => ({
|
|
19
|
+
match: { name },
|
|
20
|
+
rule: "readyOrDuplicateOrError",
|
|
21
|
+
why,
|
|
22
|
+
stopRule: earlyOnFieldErrors
|
|
23
|
+
});
|
|
24
|
+
const never = (match, why) => ({
|
|
25
|
+
match,
|
|
26
|
+
rule: "never",
|
|
27
|
+
why
|
|
28
|
+
});
|
|
29
|
+
/** The base layer: nothing observable (state, fields, KV) changes after the rule holds, whatever
|
|
30
|
+
* the consumer prunes. Exceptions: the data-loss error cascade, the `hasOriginalListeners` flag,
|
|
31
|
+
* and the writes its entries name. */
|
|
32
|
+
const StrictFinality = require_finality.FinalityTable.of("strict", [
|
|
33
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.JsonObject),
|
|
34
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.JsonGzObject),
|
|
35
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.JsonString),
|
|
36
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.JsonArray),
|
|
37
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.JsonNumber),
|
|
38
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.JsonBool),
|
|
39
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.JsonNull),
|
|
40
|
+
{
|
|
41
|
+
match: { name: _milaboratories_pl_model_common.ResourceTypeName.JsonErrorTrace },
|
|
42
|
+
rule: "always",
|
|
43
|
+
why: "an error-trace snapshot, populated and locked in its creating transaction"
|
|
44
|
+
},
|
|
45
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.BContextEnd),
|
|
46
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.FrontendFromUrl),
|
|
47
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.FrontendFromFolder),
|
|
48
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.FrontendFromLocalTgz),
|
|
49
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.BObjectSpec),
|
|
50
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.Null),
|
|
51
|
+
value(_milaboratories_pl_model_common.ResourceTypeName.Binary),
|
|
52
|
+
{
|
|
53
|
+
match: { name: _milaboratories_pl_model_common.ResourceTypeName.JsonResourceError },
|
|
54
|
+
rule: { custom: (r) => r.type.version === "1" },
|
|
55
|
+
why: "version 1 is a value, written once at creation",
|
|
56
|
+
stopRule: {
|
|
57
|
+
approx: "always",
|
|
58
|
+
reason: "a stop rule cannot see the type version"
|
|
24
59
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
match: { prefix: _milaboratories_pl_model_common.ResourceTypePrefix.LS },
|
|
63
|
+
rule: "always",
|
|
64
|
+
why: "no write after creation"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
match: { prefix: _milaboratories_pl_model_common.ResourceTypePrefix.WorkingDirectory },
|
|
68
|
+
rule: "always",
|
|
69
|
+
why: "no write after creation"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
match: { prefix: _milaboratories_pl_model_common.ResourceTypePrefix.StorageSpaceAllocation },
|
|
73
|
+
rule: "always",
|
|
74
|
+
why: "no write after creation"
|
|
75
|
+
},
|
|
76
|
+
...[
|
|
77
|
+
_milaboratories_pl_model_common.ResourceTypeName.StdMap,
|
|
78
|
+
_milaboratories_pl_model_common.ResourceTypeName.StdMapSlash,
|
|
79
|
+
_milaboratories_pl_model_common.ResourceTypeName.EphStdMap,
|
|
80
|
+
_milaboratories_pl_model_common.ResourceTypeName.PFrame,
|
|
81
|
+
_milaboratories_pl_model_common.ResourceTypeName.ParquetChunk,
|
|
82
|
+
_milaboratories_pl_model_common.ResourceTypeName.BContext,
|
|
83
|
+
_milaboratories_pl_model_common.ResourceTypeName.BinaryMap,
|
|
84
|
+
_milaboratories_pl_model_common.ResourceTypeName.BinaryValue,
|
|
85
|
+
_milaboratories_pl_model_common.ResourceTypeName.BlobMap,
|
|
86
|
+
_milaboratories_pl_model_common.ResourceTypeName.BResolveSingleNoResult,
|
|
87
|
+
_milaboratories_pl_model_common.ResourceTypeName.BQueryResult,
|
|
88
|
+
_milaboratories_pl_model_common.ResourceTypeName.TengoLib
|
|
89
|
+
].map((name) => settledAtReady(name, "its inputs are final at ready, and no controller fills it afterwards")),
|
|
90
|
+
...[
|
|
91
|
+
_milaboratories_pl_model_common.ResourceTypeName.TengoTemplate,
|
|
92
|
+
_milaboratories_pl_model_common.ResourceTypeName.SoftwareInfo,
|
|
93
|
+
_milaboratories_pl_model_common.ResourceTypeName.BlockPackCustom
|
|
94
|
+
].map((name) => settledAtReady(name, "its only later write is the `hasOriginalListeners` flag its first duplicate sets")),
|
|
95
|
+
settledAtReady(_milaboratories_pl_model_common.ResourceTypeName.Dummy, "its only later write is a data-loss error from the Blob whose incarnation field holds it"),
|
|
96
|
+
{
|
|
97
|
+
match: { prefix: _milaboratories_pl_model_common.ResourceTypePrefix.PColumnData },
|
|
98
|
+
rule: "readyOrDuplicateOrError",
|
|
99
|
+
why: "its inputs are final at ready, and no controller fills it afterwards",
|
|
100
|
+
stopRule: earlyOnFieldErrors
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
match: { prefix: _milaboratories_pl_model_common.ResourceTypePrefix.StreamWorkdir },
|
|
104
|
+
rule: "readyOrDuplicateOrError",
|
|
105
|
+
why: "no write after ready",
|
|
106
|
+
stopRule: {
|
|
107
|
+
approx: "readyOrDuplicateOrError",
|
|
108
|
+
reason: "HAS_ERRORS is set by an error on any field; on ResourceTree walks the project field filter also removes every field, `resourceError` included, before decoding, so the predicate cannot see an error the filter stops on; an early stop is followed up with a plain fetch"
|
|
70
109
|
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
match: { name: _milaboratories_pl_model_common.ResourceTypeName.BResolveSingle },
|
|
113
|
+
rule: "readyAndAllOutputsFilled",
|
|
114
|
+
why: "outputs are locked at creation and assigned after ready, never overwritten; one exception: a later context with more than one match sets an error on a resolver that already succeeded, and a reader holding it final misses that error",
|
|
115
|
+
stopRule: earlyOnFieldErrorsWithOutputs
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
match: { name: _milaboratories_pl_model_common.ResourceTypeName.BResolveChoice },
|
|
119
|
+
rule: "readyAndAllOutputsFilled",
|
|
120
|
+
why: "outputs are locked at creation and point at result maps that are completed and locked as resolution finishes",
|
|
121
|
+
stopRule: earlyOnFieldErrorsWithOutputs
|
|
122
|
+
},
|
|
123
|
+
never({ name: _milaboratories_pl_model_common.ResourceTypeName.UserProject }, "blocks and fields come and go over its life"),
|
|
124
|
+
never({ name: _milaboratories_pl_model_common.ResourceTypeName.Projects }, "projects are added and removed"),
|
|
125
|
+
never({ name: _milaboratories_pl_model_common.ResourceTypeName.ClientRoot }, "its fields are added and removed"),
|
|
126
|
+
...[
|
|
127
|
+
_milaboratories_pl_model_common.ResourceTypeName.SharingOutbox,
|
|
128
|
+
_milaboratories_pl_model_common.ResourceTypeName.SharingState,
|
|
129
|
+
_milaboratories_pl_model_common.ResourceTypeName.SharedEnvelope
|
|
130
|
+
].map((name) => never({ name }, "gains and loses dynamic child fields over its life")),
|
|
131
|
+
never({ name: _milaboratories_pl_model_common.ResourceTypeName.LSProvider }, "its storage fields are rewritten on a controller restart with a changed storage config"),
|
|
132
|
+
never({ name: _milaboratories_pl_model_common.ResourceTypeName.Blob }, "its incarnation field is attached or replaced later"),
|
|
133
|
+
never({ name: _milaboratories_pl_model_common.ResourceTypeName.StreamManager }, "`stream` is reset after an error"),
|
|
134
|
+
never({ prefix: _milaboratories_pl_model_common.ResourceTypePrefix.Blob }, "its `ctl/file/blobInfo` KV is re-pointed later"),
|
|
135
|
+
never({ prefix: _milaboratories_pl_model_common.ResourceTypePrefix.BlobIndex }, "a controller restart writes its `ctl/ctlsdk/bootstrapDone` KV"),
|
|
136
|
+
never({ prefix: _milaboratories_pl_model_common.ResourceTypePrefix.BlobUpload }, "the Reset RPC deletes its `ctl/file/storage/uploadState` KV"),
|
|
137
|
+
never({ prefix: _milaboratories_pl_model_common.ResourceTypePrefix.BlobCopy }, "a controller bootstrap records its `ctl/ctlsdk/bootstrapDone` KV in a separate transaction, which may run after the copy settled"),
|
|
138
|
+
never({ name: _milaboratories_pl_model_common.ResourceTypeName.WorkingDirectory }, "lock acquisition can write its `internal/locks/lockedBy` KV after creation")
|
|
139
|
+
]);
|
|
140
|
+
/** What the transaction resource cache may keep while an entry stays in its LRU. The cache holds
|
|
141
|
+
* state and fields, never KV, so it adds the types whose only later writes are KV. */
|
|
142
|
+
const CacheFinality = StrictFinality.extend("cache", [
|
|
143
|
+
{
|
|
144
|
+
match: { prefix: _milaboratories_pl_model_common.ResourceTypePrefix.Blob },
|
|
145
|
+
rule: "always",
|
|
146
|
+
why: "`ctl/file/blobInfo` is re-pointed for the same content: the cache holds no KV, and a tree reads only its `sizeBytes`, invariant for the same content"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
match: { prefix: _milaboratories_pl_model_common.ResourceTypePrefix.BlobIndex },
|
|
150
|
+
rule: "readyAndAllOutputsFilled",
|
|
151
|
+
why: "`ctl/ctlsdk/bootstrapDone` is backend bookkeeping KV; no client reads it",
|
|
152
|
+
stopRule: earlyOnFieldErrorsWithOutputs
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
match: { prefix: _milaboratories_pl_model_common.ResourceTypePrefix.BlobUpload },
|
|
156
|
+
rule: "readyAndAllOutputsFilled",
|
|
157
|
+
why: "`ctl/file/storage/uploadState` is backend bookkeeping KV; no client reads it",
|
|
158
|
+
stopRule: earlyOnFieldErrorsWithOutputs
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
match: { prefix: _milaboratories_pl_model_common.ResourceTypePrefix.BlobCopy },
|
|
162
|
+
rule: "readyAndAllOutputsFilled",
|
|
163
|
+
why: "outputs are locked at creation; the only later write, the bootstrap's `ctl/ctlsdk/bootstrapDone`, is backend bookkeeping KV; no client reads it",
|
|
164
|
+
stopRule: earlyOnFieldErrorsWithOutputs
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
match: { name: _milaboratories_pl_model_common.ResourceTypeName.WorkingDirectory },
|
|
168
|
+
rule: "always",
|
|
169
|
+
why: "the lock KV is backend bookkeeping; no client reads it"
|
|
71
170
|
}
|
|
72
|
-
|
|
73
|
-
|
|
171
|
+
]);
|
|
172
|
+
function streamSwitchedOrErrored(r) {
|
|
173
|
+
if (!require_finality.readyOrDuplicateOrError(r)) return false;
|
|
174
|
+
if (r.fields === void 0) return true;
|
|
175
|
+
if (require_types.isNotNullSignedResourceId(r.error)) return true;
|
|
176
|
+
const downloadable = r.fields.find((f) => f.name === "downloadable");
|
|
177
|
+
const stream = r.fields.find((f) => f.name === "stream");
|
|
178
|
+
if (downloadable === void 0 || stream === void 0 || require_types.isNullSignedResourceId(stream.value)) return false;
|
|
179
|
+
return stream.value === downloadable.value;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* The finality of trees, and the default of `PlClient.finalPredicate`: a resource it calls final
|
|
183
|
+
* leaves the refresh seeds, later bodies for it are ignored, and its mutable-state change sources
|
|
184
|
+
* are retired. It adds Blob and StreamManager under reader assumptions stated at each entry; a
|
|
185
|
+
* consumer that reads what they exclude passes its own predicate.
|
|
186
|
+
*/
|
|
187
|
+
const TreeFinality = CacheFinality.extend("tree", [{
|
|
188
|
+
match: { name: _milaboratories_pl_model_common.ResourceTypeName.Blob },
|
|
189
|
+
rule: "always",
|
|
190
|
+
why: "the incarnation field is replaced later; the project tree prunes Blob's fields, and the drivers read a blob by id, never through its fields",
|
|
191
|
+
requiresPruning: {
|
|
192
|
+
type: _milaboratories_pl_model_common.ResourceTypeName.Blob,
|
|
193
|
+
fields: "all"
|
|
194
|
+
}
|
|
195
|
+
}, {
|
|
196
|
+
match: { name: _milaboratories_pl_model_common.ResourceTypeName.StreamManager },
|
|
197
|
+
rule: { custom: streamSwitchedOrErrored },
|
|
198
|
+
why: "after an error `stream` is reset in a later transaction; default traversal raises the error before exposing the fields, so only an `ignoreError` read sees `stream`",
|
|
199
|
+
stopRule: {
|
|
200
|
+
approx: "readyOrDuplicateOrError",
|
|
201
|
+
reason: "a stop rule cannot compare two fields, so it stops before `stream` switches"
|
|
202
|
+
}
|
|
203
|
+
}]);
|
|
204
|
+
/** @deprecated use {@link TreeFinality} */
|
|
205
|
+
const DefaultFinalResourceDataPredicate = TreeFinality.predicate();
|
|
74
206
|
//#endregion
|
|
207
|
+
exports.CacheFinality = CacheFinality;
|
|
75
208
|
exports.DefaultFinalResourceDataPredicate = DefaultFinalResourceDataPredicate;
|
|
76
209
|
exports.ResourceTypeName = _milaboratories_pl_model_common.ResourceTypeName;
|
|
77
210
|
exports.ResourceTypePrefix = _milaboratories_pl_model_common.ResourceTypePrefix;
|
|
78
|
-
exports.
|
|
211
|
+
exports.StrictFinality = StrictFinality;
|
|
212
|
+
exports.TreeFinality = TreeFinality;
|
|
213
|
+
exports.readyOrDuplicateOrError = require_finality.readyOrDuplicateOrError;
|
|
79
214
|
|
|
80
215
|
//# sourceMappingURL=final.cjs.map
|
package/dist/core/final.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"final.cjs","names":["isNotNullSignedResourceId","isNullSignedResourceId","ResourceTypeName","getField","ResourceTypePrefix"],"sources":["../../src/core/final.ts"],"sourcesContent":["import type { Optional } from \"utility-types\";\nimport type { BasicResourceData, ResourceData } from \"./types\";\nimport { getField, isNotNullSignedResourceId, isNullSignedResourceId } from \"./types\";\nimport { ResourceTypeName, ResourceTypePrefix } from \"@milaboratories/pl-model-common\";\nexport { ResourceTypeName, ResourceTypePrefix };\n\n/**\n * Function is used to guide multiple layers of caching in pl-client and derived pl-tree.\n *\n * This function defines expected resource-specific state mutation behaviour,\n * if it returns true, system will expect that this data will never change as long as resource exist.\n *\n * If resource data contain information about fields, if should be taken into account, fields are undefined,\n * \"final\" state should be calculated for \"basic\" part of resource data only.\n */\nexport type FinalResourceDataPredicate = (\n resourceData: Optional<ResourceData, \"fields\">,\n) => boolean;\n\nexport function readyOrDuplicateOrError(r: ResourceData | BasicResourceData): boolean {\n return (\n r.resourceReady ||\n isNotNullSignedResourceId(r.originalResourceId) ||\n isNotNullSignedResourceId(r.error)\n );\n}\n\nfunction readyAndHasAllOutputsFilled(r: Optional<ResourceData, \"fields\">): boolean {\n if (!readyOrDuplicateOrError(r)) return false;\n if (!r.outputsLocked) return false;\n if (r.fields === undefined) return true; // if fields are not provided basic resource state is not expected to change in the future\n for (const f of r.fields)\n if (isNullSignedResourceId(f.error) && (isNullSignedResourceId(f.value) || !f.valueIsFinal))\n return false;\n return true;\n}\n\n// solely for logging\nconst unknownResourceTypeNames = new Set<string>();\n\n/** Default implementation, defining behaviour for built-in resource types. */\nexport const DefaultFinalResourceDataPredicate: FinalResourceDataPredicate = (r): boolean => {\n switch (r.type.name) {\n case ResourceTypeName.StreamManager: {\n if (!readyOrDuplicateOrError(r)) return false;\n if (r.fields === undefined) return true; // if fields are not provided basic resource state is not expected to change in the future\n if (isNotNullSignedResourceId(r.error)) return true;\n const downloadable = getField(r as ResourceData, \"downloadable\");\n const stream = getField(r as ResourceData, \"stream\");\n return stream.value === downloadable.value; // it's equal to the resource is marked as final on backend side\n }\n case ResourceTypeName.StdMap:\n case ResourceTypeName.StdMapSlash:\n case ResourceTypeName.EphStdMap:\n case ResourceTypeName.PFrame:\n case ResourceTypeName.ParquetChunk:\n case ResourceTypeName.BContext:\n case ResourceTypeName.BlockPackCustom:\n case ResourceTypeName.BinaryMap:\n case ResourceTypeName.BinaryValue:\n case ResourceTypeName.BlobMap:\n case ResourceTypeName.BResolveSingle:\n case ResourceTypeName.BResolveSingleNoResult:\n case ResourceTypeName.BQueryResult:\n case ResourceTypeName.TengoTemplate:\n case ResourceTypeName.TengoLib:\n case ResourceTypeName.SoftwareInfo:\n case ResourceTypeName.Dummy:\n return readyOrDuplicateOrError(r);\n case ResourceTypeName.JsonResourceError:\n return r.type.version === \"1\";\n case ResourceTypeName.JsonObject:\n case ResourceTypeName.JsonGzObject:\n case ResourceTypeName.JsonString:\n case ResourceTypeName.JsonArray:\n case ResourceTypeName.JsonNumber:\n case ResourceTypeName.BContextEnd:\n case ResourceTypeName.FrontendFromUrl:\n case ResourceTypeName.FrontendFromFolder:\n case ResourceTypeName.BObjectSpec:\n case ResourceTypeName.Blob:\n case ResourceTypeName.Null:\n case ResourceTypeName.Binary:\n case ResourceTypeName.LSProvider:\n case ResourceTypeName.WorkingDirectory:\n return true;\n case ResourceTypeName.UserProject:\n case ResourceTypeName.Projects:\n case ResourceTypeName.ClientRoot:\n // Never final — these sharing resources gain and lose dynamic child fields over their lifetime.\n case ResourceTypeName.SharingOutbox:\n case ResourceTypeName.SharingState:\n case ResourceTypeName.SharedEnvelope:\n return false;\n default:\n if (\n r.type.name.startsWith(ResourceTypePrefix.Blob) ||\n r.type.name.startsWith(ResourceTypePrefix.LS) ||\n r.type.name.startsWith(ResourceTypePrefix.WorkingDirectory) ||\n r.type.name.startsWith(ResourceTypePrefix.StorageSpaceAllocation)\n ) {\n return true;\n } else if (\n r.type.name.startsWith(ResourceTypePrefix.BlobUpload) ||\n r.type.name.startsWith(ResourceTypePrefix.BlobIndex)\n ) {\n return readyAndHasAllOutputsFilled(r);\n } else if (r.type.name.startsWith(ResourceTypePrefix.PColumnData)) {\n return readyOrDuplicateOrError(r);\n } else if (r.type.name.startsWith(ResourceTypePrefix.StreamWorkdir)) {\n return readyOrDuplicateOrError(r);\n } else {\n // Unknown resource type detected\n // Set used to log this message only once\n if (!unknownResourceTypeNames.has(r.type.name)) {\n console.log(\"UNKNOWN RESOURCE TYPE: \" + r.type.name);\n unknownResourceTypeNames.add(r.type.name);\n }\n }\n }\n return false;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"final.cjs","names":["FinalityTable","ResourceTypeName","ResourceTypePrefix","readyOrDuplicateOrError","isNotNullSignedResourceId","isNullSignedResourceId"],"sources":["../../src/core/final.ts"],"sourcesContent":["import { ResourceTypeName, ResourceTypePrefix } from \"@milaboratories/pl-model-common\";\nimport type { FinalityEntry, FinalityStopRule, FinalResourceDataPredicate } from \"./finality\";\nimport { FinalityTable, readyOrDuplicateOrError } from \"./finality\";\nimport { isNotNullSignedResourceId, isNullSignedResourceId } from \"./types\";\nexport { ResourceTypeName, ResourceTypePrefix };\nexport type { FinalResourceDataPredicate } from \"./finality\";\nexport { readyOrDuplicateOrError } from \"./finality\";\n\n// The finality tables, one layer per consumer. Every layer accepts two backend writes after\n// final: a data-loss error cascade, lifting the error of a stored blob found lost or corrupt to\n// the resources built from it, and the first duplicate's `hasOriginalListeners` flag on its\n// original, backend-internal and never on the wire. An entry's `why` names any other write\n// it accepts. A layer adds only the types whose later writes its consumer does not observe.\n\n// Where the backend's filter stops earlier than the predicate. An early stop is safe: the\n// backend sends a body-less stop marker, and the streaming loader fetches every stopped resource\n// it does not hold as final again without stop rules (field filtering and pruning still apply),\n// so the predicate decides on the fetched body.\nconst earlyOnFieldErrors: FinalityStopRule = {\n approx: \"readyOrDuplicateOrError\",\n reason:\n \"HAS_ERRORS is set by an error on any field, the predicate reads the resource error only; \" +\n \"an early stop is followed up with a plain fetch\",\n};\nconst earlyOnFieldErrorsWithOutputs: FinalityStopRule = {\n approx: \"readyAndAllOutputsFilled\",\n reason:\n \"HAS_ERRORS is set by an error on any field, the predicate reads the resource error only; \" +\n \"ALL_OUTPUTS_FINAL, like the predicate, checks every retained field; an early stop is \" +\n \"followed up with a plain fetch\",\n};\n\nconst value = (name: string): FinalityEntry => ({\n match: { name },\n rule: \"always\",\n why: \"a value, written once at creation\",\n});\n\nconst settledAtReady = (name: string, why: string): FinalityEntry => ({\n match: { name },\n rule: \"readyOrDuplicateOrError\",\n why,\n stopRule: earlyOnFieldErrors,\n});\n\nconst never = (match: FinalityEntry[\"match\"], why: string): FinalityEntry => ({\n match,\n rule: \"never\",\n why,\n});\n\n/** The base layer: nothing observable (state, fields, KV) changes after the rule holds, whatever\n * the consumer prunes. Exceptions: the data-loss error cascade, the `hasOriginalListeners` flag,\n * and the writes its entries name. */\nexport const StrictFinality: FinalityTable = FinalityTable.of(\"strict\", [\n value(ResourceTypeName.JsonObject),\n value(ResourceTypeName.JsonGzObject),\n value(ResourceTypeName.JsonString),\n value(ResourceTypeName.JsonArray),\n value(ResourceTypeName.JsonNumber),\n value(ResourceTypeName.JsonBool),\n value(ResourceTypeName.JsonNull),\n {\n match: { name: ResourceTypeName.JsonErrorTrace },\n rule: \"always\",\n why: \"an error-trace snapshot, populated and locked in its creating transaction\",\n },\n value(ResourceTypeName.BContextEnd),\n value(ResourceTypeName.FrontendFromUrl),\n value(ResourceTypeName.FrontendFromFolder),\n value(ResourceTypeName.FrontendFromLocalTgz),\n value(ResourceTypeName.BObjectSpec),\n value(ResourceTypeName.Null),\n value(ResourceTypeName.Binary),\n {\n match: { name: ResourceTypeName.JsonResourceError },\n rule: { custom: (r) => r.type.version === \"1\" },\n why: \"version 1 is a value, written once at creation\",\n stopRule: { approx: \"always\", reason: \"a stop rule cannot see the type version\" },\n },\n { match: { prefix: ResourceTypePrefix.LS }, rule: \"always\", why: \"no write after creation\" },\n {\n match: { prefix: ResourceTypePrefix.WorkingDirectory },\n rule: \"always\",\n why: \"no write after creation\",\n },\n {\n match: { prefix: ResourceTypePrefix.StorageSpaceAllocation },\n rule: \"always\",\n why: \"no write after creation\",\n },\n ...[\n ResourceTypeName.StdMap,\n ResourceTypeName.StdMapSlash,\n ResourceTypeName.EphStdMap,\n ResourceTypeName.PFrame,\n ResourceTypeName.ParquetChunk,\n ResourceTypeName.BContext,\n ResourceTypeName.BinaryMap,\n ResourceTypeName.BinaryValue,\n ResourceTypeName.BlobMap,\n ResourceTypeName.BResolveSingleNoResult,\n ResourceTypeName.BQueryResult,\n ResourceTypeName.TengoLib,\n ].map((name) =>\n settledAtReady(name, \"its inputs are final at ready, and no controller fills it afterwards\"),\n ),\n ...[\n ResourceTypeName.TengoTemplate,\n ResourceTypeName.SoftwareInfo,\n ResourceTypeName.BlockPackCustom,\n ].map((name) =>\n settledAtReady(\n name,\n \"its only later write is the `hasOriginalListeners` flag its first duplicate sets\",\n ),\n ),\n settledAtReady(\n ResourceTypeName.Dummy,\n \"its only later write is a data-loss error from the Blob whose incarnation field holds it\",\n ),\n {\n match: { prefix: ResourceTypePrefix.PColumnData },\n rule: \"readyOrDuplicateOrError\",\n why: \"its inputs are final at ready, and no controller fills it afterwards\",\n stopRule: earlyOnFieldErrors,\n },\n {\n match: { prefix: ResourceTypePrefix.StreamWorkdir },\n rule: \"readyOrDuplicateOrError\",\n why: \"no write after ready\",\n stopRule: {\n approx: \"readyOrDuplicateOrError\",\n reason:\n \"HAS_ERRORS is set by an error on any field; on ResourceTree walks the project field \" +\n \"filter also removes every field, `resourceError` included, before decoding, so the \" +\n \"predicate cannot see an error the filter stops on; an early stop is followed up with \" +\n \"a plain fetch\",\n },\n },\n {\n match: { name: ResourceTypeName.BResolveSingle },\n rule: \"readyAndAllOutputsFilled\",\n why:\n \"outputs are locked at creation and assigned after ready, never overwritten; one \" +\n \"exception: a later context with more than one match sets an error on a resolver that \" +\n \"already succeeded, and a reader holding it final misses that error\",\n stopRule: earlyOnFieldErrorsWithOutputs,\n },\n {\n match: { name: ResourceTypeName.BResolveChoice },\n rule: \"readyAndAllOutputsFilled\",\n why:\n \"outputs are locked at creation and point at result maps that are completed and locked \" +\n \"as resolution finishes\",\n stopRule: earlyOnFieldErrorsWithOutputs,\n },\n never({ name: ResourceTypeName.UserProject }, \"blocks and fields come and go over its life\"),\n never({ name: ResourceTypeName.Projects }, \"projects are added and removed\"),\n never({ name: ResourceTypeName.ClientRoot }, \"its fields are added and removed\"),\n ...[\n ResourceTypeName.SharingOutbox,\n ResourceTypeName.SharingState,\n ResourceTypeName.SharedEnvelope,\n ].map((name) => never({ name }, \"gains and loses dynamic child fields over its life\")),\n never(\n { name: ResourceTypeName.LSProvider },\n \"its storage fields are rewritten on a controller restart with a changed storage config\",\n ),\n never({ name: ResourceTypeName.Blob }, \"its incarnation field is attached or replaced later\"),\n never({ name: ResourceTypeName.StreamManager }, \"`stream` is reset after an error\"),\n never({ prefix: ResourceTypePrefix.Blob }, \"its `ctl/file/blobInfo` KV is re-pointed later\"),\n never(\n { prefix: ResourceTypePrefix.BlobIndex },\n \"a controller restart writes its `ctl/ctlsdk/bootstrapDone` KV\",\n ),\n never(\n { prefix: ResourceTypePrefix.BlobUpload },\n \"the Reset RPC deletes its `ctl/file/storage/uploadState` KV\",\n ),\n never(\n { prefix: ResourceTypePrefix.BlobCopy },\n \"a controller bootstrap records its `ctl/ctlsdk/bootstrapDone` KV in a separate transaction, which may run after the copy settled\",\n ),\n never(\n { name: ResourceTypeName.WorkingDirectory },\n \"lock acquisition can write its `internal/locks/lockedBy` KV after creation\",\n ),\n]);\n\n/** What the transaction resource cache may keep while an entry stays in its LRU. The cache holds\n * state and fields, never KV, so it adds the types whose only later writes are KV. */\nexport const CacheFinality: FinalityTable = StrictFinality.extend(\"cache\", [\n {\n match: { prefix: ResourceTypePrefix.Blob },\n rule: \"always\",\n why:\n \"`ctl/file/blobInfo` is re-pointed for the same content: the cache holds no KV, and a \" +\n \"tree reads only its `sizeBytes`, invariant for the same content\",\n },\n {\n match: { prefix: ResourceTypePrefix.BlobIndex },\n rule: \"readyAndAllOutputsFilled\",\n why: \"`ctl/ctlsdk/bootstrapDone` is backend bookkeeping KV; no client reads it\",\n stopRule: earlyOnFieldErrorsWithOutputs,\n },\n {\n match: { prefix: ResourceTypePrefix.BlobUpload },\n rule: \"readyAndAllOutputsFilled\",\n why: \"`ctl/file/storage/uploadState` is backend bookkeeping KV; no client reads it\",\n stopRule: earlyOnFieldErrorsWithOutputs,\n },\n {\n match: { prefix: ResourceTypePrefix.BlobCopy },\n rule: \"readyAndAllOutputsFilled\",\n why:\n \"outputs are locked at creation; the only later write, the bootstrap's \" +\n \"`ctl/ctlsdk/bootstrapDone`, is backend bookkeeping KV; no client reads it\",\n stopRule: earlyOnFieldErrorsWithOutputs,\n },\n {\n match: { name: ResourceTypeName.WorkingDirectory },\n rule: \"always\",\n why: \"the lock KV is backend bookkeeping; no client reads it\",\n },\n]);\n\nfunction streamSwitchedOrErrored(r: Parameters<FinalResourceDataPredicate>[0]): boolean {\n if (!readyOrDuplicateOrError(r)) return false;\n if (r.fields === undefined) return true;\n if (isNotNullSignedResourceId(r.error)) return true;\n // Fields can be pruned away by the reader: without them nothing proves the switch. The\n // predicate must not throw, since a throw inside a tree update rebuilds the whole tree.\n const downloadable = r.fields.find((f) => f.name === \"downloadable\");\n const stream = r.fields.find((f) => f.name === \"stream\");\n if (downloadable === undefined || stream === undefined || isNullSignedResourceId(stream.value))\n return false;\n // No backend flag marks the switch: equal non-null fields mean the controller's success branch\n // has switched `stream` to the downloadable blob.\n return stream.value === downloadable.value;\n}\n\n/**\n * The finality of trees, and the default of `PlClient.finalPredicate`: a resource it calls final\n * leaves the refresh seeds, later bodies for it are ignored, and its mutable-state change sources\n * are retired. It adds Blob and StreamManager under reader assumptions stated at each entry; a\n * consumer that reads what they exclude passes its own predicate.\n */\nexport const TreeFinality: FinalityTable = CacheFinality.extend(\"tree\", [\n {\n match: { name: ResourceTypeName.Blob },\n rule: \"always\",\n why:\n \"the incarnation field is replaced later; the project tree prunes Blob's fields, and the \" +\n \"drivers read a blob by id, never through its fields\",\n requiresPruning: { type: ResourceTypeName.Blob, fields: \"all\" },\n },\n {\n match: { name: ResourceTypeName.StreamManager },\n rule: { custom: streamSwitchedOrErrored },\n why:\n \"after an error `stream` is reset in a later transaction; default traversal raises the \" +\n \"error before exposing the fields, so only an `ignoreError` read sees `stream`\",\n stopRule: {\n approx: \"readyOrDuplicateOrError\",\n reason: \"a stop rule cannot compare two fields, so it stops before `stream` switches\",\n },\n },\n]);\n\n/** @deprecated use {@link TreeFinality} */\nexport const DefaultFinalResourceDataPredicate: FinalResourceDataPredicate =\n TreeFinality.predicate();\n"],"mappings":"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"}
|
package/dist/core/final.d.ts
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FinalResourceDataPredicate, FinalityTable, readyOrDuplicateOrError } from "./finality.js";
|
|
2
2
|
import { ResourceTypeName, ResourceTypePrefix } from "@milaboratories/pl-model-common";
|
|
3
|
-
import { Optional } from "utility-types";
|
|
4
3
|
//#region src/core/final.d.ts
|
|
4
|
+
/** The base layer: nothing observable (state, fields, KV) changes after the rule holds, whatever
|
|
5
|
+
* the consumer prunes. Exceptions: the data-loss error cascade, the `hasOriginalListeners` flag,
|
|
6
|
+
* and the writes its entries name. */
|
|
7
|
+
export declare const StrictFinality: FinalityTable;
|
|
8
|
+
/** What the transaction resource cache may keep while an entry stays in its LRU. The cache holds
|
|
9
|
+
* state and fields, never KV, so it adds the types whose only later writes are KV. */
|
|
10
|
+
export declare const CacheFinality: FinalityTable;
|
|
5
11
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* If resource data contain information about fields, if should be taken into account, fields are undefined,
|
|
12
|
-
* "final" state should be calculated for "basic" part of resource data only.
|
|
12
|
+
* The finality of trees, and the default of `PlClient.finalPredicate`: a resource it calls final
|
|
13
|
+
* leaves the refresh seeds, later bodies for it are ignored, and its mutable-state change sources
|
|
14
|
+
* are retired. It adds Blob and StreamManager under reader assumptions stated at each entry; a
|
|
15
|
+
* consumer that reads what they exclude passes its own predicate.
|
|
13
16
|
*/
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
/** Default implementation, defining behaviour for built-in resource types. */
|
|
17
|
+
export declare const TreeFinality: FinalityTable;
|
|
18
|
+
/** @deprecated use {@link TreeFinality} */
|
|
17
19
|
export declare const DefaultFinalResourceDataPredicate: FinalResourceDataPredicate;
|
|
18
20
|
//#endregion
|
|
19
|
-
export { ResourceTypeName, ResourceTypePrefix };
|
|
21
|
+
export { type FinalResourceDataPredicate, ResourceTypeName, ResourceTypePrefix, readyOrDuplicateOrError };
|
|
20
22
|
//# sourceMappingURL=final.d.ts.map
|
package/dist/core/final.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"final.d.ts","names":[],"sources":["../../src/core/final.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"final.d.ts","names":[],"sources":["../../src/core/final.ts"],"mappings":";;;;;;qBAsDa,gBAAgB;;;qBA0IhB,eAAe;;;;;;;qBAwDf,cAAc;;qBAuBd,mCAAmC"}
|