@gaganref/confect-test 10.3.1-fork.91 → 10.3.1-fork.93
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/TestConfect.d.ts +26 -0
- package/dist/TestConfect.d.ts.map +1 -1
- package/dist/TestConfect.js +9 -1
- package/dist/TestConfect.js.map +1 -1
- package/dist/internal/Attempt.d.ts +14 -1
- package/dist/internal/Attempt.d.ts.map +1 -1
- package/dist/internal/Attempt.js +18 -1
- package/dist/internal/Attempt.js.map +1 -1
- package/dist/internal/ConvexTest.d.ts +26 -1
- package/dist/internal/ConvexTest.d.ts.map +1 -1
- package/dist/internal/ConvexTest.js +55 -27
- package/dist/internal/ConvexTest.js.map +1 -1
- package/dist/internal/Execution.d.ts +151 -1
- package/dist/internal/Execution.d.ts.map +1 -1
- package/dist/internal/Execution.js +731 -214
- package/dist/internal/Execution.js.map +1 -1
- package/dist/internal/KernelQuery.d.ts +8 -3
- package/dist/internal/KernelQuery.d.ts.map +1 -1
- package/dist/internal/KernelQuery.js +10 -3
- package/dist/internal/KernelQuery.js.map +1 -1
- package/dist/internal/KernelRefusal.d.ts +134 -0
- package/dist/internal/KernelRefusal.d.ts.map +1 -1
- package/dist/internal/KernelRefusal.js +134 -1
- package/dist/internal/KernelRefusal.js.map +1 -1
- package/dist/internal/Metering.d.ts +186 -0
- package/dist/internal/Metering.d.ts.map +1 -0
- package/dist/internal/Metering.js +401 -0
- package/dist/internal/Metering.js.map +1 -0
- package/dist/internal/Redaction.d.ts +142 -0
- package/dist/internal/Redaction.d.ts.map +1 -0
- package/dist/internal/Redaction.js +448 -0
- package/dist/internal/Redaction.js.map +1 -0
- package/dist/internal/Snapshot.d.ts +298 -0
- package/dist/internal/Snapshot.d.ts.map +1 -0
- package/dist/internal/Snapshot.js +532 -0
- package/dist/internal/Snapshot.js.map +1 -0
- package/dist/internal/Subscriptions.d.ts +13 -0
- package/dist/internal/Subscriptions.d.ts.map +1 -1
- package/dist/internal/Subscriptions.js +27 -3
- package/dist/internal/Subscriptions.js.map +1 -1
- package/package.json +3 -3
- package/src/TestConfect.ts +63 -4
- package/src/internal/Attempt.ts +24 -0
- package/src/internal/ConvexTest.ts +135 -38
- package/src/internal/Execution.ts +1141 -324
- package/src/internal/KernelQuery.ts +17 -6
- package/src/internal/KernelRefusal.ts +160 -0
- package/src/internal/Metering.ts +520 -0
- package/src/internal/Redaction.ts +730 -0
- package/src/internal/Snapshot.ts +945 -0
- package/src/internal/Subscriptions.ts +34 -4
|
@@ -99,17 +99,19 @@ export const validateDocument = (
|
|
|
99
99
|
};
|
|
100
100
|
|
|
101
101
|
/**
|
|
102
|
-
* An interval a query reads, before it says where it starts and how far it got
|
|
102
|
+
* An interval a query reads, before it says where it starts and how far it got,
|
|
103
|
+
* and the index it reads it from.
|
|
103
104
|
*/
|
|
104
105
|
export type Interval = Omit<
|
|
105
106
|
ReadSet.IntervalRead,
|
|
106
107
|
"componentPath" | "after" | "through"
|
|
107
|
-
|
|
108
|
+
> & { readonly index: string };
|
|
108
109
|
|
|
109
110
|
/**
|
|
110
111
|
* What a query reads: one table of one component, as the running attempt sees
|
|
111
112
|
* it. `read` records an interval in the attempt's read set and returns how to
|
|
112
|
-
* advance it.
|
|
113
|
+
* advance it. `examine` charges one document the query examined, before the
|
|
114
|
+
* query's filters see it.
|
|
113
115
|
*/
|
|
114
116
|
export interface TableView {
|
|
115
117
|
readonly schema: KernelSchema | null;
|
|
@@ -118,6 +120,7 @@ export interface TableView {
|
|
|
118
120
|
interval: Interval,
|
|
119
121
|
after: ReadSet.Key | null,
|
|
120
122
|
) => (through: ReadSet.Key | "end") => void;
|
|
123
|
+
readonly examine: (table: string, doc: GenericDocument) => void;
|
|
121
124
|
}
|
|
122
125
|
|
|
123
126
|
interface ResolvedSource {
|
|
@@ -138,9 +141,12 @@ const resolveSource = (
|
|
|
138
141
|
let order: "asc" | "desc";
|
|
139
142
|
let table: string;
|
|
140
143
|
let range: ReadonlyArray<SerializedRangeExpression> = [];
|
|
144
|
+
let index: string;
|
|
141
145
|
switch (source.type) {
|
|
142
146
|
case "FullTableScan": {
|
|
143
147
|
table = source.tableName;
|
|
148
|
+
// The binary scans a whole table through its creation-time index.
|
|
149
|
+
index = "by_creation_time";
|
|
144
150
|
docs = [...view.scan(source.tableName)];
|
|
145
151
|
order = source.order ?? "asc";
|
|
146
152
|
fieldPathsToSortBy = ["_creationTime"];
|
|
@@ -152,6 +158,7 @@ const resolveSource = (
|
|
|
152
158
|
string,
|
|
153
159
|
];
|
|
154
160
|
table = tableName;
|
|
161
|
+
index = indexName;
|
|
155
162
|
range = source.range;
|
|
156
163
|
order = source.order ?? "asc";
|
|
157
164
|
let fields: Array<string>;
|
|
@@ -160,18 +167,18 @@ const resolveSource = (
|
|
|
160
167
|
} else if (indexName === "by_id") {
|
|
161
168
|
fields = ["_id"];
|
|
162
169
|
} else {
|
|
163
|
-
const
|
|
170
|
+
const declared = view.schema?.tables
|
|
164
171
|
.get(tableName)
|
|
165
172
|
?.indexes.find(
|
|
166
173
|
({ indexDescriptor }) => indexDescriptor === indexName,
|
|
167
174
|
);
|
|
168
|
-
if (
|
|
175
|
+
if (declared === undefined) {
|
|
169
176
|
throw new Error(
|
|
170
177
|
`Cannot use index "${indexName}" for table "${tableName}" because ` +
|
|
171
178
|
`it is not declared in the schema.`,
|
|
172
179
|
);
|
|
173
180
|
}
|
|
174
|
-
fields =
|
|
181
|
+
fields = declared.fields.concat(["_creationTime", "_id"]);
|
|
175
182
|
}
|
|
176
183
|
fieldPathsToSortBy = fields;
|
|
177
184
|
validateIndexRangeExpression(source, fields);
|
|
@@ -216,6 +223,7 @@ const resolveSource = (
|
|
|
216
223
|
order,
|
|
217
224
|
interval: {
|
|
218
225
|
kind: "interval",
|
|
226
|
+
index,
|
|
219
227
|
table,
|
|
220
228
|
fields: fieldPathsToSortBy.includes("_id")
|
|
221
229
|
? fieldPathsToSortBy
|
|
@@ -241,6 +249,7 @@ export const stream = (
|
|
|
241
249
|
let returned = 0;
|
|
242
250
|
for (const doc of sortedDocs) {
|
|
243
251
|
if (limit !== null && returned >= limit) return;
|
|
252
|
+
view.examine(interval.table, doc);
|
|
244
253
|
examined(ReadSet.keyOf(interval.fields, doc as StoredDocument));
|
|
245
254
|
if (filterFn(doc)) {
|
|
246
255
|
returned++;
|
|
@@ -352,6 +361,7 @@ export const paginate = (
|
|
|
352
361
|
reachedEnd = false;
|
|
353
362
|
examined(endCursorKeys);
|
|
354
363
|
if (cmp === 0) {
|
|
364
|
+
view.examine(interval.table, doc);
|
|
355
365
|
rowsRead += 1;
|
|
356
366
|
bytesRead += getDocumentSize(doc);
|
|
357
367
|
readDocCursors.push(encodeCursor(doc, cursorFields));
|
|
@@ -361,6 +371,7 @@ export const paginate = (
|
|
|
361
371
|
break;
|
|
362
372
|
}
|
|
363
373
|
}
|
|
374
|
+
view.examine(interval.table, doc);
|
|
364
375
|
rowsRead += 1;
|
|
365
376
|
bytesRead += getDocumentSize(doc);
|
|
366
377
|
readDocCursors.push(encodeCursor(doc, cursorFields));
|
|
@@ -110,3 +110,163 @@ export const rowPending = (operation: string, row: number) =>
|
|
|
110
110
|
row,
|
|
111
111
|
message: `The test kernel supplies ${operation} in build-order row ${row}.`,
|
|
112
112
|
});
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Snapshot bytes are not a kernel snapshot this kernel reads: an unknown
|
|
116
|
+
* header, a body that is not the snapshot's JSON, or a value that does not
|
|
117
|
+
* decode.
|
|
118
|
+
*/
|
|
119
|
+
export class SnapshotMalformed extends Schema.TaggedError<SnapshotMalformed>()(
|
|
120
|
+
"SnapshotMalformed",
|
|
121
|
+
{ reason: Schema.String, message: Schema.String },
|
|
122
|
+
) {}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* A snapshot's body does not hash to the digest its header names, so its bytes
|
|
126
|
+
* changed after export.
|
|
127
|
+
*/
|
|
128
|
+
export class SnapshotDigestMismatch extends Schema.TaggedError<SnapshotDigestMismatch>()(
|
|
129
|
+
"SnapshotDigestMismatch",
|
|
130
|
+
{ expected: Schema.String, actual: Schema.String, message: Schema.String },
|
|
131
|
+
) {}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* A snapshot's components are not the components registered on the world
|
|
135
|
+
* restoring it.
|
|
136
|
+
*/
|
|
137
|
+
export class SnapshotComponentMismatch extends Schema.TaggedError<SnapshotComponentMismatch>()(
|
|
138
|
+
"SnapshotComponentMismatch",
|
|
139
|
+
{
|
|
140
|
+
snapshot: Schema.Array(Schema.String),
|
|
141
|
+
registered: Schema.Array(Schema.String),
|
|
142
|
+
message: Schema.String,
|
|
143
|
+
},
|
|
144
|
+
) {}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* A job's test world is named by no world, or by more than one, so the job
|
|
148
|
+
* could not run under the world that scheduled it.
|
|
149
|
+
*/
|
|
150
|
+
export class SnapshotWorldUnresolved extends Schema.TaggedError<SnapshotWorldUnresolved>()(
|
|
151
|
+
"SnapshotWorldUnresolved",
|
|
152
|
+
{
|
|
153
|
+
name: Schema.String,
|
|
154
|
+
reason: Schema.Literals(["missing", "ambiguous"]),
|
|
155
|
+
message: Schema.String,
|
|
156
|
+
},
|
|
157
|
+
) {}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* A world holds work a snapshot does not carry: attempts held for `apply`, or,
|
|
161
|
+
* when it restores, commits of its own.
|
|
162
|
+
*/
|
|
163
|
+
export class SnapshotWorldBusy extends Schema.TaggedError<SnapshotWorldBusy>()(
|
|
164
|
+
"SnapshotWorldBusy",
|
|
165
|
+
{
|
|
166
|
+
version: Schema.Int,
|
|
167
|
+
held: Schema.Array(Schema.String),
|
|
168
|
+
message: Schema.String,
|
|
169
|
+
},
|
|
170
|
+
) {}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* A snapshot marks a secret the restore was not given, so the raw value its
|
|
174
|
+
* replay needs is not in memory.
|
|
175
|
+
*/
|
|
176
|
+
export class SnapshotSecretMissing extends Schema.TaggedError<SnapshotSecretMissing>()(
|
|
177
|
+
"SnapshotSecretMissing",
|
|
178
|
+
{ ref: Schema.String, message: Schema.String },
|
|
179
|
+
) {}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* A world is running work a snapshot taken or restored now would split: calls
|
|
183
|
+
* from the test, scheduler walks, or function executions, nested and detached
|
|
184
|
+
* ones included.
|
|
185
|
+
*/
|
|
186
|
+
export class SnapshotWorldRunning extends Schema.TaggedError<SnapshotWorldRunning>()(
|
|
187
|
+
"SnapshotWorldRunning",
|
|
188
|
+
{
|
|
189
|
+
registry: Schema.Literals(["running", "walks", "functions"]),
|
|
190
|
+
count: Schema.Int,
|
|
191
|
+
message: Schema.String,
|
|
192
|
+
},
|
|
193
|
+
) {}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* A world has subscribers, whose identity versions a restore would rewind.
|
|
197
|
+
* Subscriptions are live client state, so a restore needs a world with none.
|
|
198
|
+
*/
|
|
199
|
+
export class SnapshotSubscribed extends Schema.TaggedError<SnapshotSubscribed>()(
|
|
200
|
+
"SnapshotSubscribed",
|
|
201
|
+
{ subscribers: Schema.Int, message: Schema.String },
|
|
202
|
+
) {}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* A snapshot's identity counters stand at or behind an identity its state
|
|
206
|
+
* already holds, so the next allocation would reuse one.
|
|
207
|
+
*/
|
|
208
|
+
export class SnapshotAllocatorBehind extends Schema.TaggedError<SnapshotAllocatorBehind>()(
|
|
209
|
+
"SnapshotAllocatorBehind",
|
|
210
|
+
{
|
|
211
|
+
allocator: Schema.Literals([
|
|
212
|
+
"nextDocumentId",
|
|
213
|
+
"lastCreationTime",
|
|
214
|
+
"nextAttemptId",
|
|
215
|
+
"identityEpoch",
|
|
216
|
+
]),
|
|
217
|
+
value: Schema.Finite,
|
|
218
|
+
required: Schema.Finite,
|
|
219
|
+
message: Schema.String,
|
|
220
|
+
},
|
|
221
|
+
) {}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* A snapshot's rows are not what its write log publishes: a row filed under
|
|
225
|
+
* another table or an unregistered component, a version the log does not give
|
|
226
|
+
* it, or a log change whose before value is not the row it replaced.
|
|
227
|
+
*/
|
|
228
|
+
export class SnapshotRowInconsistent extends Schema.TaggedError<SnapshotRowInconsistent>()(
|
|
229
|
+
"SnapshotRowInconsistent",
|
|
230
|
+
{
|
|
231
|
+
componentPath: Schema.String,
|
|
232
|
+
id: Schema.String,
|
|
233
|
+
reason: Schema.Literals([
|
|
234
|
+
"id",
|
|
235
|
+
"component",
|
|
236
|
+
"log",
|
|
237
|
+
"row",
|
|
238
|
+
"systemFields",
|
|
239
|
+
"duplicate",
|
|
240
|
+
]),
|
|
241
|
+
message: Schema.String,
|
|
242
|
+
},
|
|
243
|
+
) {}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* A snapshot's commit timestamps do not strictly increase through its write
|
|
247
|
+
* log, or its latest commit timestamp is not the log's last.
|
|
248
|
+
*/
|
|
249
|
+
export class SnapshotTimestampInconsistent extends Schema.TaggedError<SnapshotTimestampInconsistent>()(
|
|
250
|
+
"SnapshotTimestampInconsistent",
|
|
251
|
+
{ version: Schema.Int, commitTs: Schema.String, message: Schema.String },
|
|
252
|
+
) {}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* A snapshot's jobs and job rows disagree: a job with no row, a row with no
|
|
256
|
+
* job, a job left running, or a target no registered component exports.
|
|
257
|
+
*/
|
|
258
|
+
export class SnapshotJobInconsistent extends Schema.TaggedError<SnapshotJobInconsistent>()(
|
|
259
|
+
"SnapshotJobInconsistent",
|
|
260
|
+
{
|
|
261
|
+
id: Schema.String,
|
|
262
|
+
reason: Schema.Literals([
|
|
263
|
+
"row",
|
|
264
|
+
"untargeted",
|
|
265
|
+
"inProgress",
|
|
266
|
+
"component",
|
|
267
|
+
"function",
|
|
268
|
+
"duplicate",
|
|
269
|
+
]),
|
|
270
|
+
message: Schema.String,
|
|
271
|
+
},
|
|
272
|
+
) {}
|