@rotorsoft/act-tck 1.16.0 → 1.17.1
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 +66 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/@types/cache-differential-tck.d.ts +80 -0
- package/dist/@types/cache-differential-tck.d.ts.map +1 -0
- package/dist/@types/index.d.ts +6 -0
- package/dist/@types/index.d.ts.map +1 -1
- package/dist/@types/logger-differential-tck.d.ts +61 -0
- package/dist/@types/logger-differential-tck.d.ts.map +1 -0
- package/dist/@types/store-differential-tck.d.ts +93 -0
- package/dist/@types/store-differential-tck.d.ts.map +1 -0
- package/dist/@types/store-tck.d.ts.map +1 -1
- package/dist/index.cjs +942 -507
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +915 -483
- package/dist/index.js.map +1 -1
- package/package.json +8 -5
package/dist/index.cjs
CHANGED
|
@@ -40,17 +40,154 @@ __export(index_exports, {
|
|
|
40
40
|
dec: () => dec,
|
|
41
41
|
inc: () => inc,
|
|
42
42
|
reset: () => reset,
|
|
43
|
+
runCacheDifferentialTck: () => runCacheDifferentialTck,
|
|
43
44
|
runCacheTck: () => runCacheTck,
|
|
45
|
+
runLoggerDifferentialTck: () => runLoggerDifferentialTck,
|
|
44
46
|
runLoggerTck: () => runLoggerTck,
|
|
45
47
|
runStabilityTck: () => runStabilityTck,
|
|
48
|
+
runStoreDifferentialTck: () => runStoreDifferentialTck,
|
|
46
49
|
runStorePropertyTck: () => runStorePropertyTck,
|
|
47
50
|
runStoreTck: () => runStoreTck,
|
|
48
51
|
uid: () => uid
|
|
49
52
|
});
|
|
50
53
|
module.exports = __toCommonJS(index_exports);
|
|
51
54
|
|
|
52
|
-
// src/cache-tck.ts
|
|
55
|
+
// src/cache-differential-tck.ts
|
|
53
56
|
var import_vitest = require("vitest");
|
|
57
|
+
|
|
58
|
+
// src/fixtures/helpers.ts
|
|
59
|
+
var import_node_crypto = require("crypto");
|
|
60
|
+
var uid = () => (0, import_node_crypto.randomUUID)().slice(0, 8);
|
|
61
|
+
var actor = (name = "tester") => ({ id: (0, import_node_crypto.randomUUID)(), name });
|
|
62
|
+
var make_meta = (opts = {}) => ({
|
|
63
|
+
correlation: opts.correlation ?? (0, import_node_crypto.randomUUID)(),
|
|
64
|
+
causation: opts.stream ? {
|
|
65
|
+
action: {
|
|
66
|
+
name: opts.action ?? "Test",
|
|
67
|
+
stream: opts.stream,
|
|
68
|
+
actor: actor()
|
|
69
|
+
}
|
|
70
|
+
} : {}
|
|
71
|
+
});
|
|
72
|
+
var inc = (amount = 1) => ({
|
|
73
|
+
name: "Incremented",
|
|
74
|
+
data: { amount }
|
|
75
|
+
});
|
|
76
|
+
var dec = (amount = 1) => ({
|
|
77
|
+
name: "Decremented",
|
|
78
|
+
data: { amount }
|
|
79
|
+
});
|
|
80
|
+
var reset = () => ({ name: "Reset", data: {} });
|
|
81
|
+
var seed_stream = async (store, stream, count, correlation) => {
|
|
82
|
+
const out = [];
|
|
83
|
+
for (let i = 0; i < count; i++) {
|
|
84
|
+
const committed = await store.commit(
|
|
85
|
+
stream,
|
|
86
|
+
[inc(1)],
|
|
87
|
+
make_meta({ correlation, stream })
|
|
88
|
+
);
|
|
89
|
+
out.push(...committed);
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
};
|
|
93
|
+
var collect = async (store, query) => {
|
|
94
|
+
const out = [];
|
|
95
|
+
await store.query((e) => {
|
|
96
|
+
out.push(e);
|
|
97
|
+
}, query);
|
|
98
|
+
return out;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// src/cache-differential-tck.ts
|
|
102
|
+
var mulberry32 = (seed) => {
|
|
103
|
+
let a = seed >>> 0;
|
|
104
|
+
return () => {
|
|
105
|
+
a = a + 1831565813 | 0;
|
|
106
|
+
let t = Math.imul(a ^ a >>> 15, 1 | a);
|
|
107
|
+
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
108
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
var build_cache_plan = (seed, stream_count) => {
|
|
112
|
+
const rng = mulberry32(seed);
|
|
113
|
+
const prefix = `cdiff-${uid()}-`;
|
|
114
|
+
const streams = Array.from(
|
|
115
|
+
{ length: stream_count },
|
|
116
|
+
(_, i) => `${prefix}${i}`
|
|
117
|
+
);
|
|
118
|
+
const make_entry = () => {
|
|
119
|
+
const v = Math.floor(rng() * 1e3);
|
|
120
|
+
return {
|
|
121
|
+
state: { count: v, label: `k${v % 7}` },
|
|
122
|
+
version: v,
|
|
123
|
+
event_id: v,
|
|
124
|
+
patches: 1 + Math.floor(rng() * 5),
|
|
125
|
+
snaps: Math.floor(rng() * 3)
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
const pick_stream = () => streams[Math.floor(rng() * streams.length)];
|
|
129
|
+
const ops = [];
|
|
130
|
+
for (const stream of streams)
|
|
131
|
+
ops.push({ t: "set", stream, entry: make_entry() });
|
|
132
|
+
const middle = 6 + Math.floor(rng() * 14);
|
|
133
|
+
for (let i = 0; i < middle; i++) {
|
|
134
|
+
const kind = Math.floor(rng() * 3);
|
|
135
|
+
if (kind === 0)
|
|
136
|
+
ops.push({ t: "set", stream: pick_stream(), entry: make_entry() });
|
|
137
|
+
else if (kind === 1) ops.push({ t: "invalidate", stream: pick_stream() });
|
|
138
|
+
else ops.push({ t: "clear" });
|
|
139
|
+
}
|
|
140
|
+
return { streams, ops };
|
|
141
|
+
};
|
|
142
|
+
var apply_op = async (cache, op) => {
|
|
143
|
+
if (op.t === "set") await cache.set(op.stream, op.entry);
|
|
144
|
+
else if (op.t === "invalidate") await cache.invalidate(op.stream);
|
|
145
|
+
else await cache.clear();
|
|
146
|
+
};
|
|
147
|
+
var snapshot = async (cache, streams) => {
|
|
148
|
+
const out = {};
|
|
149
|
+
for (const stream of streams)
|
|
150
|
+
out[stream] = await cache.get(stream);
|
|
151
|
+
return out;
|
|
152
|
+
};
|
|
153
|
+
var runCacheDifferentialTck = (options) => {
|
|
154
|
+
(0, import_vitest.describe)(`TCK / Cache differential / ${options.name}`, () => {
|
|
155
|
+
const base_seed = options.seed ?? 3244;
|
|
156
|
+
const stream_count = options.streams ?? 6;
|
|
157
|
+
const plans = Array.from(
|
|
158
|
+
{ length: options.runs ?? 8 },
|
|
159
|
+
(_, r) => build_cache_plan(base_seed + r, stream_count)
|
|
160
|
+
);
|
|
161
|
+
const live = [];
|
|
162
|
+
(0, import_vitest.beforeAll)(async () => {
|
|
163
|
+
for (const spec of options.caches) {
|
|
164
|
+
live.push({ name: spec.name, cache: await spec.factory() });
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
(0, import_vitest.afterAll)(async () => {
|
|
168
|
+
for (const { cache } of live) await cache.dispose();
|
|
169
|
+
});
|
|
170
|
+
plans.forEach((plan, run) => {
|
|
171
|
+
const seed_hex = `0x${(base_seed + run).toString(16)}`;
|
|
172
|
+
(0, import_vitest.it)(`agrees on get() after every op (workload ${run}, seed ${seed_hex})`, async () => {
|
|
173
|
+
for (const op of plan.ops) {
|
|
174
|
+
for (const { cache } of live) await apply_op(cache, op);
|
|
175
|
+
const reference = await snapshot(live[0].cache, plan.streams);
|
|
176
|
+
for (let i = 1; i < live.length; i++) {
|
|
177
|
+
const actual = await snapshot(live[i].cache, plan.streams);
|
|
178
|
+
(0, import_vitest.expect)(
|
|
179
|
+
actual,
|
|
180
|
+
`${live[i].name} diverged from ${live[0].name} after ${op.t}`
|
|
181
|
+
).toEqual(reference);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// src/cache-tck.ts
|
|
190
|
+
var import_vitest2 = require("vitest");
|
|
54
191
|
var entry = (event_id, state = {}) => ({
|
|
55
192
|
state,
|
|
56
193
|
version: event_id,
|
|
@@ -59,63 +196,63 @@ var entry = (event_id, state = {}) => ({
|
|
|
59
196
|
snaps: 0
|
|
60
197
|
});
|
|
61
198
|
var runCacheTck = (options) => {
|
|
62
|
-
(0,
|
|
199
|
+
(0, import_vitest2.describe)(`TCK / Cache / ${options.name}`, () => {
|
|
63
200
|
let cache;
|
|
64
|
-
(0,
|
|
201
|
+
(0, import_vitest2.beforeEach)(() => {
|
|
65
202
|
cache = options.factory();
|
|
66
203
|
});
|
|
67
|
-
(0,
|
|
204
|
+
(0, import_vitest2.afterEach)(async () => {
|
|
68
205
|
await cache.dispose();
|
|
69
206
|
});
|
|
70
|
-
(0,
|
|
71
|
-
(0,
|
|
207
|
+
(0, import_vitest2.it)("returns undefined for an unset stream", async () => {
|
|
208
|
+
(0, import_vitest2.expect)(await cache.get("missing")).toBeUndefined();
|
|
72
209
|
});
|
|
73
|
-
(0,
|
|
210
|
+
(0, import_vitest2.it)("set then get round-trips an entry", async () => {
|
|
74
211
|
const e = entry(1, { count: 7 });
|
|
75
212
|
await cache.set("s1", e);
|
|
76
|
-
(0,
|
|
213
|
+
(0, import_vitest2.expect)(await cache.get("s1")).toEqual(e);
|
|
77
214
|
});
|
|
78
|
-
(0,
|
|
215
|
+
(0, import_vitest2.it)("set overwrites a prior entry on the same stream", async () => {
|
|
79
216
|
await cache.set("s1", entry(1, { count: 1 }));
|
|
80
217
|
await cache.set("s1", entry(2, { count: 2 }));
|
|
81
218
|
const got = await cache.get("s1");
|
|
82
|
-
(0,
|
|
83
|
-
(0,
|
|
219
|
+
(0, import_vitest2.expect)(got?.event_id).toBe(2);
|
|
220
|
+
(0, import_vitest2.expect)(got?.state).toEqual({ count: 2 });
|
|
84
221
|
});
|
|
85
|
-
(0,
|
|
222
|
+
(0, import_vitest2.it)("invalidate removes one stream and leaves others", async () => {
|
|
86
223
|
await cache.set("a", entry(1));
|
|
87
224
|
await cache.set("b", entry(2));
|
|
88
225
|
await cache.invalidate("a");
|
|
89
|
-
(0,
|
|
90
|
-
(0,
|
|
226
|
+
(0, import_vitest2.expect)(await cache.get("a")).toBeUndefined();
|
|
227
|
+
(0, import_vitest2.expect)(await cache.get("b")).toBeDefined();
|
|
91
228
|
});
|
|
92
|
-
(0,
|
|
93
|
-
await (0,
|
|
229
|
+
(0, import_vitest2.it)("invalidate on an unknown stream is a no-op", async () => {
|
|
230
|
+
await (0, import_vitest2.expect)(cache.invalidate("never-set")).resolves.toBeUndefined();
|
|
94
231
|
});
|
|
95
|
-
(0,
|
|
232
|
+
(0, import_vitest2.it)("clear empties every stream", async () => {
|
|
96
233
|
await cache.set("a", entry(1));
|
|
97
234
|
await cache.set("b", entry(2));
|
|
98
235
|
await cache.set("c", entry(3));
|
|
99
236
|
await cache.clear();
|
|
100
|
-
(0,
|
|
101
|
-
(0,
|
|
102
|
-
(0,
|
|
237
|
+
(0, import_vitest2.expect)(await cache.get("a")).toBeUndefined();
|
|
238
|
+
(0, import_vitest2.expect)(await cache.get("b")).toBeUndefined();
|
|
239
|
+
(0, import_vitest2.expect)(await cache.get("c")).toBeUndefined();
|
|
103
240
|
});
|
|
104
|
-
(0,
|
|
105
|
-
await (0,
|
|
241
|
+
(0, import_vitest2.it)("clear on an empty cache is a no-op", async () => {
|
|
242
|
+
await (0, import_vitest2.expect)(cache.clear()).resolves.toBeUndefined();
|
|
106
243
|
});
|
|
107
|
-
(0,
|
|
244
|
+
(0, import_vitest2.it)("entries are isolated per stream", async () => {
|
|
108
245
|
const ea = entry(1, { id: "a" });
|
|
109
246
|
const eb = entry(2, { id: "b" });
|
|
110
247
|
await cache.set("a", ea);
|
|
111
248
|
await cache.set("b", eb);
|
|
112
|
-
(0,
|
|
113
|
-
(0,
|
|
249
|
+
(0, import_vitest2.expect)(await cache.get("a")).toEqual(ea);
|
|
250
|
+
(0, import_vitest2.expect)(await cache.get("b")).toEqual(eb);
|
|
114
251
|
});
|
|
115
|
-
(0,
|
|
252
|
+
(0, import_vitest2.it)("dispose is idempotent", async () => {
|
|
116
253
|
await cache.set("a", entry(1));
|
|
117
254
|
await cache.dispose();
|
|
118
|
-
await (0,
|
|
255
|
+
await (0, import_vitest2.expect)(cache.dispose()).resolves.toBeUndefined();
|
|
119
256
|
});
|
|
120
257
|
});
|
|
121
258
|
};
|
|
@@ -136,105 +273,122 @@ var COUNTER_EVENT_NAMES = [
|
|
|
136
273
|
"Reset"
|
|
137
274
|
];
|
|
138
275
|
|
|
139
|
-
// src/
|
|
140
|
-
var
|
|
141
|
-
var
|
|
142
|
-
var
|
|
143
|
-
var make_meta = (opts = {}) => ({
|
|
144
|
-
correlation: opts.correlation ?? (0, import_node_crypto.randomUUID)(),
|
|
145
|
-
causation: opts.stream ? {
|
|
146
|
-
action: {
|
|
147
|
-
name: opts.action ?? "Test",
|
|
148
|
-
stream: opts.stream,
|
|
149
|
-
actor: actor()
|
|
150
|
-
}
|
|
151
|
-
} : {}
|
|
152
|
-
});
|
|
153
|
-
var inc = (amount = 1) => ({
|
|
154
|
-
name: "Incremented",
|
|
155
|
-
data: { amount }
|
|
156
|
-
});
|
|
157
|
-
var dec = (amount = 1) => ({
|
|
158
|
-
name: "Decremented",
|
|
159
|
-
data: { amount }
|
|
160
|
-
});
|
|
161
|
-
var reset = () => ({ name: "Reset", data: {} });
|
|
162
|
-
var seed_stream = async (store, stream, count, correlation) => {
|
|
276
|
+
// src/logger-differential-tck.ts
|
|
277
|
+
var import_vitest3 = require("vitest");
|
|
278
|
+
var LEVELS = ["fatal", "error", "warn", "info", "debug", "trace"];
|
|
279
|
+
var drive = (logger) => {
|
|
163
280
|
const out = [];
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
281
|
+
const ok = (fn) => {
|
|
282
|
+
try {
|
|
283
|
+
fn();
|
|
284
|
+
out.push(true);
|
|
285
|
+
} catch {
|
|
286
|
+
out.push(false);
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
out.push(typeof logger.level === "string" && logger.level.length > 0);
|
|
290
|
+
for (const level of LEVELS) {
|
|
291
|
+
ok(() => logger[level]("message"));
|
|
292
|
+
ok(() => logger[level]({ k: "v", n: 1 }));
|
|
293
|
+
ok(() => logger[level]({ k: "v" }, "context"));
|
|
171
294
|
}
|
|
295
|
+
ok(() => logger.info(null, "null payload"));
|
|
296
|
+
ok(() => {
|
|
297
|
+
const cyclic = { name: "loop" };
|
|
298
|
+
cyclic.self = cyclic;
|
|
299
|
+
logger.info(cyclic, "cycle");
|
|
300
|
+
});
|
|
301
|
+
const child = logger.child({ request_id: "abc" });
|
|
302
|
+
out.push(typeof child.level === "string" && child.level.length > 0);
|
|
303
|
+
out.push(LEVELS.every((level) => typeof child[level] === "function"));
|
|
304
|
+
out.push(typeof child.child === "function");
|
|
305
|
+
ok(() => child.child({ nested: true }).info("nested"));
|
|
172
306
|
return out;
|
|
173
307
|
};
|
|
174
|
-
var
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
308
|
+
var runLoggerDifferentialTck = (options) => {
|
|
309
|
+
(0, import_vitest3.describe)(`TCK / Logger differential / ${options.name}`, () => {
|
|
310
|
+
let live = [];
|
|
311
|
+
let original_stdout;
|
|
312
|
+
(0, import_vitest3.beforeEach)(() => {
|
|
313
|
+
live = options.loggers.map((spec) => ({
|
|
314
|
+
name: spec.name,
|
|
315
|
+
logger: spec.factory()
|
|
316
|
+
}));
|
|
317
|
+
original_stdout = process.stdout.write.bind(process.stdout);
|
|
318
|
+
process.stdout.write = (() => true);
|
|
319
|
+
});
|
|
320
|
+
(0, import_vitest3.afterEach)(async () => {
|
|
321
|
+
process.stdout.write = original_stdout;
|
|
322
|
+
for (const { logger } of live) await logger.dispose();
|
|
323
|
+
});
|
|
324
|
+
(0, import_vitest3.it)("agrees on robustness and structural parity across the call surface", () => {
|
|
325
|
+
const reference = drive(live[0].logger);
|
|
326
|
+
for (let i = 1; i < live.length; i++) {
|
|
327
|
+
const actual = drive(live[i].logger);
|
|
328
|
+
(0, import_vitest3.expect)(actual, `${live[i].name} diverged from ${live[0].name}`).toEqual(
|
|
329
|
+
reference
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
});
|
|
180
334
|
};
|
|
181
335
|
|
|
182
336
|
// src/logger-tck.ts
|
|
183
|
-
var
|
|
184
|
-
var
|
|
337
|
+
var import_vitest4 = require("vitest");
|
|
338
|
+
var LEVELS2 = ["fatal", "error", "warn", "info", "debug", "trace"];
|
|
185
339
|
var runLoggerTck = (options) => {
|
|
186
|
-
(0,
|
|
340
|
+
(0, import_vitest4.describe)(`TCK / Logger / ${options.name}`, () => {
|
|
187
341
|
let logger;
|
|
188
342
|
let original_stdout;
|
|
189
|
-
(0,
|
|
343
|
+
(0, import_vitest4.beforeEach)(() => {
|
|
190
344
|
logger = options.factory();
|
|
191
345
|
original_stdout = process.stdout.write.bind(process.stdout);
|
|
192
346
|
process.stdout.write = (() => true);
|
|
193
347
|
});
|
|
194
|
-
(0,
|
|
348
|
+
(0, import_vitest4.afterEach)(async () => {
|
|
195
349
|
process.stdout.write = original_stdout;
|
|
196
350
|
await logger.dispose();
|
|
197
351
|
});
|
|
198
|
-
(0,
|
|
199
|
-
(0,
|
|
200
|
-
(0,
|
|
352
|
+
(0, import_vitest4.it)("exposes a non-empty `level` string", () => {
|
|
353
|
+
(0, import_vitest4.expect)(typeof logger.level).toBe("string");
|
|
354
|
+
(0, import_vitest4.expect)(logger.level.length).toBeGreaterThan(0);
|
|
201
355
|
});
|
|
202
|
-
for (const level of
|
|
203
|
-
(0,
|
|
204
|
-
(0,
|
|
356
|
+
for (const level of LEVELS2) {
|
|
357
|
+
(0, import_vitest4.it)(`${level}(msg) does not throw`, () => {
|
|
358
|
+
(0, import_vitest4.expect)(() => logger[level]("hello")).not.toThrow();
|
|
205
359
|
});
|
|
206
|
-
(0,
|
|
207
|
-
(0,
|
|
360
|
+
(0, import_vitest4.it)(`${level}(obj) does not throw`, () => {
|
|
361
|
+
(0, import_vitest4.expect)(() => logger[level]({ k: "v" })).not.toThrow();
|
|
208
362
|
});
|
|
209
|
-
(0,
|
|
210
|
-
(0,
|
|
363
|
+
(0, import_vitest4.it)(`${level}(obj, msg) does not throw`, () => {
|
|
364
|
+
(0, import_vitest4.expect)(() => logger[level]({ k: "v" }, "context")).not.toThrow();
|
|
211
365
|
});
|
|
212
366
|
}
|
|
213
|
-
(0,
|
|
214
|
-
(0,
|
|
367
|
+
(0, import_vitest4.it)("accepts a null payload", () => {
|
|
368
|
+
(0, import_vitest4.expect)(() => logger.info(null, "null payload")).not.toThrow();
|
|
215
369
|
});
|
|
216
|
-
(0,
|
|
370
|
+
(0, import_vitest4.it)("accepts a cyclic payload without throwing", () => {
|
|
217
371
|
const cyclic = { name: "loop" };
|
|
218
372
|
cyclic.self = cyclic;
|
|
219
|
-
(0,
|
|
373
|
+
(0, import_vitest4.expect)(() => logger.info(cyclic, "cycle")).not.toThrow();
|
|
220
374
|
});
|
|
221
|
-
(0,
|
|
375
|
+
(0, import_vitest4.it)("child(bindings) returns a Logger satisfying the same contract", () => {
|
|
222
376
|
const child = logger.child({ request_id: "abc" });
|
|
223
|
-
(0,
|
|
224
|
-
for (const level of
|
|
225
|
-
(0,
|
|
377
|
+
(0, import_vitest4.expect)(typeof child.level).toBe("string");
|
|
378
|
+
for (const level of LEVELS2) {
|
|
379
|
+
(0, import_vitest4.expect)(typeof child[level]).toBe("function");
|
|
226
380
|
}
|
|
227
|
-
(0,
|
|
228
|
-
(0,
|
|
381
|
+
(0, import_vitest4.expect)(typeof child.child).toBe("function");
|
|
382
|
+
(0, import_vitest4.expect)(typeof child.dispose).toBe("function");
|
|
229
383
|
});
|
|
230
|
-
(0,
|
|
384
|
+
(0, import_vitest4.it)("child loggers can themselves spawn children", () => {
|
|
231
385
|
const c1 = logger.child({ a: 1 });
|
|
232
386
|
const c2 = c1.child({ b: 2 });
|
|
233
|
-
(0,
|
|
387
|
+
(0, import_vitest4.expect)(() => c2.info("nested")).not.toThrow();
|
|
234
388
|
});
|
|
235
|
-
(0,
|
|
236
|
-
await (0,
|
|
237
|
-
await (0,
|
|
389
|
+
(0, import_vitest4.it)("dispose is idempotent and awaitable", async () => {
|
|
390
|
+
await (0, import_vitest4.expect)(logger.dispose()).resolves.toBeUndefined();
|
|
391
|
+
await (0, import_vitest4.expect)(logger.dispose()).resolves.toBeUndefined();
|
|
238
392
|
});
|
|
239
393
|
});
|
|
240
394
|
};
|
|
@@ -242,14 +396,14 @@ var runLoggerTck = (options) => {
|
|
|
242
396
|
// src/stability-tck.ts
|
|
243
397
|
var import_node_fs = require("fs");
|
|
244
398
|
var import_node_path = __toESM(require("path"), 1);
|
|
245
|
-
var
|
|
399
|
+
var import_vitest5 = require("vitest");
|
|
246
400
|
function runStabilityTck(options) {
|
|
247
|
-
(0,
|
|
401
|
+
(0, import_vitest5.describe)(`${options.name} \u2014 public API stability`, () => {
|
|
248
402
|
for (const [subpath, entry2] of Object.entries(options.entryPoints)) {
|
|
249
403
|
const label = subpath || "(root)";
|
|
250
|
-
(0,
|
|
404
|
+
(0, import_vitest5.it)(`stable public surface for ${label}`, async () => {
|
|
251
405
|
const surface = await load_surface(entry2);
|
|
252
|
-
(0,
|
|
406
|
+
(0, import_vitest5.expect)(surface).toMatchSnapshot();
|
|
253
407
|
});
|
|
254
408
|
}
|
|
255
409
|
});
|
|
@@ -279,39 +433,250 @@ ${content}`;
|
|
|
279
433
|
}).join("\n");
|
|
280
434
|
}
|
|
281
435
|
|
|
436
|
+
// src/store-differential-tck.ts
|
|
437
|
+
var import_act = require("@rotorsoft/act");
|
|
438
|
+
var import_vitest6 = require("vitest");
|
|
439
|
+
var mulberry322 = (seed) => {
|
|
440
|
+
let a = seed >>> 0;
|
|
441
|
+
return () => {
|
|
442
|
+
a = a + 1831565813 | 0;
|
|
443
|
+
let t = Math.imul(a ^ a >>> 15, 1 | a);
|
|
444
|
+
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
445
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
446
|
+
};
|
|
447
|
+
};
|
|
448
|
+
var normalize_event = (e) => ({
|
|
449
|
+
stream: e.stream,
|
|
450
|
+
version: e.version,
|
|
451
|
+
name: e.name,
|
|
452
|
+
data: e.data
|
|
453
|
+
});
|
|
454
|
+
var build_plan = (seed, stream_count) => {
|
|
455
|
+
const rng = mulberry322(seed);
|
|
456
|
+
const tag = uid();
|
|
457
|
+
const event_prefix = `diff-${tag}-evt-`;
|
|
458
|
+
const sub_prefix = `diff-${tag}-sub-`;
|
|
459
|
+
const event_streams = Array.from(
|
|
460
|
+
{ length: stream_count },
|
|
461
|
+
(_, i) => `${event_prefix}${i}`
|
|
462
|
+
);
|
|
463
|
+
let type_cursor = 0;
|
|
464
|
+
const next_msg = () => {
|
|
465
|
+
const kind = type_cursor++ % 3;
|
|
466
|
+
const amount = 1 + Math.floor(rng() * 9);
|
|
467
|
+
return kind === 0 ? inc(amount) : kind === 1 ? dec(amount) : reset();
|
|
468
|
+
};
|
|
469
|
+
const batch = () => Array.from({ length: 1 + Math.floor(rng() * 3) }, next_msg);
|
|
470
|
+
const pick_stream = () => event_streams[Math.floor(rng() * event_streams.length)];
|
|
471
|
+
const ops = [];
|
|
472
|
+
for (const stream of event_streams)
|
|
473
|
+
ops.push({ t: "commit", stream, msgs: batch() });
|
|
474
|
+
const middle = 8 + Math.floor(rng() * 16);
|
|
475
|
+
for (let i = 0; i < middle; i++) {
|
|
476
|
+
const stream = pick_stream();
|
|
477
|
+
const kind = Math.floor(rng() * 3);
|
|
478
|
+
if (kind === 0) ops.push({ t: "commit", stream, msgs: batch() });
|
|
479
|
+
else if (kind === 1)
|
|
480
|
+
ops.push({ t: "snapshot", stream, count: Math.floor(rng() * 1e3) });
|
|
481
|
+
else ops.push({ t: "truncate", stream, count: Math.floor(rng() * 1e3) });
|
|
482
|
+
}
|
|
483
|
+
for (const stream of event_streams)
|
|
484
|
+
ops.push({ t: "commit", stream, msgs: batch() });
|
|
485
|
+
const lanes = ["default", "slow", "fast"];
|
|
486
|
+
const subs = event_streams.map((source, i) => ({
|
|
487
|
+
stream: `${sub_prefix}${i}`,
|
|
488
|
+
source,
|
|
489
|
+
lane: lanes[i % lanes.length],
|
|
490
|
+
priority: i % 4
|
|
491
|
+
}));
|
|
492
|
+
return { event_prefix, event_streams, sub_prefix, ops, subs };
|
|
493
|
+
};
|
|
494
|
+
var apply_plan = async (store, plan) => {
|
|
495
|
+
for (const op of plan.ops) {
|
|
496
|
+
if (op.t === "commit") {
|
|
497
|
+
await store.commit(
|
|
498
|
+
op.stream,
|
|
499
|
+
op.msgs,
|
|
500
|
+
make_meta({ stream: op.stream })
|
|
501
|
+
);
|
|
502
|
+
} else if (op.t === "snapshot") {
|
|
503
|
+
await store.commit(
|
|
504
|
+
op.stream,
|
|
505
|
+
[{ name: import_act.SNAP_EVENT, data: { count: op.count } }],
|
|
506
|
+
make_meta({ stream: op.stream })
|
|
507
|
+
);
|
|
508
|
+
} else {
|
|
509
|
+
await store.truncate([
|
|
510
|
+
{ stream: op.stream, snapshot: { count: op.count } }
|
|
511
|
+
]);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
await store.subscribe(
|
|
515
|
+
plan.subs.map((s) => ({
|
|
516
|
+
stream: s.stream,
|
|
517
|
+
source: s.source,
|
|
518
|
+
lane: s.lane,
|
|
519
|
+
priority: s.priority
|
|
520
|
+
}))
|
|
521
|
+
);
|
|
522
|
+
};
|
|
523
|
+
var runStoreDifferentialTck = (options) => {
|
|
524
|
+
(0, import_vitest6.describe)(`TCK / Store differential / ${options.name}`, () => {
|
|
525
|
+
const base_seed = options.seed ?? 2759;
|
|
526
|
+
const stream_count = options.streams ?? 4;
|
|
527
|
+
const plans = Array.from(
|
|
528
|
+
{ length: options.runs ?? 8 },
|
|
529
|
+
(_, r) => build_plan(base_seed + r, stream_count)
|
|
530
|
+
);
|
|
531
|
+
const live = [];
|
|
532
|
+
(0, import_vitest6.beforeAll)(async () => {
|
|
533
|
+
for (const spec of options.stores) {
|
|
534
|
+
const store = await spec.factory();
|
|
535
|
+
await store.drop();
|
|
536
|
+
await store.seed();
|
|
537
|
+
for (const plan of plans) await apply_plan(store, plan);
|
|
538
|
+
live.push({ name: spec.name, store });
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
(0, import_vitest6.afterAll)(async () => {
|
|
542
|
+
for (const { store } of live) await store.dispose();
|
|
543
|
+
});
|
|
544
|
+
const assert_identical = async (label, produce) => {
|
|
545
|
+
const reference = await produce(live[0].store);
|
|
546
|
+
for (let i = 1; i < live.length; i++) {
|
|
547
|
+
const actual = await produce(live[i].store);
|
|
548
|
+
(0, import_vitest6.expect)(
|
|
549
|
+
actual,
|
|
550
|
+
`${live[i].name} diverged from ${live[0].name} on "${label}"`
|
|
551
|
+
).toEqual(reference);
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
plans.forEach((plan, run) => {
|
|
555
|
+
const seed_hex = `0x${(base_seed + run).toString(16)}`;
|
|
556
|
+
(0, import_vitest6.describe)(`workload ${run} (seed ${seed_hex})`, () => {
|
|
557
|
+
(0, import_vitest6.it)("yields identical event order under a global forward query", async () => {
|
|
558
|
+
await assert_identical("forward query", async (store) => {
|
|
559
|
+
const out = [];
|
|
560
|
+
await store.query(
|
|
561
|
+
(e) => {
|
|
562
|
+
out.push(normalize_event(e));
|
|
563
|
+
},
|
|
564
|
+
{ stream: `^${plan.event_prefix}` }
|
|
565
|
+
);
|
|
566
|
+
return out;
|
|
567
|
+
});
|
|
568
|
+
});
|
|
569
|
+
(0, import_vitest6.it)("yields identical snapshot floors under with_snaps", async () => {
|
|
570
|
+
await assert_identical("with_snaps floor", async (store) => {
|
|
571
|
+
const by_stream = {};
|
|
572
|
+
for (const stream of plan.event_streams) {
|
|
573
|
+
const out = [];
|
|
574
|
+
await store.query(
|
|
575
|
+
(e) => {
|
|
576
|
+
out.push(normalize_event(e));
|
|
577
|
+
},
|
|
578
|
+
{ stream, stream_exact: true, with_snaps: true }
|
|
579
|
+
);
|
|
580
|
+
by_stream[stream] = out;
|
|
581
|
+
}
|
|
582
|
+
return by_stream;
|
|
583
|
+
});
|
|
584
|
+
});
|
|
585
|
+
(0, import_vitest6.it)("yields identical order under backward traversal", async () => {
|
|
586
|
+
await assert_identical("backward query", async (store) => {
|
|
587
|
+
const by_stream = {};
|
|
588
|
+
for (const stream of plan.event_streams) {
|
|
589
|
+
const out = [];
|
|
590
|
+
await store.query(
|
|
591
|
+
(e) => {
|
|
592
|
+
out.push(normalize_event(e));
|
|
593
|
+
},
|
|
594
|
+
{ stream, stream_exact: true, backward: true }
|
|
595
|
+
);
|
|
596
|
+
by_stream[stream] = out;
|
|
597
|
+
}
|
|
598
|
+
return by_stream;
|
|
599
|
+
});
|
|
600
|
+
});
|
|
601
|
+
(0, import_vitest6.it)("yields identical query_stats output (head/tail/count/names)", async () => {
|
|
602
|
+
await assert_identical("query_stats", async (store) => {
|
|
603
|
+
const stats = await store.query_stats(
|
|
604
|
+
{ stream: `^${plan.event_prefix}` },
|
|
605
|
+
{ tail: true, count: true, names: true }
|
|
606
|
+
);
|
|
607
|
+
const keys = [...stats.keys()];
|
|
608
|
+
const content = {};
|
|
609
|
+
for (const [stream, s] of stats) {
|
|
610
|
+
content[stream] = {
|
|
611
|
+
head: normalize_event(s.head),
|
|
612
|
+
tail: normalize_event(
|
|
613
|
+
s.tail
|
|
614
|
+
),
|
|
615
|
+
count: s.count,
|
|
616
|
+
names: s.names
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
return { keys, content };
|
|
620
|
+
});
|
|
621
|
+
});
|
|
622
|
+
(0, import_vitest6.it)("yields identical query_streams output", async () => {
|
|
623
|
+
await assert_identical("query_streams", async (store) => {
|
|
624
|
+
const rows = [];
|
|
625
|
+
const { count } = await store.query_streams(
|
|
626
|
+
(p) => {
|
|
627
|
+
rows.push({
|
|
628
|
+
stream: p.stream,
|
|
629
|
+
source: p.source,
|
|
630
|
+
at: p.at,
|
|
631
|
+
blocked: p.blocked,
|
|
632
|
+
priority: p.priority,
|
|
633
|
+
lane: p.lane
|
|
634
|
+
});
|
|
635
|
+
},
|
|
636
|
+
{ stream: `^${plan.sub_prefix}`, limit: 1e3 }
|
|
637
|
+
);
|
|
638
|
+
rows.sort((a, b) => a.stream.localeCompare(b.stream));
|
|
639
|
+
return { count, rows };
|
|
640
|
+
});
|
|
641
|
+
});
|
|
642
|
+
});
|
|
643
|
+
});
|
|
644
|
+
});
|
|
645
|
+
};
|
|
646
|
+
|
|
282
647
|
// src/store-property-tck.ts
|
|
283
|
-
var
|
|
284
|
-
var
|
|
285
|
-
var streamArb =
|
|
286
|
-
var commitArb =
|
|
648
|
+
var import_vitest7 = require("@fast-check/vitest");
|
|
649
|
+
var import_vitest8 = require("vitest");
|
|
650
|
+
var streamArb = import_vitest7.fc.constantFrom("s1", "s2", "s3");
|
|
651
|
+
var commitArb = import_vitest7.fc.record({
|
|
287
652
|
stream: streamArb,
|
|
288
|
-
count:
|
|
653
|
+
count: import_vitest7.fc.integer({ min: 1, max: 3 })
|
|
289
654
|
});
|
|
290
|
-
var claimStreamArb =
|
|
291
|
-
var opArb =
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
655
|
+
var claimStreamArb = import_vitest7.fc.constantFrom("a", "b", "c");
|
|
656
|
+
var opArb = import_vitest7.fc.oneof(
|
|
657
|
+
import_vitest7.fc.record({ kind: import_vitest7.fc.constant("commit"), stream: claimStreamArb }),
|
|
658
|
+
import_vitest7.fc.record({ kind: import_vitest7.fc.constant("claim") }),
|
|
659
|
+
import_vitest7.fc.record({ kind: import_vitest7.fc.constant("ack-all") }),
|
|
660
|
+
import_vitest7.fc.record({ kind: import_vitest7.fc.constant("block-all") })
|
|
296
661
|
);
|
|
297
662
|
var events = (count) => Array.from({ length: count }, () => inc(1));
|
|
298
663
|
var runStorePropertyTck = (options) => {
|
|
299
664
|
const numRuns = options.numRuns ?? 100;
|
|
300
|
-
(0,
|
|
665
|
+
(0, import_vitest8.describe)(`TCK / Store properties / ${options.name}`, () => {
|
|
301
666
|
let store;
|
|
302
|
-
(0,
|
|
667
|
+
(0, import_vitest8.beforeAll)(async () => {
|
|
303
668
|
store = await options.factory();
|
|
304
669
|
await store.seed();
|
|
305
670
|
});
|
|
306
|
-
(0,
|
|
671
|
+
(0, import_vitest8.afterAll)(async () => {
|
|
307
672
|
await store.dispose();
|
|
308
673
|
});
|
|
309
674
|
const reset2 = async () => {
|
|
310
675
|
await store.drop();
|
|
311
676
|
await store.seed();
|
|
312
677
|
};
|
|
313
|
-
(0,
|
|
314
|
-
|
|
678
|
+
(0, import_vitest8.describe)("commit version invariants", () => {
|
|
679
|
+
import_vitest7.test.prop([import_vitest7.fc.array(commitArb, { minLength: 0, maxLength: 30 })], {
|
|
315
680
|
numRuns
|
|
316
681
|
})(
|
|
317
682
|
"per-stream versions are 0..N-1 in commit order, regardless of interleaving",
|
|
@@ -326,19 +691,19 @@ var runStorePropertyTck = (options) => {
|
|
|
326
691
|
make_meta({ stream })
|
|
327
692
|
);
|
|
328
693
|
committed.forEach((e, i) => {
|
|
329
|
-
(0,
|
|
694
|
+
(0, import_vitest8.expect)(e.version).toBe(before + 1 + i);
|
|
330
695
|
});
|
|
331
696
|
expected.set(stream, before + count);
|
|
332
697
|
}
|
|
333
698
|
for (const stream of new Set(commits.map((c) => c.stream))) {
|
|
334
699
|
const seen = await collect(store, { stream, stream_exact: true });
|
|
335
700
|
seen.forEach((e, i) => {
|
|
336
|
-
(0,
|
|
701
|
+
(0, import_vitest8.expect)(e.version).toBe(i);
|
|
337
702
|
});
|
|
338
703
|
}
|
|
339
704
|
}
|
|
340
705
|
);
|
|
341
|
-
|
|
706
|
+
import_vitest7.test.prop([import_vitest7.fc.array(commitArb, { minLength: 1, maxLength: 20 })], {
|
|
342
707
|
numRuns
|
|
343
708
|
})(
|
|
344
709
|
"bad expectedVersion throws and commits no events",
|
|
@@ -353,7 +718,7 @@ var runStorePropertyTck = (options) => {
|
|
|
353
718
|
}
|
|
354
719
|
const stream = commits[0].stream;
|
|
355
720
|
const before = await collect(store, { stream, stream_exact: true });
|
|
356
|
-
await (0,
|
|
721
|
+
await (0, import_vitest8.expect)(
|
|
357
722
|
store.commit(
|
|
358
723
|
stream,
|
|
359
724
|
[inc(1)],
|
|
@@ -362,12 +727,12 @@ var runStorePropertyTck = (options) => {
|
|
|
362
727
|
)
|
|
363
728
|
).rejects.toThrow();
|
|
364
729
|
const after = await collect(store, { stream, stream_exact: true });
|
|
365
|
-
(0,
|
|
730
|
+
(0, import_vitest8.expect)(after.length).toBe(before.length);
|
|
366
731
|
}
|
|
367
732
|
);
|
|
368
733
|
});
|
|
369
|
-
(0,
|
|
370
|
-
|
|
734
|
+
(0, import_vitest8.describe)("claim/lease lifecycle invariants", () => {
|
|
735
|
+
import_vitest7.test.prop([import_vitest7.fc.array(opArb, { minLength: 1, maxLength: 30 })], {
|
|
371
736
|
numRuns
|
|
372
737
|
})(
|
|
373
738
|
"no leaks: claims are always acked or blocked, never lost",
|
|
@@ -408,13 +773,13 @@ var runStorePropertyTck = (options) => {
|
|
|
408
773
|
);
|
|
409
774
|
}
|
|
410
775
|
}
|
|
411
|
-
(0,
|
|
776
|
+
(0, import_vitest8.expect)(totalResolved + pending.length).toBe(totalClaims);
|
|
412
777
|
}
|
|
413
778
|
);
|
|
414
|
-
|
|
779
|
+
import_vitest7.test.prop(
|
|
415
780
|
[
|
|
416
|
-
|
|
417
|
-
|
|
781
|
+
import_vitest7.fc.array(claimStreamArb, { minLength: 1, maxLength: 5 }),
|
|
782
|
+
import_vitest7.fc.array(claimStreamArb, { minLength: 0, maxLength: 5 })
|
|
418
783
|
],
|
|
419
784
|
{ numRuns }
|
|
420
785
|
)(
|
|
@@ -446,13 +811,13 @@ var runStorePropertyTck = (options) => {
|
|
|
446
811
|
await store.claim(10, 10, "worker", 6e4)
|
|
447
812
|
);
|
|
448
813
|
for (const lease of acked2) {
|
|
449
|
-
(0,
|
|
814
|
+
(0, import_vitest8.expect)(lease.at).toBeGreaterThanOrEqual(
|
|
450
815
|
watermark1.get(lease.stream)
|
|
451
816
|
);
|
|
452
817
|
}
|
|
453
818
|
}
|
|
454
819
|
);
|
|
455
|
-
|
|
820
|
+
import_vitest7.test.prop([import_vitest7.fc.array(claimStreamArb, { minLength: 1, maxLength: 5 })], {
|
|
456
821
|
numRuns
|
|
457
822
|
})("blocked streams cannot be claimed again", async (commits) => {
|
|
458
823
|
await reset2();
|
|
@@ -475,46 +840,46 @@ var runStorePropertyTck = (options) => {
|
|
|
475
840
|
make_meta({ stream: "ctrl" })
|
|
476
841
|
);
|
|
477
842
|
const reclaim = await store.claim(10, 10, "worker2", 6e4);
|
|
478
|
-
for (const l of reclaim) (0,
|
|
843
|
+
for (const l of reclaim) (0, import_vitest8.expect)(blockedSet.has(l.stream)).toBe(false);
|
|
479
844
|
});
|
|
480
845
|
});
|
|
481
846
|
});
|
|
482
847
|
};
|
|
483
848
|
|
|
484
849
|
// src/store-tck.ts
|
|
485
|
-
var
|
|
486
|
-
var
|
|
850
|
+
var import_act2 = require("@rotorsoft/act");
|
|
851
|
+
var import_vitest9 = require("vitest");
|
|
487
852
|
var runStoreTck = (options) => {
|
|
488
|
-
(0,
|
|
853
|
+
(0, import_vitest9.describe)(`TCK / Store / ${options.name}`, () => {
|
|
489
854
|
let store;
|
|
490
855
|
const caps = { ...options.capabilities };
|
|
491
|
-
(0,
|
|
856
|
+
(0, import_vitest9.beforeAll)(async () => {
|
|
492
857
|
store = await options.factory();
|
|
493
858
|
await store.drop();
|
|
494
859
|
await store.seed();
|
|
495
860
|
});
|
|
496
|
-
(0,
|
|
861
|
+
(0, import_vitest9.afterAll)(async () => {
|
|
497
862
|
await store.dispose();
|
|
498
863
|
});
|
|
499
|
-
(0,
|
|
500
|
-
(0,
|
|
864
|
+
(0, import_vitest9.describe)("commit", () => {
|
|
865
|
+
(0, import_vitest9.it)("returns committed events with sequenced ids and versions", async () => {
|
|
501
866
|
const s = `commit-seq-${uid()}`;
|
|
502
867
|
const committed = await store.commit(
|
|
503
868
|
s,
|
|
504
869
|
[inc(1), inc(2), dec(3)],
|
|
505
870
|
make_meta({ stream: s })
|
|
506
871
|
);
|
|
507
|
-
(0,
|
|
508
|
-
(0,
|
|
509
|
-
(0,
|
|
510
|
-
(0,
|
|
511
|
-
(0,
|
|
512
|
-
(0,
|
|
872
|
+
(0, import_vitest9.expect)(committed).toHaveLength(3);
|
|
873
|
+
(0, import_vitest9.expect)(committed[0].version).toBe(0);
|
|
874
|
+
(0, import_vitest9.expect)(committed[1].version).toBe(1);
|
|
875
|
+
(0, import_vitest9.expect)(committed[2].version).toBe(2);
|
|
876
|
+
(0, import_vitest9.expect)(committed[0].name).toBe("Incremented");
|
|
877
|
+
(0, import_vitest9.expect)(committed[2].data).toEqual({ amount: 3 });
|
|
513
878
|
for (let i = 1; i < committed.length; i++) {
|
|
514
|
-
(0,
|
|
879
|
+
(0, import_vitest9.expect)(committed[i].id).toBeGreaterThan(committed[i - 1].id);
|
|
515
880
|
}
|
|
516
881
|
});
|
|
517
|
-
(0,
|
|
882
|
+
(0, import_vitest9.it)("attaches correlation and stream metadata", async () => {
|
|
518
883
|
const s = `commit-meta-${uid()}`;
|
|
519
884
|
const correlation = `cor-${uid()}`;
|
|
520
885
|
const committed = await store.commit(
|
|
@@ -522,10 +887,10 @@ var runStoreTck = (options) => {
|
|
|
522
887
|
[inc(1)],
|
|
523
888
|
make_meta({ stream: s, correlation })
|
|
524
889
|
);
|
|
525
|
-
(0,
|
|
526
|
-
(0,
|
|
890
|
+
(0, import_vitest9.expect)(committed[0].stream).toBe(s);
|
|
891
|
+
(0, import_vitest9.expect)(committed[0].meta.correlation).toBe(correlation);
|
|
527
892
|
});
|
|
528
|
-
(0,
|
|
893
|
+
(0, import_vitest9.it)("throws ConcurrencyError when expectedVersion is wrong", async () => {
|
|
529
894
|
const s = `commit-cc-${uid()}`;
|
|
530
895
|
await store.commit(
|
|
531
896
|
s,
|
|
@@ -538,26 +903,26 @@ var runStoreTck = (options) => {
|
|
|
538
903
|
make_meta({ stream: s }),
|
|
539
904
|
0
|
|
540
905
|
);
|
|
541
|
-
await (0,
|
|
906
|
+
await (0, import_vitest9.expect)(
|
|
542
907
|
store.commit(s, [inc(1)], make_meta({ stream: s }), 0)
|
|
543
|
-
).rejects.toBeInstanceOf(
|
|
908
|
+
).rejects.toBeInstanceOf(import_act2.ConcurrencyError);
|
|
544
909
|
});
|
|
545
|
-
(0,
|
|
910
|
+
(0, import_vitest9.it)("preserves prior events when a concurrent commit is rejected", async () => {
|
|
546
911
|
const s = `commit-cc-preserve-${uid()}`;
|
|
547
912
|
await store.commit(
|
|
548
913
|
s,
|
|
549
914
|
[inc(1), inc(2)],
|
|
550
915
|
make_meta({ stream: s })
|
|
551
916
|
);
|
|
552
|
-
await (0,
|
|
917
|
+
await (0, import_vitest9.expect)(
|
|
553
918
|
store.commit(s, [inc(3)], make_meta({ stream: s }), 0)
|
|
554
|
-
).rejects.toBeInstanceOf(
|
|
919
|
+
).rejects.toBeInstanceOf(import_act2.ConcurrencyError);
|
|
555
920
|
const found = await collect(store, { stream: s, stream_exact: true });
|
|
556
|
-
(0,
|
|
921
|
+
(0, import_vitest9.expect)(found).toHaveLength(2);
|
|
557
922
|
});
|
|
558
923
|
});
|
|
559
|
-
(0,
|
|
560
|
-
(0,
|
|
924
|
+
(0, import_vitest9.describe)("query", () => {
|
|
925
|
+
(0, import_vitest9.it)("filters by stream, names, correlation, limit, with_snaps", async () => {
|
|
561
926
|
const s1 = `q-s1-${uid()}`;
|
|
562
927
|
const s2 = `q-s2-${uid()}`;
|
|
563
928
|
const cor = `q-cor-${uid()}`;
|
|
@@ -575,23 +940,69 @@ var runStoreTck = (options) => {
|
|
|
575
940
|
stream: s1,
|
|
576
941
|
stream_exact: true
|
|
577
942
|
});
|
|
578
|
-
(0,
|
|
943
|
+
(0, import_vitest9.expect)(by_stream).toHaveLength(2);
|
|
579
944
|
const by_name = await collect(store, {
|
|
580
945
|
stream: s2,
|
|
581
946
|
stream_exact: true,
|
|
582
947
|
names: ["Reset"]
|
|
583
948
|
});
|
|
584
|
-
(0,
|
|
585
|
-
(0,
|
|
949
|
+
(0, import_vitest9.expect)(by_name).toHaveLength(1);
|
|
950
|
+
(0, import_vitest9.expect)(by_name[0].name).toBe("Reset");
|
|
586
951
|
const by_correlation = await collect(store, { correlation: cor });
|
|
587
|
-
(0,
|
|
952
|
+
(0, import_vitest9.expect)(by_correlation).toHaveLength(5);
|
|
588
953
|
const limited = await collect(store, {
|
|
589
954
|
correlation: cor,
|
|
590
955
|
limit: 2
|
|
591
956
|
});
|
|
592
|
-
(0,
|
|
957
|
+
(0, import_vitest9.expect)(limited).toHaveLength(2);
|
|
593
958
|
});
|
|
594
|
-
(0,
|
|
959
|
+
(0, import_vitest9.it)("with_snaps resumes from the latest snapshot per stream", async () => {
|
|
960
|
+
const s = `q-snap-${uid()}`;
|
|
961
|
+
await store.commit(
|
|
962
|
+
s,
|
|
963
|
+
[inc(1), inc(1)],
|
|
964
|
+
make_meta({ stream: s })
|
|
965
|
+
);
|
|
966
|
+
const [snap] = await store.commit(
|
|
967
|
+
s,
|
|
968
|
+
[{ name: import_act2.SNAP_EVENT, data: { count: 2 } }],
|
|
969
|
+
make_meta({ stream: s })
|
|
970
|
+
);
|
|
971
|
+
await store.commit(
|
|
972
|
+
s,
|
|
973
|
+
[inc(1), inc(1), inc(1)],
|
|
974
|
+
make_meta({ stream: s })
|
|
975
|
+
);
|
|
976
|
+
const from_snap = await collect(store, {
|
|
977
|
+
stream: s,
|
|
978
|
+
stream_exact: true,
|
|
979
|
+
with_snaps: true
|
|
980
|
+
});
|
|
981
|
+
(0, import_vitest9.expect)(from_snap).toHaveLength(4);
|
|
982
|
+
(0, import_vitest9.expect)(from_snap[0].name).toBe(import_act2.SNAP_EVENT);
|
|
983
|
+
const domain = await collect(store, { stream: s, stream_exact: true });
|
|
984
|
+
(0, import_vitest9.expect)(domain).toHaveLength(5);
|
|
985
|
+
const after_snap = await collect(store, {
|
|
986
|
+
stream: s,
|
|
987
|
+
stream_exact: true,
|
|
988
|
+
with_snaps: true,
|
|
989
|
+
after: snap.id
|
|
990
|
+
});
|
|
991
|
+
(0, import_vitest9.expect)(after_snap).toHaveLength(3);
|
|
992
|
+
const s2 = `q-nosnap-${uid()}`;
|
|
993
|
+
await store.commit(
|
|
994
|
+
s2,
|
|
995
|
+
[inc(1), inc(1)],
|
|
996
|
+
make_meta({ stream: s2 })
|
|
997
|
+
);
|
|
998
|
+
const full = await collect(store, {
|
|
999
|
+
stream: s2,
|
|
1000
|
+
stream_exact: true,
|
|
1001
|
+
with_snaps: true
|
|
1002
|
+
});
|
|
1003
|
+
(0, import_vitest9.expect)(full).toHaveLength(2);
|
|
1004
|
+
});
|
|
1005
|
+
(0, import_vitest9.it)("supports backward traversal", async () => {
|
|
595
1006
|
const s = `q-back-${uid()}`;
|
|
596
1007
|
const committed = await store.commit(
|
|
597
1008
|
s,
|
|
@@ -604,8 +1015,8 @@ var runStoreTck = (options) => {
|
|
|
604
1015
|
stream_exact: true,
|
|
605
1016
|
backward: true
|
|
606
1017
|
});
|
|
607
|
-
(0,
|
|
608
|
-
(0,
|
|
1018
|
+
(0, import_vitest9.expect)(forward.map((e) => e.id)).toEqual(committed.map((c) => c.id));
|
|
1019
|
+
(0, import_vitest9.expect)(backward.map((e) => e.id)).toEqual(
|
|
609
1020
|
[...committed].reverse().map((c) => c.id)
|
|
610
1021
|
);
|
|
611
1022
|
const latest = await collect(store, {
|
|
@@ -614,10 +1025,10 @@ var runStoreTck = (options) => {
|
|
|
614
1025
|
backward: true,
|
|
615
1026
|
limit: 1
|
|
616
1027
|
});
|
|
617
|
-
(0,
|
|
618
|
-
(0,
|
|
1028
|
+
(0, import_vitest9.expect)(latest).toHaveLength(1);
|
|
1029
|
+
(0, import_vitest9.expect)(latest[0].id).toBe(committed.at(-1).id);
|
|
619
1030
|
});
|
|
620
|
-
(0,
|
|
1031
|
+
(0, import_vitest9.it)("after/before bound the id range", async () => {
|
|
621
1032
|
const s = `q-bounds-${uid()}`;
|
|
622
1033
|
const committed = await store.commit(
|
|
623
1034
|
s,
|
|
@@ -629,7 +1040,7 @@ var runStoreTck = (options) => {
|
|
|
629
1040
|
stream_exact: true,
|
|
630
1041
|
after: committed[0].id
|
|
631
1042
|
});
|
|
632
|
-
(0,
|
|
1043
|
+
(0, import_vitest9.expect)(after_first.map((e) => e.id)).toEqual(
|
|
633
1044
|
committed.slice(1).map((c) => c.id)
|
|
634
1045
|
);
|
|
635
1046
|
const before_last = await collect(store, {
|
|
@@ -637,11 +1048,11 @@ var runStoreTck = (options) => {
|
|
|
637
1048
|
stream_exact: true,
|
|
638
1049
|
before: committed[committed.length - 1].id
|
|
639
1050
|
});
|
|
640
|
-
(0,
|
|
1051
|
+
(0, import_vitest9.expect)(before_last.map((e) => e.id)).toEqual(
|
|
641
1052
|
committed.slice(0, -1).map((c) => c.id)
|
|
642
1053
|
);
|
|
643
1054
|
});
|
|
644
|
-
(0,
|
|
1055
|
+
(0, import_vitest9.it)("created_after/created_before filter by timestamp", async () => {
|
|
645
1056
|
const s = `q-ts-${uid()}`;
|
|
646
1057
|
const committed = await store.commit(
|
|
647
1058
|
s,
|
|
@@ -657,15 +1068,15 @@ var runStoreTck = (options) => {
|
|
|
657
1068
|
created_after: before,
|
|
658
1069
|
created_before: future
|
|
659
1070
|
});
|
|
660
|
-
(0,
|
|
1071
|
+
(0, import_vitest9.expect)(in_window.length).toBe(1);
|
|
661
1072
|
const out_of_window = await collect(store, {
|
|
662
1073
|
stream: s,
|
|
663
1074
|
stream_exact: true,
|
|
664
1075
|
created_after: future
|
|
665
1076
|
});
|
|
666
|
-
(0,
|
|
1077
|
+
(0, import_vitest9.expect)(out_of_window.length).toBe(0);
|
|
667
1078
|
});
|
|
668
|
-
(0,
|
|
1079
|
+
(0, import_vitest9.it)("backward traversal short-circuits at `after` id boundary", async () => {
|
|
669
1080
|
const s = `q-back-after-${uid()}`;
|
|
670
1081
|
const committed = await store.commit(
|
|
671
1082
|
s,
|
|
@@ -678,12 +1089,12 @@ var runStoreTck = (options) => {
|
|
|
678
1089
|
backward: true,
|
|
679
1090
|
after: committed[0].id
|
|
680
1091
|
});
|
|
681
|
-
(0,
|
|
1092
|
+
(0, import_vitest9.expect)(got.map((e) => e.id)).toEqual([
|
|
682
1093
|
committed[2].id,
|
|
683
1094
|
committed[1].id
|
|
684
1095
|
]);
|
|
685
1096
|
});
|
|
686
|
-
(0,
|
|
1097
|
+
(0, import_vitest9.it)("backward traversal short-circuits at `created_after` boundary", async () => {
|
|
687
1098
|
const s = `q-back-cafter-${uid()}`;
|
|
688
1099
|
await store.commit(
|
|
689
1100
|
s,
|
|
@@ -697,9 +1108,9 @@ var runStoreTck = (options) => {
|
|
|
697
1108
|
backward: true,
|
|
698
1109
|
created_after: future
|
|
699
1110
|
});
|
|
700
|
-
(0,
|
|
1111
|
+
(0, import_vitest9.expect)(got).toHaveLength(0);
|
|
701
1112
|
});
|
|
702
|
-
(0,
|
|
1113
|
+
(0, import_vitest9.it)("backward traversal honors created_before by skipping newer events", async () => {
|
|
703
1114
|
const s = `q-back-ts-${uid()}`;
|
|
704
1115
|
const committed = await store.commit(
|
|
705
1116
|
s,
|
|
@@ -713,9 +1124,9 @@ var runStoreTck = (options) => {
|
|
|
713
1124
|
backward: true,
|
|
714
1125
|
created_before: past
|
|
715
1126
|
});
|
|
716
|
-
(0,
|
|
1127
|
+
(0, import_vitest9.expect)(got).toHaveLength(0);
|
|
717
1128
|
});
|
|
718
|
-
(0,
|
|
1129
|
+
(0, import_vitest9.it)("stream_exact disables regex matching", async () => {
|
|
719
1130
|
const tag = uid();
|
|
720
1131
|
const a = `q-exact-${tag}`;
|
|
721
1132
|
const b = `q-exact-${tag}-extra`;
|
|
@@ -730,10 +1141,10 @@ var runStoreTck = (options) => {
|
|
|
730
1141
|
make_meta({ stream: b })
|
|
731
1142
|
);
|
|
732
1143
|
const exact = await collect(store, { stream: a, stream_exact: true });
|
|
733
|
-
(0,
|
|
734
|
-
(0,
|
|
1144
|
+
(0, import_vitest9.expect)(exact).toHaveLength(1);
|
|
1145
|
+
(0, import_vitest9.expect)(exact[0].data).toEqual({ amount: 1 });
|
|
735
1146
|
});
|
|
736
|
-
(0,
|
|
1147
|
+
(0, import_vitest9.it)("plain regex without anchors is a substring match", async () => {
|
|
737
1148
|
const tag = uid();
|
|
738
1149
|
const inner = `qr-${tag}-inner`;
|
|
739
1150
|
const longer = `qr-${tag}-inner-extra`;
|
|
@@ -748,9 +1159,9 @@ var runStoreTck = (options) => {
|
|
|
748
1159
|
make_meta({ stream: longer })
|
|
749
1160
|
);
|
|
750
1161
|
const got = await collect(store, { stream: `qr-${tag}-inner` });
|
|
751
|
-
(0,
|
|
1162
|
+
(0, import_vitest9.expect)(got.map((e) => e.stream).sort()).toEqual([inner, longer].sort());
|
|
752
1163
|
});
|
|
753
|
-
(0,
|
|
1164
|
+
(0, import_vitest9.it)("caller-anchored `^name$` matches only the whole string", async () => {
|
|
754
1165
|
const tag = uid();
|
|
755
1166
|
const inner = `qr-${tag}-anchor`;
|
|
756
1167
|
const longer = `qr-${tag}-anchor-extra`;
|
|
@@ -765,10 +1176,10 @@ var runStoreTck = (options) => {
|
|
|
765
1176
|
make_meta({ stream: longer })
|
|
766
1177
|
);
|
|
767
1178
|
const got = await collect(store, { stream: `^qr-${tag}-anchor$` });
|
|
768
|
-
(0,
|
|
769
|
-
(0,
|
|
1179
|
+
(0, import_vitest9.expect)(got).toHaveLength(1);
|
|
1180
|
+
(0, import_vitest9.expect)(got[0].stream).toBe(inner);
|
|
770
1181
|
});
|
|
771
|
-
(0,
|
|
1182
|
+
(0, import_vitest9.it)("caller-anchored `^prefix` matches by prefix", async () => {
|
|
772
1183
|
const tag = uid();
|
|
773
1184
|
const a = `qr-${tag}-pfx-a`;
|
|
774
1185
|
const b = `qr-${tag}-pfx-b`;
|
|
@@ -789,18 +1200,39 @@ var runStoreTck = (options) => {
|
|
|
789
1200
|
make_meta({ stream: other })
|
|
790
1201
|
);
|
|
791
1202
|
const got = await collect(store, { stream: `^qr-${tag}-pfx-` });
|
|
792
|
-
(0,
|
|
1203
|
+
(0, import_vitest9.expect)(got.map((e) => e.stream).sort()).toEqual([a, b].sort());
|
|
793
1204
|
});
|
|
794
1205
|
});
|
|
795
|
-
(0,
|
|
796
|
-
(0,
|
|
1206
|
+
(0, import_vitest9.describe)("subscribe + claim + ack", () => {
|
|
1207
|
+
(0, import_vitest9.it)("subscribes new streams and is idempotent on repeat", async () => {
|
|
797
1208
|
const s = `sub-${uid()}`;
|
|
798
1209
|
const first = await store.subscribe([{ stream: s }]);
|
|
799
|
-
(0,
|
|
1210
|
+
(0, import_vitest9.expect)(first.subscribed).toBe(1);
|
|
800
1211
|
const second = await store.subscribe([{ stream: s }]);
|
|
801
|
-
(0,
|
|
1212
|
+
(0, import_vitest9.expect)(second.subscribed).toBe(0);
|
|
802
1213
|
});
|
|
803
|
-
(0,
|
|
1214
|
+
(0, import_vitest9.it)("keeps the maximum priority when a stream is re-subscribed", async () => {
|
|
1215
|
+
const s = `sub-pri-${uid()}`;
|
|
1216
|
+
const read = async () => {
|
|
1217
|
+
const got = {};
|
|
1218
|
+
await store.query_streams(
|
|
1219
|
+
(p) => {
|
|
1220
|
+
got.priority = p.priority;
|
|
1221
|
+
},
|
|
1222
|
+
{ stream: s, stream_exact: true }
|
|
1223
|
+
);
|
|
1224
|
+
return got.priority;
|
|
1225
|
+
};
|
|
1226
|
+
await store.subscribe([{ stream: s, priority: 3 }]);
|
|
1227
|
+
(0, import_vitest9.expect)(await read()).toBe(3);
|
|
1228
|
+
await store.subscribe([{ stream: s, priority: 10 }]);
|
|
1229
|
+
(0, import_vitest9.expect)(await read()).toBe(10);
|
|
1230
|
+
await store.subscribe([{ stream: s, priority: 1 }]);
|
|
1231
|
+
(0, import_vitest9.expect)(await read()).toBe(10);
|
|
1232
|
+
await store.subscribe([{ stream: s }]);
|
|
1233
|
+
(0, import_vitest9.expect)(await read()).toBe(10);
|
|
1234
|
+
});
|
|
1235
|
+
(0, import_vitest9.it)("claims a subscribed stream and ack releases the lease", async () => {
|
|
804
1236
|
const s = `claim-${uid()}`;
|
|
805
1237
|
await store.subscribe([{ stream: s }]);
|
|
806
1238
|
await store.commit(
|
|
@@ -811,11 +1243,11 @@ var runStoreTck = (options) => {
|
|
|
811
1243
|
const by = `worker-${uid()}`;
|
|
812
1244
|
const leased = await store.claim(100, 0, by, 1e4);
|
|
813
1245
|
const mine = leased.find((l) => l.stream === s);
|
|
814
|
-
(0,
|
|
815
|
-
(0,
|
|
1246
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1247
|
+
(0, import_vitest9.expect)(mine.by).toBe(by);
|
|
816
1248
|
await store.ack([{ ...mine, at: mine.at + 1 }]);
|
|
817
1249
|
});
|
|
818
|
-
(0,
|
|
1250
|
+
(0, import_vitest9.it)("does not double-claim a held lease", async () => {
|
|
819
1251
|
const s = `claim-held-${uid()}`;
|
|
820
1252
|
const other = `claim-other-${uid()}`;
|
|
821
1253
|
await store.subscribe([{ stream: s }]);
|
|
@@ -826,7 +1258,7 @@ var runStoreTck = (options) => {
|
|
|
826
1258
|
);
|
|
827
1259
|
const leasedA = await store.claim(100, 0, `wA-${uid()}`, 1e5);
|
|
828
1260
|
const targetA = leasedA.find((l) => l.stream === s);
|
|
829
|
-
(0,
|
|
1261
|
+
(0, import_vitest9.expect)(targetA).toBeDefined();
|
|
830
1262
|
await store.subscribe([{ stream: other }]);
|
|
831
1263
|
await store.commit(
|
|
832
1264
|
other,
|
|
@@ -834,11 +1266,11 @@ var runStoreTck = (options) => {
|
|
|
834
1266
|
make_meta({ stream: other })
|
|
835
1267
|
);
|
|
836
1268
|
const leasedB = await store.claim(100, 0, `wB-${uid()}`, 1e5);
|
|
837
|
-
(0,
|
|
838
|
-
(0,
|
|
839
|
-
(0,
|
|
1269
|
+
(0, import_vitest9.expect)(leasedB.length).toBeGreaterThan(0);
|
|
1270
|
+
(0, import_vitest9.expect)(leasedB.find((l) => l.stream === s)).toBeUndefined();
|
|
1271
|
+
(0, import_vitest9.expect)(leasedB.find((l) => l.stream === other)).toBeDefined();
|
|
840
1272
|
});
|
|
841
|
-
(0,
|
|
1273
|
+
(0, import_vitest9.it)("supports dual frontiers (lagging + leading)", async () => {
|
|
842
1274
|
const s = `claim-dual-${uid()}`;
|
|
843
1275
|
await store.subscribe([{ stream: s }]);
|
|
844
1276
|
await store.commit(
|
|
@@ -848,12 +1280,12 @@ var runStoreTck = (options) => {
|
|
|
848
1280
|
);
|
|
849
1281
|
const first = await store.claim(100, 0, `w-${uid()}`, 1);
|
|
850
1282
|
const mine = first.find((l) => l.stream === s);
|
|
851
|
-
(0,
|
|
1283
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
852
1284
|
await store.ack([{ ...mine, at: mine.at + 1 }]);
|
|
853
1285
|
const second = await store.claim(0, 100, `w-${uid()}`, 1);
|
|
854
|
-
(0,
|
|
1286
|
+
(0, import_vitest9.expect)(second.find((l) => l.stream === s)).toBeDefined();
|
|
855
1287
|
});
|
|
856
|
-
(0,
|
|
1288
|
+
(0, import_vitest9.it)("dedupes when both frontiers would return the same stream", async () => {
|
|
857
1289
|
const s = `claim-dedup-${uid()}`;
|
|
858
1290
|
await store.subscribe([{ stream: s }]);
|
|
859
1291
|
await store.commit(
|
|
@@ -863,9 +1295,9 @@ var runStoreTck = (options) => {
|
|
|
863
1295
|
);
|
|
864
1296
|
const claimed = await store.claim(100, 100, `w-${uid()}`, 1e5);
|
|
865
1297
|
const matches = claimed.filter((l) => l.stream === s);
|
|
866
|
-
(0,
|
|
1298
|
+
(0, import_vitest9.expect)(matches).toHaveLength(1);
|
|
867
1299
|
});
|
|
868
|
-
(0,
|
|
1300
|
+
(0, import_vitest9.it)("silently ignores ack from the wrong holder", async () => {
|
|
869
1301
|
const s = `ack-wrong-${uid()}`;
|
|
870
1302
|
const sibling = `ack-sibling-${uid()}`;
|
|
871
1303
|
await store.subscribe([{ stream: s }, { stream: sibling }]);
|
|
@@ -882,40 +1314,40 @@ var runStoreTck = (options) => {
|
|
|
882
1314
|
const leased = await store.claim(100, 0, `right-${uid()}`, 1e5);
|
|
883
1315
|
const mine = leased.find((l) => l.stream === s);
|
|
884
1316
|
const sibling_lease = leased.find((l) => l.stream === sibling);
|
|
885
|
-
(0,
|
|
886
|
-
(0,
|
|
1317
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1318
|
+
(0, import_vitest9.expect)(sibling_lease).toBeDefined();
|
|
887
1319
|
const acked = await store.ack([
|
|
888
1320
|
{ ...mine, by: "imposter" },
|
|
889
1321
|
sibling_lease
|
|
890
1322
|
]);
|
|
891
|
-
(0,
|
|
892
|
-
(0,
|
|
1323
|
+
(0, import_vitest9.expect)(acked.length).toBeGreaterThan(0);
|
|
1324
|
+
(0, import_vitest9.expect)(acked.find((l) => l.stream === s)).toBeUndefined();
|
|
893
1325
|
});
|
|
894
|
-
(0,
|
|
1326
|
+
(0, import_vitest9.it)("ack with a stale (lower) watermark does not throw", async () => {
|
|
895
1327
|
const s = `ack-stale-${uid()}`;
|
|
896
1328
|
await store.subscribe([{ stream: s }]);
|
|
897
1329
|
const by = `w-${uid()}`;
|
|
898
1330
|
const leased = await store.claim(100, 0, by, 1e5);
|
|
899
1331
|
const mine = leased.find((l) => l.stream === s);
|
|
900
|
-
(0,
|
|
901
|
-
await (0,
|
|
1332
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1333
|
+
await (0, import_vitest9.expect)(
|
|
902
1334
|
store.ack([{ ...mine, at: -5 }])
|
|
903
1335
|
).resolves.toBeDefined();
|
|
904
1336
|
});
|
|
905
|
-
(0,
|
|
1337
|
+
(0, import_vitest9.it)("claim with no subscribed streams returns an empty array", async () => {
|
|
906
1338
|
const fresh = await options.factory();
|
|
907
1339
|
try {
|
|
908
1340
|
await fresh.drop();
|
|
909
1341
|
await fresh.seed();
|
|
910
1342
|
const claimed = await fresh.claim(1, 1, `w-${uid()}`, 1e3);
|
|
911
|
-
(0,
|
|
1343
|
+
(0, import_vitest9.expect)(claimed).toEqual([]);
|
|
912
1344
|
} finally {
|
|
913
1345
|
await fresh.dispose();
|
|
914
1346
|
}
|
|
915
1347
|
});
|
|
916
1348
|
});
|
|
917
|
-
(0,
|
|
918
|
-
(0,
|
|
1349
|
+
(0, import_vitest9.describe)("lease semantics", () => {
|
|
1350
|
+
(0, import_vitest9.it)("returns retry=0 on first claim and increments on re-claim without ack", async () => {
|
|
919
1351
|
const fresh = await options.factory();
|
|
920
1352
|
try {
|
|
921
1353
|
await fresh.drop();
|
|
@@ -929,17 +1361,17 @@ var runStoreTck = (options) => {
|
|
|
929
1361
|
);
|
|
930
1362
|
const first = await fresh.claim(1, 0, `w-${uid()}`, 0);
|
|
931
1363
|
const f = first.find((l) => l.stream === s);
|
|
932
|
-
(0,
|
|
933
|
-
(0,
|
|
1364
|
+
(0, import_vitest9.expect)(f).toBeDefined();
|
|
1365
|
+
(0, import_vitest9.expect)(f.retry).toBe(0);
|
|
934
1366
|
const second = await fresh.claim(1, 0, `w-${uid()}`, 1e5);
|
|
935
1367
|
const sec = second.find((l) => l.stream === s);
|
|
936
|
-
(0,
|
|
937
|
-
(0,
|
|
1368
|
+
(0, import_vitest9.expect)(sec).toBeDefined();
|
|
1369
|
+
(0, import_vitest9.expect)(sec.retry).toBe(1);
|
|
938
1370
|
} finally {
|
|
939
1371
|
await fresh.dispose();
|
|
940
1372
|
}
|
|
941
1373
|
});
|
|
942
|
-
(0,
|
|
1374
|
+
(0, import_vitest9.it)("reports lagging=true from the lagging frontier and false from the leading frontier", async () => {
|
|
943
1375
|
const fresh = await options.factory();
|
|
944
1376
|
try {
|
|
945
1377
|
await fresh.drop();
|
|
@@ -952,16 +1384,16 @@ var runStoreTck = (options) => {
|
|
|
952
1384
|
make_meta({ stream: s })
|
|
953
1385
|
);
|
|
954
1386
|
const lag = await fresh.claim(1, 0, `w-${uid()}`, 0);
|
|
955
|
-
(0,
|
|
1387
|
+
(0, import_vitest9.expect)(lag.find((l) => l.stream === s)?.lagging).toBe(true);
|
|
956
1388
|
const lead = await fresh.claim(0, 1, `w-${uid()}`, 1e5);
|
|
957
|
-
(0,
|
|
1389
|
+
(0, import_vitest9.expect)(lead.find((l) => l.stream === s)?.lagging).toBe(false);
|
|
958
1390
|
} finally {
|
|
959
1391
|
await fresh.dispose();
|
|
960
1392
|
}
|
|
961
1393
|
});
|
|
962
1394
|
});
|
|
963
|
-
|
|
964
|
-
(0,
|
|
1395
|
+
import_vitest9.describe.skipIf(!caps.concurrent_claim)("concurrency (capability)", () => {
|
|
1396
|
+
(0, import_vitest9.it)("never double-leases a stream across concurrent claimers", async () => {
|
|
965
1397
|
const fresh = await options.factory();
|
|
966
1398
|
try {
|
|
967
1399
|
await fresh.drop();
|
|
@@ -984,15 +1416,15 @@ var runStoreTck = (options) => {
|
|
|
984
1416
|
fresh.claim(100, 100, `wB-${uid()}`, 6e4)
|
|
985
1417
|
]);
|
|
986
1418
|
const claimed = [...a, ...b].map((l) => l.stream).filter((stream) => owned.has(stream));
|
|
987
|
-
(0,
|
|
988
|
-
(0,
|
|
1419
|
+
(0, import_vitest9.expect)(new Set(claimed).size).toBe(claimed.length);
|
|
1420
|
+
(0, import_vitest9.expect)(claimed.length).toBe(owned.size);
|
|
989
1421
|
} finally {
|
|
990
1422
|
await fresh.dispose();
|
|
991
1423
|
}
|
|
992
1424
|
});
|
|
993
1425
|
});
|
|
994
|
-
(0,
|
|
995
|
-
(0,
|
|
1426
|
+
(0, import_vitest9.describe)("block", () => {
|
|
1427
|
+
(0, import_vitest9.it)("hides blocked streams from claim", async () => {
|
|
996
1428
|
const s = `block-${uid()}`;
|
|
997
1429
|
await store.subscribe([{ stream: s }]);
|
|
998
1430
|
await store.commit(
|
|
@@ -1002,18 +1434,18 @@ var runStoreTck = (options) => {
|
|
|
1002
1434
|
);
|
|
1003
1435
|
const leased = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1004
1436
|
const mine = leased.find((l) => l.stream === s);
|
|
1005
|
-
(0,
|
|
1437
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1006
1438
|
const others = leased.filter((l) => l.stream !== s);
|
|
1007
1439
|
await store.ack(others);
|
|
1008
1440
|
const blocked = await store.block([
|
|
1009
1441
|
{ ...mine, error: "boom" }
|
|
1010
1442
|
]);
|
|
1011
|
-
(0,
|
|
1012
|
-
(0,
|
|
1443
|
+
(0, import_vitest9.expect)(blocked).toHaveLength(1);
|
|
1444
|
+
(0, import_vitest9.expect)(blocked[0].error).toBe("boom");
|
|
1013
1445
|
const again = await store.claim(100, 100, `w2-${uid()}`, 1e5);
|
|
1014
|
-
(0,
|
|
1446
|
+
(0, import_vitest9.expect)(again.find((l) => l.stream === s)).toBeUndefined();
|
|
1015
1447
|
});
|
|
1016
|
-
(0,
|
|
1448
|
+
(0, import_vitest9.it)("rejects block calls from a different holder", async () => {
|
|
1017
1449
|
const s = `block-wrong-${uid()}`;
|
|
1018
1450
|
await store.subscribe([{ stream: s }]);
|
|
1019
1451
|
await store.commit(
|
|
@@ -1023,17 +1455,17 @@ var runStoreTck = (options) => {
|
|
|
1023
1455
|
);
|
|
1024
1456
|
const leased = await store.claim(100, 0, `right-${uid()}`, 1e5);
|
|
1025
1457
|
const mine = leased.find((l) => l.stream === s);
|
|
1026
|
-
(0,
|
|
1458
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1027
1459
|
const others = leased.filter((l) => l.stream !== s);
|
|
1028
1460
|
await store.ack(others);
|
|
1029
1461
|
const blocked = await store.block([
|
|
1030
1462
|
{ ...mine, by: "imposter", error: "no" }
|
|
1031
1463
|
]);
|
|
1032
|
-
(0,
|
|
1464
|
+
(0, import_vitest9.expect)(blocked).toHaveLength(0);
|
|
1033
1465
|
});
|
|
1034
1466
|
});
|
|
1035
|
-
(0,
|
|
1036
|
-
(0,
|
|
1467
|
+
(0, import_vitest9.describe)("reset", () => {
|
|
1468
|
+
(0, import_vitest9.it)("rewinds a stream watermark to -1", async () => {
|
|
1037
1469
|
const s = `reset-${uid()}`;
|
|
1038
1470
|
await store.subscribe([{ stream: s }]);
|
|
1039
1471
|
await store.commit(
|
|
@@ -1043,15 +1475,15 @@ var runStoreTck = (options) => {
|
|
|
1043
1475
|
);
|
|
1044
1476
|
const leased = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1045
1477
|
const mine = leased.find((l) => l.stream === s);
|
|
1046
|
-
(0,
|
|
1478
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1047
1479
|
await store.ack([{ ...mine, at: 99 }]);
|
|
1048
|
-
(0,
|
|
1480
|
+
(0, import_vitest9.expect)(await store.reset([s])).toBe(1);
|
|
1049
1481
|
const after = await store.claim(100, 0, `w2-${uid()}`, 1e5);
|
|
1050
1482
|
const back = after.find((l) => l.stream === s);
|
|
1051
|
-
(0,
|
|
1052
|
-
(0,
|
|
1483
|
+
(0, import_vitest9.expect)(back).toBeDefined();
|
|
1484
|
+
(0, import_vitest9.expect)(back.at).toBe(-1);
|
|
1053
1485
|
});
|
|
1054
|
-
(0,
|
|
1486
|
+
(0, import_vitest9.it)("clears blocked status when resetting", async () => {
|
|
1055
1487
|
const s = `reset-blk-${uid()}`;
|
|
1056
1488
|
await store.subscribe([{ stream: s }]);
|
|
1057
1489
|
await store.commit(
|
|
@@ -1064,17 +1496,17 @@ var runStoreTck = (options) => {
|
|
|
1064
1496
|
const others = leased.filter((l) => l.stream !== s);
|
|
1065
1497
|
await store.ack(others);
|
|
1066
1498
|
await store.block([{ ...mine, error: "boom" }]);
|
|
1067
|
-
(0,
|
|
1499
|
+
(0, import_vitest9.expect)(await store.reset([s])).toBe(1);
|
|
1068
1500
|
const after = await store.claim(100, 0, `w2-${uid()}`, 1e5);
|
|
1069
|
-
(0,
|
|
1501
|
+
(0, import_vitest9.expect)(after.find((l) => l.stream === s)).toBeDefined();
|
|
1070
1502
|
});
|
|
1071
|
-
(0,
|
|
1072
|
-
(0,
|
|
1073
|
-
(0,
|
|
1503
|
+
(0, import_vitest9.it)("returns 0 for unknown streams and empty input", async () => {
|
|
1504
|
+
(0, import_vitest9.expect)(await store.reset([`missing-${uid()}`])).toBe(0);
|
|
1505
|
+
(0, import_vitest9.expect)(await store.reset([])).toBe(0);
|
|
1074
1506
|
});
|
|
1075
1507
|
});
|
|
1076
|
-
(0,
|
|
1077
|
-
(0,
|
|
1508
|
+
(0, import_vitest9.describe)("unblock", () => {
|
|
1509
|
+
(0, import_vitest9.it)("clears blocked flag and preserves the watermark", async () => {
|
|
1078
1510
|
const s = `unblock-${uid()}`;
|
|
1079
1511
|
await store.subscribe([{ stream: s }]);
|
|
1080
1512
|
await store.commit(
|
|
@@ -1092,7 +1524,7 @@ var runStoreTck = (options) => {
|
|
|
1092
1524
|
await store.ack([{ ...m1, at: m1.at }]);
|
|
1093
1525
|
const before_block = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1094
1526
|
const m2 = before_block.find((l) => l.stream === s);
|
|
1095
|
-
(0,
|
|
1527
|
+
(0, import_vitest9.expect)(m2).toBeDefined();
|
|
1096
1528
|
const watermark_before = m2.at;
|
|
1097
1529
|
await store.block([{ ...m2, error: "permanent" }]);
|
|
1098
1530
|
let blocked_flag;
|
|
@@ -1102,15 +1534,15 @@ var runStoreTck = (options) => {
|
|
|
1102
1534
|
},
|
|
1103
1535
|
{ stream: s, stream_exact: true, limit: 1 }
|
|
1104
1536
|
);
|
|
1105
|
-
(0,
|
|
1106
|
-
(0,
|
|
1537
|
+
(0, import_vitest9.expect)(blocked_flag).toBe(true);
|
|
1538
|
+
(0, import_vitest9.expect)(await store.unblock([s])).toBe(1);
|
|
1107
1539
|
const after = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1108
1540
|
const back = after.find((l) => l.stream === s);
|
|
1109
|
-
(0,
|
|
1110
|
-
(0,
|
|
1111
|
-
(0,
|
|
1541
|
+
(0, import_vitest9.expect)(back).toBeDefined();
|
|
1542
|
+
(0, import_vitest9.expect)(back.at).toBe(watermark_before);
|
|
1543
|
+
(0, import_vitest9.expect)(back.retry).toBe(0);
|
|
1112
1544
|
});
|
|
1113
|
-
(0,
|
|
1545
|
+
(0, import_vitest9.it)("returns 0 when the stream is not blocked", async () => {
|
|
1114
1546
|
const s = `unblock-noop-${uid()}`;
|
|
1115
1547
|
await store.subscribe([{ stream: s }]);
|
|
1116
1548
|
await store.commit(
|
|
@@ -1118,13 +1550,13 @@ var runStoreTck = (options) => {
|
|
|
1118
1550
|
[inc(1)],
|
|
1119
1551
|
make_meta({ stream: s })
|
|
1120
1552
|
);
|
|
1121
|
-
(0,
|
|
1553
|
+
(0, import_vitest9.expect)(await store.unblock([s])).toBe(0);
|
|
1122
1554
|
});
|
|
1123
|
-
(0,
|
|
1124
|
-
(0,
|
|
1125
|
-
(0,
|
|
1555
|
+
(0, import_vitest9.it)("returns 0 for unknown streams and empty input", async () => {
|
|
1556
|
+
(0, import_vitest9.expect)(await store.unblock([`missing-${uid()}`])).toBe(0);
|
|
1557
|
+
(0, import_vitest9.expect)(await store.unblock([])).toBe(0);
|
|
1126
1558
|
});
|
|
1127
|
-
(0,
|
|
1559
|
+
(0, import_vitest9.it)("only counts streams that were actually blocked", async () => {
|
|
1128
1560
|
const s1 = `unblock-mix-a-${uid()}`;
|
|
1129
1561
|
const s2 = `unblock-mix-b-${uid()}`;
|
|
1130
1562
|
await store.subscribe([{ stream: s1 }, { stream: s2 }]);
|
|
@@ -1143,9 +1575,9 @@ var runStoreTck = (options) => {
|
|
|
1143
1575
|
const others = leased.filter((l) => l.stream !== s1);
|
|
1144
1576
|
await store.ack(others);
|
|
1145
1577
|
await store.block([{ ...m1, error: "boom" }]);
|
|
1146
|
-
(0,
|
|
1578
|
+
(0, import_vitest9.expect)(await store.unblock([s1, s2])).toBe(1);
|
|
1147
1579
|
});
|
|
1148
|
-
(0,
|
|
1580
|
+
(0, import_vitest9.it)("filter form: unblocks by stream pattern", async () => {
|
|
1149
1581
|
const tag = uid();
|
|
1150
1582
|
const s1 = `unblock-filter-${tag}-a`;
|
|
1151
1583
|
const s2 = `unblock-filter-${tag}-b`;
|
|
@@ -1177,13 +1609,13 @@ var runStoreTck = (options) => {
|
|
|
1177
1609
|
const count = await store.unblock({
|
|
1178
1610
|
stream: `^unblock-filter-${tag}-`
|
|
1179
1611
|
});
|
|
1180
|
-
(0,
|
|
1612
|
+
(0, import_vitest9.expect)(count).toBe(2);
|
|
1181
1613
|
const after = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1182
|
-
(0,
|
|
1183
|
-
(0,
|
|
1184
|
-
(0,
|
|
1614
|
+
(0, import_vitest9.expect)(after.find((l) => l.stream === s3)).toBeUndefined();
|
|
1615
|
+
(0, import_vitest9.expect)(after.find((l) => l.stream === s1)).toBeDefined();
|
|
1616
|
+
(0, import_vitest9.expect)(after.find((l) => l.stream === s2)).toBeDefined();
|
|
1185
1617
|
});
|
|
1186
|
-
(0,
|
|
1618
|
+
(0, import_vitest9.it)("filter form: empty filter unblocks every blocked stream", async () => {
|
|
1187
1619
|
const tag = uid();
|
|
1188
1620
|
const s1 = `unblock-empty-${tag}-a`;
|
|
1189
1621
|
const s2 = `unblock-empty-${tag}-b`;
|
|
@@ -1207,9 +1639,9 @@ var runStoreTck = (options) => {
|
|
|
1207
1639
|
const count = await store.unblock({
|
|
1208
1640
|
stream: `^unblock-empty-${tag}-`
|
|
1209
1641
|
});
|
|
1210
|
-
(0,
|
|
1642
|
+
(0, import_vitest9.expect)(count).toBe(2);
|
|
1211
1643
|
});
|
|
1212
|
-
(0,
|
|
1644
|
+
(0, import_vitest9.it)("filter form: explicit blocked:false matches nothing", async () => {
|
|
1213
1645
|
const tag = uid();
|
|
1214
1646
|
const s = `unblock-blocked-false-${tag}`;
|
|
1215
1647
|
await store.subscribe([{ stream: s }]);
|
|
@@ -1218,7 +1650,7 @@ var runStoreTck = (options) => {
|
|
|
1218
1650
|
[inc(1)],
|
|
1219
1651
|
make_meta({ stream: s })
|
|
1220
1652
|
);
|
|
1221
|
-
(0,
|
|
1653
|
+
(0, import_vitest9.expect)(
|
|
1222
1654
|
await store.unblock({
|
|
1223
1655
|
stream: `^unblock-blocked-false-${tag}`,
|
|
1224
1656
|
blocked: false
|
|
@@ -1226,8 +1658,8 @@ var runStoreTck = (options) => {
|
|
|
1226
1658
|
).toBe(0);
|
|
1227
1659
|
});
|
|
1228
1660
|
});
|
|
1229
|
-
(0,
|
|
1230
|
-
(0,
|
|
1661
|
+
(0, import_vitest9.describe)("reset filter form", () => {
|
|
1662
|
+
(0, import_vitest9.it)("resets streams matching a stream pattern", async () => {
|
|
1231
1663
|
const tag = uid();
|
|
1232
1664
|
const s1 = `reset-filter-${tag}-a`;
|
|
1233
1665
|
const s2 = `reset-filter-${tag}-b`;
|
|
@@ -1258,7 +1690,7 @@ var runStoreTck = (options) => {
|
|
|
1258
1690
|
);
|
|
1259
1691
|
await store.ack(mine.map((l) => ({ ...l, at: l.at + 100 })));
|
|
1260
1692
|
const count = await store.reset({ stream: `^reset-filter-${tag}-` });
|
|
1261
|
-
(0,
|
|
1693
|
+
(0, import_vitest9.expect)(count).toBe(2);
|
|
1262
1694
|
const position_for = async (name) => {
|
|
1263
1695
|
let at = null;
|
|
1264
1696
|
await store.query_streams(
|
|
@@ -1269,11 +1701,11 @@ var runStoreTck = (options) => {
|
|
|
1269
1701
|
);
|
|
1270
1702
|
return at;
|
|
1271
1703
|
};
|
|
1272
|
-
(0,
|
|
1273
|
-
(0,
|
|
1274
|
-
(0,
|
|
1704
|
+
(0, import_vitest9.expect)(await position_for(s1)).toBe(-1);
|
|
1705
|
+
(0, import_vitest9.expect)(await position_for(s2)).toBe(-1);
|
|
1706
|
+
(0, import_vitest9.expect)(await position_for(other)).toBeGreaterThan(-1);
|
|
1275
1707
|
});
|
|
1276
|
-
(0,
|
|
1708
|
+
(0, import_vitest9.it)("filter form: resets only blocked streams when blocked:true", async () => {
|
|
1277
1709
|
const tag = uid();
|
|
1278
1710
|
const s1 = `reset-blocked-${tag}-blocked`;
|
|
1279
1711
|
const s2 = `reset-blocked-${tag}-fine`;
|
|
@@ -1296,11 +1728,11 @@ var runStoreTck = (options) => {
|
|
|
1296
1728
|
stream: `^reset-blocked-${tag}-`,
|
|
1297
1729
|
blocked: true
|
|
1298
1730
|
});
|
|
1299
|
-
(0,
|
|
1731
|
+
(0, import_vitest9.expect)(count).toBe(1);
|
|
1300
1732
|
});
|
|
1301
1733
|
});
|
|
1302
|
-
(0,
|
|
1303
|
-
(0,
|
|
1734
|
+
(0, import_vitest9.describe)("prioritize", () => {
|
|
1735
|
+
(0, import_vitest9.it)("sets priority directly, overriding subscribe's max() rule", async () => {
|
|
1304
1736
|
const tag = uid();
|
|
1305
1737
|
const s1 = `pri-${tag}-a`;
|
|
1306
1738
|
const s2 = `pri-${tag}-b`;
|
|
@@ -1312,7 +1744,7 @@ var runStoreTck = (options) => {
|
|
|
1312
1744
|
{ stream: s1, stream_exact: true },
|
|
1313
1745
|
3
|
|
1314
1746
|
);
|
|
1315
|
-
(0,
|
|
1747
|
+
(0, import_vitest9.expect)(updated).toBe(1);
|
|
1316
1748
|
const got1 = {};
|
|
1317
1749
|
const got2 = {};
|
|
1318
1750
|
await store.query_streams(
|
|
@@ -1322,12 +1754,12 @@ var runStoreTck = (options) => {
|
|
|
1322
1754
|
},
|
|
1323
1755
|
{ stream: `pri-${tag}-.*`, limit: 100 }
|
|
1324
1756
|
);
|
|
1325
|
-
(0,
|
|
1326
|
-
(0,
|
|
1757
|
+
(0, import_vitest9.expect)(got1.priority).toBe(3);
|
|
1758
|
+
(0, import_vitest9.expect)(got2.priority).toBe(5);
|
|
1327
1759
|
});
|
|
1328
1760
|
});
|
|
1329
|
-
(0,
|
|
1330
|
-
(0,
|
|
1761
|
+
(0, import_vitest9.describe)("lanes", () => {
|
|
1762
|
+
(0, import_vitest9.it)("subscribe defaults lane to 'default' when omitted", async () => {
|
|
1331
1763
|
const s = `lane-default-${uid()}`;
|
|
1332
1764
|
await store.subscribe([{ stream: s }]);
|
|
1333
1765
|
const seen = [];
|
|
@@ -1335,9 +1767,9 @@ var runStoreTck = (options) => {
|
|
|
1335
1767
|
stream: s,
|
|
1336
1768
|
stream_exact: true
|
|
1337
1769
|
});
|
|
1338
|
-
(0,
|
|
1770
|
+
(0, import_vitest9.expect)(seen).toEqual(["default"]);
|
|
1339
1771
|
});
|
|
1340
|
-
(0,
|
|
1772
|
+
(0, import_vitest9.it)("subscribe records the lane passed in", async () => {
|
|
1341
1773
|
const s = `lane-set-${uid()}`;
|
|
1342
1774
|
await store.subscribe([{ stream: s, lane: "slow" }]);
|
|
1343
1775
|
const seen = [];
|
|
@@ -1345,9 +1777,9 @@ var runStoreTck = (options) => {
|
|
|
1345
1777
|
stream: s,
|
|
1346
1778
|
stream_exact: true
|
|
1347
1779
|
});
|
|
1348
|
-
(0,
|
|
1780
|
+
(0, import_vitest9.expect)(seen).toEqual(["slow"]);
|
|
1349
1781
|
});
|
|
1350
|
-
(0,
|
|
1782
|
+
(0, import_vitest9.it)("subscribe re-lanes existing streams on subsequent calls", async () => {
|
|
1351
1783
|
const s = `lane-upsert-${uid()}`;
|
|
1352
1784
|
await store.subscribe([{ stream: s, lane: "slow" }]);
|
|
1353
1785
|
await store.subscribe([{ stream: s, lane: "fast" }]);
|
|
@@ -1356,9 +1788,9 @@ var runStoreTck = (options) => {
|
|
|
1356
1788
|
stream: s,
|
|
1357
1789
|
stream_exact: true
|
|
1358
1790
|
});
|
|
1359
|
-
(0,
|
|
1791
|
+
(0, import_vitest9.expect)(seen).toEqual(["fast"]);
|
|
1360
1792
|
});
|
|
1361
|
-
(0,
|
|
1793
|
+
(0, import_vitest9.it)("claim() filters by lane when supplied and returns lane on the Lease", async () => {
|
|
1362
1794
|
const tag = uid();
|
|
1363
1795
|
const src1 = `lane-claim-src1-${tag}`;
|
|
1364
1796
|
const src2 = `lane-claim-src2-${tag}`;
|
|
@@ -1382,19 +1814,19 @@ var runStoreTck = (options) => {
|
|
|
1382
1814
|
const slow_mine = slow.filter(
|
|
1383
1815
|
(l) => l.stream === sub_default || l.stream === sub_slow
|
|
1384
1816
|
);
|
|
1385
|
-
(0,
|
|
1386
|
-
(0,
|
|
1817
|
+
(0, import_vitest9.expect)(slow_mine.map((l) => l.stream)).toEqual([sub_slow]);
|
|
1818
|
+
(0, import_vitest9.expect)(slow_mine[0]?.lane).toBe("slow");
|
|
1387
1819
|
await store.ack(slow_mine.map((l) => ({ ...l, at: l.at + 1 })));
|
|
1388
1820
|
const all = await store.claim(50, 0, `w-all-${tag}`, 1e3);
|
|
1389
1821
|
const all_mine = all.filter((l) => l.stream === sub_default || l.stream === sub_slow).map((l) => ({ stream: l.stream, lane: l.lane }));
|
|
1390
|
-
(0,
|
|
1391
|
-
|
|
1822
|
+
(0, import_vitest9.expect)(all_mine).toEqual(
|
|
1823
|
+
import_vitest9.expect.arrayContaining([
|
|
1392
1824
|
{ stream: sub_default, lane: "default" },
|
|
1393
1825
|
{ stream: sub_slow, lane: "slow" }
|
|
1394
1826
|
])
|
|
1395
1827
|
);
|
|
1396
1828
|
});
|
|
1397
|
-
(0,
|
|
1829
|
+
(0, import_vitest9.it)("query_streams filters by lane", async () => {
|
|
1398
1830
|
const tag = uid();
|
|
1399
1831
|
const a = `lane-q-a-${tag}`;
|
|
1400
1832
|
const b = `lane-q-b-${tag}`;
|
|
@@ -1410,9 +1842,9 @@ var runStoreTck = (options) => {
|
|
|
1410
1842
|
stream: `lane-q-.*-${tag}`,
|
|
1411
1843
|
limit: 100
|
|
1412
1844
|
});
|
|
1413
|
-
(0,
|
|
1845
|
+
(0, import_vitest9.expect)(seen.sort()).toEqual([a, c]);
|
|
1414
1846
|
});
|
|
1415
|
-
(0,
|
|
1847
|
+
(0, import_vitest9.it)("prioritize filters by lane", async () => {
|
|
1416
1848
|
const tag = uid();
|
|
1417
1849
|
const a = `lane-pri-a-${tag}`;
|
|
1418
1850
|
const b = `lane-pri-b-${tag}`;
|
|
@@ -1421,16 +1853,16 @@ var runStoreTck = (options) => {
|
|
|
1421
1853
|
{ stream: b, lane: `pfast-${tag}` }
|
|
1422
1854
|
]);
|
|
1423
1855
|
const updated = await store.prioritize({ lane: `pslow-${tag}` }, 7);
|
|
1424
|
-
(0,
|
|
1856
|
+
(0, import_vitest9.expect)(updated).toBe(1);
|
|
1425
1857
|
const seen = /* @__PURE__ */ new Map();
|
|
1426
1858
|
await store.query_streams((p) => seen.set(p.stream, p.priority), {
|
|
1427
1859
|
stream: `lane-pri-.*-${tag}`,
|
|
1428
1860
|
limit: 100
|
|
1429
1861
|
});
|
|
1430
|
-
(0,
|
|
1431
|
-
(0,
|
|
1862
|
+
(0, import_vitest9.expect)(seen.get(a)).toBe(7);
|
|
1863
|
+
(0, import_vitest9.expect)(seen.get(b)).toBe(0);
|
|
1432
1864
|
});
|
|
1433
|
-
(0,
|
|
1865
|
+
(0, import_vitest9.it)("reset filters by lane", async () => {
|
|
1434
1866
|
const tag = uid();
|
|
1435
1867
|
const src = `lane-reset-src-${tag}`;
|
|
1436
1868
|
const a = `lane-reset-a-${tag}`;
|
|
@@ -1448,7 +1880,7 @@ var runStoreTck = (options) => {
|
|
|
1448
1880
|
const mine = leases.filter((l) => l.stream === a || l.stream === b);
|
|
1449
1881
|
await store.ack(mine.map((l) => ({ ...l, at: l.at + 1 })));
|
|
1450
1882
|
const count = await store.reset({ lane: `rslow-${tag}` });
|
|
1451
|
-
(0,
|
|
1883
|
+
(0, import_vitest9.expect)(count).toBe(1);
|
|
1452
1884
|
const ats = /* @__PURE__ */ new Map();
|
|
1453
1885
|
for (const name of [a, b]) {
|
|
1454
1886
|
await store.query_streams((p) => ats.set(p.stream, p.at), {
|
|
@@ -1456,10 +1888,10 @@ var runStoreTck = (options) => {
|
|
|
1456
1888
|
stream_exact: true
|
|
1457
1889
|
});
|
|
1458
1890
|
}
|
|
1459
|
-
(0,
|
|
1460
|
-
(0,
|
|
1891
|
+
(0, import_vitest9.expect)(ats.get(a)).toBe(-1);
|
|
1892
|
+
(0, import_vitest9.expect)(ats.get(b)).toBeGreaterThanOrEqual(0);
|
|
1461
1893
|
});
|
|
1462
|
-
(0,
|
|
1894
|
+
(0, import_vitest9.it)("unblock filters by lane", async () => {
|
|
1463
1895
|
const tag = uid();
|
|
1464
1896
|
const src = `lane-ub-src-${tag}`;
|
|
1465
1897
|
const a = `lane-ub-a-${tag}`;
|
|
@@ -1477,7 +1909,7 @@ var runStoreTck = (options) => {
|
|
|
1477
1909
|
const mine = leases.filter((l) => l.stream === a || l.stream === b);
|
|
1478
1910
|
await store.block(mine.map((l) => ({ ...l, error: "boom" })));
|
|
1479
1911
|
const count = await store.unblock({ lane: `uslow-${tag}` });
|
|
1480
|
-
(0,
|
|
1912
|
+
(0, import_vitest9.expect)(count).toBe(1);
|
|
1481
1913
|
const blocked = /* @__PURE__ */ new Map();
|
|
1482
1914
|
for (const name of [a, b]) {
|
|
1483
1915
|
await store.query_streams((p) => blocked.set(p.stream, p.blocked), {
|
|
@@ -1485,12 +1917,12 @@ var runStoreTck = (options) => {
|
|
|
1485
1917
|
stream_exact: true
|
|
1486
1918
|
});
|
|
1487
1919
|
}
|
|
1488
|
-
(0,
|
|
1489
|
-
(0,
|
|
1920
|
+
(0, import_vitest9.expect)(blocked.get(a)).toBe(false);
|
|
1921
|
+
(0, import_vitest9.expect)(blocked.get(b)).toBe(true);
|
|
1490
1922
|
});
|
|
1491
1923
|
});
|
|
1492
|
-
(0,
|
|
1493
|
-
(0,
|
|
1924
|
+
(0, import_vitest9.describe)("truncate", () => {
|
|
1925
|
+
(0, import_vitest9.it)("seeds a tombstone when no snapshot is provided", async () => {
|
|
1494
1926
|
const s = `trunc-tomb-${uid()}`;
|
|
1495
1927
|
await store.commit(
|
|
1496
1928
|
s,
|
|
@@ -1498,7 +1930,7 @@ var runStoreTck = (options) => {
|
|
|
1498
1930
|
make_meta({ stream: s })
|
|
1499
1931
|
);
|
|
1500
1932
|
const result = await store.truncate([{ stream: s }]);
|
|
1501
|
-
(0,
|
|
1933
|
+
(0, import_vitest9.expect)(result.get(s)?.deleted).toBe(2);
|
|
1502
1934
|
const remaining = [];
|
|
1503
1935
|
await store.query(
|
|
1504
1936
|
(e) => {
|
|
@@ -1506,12 +1938,12 @@ var runStoreTck = (options) => {
|
|
|
1506
1938
|
},
|
|
1507
1939
|
{ stream: s, stream_exact: true }
|
|
1508
1940
|
);
|
|
1509
|
-
(0,
|
|
1510
|
-
(0,
|
|
1941
|
+
(0, import_vitest9.expect)(remaining).toHaveLength(1);
|
|
1942
|
+
(0, import_vitest9.expect)(remaining[0].name).toBe(
|
|
1511
1943
|
"__tombstone__"
|
|
1512
1944
|
);
|
|
1513
1945
|
});
|
|
1514
|
-
(0,
|
|
1946
|
+
(0, import_vitest9.it)("seeds a snapshot when one is provided", async () => {
|
|
1515
1947
|
const s = `trunc-snap-${uid()}`;
|
|
1516
1948
|
await store.commit(
|
|
1517
1949
|
s,
|
|
@@ -1521,7 +1953,7 @@ var runStoreTck = (options) => {
|
|
|
1521
1953
|
const result = await store.truncate([
|
|
1522
1954
|
{ stream: s, snapshot: { count: 7 } }
|
|
1523
1955
|
]);
|
|
1524
|
-
(0,
|
|
1956
|
+
(0, import_vitest9.expect)(result.get(s)?.deleted).toBe(1);
|
|
1525
1957
|
const remaining = [];
|
|
1526
1958
|
await store.query(
|
|
1527
1959
|
(e) => {
|
|
@@ -1529,24 +1961,24 @@ var runStoreTck = (options) => {
|
|
|
1529
1961
|
},
|
|
1530
1962
|
{ stream: s, stream_exact: true, with_snaps: true }
|
|
1531
1963
|
);
|
|
1532
|
-
(0,
|
|
1533
|
-
(0,
|
|
1964
|
+
(0, import_vitest9.expect)(remaining).toHaveLength(1);
|
|
1965
|
+
(0, import_vitest9.expect)(remaining[0].name).toBe(
|
|
1534
1966
|
"__snapshot__"
|
|
1535
1967
|
);
|
|
1536
|
-
(0,
|
|
1968
|
+
(0, import_vitest9.expect)(remaining[0].data).toEqual({ count: 7 });
|
|
1537
1969
|
});
|
|
1538
|
-
(0,
|
|
1970
|
+
(0, import_vitest9.it)("returns an empty map for empty input", async () => {
|
|
1539
1971
|
const result = await store.truncate([]);
|
|
1540
|
-
(0,
|
|
1972
|
+
(0, import_vitest9.expect)(result.size).toBe(0);
|
|
1541
1973
|
});
|
|
1542
|
-
(0,
|
|
1974
|
+
(0, import_vitest9.it)("returns 0 deleted for streams that don't exist", async () => {
|
|
1543
1975
|
const s = `trunc-missing-${uid()}`;
|
|
1544
1976
|
const result = await store.truncate([{ stream: s }]);
|
|
1545
|
-
(0,
|
|
1977
|
+
(0, import_vitest9.expect)(result.get(s)?.deleted).toBe(0);
|
|
1546
1978
|
});
|
|
1547
1979
|
});
|
|
1548
|
-
(0,
|
|
1549
|
-
(0,
|
|
1980
|
+
(0, import_vitest9.describe)("query_streams", () => {
|
|
1981
|
+
(0, import_vitest9.it)("returns positions filtered by stream regex, exact, source, and source_exact", async () => {
|
|
1550
1982
|
const tag = uid();
|
|
1551
1983
|
const proj1 = `qs-${tag}-projection-tickets`;
|
|
1552
1984
|
const proj2 = `qs-${tag}-projection-users`;
|
|
@@ -1565,37 +1997,37 @@ var runStoreTck = (options) => {
|
|
|
1565
1997
|
(p) => all.push({ stream: p.stream, source: p.source }),
|
|
1566
1998
|
{ stream: `qs-${tag}-.*` }
|
|
1567
1999
|
);
|
|
1568
|
-
(0,
|
|
1569
|
-
(0,
|
|
1570
|
-
(0,
|
|
2000
|
+
(0, import_vitest9.expect)(all_result.count).toBe(4);
|
|
2001
|
+
(0, import_vitest9.expect)(all_result.maxEventId).toBeGreaterThanOrEqual(-1);
|
|
2002
|
+
(0, import_vitest9.expect)(all.map((p) => p.stream).sort()).toEqual(
|
|
1571
2003
|
[proj1, proj2, dyn1, dyn2].sort()
|
|
1572
2004
|
);
|
|
1573
2005
|
const projections = [];
|
|
1574
2006
|
await store.query_streams((p) => projections.push(p.stream), {
|
|
1575
2007
|
stream: `qs-${tag}-projection-.*`
|
|
1576
2008
|
});
|
|
1577
|
-
(0,
|
|
2009
|
+
(0, import_vitest9.expect)(projections.sort()).toEqual([proj1, proj2].sort());
|
|
1578
2010
|
const exact = [];
|
|
1579
2011
|
await store.query_streams((p) => exact.push(p.stream), {
|
|
1580
2012
|
stream: dyn1,
|
|
1581
2013
|
stream_exact: true
|
|
1582
2014
|
});
|
|
1583
|
-
(0,
|
|
2015
|
+
(0, import_vitest9.expect)(exact).toEqual([dyn1]);
|
|
1584
2016
|
const by_source = [];
|
|
1585
2017
|
await store.query_streams((p) => by_source.push(p.stream), {
|
|
1586
2018
|
stream: `qs-${tag}-.*`,
|
|
1587
2019
|
source: `qs-${tag}-src-.*`
|
|
1588
2020
|
});
|
|
1589
|
-
(0,
|
|
2021
|
+
(0, import_vitest9.expect)(by_source.sort()).toEqual([dyn1, dyn2].sort());
|
|
1590
2022
|
const exact_source = [];
|
|
1591
2023
|
await store.query_streams((p) => exact_source.push(p.stream), {
|
|
1592
2024
|
stream: `qs-${tag}-.*`,
|
|
1593
2025
|
source: src2,
|
|
1594
2026
|
source_exact: true
|
|
1595
2027
|
});
|
|
1596
|
-
(0,
|
|
2028
|
+
(0, import_vitest9.expect)(exact_source).toEqual([dyn2]);
|
|
1597
2029
|
});
|
|
1598
|
-
(0,
|
|
2030
|
+
(0, import_vitest9.it)("paginates with limit + after (keyset)", async () => {
|
|
1599
2031
|
const tag = uid();
|
|
1600
2032
|
const streams = [
|
|
1601
2033
|
`qp-${tag}-a`,
|
|
@@ -1609,17 +2041,17 @@ var runStoreTck = (options) => {
|
|
|
1609
2041
|
stream: `qp-${tag}-.*`,
|
|
1610
2042
|
limit: 2
|
|
1611
2043
|
});
|
|
1612
|
-
(0,
|
|
2044
|
+
(0, import_vitest9.expect)(page1).toHaveLength(2);
|
|
1613
2045
|
const page2 = [];
|
|
1614
2046
|
await store.query_streams((p) => page2.push(p.stream), {
|
|
1615
2047
|
stream: `qp-${tag}-.*`,
|
|
1616
2048
|
limit: 2,
|
|
1617
2049
|
after: page1.at(-1)
|
|
1618
2050
|
});
|
|
1619
|
-
(0,
|
|
1620
|
-
(0,
|
|
2051
|
+
(0, import_vitest9.expect)(page2).toHaveLength(2);
|
|
2052
|
+
(0, import_vitest9.expect)([...page1, ...page2].sort()).toEqual([...streams].sort());
|
|
1621
2053
|
});
|
|
1622
|
-
(0,
|
|
2054
|
+
(0, import_vitest9.it)("filters by blocked status", async () => {
|
|
1623
2055
|
const tag = uid();
|
|
1624
2056
|
const s = `qb-${tag}`;
|
|
1625
2057
|
const sibling = `qb-${tag}-other`;
|
|
@@ -1639,18 +2071,18 @@ var runStoreTck = (options) => {
|
|
|
1639
2071
|
(p) => blocked.push({ stream: p.stream, error: p.error }),
|
|
1640
2072
|
{ stream: `qb-${tag}.*`, blocked: true }
|
|
1641
2073
|
);
|
|
1642
|
-
(0,
|
|
1643
|
-
(0,
|
|
2074
|
+
(0, import_vitest9.expect)(blocked).toHaveLength(1);
|
|
2075
|
+
(0, import_vitest9.expect)(blocked[0].error).toBe("boom");
|
|
1644
2076
|
const unblocked = [];
|
|
1645
2077
|
await store.query_streams((p) => unblocked.push(p.stream), {
|
|
1646
2078
|
stream: `qb-${tag}.*`,
|
|
1647
2079
|
blocked: false
|
|
1648
2080
|
});
|
|
1649
|
-
(0,
|
|
2081
|
+
(0, import_vitest9.expect)(unblocked).toEqual([sibling]);
|
|
1650
2082
|
});
|
|
1651
2083
|
});
|
|
1652
|
-
(0,
|
|
1653
|
-
(0,
|
|
2084
|
+
(0, import_vitest9.describe)("query_stats", () => {
|
|
2085
|
+
(0, import_vitest9.it)("array input \u2014 returns head per stream, absent when not in input", async () => {
|
|
1654
2086
|
const tag = uid();
|
|
1655
2087
|
const sA = `qst-${tag}-a`;
|
|
1656
2088
|
const sB = `qst-${tag}-b`;
|
|
@@ -1671,18 +2103,18 @@ var runStoreTck = (options) => {
|
|
|
1671
2103
|
make_meta({ stream: sUnasked })
|
|
1672
2104
|
);
|
|
1673
2105
|
const stats = await store.query_stats([sA, sB]);
|
|
1674
|
-
(0,
|
|
1675
|
-
(0,
|
|
1676
|
-
(0,
|
|
1677
|
-
(0,
|
|
1678
|
-
(0,
|
|
1679
|
-
(0,
|
|
2106
|
+
(0, import_vitest9.expect)(stats.size).toBe(2);
|
|
2107
|
+
(0, import_vitest9.expect)(stats.get(sA)?.head.name).toBe("Incremented");
|
|
2108
|
+
(0, import_vitest9.expect)((stats.get(sA)?.head.data).amount).toBe(2);
|
|
2109
|
+
(0, import_vitest9.expect)(stats.get(sB)?.head.name).toBe("Decremented");
|
|
2110
|
+
(0, import_vitest9.expect)((stats.get(sB)?.head.data).amount).toBe(5);
|
|
2111
|
+
(0, import_vitest9.expect)(stats.has(sUnasked)).toBe(false);
|
|
1680
2112
|
const empty = await store.query_stats([]);
|
|
1681
|
-
(0,
|
|
2113
|
+
(0, import_vitest9.expect)(empty.size).toBe(0);
|
|
1682
2114
|
const unknown = await store.query_stats([`qst-${tag}-missing`]);
|
|
1683
|
-
(0,
|
|
2115
|
+
(0, import_vitest9.expect)(unknown.size).toBe(0);
|
|
1684
2116
|
});
|
|
1685
|
-
(0,
|
|
2117
|
+
(0, import_vitest9.it)("tail returns the earliest event per stream", async () => {
|
|
1686
2118
|
const tag = uid();
|
|
1687
2119
|
const s = `qst-tail-${tag}`;
|
|
1688
2120
|
await store.commit(
|
|
@@ -1704,12 +2136,12 @@ var runStoreTck = (options) => {
|
|
|
1704
2136
|
tail: true
|
|
1705
2137
|
});
|
|
1706
2138
|
const r = stats.get(s);
|
|
1707
|
-
(0,
|
|
1708
|
-
(0,
|
|
1709
|
-
(0,
|
|
1710
|
-
(0,
|
|
2139
|
+
(0, import_vitest9.expect)(r?.head.name).toBe("Incremented");
|
|
2140
|
+
(0, import_vitest9.expect)((r?.head.data).amount).toBe(3);
|
|
2141
|
+
(0, import_vitest9.expect)(r?.tail?.name).toBe("Incremented");
|
|
2142
|
+
(0, import_vitest9.expect)((r?.tail?.data).amount).toBe(1);
|
|
1711
2143
|
});
|
|
1712
|
-
(0,
|
|
2144
|
+
(0, import_vitest9.it)("count + names \u2014 full aggregates including framework markers", async () => {
|
|
1713
2145
|
const tag = uid();
|
|
1714
2146
|
const s = `qst-cn-${tag}`;
|
|
1715
2147
|
await store.commit(
|
|
@@ -1728,13 +2160,13 @@ var runStoreTck = (options) => {
|
|
|
1728
2160
|
names: true
|
|
1729
2161
|
});
|
|
1730
2162
|
const r = stats.get(s);
|
|
1731
|
-
(0,
|
|
1732
|
-
(0,
|
|
1733
|
-
(0,
|
|
1734
|
-
(0,
|
|
1735
|
-
(0,
|
|
2163
|
+
(0, import_vitest9.expect)(r?.count).toBe(4);
|
|
2164
|
+
(0, import_vitest9.expect)(r?.names?.[import_act2.SNAP_EVENT]).toBe(1);
|
|
2165
|
+
(0, import_vitest9.expect)(r?.names?.Incremented).toBe(2);
|
|
2166
|
+
(0, import_vitest9.expect)(r?.names?.Decremented).toBe(1);
|
|
2167
|
+
(0, import_vitest9.expect)(r?.names?.[import_act2.SNAP_EVENT]).toBe(1);
|
|
1736
2168
|
});
|
|
1737
|
-
(0,
|
|
2169
|
+
(0, import_vitest9.it)("exclude shifts head past filtered events; stream absent when all filtered", async () => {
|
|
1738
2170
|
const tag = uid();
|
|
1739
2171
|
const s = `qst-excl-${tag}`;
|
|
1740
2172
|
const sAllOut = `qst-allout-${tag}`;
|
|
@@ -1749,23 +2181,23 @@ var runStoreTck = (options) => {
|
|
|
1749
2181
|
make_meta({ stream: sAllOut })
|
|
1750
2182
|
);
|
|
1751
2183
|
const all = await store.query_stats([s]);
|
|
1752
|
-
(0,
|
|
1753
|
-
(0,
|
|
2184
|
+
(0, import_vitest9.expect)(all.get(s)?.head.name).toBe("Incremented");
|
|
2185
|
+
(0, import_vitest9.expect)((all.get(s)?.head.data).amount).toBe(3);
|
|
1754
2186
|
const excl = await store.query_stats([s], {
|
|
1755
2187
|
exclude: ["Incremented"]
|
|
1756
2188
|
});
|
|
1757
|
-
(0,
|
|
1758
|
-
(0,
|
|
2189
|
+
(0, import_vitest9.expect)(excl.get(s)?.head.name).toBe("Decremented");
|
|
2190
|
+
(0, import_vitest9.expect)((excl.get(s)?.head.data).amount).toBe(2);
|
|
1759
2191
|
const wipe = await store.query_stats([sAllOut], {
|
|
1760
2192
|
exclude: ["Incremented", "Decremented", "Reset"]
|
|
1761
2193
|
});
|
|
1762
|
-
(0,
|
|
2194
|
+
(0, import_vitest9.expect)(wipe.has(sAllOut)).toBe(false);
|
|
1763
2195
|
const no_tomb = await store.query_stats([s], {
|
|
1764
|
-
exclude: [
|
|
2196
|
+
exclude: [import_act2.TOMBSTONE_EVENT]
|
|
1765
2197
|
});
|
|
1766
|
-
(0,
|
|
2198
|
+
(0, import_vitest9.expect)(no_tomb.get(s)?.head.name).toBe("Incremented");
|
|
1767
2199
|
});
|
|
1768
|
-
(0,
|
|
2200
|
+
(0, import_vitest9.it)("before \u2014 time travel narrows head/tail/count", async () => {
|
|
1769
2201
|
const tag = uid();
|
|
1770
2202
|
const s = `qst-tt-${tag}`;
|
|
1771
2203
|
const c1 = await store.commit(
|
|
@@ -1790,15 +2222,15 @@ var runStoreTck = (options) => {
|
|
|
1790
2222
|
before
|
|
1791
2223
|
});
|
|
1792
2224
|
const r = stats.get(s);
|
|
1793
|
-
(0,
|
|
1794
|
-
(0,
|
|
1795
|
-
(0,
|
|
2225
|
+
(0, import_vitest9.expect)(r?.count).toBe(1);
|
|
2226
|
+
(0, import_vitest9.expect)(r?.head.id).toBe(c1[0].id);
|
|
2227
|
+
(0, import_vitest9.expect)(r?.tail?.id).toBe(c1[0].id);
|
|
1796
2228
|
const empty = await store.query_stats([s], {
|
|
1797
2229
|
before: 0
|
|
1798
2230
|
});
|
|
1799
|
-
(0,
|
|
2231
|
+
(0, import_vitest9.expect)(empty.has(s)).toBe(false);
|
|
1800
2232
|
});
|
|
1801
|
-
(0,
|
|
2233
|
+
(0, import_vitest9.it)("filter form \u2014 stream regex, stream_exact, empty {} match", async () => {
|
|
1802
2234
|
const tag = uid();
|
|
1803
2235
|
const sA = `qsf-${tag}-orders-1`;
|
|
1804
2236
|
const sB = `qsf-${tag}-orders-2`;
|
|
@@ -1821,18 +2253,18 @@ var runStoreTck = (options) => {
|
|
|
1821
2253
|
const orders = await store.query_stats({
|
|
1822
2254
|
stream: `^qsf-${tag}-orders-`
|
|
1823
2255
|
});
|
|
1824
|
-
(0,
|
|
2256
|
+
(0, import_vitest9.expect)([...orders.keys()].sort()).toEqual([sA, sB].sort());
|
|
1825
2257
|
const exact = await store.query_stats({
|
|
1826
2258
|
stream: sA,
|
|
1827
2259
|
stream_exact: true
|
|
1828
2260
|
});
|
|
1829
|
-
(0,
|
|
2261
|
+
(0, import_vitest9.expect)([...exact.keys()]).toEqual([sA]);
|
|
1830
2262
|
const all = await store.query_stats({
|
|
1831
2263
|
stream: `^qsf-${tag}-`
|
|
1832
2264
|
});
|
|
1833
|
-
(0,
|
|
2265
|
+
(0, import_vitest9.expect)([...all.keys()].sort()).toEqual([sA, sB, sOther].sort());
|
|
1834
2266
|
});
|
|
1835
|
-
(0,
|
|
2267
|
+
(0, import_vitest9.it)("compose with query_streams for subscription-level filters", async () => {
|
|
1836
2268
|
const tag = uid();
|
|
1837
2269
|
const a = `qsc-${tag}-a`;
|
|
1838
2270
|
const b = `qsc-${tag}-b`;
|
|
@@ -1849,7 +2281,7 @@ var runStoreTck = (options) => {
|
|
|
1849
2281
|
);
|
|
1850
2282
|
const leased = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1851
2283
|
const mine = leased.find((l) => l.stream === a);
|
|
1852
|
-
(0,
|
|
2284
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1853
2285
|
const others = leased.filter((l) => l.stream !== a);
|
|
1854
2286
|
await store.ack(others);
|
|
1855
2287
|
await store.block([{ ...mine, error: "boom" }]);
|
|
@@ -1858,12 +2290,12 @@ var runStoreTck = (options) => {
|
|
|
1858
2290
|
stream: `^qsc-${tag}-`,
|
|
1859
2291
|
blocked: true
|
|
1860
2292
|
});
|
|
1861
|
-
(0,
|
|
2293
|
+
(0, import_vitest9.expect)(blocked_names).toEqual([a]);
|
|
1862
2294
|
const stats = await store.query_stats(blocked_names);
|
|
1863
|
-
(0,
|
|
1864
|
-
(0,
|
|
2295
|
+
(0, import_vitest9.expect)(stats.get(a)?.head.name).toBe("Incremented");
|
|
2296
|
+
(0, import_vitest9.expect)(stats.has(b)).toBe(false);
|
|
1865
2297
|
});
|
|
1866
|
-
(0,
|
|
2298
|
+
(0, import_vitest9.it)("empty filter {} \u2014 matches every event-bearing stream", async () => {
|
|
1867
2299
|
const tag = uid();
|
|
1868
2300
|
const a = `qse-${tag}-a`;
|
|
1869
2301
|
const b = `qse-${tag}-b`;
|
|
@@ -1878,10 +2310,10 @@ var runStoreTck = (options) => {
|
|
|
1878
2310
|
make_meta({ stream: b })
|
|
1879
2311
|
);
|
|
1880
2312
|
const all = await store.query_stats({});
|
|
1881
|
-
(0,
|
|
1882
|
-
(0,
|
|
2313
|
+
(0, import_vitest9.expect)(all.has(a)).toBe(true);
|
|
2314
|
+
(0, import_vitest9.expect)(all.has(b)).toBe(true);
|
|
1883
2315
|
});
|
|
1884
|
-
(0,
|
|
2316
|
+
(0, import_vitest9.it)("stat-flag combinations \u2014 count-only, names-only, tail-only", async () => {
|
|
1885
2317
|
const tag = uid();
|
|
1886
2318
|
const s = `qsfl-${tag}`;
|
|
1887
2319
|
await store.commit(
|
|
@@ -1892,22 +2324,22 @@ var runStoreTck = (options) => {
|
|
|
1892
2324
|
const c = await store.query_stats([s], {
|
|
1893
2325
|
count: true
|
|
1894
2326
|
});
|
|
1895
|
-
(0,
|
|
1896
|
-
(0,
|
|
1897
|
-
(0,
|
|
2327
|
+
(0, import_vitest9.expect)(c.get(s)?.count).toBe(3);
|
|
2328
|
+
(0, import_vitest9.expect)(c.get(s)?.names).toBeUndefined();
|
|
2329
|
+
(0, import_vitest9.expect)(c.get(s)?.tail).toBeUndefined();
|
|
1898
2330
|
const n = await store.query_stats([s], {
|
|
1899
2331
|
names: true
|
|
1900
2332
|
});
|
|
1901
|
-
(0,
|
|
1902
|
-
(0,
|
|
1903
|
-
(0,
|
|
2333
|
+
(0, import_vitest9.expect)(n.get(s)?.names).toEqual({ Incremented: 2, Decremented: 1 });
|
|
2334
|
+
(0, import_vitest9.expect)(n.get(s)?.count).toBeUndefined();
|
|
2335
|
+
(0, import_vitest9.expect)(n.get(s)?.tail).toBeUndefined();
|
|
1904
2336
|
const t = await store.query_stats([s], { tail: true });
|
|
1905
|
-
(0,
|
|
1906
|
-
(0,
|
|
1907
|
-
(0,
|
|
1908
|
-
(0,
|
|
2337
|
+
(0, import_vitest9.expect)(t.get(s)?.tail?.name).toBe("Incremented");
|
|
2338
|
+
(0, import_vitest9.expect)((t.get(s)?.tail?.data).amount).toBe(1);
|
|
2339
|
+
(0, import_vitest9.expect)(t.get(s)?.count).toBeUndefined();
|
|
2340
|
+
(0, import_vitest9.expect)(t.get(s)?.names).toBeUndefined();
|
|
1909
2341
|
});
|
|
1910
|
-
(0,
|
|
2342
|
+
(0, import_vitest9.it)("paginates with limit + after (keyset), ordered by stream name", async () => {
|
|
1911
2343
|
const tag = uid();
|
|
1912
2344
|
const streams = [
|
|
1913
2345
|
`qsp-${tag}-a`,
|
|
@@ -1927,28 +2359,28 @@ var runStoreTck = (options) => {
|
|
|
1927
2359
|
{ limit: 2 }
|
|
1928
2360
|
);
|
|
1929
2361
|
const k1 = [...page1.keys()];
|
|
1930
|
-
(0,
|
|
2362
|
+
(0, import_vitest9.expect)(k1).toEqual([`qsp-${tag}-a`, `qsp-${tag}-b`]);
|
|
1931
2363
|
const page2 = await store.query_stats(
|
|
1932
2364
|
{ stream: `qsp-${tag}-.*` },
|
|
1933
2365
|
{ limit: 2, after: k1.at(-1) }
|
|
1934
2366
|
);
|
|
1935
2367
|
const k2 = [...page2.keys()];
|
|
1936
|
-
(0,
|
|
2368
|
+
(0, import_vitest9.expect)(k2).toEqual([`qsp-${tag}-c`, `qsp-${tag}-d`]);
|
|
1937
2369
|
const page3 = await store.query_stats(
|
|
1938
2370
|
{ stream: `qsp-${tag}-.*` },
|
|
1939
2371
|
{ limit: 2, after: k2.at(-1) }
|
|
1940
2372
|
);
|
|
1941
|
-
(0,
|
|
2373
|
+
(0, import_vitest9.expect)(page3.size).toBe(0);
|
|
1942
2374
|
const all = await store.query_stats({
|
|
1943
2375
|
stream: `qsp-${tag}-.*`
|
|
1944
2376
|
});
|
|
1945
|
-
(0,
|
|
2377
|
+
(0, import_vitest9.expect)([...all.keys()].sort()).toEqual([...streams].sort());
|
|
1946
2378
|
});
|
|
1947
2379
|
});
|
|
1948
|
-
|
|
2380
|
+
import_vitest9.describe.skipIf(!caps.source_matches)(
|
|
1949
2381
|
"query_streams source_matches (capability)",
|
|
1950
2382
|
() => {
|
|
1951
|
-
(0,
|
|
2383
|
+
(0, import_vitest9.it)("returns only subscriptions whose source pattern matches a name", async () => {
|
|
1952
2384
|
const tag = uid();
|
|
1953
2385
|
const subConcreteA = `sm-${tag}-sub-a`;
|
|
1954
2386
|
const subConcreteB = `sm-${tag}-sub-b`;
|
|
@@ -1969,7 +2401,7 @@ var runStoreTck = (options) => {
|
|
|
1969
2401
|
stream: `sm-${tag}-sub-.*`,
|
|
1970
2402
|
source_matches: [srcA]
|
|
1971
2403
|
});
|
|
1972
|
-
(0,
|
|
2404
|
+
(0, import_vitest9.expect)(matched.sort()).toEqual(
|
|
1973
2405
|
[subConcreteA, subRegex, subNoSource].sort()
|
|
1974
2406
|
);
|
|
1975
2407
|
const none = [];
|
|
@@ -1977,20 +2409,20 @@ var runStoreTck = (options) => {
|
|
|
1977
2409
|
stream: `sm-${tag}-sub-.*`,
|
|
1978
2410
|
source_matches: [`sm-${tag}-unrelated`]
|
|
1979
2411
|
});
|
|
1980
|
-
(0,
|
|
2412
|
+
(0, import_vitest9.expect)(none).toEqual([subNoSource]);
|
|
1981
2413
|
const both = [];
|
|
1982
2414
|
await store.query_streams((p) => both.push(p.stream), {
|
|
1983
2415
|
stream: `sm-${tag}-sub-.*`,
|
|
1984
2416
|
source_matches: [srcA, srcB]
|
|
1985
2417
|
});
|
|
1986
|
-
(0,
|
|
2418
|
+
(0, import_vitest9.expect)(both.sort()).toEqual(
|
|
1987
2419
|
[subConcreteA, subConcreteB, subRegex, subNoSource].sort()
|
|
1988
2420
|
);
|
|
1989
2421
|
});
|
|
1990
2422
|
}
|
|
1991
2423
|
);
|
|
1992
|
-
(0,
|
|
1993
|
-
(0,
|
|
2424
|
+
(0, import_vitest9.describe)("query_streams anchor contract", () => {
|
|
2425
|
+
(0, import_vitest9.it)("plain regex without anchors is a substring match", async () => {
|
|
1994
2426
|
const tag = uid();
|
|
1995
2427
|
const inner = `qsr-${tag}-inner`;
|
|
1996
2428
|
const longer = `qsr-${tag}-inner-extra`;
|
|
@@ -2004,9 +2436,9 @@ var runStoreTck = (options) => {
|
|
|
2004
2436
|
await store.query_streams((p) => seen.push(p.stream), {
|
|
2005
2437
|
stream: `qsr-${tag}-inner`
|
|
2006
2438
|
});
|
|
2007
|
-
(0,
|
|
2439
|
+
(0, import_vitest9.expect)(seen.sort()).toEqual([inner, longer].sort());
|
|
2008
2440
|
});
|
|
2009
|
-
(0,
|
|
2441
|
+
(0, import_vitest9.it)("caller-anchored `^name$` matches only the whole string", async () => {
|
|
2010
2442
|
const tag = uid();
|
|
2011
2443
|
const inner = `qsr-${tag}-anchor`;
|
|
2012
2444
|
const longer = `qsr-${tag}-anchor-extra`;
|
|
@@ -2015,9 +2447,9 @@ var runStoreTck = (options) => {
|
|
|
2015
2447
|
await store.query_streams((p) => seen.push(p.stream), {
|
|
2016
2448
|
stream: `^qsr-${tag}-anchor$`
|
|
2017
2449
|
});
|
|
2018
|
-
(0,
|
|
2450
|
+
(0, import_vitest9.expect)(seen).toEqual([inner]);
|
|
2019
2451
|
});
|
|
2020
|
-
(0,
|
|
2452
|
+
(0, import_vitest9.it)("caller-anchored `^prefix` matches by prefix", async () => {
|
|
2021
2453
|
const tag = uid();
|
|
2022
2454
|
const a = `qsr-${tag}-pfx-a`;
|
|
2023
2455
|
const b = `qsr-${tag}-pfx-b`;
|
|
@@ -2031,11 +2463,11 @@ var runStoreTck = (options) => {
|
|
|
2031
2463
|
await store.query_streams((p) => seen.push(p.stream), {
|
|
2032
2464
|
stream: `^qsr-${tag}-pfx-`
|
|
2033
2465
|
});
|
|
2034
|
-
(0,
|
|
2466
|
+
(0, import_vitest9.expect)(seen.sort()).toEqual([a, b].sort());
|
|
2035
2467
|
});
|
|
2036
2468
|
});
|
|
2037
|
-
(0,
|
|
2038
|
-
(0,
|
|
2469
|
+
(0, import_vitest9.describe)("prioritize anchor contract", () => {
|
|
2470
|
+
(0, import_vitest9.it)("caller-anchored `^name$` filter matches only the whole string", async () => {
|
|
2039
2471
|
const tag = uid();
|
|
2040
2472
|
const inner = `pr-${tag}-anchor`;
|
|
2041
2473
|
const longer = `pr-${tag}-anchor-extra`;
|
|
@@ -2047,17 +2479,17 @@ var runStoreTck = (options) => {
|
|
|
2047
2479
|
{ stream: `^pr-${tag}-anchor$` },
|
|
2048
2480
|
7
|
|
2049
2481
|
);
|
|
2050
|
-
(0,
|
|
2482
|
+
(0, import_vitest9.expect)(updated).toBe(1);
|
|
2051
2483
|
const seen = /* @__PURE__ */ new Map();
|
|
2052
2484
|
await store.query_streams((p) => seen.set(p.stream, p.priority), {
|
|
2053
2485
|
stream: `pr-${tag}-anchor`
|
|
2054
2486
|
});
|
|
2055
|
-
(0,
|
|
2056
|
-
(0,
|
|
2487
|
+
(0, import_vitest9.expect)(seen.get(inner)).toBe(7);
|
|
2488
|
+
(0, import_vitest9.expect)(seen.get(longer)).toBe(0);
|
|
2057
2489
|
});
|
|
2058
2490
|
});
|
|
2059
|
-
(0,
|
|
2060
|
-
(0,
|
|
2491
|
+
(0, import_vitest9.describe)("query_streams head", () => {
|
|
2492
|
+
(0, import_vitest9.it)("maxEventId tracks the highest committed id", async () => {
|
|
2061
2493
|
const s = `head-${uid()}`;
|
|
2062
2494
|
await store.subscribe([{ stream: s }]);
|
|
2063
2495
|
await store.commit(
|
|
@@ -2070,21 +2502,21 @@ var runStoreTck = (options) => {
|
|
|
2070
2502
|
(p) => positions.push(p.stream),
|
|
2071
2503
|
{ stream: s, stream_exact: true, limit: 1 }
|
|
2072
2504
|
);
|
|
2073
|
-
(0,
|
|
2074
|
-
(0,
|
|
2505
|
+
(0, import_vitest9.expect)(maxEventId).toBeGreaterThanOrEqual(0);
|
|
2506
|
+
(0, import_vitest9.expect)(positions).toEqual([s]);
|
|
2075
2507
|
});
|
|
2076
2508
|
});
|
|
2077
|
-
(0,
|
|
2078
|
-
(0,
|
|
2509
|
+
(0, import_vitest9.describe)("seed_stream helper coverage", () => {
|
|
2510
|
+
(0, import_vitest9.it)("commits N events with monotonically increasing ids", async () => {
|
|
2079
2511
|
const s = `seed-${uid()}`;
|
|
2080
2512
|
const committed = await seed_stream(store, s, 3);
|
|
2081
|
-
(0,
|
|
2513
|
+
(0, import_vitest9.expect)(committed).toHaveLength(3);
|
|
2082
2514
|
for (let i = 1; i < committed.length; i++) {
|
|
2083
|
-
(0,
|
|
2515
|
+
(0, import_vitest9.expect)(committed[i].id).toBeGreaterThan(committed[i - 1].id);
|
|
2084
2516
|
}
|
|
2085
2517
|
});
|
|
2086
2518
|
});
|
|
2087
|
-
|
|
2519
|
+
import_vitest9.describe.skipIf(!caps.restore)("restore (capability)", () => {
|
|
2088
2520
|
beforeEach(async () => {
|
|
2089
2521
|
await store.drop();
|
|
2090
2522
|
await store.seed();
|
|
@@ -2112,8 +2544,8 @@ var runStoreTck = (options) => {
|
|
|
2112
2544
|
meta: { correlation: "restore-tck", causation: {} }
|
|
2113
2545
|
});
|
|
2114
2546
|
const restore = async (source, opts = {}) => {
|
|
2115
|
-
const cache = new
|
|
2116
|
-
const app = (0,
|
|
2547
|
+
const cache = new import_act2.InMemoryCache();
|
|
2548
|
+
const app = (0, import_act2.act)().build({ scoped: { store, cache } });
|
|
2117
2549
|
try {
|
|
2118
2550
|
return await app.restore(source, opts);
|
|
2119
2551
|
} finally {
|
|
@@ -2121,18 +2553,18 @@ var runStoreTck = (options) => {
|
|
|
2121
2553
|
await cache.dispose();
|
|
2122
2554
|
}
|
|
2123
2555
|
};
|
|
2124
|
-
(0,
|
|
2556
|
+
(0, import_vitest9.it)("returns kept=0 on an empty source", async () => {
|
|
2125
2557
|
const result = await restore(as_source([]));
|
|
2126
|
-
(0,
|
|
2127
|
-
(0,
|
|
2128
|
-
(0,
|
|
2558
|
+
(0, import_vitest9.expect)(result.kept).toBe(0);
|
|
2559
|
+
(0, import_vitest9.expect)(result.duration_ms).toBeGreaterThanOrEqual(0);
|
|
2560
|
+
(0, import_vitest9.expect)(result.dropped).toEqual({
|
|
2129
2561
|
closed_streams: 0,
|
|
2130
2562
|
snapshots: 0
|
|
2131
2563
|
});
|
|
2132
2564
|
const events2 = await collect(store, { limit: 10 });
|
|
2133
|
-
(0,
|
|
2565
|
+
(0, import_vitest9.expect)(events2).toHaveLength(0);
|
|
2134
2566
|
});
|
|
2135
|
-
(0,
|
|
2567
|
+
(0, import_vitest9.it)("rebuilds a single stream and preserves `created` verbatim", async () => {
|
|
2136
2568
|
const s = `restore-single-${uid()}`;
|
|
2137
2569
|
const t0 = /* @__PURE__ */ new Date("2020-01-01T00:00:00.000Z");
|
|
2138
2570
|
const t1 = /* @__PURE__ */ new Date("2020-01-02T00:00:00.000Z");
|
|
@@ -2143,7 +2575,7 @@ var runStoreTck = (options) => {
|
|
|
2143
2575
|
event(3, s, 2, "Decremented", t2, { amount: 1 })
|
|
2144
2576
|
];
|
|
2145
2577
|
const result = await restore(as_source(events2));
|
|
2146
|
-
(0,
|
|
2578
|
+
(0, import_vitest9.expect)(result.kept).toBe(3);
|
|
2147
2579
|
const back = [];
|
|
2148
2580
|
await store.query(
|
|
2149
2581
|
(e) => {
|
|
@@ -2151,8 +2583,8 @@ var runStoreTck = (options) => {
|
|
|
2151
2583
|
},
|
|
2152
2584
|
{ stream: s, stream_exact: true }
|
|
2153
2585
|
);
|
|
2154
|
-
(0,
|
|
2155
|
-
(0,
|
|
2586
|
+
(0, import_vitest9.expect)(back).toHaveLength(3);
|
|
2587
|
+
(0, import_vitest9.expect)(
|
|
2156
2588
|
back.map((e) => ({
|
|
2157
2589
|
stream: e.stream,
|
|
2158
2590
|
version: e.version,
|
|
@@ -2184,7 +2616,7 @@ var runStoreTck = (options) => {
|
|
|
2184
2616
|
}
|
|
2185
2617
|
]);
|
|
2186
2618
|
});
|
|
2187
|
-
(0,
|
|
2619
|
+
(0, import_vitest9.it)("rebuilds multiple streams interleaved", async () => {
|
|
2188
2620
|
const a = `restore-multi-a-${uid()}`;
|
|
2189
2621
|
const b = `restore-multi-b-${uid()}`;
|
|
2190
2622
|
const t = /* @__PURE__ */ new Date("2020-06-01T00:00:00.000Z");
|
|
@@ -2195,7 +2627,7 @@ var runStoreTck = (options) => {
|
|
|
2195
2627
|
event(4, b, 1, "Incremented", t, { amount: 30 })
|
|
2196
2628
|
];
|
|
2197
2629
|
const result = await restore(as_source(events2));
|
|
2198
|
-
(0,
|
|
2630
|
+
(0, import_vitest9.expect)(result.kept).toBe(4);
|
|
2199
2631
|
const aBack = [];
|
|
2200
2632
|
const bBack = [];
|
|
2201
2633
|
await store.query(
|
|
@@ -2210,10 +2642,10 @@ var runStoreTck = (options) => {
|
|
|
2210
2642
|
},
|
|
2211
2643
|
{ stream: b, stream_exact: true }
|
|
2212
2644
|
);
|
|
2213
|
-
(0,
|
|
2214
|
-
(0,
|
|
2645
|
+
(0, import_vitest9.expect)(aBack.map((e) => e.version)).toEqual([0, 1]);
|
|
2646
|
+
(0, import_vitest9.expect)(bBack.map((e) => e.version)).toEqual([0, 1]);
|
|
2215
2647
|
});
|
|
2216
|
-
(0,
|
|
2648
|
+
(0, import_vitest9.it)("preserves Date `created` verbatim", async () => {
|
|
2217
2649
|
const s = `restore-isoc-${uid()}`;
|
|
2218
2650
|
const iso = "2021-07-15T12:34:56.789Z";
|
|
2219
2651
|
await restore(
|
|
@@ -2236,10 +2668,10 @@ var runStoreTck = (options) => {
|
|
|
2236
2668
|
},
|
|
2237
2669
|
{ stream: s, stream_exact: true }
|
|
2238
2670
|
);
|
|
2239
|
-
(0,
|
|
2240
|
-
(0,
|
|
2671
|
+
(0, import_vitest9.expect)(back).toHaveLength(1);
|
|
2672
|
+
(0, import_vitest9.expect)(back[0].created.toISOString()).toBe(iso);
|
|
2241
2673
|
});
|
|
2242
|
-
(0,
|
|
2674
|
+
(0, import_vitest9.it)("wipes pre-existing events before inserting", async () => {
|
|
2243
2675
|
const old = `restore-old-${uid()}`;
|
|
2244
2676
|
await store.commit(
|
|
2245
2677
|
old,
|
|
@@ -2255,14 +2687,14 @@ var runStoreTck = (options) => {
|
|
|
2255
2687
|
stream: old,
|
|
2256
2688
|
stream_exact: true
|
|
2257
2689
|
});
|
|
2258
|
-
(0,
|
|
2690
|
+
(0, import_vitest9.expect)(old_back).toHaveLength(0);
|
|
2259
2691
|
const fresh_back = await collect(store, {
|
|
2260
2692
|
stream: fresh,
|
|
2261
2693
|
stream_exact: true
|
|
2262
2694
|
});
|
|
2263
|
-
(0,
|
|
2695
|
+
(0, import_vitest9.expect)(fresh_back).toHaveLength(1);
|
|
2264
2696
|
});
|
|
2265
|
-
(0,
|
|
2697
|
+
(0, import_vitest9.it)("clears subscription/stream-position metadata", async () => {
|
|
2266
2698
|
const sub = `restore-sub-${uid()}`;
|
|
2267
2699
|
await store.subscribe([{ stream: sub, source: "anything" }]);
|
|
2268
2700
|
const collect_streams = async () => {
|
|
@@ -2273,12 +2705,12 @@ var runStoreTck = (options) => {
|
|
|
2273
2705
|
return out;
|
|
2274
2706
|
};
|
|
2275
2707
|
const before = await collect_streams();
|
|
2276
|
-
(0,
|
|
2708
|
+
(0, import_vitest9.expect)(before.includes(sub)).toBe(true);
|
|
2277
2709
|
await restore(as_source([]));
|
|
2278
2710
|
const after = await collect_streams();
|
|
2279
|
-
(0,
|
|
2711
|
+
(0, import_vitest9.expect)(after.includes(sub)).toBe(false);
|
|
2280
2712
|
});
|
|
2281
|
-
(0,
|
|
2713
|
+
(0, import_vitest9.it)("preserves snapshot events through restore", async () => {
|
|
2282
2714
|
const s = `restore-snap-${uid()}`;
|
|
2283
2715
|
const t = /* @__PURE__ */ new Date("2020-04-01T00:00:00.000Z");
|
|
2284
2716
|
await restore(
|
|
@@ -2287,7 +2719,7 @@ var runStoreTck = (options) => {
|
|
|
2287
2719
|
id: 1,
|
|
2288
2720
|
stream: s,
|
|
2289
2721
|
version: 0,
|
|
2290
|
-
name:
|
|
2722
|
+
name: import_act2.SNAP_EVENT,
|
|
2291
2723
|
data: { count: 42 },
|
|
2292
2724
|
created: t,
|
|
2293
2725
|
meta: { correlation: "snap", causation: {} }
|
|
@@ -2299,10 +2731,10 @@ var runStoreTck = (options) => {
|
|
|
2299
2731
|
stream_exact: true,
|
|
2300
2732
|
with_snaps: true
|
|
2301
2733
|
});
|
|
2302
|
-
(0,
|
|
2303
|
-
(0,
|
|
2734
|
+
(0, import_vitest9.expect)(back).toHaveLength(1);
|
|
2735
|
+
(0, import_vitest9.expect)(back[0].name).toBe(import_act2.SNAP_EVENT);
|
|
2304
2736
|
});
|
|
2305
|
-
(0,
|
|
2737
|
+
(0, import_vitest9.it)("rewrites causation refs through the old\u2192new id map", async () => {
|
|
2306
2738
|
const s = `restore-caus-${uid()}`;
|
|
2307
2739
|
const t = /* @__PURE__ */ new Date("2020-08-01T00:00:00.000Z");
|
|
2308
2740
|
const events2 = [
|
|
@@ -2352,12 +2784,12 @@ var runStoreTck = (options) => {
|
|
|
2352
2784
|
},
|
|
2353
2785
|
{ stream: s, stream_exact: true }
|
|
2354
2786
|
);
|
|
2355
|
-
(0,
|
|
2356
|
-
(0,
|
|
2357
|
-
(0,
|
|
2358
|
-
(0,
|
|
2787
|
+
(0, import_vitest9.expect)(back).toHaveLength(3);
|
|
2788
|
+
(0, import_vitest9.expect)(back[0].meta.causation.event).toBeUndefined();
|
|
2789
|
+
(0, import_vitest9.expect)(back[1].meta.causation.event?.id).toBe(back[0].id);
|
|
2790
|
+
(0, import_vitest9.expect)(back[2].meta.causation.event?.id).toBe(back[1].id);
|
|
2359
2791
|
});
|
|
2360
|
-
(0,
|
|
2792
|
+
(0, import_vitest9.it)("leaves causation refs unmapped when the target isn't in the source", async () => {
|
|
2361
2793
|
const s = `restore-orphan-${uid()}`;
|
|
2362
2794
|
const t = /* @__PURE__ */ new Date("2020-09-01T00:00:00.000Z");
|
|
2363
2795
|
await restore(
|
|
@@ -2385,9 +2817,9 @@ var runStoreTck = (options) => {
|
|
|
2385
2817
|
},
|
|
2386
2818
|
{ stream: s, stream_exact: true }
|
|
2387
2819
|
);
|
|
2388
|
-
(0,
|
|
2820
|
+
(0, import_vitest9.expect)(back[0].meta.causation.event?.id).toBe(999);
|
|
2389
2821
|
});
|
|
2390
|
-
(0,
|
|
2822
|
+
(0, import_vitest9.it)("rolls back atomically when the source throws mid-iteration", async () => {
|
|
2391
2823
|
const original = `restore-pre-${uid()}`;
|
|
2392
2824
|
const committed = await store.commit(
|
|
2393
2825
|
original,
|
|
@@ -2413,7 +2845,7 @@ var runStoreTck = (options) => {
|
|
|
2413
2845
|
async dispose() {
|
|
2414
2846
|
}
|
|
2415
2847
|
};
|
|
2416
|
-
await (0,
|
|
2848
|
+
await (0, import_vitest9.expect)(restore(explosive)).rejects.toThrow("boom");
|
|
2417
2849
|
const back = [];
|
|
2418
2850
|
await store.query(
|
|
2419
2851
|
(e) => {
|
|
@@ -2421,10 +2853,10 @@ var runStoreTck = (options) => {
|
|
|
2421
2853
|
},
|
|
2422
2854
|
{ stream: original, stream_exact: true }
|
|
2423
2855
|
);
|
|
2424
|
-
(0,
|
|
2425
|
-
(0,
|
|
2856
|
+
(0, import_vitest9.expect)(back).toHaveLength(3);
|
|
2857
|
+
(0, import_vitest9.expect)(back.map((e) => e.id)).toEqual(committed.map((c) => c.id));
|
|
2426
2858
|
});
|
|
2427
|
-
(0,
|
|
2859
|
+
(0, import_vitest9.it)("drop_snapshots: skips SNAP_EVENT rows and counts them", async () => {
|
|
2428
2860
|
const s = `restore-drop-snap-${uid()}`;
|
|
2429
2861
|
const t = /* @__PURE__ */ new Date("2020-10-01T00:00:00.000Z");
|
|
2430
2862
|
const result = await restore(
|
|
@@ -2434,7 +2866,7 @@ var runStoreTck = (options) => {
|
|
|
2434
2866
|
id: 2,
|
|
2435
2867
|
stream: s,
|
|
2436
2868
|
version: 1,
|
|
2437
|
-
name:
|
|
2869
|
+
name: import_act2.SNAP_EVENT,
|
|
2438
2870
|
data: { count: 1 },
|
|
2439
2871
|
created: t,
|
|
2440
2872
|
meta: { correlation: "snap", causation: {} }
|
|
@@ -2443,19 +2875,19 @@ var runStoreTck = (options) => {
|
|
|
2443
2875
|
]),
|
|
2444
2876
|
{ drop_snapshots: true }
|
|
2445
2877
|
);
|
|
2446
|
-
(0,
|
|
2447
|
-
(0,
|
|
2878
|
+
(0, import_vitest9.expect)(result.kept).toBe(2);
|
|
2879
|
+
(0, import_vitest9.expect)(result.dropped.snapshots).toBe(1);
|
|
2448
2880
|
const back = await collect(store, {
|
|
2449
2881
|
stream: s,
|
|
2450
2882
|
stream_exact: true,
|
|
2451
2883
|
with_snaps: true
|
|
2452
2884
|
});
|
|
2453
|
-
(0,
|
|
2454
|
-
(0,
|
|
2455
|
-
back.every((e) => e.name !==
|
|
2885
|
+
(0, import_vitest9.expect)(back).toHaveLength(2);
|
|
2886
|
+
(0, import_vitest9.expect)(
|
|
2887
|
+
back.every((e) => e.name !== import_act2.SNAP_EVENT)
|
|
2456
2888
|
).toBe(true);
|
|
2457
2889
|
});
|
|
2458
|
-
(0,
|
|
2890
|
+
(0, import_vitest9.it)("on_progress fires once per event (caller throttles)", async () => {
|
|
2459
2891
|
const calls = [];
|
|
2460
2892
|
const s = `restore-progress-${uid()}`;
|
|
2461
2893
|
const t = /* @__PURE__ */ new Date("2021-02-01T00:00:00.000Z");
|
|
@@ -2466,11 +2898,11 @@ var runStoreTck = (options) => {
|
|
|
2466
2898
|
]),
|
|
2467
2899
|
{ on_progress: (p) => calls.push(p.processed) }
|
|
2468
2900
|
);
|
|
2469
|
-
(0,
|
|
2901
|
+
(0, import_vitest9.expect)(calls).toEqual([1, 2]);
|
|
2470
2902
|
});
|
|
2471
2903
|
});
|
|
2472
|
-
|
|
2473
|
-
(0,
|
|
2904
|
+
import_vitest9.describe.skipIf(!caps.pii_isolation)("pii_isolation (capability)", () => {
|
|
2905
|
+
(0, import_vitest9.it)("commits and loads pii alongside data", async () => {
|
|
2474
2906
|
const s = `pii-roundtrip-${uid()}`;
|
|
2475
2907
|
const committed = await store.commit(
|
|
2476
2908
|
s,
|
|
@@ -2483,8 +2915,8 @@ var runStoreTck = (options) => {
|
|
|
2483
2915
|
],
|
|
2484
2916
|
make_meta({ stream: s })
|
|
2485
2917
|
);
|
|
2486
|
-
(0,
|
|
2487
|
-
(0,
|
|
2918
|
+
(0, import_vitest9.expect)(committed).toHaveLength(1);
|
|
2919
|
+
(0, import_vitest9.expect)(committed[0].pii).toEqual({
|
|
2488
2920
|
email: "u@example.com",
|
|
2489
2921
|
name: "Ursula"
|
|
2490
2922
|
});
|
|
@@ -2495,11 +2927,11 @@ var runStoreTck = (options) => {
|
|
|
2495
2927
|
},
|
|
2496
2928
|
{ stream: s, stream_exact: true }
|
|
2497
2929
|
);
|
|
2498
|
-
(0,
|
|
2499
|
-
(0,
|
|
2500
|
-
(0,
|
|
2930
|
+
(0, import_vitest9.expect)(seen).toHaveLength(1);
|
|
2931
|
+
(0, import_vitest9.expect)(seen[0].pii).toEqual({ email: "u@example.com", name: "Ursula" });
|
|
2932
|
+
(0, import_vitest9.expect)(seen[0].data).toEqual({ amount: 1 });
|
|
2501
2933
|
});
|
|
2502
|
-
(0,
|
|
2934
|
+
(0, import_vitest9.it)("passes through events without pii (pii is null or undefined on load)", async () => {
|
|
2503
2935
|
const s = `pii-none-${uid()}`;
|
|
2504
2936
|
await store.commit(
|
|
2505
2937
|
s,
|
|
@@ -2513,10 +2945,10 @@ var runStoreTck = (options) => {
|
|
|
2513
2945
|
},
|
|
2514
2946
|
{ stream: s, stream_exact: true }
|
|
2515
2947
|
);
|
|
2516
|
-
(0,
|
|
2517
|
-
(0,
|
|
2948
|
+
(0, import_vitest9.expect)(seen).toHaveLength(1);
|
|
2949
|
+
(0, import_vitest9.expect)(seen[0].pii == null).toBe(true);
|
|
2518
2950
|
});
|
|
2519
|
-
(0,
|
|
2951
|
+
(0, import_vitest9.it)("wipes pii for every event on the stream via forget_pii", async () => {
|
|
2520
2952
|
const s = `pii-forget-${uid()}`;
|
|
2521
2953
|
await store.commit(
|
|
2522
2954
|
s,
|
|
@@ -2535,9 +2967,9 @@ var runStoreTck = (options) => {
|
|
|
2535
2967
|
make_meta({ stream: s })
|
|
2536
2968
|
);
|
|
2537
2969
|
const forget = store.forget_pii;
|
|
2538
|
-
(0,
|
|
2970
|
+
(0, import_vitest9.expect)(forget).toBeDefined();
|
|
2539
2971
|
const wiped = await forget.call(store, s);
|
|
2540
|
-
(0,
|
|
2972
|
+
(0, import_vitest9.expect)(wiped).toBe(2);
|
|
2541
2973
|
const seen = [];
|
|
2542
2974
|
await store.query(
|
|
2543
2975
|
(e) => {
|
|
@@ -2545,13 +2977,13 @@ var runStoreTck = (options) => {
|
|
|
2545
2977
|
},
|
|
2546
2978
|
{ stream: s, stream_exact: true }
|
|
2547
2979
|
);
|
|
2548
|
-
(0,
|
|
2980
|
+
(0, import_vitest9.expect)(seen).toHaveLength(2);
|
|
2549
2981
|
for (const e of seen) {
|
|
2550
|
-
(0,
|
|
2551
|
-
(0,
|
|
2982
|
+
(0, import_vitest9.expect)(e.pii == null).toBe(true);
|
|
2983
|
+
(0, import_vitest9.expect)(e.data).toBeDefined();
|
|
2552
2984
|
}
|
|
2553
2985
|
});
|
|
2554
|
-
(0,
|
|
2986
|
+
(0, import_vitest9.it)("is idempotent \u2014 second forget_pii returns 0, no error", async () => {
|
|
2555
2987
|
const s = `pii-forget-idem-${uid()}`;
|
|
2556
2988
|
await store.commit(
|
|
2557
2989
|
s,
|
|
@@ -2566,11 +2998,11 @@ var runStoreTck = (options) => {
|
|
|
2566
2998
|
);
|
|
2567
2999
|
const forget = store.forget_pii;
|
|
2568
3000
|
const first = await forget.call(store, s);
|
|
2569
|
-
(0,
|
|
3001
|
+
(0, import_vitest9.expect)(first).toBe(1);
|
|
2570
3002
|
const second = await forget.call(store, s);
|
|
2571
|
-
(0,
|
|
3003
|
+
(0, import_vitest9.expect)(second).toBe(0);
|
|
2572
3004
|
});
|
|
2573
|
-
(0,
|
|
3005
|
+
(0, import_vitest9.it)("only wipes the targeted stream \u2014 siblings untouched", async () => {
|
|
2574
3006
|
const sA = `pii-iso-a-${uid()}`;
|
|
2575
3007
|
const sB = `pii-iso-b-${uid()}`;
|
|
2576
3008
|
await store.commit(
|
|
@@ -2603,7 +3035,7 @@ var runStoreTck = (options) => {
|
|
|
2603
3035
|
},
|
|
2604
3036
|
{ stream: sA, stream_exact: true }
|
|
2605
3037
|
);
|
|
2606
|
-
(0,
|
|
3038
|
+
(0, import_vitest9.expect)(a[0].pii == null).toBe(true);
|
|
2607
3039
|
const b = [];
|
|
2608
3040
|
await store.query(
|
|
2609
3041
|
(e) => {
|
|
@@ -2611,9 +3043,9 @@ var runStoreTck = (options) => {
|
|
|
2611
3043
|
},
|
|
2612
3044
|
{ stream: sB, stream_exact: true }
|
|
2613
3045
|
);
|
|
2614
|
-
(0,
|
|
3046
|
+
(0, import_vitest9.expect)(b[0].pii).toEqual({ email: "bob@example.com" });
|
|
2615
3047
|
});
|
|
2616
|
-
(0,
|
|
3048
|
+
(0, import_vitest9.it)("forget_pii on a stream with no pii events returns 0", async () => {
|
|
2617
3049
|
const s = `pii-forget-empty-${uid()}`;
|
|
2618
3050
|
await store.commit(
|
|
2619
3051
|
s,
|
|
@@ -2621,14 +3053,14 @@ var runStoreTck = (options) => {
|
|
|
2621
3053
|
make_meta({ stream: s })
|
|
2622
3054
|
);
|
|
2623
3055
|
const wiped = await store.forget_pii.call(store, s);
|
|
2624
|
-
(0,
|
|
3056
|
+
(0, import_vitest9.expect)(wiped).toBe(0);
|
|
2625
3057
|
});
|
|
2626
3058
|
});
|
|
2627
3059
|
if (caps.notify) {
|
|
2628
|
-
(0,
|
|
2629
|
-
(0,
|
|
3060
|
+
(0, import_vitest9.describe)("notify (capability)", () => {
|
|
3061
|
+
(0, import_vitest9.it)("delivers a notification when a different instance commits", async () => {
|
|
2630
3062
|
const notify = store.notify;
|
|
2631
|
-
(0,
|
|
3063
|
+
(0, import_vitest9.expect)(notify).toBeDefined();
|
|
2632
3064
|
const received = [];
|
|
2633
3065
|
let resolve_arrived;
|
|
2634
3066
|
const arrived = new Promise((res) => {
|
|
@@ -2647,9 +3079,9 @@ var runStoreTck = (options) => {
|
|
|
2647
3079
|
make_meta({ stream })
|
|
2648
3080
|
);
|
|
2649
3081
|
await arrived;
|
|
2650
|
-
(0,
|
|
2651
|
-
(0,
|
|
2652
|
-
(0,
|
|
3082
|
+
(0, import_vitest9.expect)(received.length).toBeGreaterThanOrEqual(1);
|
|
3083
|
+
(0, import_vitest9.expect)(received[0].stream).toBe(stream);
|
|
3084
|
+
(0, import_vitest9.expect)(received[0].events.length).toBeGreaterThanOrEqual(1);
|
|
2653
3085
|
} finally {
|
|
2654
3086
|
await writer.dispose();
|
|
2655
3087
|
await Promise.resolve(disposer());
|
|
@@ -2671,9 +3103,12 @@ var runStoreTck = (options) => {
|
|
|
2671
3103
|
dec,
|
|
2672
3104
|
inc,
|
|
2673
3105
|
reset,
|
|
3106
|
+
runCacheDifferentialTck,
|
|
2674
3107
|
runCacheTck,
|
|
3108
|
+
runLoggerDifferentialTck,
|
|
2675
3109
|
runLoggerTck,
|
|
2676
3110
|
runStabilityTck,
|
|
3111
|
+
runStoreDifferentialTck,
|
|
2677
3112
|
runStorePropertyTck,
|
|
2678
3113
|
runStoreTck,
|
|
2679
3114
|
uid
|