@rotorsoft/act-tck 1.41.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/.tsbuildinfo +1 -1
- package/dist/@types/fixtures/helpers.d.ts.map +1 -1
- package/dist/@types/store-differential-tck.d.ts.map +1 -1
- package/dist/@types/store-property-tck.d.ts.map +1 -1
- package/dist/@types/store-tck.d.ts +2 -2
- package/dist/@types/store-tck.d.ts.map +1 -1
- package/dist/index.cjs +947 -420
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +949 -420
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -28,8 +28,7 @@ var seed_stream = async (store, stream, count, correlation) => {
|
|
|
28
28
|
const out = [];
|
|
29
29
|
for (let i = 0; i < count; i++) {
|
|
30
30
|
const committed = await store.commit(
|
|
31
|
-
stream,
|
|
32
|
-
[inc(1)],
|
|
31
|
+
[{ stream, msgs: [inc(1)] }],
|
|
33
32
|
make_meta({ correlation, stream })
|
|
34
33
|
);
|
|
35
34
|
out.push(...committed);
|
|
@@ -592,14 +591,17 @@ var apply_plan = async (store, plan, pii_isolation) => {
|
|
|
592
591
|
if (op.t === "commit") {
|
|
593
592
|
const msgs = op.pii && pii_isolation ? op.msgs.map((m, i) => i === 0 ? { ...m, pii: op.pii } : m) : op.msgs;
|
|
594
593
|
await store.commit(
|
|
595
|
-
op.stream,
|
|
596
|
-
msgs,
|
|
594
|
+
[{ stream: op.stream, msgs }],
|
|
597
595
|
make_meta({ stream: op.stream, correlation: plan.correlation })
|
|
598
596
|
);
|
|
599
597
|
} else if (op.t === "snapshot") {
|
|
600
598
|
await store.commit(
|
|
601
|
-
|
|
602
|
-
|
|
599
|
+
[
|
|
600
|
+
{
|
|
601
|
+
stream: op.stream,
|
|
602
|
+
msgs: [{ name: SNAP_EVENT, data: { count: op.count } }]
|
|
603
|
+
}
|
|
604
|
+
],
|
|
603
605
|
make_meta({ stream: op.stream, correlation: plan.correlation })
|
|
604
606
|
);
|
|
605
607
|
} else if (op.t === "truncate") {
|
|
@@ -608,8 +610,12 @@ var apply_plan = async (store, plan, pii_isolation) => {
|
|
|
608
610
|
]);
|
|
609
611
|
} else if (op.t === "truncate_windowed") {
|
|
610
612
|
await store.commit(
|
|
611
|
-
|
|
612
|
-
|
|
613
|
+
[
|
|
614
|
+
{
|
|
615
|
+
stream: op.stream,
|
|
616
|
+
msgs: [{ name: SNAP_EVENT, data: { count: 1 } }]
|
|
617
|
+
}
|
|
618
|
+
],
|
|
613
619
|
make_meta({ stream: op.stream, correlation: plan.correlation })
|
|
614
620
|
);
|
|
615
621
|
await store.truncate([
|
|
@@ -920,8 +926,7 @@ var runStorePropertyTck = (options) => {
|
|
|
920
926
|
for (const { stream, count } of commits) {
|
|
921
927
|
const before = expected.get(stream) ?? -1;
|
|
922
928
|
const committed = await store.commit(
|
|
923
|
-
stream,
|
|
924
|
-
events(count),
|
|
929
|
+
[{ stream, msgs: events(count) }],
|
|
925
930
|
make_meta({ stream })
|
|
926
931
|
);
|
|
927
932
|
committed.forEach((e, i) => {
|
|
@@ -946,8 +951,7 @@ var runStorePropertyTck = (options) => {
|
|
|
946
951
|
await reset2();
|
|
947
952
|
for (const { stream: stream2, count } of commits) {
|
|
948
953
|
await store.commit(
|
|
949
|
-
stream2,
|
|
950
|
-
events(count),
|
|
954
|
+
[{ stream: stream2, msgs: events(count) }],
|
|
951
955
|
make_meta({ stream: stream2 })
|
|
952
956
|
);
|
|
953
957
|
}
|
|
@@ -955,10 +959,8 @@ var runStorePropertyTck = (options) => {
|
|
|
955
959
|
const before = await collect(store, { stream, stream_exact: true });
|
|
956
960
|
await expect7(
|
|
957
961
|
store.commit(
|
|
958
|
-
stream,
|
|
959
|
-
|
|
960
|
-
make_meta({ stream }),
|
|
961
|
-
before.length
|
|
962
|
+
[{ stream, msgs: [inc(1)], expectedVersion: before.length }],
|
|
963
|
+
make_meta({ stream })
|
|
962
964
|
)
|
|
963
965
|
).rejects.toThrow();
|
|
964
966
|
const after = await collect(store, { stream, stream_exact: true });
|
|
@@ -985,8 +987,7 @@ var runStorePropertyTck = (options) => {
|
|
|
985
987
|
for (const op of ops) {
|
|
986
988
|
if (op.kind === "commit") {
|
|
987
989
|
await store.commit(
|
|
988
|
-
op.stream,
|
|
989
|
-
[inc(1)],
|
|
990
|
+
[{ stream: op.stream, msgs: [inc(1)] }],
|
|
990
991
|
make_meta({ stream: op.stream })
|
|
991
992
|
);
|
|
992
993
|
} else if (op.kind === "claim") {
|
|
@@ -1028,8 +1029,7 @@ var runStorePropertyTck = (options) => {
|
|
|
1028
1029
|
await store.subscribe(all.map((stream) => ({ stream })));
|
|
1029
1030
|
for (const stream of commitsA) {
|
|
1030
1031
|
await store.commit(
|
|
1031
|
-
stream,
|
|
1032
|
-
[inc(1)],
|
|
1032
|
+
[{ stream, msgs: [inc(1)] }],
|
|
1033
1033
|
make_meta({ stream })
|
|
1034
1034
|
);
|
|
1035
1035
|
}
|
|
@@ -1041,8 +1041,7 @@ var runStorePropertyTck = (options) => {
|
|
|
1041
1041
|
for (const l of acked1) watermark1.set(l.stream, l.at);
|
|
1042
1042
|
for (const stream of commitsB) {
|
|
1043
1043
|
await store.commit(
|
|
1044
|
-
stream,
|
|
1045
|
-
[inc(1)],
|
|
1044
|
+
[{ stream, msgs: [inc(1)] }],
|
|
1046
1045
|
make_meta({ stream })
|
|
1047
1046
|
);
|
|
1048
1047
|
}
|
|
@@ -1068,8 +1067,7 @@ var runStorePropertyTck = (options) => {
|
|
|
1068
1067
|
await store.subscribe(streams.map((stream) => ({ stream })));
|
|
1069
1068
|
for (const stream of commits) {
|
|
1070
1069
|
await store.commit(
|
|
1071
|
-
stream,
|
|
1072
|
-
[inc(1)],
|
|
1070
|
+
[{ stream, msgs: [inc(1)] }],
|
|
1073
1071
|
make_meta({ stream })
|
|
1074
1072
|
);
|
|
1075
1073
|
}
|
|
@@ -1079,8 +1077,7 @@ var runStorePropertyTck = (options) => {
|
|
|
1079
1077
|
const blockedSet = new Set(claimed.map((l) => l.stream));
|
|
1080
1078
|
await store.subscribe([{ stream: "ctrl" }]);
|
|
1081
1079
|
await store.commit(
|
|
1082
|
-
"ctrl",
|
|
1083
|
-
[inc(1)],
|
|
1080
|
+
[{ stream: "ctrl", msgs: [inc(1)] }],
|
|
1084
1081
|
make_meta({ stream: "ctrl" })
|
|
1085
1082
|
);
|
|
1086
1083
|
await mark_all(store);
|
|
@@ -1098,6 +1095,8 @@ import {
|
|
|
1098
1095
|
act,
|
|
1099
1096
|
ConcurrencyError,
|
|
1100
1097
|
InMemoryCache,
|
|
1098
|
+
is_literal_source,
|
|
1099
|
+
PreconditionError,
|
|
1101
1100
|
SNAP_EVENT as SNAP_EVENT2,
|
|
1102
1101
|
sensitive,
|
|
1103
1102
|
sleep,
|
|
@@ -1111,7 +1110,6 @@ var runStoreTck = (options) => {
|
|
|
1111
1110
|
describe8(`TCK / Store / ${options.name}`, () => {
|
|
1112
1111
|
let store;
|
|
1113
1112
|
const caps = { ...options.capabilities };
|
|
1114
|
-
const is_literal = (source) => !/[\]^$.*+?()[{}|\\]/.test(source);
|
|
1115
1113
|
const correlate = async (target = store) => {
|
|
1116
1114
|
const rows = [];
|
|
1117
1115
|
await target.query_streams(
|
|
@@ -1131,7 +1129,10 @@ var runStoreTck = (options) => {
|
|
|
1131
1129
|
(e) => {
|
|
1132
1130
|
mark = Math.max(mark, e.id);
|
|
1133
1131
|
},
|
|
1134
|
-
row.source !== void 0 ? {
|
|
1132
|
+
row.source !== void 0 ? {
|
|
1133
|
+
stream: row.source,
|
|
1134
|
+
stream_exact: is_literal_source(row.source, row.stream)
|
|
1135
|
+
} : {}
|
|
1135
1136
|
);
|
|
1136
1137
|
if (mark > row.at)
|
|
1137
1138
|
marks.push({
|
|
@@ -1167,14 +1168,12 @@ var runStoreTck = (options) => {
|
|
|
1167
1168
|
await zero_config.seed();
|
|
1168
1169
|
const s = `default-config-${uid()}`;
|
|
1169
1170
|
const first = await zero_config.commit(
|
|
1170
|
-
s,
|
|
1171
|
-
[inc(1)],
|
|
1171
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
1172
1172
|
make_meta({ stream: s })
|
|
1173
1173
|
);
|
|
1174
1174
|
expect8(first[0].version).toBe(0);
|
|
1175
1175
|
const second = await zero_config.commit(
|
|
1176
|
-
s,
|
|
1177
|
-
[inc(2)],
|
|
1176
|
+
[{ stream: s, msgs: [inc(2)] }],
|
|
1178
1177
|
make_meta({ stream: s })
|
|
1179
1178
|
);
|
|
1180
1179
|
expect8(second[0].version).toBe(1);
|
|
@@ -1190,12 +1189,371 @@ var runStoreTck = (options) => {
|
|
|
1190
1189
|
});
|
|
1191
1190
|
});
|
|
1192
1191
|
}
|
|
1192
|
+
describe8("commit across streams", () => {
|
|
1193
|
+
const meta = make_meta({ stream: "across" });
|
|
1194
|
+
const count = (stream) => store.query(() => {
|
|
1195
|
+
}, { stream, stream_exact: true });
|
|
1196
|
+
it7("lands every append, each from its own head, with ids in append order", async () => {
|
|
1197
|
+
const a = `across-a-${uid()}`;
|
|
1198
|
+
const b = `across-b-${uid()}`;
|
|
1199
|
+
await store.commit(
|
|
1200
|
+
[{ stream: a, msgs: [inc(1)] }],
|
|
1201
|
+
meta
|
|
1202
|
+
);
|
|
1203
|
+
const committed = await store.commit(
|
|
1204
|
+
[
|
|
1205
|
+
{ stream: a, msgs: [inc(2), inc(3)], expectedVersion: 0 },
|
|
1206
|
+
{ stream: b, msgs: [dec(4)], expectedVersion: -1 }
|
|
1207
|
+
],
|
|
1208
|
+
meta
|
|
1209
|
+
);
|
|
1210
|
+
expect8(committed.map((e) => [e.stream, e.version])).toEqual([
|
|
1211
|
+
[a, 1],
|
|
1212
|
+
[a, 2],
|
|
1213
|
+
[b, 0]
|
|
1214
|
+
]);
|
|
1215
|
+
for (let i = 1; i < committed.length; i++)
|
|
1216
|
+
expect8(committed[i].id).toBeGreaterThan(committed[i - 1].id);
|
|
1217
|
+
const read = [];
|
|
1218
|
+
await store.query((e) => read.push(e.id), {
|
|
1219
|
+
after: committed[0].id - 1
|
|
1220
|
+
});
|
|
1221
|
+
expect8(read.filter((id) => committed.some((e) => e.id === id))).toEqual(
|
|
1222
|
+
committed.map((e) => e.id)
|
|
1223
|
+
);
|
|
1224
|
+
});
|
|
1225
|
+
it7("stores nothing when the first, a middle or the last append is stale, and names its stream", async () => {
|
|
1226
|
+
for (const at of [0, 1, 2]) {
|
|
1227
|
+
const streams = [0, 1, 2].map((i) => `across-stale-${i}-${uid()}`);
|
|
1228
|
+
for (const stream of streams)
|
|
1229
|
+
await store.commit(
|
|
1230
|
+
[{ stream, msgs: [inc(1)] }],
|
|
1231
|
+
meta
|
|
1232
|
+
);
|
|
1233
|
+
const refused = store.commit(
|
|
1234
|
+
streams.map((stream, i) => ({
|
|
1235
|
+
stream,
|
|
1236
|
+
msgs: [inc(2)],
|
|
1237
|
+
expectedVersion: i === at ? 5 : 0
|
|
1238
|
+
})),
|
|
1239
|
+
meta
|
|
1240
|
+
);
|
|
1241
|
+
await expect8(refused).rejects.toBeInstanceOf(ConcurrencyError);
|
|
1242
|
+
await expect8(refused).rejects.toMatchObject({ stream: streams[at] });
|
|
1243
|
+
for (const stream of streams) expect8(await count(stream)).toBe(1);
|
|
1244
|
+
}
|
|
1245
|
+
});
|
|
1246
|
+
it7("refuses a stream named twice and an append with no events, storing nothing", async () => {
|
|
1247
|
+
const a = `across-twice-${uid()}`;
|
|
1248
|
+
const b = `across-empty-${uid()}`;
|
|
1249
|
+
await expect8(
|
|
1250
|
+
store.commit(
|
|
1251
|
+
[
|
|
1252
|
+
{ stream: a, msgs: [inc(1)] },
|
|
1253
|
+
{ stream: a, msgs: [inc(2)] }
|
|
1254
|
+
],
|
|
1255
|
+
meta
|
|
1256
|
+
)
|
|
1257
|
+
).rejects.toThrow(`stream "${a}" is named twice`);
|
|
1258
|
+
await expect8(
|
|
1259
|
+
store.commit(
|
|
1260
|
+
[
|
|
1261
|
+
{ stream: a, msgs: [inc(1)] },
|
|
1262
|
+
{ stream: b, msgs: [] }
|
|
1263
|
+
],
|
|
1264
|
+
meta
|
|
1265
|
+
)
|
|
1266
|
+
).rejects.toThrow(`the append to "${b}" has no events`);
|
|
1267
|
+
expect8(await count(a)).toBe(0);
|
|
1268
|
+
expect8(await count(b)).toBe(0);
|
|
1269
|
+
});
|
|
1270
|
+
it7("commits nothing for no appends", async () => {
|
|
1271
|
+
expect8(await store.commit([], meta)).toEqual([]);
|
|
1272
|
+
});
|
|
1273
|
+
it7("lands an unguarded append beside guarded ones", async () => {
|
|
1274
|
+
const a = `across-guarded-${uid()}`;
|
|
1275
|
+
const b = `across-free-${uid()}`;
|
|
1276
|
+
await store.commit(
|
|
1277
|
+
[{ stream: b, msgs: [inc(1)] }],
|
|
1278
|
+
meta
|
|
1279
|
+
);
|
|
1280
|
+
const committed = await store.commit(
|
|
1281
|
+
[
|
|
1282
|
+
{ stream: a, msgs: [inc(1)], expectedVersion: -1 },
|
|
1283
|
+
{ stream: b, msgs: [inc(2)] }
|
|
1284
|
+
],
|
|
1285
|
+
meta
|
|
1286
|
+
);
|
|
1287
|
+
expect8(committed.map((e) => [e.stream, e.version])).toEqual([
|
|
1288
|
+
[a, 0],
|
|
1289
|
+
[b, 1]
|
|
1290
|
+
]);
|
|
1291
|
+
});
|
|
1292
|
+
it7("stores every event of every append, whole", async () => {
|
|
1293
|
+
const a = `across-whole-a-${uid()}`;
|
|
1294
|
+
const b = `across-whole-b-${uid()}`;
|
|
1295
|
+
const across = make_meta({ stream: a });
|
|
1296
|
+
const committed = await store.commit(
|
|
1297
|
+
[
|
|
1298
|
+
{ stream: a, msgs: [inc(1)] },
|
|
1299
|
+
{ stream: b, msgs: [inc(2), dec(3)] }
|
|
1300
|
+
],
|
|
1301
|
+
across
|
|
1302
|
+
);
|
|
1303
|
+
const shape = (e) => [
|
|
1304
|
+
e.name,
|
|
1305
|
+
e.data,
|
|
1306
|
+
e.meta
|
|
1307
|
+
];
|
|
1308
|
+
const expected = [
|
|
1309
|
+
["Incremented", { amount: 2 }, across],
|
|
1310
|
+
["Decremented", { amount: 3 }, across]
|
|
1311
|
+
];
|
|
1312
|
+
expect8(committed.filter((e) => e.stream === b).map(shape)).toEqual(
|
|
1313
|
+
expected
|
|
1314
|
+
);
|
|
1315
|
+
const stored = [];
|
|
1316
|
+
await store.query((e) => stored.push(e), {
|
|
1317
|
+
stream: b,
|
|
1318
|
+
stream_exact: true
|
|
1319
|
+
});
|
|
1320
|
+
expect8(stored.map(shape)).toEqual(expected);
|
|
1321
|
+
});
|
|
1322
|
+
it7.skipIf(!caps.pii_isolation)(
|
|
1323
|
+
"keeps the sensitive fields of a later append",
|
|
1324
|
+
async () => {
|
|
1325
|
+
const a = `across-pii-a-${uid()}`;
|
|
1326
|
+
const b = `across-pii-b-${uid()}`;
|
|
1327
|
+
await store.commit(
|
|
1328
|
+
[
|
|
1329
|
+
{ stream: a, msgs: [inc(1)] },
|
|
1330
|
+
{ stream: b, msgs: [{ ...inc(2), pii: { email: "e" } }] }
|
|
1331
|
+
],
|
|
1332
|
+
make_meta({ stream: a })
|
|
1333
|
+
);
|
|
1334
|
+
const stored = [];
|
|
1335
|
+
await store.query((e) => stored.push(e.pii), {
|
|
1336
|
+
stream: b,
|
|
1337
|
+
stream_exact: true
|
|
1338
|
+
});
|
|
1339
|
+
expect8(stored).toEqual([{ email: "e" }]);
|
|
1340
|
+
}
|
|
1341
|
+
);
|
|
1342
|
+
it7("leaves nothing of the commit that lost a race, on any of its streams", async () => {
|
|
1343
|
+
const shared = `across-all-shared-${uid()}`;
|
|
1344
|
+
const [x, y] = [`across-all-x-${uid()}`, `across-all-y-${uid()}`];
|
|
1345
|
+
const race = (own) => store.commit(
|
|
1346
|
+
[
|
|
1347
|
+
{ stream: own, msgs: [inc(1)], expectedVersion: -1 },
|
|
1348
|
+
{ stream: shared, msgs: [inc(1)], expectedVersion: -1 }
|
|
1349
|
+
],
|
|
1350
|
+
meta
|
|
1351
|
+
);
|
|
1352
|
+
const rs = await Promise.allSettled([race(x), race(y)]);
|
|
1353
|
+
expect8(rs.filter((r) => r.status === "fulfilled")).toHaveLength(1);
|
|
1354
|
+
expect8(await count(x) + await count(y)).toBe(1);
|
|
1355
|
+
});
|
|
1356
|
+
it7("lets one of two racing commits on a shared stream win, and both on disjoint streams", async () => {
|
|
1357
|
+
const shared = `across-shared-${uid()}`;
|
|
1358
|
+
const [x, y] = [`across-x-${uid()}`, `across-y-${uid()}`];
|
|
1359
|
+
const race = (own, other) => store.commit(
|
|
1360
|
+
[
|
|
1361
|
+
{ stream: own, msgs: [inc(1)], expectedVersion: -1 },
|
|
1362
|
+
{ stream: other, msgs: [inc(1)], expectedVersion: -1 }
|
|
1363
|
+
],
|
|
1364
|
+
meta
|
|
1365
|
+
);
|
|
1366
|
+
const shared_race = await Promise.allSettled([
|
|
1367
|
+
race(x, shared),
|
|
1368
|
+
race(y, shared)
|
|
1369
|
+
]);
|
|
1370
|
+
expect8(
|
|
1371
|
+
shared_race.filter((r2) => r2.status === "fulfilled")
|
|
1372
|
+
).toHaveLength(1);
|
|
1373
|
+
const lost = shared_race.find((r2) => r2.status === "rejected");
|
|
1374
|
+
expect8(lost.reason).toBeInstanceOf(
|
|
1375
|
+
ConcurrencyError
|
|
1376
|
+
);
|
|
1377
|
+
expect8(await count(shared)).toBe(1);
|
|
1378
|
+
const [p, q, r, t] = [0, 1, 2, 3].map((i) => `across-d${i}-${uid()}`);
|
|
1379
|
+
const disjoint = await Promise.allSettled([race(p, q), race(r, t)]);
|
|
1380
|
+
expect8(disjoint.every((d) => d.status === "fulfilled")).toBe(true);
|
|
1381
|
+
});
|
|
1382
|
+
});
|
|
1383
|
+
describe8("what a commit, guard or truncate must not get wrong", () => {
|
|
1384
|
+
const edge_uid = () => uid();
|
|
1385
|
+
const E = (data = { a: 1 }, pii) => ({
|
|
1386
|
+
name: "E",
|
|
1387
|
+
data,
|
|
1388
|
+
...pii ? { pii } : {}
|
|
1389
|
+
});
|
|
1390
|
+
const edge_meta = (correlation = "m") => ({ correlation, causation: {} });
|
|
1391
|
+
const rows = async (query) => {
|
|
1392
|
+
const found = [];
|
|
1393
|
+
await store.query((e) => found.push(e), query);
|
|
1394
|
+
return found;
|
|
1395
|
+
};
|
|
1396
|
+
const one = (stream) => ({ stream, stream_exact: true });
|
|
1397
|
+
it7("names the FIRST stale stream when two are stale", async () => {
|
|
1398
|
+
const [a, b] = [`a-${edge_uid()}`, `b-${edge_uid()}`];
|
|
1399
|
+
const e = await store.commit(
|
|
1400
|
+
[
|
|
1401
|
+
{ stream: a, msgs: [E()], expectedVersion: 3 },
|
|
1402
|
+
{ stream: b, msgs: [E()], expectedVersion: 4 }
|
|
1403
|
+
],
|
|
1404
|
+
edge_meta()
|
|
1405
|
+
).catch((x) => x);
|
|
1406
|
+
expect8(e).toBeInstanceOf(ConcurrencyError);
|
|
1407
|
+
expect8(e.stream).toBe(a);
|
|
1408
|
+
});
|
|
1409
|
+
it7("checks a stale expectedVersion of 0 inside a multi-stream commit", async () => {
|
|
1410
|
+
const [a, b] = [`a-${edge_uid()}`, `b-${edge_uid()}`];
|
|
1411
|
+
await store.commit(
|
|
1412
|
+
[{ stream: b, msgs: [E(), E()] }],
|
|
1413
|
+
edge_meta()
|
|
1414
|
+
);
|
|
1415
|
+
await expect8(
|
|
1416
|
+
store.commit(
|
|
1417
|
+
[
|
|
1418
|
+
{ stream: a, msgs: [E()], expectedVersion: -1 },
|
|
1419
|
+
{ stream: b, msgs: [E()], expectedVersion: 0 }
|
|
1420
|
+
],
|
|
1421
|
+
edge_meta()
|
|
1422
|
+
)
|
|
1423
|
+
).rejects.toBeInstanceOf(ConcurrencyError);
|
|
1424
|
+
expect8(await rows(one(a))).toHaveLength(0);
|
|
1425
|
+
});
|
|
1426
|
+
it7("attaches meta to every append, not just the last", async () => {
|
|
1427
|
+
const ss = [0, 1, 2].map((i) => `m${i}-${edge_uid()}`);
|
|
1428
|
+
const c = `corr-${edge_uid()}`;
|
|
1429
|
+
await store.commit(
|
|
1430
|
+
ss.map((stream) => ({ stream, msgs: [E()] })),
|
|
1431
|
+
edge_meta(c)
|
|
1432
|
+
);
|
|
1433
|
+
for (const stream of ss)
|
|
1434
|
+
expect8((await rows(one(stream)))[0].meta.correlation).toBe(c);
|
|
1435
|
+
});
|
|
1436
|
+
it7("refuses a stream named twice when not adjacent", async () => {
|
|
1437
|
+
const [a, b] = [`a-${edge_uid()}`, `b-${edge_uid()}`];
|
|
1438
|
+
await expect8(
|
|
1439
|
+
store.commit(
|
|
1440
|
+
[
|
|
1441
|
+
{ stream: a, msgs: [E()] },
|
|
1442
|
+
{ stream: b, msgs: [E()] },
|
|
1443
|
+
{ stream: a, msgs: [E()] }
|
|
1444
|
+
],
|
|
1445
|
+
edge_meta()
|
|
1446
|
+
)
|
|
1447
|
+
).rejects.toThrow("named twice");
|
|
1448
|
+
expect8(await rows(one(a))).toHaveLength(0);
|
|
1449
|
+
});
|
|
1450
|
+
it7("refuses a lone empty append (a version check alone)", async () => {
|
|
1451
|
+
const a = `a-${edge_uid()}`;
|
|
1452
|
+
await expect8(
|
|
1453
|
+
store.commit(
|
|
1454
|
+
[{ stream: a, msgs: [], expectedVersion: -1 }],
|
|
1455
|
+
edge_meta()
|
|
1456
|
+
)
|
|
1457
|
+
).rejects.toThrow("no events");
|
|
1458
|
+
});
|
|
1459
|
+
it7("refuses an empty FIRST append", async () => {
|
|
1460
|
+
const [a, b] = [`a-${edge_uid()}`, `b-${edge_uid()}`];
|
|
1461
|
+
await expect8(
|
|
1462
|
+
store.commit(
|
|
1463
|
+
[
|
|
1464
|
+
{ stream: a, msgs: [] },
|
|
1465
|
+
{ stream: b, msgs: [E()] }
|
|
1466
|
+
],
|
|
1467
|
+
edge_meta()
|
|
1468
|
+
)
|
|
1469
|
+
).rejects.toThrow("no events");
|
|
1470
|
+
expect8(await rows(one(b))).toHaveLength(0);
|
|
1471
|
+
});
|
|
1472
|
+
it7("keeps the sensitive fields of the FIRST append", async () => {
|
|
1473
|
+
const [a, b] = [`a-${edge_uid()}`, `b-${edge_uid()}`];
|
|
1474
|
+
await store.commit(
|
|
1475
|
+
[
|
|
1476
|
+
{ stream: a, msgs: [E({}, { email: "x" })] },
|
|
1477
|
+
{ stream: b, msgs: [E()] }
|
|
1478
|
+
],
|
|
1479
|
+
edge_meta()
|
|
1480
|
+
);
|
|
1481
|
+
expect8((await rows(one(a)))[0].pii).toEqual({ email: "x" });
|
|
1482
|
+
});
|
|
1483
|
+
it7("a guard below a trailing snapshot is stale", async () => {
|
|
1484
|
+
const a = `a-${edge_uid()}`;
|
|
1485
|
+
await store.commit([{ stream: a, msgs: [E()] }], edge_meta());
|
|
1486
|
+
await store.commit(
|
|
1487
|
+
[
|
|
1488
|
+
{
|
|
1489
|
+
stream: a,
|
|
1490
|
+
msgs: [{ name: SNAP_EVENT2, data: {} }],
|
|
1491
|
+
expectedVersion: 0
|
|
1492
|
+
}
|
|
1493
|
+
],
|
|
1494
|
+
edge_meta()
|
|
1495
|
+
);
|
|
1496
|
+
await expect8(
|
|
1497
|
+
store.commit(
|
|
1498
|
+
[{ stream: a, msgs: [E()], expectedVersion: 0 }],
|
|
1499
|
+
edge_meta()
|
|
1500
|
+
)
|
|
1501
|
+
).rejects.toBeInstanceOf(ConcurrencyError);
|
|
1502
|
+
});
|
|
1503
|
+
it7("a guard below a trailing tombstone is stale (what stops a writer during a close)", async () => {
|
|
1504
|
+
const a = `a-${edge_uid()}`;
|
|
1505
|
+
await store.commit([{ stream: a, msgs: [E()] }], edge_meta());
|
|
1506
|
+
await store.commit(
|
|
1507
|
+
[
|
|
1508
|
+
{
|
|
1509
|
+
stream: a,
|
|
1510
|
+
msgs: [{ name: "__tombstone__", data: {} }],
|
|
1511
|
+
expectedVersion: 0
|
|
1512
|
+
}
|
|
1513
|
+
],
|
|
1514
|
+
edge_meta()
|
|
1515
|
+
);
|
|
1516
|
+
await expect8(
|
|
1517
|
+
store.commit(
|
|
1518
|
+
[{ stream: a, msgs: [E()], expectedVersion: 0 }],
|
|
1519
|
+
edge_meta()
|
|
1520
|
+
)
|
|
1521
|
+
).rejects.toBeInstanceOf(ConcurrencyError);
|
|
1522
|
+
});
|
|
1523
|
+
it7("a commit after a full truncate continues from the seed at version 0", async () => {
|
|
1524
|
+
const a = `a-${edge_uid()}`;
|
|
1525
|
+
await store.commit(
|
|
1526
|
+
[{ stream: a, msgs: [E(), E(), E()] }],
|
|
1527
|
+
edge_meta()
|
|
1528
|
+
);
|
|
1529
|
+
await store.truncate([{ stream: a, snapshot: { n: 3 } }]);
|
|
1530
|
+
const [c] = await store.commit(
|
|
1531
|
+
[{ stream: a, msgs: [E()], expectedVersion: 0 }],
|
|
1532
|
+
edge_meta()
|
|
1533
|
+
);
|
|
1534
|
+
expect8(c.version).toBe(1);
|
|
1535
|
+
});
|
|
1536
|
+
it7("seeds a full truncate at version 0, carrying the meta it was given", async () => {
|
|
1537
|
+
const a = `a-${edge_uid()}`;
|
|
1538
|
+
await store.commit(
|
|
1539
|
+
[{ stream: a, msgs: [E(), E(), E()] }],
|
|
1540
|
+
edge_meta()
|
|
1541
|
+
);
|
|
1542
|
+
const c = `close-${edge_uid()}`;
|
|
1543
|
+
const r = await store.truncate([
|
|
1544
|
+
{ stream: a, snapshot: { n: 3 }, meta: edge_meta(c) }
|
|
1545
|
+
]);
|
|
1546
|
+
expect8(r.get(a).committed.version).toBe(0);
|
|
1547
|
+
const [seed] = await rows({ ...one(a), with_snaps: true });
|
|
1548
|
+
expect8(seed.version).toBe(0);
|
|
1549
|
+
expect8(seed.meta.correlation).toBe(c);
|
|
1550
|
+
});
|
|
1551
|
+
});
|
|
1193
1552
|
describe8("commit", () => {
|
|
1194
1553
|
it7("returns committed events with sequenced ids and versions", async () => {
|
|
1195
1554
|
const s = `commit-seq-${uid()}`;
|
|
1196
1555
|
const committed = await store.commit(
|
|
1197
|
-
s,
|
|
1198
|
-
[inc(1), inc(2), dec(3)],
|
|
1556
|
+
[{ stream: s, msgs: [inc(1), inc(2), dec(3)] }],
|
|
1199
1557
|
make_meta({ stream: s })
|
|
1200
1558
|
);
|
|
1201
1559
|
expect8(committed).toHaveLength(3);
|
|
@@ -1212,8 +1570,7 @@ var runStoreTck = (options) => {
|
|
|
1212
1570
|
const s = `commit-meta-${uid()}`;
|
|
1213
1571
|
const correlation = `cor-${uid()}`;
|
|
1214
1572
|
const committed = await store.commit(
|
|
1215
|
-
s,
|
|
1216
|
-
[inc(1)],
|
|
1573
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
1217
1574
|
make_meta({ stream: s, correlation })
|
|
1218
1575
|
);
|
|
1219
1576
|
expect8(committed[0].stream).toBe(s);
|
|
@@ -1222,64 +1579,50 @@ var runStoreTck = (options) => {
|
|
|
1222
1579
|
it7("throws ConcurrencyError when expectedVersion is wrong", async () => {
|
|
1223
1580
|
const s = `commit-cc-${uid()}`;
|
|
1224
1581
|
await store.commit(
|
|
1225
|
-
s,
|
|
1226
|
-
[inc(1)],
|
|
1582
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
1227
1583
|
make_meta({ stream: s })
|
|
1228
1584
|
);
|
|
1229
1585
|
await store.commit(
|
|
1230
|
-
s,
|
|
1231
|
-
|
|
1232
|
-
make_meta({ stream: s }),
|
|
1233
|
-
0
|
|
1586
|
+
[{ stream: s, msgs: [inc(1)], expectedVersion: 0 }],
|
|
1587
|
+
make_meta({ stream: s })
|
|
1234
1588
|
);
|
|
1235
1589
|
await expect8(
|
|
1236
|
-
store.commit(
|
|
1590
|
+
store.commit(
|
|
1591
|
+
[{ stream: s, msgs: [inc(1)], expectedVersion: 0 }],
|
|
1592
|
+
make_meta({ stream: s })
|
|
1593
|
+
)
|
|
1237
1594
|
).rejects.toBeInstanceOf(ConcurrencyError);
|
|
1238
1595
|
});
|
|
1239
1596
|
it7("treats expectedVersion -1 as an empty stream", async () => {
|
|
1240
1597
|
const s = `commit-new-cc-${uid()}`;
|
|
1241
1598
|
const [first] = await store.commit(
|
|
1242
|
-
s,
|
|
1243
|
-
[inc(1)],
|
|
1244
|
-
make_meta({ stream: s }),
|
|
1245
|
-
-1
|
|
1246
|
-
);
|
|
1247
|
-
expect8(first.version).toBe(0);
|
|
1248
|
-
await expect8(
|
|
1249
|
-
store.commit(s, [inc(1)], make_meta({ stream: s }), -1)
|
|
1250
|
-
).rejects.toBeInstanceOf(ConcurrencyError);
|
|
1251
|
-
});
|
|
1252
|
-
it7("checks expectedVersion even when committing no events", async () => {
|
|
1253
|
-
const s = `commit-empty-cc-${uid()}`;
|
|
1254
|
-
await store.commit(
|
|
1255
|
-
s,
|
|
1256
|
-
[inc(1)],
|
|
1599
|
+
[{ stream: s, msgs: [inc(1)], expectedVersion: -1 }],
|
|
1257
1600
|
make_meta({ stream: s })
|
|
1258
1601
|
);
|
|
1602
|
+
expect8(first.version).toBe(0);
|
|
1259
1603
|
await expect8(
|
|
1260
|
-
store.commit(
|
|
1604
|
+
store.commit(
|
|
1605
|
+
[{ stream: s, msgs: [inc(1)], expectedVersion: -1 }],
|
|
1606
|
+
make_meta({ stream: s })
|
|
1607
|
+
)
|
|
1261
1608
|
).rejects.toBeInstanceOf(ConcurrencyError);
|
|
1262
|
-
expect8(
|
|
1263
|
-
await store.commit(s, [], make_meta({ stream: s }), 0)
|
|
1264
|
-
).toEqual([]);
|
|
1265
1609
|
});
|
|
1266
1610
|
it7("takes concurrent commits, reads and writes on one instance", async () => {
|
|
1267
1611
|
const x = `commit-concurrent-x-${uid()}`;
|
|
1268
1612
|
const y = `commit-concurrent-y-${uid()}`;
|
|
1269
1613
|
const [first, second, other, read, subscribed] = await Promise.allSettled([
|
|
1270
1614
|
store.commit(
|
|
1271
|
-
x,
|
|
1272
|
-
|
|
1273
|
-
make_meta({ stream: x }),
|
|
1274
|
-
-1
|
|
1615
|
+
[{ stream: x, msgs: [inc(1)], expectedVersion: -1 }],
|
|
1616
|
+
make_meta({ stream: x })
|
|
1275
1617
|
),
|
|
1276
1618
|
store.commit(
|
|
1277
|
-
x,
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1619
|
+
[{ stream: x, msgs: [inc(2)], expectedVersion: -1 }],
|
|
1620
|
+
make_meta({ stream: x })
|
|
1621
|
+
),
|
|
1622
|
+
store.commit(
|
|
1623
|
+
[{ stream: y, msgs: [inc(1)] }],
|
|
1624
|
+
make_meta({ stream: y })
|
|
1281
1625
|
),
|
|
1282
|
-
store.commit(y, [inc(1)], make_meta({ stream: y })),
|
|
1283
1626
|
store.query(() => {
|
|
1284
1627
|
}, { stream: x, stream_exact: true }),
|
|
1285
1628
|
// A source nothing writes, so later claims never see it.
|
|
@@ -1301,12 +1644,14 @@ var runStoreTck = (options) => {
|
|
|
1301
1644
|
it7("preserves prior events when a concurrent commit is rejected", async () => {
|
|
1302
1645
|
const s = `commit-cc-preserve-${uid()}`;
|
|
1303
1646
|
await store.commit(
|
|
1304
|
-
s,
|
|
1305
|
-
[inc(1), inc(2)],
|
|
1647
|
+
[{ stream: s, msgs: [inc(1), inc(2)] }],
|
|
1306
1648
|
make_meta({ stream: s })
|
|
1307
1649
|
);
|
|
1308
1650
|
await expect8(
|
|
1309
|
-
store.commit(
|
|
1651
|
+
store.commit(
|
|
1652
|
+
[{ stream: s, msgs: [inc(3)], expectedVersion: 0 }],
|
|
1653
|
+
make_meta({ stream: s })
|
|
1654
|
+
)
|
|
1310
1655
|
).rejects.toBeInstanceOf(ConcurrencyError);
|
|
1311
1656
|
const found = await collect(store, { stream: s, stream_exact: true });
|
|
1312
1657
|
expect8(found).toHaveLength(2);
|
|
@@ -1318,13 +1663,11 @@ var runStoreTck = (options) => {
|
|
|
1318
1663
|
const s2 = `q-s2-${uid()}`;
|
|
1319
1664
|
const cor = `q-cor-${uid()}`;
|
|
1320
1665
|
await store.commit(
|
|
1321
|
-
s1,
|
|
1322
|
-
[inc(1), dec(1)],
|
|
1666
|
+
[{ stream: s1, msgs: [inc(1), dec(1)] }],
|
|
1323
1667
|
make_meta({ stream: s1, correlation: cor })
|
|
1324
1668
|
);
|
|
1325
1669
|
await store.commit(
|
|
1326
|
-
s2,
|
|
1327
|
-
[inc(2), dec(2), reset()],
|
|
1670
|
+
[{ stream: s2, msgs: [inc(2), dec(2), reset()] }],
|
|
1328
1671
|
make_meta({ stream: s2, correlation: cor })
|
|
1329
1672
|
);
|
|
1330
1673
|
const by_stream = await collect(store, {
|
|
@@ -1350,8 +1693,7 @@ var runStoreTck = (options) => {
|
|
|
1350
1693
|
it7("excludes snapshots when called with no query object", async () => {
|
|
1351
1694
|
const s = `q-nofilter-${uid()}`;
|
|
1352
1695
|
await store.commit(
|
|
1353
|
-
s,
|
|
1354
|
-
[{ name: SNAP_EVENT2, data: { count: 0 } }],
|
|
1696
|
+
[{ stream: s, msgs: [{ name: SNAP_EVENT2, data: { count: 0 } }] }],
|
|
1355
1697
|
make_meta({ stream: s })
|
|
1356
1698
|
);
|
|
1357
1699
|
const names = [];
|
|
@@ -1363,18 +1705,15 @@ var runStoreTck = (options) => {
|
|
|
1363
1705
|
it7("with_snaps resumes from the latest snapshot per stream", async () => {
|
|
1364
1706
|
const s = `q-snap-${uid()}`;
|
|
1365
1707
|
await store.commit(
|
|
1366
|
-
s,
|
|
1367
|
-
[inc(1), inc(1)],
|
|
1708
|
+
[{ stream: s, msgs: [inc(1), inc(1)] }],
|
|
1368
1709
|
make_meta({ stream: s })
|
|
1369
1710
|
);
|
|
1370
1711
|
const [snap] = await store.commit(
|
|
1371
|
-
s,
|
|
1372
|
-
[{ name: SNAP_EVENT2, data: { count: 2 } }],
|
|
1712
|
+
[{ stream: s, msgs: [{ name: SNAP_EVENT2, data: { count: 2 } }] }],
|
|
1373
1713
|
make_meta({ stream: s })
|
|
1374
1714
|
);
|
|
1375
1715
|
await store.commit(
|
|
1376
|
-
s,
|
|
1377
|
-
[inc(1), inc(1), inc(1)],
|
|
1716
|
+
[{ stream: s, msgs: [inc(1), inc(1), inc(1)] }],
|
|
1378
1717
|
make_meta({ stream: s })
|
|
1379
1718
|
);
|
|
1380
1719
|
const from_snap = await collect(store, {
|
|
@@ -1395,8 +1734,7 @@ var runStoreTck = (options) => {
|
|
|
1395
1734
|
expect8(after_snap).toHaveLength(3);
|
|
1396
1735
|
const s2 = `q-nosnap-${uid()}`;
|
|
1397
1736
|
await store.commit(
|
|
1398
|
-
s2,
|
|
1399
|
-
[inc(1), inc(1)],
|
|
1737
|
+
[{ stream: s2, msgs: [inc(1), inc(1)] }],
|
|
1400
1738
|
make_meta({ stream: s2 })
|
|
1401
1739
|
);
|
|
1402
1740
|
const full = await collect(store, {
|
|
@@ -1409,18 +1747,15 @@ var runStoreTck = (options) => {
|
|
|
1409
1747
|
it7("with_snaps applies the resume floor on a backward scan too", async () => {
|
|
1410
1748
|
const s = `q-snap-back-${uid()}`;
|
|
1411
1749
|
await store.commit(
|
|
1412
|
-
s,
|
|
1413
|
-
[inc(1), inc(1)],
|
|
1750
|
+
[{ stream: s, msgs: [inc(1), inc(1)] }],
|
|
1414
1751
|
make_meta({ stream: s })
|
|
1415
1752
|
);
|
|
1416
1753
|
const [snap] = await store.commit(
|
|
1417
|
-
s,
|
|
1418
|
-
[{ name: SNAP_EVENT2, data: { count: 2 } }],
|
|
1754
|
+
[{ stream: s, msgs: [{ name: SNAP_EVENT2, data: { count: 2 } }] }],
|
|
1419
1755
|
make_meta({ stream: s })
|
|
1420
1756
|
);
|
|
1421
1757
|
await store.commit(
|
|
1422
|
-
s,
|
|
1423
|
-
[inc(1), inc(1), inc(1)],
|
|
1758
|
+
[{ stream: s, msgs: [inc(1), inc(1), inc(1)] }],
|
|
1424
1759
|
make_meta({ stream: s })
|
|
1425
1760
|
);
|
|
1426
1761
|
const backward = await collect(store, {
|
|
@@ -1434,8 +1769,7 @@ var runStoreTck = (options) => {
|
|
|
1434
1769
|
expect8(backward.every((e) => e.id >= snap.id)).toBe(true);
|
|
1435
1770
|
const s2 = `q-nosnap-back-${uid()}`;
|
|
1436
1771
|
await store.commit(
|
|
1437
|
-
s2,
|
|
1438
|
-
[inc(1), inc(1)],
|
|
1772
|
+
[{ stream: s2, msgs: [inc(1), inc(1)] }],
|
|
1439
1773
|
make_meta({ stream: s2 })
|
|
1440
1774
|
);
|
|
1441
1775
|
const full = await collect(store, {
|
|
@@ -1449,8 +1783,7 @@ var runStoreTck = (options) => {
|
|
|
1449
1783
|
it7("supports backward traversal", async () => {
|
|
1450
1784
|
const s = `q-back-${uid()}`;
|
|
1451
1785
|
const committed = await store.commit(
|
|
1452
|
-
s,
|
|
1453
|
-
[inc(1), inc(2), inc(3)],
|
|
1786
|
+
[{ stream: s, msgs: [inc(1), inc(2), inc(3)] }],
|
|
1454
1787
|
make_meta({ stream: s })
|
|
1455
1788
|
);
|
|
1456
1789
|
const forward = await collect(store, { stream: s, stream_exact: true });
|
|
@@ -1475,8 +1808,7 @@ var runStoreTck = (options) => {
|
|
|
1475
1808
|
it7("after/before bound the id range", async () => {
|
|
1476
1809
|
const s = `q-bounds-${uid()}`;
|
|
1477
1810
|
const committed = await store.commit(
|
|
1478
|
-
s,
|
|
1479
|
-
[inc(1), inc(2), inc(3), inc(4)],
|
|
1811
|
+
[{ stream: s, msgs: [inc(1), inc(2), inc(3), inc(4)] }],
|
|
1480
1812
|
make_meta({ stream: s })
|
|
1481
1813
|
);
|
|
1482
1814
|
const after_first = await collect(store, {
|
|
@@ -1499,8 +1831,7 @@ var runStoreTck = (options) => {
|
|
|
1499
1831
|
it7("names:[] matches no events", async () => {
|
|
1500
1832
|
const s = `q-names-empty-${uid()}`;
|
|
1501
1833
|
await store.commit(
|
|
1502
|
-
s,
|
|
1503
|
-
[inc(1), dec(1)],
|
|
1834
|
+
[{ stream: s, msgs: [inc(1), dec(1)] }],
|
|
1504
1835
|
make_meta({ stream: s })
|
|
1505
1836
|
);
|
|
1506
1837
|
const none = await collect(store, {
|
|
@@ -1515,8 +1846,7 @@ var runStoreTck = (options) => {
|
|
|
1515
1846
|
it7("after:0 and before:0 are honored as id bounds", async () => {
|
|
1516
1847
|
const s = `q-zero-bound-${uid()}`;
|
|
1517
1848
|
await store.commit(
|
|
1518
|
-
s,
|
|
1519
|
-
[inc(1), inc(2), inc(3)],
|
|
1849
|
+
[{ stream: s, msgs: [inc(1), inc(2), inc(3)] }],
|
|
1520
1850
|
make_meta({ stream: s })
|
|
1521
1851
|
);
|
|
1522
1852
|
expect8(
|
|
@@ -1547,8 +1877,7 @@ var runStoreTck = (options) => {
|
|
|
1547
1877
|
it7("created_after/created_before filter by timestamp", async () => {
|
|
1548
1878
|
const s = `q-ts-${uid()}`;
|
|
1549
1879
|
const committed = await store.commit(
|
|
1550
|
-
s,
|
|
1551
|
-
[inc(1)],
|
|
1880
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
1552
1881
|
make_meta({ stream: s })
|
|
1553
1882
|
);
|
|
1554
1883
|
const ts = committed[0].created.getTime();
|
|
@@ -1571,8 +1900,7 @@ var runStoreTck = (options) => {
|
|
|
1571
1900
|
it7("created bounds exclude the event they are pinned to", async () => {
|
|
1572
1901
|
const s = `q-ts-self-${uid()}`;
|
|
1573
1902
|
const committed = await store.commit(
|
|
1574
|
-
s,
|
|
1575
|
-
[inc(1)],
|
|
1903
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
1576
1904
|
make_meta({ stream: s })
|
|
1577
1905
|
);
|
|
1578
1906
|
const own = committed[0].created;
|
|
@@ -1592,8 +1920,7 @@ var runStoreTck = (options) => {
|
|
|
1592
1920
|
it7("backward traversal short-circuits at `after` id boundary", async () => {
|
|
1593
1921
|
const s = `q-back-after-${uid()}`;
|
|
1594
1922
|
const committed = await store.commit(
|
|
1595
|
-
s,
|
|
1596
|
-
[inc(1), inc(2), inc(3)],
|
|
1923
|
+
[{ stream: s, msgs: [inc(1), inc(2), inc(3)] }],
|
|
1597
1924
|
make_meta({ stream: s })
|
|
1598
1925
|
);
|
|
1599
1926
|
const got = await collect(store, {
|
|
@@ -1610,8 +1937,7 @@ var runStoreTck = (options) => {
|
|
|
1610
1937
|
it7("backward traversal short-circuits at `created_after` boundary", async () => {
|
|
1611
1938
|
const s = `q-back-cafter-${uid()}`;
|
|
1612
1939
|
await store.commit(
|
|
1613
|
-
s,
|
|
1614
|
-
[inc(1)],
|
|
1940
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
1615
1941
|
make_meta({ stream: s })
|
|
1616
1942
|
);
|
|
1617
1943
|
const future = new Date(Date.now() + 6e4);
|
|
@@ -1626,8 +1952,7 @@ var runStoreTck = (options) => {
|
|
|
1626
1952
|
it7("backward traversal honors created_before by skipping newer events", async () => {
|
|
1627
1953
|
const s = `q-back-ts-${uid()}`;
|
|
1628
1954
|
const committed = await store.commit(
|
|
1629
|
-
s,
|
|
1630
|
-
[inc(1)],
|
|
1955
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
1631
1956
|
make_meta()
|
|
1632
1957
|
);
|
|
1633
1958
|
const past = new Date(committed[0].created.getTime() - 6e4);
|
|
@@ -1644,13 +1969,11 @@ var runStoreTck = (options) => {
|
|
|
1644
1969
|
const a = `q-exact-${tag}`;
|
|
1645
1970
|
const b = `q-exact-${tag}-extra`;
|
|
1646
1971
|
await store.commit(
|
|
1647
|
-
a,
|
|
1648
|
-
[inc(1)],
|
|
1972
|
+
[{ stream: a, msgs: [inc(1)] }],
|
|
1649
1973
|
make_meta({ stream: a })
|
|
1650
1974
|
);
|
|
1651
1975
|
await store.commit(
|
|
1652
|
-
b,
|
|
1653
|
-
[inc(2)],
|
|
1976
|
+
[{ stream: b, msgs: [inc(2)] }],
|
|
1654
1977
|
make_meta({ stream: b })
|
|
1655
1978
|
);
|
|
1656
1979
|
const exact = await collect(store, { stream: a, stream_exact: true });
|
|
@@ -1662,13 +1985,11 @@ var runStoreTck = (options) => {
|
|
|
1662
1985
|
const inner = `qr-${tag}-inner`;
|
|
1663
1986
|
const longer = `qr-${tag}-inner-extra`;
|
|
1664
1987
|
await store.commit(
|
|
1665
|
-
inner,
|
|
1666
|
-
[inc(1)],
|
|
1988
|
+
[{ stream: inner, msgs: [inc(1)] }],
|
|
1667
1989
|
make_meta({ stream: inner })
|
|
1668
1990
|
);
|
|
1669
1991
|
await store.commit(
|
|
1670
|
-
longer,
|
|
1671
|
-
[inc(2)],
|
|
1992
|
+
[{ stream: longer, msgs: [inc(2)] }],
|
|
1672
1993
|
make_meta({ stream: longer })
|
|
1673
1994
|
);
|
|
1674
1995
|
const got = await collect(store, { stream: `qr-${tag}-inner` });
|
|
@@ -1679,13 +2000,11 @@ var runStoreTck = (options) => {
|
|
|
1679
2000
|
const inner = `qr-${tag}-anchor`;
|
|
1680
2001
|
const longer = `qr-${tag}-anchor-extra`;
|
|
1681
2002
|
await store.commit(
|
|
1682
|
-
inner,
|
|
1683
|
-
[inc(1)],
|
|
2003
|
+
[{ stream: inner, msgs: [inc(1)] }],
|
|
1684
2004
|
make_meta({ stream: inner })
|
|
1685
2005
|
);
|
|
1686
2006
|
await store.commit(
|
|
1687
|
-
longer,
|
|
1688
|
-
[inc(2)],
|
|
2007
|
+
[{ stream: longer, msgs: [inc(2)] }],
|
|
1689
2008
|
make_meta({ stream: longer })
|
|
1690
2009
|
);
|
|
1691
2010
|
const got = await collect(store, { stream: `^qr-${tag}-anchor$` });
|
|
@@ -1698,18 +2017,15 @@ var runStoreTck = (options) => {
|
|
|
1698
2017
|
const b = `qr-${tag}-pfx-b`;
|
|
1699
2018
|
const other = `zz-${tag}-other`;
|
|
1700
2019
|
await store.commit(
|
|
1701
|
-
a,
|
|
1702
|
-
[inc(1)],
|
|
2020
|
+
[{ stream: a, msgs: [inc(1)] }],
|
|
1703
2021
|
make_meta({ stream: a })
|
|
1704
2022
|
);
|
|
1705
2023
|
await store.commit(
|
|
1706
|
-
b,
|
|
1707
|
-
[inc(2)],
|
|
2024
|
+
[{ stream: b, msgs: [inc(2)] }],
|
|
1708
2025
|
make_meta({ stream: b })
|
|
1709
2026
|
);
|
|
1710
2027
|
await store.commit(
|
|
1711
|
-
other,
|
|
1712
|
-
[inc(3)],
|
|
2028
|
+
[{ stream: other, msgs: [inc(3)] }],
|
|
1713
2029
|
make_meta({ stream: other })
|
|
1714
2030
|
);
|
|
1715
2031
|
const got = await collect(store, { stream: `^qr-${tag}-pfx-` });
|
|
@@ -1720,8 +2036,7 @@ var runStoreTck = (options) => {
|
|
|
1720
2036
|
const seed_streams = async (streams) => {
|
|
1721
2037
|
for (const s of streams)
|
|
1722
2038
|
await store.commit(
|
|
1723
|
-
s,
|
|
1724
|
-
[inc(1)],
|
|
2039
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
1725
2040
|
make_meta({ stream: s })
|
|
1726
2041
|
);
|
|
1727
2042
|
};
|
|
@@ -1885,13 +2200,22 @@ var runStoreTck = (options) => {
|
|
|
1885
2200
|
const leases = await store.claim(5, 5, `w-${uid()}`, 5e3);
|
|
1886
2201
|
expect8(leases.filter((l) => l.stream === s)).toHaveLength(0);
|
|
1887
2202
|
});
|
|
2203
|
+
it7("takes a target reading itself, whatever its name holds", async () => {
|
|
2204
|
+
const name = `self-a+b(${uid()}`;
|
|
2205
|
+
await store.subscribe([{ stream: name, source: name }]);
|
|
2206
|
+
const found = [];
|
|
2207
|
+
await store.query_streams((p) => found.push(p.stream), {
|
|
2208
|
+
stream: name,
|
|
2209
|
+
stream_exact: true
|
|
2210
|
+
});
|
|
2211
|
+
expect8(found).toEqual([name]);
|
|
2212
|
+
});
|
|
1888
2213
|
it7("claims a fresh subscription as soon as its first event is marked", async () => {
|
|
1889
2214
|
const s = `fresh-first-${uid()}`;
|
|
1890
2215
|
const src = `fresh-first-src-${uid()}`;
|
|
1891
2216
|
await store.subscribe([{ stream: s, source: src }]);
|
|
1892
2217
|
const [first] = await store.commit(
|
|
1893
|
-
src,
|
|
1894
|
-
[inc(1)],
|
|
2218
|
+
[{ stream: src, msgs: [inc(1)] }],
|
|
1895
2219
|
make_meta({ stream: src })
|
|
1896
2220
|
);
|
|
1897
2221
|
await store.subscribe([{ stream: s, correlated_at: first.id }]);
|
|
@@ -2080,8 +2404,7 @@ var runStoreTck = (options) => {
|
|
|
2080
2404
|
const src = `ws-unmarked-src-${uid()}`;
|
|
2081
2405
|
await store.subscribe([{ stream: s, source: src }]);
|
|
2082
2406
|
const [event] = await store.commit(
|
|
2083
|
-
src,
|
|
2084
|
-
[inc(1)],
|
|
2407
|
+
[{ stream: src, msgs: [inc(1)] }],
|
|
2085
2408
|
make_meta({ stream: src })
|
|
2086
2409
|
);
|
|
2087
2410
|
expect8(await claimable(s)).toBe(false);
|
|
@@ -2113,8 +2436,7 @@ var runStoreTck = (options) => {
|
|
|
2113
2436
|
const s = `claim-${uid()}`;
|
|
2114
2437
|
await store.subscribe([{ stream: s }]);
|
|
2115
2438
|
await store.commit(
|
|
2116
|
-
s,
|
|
2117
|
-
[inc(1)],
|
|
2439
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2118
2440
|
make_meta({ stream: s })
|
|
2119
2441
|
);
|
|
2120
2442
|
const by = `worker-${uid()}`;
|
|
@@ -2137,8 +2459,7 @@ var runStoreTck = (options) => {
|
|
|
2137
2459
|
const other = `claim-other-${uid()}`;
|
|
2138
2460
|
await store.subscribe([{ stream: s }]);
|
|
2139
2461
|
await store.commit(
|
|
2140
|
-
s,
|
|
2141
|
-
[inc(1)],
|
|
2462
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2142
2463
|
make_meta({ stream: s })
|
|
2143
2464
|
);
|
|
2144
2465
|
await correlate();
|
|
@@ -2147,8 +2468,7 @@ var runStoreTck = (options) => {
|
|
|
2147
2468
|
expect8(targetA).toBeDefined();
|
|
2148
2469
|
await store.subscribe([{ stream: other }]);
|
|
2149
2470
|
await store.commit(
|
|
2150
|
-
other,
|
|
2151
|
-
[inc(2)],
|
|
2471
|
+
[{ stream: other, msgs: [inc(2)] }],
|
|
2152
2472
|
make_meta({ stream: other })
|
|
2153
2473
|
);
|
|
2154
2474
|
await correlate();
|
|
@@ -2161,8 +2481,7 @@ var runStoreTck = (options) => {
|
|
|
2161
2481
|
const s = `claim-stolen-${uid()}`;
|
|
2162
2482
|
await store.subscribe([{ stream: s }]);
|
|
2163
2483
|
await store.commit(
|
|
2164
|
-
s,
|
|
2165
|
-
[inc(1), inc(2)],
|
|
2484
|
+
[{ stream: s, msgs: [inc(1), inc(2)] }],
|
|
2166
2485
|
make_meta({ stream: s })
|
|
2167
2486
|
);
|
|
2168
2487
|
await correlate();
|
|
@@ -2188,8 +2507,7 @@ var runStoreTck = (options) => {
|
|
|
2188
2507
|
const s = `claim-dual-${uid()}`;
|
|
2189
2508
|
await store.subscribe([{ stream: s }]);
|
|
2190
2509
|
await store.commit(
|
|
2191
|
-
s,
|
|
2192
|
-
[inc(1), inc(2)],
|
|
2510
|
+
[{ stream: s, msgs: [inc(1), inc(2)] }],
|
|
2193
2511
|
make_meta({ stream: s })
|
|
2194
2512
|
);
|
|
2195
2513
|
await correlate();
|
|
@@ -2218,13 +2536,11 @@ var runStoreTck = (options) => {
|
|
|
2218
2536
|
]);
|
|
2219
2537
|
for (const stream of highs)
|
|
2220
2538
|
await fresh.commit(
|
|
2221
|
-
stream,
|
|
2222
|
-
[inc(1)],
|
|
2539
|
+
[{ stream, msgs: [inc(1)] }],
|
|
2223
2540
|
make_meta({ stream })
|
|
2224
2541
|
);
|
|
2225
2542
|
await fresh.commit(
|
|
2226
|
-
low,
|
|
2227
|
-
[inc(1)],
|
|
2543
|
+
[{ stream: low, msgs: [inc(1)] }],
|
|
2228
2544
|
make_meta({ stream: low })
|
|
2229
2545
|
);
|
|
2230
2546
|
const by = `w-${uid()}`;
|
|
@@ -2240,8 +2556,7 @@ var runStoreTck = (options) => {
|
|
|
2240
2556
|
for (const l of leases) {
|
|
2241
2557
|
await fresh.ack([{ ...l, at: l.at + 1 }]);
|
|
2242
2558
|
await fresh.commit(
|
|
2243
|
-
l.stream,
|
|
2244
|
-
[inc(1)],
|
|
2559
|
+
[{ stream: l.stream, msgs: [inc(1)] }],
|
|
2245
2560
|
make_meta({ stream: l.stream })
|
|
2246
2561
|
);
|
|
2247
2562
|
}
|
|
@@ -2255,8 +2570,7 @@ var runStoreTck = (options) => {
|
|
|
2255
2570
|
const s = `claim-dedup-${uid()}`;
|
|
2256
2571
|
await store.subscribe([{ stream: s }]);
|
|
2257
2572
|
await store.commit(
|
|
2258
|
-
s,
|
|
2259
|
-
[inc(1)],
|
|
2573
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2260
2574
|
make_meta({ stream: s })
|
|
2261
2575
|
);
|
|
2262
2576
|
await correlate();
|
|
@@ -2269,13 +2583,11 @@ var runStoreTck = (options) => {
|
|
|
2269
2583
|
const sibling = `ack-sibling-${uid()}`;
|
|
2270
2584
|
await store.subscribe([{ stream: s }, { stream: sibling }]);
|
|
2271
2585
|
await store.commit(
|
|
2272
|
-
s,
|
|
2273
|
-
[inc(1)],
|
|
2586
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2274
2587
|
make_meta({ stream: s })
|
|
2275
2588
|
);
|
|
2276
2589
|
await store.commit(
|
|
2277
|
-
sibling,
|
|
2278
|
-
[inc(2)],
|
|
2590
|
+
[{ stream: sibling, msgs: [inc(2)] }],
|
|
2279
2591
|
make_meta({ stream: sibling })
|
|
2280
2592
|
);
|
|
2281
2593
|
await correlate();
|
|
@@ -2325,8 +2637,7 @@ var runStoreTck = (options) => {
|
|
|
2325
2637
|
const s = `lease-retry-${uid()}`;
|
|
2326
2638
|
await fresh.subscribe([{ stream: s }]);
|
|
2327
2639
|
await fresh.commit(
|
|
2328
|
-
s,
|
|
2329
|
-
[inc(1)],
|
|
2640
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2330
2641
|
make_meta({ stream: s })
|
|
2331
2642
|
);
|
|
2332
2643
|
await correlate(fresh);
|
|
@@ -2351,8 +2662,7 @@ var runStoreTck = (options) => {
|
|
|
2351
2662
|
const s = `lease-zero-${uid()}`;
|
|
2352
2663
|
await fresh.subscribe([{ stream: s }]);
|
|
2353
2664
|
const [committed] = await fresh.commit(
|
|
2354
|
-
s,
|
|
2355
|
-
[inc(1)],
|
|
2665
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2356
2666
|
make_meta({ stream: s })
|
|
2357
2667
|
);
|
|
2358
2668
|
await correlate(fresh);
|
|
@@ -2381,8 +2691,7 @@ var runStoreTck = (options) => {
|
|
|
2381
2691
|
const s = `lease-lag-${uid()}`;
|
|
2382
2692
|
await fresh.subscribe([{ stream: s }]);
|
|
2383
2693
|
await fresh.commit(
|
|
2384
|
-
s,
|
|
2385
|
-
[inc(1)],
|
|
2694
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2386
2695
|
make_meta({ stream: s })
|
|
2387
2696
|
);
|
|
2388
2697
|
await correlate(fresh);
|
|
@@ -2511,8 +2820,7 @@ var runStoreTck = (options) => {
|
|
|
2511
2820
|
await fresh.subscribe(streams.map((stream) => ({ stream })));
|
|
2512
2821
|
for (const stream of streams) {
|
|
2513
2822
|
await fresh.commit(
|
|
2514
|
-
stream,
|
|
2515
|
-
[inc(1)],
|
|
2823
|
+
[{ stream, msgs: [inc(1)] }],
|
|
2516
2824
|
make_meta({ stream })
|
|
2517
2825
|
);
|
|
2518
2826
|
}
|
|
@@ -2584,8 +2892,7 @@ var runStoreTck = (options) => {
|
|
|
2584
2892
|
const s = `block-${uid()}`;
|
|
2585
2893
|
await store.subscribe([{ stream: s }]);
|
|
2586
2894
|
await store.commit(
|
|
2587
|
-
s,
|
|
2588
|
-
[inc(1)],
|
|
2895
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2589
2896
|
make_meta({ stream: s })
|
|
2590
2897
|
);
|
|
2591
2898
|
await correlate();
|
|
@@ -2607,8 +2914,7 @@ var runStoreTck = (options) => {
|
|
|
2607
2914
|
const s = `block-returns-${uid()}`;
|
|
2608
2915
|
await store.subscribe([{ stream: s }]);
|
|
2609
2916
|
await store.commit(
|
|
2610
|
-
s,
|
|
2611
|
-
[inc(1)],
|
|
2917
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2612
2918
|
make_meta({ stream: s })
|
|
2613
2919
|
);
|
|
2614
2920
|
await correlate();
|
|
@@ -2633,8 +2939,7 @@ var runStoreTck = (options) => {
|
|
|
2633
2939
|
const s = `block-wrong-${uid()}`;
|
|
2634
2940
|
await store.subscribe([{ stream: s }]);
|
|
2635
2941
|
await store.commit(
|
|
2636
|
-
s,
|
|
2637
|
-
[inc(1)],
|
|
2942
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2638
2943
|
make_meta({ stream: s })
|
|
2639
2944
|
);
|
|
2640
2945
|
await correlate();
|
|
@@ -2652,8 +2957,7 @@ var runStoreTck = (options) => {
|
|
|
2652
2957
|
const s = `block-twice-${uid()}`;
|
|
2653
2958
|
await store.subscribe([{ stream: s }]);
|
|
2654
2959
|
await store.commit(
|
|
2655
|
-
s,
|
|
2656
|
-
[inc(1)],
|
|
2960
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2657
2961
|
make_meta({ stream: s })
|
|
2658
2962
|
);
|
|
2659
2963
|
await correlate();
|
|
@@ -2678,8 +2982,7 @@ var runStoreTck = (options) => {
|
|
|
2678
2982
|
await store.subscribe([{ stream: s }, { stream: ctl }]);
|
|
2679
2983
|
for (const st of [s, ctl])
|
|
2680
2984
|
await store.commit(
|
|
2681
|
-
st,
|
|
2682
|
-
[inc(1)],
|
|
2985
|
+
[{ stream: st, msgs: [inc(1)] }],
|
|
2683
2986
|
make_meta({ stream: st })
|
|
2684
2987
|
);
|
|
2685
2988
|
expect8(await store.defer([s], Date.now() + 36e5)).toBe(1);
|
|
@@ -2692,8 +2995,7 @@ var runStoreTck = (options) => {
|
|
|
2692
2995
|
const s = `defer-clock-${uid()}`;
|
|
2693
2996
|
await store.subscribe([{ stream: s }]);
|
|
2694
2997
|
await store.commit(
|
|
2695
|
-
s,
|
|
2696
|
-
[inc(1)],
|
|
2998
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2697
2999
|
make_meta({ stream: s })
|
|
2698
3000
|
);
|
|
2699
3001
|
expect8(await store.defer([s], Date.now() + 6e4)).toBe(1);
|
|
@@ -2716,8 +3018,7 @@ var runStoreTck = (options) => {
|
|
|
2716
3018
|
const s = `defer-past-${uid()}`;
|
|
2717
3019
|
await store.subscribe([{ stream: s }]);
|
|
2718
3020
|
await store.commit(
|
|
2719
|
-
s,
|
|
2720
|
-
[inc(1)],
|
|
3021
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2721
3022
|
make_meta({ stream: s })
|
|
2722
3023
|
);
|
|
2723
3024
|
expect8(await store.defer([s], Date.now() - 1e3)).toBe(1);
|
|
@@ -2733,8 +3034,7 @@ var runStoreTck = (options) => {
|
|
|
2733
3034
|
const s = `defer-retry-${uid()}`;
|
|
2734
3035
|
await store.subscribe([{ stream: s }]);
|
|
2735
3036
|
await store.commit(
|
|
2736
|
-
s,
|
|
2737
|
-
[inc(1)],
|
|
3037
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2738
3038
|
make_meta({ stream: s })
|
|
2739
3039
|
);
|
|
2740
3040
|
await store.defer([s], Date.now() + 36e5);
|
|
@@ -2756,8 +3056,7 @@ var runStoreTck = (options) => {
|
|
|
2756
3056
|
const s = `defer-reset-${uid()}`;
|
|
2757
3057
|
await store.subscribe([{ stream: s }]);
|
|
2758
3058
|
await store.commit(
|
|
2759
|
-
s,
|
|
2760
|
-
[inc(1)],
|
|
3059
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2761
3060
|
make_meta({ stream: s })
|
|
2762
3061
|
);
|
|
2763
3062
|
await store.defer([s], Date.now() + 36e5);
|
|
@@ -2772,8 +3071,7 @@ var runStoreTck = (options) => {
|
|
|
2772
3071
|
await store.subscribe([{ stream: deferred }, { stream: plain }]);
|
|
2773
3072
|
for (const s of [deferred, plain])
|
|
2774
3073
|
await store.commit(
|
|
2775
|
-
s,
|
|
2776
|
-
[inc(1)],
|
|
3074
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2777
3075
|
make_meta({ stream: s })
|
|
2778
3076
|
);
|
|
2779
3077
|
const due = Date.now() + 36e5;
|
|
@@ -2795,15 +3093,13 @@ var runStoreTck = (options) => {
|
|
|
2795
3093
|
await store.subscribe([{ stream: a }, { stream: b }]);
|
|
2796
3094
|
for (const s of [a, b])
|
|
2797
3095
|
await store.commit(
|
|
2798
|
-
s,
|
|
2799
|
-
[inc(1)],
|
|
3096
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2800
3097
|
make_meta({ stream: s })
|
|
2801
3098
|
);
|
|
2802
3099
|
const ctl = `defer-filterctl-${tag}`;
|
|
2803
3100
|
await store.subscribe([{ stream: ctl }]);
|
|
2804
3101
|
await store.commit(
|
|
2805
|
-
ctl,
|
|
2806
|
-
[inc(1)],
|
|
3102
|
+
[{ stream: ctl, msgs: [inc(1)] }],
|
|
2807
3103
|
make_meta({ stream: ctl })
|
|
2808
3104
|
);
|
|
2809
3105
|
const n = await store.defer(
|
|
@@ -2825,8 +3121,7 @@ var runStoreTck = (options) => {
|
|
|
2825
3121
|
const s = `defer-dup-${uid()}`;
|
|
2826
3122
|
await store.subscribe([{ stream: s }]);
|
|
2827
3123
|
await store.commit(
|
|
2828
|
-
s,
|
|
2829
|
-
[inc(1)],
|
|
3124
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2830
3125
|
make_meta({ stream: s })
|
|
2831
3126
|
);
|
|
2832
3127
|
expect8(await store.defer([s, s], Date.now() + 36e5)).toBe(1);
|
|
@@ -2838,13 +3133,11 @@ var runStoreTck = (options) => {
|
|
|
2838
3133
|
const ctl = `ackdefer-ctl-${uid()}`;
|
|
2839
3134
|
await store.subscribe([{ stream: s }, { stream: ctl }]);
|
|
2840
3135
|
await store.commit(
|
|
2841
|
-
s,
|
|
2842
|
-
[inc(1)],
|
|
3136
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2843
3137
|
make_meta({ stream: s })
|
|
2844
3138
|
);
|
|
2845
3139
|
const [ctl_head] = await store.commit(
|
|
2846
|
-
ctl,
|
|
2847
|
-
[inc(1)],
|
|
3140
|
+
[{ stream: ctl, msgs: [inc(1)] }],
|
|
2848
3141
|
make_meta({ stream: ctl })
|
|
2849
3142
|
);
|
|
2850
3143
|
await correlate();
|
|
@@ -2858,8 +3151,7 @@ var runStoreTck = (options) => {
|
|
|
2858
3151
|
expect8(acked.find((l) => l.stream === ctl)).toBeDefined();
|
|
2859
3152
|
expect8(acked.find((l) => l.stream === s)).toBeUndefined();
|
|
2860
3153
|
await store.commit(
|
|
2861
|
-
ctl,
|
|
2862
|
-
[inc(2)],
|
|
3154
|
+
[{ stream: ctl, msgs: [inc(2)] }],
|
|
2863
3155
|
make_meta({ stream: ctl })
|
|
2864
3156
|
);
|
|
2865
3157
|
await correlate();
|
|
@@ -2871,8 +3163,7 @@ var runStoreTck = (options) => {
|
|
|
2871
3163
|
const s = `ackdefer-past-${uid()}`;
|
|
2872
3164
|
await store.subscribe([{ stream: s }]);
|
|
2873
3165
|
await store.commit(
|
|
2874
|
-
s,
|
|
2875
|
-
[inc(1)],
|
|
3166
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2876
3167
|
make_meta({ stream: s })
|
|
2877
3168
|
);
|
|
2878
3169
|
await correlate();
|
|
@@ -2891,8 +3182,7 @@ var runStoreTck = (options) => {
|
|
|
2891
3182
|
const s = `ackdefer-retry-${uid()}`;
|
|
2892
3183
|
await store.subscribe([{ stream: s }]);
|
|
2893
3184
|
await store.commit(
|
|
2894
|
-
s,
|
|
2895
|
-
[inc(1)],
|
|
3185
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2896
3186
|
make_meta({ stream: s })
|
|
2897
3187
|
);
|
|
2898
3188
|
await correlate();
|
|
@@ -2911,13 +3201,11 @@ var runStoreTck = (options) => {
|
|
|
2911
3201
|
const s = `ackadvance-${uid()}`;
|
|
2912
3202
|
await store.subscribe([{ stream: s }]);
|
|
2913
3203
|
const [e1] = await store.commit(
|
|
2914
|
-
s,
|
|
2915
|
-
[inc(1)],
|
|
3204
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2916
3205
|
make_meta({ stream: s })
|
|
2917
3206
|
);
|
|
2918
3207
|
await store.commit(
|
|
2919
|
-
s,
|
|
2920
|
-
[inc(1)],
|
|
3208
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2921
3209
|
make_meta({ stream: s })
|
|
2922
3210
|
);
|
|
2923
3211
|
await correlate();
|
|
@@ -2939,8 +3227,7 @@ var runStoreTck = (options) => {
|
|
|
2939
3227
|
const s = `ackdefer-owner-${uid()}`;
|
|
2940
3228
|
await store.subscribe([{ stream: s }]);
|
|
2941
3229
|
await store.commit(
|
|
2942
|
-
s,
|
|
2943
|
-
[inc(1)],
|
|
3230
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2944
3231
|
make_meta({ stream: s })
|
|
2945
3232
|
);
|
|
2946
3233
|
await correlate();
|
|
@@ -2958,8 +3245,7 @@ var runStoreTck = (options) => {
|
|
|
2958
3245
|
const s = `reset-${uid()}`;
|
|
2959
3246
|
await store.subscribe([{ stream: s }]);
|
|
2960
3247
|
await store.commit(
|
|
2961
|
-
s,
|
|
2962
|
-
[inc(1)],
|
|
3248
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2963
3249
|
make_meta({ stream: s })
|
|
2964
3250
|
);
|
|
2965
3251
|
await correlate();
|
|
@@ -2978,8 +3264,7 @@ var runStoreTck = (options) => {
|
|
|
2978
3264
|
const s = `reset-blk-${uid()}`;
|
|
2979
3265
|
await store.subscribe([{ stream: s }]);
|
|
2980
3266
|
await store.commit(
|
|
2981
|
-
s,
|
|
2982
|
-
[inc(1)],
|
|
3267
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
2983
3268
|
make_meta({ stream: s })
|
|
2984
3269
|
);
|
|
2985
3270
|
await correlate();
|
|
@@ -3001,8 +3286,7 @@ var runStoreTck = (options) => {
|
|
|
3001
3286
|
const s = `reset-dup-${uid()}`;
|
|
3002
3287
|
await store.subscribe([{ stream: s }]);
|
|
3003
3288
|
await store.commit(
|
|
3004
|
-
s,
|
|
3005
|
-
[inc(1)],
|
|
3289
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
3006
3290
|
make_meta({ stream: s })
|
|
3007
3291
|
);
|
|
3008
3292
|
expect8(await store.reset([s, s])).toBe(1);
|
|
@@ -3013,13 +3297,11 @@ var runStoreTck = (options) => {
|
|
|
3013
3297
|
const s = `unblock-${uid()}`;
|
|
3014
3298
|
await store.subscribe([{ stream: s }]);
|
|
3015
3299
|
await store.commit(
|
|
3016
|
-
s,
|
|
3017
|
-
[inc(1)],
|
|
3300
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
3018
3301
|
make_meta({ stream: s })
|
|
3019
3302
|
);
|
|
3020
3303
|
await store.commit(
|
|
3021
|
-
s,
|
|
3022
|
-
[inc(2)],
|
|
3304
|
+
[{ stream: s, msgs: [inc(2)] }],
|
|
3023
3305
|
make_meta({ stream: s })
|
|
3024
3306
|
);
|
|
3025
3307
|
await correlate();
|
|
@@ -3052,8 +3334,7 @@ var runStoreTck = (options) => {
|
|
|
3052
3334
|
const s = `unblock-noop-${uid()}`;
|
|
3053
3335
|
await store.subscribe([{ stream: s }]);
|
|
3054
3336
|
await store.commit(
|
|
3055
|
-
s,
|
|
3056
|
-
[inc(1)],
|
|
3337
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
3057
3338
|
make_meta({ stream: s })
|
|
3058
3339
|
);
|
|
3059
3340
|
expect8(await store.unblock([s])).toBe(0);
|
|
@@ -3067,13 +3348,11 @@ var runStoreTck = (options) => {
|
|
|
3067
3348
|
const s2 = `unblock-mix-b-${uid()}`;
|
|
3068
3349
|
await store.subscribe([{ stream: s1 }, { stream: s2 }]);
|
|
3069
3350
|
await store.commit(
|
|
3070
|
-
s1,
|
|
3071
|
-
[inc(1)],
|
|
3351
|
+
[{ stream: s1, msgs: [inc(1)] }],
|
|
3072
3352
|
make_meta({ stream: s1 })
|
|
3073
3353
|
);
|
|
3074
3354
|
await store.commit(
|
|
3075
|
-
s2,
|
|
3076
|
-
[inc(1)],
|
|
3355
|
+
[{ stream: s2, msgs: [inc(1)] }],
|
|
3077
3356
|
make_meta({ stream: s2 })
|
|
3078
3357
|
);
|
|
3079
3358
|
await correlate();
|
|
@@ -3091,18 +3370,15 @@ var runStoreTck = (options) => {
|
|
|
3091
3370
|
const s3 = `other-${tag}`;
|
|
3092
3371
|
await store.subscribe([{ stream: s1 }, { stream: s2 }, { stream: s3 }]);
|
|
3093
3372
|
await store.commit(
|
|
3094
|
-
s1,
|
|
3095
|
-
[inc(1)],
|
|
3373
|
+
[{ stream: s1, msgs: [inc(1)] }],
|
|
3096
3374
|
make_meta({ stream: s1 })
|
|
3097
3375
|
);
|
|
3098
3376
|
await store.commit(
|
|
3099
|
-
s2,
|
|
3100
|
-
[inc(1)],
|
|
3377
|
+
[{ stream: s2, msgs: [inc(1)] }],
|
|
3101
3378
|
make_meta({ stream: s2 })
|
|
3102
3379
|
);
|
|
3103
3380
|
await store.commit(
|
|
3104
|
-
s3,
|
|
3105
|
-
[inc(1)],
|
|
3381
|
+
[{ stream: s3, msgs: [inc(1)] }],
|
|
3106
3382
|
make_meta({ stream: s3 })
|
|
3107
3383
|
);
|
|
3108
3384
|
await correlate();
|
|
@@ -3130,13 +3406,11 @@ var runStoreTck = (options) => {
|
|
|
3130
3406
|
const s2 = `unblock-empty-${tag}-b`;
|
|
3131
3407
|
await store.subscribe([{ stream: s1 }, { stream: s2 }]);
|
|
3132
3408
|
await store.commit(
|
|
3133
|
-
s1,
|
|
3134
|
-
[inc(1)],
|
|
3409
|
+
[{ stream: s1, msgs: [inc(1)] }],
|
|
3135
3410
|
make_meta({ stream: s1 })
|
|
3136
3411
|
);
|
|
3137
3412
|
await store.commit(
|
|
3138
|
-
s2,
|
|
3139
|
-
[inc(1)],
|
|
3413
|
+
[{ stream: s2, msgs: [inc(1)] }],
|
|
3140
3414
|
make_meta({ stream: s2 })
|
|
3141
3415
|
);
|
|
3142
3416
|
await correlate();
|
|
@@ -3156,8 +3430,7 @@ var runStoreTck = (options) => {
|
|
|
3156
3430
|
const s = `unblock-blocked-false-${tag}`;
|
|
3157
3431
|
await store.subscribe([{ stream: s }]);
|
|
3158
3432
|
await store.commit(
|
|
3159
|
-
s,
|
|
3160
|
-
[inc(1)],
|
|
3433
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
3161
3434
|
make_meta({ stream: s })
|
|
3162
3435
|
);
|
|
3163
3436
|
expect8(
|
|
@@ -3180,18 +3453,15 @@ var runStoreTck = (options) => {
|
|
|
3180
3453
|
{ stream: other }
|
|
3181
3454
|
]);
|
|
3182
3455
|
await store.commit(
|
|
3183
|
-
s1,
|
|
3184
|
-
[inc(1)],
|
|
3456
|
+
[{ stream: s1, msgs: [inc(1)] }],
|
|
3185
3457
|
make_meta({ stream: s1 })
|
|
3186
3458
|
);
|
|
3187
3459
|
await store.commit(
|
|
3188
|
-
s2,
|
|
3189
|
-
[inc(1)],
|
|
3460
|
+
[{ stream: s2, msgs: [inc(1)] }],
|
|
3190
3461
|
make_meta({ stream: s2 })
|
|
3191
3462
|
);
|
|
3192
3463
|
await store.commit(
|
|
3193
|
-
other,
|
|
3194
|
-
[inc(1)],
|
|
3464
|
+
[{ stream: other, msgs: [inc(1)] }],
|
|
3195
3465
|
make_meta({ stream: other })
|
|
3196
3466
|
);
|
|
3197
3467
|
await correlate();
|
|
@@ -3222,13 +3492,11 @@ var runStoreTck = (options) => {
|
|
|
3222
3492
|
const s2 = `reset-blocked-${tag}-fine`;
|
|
3223
3493
|
await store.subscribe([{ stream: s1 }, { stream: s2 }]);
|
|
3224
3494
|
await store.commit(
|
|
3225
|
-
s1,
|
|
3226
|
-
[inc(1)],
|
|
3495
|
+
[{ stream: s1, msgs: [inc(1)] }],
|
|
3227
3496
|
make_meta({ stream: s1 })
|
|
3228
3497
|
);
|
|
3229
3498
|
await store.commit(
|
|
3230
|
-
s2,
|
|
3231
|
-
[inc(1)],
|
|
3499
|
+
[{ stream: s2, msgs: [inc(1)] }],
|
|
3232
3500
|
make_meta({ stream: s2 })
|
|
3233
3501
|
);
|
|
3234
3502
|
await correlate();
|
|
@@ -3307,8 +3575,7 @@ var runStoreTck = (options) => {
|
|
|
3307
3575
|
const ok = `pri-${tag}-ok`;
|
|
3308
3576
|
const bad = `pri-${tag}-bad`;
|
|
3309
3577
|
await fresh.commit(
|
|
3310
|
-
src,
|
|
3311
|
-
[inc(1)],
|
|
3578
|
+
[{ stream: src, msgs: [inc(1)] }],
|
|
3312
3579
|
make_meta({ stream: src })
|
|
3313
3580
|
);
|
|
3314
3581
|
await fresh.subscribe([
|
|
@@ -3354,8 +3621,7 @@ var runStoreTck = (options) => {
|
|
|
3354
3621
|
const tag = uid();
|
|
3355
3622
|
const src = `pri-src-${tag}`;
|
|
3356
3623
|
await fresh.commit(
|
|
3357
|
-
src,
|
|
3358
|
-
[inc(1), inc(2)],
|
|
3624
|
+
[{ stream: src, msgs: [inc(1), inc(2)] }],
|
|
3359
3625
|
make_meta({ stream: src })
|
|
3360
3626
|
);
|
|
3361
3627
|
await fresh.subscribe([
|
|
@@ -3453,13 +3719,11 @@ var runStoreTck = (options) => {
|
|
|
3453
3719
|
const sub_default = `lane-claim-def-${tag}`;
|
|
3454
3720
|
const sub_slow = `lane-claim-slow-${tag}`;
|
|
3455
3721
|
await store.commit(
|
|
3456
|
-
src1,
|
|
3457
|
-
[inc(1)],
|
|
3722
|
+
[{ stream: src1, msgs: [inc(1)] }],
|
|
3458
3723
|
make_meta({ stream: src1 })
|
|
3459
3724
|
);
|
|
3460
3725
|
await store.commit(
|
|
3461
|
-
src2,
|
|
3462
|
-
[inc(1)],
|
|
3726
|
+
[{ stream: src2, msgs: [inc(1)] }],
|
|
3463
3727
|
make_meta({ stream: src2 })
|
|
3464
3728
|
);
|
|
3465
3729
|
await store.subscribe([
|
|
@@ -3526,8 +3790,7 @@ var runStoreTck = (options) => {
|
|
|
3526
3790
|
const a = `lane-reset-a-${tag}`;
|
|
3527
3791
|
const b = `lane-reset-b-${tag}`;
|
|
3528
3792
|
await store.commit(
|
|
3529
|
-
src,
|
|
3530
|
-
[inc(1)],
|
|
3793
|
+
[{ stream: src, msgs: [inc(1)] }],
|
|
3531
3794
|
make_meta({ stream: src })
|
|
3532
3795
|
);
|
|
3533
3796
|
await store.subscribe([
|
|
@@ -3556,8 +3819,7 @@ var runStoreTck = (options) => {
|
|
|
3556
3819
|
const a = `lane-ub-a-${tag}`;
|
|
3557
3820
|
const b = `lane-ub-b-${tag}`;
|
|
3558
3821
|
await store.commit(
|
|
3559
|
-
src,
|
|
3560
|
-
[inc(1)],
|
|
3822
|
+
[{ stream: src, msgs: [inc(1)] }],
|
|
3561
3823
|
make_meta({ stream: src })
|
|
3562
3824
|
);
|
|
3563
3825
|
await store.subscribe([
|
|
@@ -3586,8 +3848,7 @@ var runStoreTck = (options) => {
|
|
|
3586
3848
|
const tag = uid();
|
|
3587
3849
|
const long = `${tag}-${"x".repeat(140)}`;
|
|
3588
3850
|
await store.commit(
|
|
3589
|
-
long,
|
|
3590
|
-
[inc(1)],
|
|
3851
|
+
[{ stream: long, msgs: [inc(1)] }],
|
|
3591
3852
|
make_meta({ stream: long })
|
|
3592
3853
|
);
|
|
3593
3854
|
await store.subscribe([
|
|
@@ -3612,8 +3873,7 @@ var runStoreTck = (options) => {
|
|
|
3612
3873
|
for (const s of [restarted, retired]) {
|
|
3613
3874
|
await store.subscribe([{ stream: s }]);
|
|
3614
3875
|
await store.commit(
|
|
3615
|
-
s,
|
|
3616
|
-
[inc(1)],
|
|
3876
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
3617
3877
|
make_meta({ stream: s })
|
|
3618
3878
|
);
|
|
3619
3879
|
}
|
|
@@ -3637,8 +3897,7 @@ var runStoreTck = (options) => {
|
|
|
3637
3897
|
const lane = `inert-lane-${uid()}`;
|
|
3638
3898
|
const s = `trunc-inert-${uid()}`;
|
|
3639
3899
|
const [e] = await store.commit(
|
|
3640
|
-
s,
|
|
3641
|
-
[inc(1)],
|
|
3900
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
3642
3901
|
make_meta({ stream: s })
|
|
3643
3902
|
);
|
|
3644
3903
|
await store.subscribe([{ stream: s, correlated_at: e.id, lane }]);
|
|
@@ -3653,8 +3912,7 @@ var runStoreTck = (options) => {
|
|
|
3653
3912
|
it7("seeds a tombstone when no snapshot is provided", async () => {
|
|
3654
3913
|
const s = `trunc-tomb-${uid()}`;
|
|
3655
3914
|
await store.commit(
|
|
3656
|
-
s,
|
|
3657
|
-
[inc(1), inc(2)],
|
|
3915
|
+
[{ stream: s, msgs: [inc(1), inc(2)] }],
|
|
3658
3916
|
make_meta({ stream: s })
|
|
3659
3917
|
);
|
|
3660
3918
|
const result = await store.truncate([{ stream: s }]);
|
|
@@ -3674,8 +3932,7 @@ var runStoreTck = (options) => {
|
|
|
3674
3932
|
it7("seeds a snapshot when one is provided", async () => {
|
|
3675
3933
|
const s = `trunc-snap-${uid()}`;
|
|
3676
3934
|
await store.commit(
|
|
3677
|
-
s,
|
|
3678
|
-
[inc(1)],
|
|
3935
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
3679
3936
|
make_meta({ stream: s })
|
|
3680
3937
|
);
|
|
3681
3938
|
const result = await store.truncate([
|
|
@@ -3698,8 +3955,7 @@ var runStoreTck = (options) => {
|
|
|
3698
3955
|
it7("leaves exactly one seed when a stream is listed twice", async () => {
|
|
3699
3956
|
const s = `trunc-dup-${uid()}`;
|
|
3700
3957
|
await store.commit(
|
|
3701
|
-
s,
|
|
3702
|
-
[inc(1), inc(2)],
|
|
3958
|
+
[{ stream: s, msgs: [inc(1), inc(2)] }],
|
|
3703
3959
|
make_meta({ stream: s })
|
|
3704
3960
|
);
|
|
3705
3961
|
const result = await store.truncate([
|
|
@@ -3720,13 +3976,11 @@ var runStoreTck = (options) => {
|
|
|
3720
3976
|
it7("applies windowed targets before full ones", async () => {
|
|
3721
3977
|
const s = `trunc-mix-${uid()}`;
|
|
3722
3978
|
await store.commit(
|
|
3723
|
-
s,
|
|
3724
|
-
[inc(1)],
|
|
3979
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
3725
3980
|
make_meta({ stream: s })
|
|
3726
3981
|
);
|
|
3727
3982
|
await store.commit(
|
|
3728
|
-
s,
|
|
3729
|
-
[inc(2)],
|
|
3983
|
+
[{ stream: s, msgs: [inc(2)] }],
|
|
3730
3984
|
make_meta({ stream: s })
|
|
3731
3985
|
);
|
|
3732
3986
|
await sleep(5);
|
|
@@ -3763,28 +4017,23 @@ var runStoreTck = (options) => {
|
|
|
3763
4017
|
describe8("windowed (before boundary)", () => {
|
|
3764
4018
|
async function seed_windowed(s) {
|
|
3765
4019
|
await store.commit(
|
|
3766
|
-
s,
|
|
3767
|
-
[inc(1), inc(1)],
|
|
4020
|
+
[{ stream: s, msgs: [inc(1), inc(1)] }],
|
|
3768
4021
|
make_meta({ stream: s })
|
|
3769
4022
|
);
|
|
3770
4023
|
const [snap_a] = await store.commit(
|
|
3771
|
-
s,
|
|
3772
|
-
[{ name: SNAP_EVENT2, data: { count: 2 } }],
|
|
4024
|
+
[{ stream: s, msgs: [{ name: SNAP_EVENT2, data: { count: 2 } }] }],
|
|
3773
4025
|
make_meta({ stream: s })
|
|
3774
4026
|
);
|
|
3775
4027
|
await store.commit(
|
|
3776
|
-
s,
|
|
3777
|
-
[inc(1)],
|
|
4028
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
3778
4029
|
make_meta({ stream: s })
|
|
3779
4030
|
);
|
|
3780
4031
|
const [snap_b] = await store.commit(
|
|
3781
|
-
s,
|
|
3782
|
-
[{ name: SNAP_EVENT2, data: { count: 3 } }],
|
|
4032
|
+
[{ stream: s, msgs: [{ name: SNAP_EVENT2, data: { count: 3 } }] }],
|
|
3783
4033
|
make_meta({ stream: s })
|
|
3784
4034
|
);
|
|
3785
4035
|
await store.commit(
|
|
3786
|
-
s,
|
|
3787
|
-
[inc(1)],
|
|
4036
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
3788
4037
|
make_meta({ stream: s })
|
|
3789
4038
|
);
|
|
3790
4039
|
return { snap_a, snap_b };
|
|
@@ -3854,8 +4103,7 @@ var runStoreTck = (options) => {
|
|
|
3854
4103
|
it7("no-ops when no snapshot qualifies \u2014 stream absent from the result, events untouched", async () => {
|
|
3855
4104
|
const s = `trunc-win-noop-${uid()}`;
|
|
3856
4105
|
await store.commit(
|
|
3857
|
-
s,
|
|
3858
|
-
[inc(1), inc(1)],
|
|
4106
|
+
[{ stream: s, msgs: [inc(1), inc(1)] }],
|
|
3859
4107
|
make_meta({ stream: s })
|
|
3860
4108
|
);
|
|
3861
4109
|
const none = await store.truncate([
|
|
@@ -3863,8 +4111,7 @@ var runStoreTck = (options) => {
|
|
|
3863
4111
|
]);
|
|
3864
4112
|
expect8(none.has(s)).toBe(false);
|
|
3865
4113
|
await store.commit(
|
|
3866
|
-
s,
|
|
3867
|
-
[{ name: SNAP_EVENT2, data: { count: 2 } }],
|
|
4114
|
+
[{ stream: s, msgs: [{ name: SNAP_EVENT2, data: { count: 2 } }] }],
|
|
3868
4115
|
make_meta({ stream: s })
|
|
3869
4116
|
);
|
|
3870
4117
|
const too_early = await store.truncate([
|
|
@@ -3902,8 +4149,7 @@ var runStoreTck = (options) => {
|
|
|
3902
4149
|
const f = `trunc-win-mix-f-${uid()}`;
|
|
3903
4150
|
const { snap_b } = await seed_windowed(w);
|
|
3904
4151
|
await store.commit(
|
|
3905
|
-
f,
|
|
3906
|
-
[inc(1)],
|
|
4152
|
+
[{ stream: f, msgs: [inc(1)] }],
|
|
3907
4153
|
make_meta({ stream: f })
|
|
3908
4154
|
);
|
|
3909
4155
|
const result = await store.truncate([
|
|
@@ -3923,8 +4169,7 @@ var runStoreTck = (options) => {
|
|
|
3923
4169
|
{ stream: s, before: new Date(Date.now() + 6e4) }
|
|
3924
4170
|
]);
|
|
3925
4171
|
const [next] = await store.commit(
|
|
3926
|
-
s,
|
|
3927
|
-
[inc(1)],
|
|
4172
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
3928
4173
|
make_meta({ stream: s })
|
|
3929
4174
|
);
|
|
3930
4175
|
expect8(next.version).toBe(6);
|
|
@@ -4062,8 +4307,7 @@ var runStoreTck = (options) => {
|
|
|
4062
4307
|
const sibling = `qb-${tag}-other`;
|
|
4063
4308
|
await store.subscribe([{ stream: s }, { stream: sibling }]);
|
|
4064
4309
|
await store.commit(
|
|
4065
|
-
s,
|
|
4066
|
-
[inc(1)],
|
|
4310
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
4067
4311
|
make_meta({ stream: s })
|
|
4068
4312
|
);
|
|
4069
4313
|
await correlate();
|
|
@@ -4094,18 +4338,15 @@ var runStoreTck = (options) => {
|
|
|
4094
4338
|
const sB = `qst-${tag}-b`;
|
|
4095
4339
|
const sUnasked = `qst-${tag}-unasked`;
|
|
4096
4340
|
await store.commit(
|
|
4097
|
-
sA,
|
|
4098
|
-
[inc(1), inc(2)],
|
|
4341
|
+
[{ stream: sA, msgs: [inc(1), inc(2)] }],
|
|
4099
4342
|
make_meta({ stream: sA })
|
|
4100
4343
|
);
|
|
4101
4344
|
await store.commit(
|
|
4102
|
-
sB,
|
|
4103
|
-
[dec(5)],
|
|
4345
|
+
[{ stream: sB, msgs: [dec(5)] }],
|
|
4104
4346
|
make_meta({ stream: sB })
|
|
4105
4347
|
);
|
|
4106
4348
|
await store.commit(
|
|
4107
|
-
sUnasked,
|
|
4108
|
-
[inc(99)],
|
|
4349
|
+
[{ stream: sUnasked, msgs: [inc(99)] }],
|
|
4109
4350
|
make_meta({ stream: sUnasked })
|
|
4110
4351
|
);
|
|
4111
4352
|
const stats = await store.query_stats([sA, sB]);
|
|
@@ -4123,8 +4364,7 @@ var runStoreTck = (options) => {
|
|
|
4123
4364
|
it7("limit: 0 returns no rows", async () => {
|
|
4124
4365
|
const s = `qst-zero-${uid()}`;
|
|
4125
4366
|
await store.commit(
|
|
4126
|
-
s,
|
|
4127
|
-
[inc(1)],
|
|
4367
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
4128
4368
|
make_meta({ stream: s })
|
|
4129
4369
|
);
|
|
4130
4370
|
const filter = { stream: s, stream_exact: true };
|
|
@@ -4145,8 +4385,7 @@ var runStoreTck = (options) => {
|
|
|
4145
4385
|
];
|
|
4146
4386
|
for (const s of names)
|
|
4147
4387
|
await store.commit(
|
|
4148
|
-
s,
|
|
4149
|
-
[inc(1)],
|
|
4388
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
4150
4389
|
make_meta({ stream: s })
|
|
4151
4390
|
);
|
|
4152
4391
|
const visited = [];
|
|
@@ -4169,18 +4408,15 @@ var runStoreTck = (options) => {
|
|
|
4169
4408
|
const tag = uid();
|
|
4170
4409
|
const s = `qst-tail-${tag}`;
|
|
4171
4410
|
await store.commit(
|
|
4172
|
-
s,
|
|
4173
|
-
[inc(1)],
|
|
4411
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
4174
4412
|
make_meta({ stream: s })
|
|
4175
4413
|
);
|
|
4176
4414
|
await store.commit(
|
|
4177
|
-
s,
|
|
4178
|
-
[inc(2)],
|
|
4415
|
+
[{ stream: s, msgs: [inc(2)] }],
|
|
4179
4416
|
make_meta({ stream: s })
|
|
4180
4417
|
);
|
|
4181
4418
|
await store.commit(
|
|
4182
|
-
s,
|
|
4183
|
-
[inc(3)],
|
|
4419
|
+
[{ stream: s, msgs: [inc(3)] }],
|
|
4184
4420
|
make_meta({ stream: s })
|
|
4185
4421
|
);
|
|
4186
4422
|
const stats = await store.query_stats([s], {
|
|
@@ -4196,14 +4432,12 @@ var runStoreTck = (options) => {
|
|
|
4196
4432
|
const tag = uid();
|
|
4197
4433
|
const s = `qst-cn-${tag}`;
|
|
4198
4434
|
await store.commit(
|
|
4199
|
-
s,
|
|
4200
|
-
[inc(1)],
|
|
4435
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
4201
4436
|
make_meta({ stream: s })
|
|
4202
4437
|
);
|
|
4203
4438
|
await store.truncate([{ stream: s, snapshot: { count: 99 } }]);
|
|
4204
4439
|
await store.commit(
|
|
4205
|
-
s,
|
|
4206
|
-
[inc(2), inc(3), dec(1)],
|
|
4440
|
+
[{ stream: s, msgs: [inc(2), inc(3), dec(1)] }],
|
|
4207
4441
|
make_meta({ stream: s })
|
|
4208
4442
|
);
|
|
4209
4443
|
const stats = await store.query_stats([s], {
|
|
@@ -4222,13 +4456,11 @@ var runStoreTck = (options) => {
|
|
|
4222
4456
|
const s = `qst-excl-${tag}`;
|
|
4223
4457
|
const sAllOut = `qst-allout-${tag}`;
|
|
4224
4458
|
await store.commit(
|
|
4225
|
-
s,
|
|
4226
|
-
[inc(1), dec(2), inc(3)],
|
|
4459
|
+
[{ stream: s, msgs: [inc(1), dec(2), inc(3)] }],
|
|
4227
4460
|
make_meta({ stream: s })
|
|
4228
4461
|
);
|
|
4229
4462
|
await store.commit(
|
|
4230
|
-
sAllOut,
|
|
4231
|
-
[inc(7)],
|
|
4463
|
+
[{ stream: sAllOut, msgs: [inc(7)] }],
|
|
4232
4464
|
make_meta({ stream: sAllOut })
|
|
4233
4465
|
);
|
|
4234
4466
|
const all = await store.query_stats([s]);
|
|
@@ -4252,18 +4484,15 @@ var runStoreTck = (options) => {
|
|
|
4252
4484
|
const tag = uid();
|
|
4253
4485
|
const s = `qst-tt-${tag}`;
|
|
4254
4486
|
const c1 = await store.commit(
|
|
4255
|
-
s,
|
|
4256
|
-
[inc(1)],
|
|
4487
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
4257
4488
|
make_meta({ stream: s })
|
|
4258
4489
|
);
|
|
4259
4490
|
const c2 = await store.commit(
|
|
4260
|
-
s,
|
|
4261
|
-
[inc(2)],
|
|
4491
|
+
[{ stream: s, msgs: [inc(2)] }],
|
|
4262
4492
|
make_meta({ stream: s })
|
|
4263
4493
|
);
|
|
4264
4494
|
await store.commit(
|
|
4265
|
-
s,
|
|
4266
|
-
[inc(3)],
|
|
4495
|
+
[{ stream: s, msgs: [inc(3)] }],
|
|
4267
4496
|
make_meta({ stream: s })
|
|
4268
4497
|
);
|
|
4269
4498
|
const before = c2[0].id;
|
|
@@ -4287,18 +4516,15 @@ var runStoreTck = (options) => {
|
|
|
4287
4516
|
const sB = `qsf-${tag}-orders-2`;
|
|
4288
4517
|
const sOther = `qsf-${tag}-users-1`;
|
|
4289
4518
|
await store.commit(
|
|
4290
|
-
sA,
|
|
4291
|
-
[inc(1)],
|
|
4519
|
+
[{ stream: sA, msgs: [inc(1)] }],
|
|
4292
4520
|
make_meta({ stream: sA })
|
|
4293
4521
|
);
|
|
4294
4522
|
await store.commit(
|
|
4295
|
-
sB,
|
|
4296
|
-
[inc(2)],
|
|
4523
|
+
[{ stream: sB, msgs: [inc(2)] }],
|
|
4297
4524
|
make_meta({ stream: sB })
|
|
4298
4525
|
);
|
|
4299
4526
|
await store.commit(
|
|
4300
|
-
sOther,
|
|
4301
|
-
[inc(3)],
|
|
4527
|
+
[{ stream: sOther, msgs: [inc(3)] }],
|
|
4302
4528
|
make_meta({ stream: sOther })
|
|
4303
4529
|
);
|
|
4304
4530
|
const orders = await store.query_stats({
|
|
@@ -4321,13 +4547,11 @@ var runStoreTck = (options) => {
|
|
|
4321
4547
|
const b = `qsc-${tag}-b`;
|
|
4322
4548
|
await store.subscribe([{ stream: a }, { stream: b }]);
|
|
4323
4549
|
await store.commit(
|
|
4324
|
-
a,
|
|
4325
|
-
[inc(1)],
|
|
4550
|
+
[{ stream: a, msgs: [inc(1)] }],
|
|
4326
4551
|
make_meta({ stream: a })
|
|
4327
4552
|
);
|
|
4328
4553
|
await store.commit(
|
|
4329
|
-
b,
|
|
4330
|
-
[inc(2)],
|
|
4554
|
+
[{ stream: b, msgs: [inc(2)] }],
|
|
4331
4555
|
make_meta({ stream: b })
|
|
4332
4556
|
);
|
|
4333
4557
|
await correlate();
|
|
@@ -4352,13 +4576,11 @@ var runStoreTck = (options) => {
|
|
|
4352
4576
|
const a = `qse-${tag}-a`;
|
|
4353
4577
|
const b = `qse-${tag}-b`;
|
|
4354
4578
|
await store.commit(
|
|
4355
|
-
a,
|
|
4356
|
-
[inc(1)],
|
|
4579
|
+
[{ stream: a, msgs: [inc(1)] }],
|
|
4357
4580
|
make_meta({ stream: a })
|
|
4358
4581
|
);
|
|
4359
4582
|
await store.commit(
|
|
4360
|
-
b,
|
|
4361
|
-
[dec(2)],
|
|
4583
|
+
[{ stream: b, msgs: [dec(2)] }],
|
|
4362
4584
|
make_meta({ stream: b })
|
|
4363
4585
|
);
|
|
4364
4586
|
const all = await store.query_stats({});
|
|
@@ -4369,8 +4591,7 @@ var runStoreTck = (options) => {
|
|
|
4369
4591
|
const tag = uid();
|
|
4370
4592
|
const s = `qsfl-${tag}`;
|
|
4371
4593
|
await store.commit(
|
|
4372
|
-
s,
|
|
4373
|
-
[inc(1), inc(2), dec(3)],
|
|
4594
|
+
[{ stream: s, msgs: [inc(1), inc(2), dec(3)] }],
|
|
4374
4595
|
make_meta({ stream: s })
|
|
4375
4596
|
);
|
|
4376
4597
|
const c = await store.query_stats([s], {
|
|
@@ -4401,8 +4622,7 @@ var runStoreTck = (options) => {
|
|
|
4401
4622
|
];
|
|
4402
4623
|
for (const s of streams) {
|
|
4403
4624
|
await store.commit(
|
|
4404
|
-
s,
|
|
4405
|
-
[inc(1)],
|
|
4625
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
4406
4626
|
make_meta({ stream: s })
|
|
4407
4627
|
);
|
|
4408
4628
|
}
|
|
@@ -4432,8 +4652,7 @@ var runStoreTck = (options) => {
|
|
|
4432
4652
|
const tag = uid();
|
|
4433
4653
|
for (const s of [`qsc-${tag}-c`, `qsc-${tag}-a`, `qsc-${tag}-b`])
|
|
4434
4654
|
await store.commit(
|
|
4435
|
-
s,
|
|
4436
|
-
[inc(1), inc(2)],
|
|
4655
|
+
[{ stream: s, msgs: [inc(1), inc(2)] }],
|
|
4437
4656
|
make_meta({ stream: s })
|
|
4438
4657
|
);
|
|
4439
4658
|
const pattern = { stream: `qsc-${tag}-.*` };
|
|
@@ -4582,8 +4801,7 @@ var runStoreTck = (options) => {
|
|
|
4582
4801
|
const s = `head-${uid()}`;
|
|
4583
4802
|
await store.subscribe([{ stream: s }]);
|
|
4584
4803
|
await store.commit(
|
|
4585
|
-
s,
|
|
4586
|
-
[inc(1)],
|
|
4804
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
4587
4805
|
make_meta({ stream: s })
|
|
4588
4806
|
);
|
|
4589
4807
|
const positions = [];
|
|
@@ -4599,7 +4817,7 @@ var runStoreTck = (options) => {
|
|
|
4599
4817
|
const actor2 = { id: "reader", name: "Reader" };
|
|
4600
4818
|
const reader = (shape) => {
|
|
4601
4819
|
const Happened = z2.object(shape);
|
|
4602
|
-
return state({ Reader: z2.object({ n: z2.number() }) }).init(() => ({ n: 0 })).emits({ Happened }).patch({ Happened: (_, s) => ({ n: s.n + 1 }) }).on({ Do: Happened }).emit(
|
|
4820
|
+
return state({ Reader: z2.object({ n: z2.number() }) }).init(() => ({ n: 0 })).emits({ Happened }).patch({ Happened: (_, s) => ({ n: s.n + 1 }) }).on({ Do: Happened }).emit("Happened").build();
|
|
4603
4821
|
};
|
|
4604
4822
|
const over = async (S) => {
|
|
4605
4823
|
const fresh = await options.factory();
|
|
@@ -4692,10 +4910,16 @@ var runStoreTck = (options) => {
|
|
|
4692
4910
|
const t = await over(S);
|
|
4693
4911
|
try {
|
|
4694
4912
|
await t.fresh.commit(
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4913
|
+
[
|
|
4914
|
+
{
|
|
4915
|
+
stream: t.stream,
|
|
4916
|
+
msgs: [
|
|
4917
|
+
{ name: "Happened", data: { at: /* @__PURE__ */ new Date("2020-01-01") } }
|
|
4918
|
+
],
|
|
4919
|
+
expectedVersion: -1
|
|
4920
|
+
}
|
|
4921
|
+
],
|
|
4922
|
+
raw
|
|
4699
4923
|
);
|
|
4700
4924
|
const d = await t.read();
|
|
4701
4925
|
expect8(d.label).toBeUndefined();
|
|
@@ -4709,10 +4933,14 @@ var runStoreTck = (options) => {
|
|
|
4709
4933
|
const t = await over(S);
|
|
4710
4934
|
try {
|
|
4711
4935
|
await t.fresh.commit(
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4936
|
+
[
|
|
4937
|
+
{
|
|
4938
|
+
stream: t.stream,
|
|
4939
|
+
msgs: [{ name: "Happened", data: { at: "not a date" } }],
|
|
4940
|
+
expectedVersion: -1
|
|
4941
|
+
}
|
|
4942
|
+
],
|
|
4943
|
+
raw
|
|
4716
4944
|
);
|
|
4717
4945
|
expect8((await t.read()).at).toBe("not a date");
|
|
4718
4946
|
} finally {
|
|
@@ -4852,6 +5080,19 @@ var runStoreTck = (options) => {
|
|
|
4852
5080
|
expect8((await take(k, who)).correlating).toBe(true);
|
|
4853
5081
|
await release(k, who);
|
|
4854
5082
|
});
|
|
5083
|
+
it7("advances the checkpoint for a caller refused the lease", async () => {
|
|
5084
|
+
const k = key();
|
|
5085
|
+
const holder = by();
|
|
5086
|
+
expect8((await take(k, holder)).correlating).toBe(true);
|
|
5087
|
+
const refused = await store.subscribe([], 123456, {
|
|
5088
|
+
key: k,
|
|
5089
|
+
by: by(),
|
|
5090
|
+
millis: 1e4
|
|
5091
|
+
});
|
|
5092
|
+
expect8(refused.correlating).toBe(false);
|
|
5093
|
+
expect8((await take(k, holder)).correlated_at).toBe(123456);
|
|
5094
|
+
await release(k, holder);
|
|
5095
|
+
});
|
|
4855
5096
|
it7("answers undefined when no correlator is supplied", async () => {
|
|
4856
5097
|
expect8(await store.subscribe([])).not.toHaveProperty("correlating");
|
|
4857
5098
|
});
|
|
@@ -4933,7 +5174,234 @@ var runStoreTck = (options) => {
|
|
|
4933
5174
|
});
|
|
4934
5175
|
}
|
|
4935
5176
|
);
|
|
5177
|
+
describe8("an action across streams", () => {
|
|
5178
|
+
const SeatTaken = z2.object({ student: z2.string() });
|
|
5179
|
+
const Seats = state({
|
|
5180
|
+
Seats: z2.object({ taken: z2.number() }).refine((s) => s.taken <= 3, "the course is full")
|
|
5181
|
+
}).init(() => ({ taken: 0 })).emits({ SeatTaken }).patch({ SeatTaken: (_, s) => ({ taken: s.taken + 1 }) }).on({ TakeSeat: SeatTaken }).emit("SeatTaken").build();
|
|
5182
|
+
const Enroll = z2.object({ course: z2.string(), student: z2.string() });
|
|
5183
|
+
const course = (data) => `course-${data.course}`;
|
|
5184
|
+
const Enrollment = state({ Enrollment: Enroll }).init(() => ({ course: "", student: "" })).emits({ Enrolled: Enroll }).on({ Enroll }, { maxRetries: 8 }).loads(Seats, course, ["SeatTaken"]).requires([
|
|
5185
|
+
{
|
|
5186
|
+
description: "the course has a free seat",
|
|
5187
|
+
holds: (_, __, ___, { Seats: Seats2 }) => Seats2.taken < 3
|
|
5188
|
+
}
|
|
5189
|
+
]).emit((data) => [
|
|
5190
|
+
["Enrolled", data],
|
|
5191
|
+
["SeatTaken", { student: data.student }]
|
|
5192
|
+
]).on({ Overfill: Enroll }).loads(Seats, course, ["SeatTaken"]).emit((data) => [
|
|
5193
|
+
["Enrolled", data],
|
|
5194
|
+
["SeatTaken", { student: data.student }]
|
|
5195
|
+
]).build();
|
|
5196
|
+
const actor2 = { id: "a", name: "a" };
|
|
5197
|
+
const at = (stream) => ({ stream, actor: actor2 });
|
|
5198
|
+
const over = async (run) => {
|
|
5199
|
+
const fresh = await options.factory();
|
|
5200
|
+
await fresh.seed();
|
|
5201
|
+
const cache = new InMemoryCache();
|
|
5202
|
+
const app = act().withState(Seats).withState(Enrollment).build({ scoped: { store: fresh, cache } });
|
|
5203
|
+
const c = `c${uid()}`;
|
|
5204
|
+
const events2 = async (stream) => {
|
|
5205
|
+
const found = [];
|
|
5206
|
+
await fresh.query((e) => found.push(e), {
|
|
5207
|
+
stream,
|
|
5208
|
+
stream_exact: true
|
|
5209
|
+
});
|
|
5210
|
+
return found;
|
|
5211
|
+
};
|
|
5212
|
+
try {
|
|
5213
|
+
await run({
|
|
5214
|
+
app,
|
|
5215
|
+
fresh,
|
|
5216
|
+
c,
|
|
5217
|
+
events: events2,
|
|
5218
|
+
seat: (student) => ({ course: c, student })
|
|
5219
|
+
});
|
|
5220
|
+
} finally {
|
|
5221
|
+
vi.restoreAllMocks();
|
|
5222
|
+
await app.shutdown();
|
|
5223
|
+
await cache.dispose();
|
|
5224
|
+
await fresh.dispose();
|
|
5225
|
+
}
|
|
5226
|
+
};
|
|
5227
|
+
it7("commits both streams at once and fires committed once per stream", () => over(async ({ app, c, events: events2, seat }) => {
|
|
5228
|
+
const stream = `enr-${uid()}`;
|
|
5229
|
+
const heard = [];
|
|
5230
|
+
app.on("committed", (s) => heard.push(s));
|
|
5231
|
+
const snapshots = await app.do("Enroll", at(stream), seat("s1"));
|
|
5232
|
+
expect8(snapshots.map((s) => s.event?.name)).toEqual([
|
|
5233
|
+
"Enrolled"
|
|
5234
|
+
]);
|
|
5235
|
+
const [own] = await events2(stream);
|
|
5236
|
+
const [other] = await events2(`course-${c}`);
|
|
5237
|
+
expect8(own.name).toBe("Enrolled");
|
|
5238
|
+
expect8(other.name).toBe("SeatTaken");
|
|
5239
|
+
expect8(other.id).toBeGreaterThan(own.id);
|
|
5240
|
+
expect8(other.meta.correlation).toBe(own.meta.correlation);
|
|
5241
|
+
expect8(heard.map((h) => h[0].event?.stream)).toEqual([
|
|
5242
|
+
stream,
|
|
5243
|
+
`course-${c}`
|
|
5244
|
+
]);
|
|
5245
|
+
expect8((await app.load(Seats, `course-${c}`)).state.taken).toBe(1);
|
|
5246
|
+
}));
|
|
5247
|
+
it7("stores nothing on either stream when a rule or a schema refuses", () => over(async ({ app, c, events: events2, seat }) => {
|
|
5248
|
+
for (const i of [1, 2, 3])
|
|
5249
|
+
await app.do("TakeSeat", at(`course-${c}`), { student: `s${i}` });
|
|
5250
|
+
const [a, b] = [`enr-${uid()}`, `enr-${uid()}`];
|
|
5251
|
+
await expect8(app.do("Enroll", at(a), seat("late"))).rejects.toThrow(
|
|
5252
|
+
PreconditionError
|
|
5253
|
+
);
|
|
5254
|
+
await expect8(app.do("Overfill", at(b), seat("late"))).rejects.toThrow(
|
|
5255
|
+
ValidationError
|
|
5256
|
+
);
|
|
5257
|
+
expect8(await events2(a)).toEqual([]);
|
|
5258
|
+
expect8(await events2(b)).toEqual([]);
|
|
5259
|
+
expect8(await events2(`course-${c}`)).toHaveLength(3);
|
|
5260
|
+
}));
|
|
5261
|
+
it7("a rival on the loaded stream refuses the whole commit, naming that stream", () => over(async ({ app, fresh, c, events: events2, seat }) => {
|
|
5262
|
+
const commit = fresh.commit.bind(fresh);
|
|
5263
|
+
vi.spyOn(fresh, "commit").mockImplementationOnce(
|
|
5264
|
+
async (...args) => {
|
|
5265
|
+
await commit(
|
|
5266
|
+
[
|
|
5267
|
+
{
|
|
5268
|
+
stream: `course-${c}`,
|
|
5269
|
+
msgs: [{ name: "SeatTaken", data: { student: "rival" } }]
|
|
5270
|
+
}
|
|
5271
|
+
],
|
|
5272
|
+
{ correlation: "rival", causation: {} }
|
|
5273
|
+
);
|
|
5274
|
+
return commit(...args);
|
|
5275
|
+
}
|
|
5276
|
+
);
|
|
5277
|
+
const stream = `enr-${uid()}`;
|
|
5278
|
+
const err = await app.do("Overfill", at(stream), seat("s")).catch((e) => e);
|
|
5279
|
+
expect8(err).toBeInstanceOf(ConcurrencyError);
|
|
5280
|
+
expect8(err.stream).toBe(`course-${c}`);
|
|
5281
|
+
expect8(await events2(stream)).toEqual([]);
|
|
5282
|
+
expect8(await events2(`course-${c}`)).toHaveLength(1);
|
|
5283
|
+
}));
|
|
5284
|
+
it7("racing enrollments fill the seats exactly: the rest are refused by the rule", () => over(async ({ app, c, events: events2, seat }) => {
|
|
5285
|
+
const results = await Promise.allSettled(
|
|
5286
|
+
[1, 2, 3, 4, 5, 6].map(
|
|
5287
|
+
(i) => app.do("Enroll", at(`race-${uid()}-${i}`), seat(`s${i}`))
|
|
5288
|
+
)
|
|
5289
|
+
);
|
|
5290
|
+
expect8(results.filter((r) => r.status === "fulfilled")).toHaveLength(
|
|
5291
|
+
3
|
|
5292
|
+
);
|
|
5293
|
+
for (const r of results.filter((r2) => r2.status === "rejected"))
|
|
5294
|
+
expect8(r.reason).toBeInstanceOf(
|
|
5295
|
+
PreconditionError
|
|
5296
|
+
);
|
|
5297
|
+
expect8(await events2(`course-${c}`)).toHaveLength(3);
|
|
5298
|
+
}));
|
|
5299
|
+
});
|
|
4936
5300
|
describe8.skipIf(!caps.restore)("restore (capability)", () => {
|
|
5301
|
+
describe8("what a restore must not get wrong", () => {
|
|
5302
|
+
const edge_uid = () => uid();
|
|
5303
|
+
const E = (data = { a: 1 }, pii) => ({
|
|
5304
|
+
name: "E",
|
|
5305
|
+
data,
|
|
5306
|
+
...pii ? { pii } : {}
|
|
5307
|
+
});
|
|
5308
|
+
const edge_meta = (correlation = "m") => ({ correlation, causation: {} });
|
|
5309
|
+
const rows = async (query) => {
|
|
5310
|
+
const found = [];
|
|
5311
|
+
await store.query((e) => found.push(e), query);
|
|
5312
|
+
return found;
|
|
5313
|
+
};
|
|
5314
|
+
const one = (stream) => ({ stream, stream_exact: true });
|
|
5315
|
+
it7("a commit after restore continues each stream from its restored head", async () => {
|
|
5316
|
+
const a = `a-${edge_uid()}`;
|
|
5317
|
+
await store.commit(
|
|
5318
|
+
[{ stream: a, msgs: [E(), E()] }],
|
|
5319
|
+
edge_meta()
|
|
5320
|
+
);
|
|
5321
|
+
const log = await rows({ with_snaps: true });
|
|
5322
|
+
await store.restore(async (cb) => {
|
|
5323
|
+
for (const e of log) await cb(e);
|
|
5324
|
+
});
|
|
5325
|
+
const [c] = await store.commit(
|
|
5326
|
+
[{ stream: a, msgs: [E()], expectedVersion: 1 }],
|
|
5327
|
+
edge_meta()
|
|
5328
|
+
);
|
|
5329
|
+
expect8(c.version).toBe(2);
|
|
5330
|
+
});
|
|
5331
|
+
it7("restore renumbers: ids are dense whatever the source ids were", async () => {
|
|
5332
|
+
const a = `a-${edge_uid()}`;
|
|
5333
|
+
const ev = (version, id) => ({
|
|
5334
|
+
id,
|
|
5335
|
+
stream: a,
|
|
5336
|
+
version,
|
|
5337
|
+
name: "E",
|
|
5338
|
+
data: {},
|
|
5339
|
+
meta: edge_meta(),
|
|
5340
|
+
created: /* @__PURE__ */ new Date()
|
|
5341
|
+
});
|
|
5342
|
+
const ids = [];
|
|
5343
|
+
await store.restore(async (cb) => {
|
|
5344
|
+
ids.push(await cb(ev(0, 500)));
|
|
5345
|
+
ids.push(await cb(ev(1, 900)));
|
|
5346
|
+
});
|
|
5347
|
+
expect8(ids[1]).toBe(ids[0] + 1);
|
|
5348
|
+
expect8(ids[0]).toBeLessThanOrEqual(1);
|
|
5349
|
+
});
|
|
5350
|
+
it7("changes nothing when it fails", async () => {
|
|
5351
|
+
const a = `rb-${edge_uid()}`;
|
|
5352
|
+
const key = `k-${edge_uid()}`;
|
|
5353
|
+
const sub = `sub-${edge_uid()}`;
|
|
5354
|
+
const committed = await store.commit(
|
|
5355
|
+
[{ stream: a, msgs: [E({}, { email: "x" }), E()] }],
|
|
5356
|
+
edge_meta()
|
|
5357
|
+
);
|
|
5358
|
+
const head = committed.at(-1).id;
|
|
5359
|
+
await store.subscribe([{ stream: sub }], head);
|
|
5360
|
+
const keyed = await store.subscribe([], head, {
|
|
5361
|
+
key,
|
|
5362
|
+
by: "w",
|
|
5363
|
+
millis: 1
|
|
5364
|
+
});
|
|
5365
|
+
const shared = await store.subscribe([]);
|
|
5366
|
+
await expect8(
|
|
5367
|
+
store.restore(async (callback) => {
|
|
5368
|
+
await callback({
|
|
5369
|
+
id: 1,
|
|
5370
|
+
stream: "other",
|
|
5371
|
+
version: 0,
|
|
5372
|
+
name: "E",
|
|
5373
|
+
data: {},
|
|
5374
|
+
meta: edge_meta(),
|
|
5375
|
+
created: /* @__PURE__ */ new Date()
|
|
5376
|
+
});
|
|
5377
|
+
throw new Error("mid-restore");
|
|
5378
|
+
})
|
|
5379
|
+
).rejects.toThrow();
|
|
5380
|
+
const subscriptions = [];
|
|
5381
|
+
await store.query_streams((p) => subscriptions.push(p.stream), {
|
|
5382
|
+
stream: sub,
|
|
5383
|
+
stream_exact: true
|
|
5384
|
+
});
|
|
5385
|
+
expect8(subscriptions).toEqual([sub]);
|
|
5386
|
+
expect8((await store.subscribe([])).correlated_at).toBe(
|
|
5387
|
+
shared.correlated_at
|
|
5388
|
+
);
|
|
5389
|
+
await sleep(5);
|
|
5390
|
+
const keyed_after = await store.subscribe([], void 0, {
|
|
5391
|
+
key,
|
|
5392
|
+
by: "w2",
|
|
5393
|
+
millis: 1
|
|
5394
|
+
});
|
|
5395
|
+
expect8(keyed_after.correlated_at).toBe(keyed.correlated_at);
|
|
5396
|
+
expect8((await rows(one(a)))[0].pii).toEqual({ email: "x" });
|
|
5397
|
+
const [next] = await store.commit(
|
|
5398
|
+
[{ stream: a, msgs: [E()], expectedVersion: 1 }],
|
|
5399
|
+
edge_meta()
|
|
5400
|
+
);
|
|
5401
|
+
expect8(next.version).toBe(2);
|
|
5402
|
+
expect8(next.id).toBeGreaterThan(head);
|
|
5403
|
+
});
|
|
5404
|
+
});
|
|
4937
5405
|
beforeEach(async () => {
|
|
4938
5406
|
await store.drop();
|
|
4939
5407
|
await store.seed();
|
|
@@ -5119,8 +5587,7 @@ var runStoreTck = (options) => {
|
|
|
5119
5587
|
it7("wipes pre-existing events before inserting", async () => {
|
|
5120
5588
|
const old = `restore-old-${uid()}`;
|
|
5121
5589
|
await store.commit(
|
|
5122
|
-
old,
|
|
5123
|
-
[inc(1), inc(2)],
|
|
5590
|
+
[{ stream: old, msgs: [inc(1), inc(2)] }],
|
|
5124
5591
|
make_meta({ stream: old })
|
|
5125
5592
|
);
|
|
5126
5593
|
const fresh = `restore-fresh-${uid()}`;
|
|
@@ -5267,8 +5734,7 @@ var runStoreTck = (options) => {
|
|
|
5267
5734
|
it7("rolls back atomically when the source throws mid-iteration", async () => {
|
|
5268
5735
|
const original = `restore-pre-${uid()}`;
|
|
5269
5736
|
const committed = await store.commit(
|
|
5270
|
-
original,
|
|
5271
|
-
[inc(1), inc(2), inc(3)],
|
|
5737
|
+
[{ stream: original, msgs: [inc(1), inc(2), inc(3)] }],
|
|
5272
5738
|
make_meta({ stream: original })
|
|
5273
5739
|
);
|
|
5274
5740
|
const explosive = {
|
|
@@ -5441,12 +5907,16 @@ var runStoreTck = (options) => {
|
|
|
5441
5907
|
it7("commits and loads pii alongside data", async () => {
|
|
5442
5908
|
const s = `pii-roundtrip-${uid()}`;
|
|
5443
5909
|
const committed = await store.commit(
|
|
5444
|
-
s,
|
|
5445
5910
|
[
|
|
5446
5911
|
{
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5912
|
+
stream: s,
|
|
5913
|
+
msgs: [
|
|
5914
|
+
{
|
|
5915
|
+
name: "Incremented",
|
|
5916
|
+
data: { amount: 1 },
|
|
5917
|
+
pii: { email: "u@example.com", name: "Ursula" }
|
|
5918
|
+
}
|
|
5919
|
+
]
|
|
5450
5920
|
}
|
|
5451
5921
|
],
|
|
5452
5922
|
make_meta({ stream: s })
|
|
@@ -5469,12 +5939,16 @@ var runStoreTck = (options) => {
|
|
|
5469
5939
|
});
|
|
5470
5940
|
describe8("with_pii", () => {
|
|
5471
5941
|
const seed_pii = async (s) => await store.commit(
|
|
5472
|
-
s,
|
|
5473
5942
|
[
|
|
5474
5943
|
{
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5944
|
+
stream: s,
|
|
5945
|
+
msgs: [
|
|
5946
|
+
{
|
|
5947
|
+
name: "Incremented",
|
|
5948
|
+
data: { amount: 1 },
|
|
5949
|
+
pii: { email: "w@example.com" }
|
|
5950
|
+
}
|
|
5951
|
+
]
|
|
5478
5952
|
}
|
|
5479
5953
|
],
|
|
5480
5954
|
make_meta({ stream: s })
|
|
@@ -5535,12 +6009,16 @@ var runStoreTck = (options) => {
|
|
|
5535
6009
|
const s = `pii-date-${uid()}`;
|
|
5536
6010
|
const when = /* @__PURE__ */ new Date("2024-03-01T10:20:30.000Z");
|
|
5537
6011
|
await store.commit(
|
|
5538
|
-
s,
|
|
5539
6012
|
[
|
|
5540
6013
|
{
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
6014
|
+
stream: s,
|
|
6015
|
+
msgs: [
|
|
6016
|
+
{
|
|
6017
|
+
name: "Incremented",
|
|
6018
|
+
data: { amount: 1, at: when },
|
|
6019
|
+
pii: { born: when }
|
|
6020
|
+
}
|
|
6021
|
+
]
|
|
5544
6022
|
}
|
|
5545
6023
|
],
|
|
5546
6024
|
make_meta({ stream: s })
|
|
@@ -5563,17 +6041,21 @@ var runStoreTck = (options) => {
|
|
|
5563
6041
|
it7("query_stats head/tail never carry pii \u2014 introspection surface is pii-safe", async () => {
|
|
5564
6042
|
const s = `pii-stats-${uid()}`;
|
|
5565
6043
|
await store.commit(
|
|
5566
|
-
s,
|
|
5567
6044
|
[
|
|
5568
6045
|
{
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
6046
|
+
stream: s,
|
|
6047
|
+
msgs: [
|
|
6048
|
+
{
|
|
6049
|
+
name: "Incremented",
|
|
6050
|
+
data: { amount: 1 },
|
|
6051
|
+
pii: { email: "head@example.com" }
|
|
6052
|
+
},
|
|
6053
|
+
{
|
|
6054
|
+
name: "Incremented",
|
|
6055
|
+
data: { amount: 2 },
|
|
6056
|
+
pii: { email: "tail@example.com" }
|
|
6057
|
+
}
|
|
6058
|
+
]
|
|
5577
6059
|
}
|
|
5578
6060
|
],
|
|
5579
6061
|
make_meta({ stream: s })
|
|
@@ -5597,8 +6079,7 @@ var runStoreTck = (options) => {
|
|
|
5597
6079
|
it7("passes through events without pii (pii is null or undefined on load)", async () => {
|
|
5598
6080
|
const s = `pii-none-${uid()}`;
|
|
5599
6081
|
await store.commit(
|
|
5600
|
-
s,
|
|
5601
|
-
[inc(1)],
|
|
6082
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
5602
6083
|
make_meta({ stream: s })
|
|
5603
6084
|
);
|
|
5604
6085
|
const seen = [];
|
|
@@ -5614,17 +6095,21 @@ var runStoreTck = (options) => {
|
|
|
5614
6095
|
it7("wipes pii for every event on the stream via forget_pii", async () => {
|
|
5615
6096
|
const s = `pii-forget-${uid()}`;
|
|
5616
6097
|
await store.commit(
|
|
5617
|
-
s,
|
|
5618
6098
|
[
|
|
5619
6099
|
{
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
6100
|
+
stream: s,
|
|
6101
|
+
msgs: [
|
|
6102
|
+
{
|
|
6103
|
+
name: "Incremented",
|
|
6104
|
+
data: { amount: 1 },
|
|
6105
|
+
pii: { email: "a@example.com" }
|
|
6106
|
+
},
|
|
6107
|
+
{
|
|
6108
|
+
name: "Incremented",
|
|
6109
|
+
data: { amount: 2 },
|
|
6110
|
+
pii: { email: "b@example.com" }
|
|
6111
|
+
}
|
|
6112
|
+
]
|
|
5628
6113
|
}
|
|
5629
6114
|
],
|
|
5630
6115
|
make_meta({ stream: s })
|
|
@@ -5649,12 +6134,16 @@ var runStoreTck = (options) => {
|
|
|
5649
6134
|
it7("is idempotent \u2014 second forget_pii returns 0, no error", async () => {
|
|
5650
6135
|
const s = `pii-forget-idem-${uid()}`;
|
|
5651
6136
|
await store.commit(
|
|
5652
|
-
s,
|
|
5653
6137
|
[
|
|
5654
6138
|
{
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
6139
|
+
stream: s,
|
|
6140
|
+
msgs: [
|
|
6141
|
+
{
|
|
6142
|
+
name: "Incremented",
|
|
6143
|
+
data: { amount: 1 },
|
|
6144
|
+
pii: { email: "u@example.com" }
|
|
6145
|
+
}
|
|
6146
|
+
]
|
|
5658
6147
|
}
|
|
5659
6148
|
],
|
|
5660
6149
|
make_meta({ stream: s })
|
|
@@ -5669,23 +6158,31 @@ var runStoreTck = (options) => {
|
|
|
5669
6158
|
const sA = `pii-iso-a-${uid()}`;
|
|
5670
6159
|
const sB = `pii-iso-b-${uid()}`;
|
|
5671
6160
|
await store.commit(
|
|
5672
|
-
sA,
|
|
5673
6161
|
[
|
|
5674
6162
|
{
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
6163
|
+
stream: sA,
|
|
6164
|
+
msgs: [
|
|
6165
|
+
{
|
|
6166
|
+
name: "Incremented",
|
|
6167
|
+
data: { amount: 1 },
|
|
6168
|
+
pii: { email: "alice@example.com" }
|
|
6169
|
+
}
|
|
6170
|
+
]
|
|
5678
6171
|
}
|
|
5679
6172
|
],
|
|
5680
6173
|
make_meta({ stream: sA })
|
|
5681
6174
|
);
|
|
5682
6175
|
await store.commit(
|
|
5683
|
-
sB,
|
|
5684
6176
|
[
|
|
5685
6177
|
{
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
6178
|
+
stream: sB,
|
|
6179
|
+
msgs: [
|
|
6180
|
+
{
|
|
6181
|
+
name: "Incremented",
|
|
6182
|
+
data: { amount: 1 },
|
|
6183
|
+
pii: { email: "bob@example.com" }
|
|
6184
|
+
}
|
|
6185
|
+
]
|
|
5689
6186
|
}
|
|
5690
6187
|
],
|
|
5691
6188
|
make_meta({ stream: sB })
|
|
@@ -5711,8 +6208,7 @@ var runStoreTck = (options) => {
|
|
|
5711
6208
|
it7("forget_pii on a stream with no pii events returns 0", async () => {
|
|
5712
6209
|
const s = `pii-forget-empty-${uid()}`;
|
|
5713
6210
|
await store.commit(
|
|
5714
|
-
s,
|
|
5715
|
-
[inc(1)],
|
|
6211
|
+
[{ stream: s, msgs: [inc(1)] }],
|
|
5716
6212
|
make_meta({ stream: s })
|
|
5717
6213
|
);
|
|
5718
6214
|
const wiped = await store.forget_pii.call(store, s);
|
|
@@ -5737,8 +6233,7 @@ var runStoreTck = (options) => {
|
|
|
5737
6233
|
try {
|
|
5738
6234
|
const stream = `notify-${uid()}`;
|
|
5739
6235
|
await writer.commit(
|
|
5740
|
-
stream,
|
|
5741
|
-
[inc(1)],
|
|
6236
|
+
[{ stream, msgs: [inc(1)] }],
|
|
5742
6237
|
make_meta({ stream })
|
|
5743
6238
|
);
|
|
5744
6239
|
await arrived;
|
|
@@ -5766,18 +6261,15 @@ var runStoreTck = (options) => {
|
|
|
5766
6261
|
const writer = await options.factory();
|
|
5767
6262
|
try {
|
|
5768
6263
|
await store.commit(
|
|
5769
|
-
own,
|
|
5770
|
-
[inc(1)],
|
|
6264
|
+
[{ stream: own, msgs: [inc(1)] }],
|
|
5771
6265
|
make_meta({ stream: own })
|
|
5772
6266
|
);
|
|
5773
6267
|
await writer.commit(
|
|
5774
|
-
remote,
|
|
5775
|
-
[inc(1)],
|
|
6268
|
+
[{ stream: remote, msgs: [inc(1)] }],
|
|
5776
6269
|
make_meta({ stream: remote })
|
|
5777
6270
|
);
|
|
5778
6271
|
await writer.commit(
|
|
5779
|
-
sentinel,
|
|
5780
|
-
[inc(1)],
|
|
6272
|
+
[{ stream: sentinel, msgs: [inc(1)] }],
|
|
5781
6273
|
make_meta({ stream: sentinel })
|
|
5782
6274
|
);
|
|
5783
6275
|
await sentinel_arrived;
|
|
@@ -5789,7 +6281,7 @@ var runStoreTck = (options) => {
|
|
|
5789
6281
|
await Promise.resolve(disposer());
|
|
5790
6282
|
}
|
|
5791
6283
|
});
|
|
5792
|
-
it7("delivers one notification
|
|
6284
|
+
it7("delivers one notification carrying a stream's full batch from one commit", async () => {
|
|
5793
6285
|
const received = [];
|
|
5794
6286
|
let resolve_sentinel;
|
|
5795
6287
|
const sentinel_arrived = new Promise((res) => {
|
|
@@ -5804,13 +6296,11 @@ var runStoreTck = (options) => {
|
|
|
5804
6296
|
const writer = await options.factory();
|
|
5805
6297
|
try {
|
|
5806
6298
|
await writer.commit(
|
|
5807
|
-
batch,
|
|
5808
|
-
[inc(1), inc(2), inc(3)],
|
|
6299
|
+
[{ stream: batch, msgs: [inc(1), inc(2), inc(3)] }],
|
|
5809
6300
|
make_meta({ stream: batch })
|
|
5810
6301
|
);
|
|
5811
6302
|
await writer.commit(
|
|
5812
|
-
sentinel,
|
|
5813
|
-
[inc(1)],
|
|
6303
|
+
[{ stream: sentinel, msgs: [inc(1)] }],
|
|
5814
6304
|
make_meta({ stream: sentinel })
|
|
5815
6305
|
);
|
|
5816
6306
|
await sentinel_arrived;
|
|
@@ -5833,6 +6323,45 @@ var runStoreTck = (options) => {
|
|
|
5833
6323
|
await Promise.resolve(disposer());
|
|
5834
6324
|
}
|
|
5835
6325
|
});
|
|
6326
|
+
it7("delivers one notification per stream a commit appends to, with that stream's events", async () => {
|
|
6327
|
+
const received = [];
|
|
6328
|
+
let resolve_sentinel;
|
|
6329
|
+
const sentinel_arrived = new Promise((res) => {
|
|
6330
|
+
resolve_sentinel = res;
|
|
6331
|
+
});
|
|
6332
|
+
const a = `notify-across-a-${uid()}`;
|
|
6333
|
+
const b = `notify-across-b-${uid()}`;
|
|
6334
|
+
const sentinel = `notify-across-sentinel-${uid()}`;
|
|
6335
|
+
const disposer = await store.notify.call(store, (n) => {
|
|
6336
|
+
received.push(n);
|
|
6337
|
+
if (n.stream === sentinel) resolve_sentinel();
|
|
6338
|
+
});
|
|
6339
|
+
const writer = await options.factory();
|
|
6340
|
+
try {
|
|
6341
|
+
const committed = await writer.commit(
|
|
6342
|
+
[
|
|
6343
|
+
{ stream: a, msgs: [inc(1), inc(2)] },
|
|
6344
|
+
{ stream: b, msgs: [dec(3)] }
|
|
6345
|
+
],
|
|
6346
|
+
make_meta({ stream: a })
|
|
6347
|
+
);
|
|
6348
|
+
await writer.commit(
|
|
6349
|
+
[{ stream: sentinel, msgs: [inc(1)] }],
|
|
6350
|
+
make_meta({ stream: sentinel })
|
|
6351
|
+
);
|
|
6352
|
+
await sentinel_arrived;
|
|
6353
|
+
for (const stream of [a, b]) {
|
|
6354
|
+
const of_stream = received.filter((n) => n.stream === stream);
|
|
6355
|
+
expect8(of_stream).toHaveLength(1);
|
|
6356
|
+
expect8(of_stream[0].events.map((e) => e.id)).toEqual(
|
|
6357
|
+
committed.filter((e) => e.stream === stream).map((e) => e.id)
|
|
6358
|
+
);
|
|
6359
|
+
}
|
|
6360
|
+
} finally {
|
|
6361
|
+
await writer.dispose();
|
|
6362
|
+
await Promise.resolve(disposer());
|
|
6363
|
+
}
|
|
6364
|
+
});
|
|
5836
6365
|
});
|
|
5837
6366
|
}
|
|
5838
6367
|
});
|