@rotorsoft/act-tck 1.17.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 +903 -514
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +876 -490
- 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,23 @@ 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 () => {
|
|
595
960
|
const s = `q-snap-${uid()}`;
|
|
596
961
|
await store.commit(
|
|
597
962
|
s,
|
|
@@ -600,7 +965,7 @@ var runStoreTck = (options) => {
|
|
|
600
965
|
);
|
|
601
966
|
const [snap] = await store.commit(
|
|
602
967
|
s,
|
|
603
|
-
[{ name:
|
|
968
|
+
[{ name: import_act2.SNAP_EVENT, data: { count: 2 } }],
|
|
604
969
|
make_meta({ stream: s })
|
|
605
970
|
);
|
|
606
971
|
await store.commit(
|
|
@@ -613,17 +978,17 @@ var runStoreTck = (options) => {
|
|
|
613
978
|
stream_exact: true,
|
|
614
979
|
with_snaps: true
|
|
615
980
|
});
|
|
616
|
-
(0,
|
|
617
|
-
(0,
|
|
981
|
+
(0, import_vitest9.expect)(from_snap).toHaveLength(4);
|
|
982
|
+
(0, import_vitest9.expect)(from_snap[0].name).toBe(import_act2.SNAP_EVENT);
|
|
618
983
|
const domain = await collect(store, { stream: s, stream_exact: true });
|
|
619
|
-
(0,
|
|
984
|
+
(0, import_vitest9.expect)(domain).toHaveLength(5);
|
|
620
985
|
const after_snap = await collect(store, {
|
|
621
986
|
stream: s,
|
|
622
987
|
stream_exact: true,
|
|
623
988
|
with_snaps: true,
|
|
624
989
|
after: snap.id
|
|
625
990
|
});
|
|
626
|
-
(0,
|
|
991
|
+
(0, import_vitest9.expect)(after_snap).toHaveLength(3);
|
|
627
992
|
const s2 = `q-nosnap-${uid()}`;
|
|
628
993
|
await store.commit(
|
|
629
994
|
s2,
|
|
@@ -635,9 +1000,9 @@ var runStoreTck = (options) => {
|
|
|
635
1000
|
stream_exact: true,
|
|
636
1001
|
with_snaps: true
|
|
637
1002
|
});
|
|
638
|
-
(0,
|
|
1003
|
+
(0, import_vitest9.expect)(full).toHaveLength(2);
|
|
639
1004
|
});
|
|
640
|
-
(0,
|
|
1005
|
+
(0, import_vitest9.it)("supports backward traversal", async () => {
|
|
641
1006
|
const s = `q-back-${uid()}`;
|
|
642
1007
|
const committed = await store.commit(
|
|
643
1008
|
s,
|
|
@@ -650,8 +1015,8 @@ var runStoreTck = (options) => {
|
|
|
650
1015
|
stream_exact: true,
|
|
651
1016
|
backward: true
|
|
652
1017
|
});
|
|
653
|
-
(0,
|
|
654
|
-
(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(
|
|
655
1020
|
[...committed].reverse().map((c) => c.id)
|
|
656
1021
|
);
|
|
657
1022
|
const latest = await collect(store, {
|
|
@@ -660,10 +1025,10 @@ var runStoreTck = (options) => {
|
|
|
660
1025
|
backward: true,
|
|
661
1026
|
limit: 1
|
|
662
1027
|
});
|
|
663
|
-
(0,
|
|
664
|
-
(0,
|
|
1028
|
+
(0, import_vitest9.expect)(latest).toHaveLength(1);
|
|
1029
|
+
(0, import_vitest9.expect)(latest[0].id).toBe(committed.at(-1).id);
|
|
665
1030
|
});
|
|
666
|
-
(0,
|
|
1031
|
+
(0, import_vitest9.it)("after/before bound the id range", async () => {
|
|
667
1032
|
const s = `q-bounds-${uid()}`;
|
|
668
1033
|
const committed = await store.commit(
|
|
669
1034
|
s,
|
|
@@ -675,7 +1040,7 @@ var runStoreTck = (options) => {
|
|
|
675
1040
|
stream_exact: true,
|
|
676
1041
|
after: committed[0].id
|
|
677
1042
|
});
|
|
678
|
-
(0,
|
|
1043
|
+
(0, import_vitest9.expect)(after_first.map((e) => e.id)).toEqual(
|
|
679
1044
|
committed.slice(1).map((c) => c.id)
|
|
680
1045
|
);
|
|
681
1046
|
const before_last = await collect(store, {
|
|
@@ -683,11 +1048,11 @@ var runStoreTck = (options) => {
|
|
|
683
1048
|
stream_exact: true,
|
|
684
1049
|
before: committed[committed.length - 1].id
|
|
685
1050
|
});
|
|
686
|
-
(0,
|
|
1051
|
+
(0, import_vitest9.expect)(before_last.map((e) => e.id)).toEqual(
|
|
687
1052
|
committed.slice(0, -1).map((c) => c.id)
|
|
688
1053
|
);
|
|
689
1054
|
});
|
|
690
|
-
(0,
|
|
1055
|
+
(0, import_vitest9.it)("created_after/created_before filter by timestamp", async () => {
|
|
691
1056
|
const s = `q-ts-${uid()}`;
|
|
692
1057
|
const committed = await store.commit(
|
|
693
1058
|
s,
|
|
@@ -703,15 +1068,15 @@ var runStoreTck = (options) => {
|
|
|
703
1068
|
created_after: before,
|
|
704
1069
|
created_before: future
|
|
705
1070
|
});
|
|
706
|
-
(0,
|
|
1071
|
+
(0, import_vitest9.expect)(in_window.length).toBe(1);
|
|
707
1072
|
const out_of_window = await collect(store, {
|
|
708
1073
|
stream: s,
|
|
709
1074
|
stream_exact: true,
|
|
710
1075
|
created_after: future
|
|
711
1076
|
});
|
|
712
|
-
(0,
|
|
1077
|
+
(0, import_vitest9.expect)(out_of_window.length).toBe(0);
|
|
713
1078
|
});
|
|
714
|
-
(0,
|
|
1079
|
+
(0, import_vitest9.it)("backward traversal short-circuits at `after` id boundary", async () => {
|
|
715
1080
|
const s = `q-back-after-${uid()}`;
|
|
716
1081
|
const committed = await store.commit(
|
|
717
1082
|
s,
|
|
@@ -724,12 +1089,12 @@ var runStoreTck = (options) => {
|
|
|
724
1089
|
backward: true,
|
|
725
1090
|
after: committed[0].id
|
|
726
1091
|
});
|
|
727
|
-
(0,
|
|
1092
|
+
(0, import_vitest9.expect)(got.map((e) => e.id)).toEqual([
|
|
728
1093
|
committed[2].id,
|
|
729
1094
|
committed[1].id
|
|
730
1095
|
]);
|
|
731
1096
|
});
|
|
732
|
-
(0,
|
|
1097
|
+
(0, import_vitest9.it)("backward traversal short-circuits at `created_after` boundary", async () => {
|
|
733
1098
|
const s = `q-back-cafter-${uid()}`;
|
|
734
1099
|
await store.commit(
|
|
735
1100
|
s,
|
|
@@ -743,9 +1108,9 @@ var runStoreTck = (options) => {
|
|
|
743
1108
|
backward: true,
|
|
744
1109
|
created_after: future
|
|
745
1110
|
});
|
|
746
|
-
(0,
|
|
1111
|
+
(0, import_vitest9.expect)(got).toHaveLength(0);
|
|
747
1112
|
});
|
|
748
|
-
(0,
|
|
1113
|
+
(0, import_vitest9.it)("backward traversal honors created_before by skipping newer events", async () => {
|
|
749
1114
|
const s = `q-back-ts-${uid()}`;
|
|
750
1115
|
const committed = await store.commit(
|
|
751
1116
|
s,
|
|
@@ -759,9 +1124,9 @@ var runStoreTck = (options) => {
|
|
|
759
1124
|
backward: true,
|
|
760
1125
|
created_before: past
|
|
761
1126
|
});
|
|
762
|
-
(0,
|
|
1127
|
+
(0, import_vitest9.expect)(got).toHaveLength(0);
|
|
763
1128
|
});
|
|
764
|
-
(0,
|
|
1129
|
+
(0, import_vitest9.it)("stream_exact disables regex matching", async () => {
|
|
765
1130
|
const tag = uid();
|
|
766
1131
|
const a = `q-exact-${tag}`;
|
|
767
1132
|
const b = `q-exact-${tag}-extra`;
|
|
@@ -776,10 +1141,10 @@ var runStoreTck = (options) => {
|
|
|
776
1141
|
make_meta({ stream: b })
|
|
777
1142
|
);
|
|
778
1143
|
const exact = await collect(store, { stream: a, stream_exact: true });
|
|
779
|
-
(0,
|
|
780
|
-
(0,
|
|
1144
|
+
(0, import_vitest9.expect)(exact).toHaveLength(1);
|
|
1145
|
+
(0, import_vitest9.expect)(exact[0].data).toEqual({ amount: 1 });
|
|
781
1146
|
});
|
|
782
|
-
(0,
|
|
1147
|
+
(0, import_vitest9.it)("plain regex without anchors is a substring match", async () => {
|
|
783
1148
|
const tag = uid();
|
|
784
1149
|
const inner = `qr-${tag}-inner`;
|
|
785
1150
|
const longer = `qr-${tag}-inner-extra`;
|
|
@@ -794,9 +1159,9 @@ var runStoreTck = (options) => {
|
|
|
794
1159
|
make_meta({ stream: longer })
|
|
795
1160
|
);
|
|
796
1161
|
const got = await collect(store, { stream: `qr-${tag}-inner` });
|
|
797
|
-
(0,
|
|
1162
|
+
(0, import_vitest9.expect)(got.map((e) => e.stream).sort()).toEqual([inner, longer].sort());
|
|
798
1163
|
});
|
|
799
|
-
(0,
|
|
1164
|
+
(0, import_vitest9.it)("caller-anchored `^name$` matches only the whole string", async () => {
|
|
800
1165
|
const tag = uid();
|
|
801
1166
|
const inner = `qr-${tag}-anchor`;
|
|
802
1167
|
const longer = `qr-${tag}-anchor-extra`;
|
|
@@ -811,10 +1176,10 @@ var runStoreTck = (options) => {
|
|
|
811
1176
|
make_meta({ stream: longer })
|
|
812
1177
|
);
|
|
813
1178
|
const got = await collect(store, { stream: `^qr-${tag}-anchor$` });
|
|
814
|
-
(0,
|
|
815
|
-
(0,
|
|
1179
|
+
(0, import_vitest9.expect)(got).toHaveLength(1);
|
|
1180
|
+
(0, import_vitest9.expect)(got[0].stream).toBe(inner);
|
|
816
1181
|
});
|
|
817
|
-
(0,
|
|
1182
|
+
(0, import_vitest9.it)("caller-anchored `^prefix` matches by prefix", async () => {
|
|
818
1183
|
const tag = uid();
|
|
819
1184
|
const a = `qr-${tag}-pfx-a`;
|
|
820
1185
|
const b = `qr-${tag}-pfx-b`;
|
|
@@ -835,18 +1200,39 @@ var runStoreTck = (options) => {
|
|
|
835
1200
|
make_meta({ stream: other })
|
|
836
1201
|
);
|
|
837
1202
|
const got = await collect(store, { stream: `^qr-${tag}-pfx-` });
|
|
838
|
-
(0,
|
|
1203
|
+
(0, import_vitest9.expect)(got.map((e) => e.stream).sort()).toEqual([a, b].sort());
|
|
839
1204
|
});
|
|
840
1205
|
});
|
|
841
|
-
(0,
|
|
842
|
-
(0,
|
|
1206
|
+
(0, import_vitest9.describe)("subscribe + claim + ack", () => {
|
|
1207
|
+
(0, import_vitest9.it)("subscribes new streams and is idempotent on repeat", async () => {
|
|
843
1208
|
const s = `sub-${uid()}`;
|
|
844
1209
|
const first = await store.subscribe([{ stream: s }]);
|
|
845
|
-
(0,
|
|
1210
|
+
(0, import_vitest9.expect)(first.subscribed).toBe(1);
|
|
846
1211
|
const second = await store.subscribe([{ stream: s }]);
|
|
847
|
-
(0,
|
|
1212
|
+
(0, import_vitest9.expect)(second.subscribed).toBe(0);
|
|
848
1213
|
});
|
|
849
|
-
(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 () => {
|
|
850
1236
|
const s = `claim-${uid()}`;
|
|
851
1237
|
await store.subscribe([{ stream: s }]);
|
|
852
1238
|
await store.commit(
|
|
@@ -857,11 +1243,11 @@ var runStoreTck = (options) => {
|
|
|
857
1243
|
const by = `worker-${uid()}`;
|
|
858
1244
|
const leased = await store.claim(100, 0, by, 1e4);
|
|
859
1245
|
const mine = leased.find((l) => l.stream === s);
|
|
860
|
-
(0,
|
|
861
|
-
(0,
|
|
1246
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1247
|
+
(0, import_vitest9.expect)(mine.by).toBe(by);
|
|
862
1248
|
await store.ack([{ ...mine, at: mine.at + 1 }]);
|
|
863
1249
|
});
|
|
864
|
-
(0,
|
|
1250
|
+
(0, import_vitest9.it)("does not double-claim a held lease", async () => {
|
|
865
1251
|
const s = `claim-held-${uid()}`;
|
|
866
1252
|
const other = `claim-other-${uid()}`;
|
|
867
1253
|
await store.subscribe([{ stream: s }]);
|
|
@@ -872,7 +1258,7 @@ var runStoreTck = (options) => {
|
|
|
872
1258
|
);
|
|
873
1259
|
const leasedA = await store.claim(100, 0, `wA-${uid()}`, 1e5);
|
|
874
1260
|
const targetA = leasedA.find((l) => l.stream === s);
|
|
875
|
-
(0,
|
|
1261
|
+
(0, import_vitest9.expect)(targetA).toBeDefined();
|
|
876
1262
|
await store.subscribe([{ stream: other }]);
|
|
877
1263
|
await store.commit(
|
|
878
1264
|
other,
|
|
@@ -880,11 +1266,11 @@ var runStoreTck = (options) => {
|
|
|
880
1266
|
make_meta({ stream: other })
|
|
881
1267
|
);
|
|
882
1268
|
const leasedB = await store.claim(100, 0, `wB-${uid()}`, 1e5);
|
|
883
|
-
(0,
|
|
884
|
-
(0,
|
|
885
|
-
(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();
|
|
886
1272
|
});
|
|
887
|
-
(0,
|
|
1273
|
+
(0, import_vitest9.it)("supports dual frontiers (lagging + leading)", async () => {
|
|
888
1274
|
const s = `claim-dual-${uid()}`;
|
|
889
1275
|
await store.subscribe([{ stream: s }]);
|
|
890
1276
|
await store.commit(
|
|
@@ -894,12 +1280,12 @@ var runStoreTck = (options) => {
|
|
|
894
1280
|
);
|
|
895
1281
|
const first = await store.claim(100, 0, `w-${uid()}`, 1);
|
|
896
1282
|
const mine = first.find((l) => l.stream === s);
|
|
897
|
-
(0,
|
|
1283
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
898
1284
|
await store.ack([{ ...mine, at: mine.at + 1 }]);
|
|
899
1285
|
const second = await store.claim(0, 100, `w-${uid()}`, 1);
|
|
900
|
-
(0,
|
|
1286
|
+
(0, import_vitest9.expect)(second.find((l) => l.stream === s)).toBeDefined();
|
|
901
1287
|
});
|
|
902
|
-
(0,
|
|
1288
|
+
(0, import_vitest9.it)("dedupes when both frontiers would return the same stream", async () => {
|
|
903
1289
|
const s = `claim-dedup-${uid()}`;
|
|
904
1290
|
await store.subscribe([{ stream: s }]);
|
|
905
1291
|
await store.commit(
|
|
@@ -909,9 +1295,9 @@ var runStoreTck = (options) => {
|
|
|
909
1295
|
);
|
|
910
1296
|
const claimed = await store.claim(100, 100, `w-${uid()}`, 1e5);
|
|
911
1297
|
const matches = claimed.filter((l) => l.stream === s);
|
|
912
|
-
(0,
|
|
1298
|
+
(0, import_vitest9.expect)(matches).toHaveLength(1);
|
|
913
1299
|
});
|
|
914
|
-
(0,
|
|
1300
|
+
(0, import_vitest9.it)("silently ignores ack from the wrong holder", async () => {
|
|
915
1301
|
const s = `ack-wrong-${uid()}`;
|
|
916
1302
|
const sibling = `ack-sibling-${uid()}`;
|
|
917
1303
|
await store.subscribe([{ stream: s }, { stream: sibling }]);
|
|
@@ -928,40 +1314,40 @@ var runStoreTck = (options) => {
|
|
|
928
1314
|
const leased = await store.claim(100, 0, `right-${uid()}`, 1e5);
|
|
929
1315
|
const mine = leased.find((l) => l.stream === s);
|
|
930
1316
|
const sibling_lease = leased.find((l) => l.stream === sibling);
|
|
931
|
-
(0,
|
|
932
|
-
(0,
|
|
1317
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1318
|
+
(0, import_vitest9.expect)(sibling_lease).toBeDefined();
|
|
933
1319
|
const acked = await store.ack([
|
|
934
1320
|
{ ...mine, by: "imposter" },
|
|
935
1321
|
sibling_lease
|
|
936
1322
|
]);
|
|
937
|
-
(0,
|
|
938
|
-
(0,
|
|
1323
|
+
(0, import_vitest9.expect)(acked.length).toBeGreaterThan(0);
|
|
1324
|
+
(0, import_vitest9.expect)(acked.find((l) => l.stream === s)).toBeUndefined();
|
|
939
1325
|
});
|
|
940
|
-
(0,
|
|
1326
|
+
(0, import_vitest9.it)("ack with a stale (lower) watermark does not throw", async () => {
|
|
941
1327
|
const s = `ack-stale-${uid()}`;
|
|
942
1328
|
await store.subscribe([{ stream: s }]);
|
|
943
1329
|
const by = `w-${uid()}`;
|
|
944
1330
|
const leased = await store.claim(100, 0, by, 1e5);
|
|
945
1331
|
const mine = leased.find((l) => l.stream === s);
|
|
946
|
-
(0,
|
|
947
|
-
await (0,
|
|
1332
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1333
|
+
await (0, import_vitest9.expect)(
|
|
948
1334
|
store.ack([{ ...mine, at: -5 }])
|
|
949
1335
|
).resolves.toBeDefined();
|
|
950
1336
|
});
|
|
951
|
-
(0,
|
|
1337
|
+
(0, import_vitest9.it)("claim with no subscribed streams returns an empty array", async () => {
|
|
952
1338
|
const fresh = await options.factory();
|
|
953
1339
|
try {
|
|
954
1340
|
await fresh.drop();
|
|
955
1341
|
await fresh.seed();
|
|
956
1342
|
const claimed = await fresh.claim(1, 1, `w-${uid()}`, 1e3);
|
|
957
|
-
(0,
|
|
1343
|
+
(0, import_vitest9.expect)(claimed).toEqual([]);
|
|
958
1344
|
} finally {
|
|
959
1345
|
await fresh.dispose();
|
|
960
1346
|
}
|
|
961
1347
|
});
|
|
962
1348
|
});
|
|
963
|
-
(0,
|
|
964
|
-
(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 () => {
|
|
965
1351
|
const fresh = await options.factory();
|
|
966
1352
|
try {
|
|
967
1353
|
await fresh.drop();
|
|
@@ -975,17 +1361,17 @@ var runStoreTck = (options) => {
|
|
|
975
1361
|
);
|
|
976
1362
|
const first = await fresh.claim(1, 0, `w-${uid()}`, 0);
|
|
977
1363
|
const f = first.find((l) => l.stream === s);
|
|
978
|
-
(0,
|
|
979
|
-
(0,
|
|
1364
|
+
(0, import_vitest9.expect)(f).toBeDefined();
|
|
1365
|
+
(0, import_vitest9.expect)(f.retry).toBe(0);
|
|
980
1366
|
const second = await fresh.claim(1, 0, `w-${uid()}`, 1e5);
|
|
981
1367
|
const sec = second.find((l) => l.stream === s);
|
|
982
|
-
(0,
|
|
983
|
-
(0,
|
|
1368
|
+
(0, import_vitest9.expect)(sec).toBeDefined();
|
|
1369
|
+
(0, import_vitest9.expect)(sec.retry).toBe(1);
|
|
984
1370
|
} finally {
|
|
985
1371
|
await fresh.dispose();
|
|
986
1372
|
}
|
|
987
1373
|
});
|
|
988
|
-
(0,
|
|
1374
|
+
(0, import_vitest9.it)("reports lagging=true from the lagging frontier and false from the leading frontier", async () => {
|
|
989
1375
|
const fresh = await options.factory();
|
|
990
1376
|
try {
|
|
991
1377
|
await fresh.drop();
|
|
@@ -998,16 +1384,16 @@ var runStoreTck = (options) => {
|
|
|
998
1384
|
make_meta({ stream: s })
|
|
999
1385
|
);
|
|
1000
1386
|
const lag = await fresh.claim(1, 0, `w-${uid()}`, 0);
|
|
1001
|
-
(0,
|
|
1387
|
+
(0, import_vitest9.expect)(lag.find((l) => l.stream === s)?.lagging).toBe(true);
|
|
1002
1388
|
const lead = await fresh.claim(0, 1, `w-${uid()}`, 1e5);
|
|
1003
|
-
(0,
|
|
1389
|
+
(0, import_vitest9.expect)(lead.find((l) => l.stream === s)?.lagging).toBe(false);
|
|
1004
1390
|
} finally {
|
|
1005
1391
|
await fresh.dispose();
|
|
1006
1392
|
}
|
|
1007
1393
|
});
|
|
1008
1394
|
});
|
|
1009
|
-
|
|
1010
|
-
(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 () => {
|
|
1011
1397
|
const fresh = await options.factory();
|
|
1012
1398
|
try {
|
|
1013
1399
|
await fresh.drop();
|
|
@@ -1030,15 +1416,15 @@ var runStoreTck = (options) => {
|
|
|
1030
1416
|
fresh.claim(100, 100, `wB-${uid()}`, 6e4)
|
|
1031
1417
|
]);
|
|
1032
1418
|
const claimed = [...a, ...b].map((l) => l.stream).filter((stream) => owned.has(stream));
|
|
1033
|
-
(0,
|
|
1034
|
-
(0,
|
|
1419
|
+
(0, import_vitest9.expect)(new Set(claimed).size).toBe(claimed.length);
|
|
1420
|
+
(0, import_vitest9.expect)(claimed.length).toBe(owned.size);
|
|
1035
1421
|
} finally {
|
|
1036
1422
|
await fresh.dispose();
|
|
1037
1423
|
}
|
|
1038
1424
|
});
|
|
1039
1425
|
});
|
|
1040
|
-
(0,
|
|
1041
|
-
(0,
|
|
1426
|
+
(0, import_vitest9.describe)("block", () => {
|
|
1427
|
+
(0, import_vitest9.it)("hides blocked streams from claim", async () => {
|
|
1042
1428
|
const s = `block-${uid()}`;
|
|
1043
1429
|
await store.subscribe([{ stream: s }]);
|
|
1044
1430
|
await store.commit(
|
|
@@ -1048,18 +1434,18 @@ var runStoreTck = (options) => {
|
|
|
1048
1434
|
);
|
|
1049
1435
|
const leased = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1050
1436
|
const mine = leased.find((l) => l.stream === s);
|
|
1051
|
-
(0,
|
|
1437
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1052
1438
|
const others = leased.filter((l) => l.stream !== s);
|
|
1053
1439
|
await store.ack(others);
|
|
1054
1440
|
const blocked = await store.block([
|
|
1055
1441
|
{ ...mine, error: "boom" }
|
|
1056
1442
|
]);
|
|
1057
|
-
(0,
|
|
1058
|
-
(0,
|
|
1443
|
+
(0, import_vitest9.expect)(blocked).toHaveLength(1);
|
|
1444
|
+
(0, import_vitest9.expect)(blocked[0].error).toBe("boom");
|
|
1059
1445
|
const again = await store.claim(100, 100, `w2-${uid()}`, 1e5);
|
|
1060
|
-
(0,
|
|
1446
|
+
(0, import_vitest9.expect)(again.find((l) => l.stream === s)).toBeUndefined();
|
|
1061
1447
|
});
|
|
1062
|
-
(0,
|
|
1448
|
+
(0, import_vitest9.it)("rejects block calls from a different holder", async () => {
|
|
1063
1449
|
const s = `block-wrong-${uid()}`;
|
|
1064
1450
|
await store.subscribe([{ stream: s }]);
|
|
1065
1451
|
await store.commit(
|
|
@@ -1069,17 +1455,17 @@ var runStoreTck = (options) => {
|
|
|
1069
1455
|
);
|
|
1070
1456
|
const leased = await store.claim(100, 0, `right-${uid()}`, 1e5);
|
|
1071
1457
|
const mine = leased.find((l) => l.stream === s);
|
|
1072
|
-
(0,
|
|
1458
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1073
1459
|
const others = leased.filter((l) => l.stream !== s);
|
|
1074
1460
|
await store.ack(others);
|
|
1075
1461
|
const blocked = await store.block([
|
|
1076
1462
|
{ ...mine, by: "imposter", error: "no" }
|
|
1077
1463
|
]);
|
|
1078
|
-
(0,
|
|
1464
|
+
(0, import_vitest9.expect)(blocked).toHaveLength(0);
|
|
1079
1465
|
});
|
|
1080
1466
|
});
|
|
1081
|
-
(0,
|
|
1082
|
-
(0,
|
|
1467
|
+
(0, import_vitest9.describe)("reset", () => {
|
|
1468
|
+
(0, import_vitest9.it)("rewinds a stream watermark to -1", async () => {
|
|
1083
1469
|
const s = `reset-${uid()}`;
|
|
1084
1470
|
await store.subscribe([{ stream: s }]);
|
|
1085
1471
|
await store.commit(
|
|
@@ -1089,15 +1475,15 @@ var runStoreTck = (options) => {
|
|
|
1089
1475
|
);
|
|
1090
1476
|
const leased = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1091
1477
|
const mine = leased.find((l) => l.stream === s);
|
|
1092
|
-
(0,
|
|
1478
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1093
1479
|
await store.ack([{ ...mine, at: 99 }]);
|
|
1094
|
-
(0,
|
|
1480
|
+
(0, import_vitest9.expect)(await store.reset([s])).toBe(1);
|
|
1095
1481
|
const after = await store.claim(100, 0, `w2-${uid()}`, 1e5);
|
|
1096
1482
|
const back = after.find((l) => l.stream === s);
|
|
1097
|
-
(0,
|
|
1098
|
-
(0,
|
|
1483
|
+
(0, import_vitest9.expect)(back).toBeDefined();
|
|
1484
|
+
(0, import_vitest9.expect)(back.at).toBe(-1);
|
|
1099
1485
|
});
|
|
1100
|
-
(0,
|
|
1486
|
+
(0, import_vitest9.it)("clears blocked status when resetting", async () => {
|
|
1101
1487
|
const s = `reset-blk-${uid()}`;
|
|
1102
1488
|
await store.subscribe([{ stream: s }]);
|
|
1103
1489
|
await store.commit(
|
|
@@ -1110,17 +1496,17 @@ var runStoreTck = (options) => {
|
|
|
1110
1496
|
const others = leased.filter((l) => l.stream !== s);
|
|
1111
1497
|
await store.ack(others);
|
|
1112
1498
|
await store.block([{ ...mine, error: "boom" }]);
|
|
1113
|
-
(0,
|
|
1499
|
+
(0, import_vitest9.expect)(await store.reset([s])).toBe(1);
|
|
1114
1500
|
const after = await store.claim(100, 0, `w2-${uid()}`, 1e5);
|
|
1115
|
-
(0,
|
|
1501
|
+
(0, import_vitest9.expect)(after.find((l) => l.stream === s)).toBeDefined();
|
|
1116
1502
|
});
|
|
1117
|
-
(0,
|
|
1118
|
-
(0,
|
|
1119
|
-
(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);
|
|
1120
1506
|
});
|
|
1121
1507
|
});
|
|
1122
|
-
(0,
|
|
1123
|
-
(0,
|
|
1508
|
+
(0, import_vitest9.describe)("unblock", () => {
|
|
1509
|
+
(0, import_vitest9.it)("clears blocked flag and preserves the watermark", async () => {
|
|
1124
1510
|
const s = `unblock-${uid()}`;
|
|
1125
1511
|
await store.subscribe([{ stream: s }]);
|
|
1126
1512
|
await store.commit(
|
|
@@ -1138,7 +1524,7 @@ var runStoreTck = (options) => {
|
|
|
1138
1524
|
await store.ack([{ ...m1, at: m1.at }]);
|
|
1139
1525
|
const before_block = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1140
1526
|
const m2 = before_block.find((l) => l.stream === s);
|
|
1141
|
-
(0,
|
|
1527
|
+
(0, import_vitest9.expect)(m2).toBeDefined();
|
|
1142
1528
|
const watermark_before = m2.at;
|
|
1143
1529
|
await store.block([{ ...m2, error: "permanent" }]);
|
|
1144
1530
|
let blocked_flag;
|
|
@@ -1148,15 +1534,15 @@ var runStoreTck = (options) => {
|
|
|
1148
1534
|
},
|
|
1149
1535
|
{ stream: s, stream_exact: true, limit: 1 }
|
|
1150
1536
|
);
|
|
1151
|
-
(0,
|
|
1152
|
-
(0,
|
|
1537
|
+
(0, import_vitest9.expect)(blocked_flag).toBe(true);
|
|
1538
|
+
(0, import_vitest9.expect)(await store.unblock([s])).toBe(1);
|
|
1153
1539
|
const after = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1154
1540
|
const back = after.find((l) => l.stream === s);
|
|
1155
|
-
(0,
|
|
1156
|
-
(0,
|
|
1157
|
-
(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);
|
|
1158
1544
|
});
|
|
1159
|
-
(0,
|
|
1545
|
+
(0, import_vitest9.it)("returns 0 when the stream is not blocked", async () => {
|
|
1160
1546
|
const s = `unblock-noop-${uid()}`;
|
|
1161
1547
|
await store.subscribe([{ stream: s }]);
|
|
1162
1548
|
await store.commit(
|
|
@@ -1164,13 +1550,13 @@ var runStoreTck = (options) => {
|
|
|
1164
1550
|
[inc(1)],
|
|
1165
1551
|
make_meta({ stream: s })
|
|
1166
1552
|
);
|
|
1167
|
-
(0,
|
|
1553
|
+
(0, import_vitest9.expect)(await store.unblock([s])).toBe(0);
|
|
1168
1554
|
});
|
|
1169
|
-
(0,
|
|
1170
|
-
(0,
|
|
1171
|
-
(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);
|
|
1172
1558
|
});
|
|
1173
|
-
(0,
|
|
1559
|
+
(0, import_vitest9.it)("only counts streams that were actually blocked", async () => {
|
|
1174
1560
|
const s1 = `unblock-mix-a-${uid()}`;
|
|
1175
1561
|
const s2 = `unblock-mix-b-${uid()}`;
|
|
1176
1562
|
await store.subscribe([{ stream: s1 }, { stream: s2 }]);
|
|
@@ -1189,9 +1575,9 @@ var runStoreTck = (options) => {
|
|
|
1189
1575
|
const others = leased.filter((l) => l.stream !== s1);
|
|
1190
1576
|
await store.ack(others);
|
|
1191
1577
|
await store.block([{ ...m1, error: "boom" }]);
|
|
1192
|
-
(0,
|
|
1578
|
+
(0, import_vitest9.expect)(await store.unblock([s1, s2])).toBe(1);
|
|
1193
1579
|
});
|
|
1194
|
-
(0,
|
|
1580
|
+
(0, import_vitest9.it)("filter form: unblocks by stream pattern", async () => {
|
|
1195
1581
|
const tag = uid();
|
|
1196
1582
|
const s1 = `unblock-filter-${tag}-a`;
|
|
1197
1583
|
const s2 = `unblock-filter-${tag}-b`;
|
|
@@ -1223,13 +1609,13 @@ var runStoreTck = (options) => {
|
|
|
1223
1609
|
const count = await store.unblock({
|
|
1224
1610
|
stream: `^unblock-filter-${tag}-`
|
|
1225
1611
|
});
|
|
1226
|
-
(0,
|
|
1612
|
+
(0, import_vitest9.expect)(count).toBe(2);
|
|
1227
1613
|
const after = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1228
|
-
(0,
|
|
1229
|
-
(0,
|
|
1230
|
-
(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();
|
|
1231
1617
|
});
|
|
1232
|
-
(0,
|
|
1618
|
+
(0, import_vitest9.it)("filter form: empty filter unblocks every blocked stream", async () => {
|
|
1233
1619
|
const tag = uid();
|
|
1234
1620
|
const s1 = `unblock-empty-${tag}-a`;
|
|
1235
1621
|
const s2 = `unblock-empty-${tag}-b`;
|
|
@@ -1253,9 +1639,9 @@ var runStoreTck = (options) => {
|
|
|
1253
1639
|
const count = await store.unblock({
|
|
1254
1640
|
stream: `^unblock-empty-${tag}-`
|
|
1255
1641
|
});
|
|
1256
|
-
(0,
|
|
1642
|
+
(0, import_vitest9.expect)(count).toBe(2);
|
|
1257
1643
|
});
|
|
1258
|
-
(0,
|
|
1644
|
+
(0, import_vitest9.it)("filter form: explicit blocked:false matches nothing", async () => {
|
|
1259
1645
|
const tag = uid();
|
|
1260
1646
|
const s = `unblock-blocked-false-${tag}`;
|
|
1261
1647
|
await store.subscribe([{ stream: s }]);
|
|
@@ -1264,7 +1650,7 @@ var runStoreTck = (options) => {
|
|
|
1264
1650
|
[inc(1)],
|
|
1265
1651
|
make_meta({ stream: s })
|
|
1266
1652
|
);
|
|
1267
|
-
(0,
|
|
1653
|
+
(0, import_vitest9.expect)(
|
|
1268
1654
|
await store.unblock({
|
|
1269
1655
|
stream: `^unblock-blocked-false-${tag}`,
|
|
1270
1656
|
blocked: false
|
|
@@ -1272,8 +1658,8 @@ var runStoreTck = (options) => {
|
|
|
1272
1658
|
).toBe(0);
|
|
1273
1659
|
});
|
|
1274
1660
|
});
|
|
1275
|
-
(0,
|
|
1276
|
-
(0,
|
|
1661
|
+
(0, import_vitest9.describe)("reset filter form", () => {
|
|
1662
|
+
(0, import_vitest9.it)("resets streams matching a stream pattern", async () => {
|
|
1277
1663
|
const tag = uid();
|
|
1278
1664
|
const s1 = `reset-filter-${tag}-a`;
|
|
1279
1665
|
const s2 = `reset-filter-${tag}-b`;
|
|
@@ -1304,7 +1690,7 @@ var runStoreTck = (options) => {
|
|
|
1304
1690
|
);
|
|
1305
1691
|
await store.ack(mine.map((l) => ({ ...l, at: l.at + 100 })));
|
|
1306
1692
|
const count = await store.reset({ stream: `^reset-filter-${tag}-` });
|
|
1307
|
-
(0,
|
|
1693
|
+
(0, import_vitest9.expect)(count).toBe(2);
|
|
1308
1694
|
const position_for = async (name) => {
|
|
1309
1695
|
let at = null;
|
|
1310
1696
|
await store.query_streams(
|
|
@@ -1315,11 +1701,11 @@ var runStoreTck = (options) => {
|
|
|
1315
1701
|
);
|
|
1316
1702
|
return at;
|
|
1317
1703
|
};
|
|
1318
|
-
(0,
|
|
1319
|
-
(0,
|
|
1320
|
-
(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);
|
|
1321
1707
|
});
|
|
1322
|
-
(0,
|
|
1708
|
+
(0, import_vitest9.it)("filter form: resets only blocked streams when blocked:true", async () => {
|
|
1323
1709
|
const tag = uid();
|
|
1324
1710
|
const s1 = `reset-blocked-${tag}-blocked`;
|
|
1325
1711
|
const s2 = `reset-blocked-${tag}-fine`;
|
|
@@ -1342,11 +1728,11 @@ var runStoreTck = (options) => {
|
|
|
1342
1728
|
stream: `^reset-blocked-${tag}-`,
|
|
1343
1729
|
blocked: true
|
|
1344
1730
|
});
|
|
1345
|
-
(0,
|
|
1731
|
+
(0, import_vitest9.expect)(count).toBe(1);
|
|
1346
1732
|
});
|
|
1347
1733
|
});
|
|
1348
|
-
(0,
|
|
1349
|
-
(0,
|
|
1734
|
+
(0, import_vitest9.describe)("prioritize", () => {
|
|
1735
|
+
(0, import_vitest9.it)("sets priority directly, overriding subscribe's max() rule", async () => {
|
|
1350
1736
|
const tag = uid();
|
|
1351
1737
|
const s1 = `pri-${tag}-a`;
|
|
1352
1738
|
const s2 = `pri-${tag}-b`;
|
|
@@ -1358,7 +1744,7 @@ var runStoreTck = (options) => {
|
|
|
1358
1744
|
{ stream: s1, stream_exact: true },
|
|
1359
1745
|
3
|
|
1360
1746
|
);
|
|
1361
|
-
(0,
|
|
1747
|
+
(0, import_vitest9.expect)(updated).toBe(1);
|
|
1362
1748
|
const got1 = {};
|
|
1363
1749
|
const got2 = {};
|
|
1364
1750
|
await store.query_streams(
|
|
@@ -1368,12 +1754,12 @@ var runStoreTck = (options) => {
|
|
|
1368
1754
|
},
|
|
1369
1755
|
{ stream: `pri-${tag}-.*`, limit: 100 }
|
|
1370
1756
|
);
|
|
1371
|
-
(0,
|
|
1372
|
-
(0,
|
|
1757
|
+
(0, import_vitest9.expect)(got1.priority).toBe(3);
|
|
1758
|
+
(0, import_vitest9.expect)(got2.priority).toBe(5);
|
|
1373
1759
|
});
|
|
1374
1760
|
});
|
|
1375
|
-
(0,
|
|
1376
|
-
(0,
|
|
1761
|
+
(0, import_vitest9.describe)("lanes", () => {
|
|
1762
|
+
(0, import_vitest9.it)("subscribe defaults lane to 'default' when omitted", async () => {
|
|
1377
1763
|
const s = `lane-default-${uid()}`;
|
|
1378
1764
|
await store.subscribe([{ stream: s }]);
|
|
1379
1765
|
const seen = [];
|
|
@@ -1381,9 +1767,9 @@ var runStoreTck = (options) => {
|
|
|
1381
1767
|
stream: s,
|
|
1382
1768
|
stream_exact: true
|
|
1383
1769
|
});
|
|
1384
|
-
(0,
|
|
1770
|
+
(0, import_vitest9.expect)(seen).toEqual(["default"]);
|
|
1385
1771
|
});
|
|
1386
|
-
(0,
|
|
1772
|
+
(0, import_vitest9.it)("subscribe records the lane passed in", async () => {
|
|
1387
1773
|
const s = `lane-set-${uid()}`;
|
|
1388
1774
|
await store.subscribe([{ stream: s, lane: "slow" }]);
|
|
1389
1775
|
const seen = [];
|
|
@@ -1391,9 +1777,9 @@ var runStoreTck = (options) => {
|
|
|
1391
1777
|
stream: s,
|
|
1392
1778
|
stream_exact: true
|
|
1393
1779
|
});
|
|
1394
|
-
(0,
|
|
1780
|
+
(0, import_vitest9.expect)(seen).toEqual(["slow"]);
|
|
1395
1781
|
});
|
|
1396
|
-
(0,
|
|
1782
|
+
(0, import_vitest9.it)("subscribe re-lanes existing streams on subsequent calls", async () => {
|
|
1397
1783
|
const s = `lane-upsert-${uid()}`;
|
|
1398
1784
|
await store.subscribe([{ stream: s, lane: "slow" }]);
|
|
1399
1785
|
await store.subscribe([{ stream: s, lane: "fast" }]);
|
|
@@ -1402,9 +1788,9 @@ var runStoreTck = (options) => {
|
|
|
1402
1788
|
stream: s,
|
|
1403
1789
|
stream_exact: true
|
|
1404
1790
|
});
|
|
1405
|
-
(0,
|
|
1791
|
+
(0, import_vitest9.expect)(seen).toEqual(["fast"]);
|
|
1406
1792
|
});
|
|
1407
|
-
(0,
|
|
1793
|
+
(0, import_vitest9.it)("claim() filters by lane when supplied and returns lane on the Lease", async () => {
|
|
1408
1794
|
const tag = uid();
|
|
1409
1795
|
const src1 = `lane-claim-src1-${tag}`;
|
|
1410
1796
|
const src2 = `lane-claim-src2-${tag}`;
|
|
@@ -1428,19 +1814,19 @@ var runStoreTck = (options) => {
|
|
|
1428
1814
|
const slow_mine = slow.filter(
|
|
1429
1815
|
(l) => l.stream === sub_default || l.stream === sub_slow
|
|
1430
1816
|
);
|
|
1431
|
-
(0,
|
|
1432
|
-
(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");
|
|
1433
1819
|
await store.ack(slow_mine.map((l) => ({ ...l, at: l.at + 1 })));
|
|
1434
1820
|
const all = await store.claim(50, 0, `w-all-${tag}`, 1e3);
|
|
1435
1821
|
const all_mine = all.filter((l) => l.stream === sub_default || l.stream === sub_slow).map((l) => ({ stream: l.stream, lane: l.lane }));
|
|
1436
|
-
(0,
|
|
1437
|
-
|
|
1822
|
+
(0, import_vitest9.expect)(all_mine).toEqual(
|
|
1823
|
+
import_vitest9.expect.arrayContaining([
|
|
1438
1824
|
{ stream: sub_default, lane: "default" },
|
|
1439
1825
|
{ stream: sub_slow, lane: "slow" }
|
|
1440
1826
|
])
|
|
1441
1827
|
);
|
|
1442
1828
|
});
|
|
1443
|
-
(0,
|
|
1829
|
+
(0, import_vitest9.it)("query_streams filters by lane", async () => {
|
|
1444
1830
|
const tag = uid();
|
|
1445
1831
|
const a = `lane-q-a-${tag}`;
|
|
1446
1832
|
const b = `lane-q-b-${tag}`;
|
|
@@ -1456,9 +1842,9 @@ var runStoreTck = (options) => {
|
|
|
1456
1842
|
stream: `lane-q-.*-${tag}`,
|
|
1457
1843
|
limit: 100
|
|
1458
1844
|
});
|
|
1459
|
-
(0,
|
|
1845
|
+
(0, import_vitest9.expect)(seen.sort()).toEqual([a, c]);
|
|
1460
1846
|
});
|
|
1461
|
-
(0,
|
|
1847
|
+
(0, import_vitest9.it)("prioritize filters by lane", async () => {
|
|
1462
1848
|
const tag = uid();
|
|
1463
1849
|
const a = `lane-pri-a-${tag}`;
|
|
1464
1850
|
const b = `lane-pri-b-${tag}`;
|
|
@@ -1467,16 +1853,16 @@ var runStoreTck = (options) => {
|
|
|
1467
1853
|
{ stream: b, lane: `pfast-${tag}` }
|
|
1468
1854
|
]);
|
|
1469
1855
|
const updated = await store.prioritize({ lane: `pslow-${tag}` }, 7);
|
|
1470
|
-
(0,
|
|
1856
|
+
(0, import_vitest9.expect)(updated).toBe(1);
|
|
1471
1857
|
const seen = /* @__PURE__ */ new Map();
|
|
1472
1858
|
await store.query_streams((p) => seen.set(p.stream, p.priority), {
|
|
1473
1859
|
stream: `lane-pri-.*-${tag}`,
|
|
1474
1860
|
limit: 100
|
|
1475
1861
|
});
|
|
1476
|
-
(0,
|
|
1477
|
-
(0,
|
|
1862
|
+
(0, import_vitest9.expect)(seen.get(a)).toBe(7);
|
|
1863
|
+
(0, import_vitest9.expect)(seen.get(b)).toBe(0);
|
|
1478
1864
|
});
|
|
1479
|
-
(0,
|
|
1865
|
+
(0, import_vitest9.it)("reset filters by lane", async () => {
|
|
1480
1866
|
const tag = uid();
|
|
1481
1867
|
const src = `lane-reset-src-${tag}`;
|
|
1482
1868
|
const a = `lane-reset-a-${tag}`;
|
|
@@ -1494,7 +1880,7 @@ var runStoreTck = (options) => {
|
|
|
1494
1880
|
const mine = leases.filter((l) => l.stream === a || l.stream === b);
|
|
1495
1881
|
await store.ack(mine.map((l) => ({ ...l, at: l.at + 1 })));
|
|
1496
1882
|
const count = await store.reset({ lane: `rslow-${tag}` });
|
|
1497
|
-
(0,
|
|
1883
|
+
(0, import_vitest9.expect)(count).toBe(1);
|
|
1498
1884
|
const ats = /* @__PURE__ */ new Map();
|
|
1499
1885
|
for (const name of [a, b]) {
|
|
1500
1886
|
await store.query_streams((p) => ats.set(p.stream, p.at), {
|
|
@@ -1502,10 +1888,10 @@ var runStoreTck = (options) => {
|
|
|
1502
1888
|
stream_exact: true
|
|
1503
1889
|
});
|
|
1504
1890
|
}
|
|
1505
|
-
(0,
|
|
1506
|
-
(0,
|
|
1891
|
+
(0, import_vitest9.expect)(ats.get(a)).toBe(-1);
|
|
1892
|
+
(0, import_vitest9.expect)(ats.get(b)).toBeGreaterThanOrEqual(0);
|
|
1507
1893
|
});
|
|
1508
|
-
(0,
|
|
1894
|
+
(0, import_vitest9.it)("unblock filters by lane", async () => {
|
|
1509
1895
|
const tag = uid();
|
|
1510
1896
|
const src = `lane-ub-src-${tag}`;
|
|
1511
1897
|
const a = `lane-ub-a-${tag}`;
|
|
@@ -1523,7 +1909,7 @@ var runStoreTck = (options) => {
|
|
|
1523
1909
|
const mine = leases.filter((l) => l.stream === a || l.stream === b);
|
|
1524
1910
|
await store.block(mine.map((l) => ({ ...l, error: "boom" })));
|
|
1525
1911
|
const count = await store.unblock({ lane: `uslow-${tag}` });
|
|
1526
|
-
(0,
|
|
1912
|
+
(0, import_vitest9.expect)(count).toBe(1);
|
|
1527
1913
|
const blocked = /* @__PURE__ */ new Map();
|
|
1528
1914
|
for (const name of [a, b]) {
|
|
1529
1915
|
await store.query_streams((p) => blocked.set(p.stream, p.blocked), {
|
|
@@ -1531,12 +1917,12 @@ var runStoreTck = (options) => {
|
|
|
1531
1917
|
stream_exact: true
|
|
1532
1918
|
});
|
|
1533
1919
|
}
|
|
1534
|
-
(0,
|
|
1535
|
-
(0,
|
|
1920
|
+
(0, import_vitest9.expect)(blocked.get(a)).toBe(false);
|
|
1921
|
+
(0, import_vitest9.expect)(blocked.get(b)).toBe(true);
|
|
1536
1922
|
});
|
|
1537
1923
|
});
|
|
1538
|
-
(0,
|
|
1539
|
-
(0,
|
|
1924
|
+
(0, import_vitest9.describe)("truncate", () => {
|
|
1925
|
+
(0, import_vitest9.it)("seeds a tombstone when no snapshot is provided", async () => {
|
|
1540
1926
|
const s = `trunc-tomb-${uid()}`;
|
|
1541
1927
|
await store.commit(
|
|
1542
1928
|
s,
|
|
@@ -1544,7 +1930,7 @@ var runStoreTck = (options) => {
|
|
|
1544
1930
|
make_meta({ stream: s })
|
|
1545
1931
|
);
|
|
1546
1932
|
const result = await store.truncate([{ stream: s }]);
|
|
1547
|
-
(0,
|
|
1933
|
+
(0, import_vitest9.expect)(result.get(s)?.deleted).toBe(2);
|
|
1548
1934
|
const remaining = [];
|
|
1549
1935
|
await store.query(
|
|
1550
1936
|
(e) => {
|
|
@@ -1552,12 +1938,12 @@ var runStoreTck = (options) => {
|
|
|
1552
1938
|
},
|
|
1553
1939
|
{ stream: s, stream_exact: true }
|
|
1554
1940
|
);
|
|
1555
|
-
(0,
|
|
1556
|
-
(0,
|
|
1941
|
+
(0, import_vitest9.expect)(remaining).toHaveLength(1);
|
|
1942
|
+
(0, import_vitest9.expect)(remaining[0].name).toBe(
|
|
1557
1943
|
"__tombstone__"
|
|
1558
1944
|
);
|
|
1559
1945
|
});
|
|
1560
|
-
(0,
|
|
1946
|
+
(0, import_vitest9.it)("seeds a snapshot when one is provided", async () => {
|
|
1561
1947
|
const s = `trunc-snap-${uid()}`;
|
|
1562
1948
|
await store.commit(
|
|
1563
1949
|
s,
|
|
@@ -1567,7 +1953,7 @@ var runStoreTck = (options) => {
|
|
|
1567
1953
|
const result = await store.truncate([
|
|
1568
1954
|
{ stream: s, snapshot: { count: 7 } }
|
|
1569
1955
|
]);
|
|
1570
|
-
(0,
|
|
1956
|
+
(0, import_vitest9.expect)(result.get(s)?.deleted).toBe(1);
|
|
1571
1957
|
const remaining = [];
|
|
1572
1958
|
await store.query(
|
|
1573
1959
|
(e) => {
|
|
@@ -1575,24 +1961,24 @@ var runStoreTck = (options) => {
|
|
|
1575
1961
|
},
|
|
1576
1962
|
{ stream: s, stream_exact: true, with_snaps: true }
|
|
1577
1963
|
);
|
|
1578
|
-
(0,
|
|
1579
|
-
(0,
|
|
1964
|
+
(0, import_vitest9.expect)(remaining).toHaveLength(1);
|
|
1965
|
+
(0, import_vitest9.expect)(remaining[0].name).toBe(
|
|
1580
1966
|
"__snapshot__"
|
|
1581
1967
|
);
|
|
1582
|
-
(0,
|
|
1968
|
+
(0, import_vitest9.expect)(remaining[0].data).toEqual({ count: 7 });
|
|
1583
1969
|
});
|
|
1584
|
-
(0,
|
|
1970
|
+
(0, import_vitest9.it)("returns an empty map for empty input", async () => {
|
|
1585
1971
|
const result = await store.truncate([]);
|
|
1586
|
-
(0,
|
|
1972
|
+
(0, import_vitest9.expect)(result.size).toBe(0);
|
|
1587
1973
|
});
|
|
1588
|
-
(0,
|
|
1974
|
+
(0, import_vitest9.it)("returns 0 deleted for streams that don't exist", async () => {
|
|
1589
1975
|
const s = `trunc-missing-${uid()}`;
|
|
1590
1976
|
const result = await store.truncate([{ stream: s }]);
|
|
1591
|
-
(0,
|
|
1977
|
+
(0, import_vitest9.expect)(result.get(s)?.deleted).toBe(0);
|
|
1592
1978
|
});
|
|
1593
1979
|
});
|
|
1594
|
-
(0,
|
|
1595
|
-
(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 () => {
|
|
1596
1982
|
const tag = uid();
|
|
1597
1983
|
const proj1 = `qs-${tag}-projection-tickets`;
|
|
1598
1984
|
const proj2 = `qs-${tag}-projection-users`;
|
|
@@ -1611,37 +1997,37 @@ var runStoreTck = (options) => {
|
|
|
1611
1997
|
(p) => all.push({ stream: p.stream, source: p.source }),
|
|
1612
1998
|
{ stream: `qs-${tag}-.*` }
|
|
1613
1999
|
);
|
|
1614
|
-
(0,
|
|
1615
|
-
(0,
|
|
1616
|
-
(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(
|
|
1617
2003
|
[proj1, proj2, dyn1, dyn2].sort()
|
|
1618
2004
|
);
|
|
1619
2005
|
const projections = [];
|
|
1620
2006
|
await store.query_streams((p) => projections.push(p.stream), {
|
|
1621
2007
|
stream: `qs-${tag}-projection-.*`
|
|
1622
2008
|
});
|
|
1623
|
-
(0,
|
|
2009
|
+
(0, import_vitest9.expect)(projections.sort()).toEqual([proj1, proj2].sort());
|
|
1624
2010
|
const exact = [];
|
|
1625
2011
|
await store.query_streams((p) => exact.push(p.stream), {
|
|
1626
2012
|
stream: dyn1,
|
|
1627
2013
|
stream_exact: true
|
|
1628
2014
|
});
|
|
1629
|
-
(0,
|
|
2015
|
+
(0, import_vitest9.expect)(exact).toEqual([dyn1]);
|
|
1630
2016
|
const by_source = [];
|
|
1631
2017
|
await store.query_streams((p) => by_source.push(p.stream), {
|
|
1632
2018
|
stream: `qs-${tag}-.*`,
|
|
1633
2019
|
source: `qs-${tag}-src-.*`
|
|
1634
2020
|
});
|
|
1635
|
-
(0,
|
|
2021
|
+
(0, import_vitest9.expect)(by_source.sort()).toEqual([dyn1, dyn2].sort());
|
|
1636
2022
|
const exact_source = [];
|
|
1637
2023
|
await store.query_streams((p) => exact_source.push(p.stream), {
|
|
1638
2024
|
stream: `qs-${tag}-.*`,
|
|
1639
2025
|
source: src2,
|
|
1640
2026
|
source_exact: true
|
|
1641
2027
|
});
|
|
1642
|
-
(0,
|
|
2028
|
+
(0, import_vitest9.expect)(exact_source).toEqual([dyn2]);
|
|
1643
2029
|
});
|
|
1644
|
-
(0,
|
|
2030
|
+
(0, import_vitest9.it)("paginates with limit + after (keyset)", async () => {
|
|
1645
2031
|
const tag = uid();
|
|
1646
2032
|
const streams = [
|
|
1647
2033
|
`qp-${tag}-a`,
|
|
@@ -1655,17 +2041,17 @@ var runStoreTck = (options) => {
|
|
|
1655
2041
|
stream: `qp-${tag}-.*`,
|
|
1656
2042
|
limit: 2
|
|
1657
2043
|
});
|
|
1658
|
-
(0,
|
|
2044
|
+
(0, import_vitest9.expect)(page1).toHaveLength(2);
|
|
1659
2045
|
const page2 = [];
|
|
1660
2046
|
await store.query_streams((p) => page2.push(p.stream), {
|
|
1661
2047
|
stream: `qp-${tag}-.*`,
|
|
1662
2048
|
limit: 2,
|
|
1663
2049
|
after: page1.at(-1)
|
|
1664
2050
|
});
|
|
1665
|
-
(0,
|
|
1666
|
-
(0,
|
|
2051
|
+
(0, import_vitest9.expect)(page2).toHaveLength(2);
|
|
2052
|
+
(0, import_vitest9.expect)([...page1, ...page2].sort()).toEqual([...streams].sort());
|
|
1667
2053
|
});
|
|
1668
|
-
(0,
|
|
2054
|
+
(0, import_vitest9.it)("filters by blocked status", async () => {
|
|
1669
2055
|
const tag = uid();
|
|
1670
2056
|
const s = `qb-${tag}`;
|
|
1671
2057
|
const sibling = `qb-${tag}-other`;
|
|
@@ -1685,18 +2071,18 @@ var runStoreTck = (options) => {
|
|
|
1685
2071
|
(p) => blocked.push({ stream: p.stream, error: p.error }),
|
|
1686
2072
|
{ stream: `qb-${tag}.*`, blocked: true }
|
|
1687
2073
|
);
|
|
1688
|
-
(0,
|
|
1689
|
-
(0,
|
|
2074
|
+
(0, import_vitest9.expect)(blocked).toHaveLength(1);
|
|
2075
|
+
(0, import_vitest9.expect)(blocked[0].error).toBe("boom");
|
|
1690
2076
|
const unblocked = [];
|
|
1691
2077
|
await store.query_streams((p) => unblocked.push(p.stream), {
|
|
1692
2078
|
stream: `qb-${tag}.*`,
|
|
1693
2079
|
blocked: false
|
|
1694
2080
|
});
|
|
1695
|
-
(0,
|
|
2081
|
+
(0, import_vitest9.expect)(unblocked).toEqual([sibling]);
|
|
1696
2082
|
});
|
|
1697
2083
|
});
|
|
1698
|
-
(0,
|
|
1699
|
-
(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 () => {
|
|
1700
2086
|
const tag = uid();
|
|
1701
2087
|
const sA = `qst-${tag}-a`;
|
|
1702
2088
|
const sB = `qst-${tag}-b`;
|
|
@@ -1717,18 +2103,18 @@ var runStoreTck = (options) => {
|
|
|
1717
2103
|
make_meta({ stream: sUnasked })
|
|
1718
2104
|
);
|
|
1719
2105
|
const stats = await store.query_stats([sA, sB]);
|
|
1720
|
-
(0,
|
|
1721
|
-
(0,
|
|
1722
|
-
(0,
|
|
1723
|
-
(0,
|
|
1724
|
-
(0,
|
|
1725
|
-
(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);
|
|
1726
2112
|
const empty = await store.query_stats([]);
|
|
1727
|
-
(0,
|
|
2113
|
+
(0, import_vitest9.expect)(empty.size).toBe(0);
|
|
1728
2114
|
const unknown = await store.query_stats([`qst-${tag}-missing`]);
|
|
1729
|
-
(0,
|
|
2115
|
+
(0, import_vitest9.expect)(unknown.size).toBe(0);
|
|
1730
2116
|
});
|
|
1731
|
-
(0,
|
|
2117
|
+
(0, import_vitest9.it)("tail returns the earliest event per stream", async () => {
|
|
1732
2118
|
const tag = uid();
|
|
1733
2119
|
const s = `qst-tail-${tag}`;
|
|
1734
2120
|
await store.commit(
|
|
@@ -1750,12 +2136,12 @@ var runStoreTck = (options) => {
|
|
|
1750
2136
|
tail: true
|
|
1751
2137
|
});
|
|
1752
2138
|
const r = stats.get(s);
|
|
1753
|
-
(0,
|
|
1754
|
-
(0,
|
|
1755
|
-
(0,
|
|
1756
|
-
(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);
|
|
1757
2143
|
});
|
|
1758
|
-
(0,
|
|
2144
|
+
(0, import_vitest9.it)("count + names \u2014 full aggregates including framework markers", async () => {
|
|
1759
2145
|
const tag = uid();
|
|
1760
2146
|
const s = `qst-cn-${tag}`;
|
|
1761
2147
|
await store.commit(
|
|
@@ -1774,13 +2160,13 @@ var runStoreTck = (options) => {
|
|
|
1774
2160
|
names: true
|
|
1775
2161
|
});
|
|
1776
2162
|
const r = stats.get(s);
|
|
1777
|
-
(0,
|
|
1778
|
-
(0,
|
|
1779
|
-
(0,
|
|
1780
|
-
(0,
|
|
1781
|
-
(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);
|
|
1782
2168
|
});
|
|
1783
|
-
(0,
|
|
2169
|
+
(0, import_vitest9.it)("exclude shifts head past filtered events; stream absent when all filtered", async () => {
|
|
1784
2170
|
const tag = uid();
|
|
1785
2171
|
const s = `qst-excl-${tag}`;
|
|
1786
2172
|
const sAllOut = `qst-allout-${tag}`;
|
|
@@ -1795,23 +2181,23 @@ var runStoreTck = (options) => {
|
|
|
1795
2181
|
make_meta({ stream: sAllOut })
|
|
1796
2182
|
);
|
|
1797
2183
|
const all = await store.query_stats([s]);
|
|
1798
|
-
(0,
|
|
1799
|
-
(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);
|
|
1800
2186
|
const excl = await store.query_stats([s], {
|
|
1801
2187
|
exclude: ["Incremented"]
|
|
1802
2188
|
});
|
|
1803
|
-
(0,
|
|
1804
|
-
(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);
|
|
1805
2191
|
const wipe = await store.query_stats([sAllOut], {
|
|
1806
2192
|
exclude: ["Incremented", "Decremented", "Reset"]
|
|
1807
2193
|
});
|
|
1808
|
-
(0,
|
|
2194
|
+
(0, import_vitest9.expect)(wipe.has(sAllOut)).toBe(false);
|
|
1809
2195
|
const no_tomb = await store.query_stats([s], {
|
|
1810
|
-
exclude: [
|
|
2196
|
+
exclude: [import_act2.TOMBSTONE_EVENT]
|
|
1811
2197
|
});
|
|
1812
|
-
(0,
|
|
2198
|
+
(0, import_vitest9.expect)(no_tomb.get(s)?.head.name).toBe("Incremented");
|
|
1813
2199
|
});
|
|
1814
|
-
(0,
|
|
2200
|
+
(0, import_vitest9.it)("before \u2014 time travel narrows head/tail/count", async () => {
|
|
1815
2201
|
const tag = uid();
|
|
1816
2202
|
const s = `qst-tt-${tag}`;
|
|
1817
2203
|
const c1 = await store.commit(
|
|
@@ -1836,15 +2222,15 @@ var runStoreTck = (options) => {
|
|
|
1836
2222
|
before
|
|
1837
2223
|
});
|
|
1838
2224
|
const r = stats.get(s);
|
|
1839
|
-
(0,
|
|
1840
|
-
(0,
|
|
1841
|
-
(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);
|
|
1842
2228
|
const empty = await store.query_stats([s], {
|
|
1843
2229
|
before: 0
|
|
1844
2230
|
});
|
|
1845
|
-
(0,
|
|
2231
|
+
(0, import_vitest9.expect)(empty.has(s)).toBe(false);
|
|
1846
2232
|
});
|
|
1847
|
-
(0,
|
|
2233
|
+
(0, import_vitest9.it)("filter form \u2014 stream regex, stream_exact, empty {} match", async () => {
|
|
1848
2234
|
const tag = uid();
|
|
1849
2235
|
const sA = `qsf-${tag}-orders-1`;
|
|
1850
2236
|
const sB = `qsf-${tag}-orders-2`;
|
|
@@ -1867,18 +2253,18 @@ var runStoreTck = (options) => {
|
|
|
1867
2253
|
const orders = await store.query_stats({
|
|
1868
2254
|
stream: `^qsf-${tag}-orders-`
|
|
1869
2255
|
});
|
|
1870
|
-
(0,
|
|
2256
|
+
(0, import_vitest9.expect)([...orders.keys()].sort()).toEqual([sA, sB].sort());
|
|
1871
2257
|
const exact = await store.query_stats({
|
|
1872
2258
|
stream: sA,
|
|
1873
2259
|
stream_exact: true
|
|
1874
2260
|
});
|
|
1875
|
-
(0,
|
|
2261
|
+
(0, import_vitest9.expect)([...exact.keys()]).toEqual([sA]);
|
|
1876
2262
|
const all = await store.query_stats({
|
|
1877
2263
|
stream: `^qsf-${tag}-`
|
|
1878
2264
|
});
|
|
1879
|
-
(0,
|
|
2265
|
+
(0, import_vitest9.expect)([...all.keys()].sort()).toEqual([sA, sB, sOther].sort());
|
|
1880
2266
|
});
|
|
1881
|
-
(0,
|
|
2267
|
+
(0, import_vitest9.it)("compose with query_streams for subscription-level filters", async () => {
|
|
1882
2268
|
const tag = uid();
|
|
1883
2269
|
const a = `qsc-${tag}-a`;
|
|
1884
2270
|
const b = `qsc-${tag}-b`;
|
|
@@ -1895,7 +2281,7 @@ var runStoreTck = (options) => {
|
|
|
1895
2281
|
);
|
|
1896
2282
|
const leased = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1897
2283
|
const mine = leased.find((l) => l.stream === a);
|
|
1898
|
-
(0,
|
|
2284
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1899
2285
|
const others = leased.filter((l) => l.stream !== a);
|
|
1900
2286
|
await store.ack(others);
|
|
1901
2287
|
await store.block([{ ...mine, error: "boom" }]);
|
|
@@ -1904,12 +2290,12 @@ var runStoreTck = (options) => {
|
|
|
1904
2290
|
stream: `^qsc-${tag}-`,
|
|
1905
2291
|
blocked: true
|
|
1906
2292
|
});
|
|
1907
|
-
(0,
|
|
2293
|
+
(0, import_vitest9.expect)(blocked_names).toEqual([a]);
|
|
1908
2294
|
const stats = await store.query_stats(blocked_names);
|
|
1909
|
-
(0,
|
|
1910
|
-
(0,
|
|
2295
|
+
(0, import_vitest9.expect)(stats.get(a)?.head.name).toBe("Incremented");
|
|
2296
|
+
(0, import_vitest9.expect)(stats.has(b)).toBe(false);
|
|
1911
2297
|
});
|
|
1912
|
-
(0,
|
|
2298
|
+
(0, import_vitest9.it)("empty filter {} \u2014 matches every event-bearing stream", async () => {
|
|
1913
2299
|
const tag = uid();
|
|
1914
2300
|
const a = `qse-${tag}-a`;
|
|
1915
2301
|
const b = `qse-${tag}-b`;
|
|
@@ -1924,10 +2310,10 @@ var runStoreTck = (options) => {
|
|
|
1924
2310
|
make_meta({ stream: b })
|
|
1925
2311
|
);
|
|
1926
2312
|
const all = await store.query_stats({});
|
|
1927
|
-
(0,
|
|
1928
|
-
(0,
|
|
2313
|
+
(0, import_vitest9.expect)(all.has(a)).toBe(true);
|
|
2314
|
+
(0, import_vitest9.expect)(all.has(b)).toBe(true);
|
|
1929
2315
|
});
|
|
1930
|
-
(0,
|
|
2316
|
+
(0, import_vitest9.it)("stat-flag combinations \u2014 count-only, names-only, tail-only", async () => {
|
|
1931
2317
|
const tag = uid();
|
|
1932
2318
|
const s = `qsfl-${tag}`;
|
|
1933
2319
|
await store.commit(
|
|
@@ -1938,22 +2324,22 @@ var runStoreTck = (options) => {
|
|
|
1938
2324
|
const c = await store.query_stats([s], {
|
|
1939
2325
|
count: true
|
|
1940
2326
|
});
|
|
1941
|
-
(0,
|
|
1942
|
-
(0,
|
|
1943
|
-
(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();
|
|
1944
2330
|
const n = await store.query_stats([s], {
|
|
1945
2331
|
names: true
|
|
1946
2332
|
});
|
|
1947
|
-
(0,
|
|
1948
|
-
(0,
|
|
1949
|
-
(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();
|
|
1950
2336
|
const t = await store.query_stats([s], { tail: true });
|
|
1951
|
-
(0,
|
|
1952
|
-
(0,
|
|
1953
|
-
(0,
|
|
1954
|
-
(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();
|
|
1955
2341
|
});
|
|
1956
|
-
(0,
|
|
2342
|
+
(0, import_vitest9.it)("paginates with limit + after (keyset), ordered by stream name", async () => {
|
|
1957
2343
|
const tag = uid();
|
|
1958
2344
|
const streams = [
|
|
1959
2345
|
`qsp-${tag}-a`,
|
|
@@ -1973,28 +2359,28 @@ var runStoreTck = (options) => {
|
|
|
1973
2359
|
{ limit: 2 }
|
|
1974
2360
|
);
|
|
1975
2361
|
const k1 = [...page1.keys()];
|
|
1976
|
-
(0,
|
|
2362
|
+
(0, import_vitest9.expect)(k1).toEqual([`qsp-${tag}-a`, `qsp-${tag}-b`]);
|
|
1977
2363
|
const page2 = await store.query_stats(
|
|
1978
2364
|
{ stream: `qsp-${tag}-.*` },
|
|
1979
2365
|
{ limit: 2, after: k1.at(-1) }
|
|
1980
2366
|
);
|
|
1981
2367
|
const k2 = [...page2.keys()];
|
|
1982
|
-
(0,
|
|
2368
|
+
(0, import_vitest9.expect)(k2).toEqual([`qsp-${tag}-c`, `qsp-${tag}-d`]);
|
|
1983
2369
|
const page3 = await store.query_stats(
|
|
1984
2370
|
{ stream: `qsp-${tag}-.*` },
|
|
1985
2371
|
{ limit: 2, after: k2.at(-1) }
|
|
1986
2372
|
);
|
|
1987
|
-
(0,
|
|
2373
|
+
(0, import_vitest9.expect)(page3.size).toBe(0);
|
|
1988
2374
|
const all = await store.query_stats({
|
|
1989
2375
|
stream: `qsp-${tag}-.*`
|
|
1990
2376
|
});
|
|
1991
|
-
(0,
|
|
2377
|
+
(0, import_vitest9.expect)([...all.keys()].sort()).toEqual([...streams].sort());
|
|
1992
2378
|
});
|
|
1993
2379
|
});
|
|
1994
|
-
|
|
2380
|
+
import_vitest9.describe.skipIf(!caps.source_matches)(
|
|
1995
2381
|
"query_streams source_matches (capability)",
|
|
1996
2382
|
() => {
|
|
1997
|
-
(0,
|
|
2383
|
+
(0, import_vitest9.it)("returns only subscriptions whose source pattern matches a name", async () => {
|
|
1998
2384
|
const tag = uid();
|
|
1999
2385
|
const subConcreteA = `sm-${tag}-sub-a`;
|
|
2000
2386
|
const subConcreteB = `sm-${tag}-sub-b`;
|
|
@@ -2015,7 +2401,7 @@ var runStoreTck = (options) => {
|
|
|
2015
2401
|
stream: `sm-${tag}-sub-.*`,
|
|
2016
2402
|
source_matches: [srcA]
|
|
2017
2403
|
});
|
|
2018
|
-
(0,
|
|
2404
|
+
(0, import_vitest9.expect)(matched.sort()).toEqual(
|
|
2019
2405
|
[subConcreteA, subRegex, subNoSource].sort()
|
|
2020
2406
|
);
|
|
2021
2407
|
const none = [];
|
|
@@ -2023,20 +2409,20 @@ var runStoreTck = (options) => {
|
|
|
2023
2409
|
stream: `sm-${tag}-sub-.*`,
|
|
2024
2410
|
source_matches: [`sm-${tag}-unrelated`]
|
|
2025
2411
|
});
|
|
2026
|
-
(0,
|
|
2412
|
+
(0, import_vitest9.expect)(none).toEqual([subNoSource]);
|
|
2027
2413
|
const both = [];
|
|
2028
2414
|
await store.query_streams((p) => both.push(p.stream), {
|
|
2029
2415
|
stream: `sm-${tag}-sub-.*`,
|
|
2030
2416
|
source_matches: [srcA, srcB]
|
|
2031
2417
|
});
|
|
2032
|
-
(0,
|
|
2418
|
+
(0, import_vitest9.expect)(both.sort()).toEqual(
|
|
2033
2419
|
[subConcreteA, subConcreteB, subRegex, subNoSource].sort()
|
|
2034
2420
|
);
|
|
2035
2421
|
});
|
|
2036
2422
|
}
|
|
2037
2423
|
);
|
|
2038
|
-
(0,
|
|
2039
|
-
(0,
|
|
2424
|
+
(0, import_vitest9.describe)("query_streams anchor contract", () => {
|
|
2425
|
+
(0, import_vitest9.it)("plain regex without anchors is a substring match", async () => {
|
|
2040
2426
|
const tag = uid();
|
|
2041
2427
|
const inner = `qsr-${tag}-inner`;
|
|
2042
2428
|
const longer = `qsr-${tag}-inner-extra`;
|
|
@@ -2050,9 +2436,9 @@ var runStoreTck = (options) => {
|
|
|
2050
2436
|
await store.query_streams((p) => seen.push(p.stream), {
|
|
2051
2437
|
stream: `qsr-${tag}-inner`
|
|
2052
2438
|
});
|
|
2053
|
-
(0,
|
|
2439
|
+
(0, import_vitest9.expect)(seen.sort()).toEqual([inner, longer].sort());
|
|
2054
2440
|
});
|
|
2055
|
-
(0,
|
|
2441
|
+
(0, import_vitest9.it)("caller-anchored `^name$` matches only the whole string", async () => {
|
|
2056
2442
|
const tag = uid();
|
|
2057
2443
|
const inner = `qsr-${tag}-anchor`;
|
|
2058
2444
|
const longer = `qsr-${tag}-anchor-extra`;
|
|
@@ -2061,9 +2447,9 @@ var runStoreTck = (options) => {
|
|
|
2061
2447
|
await store.query_streams((p) => seen.push(p.stream), {
|
|
2062
2448
|
stream: `^qsr-${tag}-anchor$`
|
|
2063
2449
|
});
|
|
2064
|
-
(0,
|
|
2450
|
+
(0, import_vitest9.expect)(seen).toEqual([inner]);
|
|
2065
2451
|
});
|
|
2066
|
-
(0,
|
|
2452
|
+
(0, import_vitest9.it)("caller-anchored `^prefix` matches by prefix", async () => {
|
|
2067
2453
|
const tag = uid();
|
|
2068
2454
|
const a = `qsr-${tag}-pfx-a`;
|
|
2069
2455
|
const b = `qsr-${tag}-pfx-b`;
|
|
@@ -2077,11 +2463,11 @@ var runStoreTck = (options) => {
|
|
|
2077
2463
|
await store.query_streams((p) => seen.push(p.stream), {
|
|
2078
2464
|
stream: `^qsr-${tag}-pfx-`
|
|
2079
2465
|
});
|
|
2080
|
-
(0,
|
|
2466
|
+
(0, import_vitest9.expect)(seen.sort()).toEqual([a, b].sort());
|
|
2081
2467
|
});
|
|
2082
2468
|
});
|
|
2083
|
-
(0,
|
|
2084
|
-
(0,
|
|
2469
|
+
(0, import_vitest9.describe)("prioritize anchor contract", () => {
|
|
2470
|
+
(0, import_vitest9.it)("caller-anchored `^name$` filter matches only the whole string", async () => {
|
|
2085
2471
|
const tag = uid();
|
|
2086
2472
|
const inner = `pr-${tag}-anchor`;
|
|
2087
2473
|
const longer = `pr-${tag}-anchor-extra`;
|
|
@@ -2093,17 +2479,17 @@ var runStoreTck = (options) => {
|
|
|
2093
2479
|
{ stream: `^pr-${tag}-anchor$` },
|
|
2094
2480
|
7
|
|
2095
2481
|
);
|
|
2096
|
-
(0,
|
|
2482
|
+
(0, import_vitest9.expect)(updated).toBe(1);
|
|
2097
2483
|
const seen = /* @__PURE__ */ new Map();
|
|
2098
2484
|
await store.query_streams((p) => seen.set(p.stream, p.priority), {
|
|
2099
2485
|
stream: `pr-${tag}-anchor`
|
|
2100
2486
|
});
|
|
2101
|
-
(0,
|
|
2102
|
-
(0,
|
|
2487
|
+
(0, import_vitest9.expect)(seen.get(inner)).toBe(7);
|
|
2488
|
+
(0, import_vitest9.expect)(seen.get(longer)).toBe(0);
|
|
2103
2489
|
});
|
|
2104
2490
|
});
|
|
2105
|
-
(0,
|
|
2106
|
-
(0,
|
|
2491
|
+
(0, import_vitest9.describe)("query_streams head", () => {
|
|
2492
|
+
(0, import_vitest9.it)("maxEventId tracks the highest committed id", async () => {
|
|
2107
2493
|
const s = `head-${uid()}`;
|
|
2108
2494
|
await store.subscribe([{ stream: s }]);
|
|
2109
2495
|
await store.commit(
|
|
@@ -2116,21 +2502,21 @@ var runStoreTck = (options) => {
|
|
|
2116
2502
|
(p) => positions.push(p.stream),
|
|
2117
2503
|
{ stream: s, stream_exact: true, limit: 1 }
|
|
2118
2504
|
);
|
|
2119
|
-
(0,
|
|
2120
|
-
(0,
|
|
2505
|
+
(0, import_vitest9.expect)(maxEventId).toBeGreaterThanOrEqual(0);
|
|
2506
|
+
(0, import_vitest9.expect)(positions).toEqual([s]);
|
|
2121
2507
|
});
|
|
2122
2508
|
});
|
|
2123
|
-
(0,
|
|
2124
|
-
(0,
|
|
2509
|
+
(0, import_vitest9.describe)("seed_stream helper coverage", () => {
|
|
2510
|
+
(0, import_vitest9.it)("commits N events with monotonically increasing ids", async () => {
|
|
2125
2511
|
const s = `seed-${uid()}`;
|
|
2126
2512
|
const committed = await seed_stream(store, s, 3);
|
|
2127
|
-
(0,
|
|
2513
|
+
(0, import_vitest9.expect)(committed).toHaveLength(3);
|
|
2128
2514
|
for (let i = 1; i < committed.length; i++) {
|
|
2129
|
-
(0,
|
|
2515
|
+
(0, import_vitest9.expect)(committed[i].id).toBeGreaterThan(committed[i - 1].id);
|
|
2130
2516
|
}
|
|
2131
2517
|
});
|
|
2132
2518
|
});
|
|
2133
|
-
|
|
2519
|
+
import_vitest9.describe.skipIf(!caps.restore)("restore (capability)", () => {
|
|
2134
2520
|
beforeEach(async () => {
|
|
2135
2521
|
await store.drop();
|
|
2136
2522
|
await store.seed();
|
|
@@ -2158,8 +2544,8 @@ var runStoreTck = (options) => {
|
|
|
2158
2544
|
meta: { correlation: "restore-tck", causation: {} }
|
|
2159
2545
|
});
|
|
2160
2546
|
const restore = async (source, opts = {}) => {
|
|
2161
|
-
const cache = new
|
|
2162
|
-
const app = (0,
|
|
2547
|
+
const cache = new import_act2.InMemoryCache();
|
|
2548
|
+
const app = (0, import_act2.act)().build({ scoped: { store, cache } });
|
|
2163
2549
|
try {
|
|
2164
2550
|
return await app.restore(source, opts);
|
|
2165
2551
|
} finally {
|
|
@@ -2167,18 +2553,18 @@ var runStoreTck = (options) => {
|
|
|
2167
2553
|
await cache.dispose();
|
|
2168
2554
|
}
|
|
2169
2555
|
};
|
|
2170
|
-
(0,
|
|
2556
|
+
(0, import_vitest9.it)("returns kept=0 on an empty source", async () => {
|
|
2171
2557
|
const result = await restore(as_source([]));
|
|
2172
|
-
(0,
|
|
2173
|
-
(0,
|
|
2174
|
-
(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({
|
|
2175
2561
|
closed_streams: 0,
|
|
2176
2562
|
snapshots: 0
|
|
2177
2563
|
});
|
|
2178
2564
|
const events2 = await collect(store, { limit: 10 });
|
|
2179
|
-
(0,
|
|
2565
|
+
(0, import_vitest9.expect)(events2).toHaveLength(0);
|
|
2180
2566
|
});
|
|
2181
|
-
(0,
|
|
2567
|
+
(0, import_vitest9.it)("rebuilds a single stream and preserves `created` verbatim", async () => {
|
|
2182
2568
|
const s = `restore-single-${uid()}`;
|
|
2183
2569
|
const t0 = /* @__PURE__ */ new Date("2020-01-01T00:00:00.000Z");
|
|
2184
2570
|
const t1 = /* @__PURE__ */ new Date("2020-01-02T00:00:00.000Z");
|
|
@@ -2189,7 +2575,7 @@ var runStoreTck = (options) => {
|
|
|
2189
2575
|
event(3, s, 2, "Decremented", t2, { amount: 1 })
|
|
2190
2576
|
];
|
|
2191
2577
|
const result = await restore(as_source(events2));
|
|
2192
|
-
(0,
|
|
2578
|
+
(0, import_vitest9.expect)(result.kept).toBe(3);
|
|
2193
2579
|
const back = [];
|
|
2194
2580
|
await store.query(
|
|
2195
2581
|
(e) => {
|
|
@@ -2197,8 +2583,8 @@ var runStoreTck = (options) => {
|
|
|
2197
2583
|
},
|
|
2198
2584
|
{ stream: s, stream_exact: true }
|
|
2199
2585
|
);
|
|
2200
|
-
(0,
|
|
2201
|
-
(0,
|
|
2586
|
+
(0, import_vitest9.expect)(back).toHaveLength(3);
|
|
2587
|
+
(0, import_vitest9.expect)(
|
|
2202
2588
|
back.map((e) => ({
|
|
2203
2589
|
stream: e.stream,
|
|
2204
2590
|
version: e.version,
|
|
@@ -2230,7 +2616,7 @@ var runStoreTck = (options) => {
|
|
|
2230
2616
|
}
|
|
2231
2617
|
]);
|
|
2232
2618
|
});
|
|
2233
|
-
(0,
|
|
2619
|
+
(0, import_vitest9.it)("rebuilds multiple streams interleaved", async () => {
|
|
2234
2620
|
const a = `restore-multi-a-${uid()}`;
|
|
2235
2621
|
const b = `restore-multi-b-${uid()}`;
|
|
2236
2622
|
const t = /* @__PURE__ */ new Date("2020-06-01T00:00:00.000Z");
|
|
@@ -2241,7 +2627,7 @@ var runStoreTck = (options) => {
|
|
|
2241
2627
|
event(4, b, 1, "Incremented", t, { amount: 30 })
|
|
2242
2628
|
];
|
|
2243
2629
|
const result = await restore(as_source(events2));
|
|
2244
|
-
(0,
|
|
2630
|
+
(0, import_vitest9.expect)(result.kept).toBe(4);
|
|
2245
2631
|
const aBack = [];
|
|
2246
2632
|
const bBack = [];
|
|
2247
2633
|
await store.query(
|
|
@@ -2256,10 +2642,10 @@ var runStoreTck = (options) => {
|
|
|
2256
2642
|
},
|
|
2257
2643
|
{ stream: b, stream_exact: true }
|
|
2258
2644
|
);
|
|
2259
|
-
(0,
|
|
2260
|
-
(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]);
|
|
2261
2647
|
});
|
|
2262
|
-
(0,
|
|
2648
|
+
(0, import_vitest9.it)("preserves Date `created` verbatim", async () => {
|
|
2263
2649
|
const s = `restore-isoc-${uid()}`;
|
|
2264
2650
|
const iso = "2021-07-15T12:34:56.789Z";
|
|
2265
2651
|
await restore(
|
|
@@ -2282,10 +2668,10 @@ var runStoreTck = (options) => {
|
|
|
2282
2668
|
},
|
|
2283
2669
|
{ stream: s, stream_exact: true }
|
|
2284
2670
|
);
|
|
2285
|
-
(0,
|
|
2286
|
-
(0,
|
|
2671
|
+
(0, import_vitest9.expect)(back).toHaveLength(1);
|
|
2672
|
+
(0, import_vitest9.expect)(back[0].created.toISOString()).toBe(iso);
|
|
2287
2673
|
});
|
|
2288
|
-
(0,
|
|
2674
|
+
(0, import_vitest9.it)("wipes pre-existing events before inserting", async () => {
|
|
2289
2675
|
const old = `restore-old-${uid()}`;
|
|
2290
2676
|
await store.commit(
|
|
2291
2677
|
old,
|
|
@@ -2301,14 +2687,14 @@ var runStoreTck = (options) => {
|
|
|
2301
2687
|
stream: old,
|
|
2302
2688
|
stream_exact: true
|
|
2303
2689
|
});
|
|
2304
|
-
(0,
|
|
2690
|
+
(0, import_vitest9.expect)(old_back).toHaveLength(0);
|
|
2305
2691
|
const fresh_back = await collect(store, {
|
|
2306
2692
|
stream: fresh,
|
|
2307
2693
|
stream_exact: true
|
|
2308
2694
|
});
|
|
2309
|
-
(0,
|
|
2695
|
+
(0, import_vitest9.expect)(fresh_back).toHaveLength(1);
|
|
2310
2696
|
});
|
|
2311
|
-
(0,
|
|
2697
|
+
(0, import_vitest9.it)("clears subscription/stream-position metadata", async () => {
|
|
2312
2698
|
const sub = `restore-sub-${uid()}`;
|
|
2313
2699
|
await store.subscribe([{ stream: sub, source: "anything" }]);
|
|
2314
2700
|
const collect_streams = async () => {
|
|
@@ -2319,12 +2705,12 @@ var runStoreTck = (options) => {
|
|
|
2319
2705
|
return out;
|
|
2320
2706
|
};
|
|
2321
2707
|
const before = await collect_streams();
|
|
2322
|
-
(0,
|
|
2708
|
+
(0, import_vitest9.expect)(before.includes(sub)).toBe(true);
|
|
2323
2709
|
await restore(as_source([]));
|
|
2324
2710
|
const after = await collect_streams();
|
|
2325
|
-
(0,
|
|
2711
|
+
(0, import_vitest9.expect)(after.includes(sub)).toBe(false);
|
|
2326
2712
|
});
|
|
2327
|
-
(0,
|
|
2713
|
+
(0, import_vitest9.it)("preserves snapshot events through restore", async () => {
|
|
2328
2714
|
const s = `restore-snap-${uid()}`;
|
|
2329
2715
|
const t = /* @__PURE__ */ new Date("2020-04-01T00:00:00.000Z");
|
|
2330
2716
|
await restore(
|
|
@@ -2333,7 +2719,7 @@ var runStoreTck = (options) => {
|
|
|
2333
2719
|
id: 1,
|
|
2334
2720
|
stream: s,
|
|
2335
2721
|
version: 0,
|
|
2336
|
-
name:
|
|
2722
|
+
name: import_act2.SNAP_EVENT,
|
|
2337
2723
|
data: { count: 42 },
|
|
2338
2724
|
created: t,
|
|
2339
2725
|
meta: { correlation: "snap", causation: {} }
|
|
@@ -2345,10 +2731,10 @@ var runStoreTck = (options) => {
|
|
|
2345
2731
|
stream_exact: true,
|
|
2346
2732
|
with_snaps: true
|
|
2347
2733
|
});
|
|
2348
|
-
(0,
|
|
2349
|
-
(0,
|
|
2734
|
+
(0, import_vitest9.expect)(back).toHaveLength(1);
|
|
2735
|
+
(0, import_vitest9.expect)(back[0].name).toBe(import_act2.SNAP_EVENT);
|
|
2350
2736
|
});
|
|
2351
|
-
(0,
|
|
2737
|
+
(0, import_vitest9.it)("rewrites causation refs through the old\u2192new id map", async () => {
|
|
2352
2738
|
const s = `restore-caus-${uid()}`;
|
|
2353
2739
|
const t = /* @__PURE__ */ new Date("2020-08-01T00:00:00.000Z");
|
|
2354
2740
|
const events2 = [
|
|
@@ -2398,12 +2784,12 @@ var runStoreTck = (options) => {
|
|
|
2398
2784
|
},
|
|
2399
2785
|
{ stream: s, stream_exact: true }
|
|
2400
2786
|
);
|
|
2401
|
-
(0,
|
|
2402
|
-
(0,
|
|
2403
|
-
(0,
|
|
2404
|
-
(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);
|
|
2405
2791
|
});
|
|
2406
|
-
(0,
|
|
2792
|
+
(0, import_vitest9.it)("leaves causation refs unmapped when the target isn't in the source", async () => {
|
|
2407
2793
|
const s = `restore-orphan-${uid()}`;
|
|
2408
2794
|
const t = /* @__PURE__ */ new Date("2020-09-01T00:00:00.000Z");
|
|
2409
2795
|
await restore(
|
|
@@ -2431,9 +2817,9 @@ var runStoreTck = (options) => {
|
|
|
2431
2817
|
},
|
|
2432
2818
|
{ stream: s, stream_exact: true }
|
|
2433
2819
|
);
|
|
2434
|
-
(0,
|
|
2820
|
+
(0, import_vitest9.expect)(back[0].meta.causation.event?.id).toBe(999);
|
|
2435
2821
|
});
|
|
2436
|
-
(0,
|
|
2822
|
+
(0, import_vitest9.it)("rolls back atomically when the source throws mid-iteration", async () => {
|
|
2437
2823
|
const original = `restore-pre-${uid()}`;
|
|
2438
2824
|
const committed = await store.commit(
|
|
2439
2825
|
original,
|
|
@@ -2459,7 +2845,7 @@ var runStoreTck = (options) => {
|
|
|
2459
2845
|
async dispose() {
|
|
2460
2846
|
}
|
|
2461
2847
|
};
|
|
2462
|
-
await (0,
|
|
2848
|
+
await (0, import_vitest9.expect)(restore(explosive)).rejects.toThrow("boom");
|
|
2463
2849
|
const back = [];
|
|
2464
2850
|
await store.query(
|
|
2465
2851
|
(e) => {
|
|
@@ -2467,10 +2853,10 @@ var runStoreTck = (options) => {
|
|
|
2467
2853
|
},
|
|
2468
2854
|
{ stream: original, stream_exact: true }
|
|
2469
2855
|
);
|
|
2470
|
-
(0,
|
|
2471
|
-
(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));
|
|
2472
2858
|
});
|
|
2473
|
-
(0,
|
|
2859
|
+
(0, import_vitest9.it)("drop_snapshots: skips SNAP_EVENT rows and counts them", async () => {
|
|
2474
2860
|
const s = `restore-drop-snap-${uid()}`;
|
|
2475
2861
|
const t = /* @__PURE__ */ new Date("2020-10-01T00:00:00.000Z");
|
|
2476
2862
|
const result = await restore(
|
|
@@ -2480,7 +2866,7 @@ var runStoreTck = (options) => {
|
|
|
2480
2866
|
id: 2,
|
|
2481
2867
|
stream: s,
|
|
2482
2868
|
version: 1,
|
|
2483
|
-
name:
|
|
2869
|
+
name: import_act2.SNAP_EVENT,
|
|
2484
2870
|
data: { count: 1 },
|
|
2485
2871
|
created: t,
|
|
2486
2872
|
meta: { correlation: "snap", causation: {} }
|
|
@@ -2489,19 +2875,19 @@ var runStoreTck = (options) => {
|
|
|
2489
2875
|
]),
|
|
2490
2876
|
{ drop_snapshots: true }
|
|
2491
2877
|
);
|
|
2492
|
-
(0,
|
|
2493
|
-
(0,
|
|
2878
|
+
(0, import_vitest9.expect)(result.kept).toBe(2);
|
|
2879
|
+
(0, import_vitest9.expect)(result.dropped.snapshots).toBe(1);
|
|
2494
2880
|
const back = await collect(store, {
|
|
2495
2881
|
stream: s,
|
|
2496
2882
|
stream_exact: true,
|
|
2497
2883
|
with_snaps: true
|
|
2498
2884
|
});
|
|
2499
|
-
(0,
|
|
2500
|
-
(0,
|
|
2501
|
-
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)
|
|
2502
2888
|
).toBe(true);
|
|
2503
2889
|
});
|
|
2504
|
-
(0,
|
|
2890
|
+
(0, import_vitest9.it)("on_progress fires once per event (caller throttles)", async () => {
|
|
2505
2891
|
const calls = [];
|
|
2506
2892
|
const s = `restore-progress-${uid()}`;
|
|
2507
2893
|
const t = /* @__PURE__ */ new Date("2021-02-01T00:00:00.000Z");
|
|
@@ -2512,11 +2898,11 @@ var runStoreTck = (options) => {
|
|
|
2512
2898
|
]),
|
|
2513
2899
|
{ on_progress: (p) => calls.push(p.processed) }
|
|
2514
2900
|
);
|
|
2515
|
-
(0,
|
|
2901
|
+
(0, import_vitest9.expect)(calls).toEqual([1, 2]);
|
|
2516
2902
|
});
|
|
2517
2903
|
});
|
|
2518
|
-
|
|
2519
|
-
(0,
|
|
2904
|
+
import_vitest9.describe.skipIf(!caps.pii_isolation)("pii_isolation (capability)", () => {
|
|
2905
|
+
(0, import_vitest9.it)("commits and loads pii alongside data", async () => {
|
|
2520
2906
|
const s = `pii-roundtrip-${uid()}`;
|
|
2521
2907
|
const committed = await store.commit(
|
|
2522
2908
|
s,
|
|
@@ -2529,8 +2915,8 @@ var runStoreTck = (options) => {
|
|
|
2529
2915
|
],
|
|
2530
2916
|
make_meta({ stream: s })
|
|
2531
2917
|
);
|
|
2532
|
-
(0,
|
|
2533
|
-
(0,
|
|
2918
|
+
(0, import_vitest9.expect)(committed).toHaveLength(1);
|
|
2919
|
+
(0, import_vitest9.expect)(committed[0].pii).toEqual({
|
|
2534
2920
|
email: "u@example.com",
|
|
2535
2921
|
name: "Ursula"
|
|
2536
2922
|
});
|
|
@@ -2541,11 +2927,11 @@ var runStoreTck = (options) => {
|
|
|
2541
2927
|
},
|
|
2542
2928
|
{ stream: s, stream_exact: true }
|
|
2543
2929
|
);
|
|
2544
|
-
(0,
|
|
2545
|
-
(0,
|
|
2546
|
-
(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 });
|
|
2547
2933
|
});
|
|
2548
|
-
(0,
|
|
2934
|
+
(0, import_vitest9.it)("passes through events without pii (pii is null or undefined on load)", async () => {
|
|
2549
2935
|
const s = `pii-none-${uid()}`;
|
|
2550
2936
|
await store.commit(
|
|
2551
2937
|
s,
|
|
@@ -2559,10 +2945,10 @@ var runStoreTck = (options) => {
|
|
|
2559
2945
|
},
|
|
2560
2946
|
{ stream: s, stream_exact: true }
|
|
2561
2947
|
);
|
|
2562
|
-
(0,
|
|
2563
|
-
(0,
|
|
2948
|
+
(0, import_vitest9.expect)(seen).toHaveLength(1);
|
|
2949
|
+
(0, import_vitest9.expect)(seen[0].pii == null).toBe(true);
|
|
2564
2950
|
});
|
|
2565
|
-
(0,
|
|
2951
|
+
(0, import_vitest9.it)("wipes pii for every event on the stream via forget_pii", async () => {
|
|
2566
2952
|
const s = `pii-forget-${uid()}`;
|
|
2567
2953
|
await store.commit(
|
|
2568
2954
|
s,
|
|
@@ -2581,9 +2967,9 @@ var runStoreTck = (options) => {
|
|
|
2581
2967
|
make_meta({ stream: s })
|
|
2582
2968
|
);
|
|
2583
2969
|
const forget = store.forget_pii;
|
|
2584
|
-
(0,
|
|
2970
|
+
(0, import_vitest9.expect)(forget).toBeDefined();
|
|
2585
2971
|
const wiped = await forget.call(store, s);
|
|
2586
|
-
(0,
|
|
2972
|
+
(0, import_vitest9.expect)(wiped).toBe(2);
|
|
2587
2973
|
const seen = [];
|
|
2588
2974
|
await store.query(
|
|
2589
2975
|
(e) => {
|
|
@@ -2591,13 +2977,13 @@ var runStoreTck = (options) => {
|
|
|
2591
2977
|
},
|
|
2592
2978
|
{ stream: s, stream_exact: true }
|
|
2593
2979
|
);
|
|
2594
|
-
(0,
|
|
2980
|
+
(0, import_vitest9.expect)(seen).toHaveLength(2);
|
|
2595
2981
|
for (const e of seen) {
|
|
2596
|
-
(0,
|
|
2597
|
-
(0,
|
|
2982
|
+
(0, import_vitest9.expect)(e.pii == null).toBe(true);
|
|
2983
|
+
(0, import_vitest9.expect)(e.data).toBeDefined();
|
|
2598
2984
|
}
|
|
2599
2985
|
});
|
|
2600
|
-
(0,
|
|
2986
|
+
(0, import_vitest9.it)("is idempotent \u2014 second forget_pii returns 0, no error", async () => {
|
|
2601
2987
|
const s = `pii-forget-idem-${uid()}`;
|
|
2602
2988
|
await store.commit(
|
|
2603
2989
|
s,
|
|
@@ -2612,11 +2998,11 @@ var runStoreTck = (options) => {
|
|
|
2612
2998
|
);
|
|
2613
2999
|
const forget = store.forget_pii;
|
|
2614
3000
|
const first = await forget.call(store, s);
|
|
2615
|
-
(0,
|
|
3001
|
+
(0, import_vitest9.expect)(first).toBe(1);
|
|
2616
3002
|
const second = await forget.call(store, s);
|
|
2617
|
-
(0,
|
|
3003
|
+
(0, import_vitest9.expect)(second).toBe(0);
|
|
2618
3004
|
});
|
|
2619
|
-
(0,
|
|
3005
|
+
(0, import_vitest9.it)("only wipes the targeted stream \u2014 siblings untouched", async () => {
|
|
2620
3006
|
const sA = `pii-iso-a-${uid()}`;
|
|
2621
3007
|
const sB = `pii-iso-b-${uid()}`;
|
|
2622
3008
|
await store.commit(
|
|
@@ -2649,7 +3035,7 @@ var runStoreTck = (options) => {
|
|
|
2649
3035
|
},
|
|
2650
3036
|
{ stream: sA, stream_exact: true }
|
|
2651
3037
|
);
|
|
2652
|
-
(0,
|
|
3038
|
+
(0, import_vitest9.expect)(a[0].pii == null).toBe(true);
|
|
2653
3039
|
const b = [];
|
|
2654
3040
|
await store.query(
|
|
2655
3041
|
(e) => {
|
|
@@ -2657,9 +3043,9 @@ var runStoreTck = (options) => {
|
|
|
2657
3043
|
},
|
|
2658
3044
|
{ stream: sB, stream_exact: true }
|
|
2659
3045
|
);
|
|
2660
|
-
(0,
|
|
3046
|
+
(0, import_vitest9.expect)(b[0].pii).toEqual({ email: "bob@example.com" });
|
|
2661
3047
|
});
|
|
2662
|
-
(0,
|
|
3048
|
+
(0, import_vitest9.it)("forget_pii on a stream with no pii events returns 0", async () => {
|
|
2663
3049
|
const s = `pii-forget-empty-${uid()}`;
|
|
2664
3050
|
await store.commit(
|
|
2665
3051
|
s,
|
|
@@ -2667,14 +3053,14 @@ var runStoreTck = (options) => {
|
|
|
2667
3053
|
make_meta({ stream: s })
|
|
2668
3054
|
);
|
|
2669
3055
|
const wiped = await store.forget_pii.call(store, s);
|
|
2670
|
-
(0,
|
|
3056
|
+
(0, import_vitest9.expect)(wiped).toBe(0);
|
|
2671
3057
|
});
|
|
2672
3058
|
});
|
|
2673
3059
|
if (caps.notify) {
|
|
2674
|
-
(0,
|
|
2675
|
-
(0,
|
|
3060
|
+
(0, import_vitest9.describe)("notify (capability)", () => {
|
|
3061
|
+
(0, import_vitest9.it)("delivers a notification when a different instance commits", async () => {
|
|
2676
3062
|
const notify = store.notify;
|
|
2677
|
-
(0,
|
|
3063
|
+
(0, import_vitest9.expect)(notify).toBeDefined();
|
|
2678
3064
|
const received = [];
|
|
2679
3065
|
let resolve_arrived;
|
|
2680
3066
|
const arrived = new Promise((res) => {
|
|
@@ -2693,9 +3079,9 @@ var runStoreTck = (options) => {
|
|
|
2693
3079
|
make_meta({ stream })
|
|
2694
3080
|
);
|
|
2695
3081
|
await arrived;
|
|
2696
|
-
(0,
|
|
2697
|
-
(0,
|
|
2698
|
-
(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);
|
|
2699
3085
|
} finally {
|
|
2700
3086
|
await writer.dispose();
|
|
2701
3087
|
await Promise.resolve(disposer());
|
|
@@ -2717,9 +3103,12 @@ var runStoreTck = (options) => {
|
|
|
2717
3103
|
dec,
|
|
2718
3104
|
inc,
|
|
2719
3105
|
reset,
|
|
3106
|
+
runCacheDifferentialTck,
|
|
2720
3107
|
runCacheTck,
|
|
3108
|
+
runLoggerDifferentialTck,
|
|
2721
3109
|
runLoggerTck,
|
|
2722
3110
|
runStabilityTck,
|
|
3111
|
+
runStoreDifferentialTck,
|
|
2723
3112
|
runStorePropertyTck,
|
|
2724
3113
|
runStoreTck,
|
|
2725
3114
|
uid
|