@rotorsoft/act-tck 1.17.0 → 1.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +1001 -514
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +974 -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,115 @@ 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);
|
|
1465
|
+
});
|
|
1466
|
+
});
|
|
1467
|
+
(0, import_vitest9.describe)("defer", () => {
|
|
1468
|
+
(0, import_vitest9.it)("hides a stream from claim until its deferred_at passes", async () => {
|
|
1469
|
+
const s = `defer-${uid()}`;
|
|
1470
|
+
const ctl = `defer-ctl-${uid()}`;
|
|
1471
|
+
await store.subscribe([{ stream: s }, { stream: ctl }]);
|
|
1472
|
+
for (const st of [s, ctl])
|
|
1473
|
+
await store.commit(
|
|
1474
|
+
st,
|
|
1475
|
+
[inc(1)],
|
|
1476
|
+
make_meta({ stream: st })
|
|
1477
|
+
);
|
|
1478
|
+
(0, import_vitest9.expect)(await store.defer([s], Date.now() + 36e5)).toBe(1);
|
|
1479
|
+
const leased = await store.claim(100, 100, `w-${uid()}`, 1e5);
|
|
1480
|
+
(0, import_vitest9.expect)(leased.find((l) => l.stream === ctl)).toBeDefined();
|
|
1481
|
+
(0, import_vitest9.expect)(leased.find((l) => l.stream === s)).toBeUndefined();
|
|
1482
|
+
});
|
|
1483
|
+
(0, import_vitest9.it)("makes a stream claimable once the deferred_at is in the past", async () => {
|
|
1484
|
+
const s = `defer-past-${uid()}`;
|
|
1485
|
+
await store.subscribe([{ stream: s }]);
|
|
1486
|
+
await store.commit(
|
|
1487
|
+
s,
|
|
1488
|
+
[inc(1)],
|
|
1489
|
+
make_meta({ stream: s })
|
|
1490
|
+
);
|
|
1491
|
+
(0, import_vitest9.expect)(await store.defer([s], Date.now() - 1e3)).toBe(1);
|
|
1492
|
+
const leased = await store.claim(100, 100, `w-${uid()}`, 1e5);
|
|
1493
|
+
const mine = leased.find((l) => l.stream === s);
|
|
1494
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1495
|
+
await store.ack(
|
|
1496
|
+
leased.filter((l) => l.stream !== s).concat(mine)
|
|
1497
|
+
);
|
|
1498
|
+
});
|
|
1499
|
+
(0, import_vitest9.it)("does not bump retry while a stream is deferred", async () => {
|
|
1500
|
+
const s = `defer-retry-${uid()}`;
|
|
1501
|
+
await store.subscribe([{ stream: s }]);
|
|
1502
|
+
await store.commit(
|
|
1503
|
+
s,
|
|
1504
|
+
[inc(1)],
|
|
1505
|
+
make_meta({ stream: s })
|
|
1506
|
+
);
|
|
1507
|
+
await store.defer([s], Date.now() + 36e5);
|
|
1508
|
+
await store.claim(100, 100, `w1-${uid()}`, 1e5);
|
|
1509
|
+
await store.claim(100, 100, `w2-${uid()}`, 1e5);
|
|
1510
|
+
await store.defer([s], Date.now() - 1e3);
|
|
1511
|
+
const leased = await store.claim(100, 100, `w3-${uid()}`, 1e5);
|
|
1512
|
+
const mine = leased.find((l) => l.stream === s);
|
|
1513
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1514
|
+
(0, import_vitest9.expect)(mine.retry).toBe(0);
|
|
1515
|
+
await store.ack(
|
|
1516
|
+
leased.filter((l) => l.stream !== s).concat(mine)
|
|
1517
|
+
);
|
|
1518
|
+
});
|
|
1519
|
+
(0, import_vitest9.it)("reset clears a pending defer", async () => {
|
|
1520
|
+
const s = `defer-reset-${uid()}`;
|
|
1521
|
+
await store.subscribe([{ stream: s }]);
|
|
1522
|
+
await store.commit(
|
|
1523
|
+
s,
|
|
1524
|
+
[inc(1)],
|
|
1525
|
+
make_meta({ stream: s })
|
|
1526
|
+
);
|
|
1527
|
+
await store.defer([s], Date.now() + 36e5);
|
|
1528
|
+
(0, import_vitest9.expect)(await store.reset([s])).toBe(1);
|
|
1529
|
+
const leased = await store.claim(100, 100, `w-${uid()}`, 1e5);
|
|
1530
|
+
(0, import_vitest9.expect)(leased.find((l) => l.stream === s)).toBeDefined();
|
|
1531
|
+
});
|
|
1532
|
+
(0, import_vitest9.it)("defers streams matching a filter and counts matches", async () => {
|
|
1533
|
+
const tag = uid();
|
|
1534
|
+
const a = `deferfilter-${tag}-a`;
|
|
1535
|
+
const b = `deferfilter-${tag}-b`;
|
|
1536
|
+
await store.subscribe([{ stream: a }, { stream: b }]);
|
|
1537
|
+
for (const s of [a, b])
|
|
1538
|
+
await store.commit(
|
|
1539
|
+
s,
|
|
1540
|
+
[inc(1)],
|
|
1541
|
+
make_meta({ stream: s })
|
|
1542
|
+
);
|
|
1543
|
+
const ctl = `defer-filterctl-${tag}`;
|
|
1544
|
+
await store.subscribe([{ stream: ctl }]);
|
|
1545
|
+
await store.commit(
|
|
1546
|
+
ctl,
|
|
1547
|
+
[inc(1)],
|
|
1548
|
+
make_meta({ stream: ctl })
|
|
1549
|
+
);
|
|
1550
|
+
const n = await store.defer(
|
|
1551
|
+
{ stream: `^deferfilter-${tag}-`, stream_exact: false },
|
|
1552
|
+
Date.now() + 36e5
|
|
1553
|
+
);
|
|
1554
|
+
(0, import_vitest9.expect)(n).toBe(2);
|
|
1555
|
+
const leased = await store.claim(100, 100, `w-${uid()}`, 1e5);
|
|
1556
|
+
(0, import_vitest9.expect)(leased.find((l) => l.stream === ctl)).toBeDefined();
|
|
1557
|
+
(0, import_vitest9.expect)(leased.find((l) => l.stream === a)).toBeUndefined();
|
|
1558
|
+
(0, import_vitest9.expect)(leased.find((l) => l.stream === b)).toBeUndefined();
|
|
1559
|
+
});
|
|
1560
|
+
(0, import_vitest9.it)("returns 0 for unknown streams and empty input", async () => {
|
|
1561
|
+
(0, import_vitest9.expect)(await store.defer([`missing-${uid()}`], Date.now())).toBe(0);
|
|
1562
|
+
(0, import_vitest9.expect)(await store.defer([], Date.now())).toBe(0);
|
|
1079
1563
|
});
|
|
1080
1564
|
});
|
|
1081
|
-
(0,
|
|
1082
|
-
(0,
|
|
1565
|
+
(0, import_vitest9.describe)("reset", () => {
|
|
1566
|
+
(0, import_vitest9.it)("rewinds a stream watermark to -1", async () => {
|
|
1083
1567
|
const s = `reset-${uid()}`;
|
|
1084
1568
|
await store.subscribe([{ stream: s }]);
|
|
1085
1569
|
await store.commit(
|
|
@@ -1089,15 +1573,15 @@ var runStoreTck = (options) => {
|
|
|
1089
1573
|
);
|
|
1090
1574
|
const leased = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1091
1575
|
const mine = leased.find((l) => l.stream === s);
|
|
1092
|
-
(0,
|
|
1576
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1093
1577
|
await store.ack([{ ...mine, at: 99 }]);
|
|
1094
|
-
(0,
|
|
1578
|
+
(0, import_vitest9.expect)(await store.reset([s])).toBe(1);
|
|
1095
1579
|
const after = await store.claim(100, 0, `w2-${uid()}`, 1e5);
|
|
1096
1580
|
const back = after.find((l) => l.stream === s);
|
|
1097
|
-
(0,
|
|
1098
|
-
(0,
|
|
1581
|
+
(0, import_vitest9.expect)(back).toBeDefined();
|
|
1582
|
+
(0, import_vitest9.expect)(back.at).toBe(-1);
|
|
1099
1583
|
});
|
|
1100
|
-
(0,
|
|
1584
|
+
(0, import_vitest9.it)("clears blocked status when resetting", async () => {
|
|
1101
1585
|
const s = `reset-blk-${uid()}`;
|
|
1102
1586
|
await store.subscribe([{ stream: s }]);
|
|
1103
1587
|
await store.commit(
|
|
@@ -1110,17 +1594,17 @@ var runStoreTck = (options) => {
|
|
|
1110
1594
|
const others = leased.filter((l) => l.stream !== s);
|
|
1111
1595
|
await store.ack(others);
|
|
1112
1596
|
await store.block([{ ...mine, error: "boom" }]);
|
|
1113
|
-
(0,
|
|
1597
|
+
(0, import_vitest9.expect)(await store.reset([s])).toBe(1);
|
|
1114
1598
|
const after = await store.claim(100, 0, `w2-${uid()}`, 1e5);
|
|
1115
|
-
(0,
|
|
1599
|
+
(0, import_vitest9.expect)(after.find((l) => l.stream === s)).toBeDefined();
|
|
1116
1600
|
});
|
|
1117
|
-
(0,
|
|
1118
|
-
(0,
|
|
1119
|
-
(0,
|
|
1601
|
+
(0, import_vitest9.it)("returns 0 for unknown streams and empty input", async () => {
|
|
1602
|
+
(0, import_vitest9.expect)(await store.reset([`missing-${uid()}`])).toBe(0);
|
|
1603
|
+
(0, import_vitest9.expect)(await store.reset([])).toBe(0);
|
|
1120
1604
|
});
|
|
1121
1605
|
});
|
|
1122
|
-
(0,
|
|
1123
|
-
(0,
|
|
1606
|
+
(0, import_vitest9.describe)("unblock", () => {
|
|
1607
|
+
(0, import_vitest9.it)("clears blocked flag and preserves the watermark", async () => {
|
|
1124
1608
|
const s = `unblock-${uid()}`;
|
|
1125
1609
|
await store.subscribe([{ stream: s }]);
|
|
1126
1610
|
await store.commit(
|
|
@@ -1138,7 +1622,7 @@ var runStoreTck = (options) => {
|
|
|
1138
1622
|
await store.ack([{ ...m1, at: m1.at }]);
|
|
1139
1623
|
const before_block = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1140
1624
|
const m2 = before_block.find((l) => l.stream === s);
|
|
1141
|
-
(0,
|
|
1625
|
+
(0, import_vitest9.expect)(m2).toBeDefined();
|
|
1142
1626
|
const watermark_before = m2.at;
|
|
1143
1627
|
await store.block([{ ...m2, error: "permanent" }]);
|
|
1144
1628
|
let blocked_flag;
|
|
@@ -1148,15 +1632,15 @@ var runStoreTck = (options) => {
|
|
|
1148
1632
|
},
|
|
1149
1633
|
{ stream: s, stream_exact: true, limit: 1 }
|
|
1150
1634
|
);
|
|
1151
|
-
(0,
|
|
1152
|
-
(0,
|
|
1635
|
+
(0, import_vitest9.expect)(blocked_flag).toBe(true);
|
|
1636
|
+
(0, import_vitest9.expect)(await store.unblock([s])).toBe(1);
|
|
1153
1637
|
const after = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1154
1638
|
const back = after.find((l) => l.stream === s);
|
|
1155
|
-
(0,
|
|
1156
|
-
(0,
|
|
1157
|
-
(0,
|
|
1639
|
+
(0, import_vitest9.expect)(back).toBeDefined();
|
|
1640
|
+
(0, import_vitest9.expect)(back.at).toBe(watermark_before);
|
|
1641
|
+
(0, import_vitest9.expect)(back.retry).toBe(0);
|
|
1158
1642
|
});
|
|
1159
|
-
(0,
|
|
1643
|
+
(0, import_vitest9.it)("returns 0 when the stream is not blocked", async () => {
|
|
1160
1644
|
const s = `unblock-noop-${uid()}`;
|
|
1161
1645
|
await store.subscribe([{ stream: s }]);
|
|
1162
1646
|
await store.commit(
|
|
@@ -1164,13 +1648,13 @@ var runStoreTck = (options) => {
|
|
|
1164
1648
|
[inc(1)],
|
|
1165
1649
|
make_meta({ stream: s })
|
|
1166
1650
|
);
|
|
1167
|
-
(0,
|
|
1651
|
+
(0, import_vitest9.expect)(await store.unblock([s])).toBe(0);
|
|
1168
1652
|
});
|
|
1169
|
-
(0,
|
|
1170
|
-
(0,
|
|
1171
|
-
(0,
|
|
1653
|
+
(0, import_vitest9.it)("returns 0 for unknown streams and empty input", async () => {
|
|
1654
|
+
(0, import_vitest9.expect)(await store.unblock([`missing-${uid()}`])).toBe(0);
|
|
1655
|
+
(0, import_vitest9.expect)(await store.unblock([])).toBe(0);
|
|
1172
1656
|
});
|
|
1173
|
-
(0,
|
|
1657
|
+
(0, import_vitest9.it)("only counts streams that were actually blocked", async () => {
|
|
1174
1658
|
const s1 = `unblock-mix-a-${uid()}`;
|
|
1175
1659
|
const s2 = `unblock-mix-b-${uid()}`;
|
|
1176
1660
|
await store.subscribe([{ stream: s1 }, { stream: s2 }]);
|
|
@@ -1189,9 +1673,9 @@ var runStoreTck = (options) => {
|
|
|
1189
1673
|
const others = leased.filter((l) => l.stream !== s1);
|
|
1190
1674
|
await store.ack(others);
|
|
1191
1675
|
await store.block([{ ...m1, error: "boom" }]);
|
|
1192
|
-
(0,
|
|
1676
|
+
(0, import_vitest9.expect)(await store.unblock([s1, s2])).toBe(1);
|
|
1193
1677
|
});
|
|
1194
|
-
(0,
|
|
1678
|
+
(0, import_vitest9.it)("filter form: unblocks by stream pattern", async () => {
|
|
1195
1679
|
const tag = uid();
|
|
1196
1680
|
const s1 = `unblock-filter-${tag}-a`;
|
|
1197
1681
|
const s2 = `unblock-filter-${tag}-b`;
|
|
@@ -1223,13 +1707,13 @@ var runStoreTck = (options) => {
|
|
|
1223
1707
|
const count = await store.unblock({
|
|
1224
1708
|
stream: `^unblock-filter-${tag}-`
|
|
1225
1709
|
});
|
|
1226
|
-
(0,
|
|
1710
|
+
(0, import_vitest9.expect)(count).toBe(2);
|
|
1227
1711
|
const after = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1228
|
-
(0,
|
|
1229
|
-
(0,
|
|
1230
|
-
(0,
|
|
1712
|
+
(0, import_vitest9.expect)(after.find((l) => l.stream === s3)).toBeUndefined();
|
|
1713
|
+
(0, import_vitest9.expect)(after.find((l) => l.stream === s1)).toBeDefined();
|
|
1714
|
+
(0, import_vitest9.expect)(after.find((l) => l.stream === s2)).toBeDefined();
|
|
1231
1715
|
});
|
|
1232
|
-
(0,
|
|
1716
|
+
(0, import_vitest9.it)("filter form: empty filter unblocks every blocked stream", async () => {
|
|
1233
1717
|
const tag = uid();
|
|
1234
1718
|
const s1 = `unblock-empty-${tag}-a`;
|
|
1235
1719
|
const s2 = `unblock-empty-${tag}-b`;
|
|
@@ -1253,9 +1737,9 @@ var runStoreTck = (options) => {
|
|
|
1253
1737
|
const count = await store.unblock({
|
|
1254
1738
|
stream: `^unblock-empty-${tag}-`
|
|
1255
1739
|
});
|
|
1256
|
-
(0,
|
|
1740
|
+
(0, import_vitest9.expect)(count).toBe(2);
|
|
1257
1741
|
});
|
|
1258
|
-
(0,
|
|
1742
|
+
(0, import_vitest9.it)("filter form: explicit blocked:false matches nothing", async () => {
|
|
1259
1743
|
const tag = uid();
|
|
1260
1744
|
const s = `unblock-blocked-false-${tag}`;
|
|
1261
1745
|
await store.subscribe([{ stream: s }]);
|
|
@@ -1264,7 +1748,7 @@ var runStoreTck = (options) => {
|
|
|
1264
1748
|
[inc(1)],
|
|
1265
1749
|
make_meta({ stream: s })
|
|
1266
1750
|
);
|
|
1267
|
-
(0,
|
|
1751
|
+
(0, import_vitest9.expect)(
|
|
1268
1752
|
await store.unblock({
|
|
1269
1753
|
stream: `^unblock-blocked-false-${tag}`,
|
|
1270
1754
|
blocked: false
|
|
@@ -1272,8 +1756,8 @@ var runStoreTck = (options) => {
|
|
|
1272
1756
|
).toBe(0);
|
|
1273
1757
|
});
|
|
1274
1758
|
});
|
|
1275
|
-
(0,
|
|
1276
|
-
(0,
|
|
1759
|
+
(0, import_vitest9.describe)("reset filter form", () => {
|
|
1760
|
+
(0, import_vitest9.it)("resets streams matching a stream pattern", async () => {
|
|
1277
1761
|
const tag = uid();
|
|
1278
1762
|
const s1 = `reset-filter-${tag}-a`;
|
|
1279
1763
|
const s2 = `reset-filter-${tag}-b`;
|
|
@@ -1304,7 +1788,7 @@ var runStoreTck = (options) => {
|
|
|
1304
1788
|
);
|
|
1305
1789
|
await store.ack(mine.map((l) => ({ ...l, at: l.at + 100 })));
|
|
1306
1790
|
const count = await store.reset({ stream: `^reset-filter-${tag}-` });
|
|
1307
|
-
(0,
|
|
1791
|
+
(0, import_vitest9.expect)(count).toBe(2);
|
|
1308
1792
|
const position_for = async (name) => {
|
|
1309
1793
|
let at = null;
|
|
1310
1794
|
await store.query_streams(
|
|
@@ -1315,11 +1799,11 @@ var runStoreTck = (options) => {
|
|
|
1315
1799
|
);
|
|
1316
1800
|
return at;
|
|
1317
1801
|
};
|
|
1318
|
-
(0,
|
|
1319
|
-
(0,
|
|
1320
|
-
(0,
|
|
1802
|
+
(0, import_vitest9.expect)(await position_for(s1)).toBe(-1);
|
|
1803
|
+
(0, import_vitest9.expect)(await position_for(s2)).toBe(-1);
|
|
1804
|
+
(0, import_vitest9.expect)(await position_for(other)).toBeGreaterThan(-1);
|
|
1321
1805
|
});
|
|
1322
|
-
(0,
|
|
1806
|
+
(0, import_vitest9.it)("filter form: resets only blocked streams when blocked:true", async () => {
|
|
1323
1807
|
const tag = uid();
|
|
1324
1808
|
const s1 = `reset-blocked-${tag}-blocked`;
|
|
1325
1809
|
const s2 = `reset-blocked-${tag}-fine`;
|
|
@@ -1342,11 +1826,11 @@ var runStoreTck = (options) => {
|
|
|
1342
1826
|
stream: `^reset-blocked-${tag}-`,
|
|
1343
1827
|
blocked: true
|
|
1344
1828
|
});
|
|
1345
|
-
(0,
|
|
1829
|
+
(0, import_vitest9.expect)(count).toBe(1);
|
|
1346
1830
|
});
|
|
1347
1831
|
});
|
|
1348
|
-
(0,
|
|
1349
|
-
(0,
|
|
1832
|
+
(0, import_vitest9.describe)("prioritize", () => {
|
|
1833
|
+
(0, import_vitest9.it)("sets priority directly, overriding subscribe's max() rule", async () => {
|
|
1350
1834
|
const tag = uid();
|
|
1351
1835
|
const s1 = `pri-${tag}-a`;
|
|
1352
1836
|
const s2 = `pri-${tag}-b`;
|
|
@@ -1358,7 +1842,7 @@ var runStoreTck = (options) => {
|
|
|
1358
1842
|
{ stream: s1, stream_exact: true },
|
|
1359
1843
|
3
|
|
1360
1844
|
);
|
|
1361
|
-
(0,
|
|
1845
|
+
(0, import_vitest9.expect)(updated).toBe(1);
|
|
1362
1846
|
const got1 = {};
|
|
1363
1847
|
const got2 = {};
|
|
1364
1848
|
await store.query_streams(
|
|
@@ -1368,12 +1852,12 @@ var runStoreTck = (options) => {
|
|
|
1368
1852
|
},
|
|
1369
1853
|
{ stream: `pri-${tag}-.*`, limit: 100 }
|
|
1370
1854
|
);
|
|
1371
|
-
(0,
|
|
1372
|
-
(0,
|
|
1855
|
+
(0, import_vitest9.expect)(got1.priority).toBe(3);
|
|
1856
|
+
(0, import_vitest9.expect)(got2.priority).toBe(5);
|
|
1373
1857
|
});
|
|
1374
1858
|
});
|
|
1375
|
-
(0,
|
|
1376
|
-
(0,
|
|
1859
|
+
(0, import_vitest9.describe)("lanes", () => {
|
|
1860
|
+
(0, import_vitest9.it)("subscribe defaults lane to 'default' when omitted", async () => {
|
|
1377
1861
|
const s = `lane-default-${uid()}`;
|
|
1378
1862
|
await store.subscribe([{ stream: s }]);
|
|
1379
1863
|
const seen = [];
|
|
@@ -1381,9 +1865,9 @@ var runStoreTck = (options) => {
|
|
|
1381
1865
|
stream: s,
|
|
1382
1866
|
stream_exact: true
|
|
1383
1867
|
});
|
|
1384
|
-
(0,
|
|
1868
|
+
(0, import_vitest9.expect)(seen).toEqual(["default"]);
|
|
1385
1869
|
});
|
|
1386
|
-
(0,
|
|
1870
|
+
(0, import_vitest9.it)("subscribe records the lane passed in", async () => {
|
|
1387
1871
|
const s = `lane-set-${uid()}`;
|
|
1388
1872
|
await store.subscribe([{ stream: s, lane: "slow" }]);
|
|
1389
1873
|
const seen = [];
|
|
@@ -1391,9 +1875,9 @@ var runStoreTck = (options) => {
|
|
|
1391
1875
|
stream: s,
|
|
1392
1876
|
stream_exact: true
|
|
1393
1877
|
});
|
|
1394
|
-
(0,
|
|
1878
|
+
(0, import_vitest9.expect)(seen).toEqual(["slow"]);
|
|
1395
1879
|
});
|
|
1396
|
-
(0,
|
|
1880
|
+
(0, import_vitest9.it)("subscribe re-lanes existing streams on subsequent calls", async () => {
|
|
1397
1881
|
const s = `lane-upsert-${uid()}`;
|
|
1398
1882
|
await store.subscribe([{ stream: s, lane: "slow" }]);
|
|
1399
1883
|
await store.subscribe([{ stream: s, lane: "fast" }]);
|
|
@@ -1402,9 +1886,9 @@ var runStoreTck = (options) => {
|
|
|
1402
1886
|
stream: s,
|
|
1403
1887
|
stream_exact: true
|
|
1404
1888
|
});
|
|
1405
|
-
(0,
|
|
1889
|
+
(0, import_vitest9.expect)(seen).toEqual(["fast"]);
|
|
1406
1890
|
});
|
|
1407
|
-
(0,
|
|
1891
|
+
(0, import_vitest9.it)("claim() filters by lane when supplied and returns lane on the Lease", async () => {
|
|
1408
1892
|
const tag = uid();
|
|
1409
1893
|
const src1 = `lane-claim-src1-${tag}`;
|
|
1410
1894
|
const src2 = `lane-claim-src2-${tag}`;
|
|
@@ -1428,19 +1912,19 @@ var runStoreTck = (options) => {
|
|
|
1428
1912
|
const slow_mine = slow.filter(
|
|
1429
1913
|
(l) => l.stream === sub_default || l.stream === sub_slow
|
|
1430
1914
|
);
|
|
1431
|
-
(0,
|
|
1432
|
-
(0,
|
|
1915
|
+
(0, import_vitest9.expect)(slow_mine.map((l) => l.stream)).toEqual([sub_slow]);
|
|
1916
|
+
(0, import_vitest9.expect)(slow_mine[0]?.lane).toBe("slow");
|
|
1433
1917
|
await store.ack(slow_mine.map((l) => ({ ...l, at: l.at + 1 })));
|
|
1434
1918
|
const all = await store.claim(50, 0, `w-all-${tag}`, 1e3);
|
|
1435
1919
|
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
|
-
|
|
1920
|
+
(0, import_vitest9.expect)(all_mine).toEqual(
|
|
1921
|
+
import_vitest9.expect.arrayContaining([
|
|
1438
1922
|
{ stream: sub_default, lane: "default" },
|
|
1439
1923
|
{ stream: sub_slow, lane: "slow" }
|
|
1440
1924
|
])
|
|
1441
1925
|
);
|
|
1442
1926
|
});
|
|
1443
|
-
(0,
|
|
1927
|
+
(0, import_vitest9.it)("query_streams filters by lane", async () => {
|
|
1444
1928
|
const tag = uid();
|
|
1445
1929
|
const a = `lane-q-a-${tag}`;
|
|
1446
1930
|
const b = `lane-q-b-${tag}`;
|
|
@@ -1456,9 +1940,9 @@ var runStoreTck = (options) => {
|
|
|
1456
1940
|
stream: `lane-q-.*-${tag}`,
|
|
1457
1941
|
limit: 100
|
|
1458
1942
|
});
|
|
1459
|
-
(0,
|
|
1943
|
+
(0, import_vitest9.expect)(seen.sort()).toEqual([a, c]);
|
|
1460
1944
|
});
|
|
1461
|
-
(0,
|
|
1945
|
+
(0, import_vitest9.it)("prioritize filters by lane", async () => {
|
|
1462
1946
|
const tag = uid();
|
|
1463
1947
|
const a = `lane-pri-a-${tag}`;
|
|
1464
1948
|
const b = `lane-pri-b-${tag}`;
|
|
@@ -1467,16 +1951,16 @@ var runStoreTck = (options) => {
|
|
|
1467
1951
|
{ stream: b, lane: `pfast-${tag}` }
|
|
1468
1952
|
]);
|
|
1469
1953
|
const updated = await store.prioritize({ lane: `pslow-${tag}` }, 7);
|
|
1470
|
-
(0,
|
|
1954
|
+
(0, import_vitest9.expect)(updated).toBe(1);
|
|
1471
1955
|
const seen = /* @__PURE__ */ new Map();
|
|
1472
1956
|
await store.query_streams((p) => seen.set(p.stream, p.priority), {
|
|
1473
1957
|
stream: `lane-pri-.*-${tag}`,
|
|
1474
1958
|
limit: 100
|
|
1475
1959
|
});
|
|
1476
|
-
(0,
|
|
1477
|
-
(0,
|
|
1960
|
+
(0, import_vitest9.expect)(seen.get(a)).toBe(7);
|
|
1961
|
+
(0, import_vitest9.expect)(seen.get(b)).toBe(0);
|
|
1478
1962
|
});
|
|
1479
|
-
(0,
|
|
1963
|
+
(0, import_vitest9.it)("reset filters by lane", async () => {
|
|
1480
1964
|
const tag = uid();
|
|
1481
1965
|
const src = `lane-reset-src-${tag}`;
|
|
1482
1966
|
const a = `lane-reset-a-${tag}`;
|
|
@@ -1494,7 +1978,7 @@ var runStoreTck = (options) => {
|
|
|
1494
1978
|
const mine = leases.filter((l) => l.stream === a || l.stream === b);
|
|
1495
1979
|
await store.ack(mine.map((l) => ({ ...l, at: l.at + 1 })));
|
|
1496
1980
|
const count = await store.reset({ lane: `rslow-${tag}` });
|
|
1497
|
-
(0,
|
|
1981
|
+
(0, import_vitest9.expect)(count).toBe(1);
|
|
1498
1982
|
const ats = /* @__PURE__ */ new Map();
|
|
1499
1983
|
for (const name of [a, b]) {
|
|
1500
1984
|
await store.query_streams((p) => ats.set(p.stream, p.at), {
|
|
@@ -1502,10 +1986,10 @@ var runStoreTck = (options) => {
|
|
|
1502
1986
|
stream_exact: true
|
|
1503
1987
|
});
|
|
1504
1988
|
}
|
|
1505
|
-
(0,
|
|
1506
|
-
(0,
|
|
1989
|
+
(0, import_vitest9.expect)(ats.get(a)).toBe(-1);
|
|
1990
|
+
(0, import_vitest9.expect)(ats.get(b)).toBeGreaterThanOrEqual(0);
|
|
1507
1991
|
});
|
|
1508
|
-
(0,
|
|
1992
|
+
(0, import_vitest9.it)("unblock filters by lane", async () => {
|
|
1509
1993
|
const tag = uid();
|
|
1510
1994
|
const src = `lane-ub-src-${tag}`;
|
|
1511
1995
|
const a = `lane-ub-a-${tag}`;
|
|
@@ -1523,7 +2007,7 @@ var runStoreTck = (options) => {
|
|
|
1523
2007
|
const mine = leases.filter((l) => l.stream === a || l.stream === b);
|
|
1524
2008
|
await store.block(mine.map((l) => ({ ...l, error: "boom" })));
|
|
1525
2009
|
const count = await store.unblock({ lane: `uslow-${tag}` });
|
|
1526
|
-
(0,
|
|
2010
|
+
(0, import_vitest9.expect)(count).toBe(1);
|
|
1527
2011
|
const blocked = /* @__PURE__ */ new Map();
|
|
1528
2012
|
for (const name of [a, b]) {
|
|
1529
2013
|
await store.query_streams((p) => blocked.set(p.stream, p.blocked), {
|
|
@@ -1531,12 +2015,12 @@ var runStoreTck = (options) => {
|
|
|
1531
2015
|
stream_exact: true
|
|
1532
2016
|
});
|
|
1533
2017
|
}
|
|
1534
|
-
(0,
|
|
1535
|
-
(0,
|
|
2018
|
+
(0, import_vitest9.expect)(blocked.get(a)).toBe(false);
|
|
2019
|
+
(0, import_vitest9.expect)(blocked.get(b)).toBe(true);
|
|
1536
2020
|
});
|
|
1537
2021
|
});
|
|
1538
|
-
(0,
|
|
1539
|
-
(0,
|
|
2022
|
+
(0, import_vitest9.describe)("truncate", () => {
|
|
2023
|
+
(0, import_vitest9.it)("seeds a tombstone when no snapshot is provided", async () => {
|
|
1540
2024
|
const s = `trunc-tomb-${uid()}`;
|
|
1541
2025
|
await store.commit(
|
|
1542
2026
|
s,
|
|
@@ -1544,7 +2028,7 @@ var runStoreTck = (options) => {
|
|
|
1544
2028
|
make_meta({ stream: s })
|
|
1545
2029
|
);
|
|
1546
2030
|
const result = await store.truncate([{ stream: s }]);
|
|
1547
|
-
(0,
|
|
2031
|
+
(0, import_vitest9.expect)(result.get(s)?.deleted).toBe(2);
|
|
1548
2032
|
const remaining = [];
|
|
1549
2033
|
await store.query(
|
|
1550
2034
|
(e) => {
|
|
@@ -1552,12 +2036,12 @@ var runStoreTck = (options) => {
|
|
|
1552
2036
|
},
|
|
1553
2037
|
{ stream: s, stream_exact: true }
|
|
1554
2038
|
);
|
|
1555
|
-
(0,
|
|
1556
|
-
(0,
|
|
2039
|
+
(0, import_vitest9.expect)(remaining).toHaveLength(1);
|
|
2040
|
+
(0, import_vitest9.expect)(remaining[0].name).toBe(
|
|
1557
2041
|
"__tombstone__"
|
|
1558
2042
|
);
|
|
1559
2043
|
});
|
|
1560
|
-
(0,
|
|
2044
|
+
(0, import_vitest9.it)("seeds a snapshot when one is provided", async () => {
|
|
1561
2045
|
const s = `trunc-snap-${uid()}`;
|
|
1562
2046
|
await store.commit(
|
|
1563
2047
|
s,
|
|
@@ -1567,7 +2051,7 @@ var runStoreTck = (options) => {
|
|
|
1567
2051
|
const result = await store.truncate([
|
|
1568
2052
|
{ stream: s, snapshot: { count: 7 } }
|
|
1569
2053
|
]);
|
|
1570
|
-
(0,
|
|
2054
|
+
(0, import_vitest9.expect)(result.get(s)?.deleted).toBe(1);
|
|
1571
2055
|
const remaining = [];
|
|
1572
2056
|
await store.query(
|
|
1573
2057
|
(e) => {
|
|
@@ -1575,24 +2059,24 @@ var runStoreTck = (options) => {
|
|
|
1575
2059
|
},
|
|
1576
2060
|
{ stream: s, stream_exact: true, with_snaps: true }
|
|
1577
2061
|
);
|
|
1578
|
-
(0,
|
|
1579
|
-
(0,
|
|
2062
|
+
(0, import_vitest9.expect)(remaining).toHaveLength(1);
|
|
2063
|
+
(0, import_vitest9.expect)(remaining[0].name).toBe(
|
|
1580
2064
|
"__snapshot__"
|
|
1581
2065
|
);
|
|
1582
|
-
(0,
|
|
2066
|
+
(0, import_vitest9.expect)(remaining[0].data).toEqual({ count: 7 });
|
|
1583
2067
|
});
|
|
1584
|
-
(0,
|
|
2068
|
+
(0, import_vitest9.it)("returns an empty map for empty input", async () => {
|
|
1585
2069
|
const result = await store.truncate([]);
|
|
1586
|
-
(0,
|
|
2070
|
+
(0, import_vitest9.expect)(result.size).toBe(0);
|
|
1587
2071
|
});
|
|
1588
|
-
(0,
|
|
2072
|
+
(0, import_vitest9.it)("returns 0 deleted for streams that don't exist", async () => {
|
|
1589
2073
|
const s = `trunc-missing-${uid()}`;
|
|
1590
2074
|
const result = await store.truncate([{ stream: s }]);
|
|
1591
|
-
(0,
|
|
2075
|
+
(0, import_vitest9.expect)(result.get(s)?.deleted).toBe(0);
|
|
1592
2076
|
});
|
|
1593
2077
|
});
|
|
1594
|
-
(0,
|
|
1595
|
-
(0,
|
|
2078
|
+
(0, import_vitest9.describe)("query_streams", () => {
|
|
2079
|
+
(0, import_vitest9.it)("returns positions filtered by stream regex, exact, source, and source_exact", async () => {
|
|
1596
2080
|
const tag = uid();
|
|
1597
2081
|
const proj1 = `qs-${tag}-projection-tickets`;
|
|
1598
2082
|
const proj2 = `qs-${tag}-projection-users`;
|
|
@@ -1611,37 +2095,37 @@ var runStoreTck = (options) => {
|
|
|
1611
2095
|
(p) => all.push({ stream: p.stream, source: p.source }),
|
|
1612
2096
|
{ stream: `qs-${tag}-.*` }
|
|
1613
2097
|
);
|
|
1614
|
-
(0,
|
|
1615
|
-
(0,
|
|
1616
|
-
(0,
|
|
2098
|
+
(0, import_vitest9.expect)(all_result.count).toBe(4);
|
|
2099
|
+
(0, import_vitest9.expect)(all_result.maxEventId).toBeGreaterThanOrEqual(-1);
|
|
2100
|
+
(0, import_vitest9.expect)(all.map((p) => p.stream).sort()).toEqual(
|
|
1617
2101
|
[proj1, proj2, dyn1, dyn2].sort()
|
|
1618
2102
|
);
|
|
1619
2103
|
const projections = [];
|
|
1620
2104
|
await store.query_streams((p) => projections.push(p.stream), {
|
|
1621
2105
|
stream: `qs-${tag}-projection-.*`
|
|
1622
2106
|
});
|
|
1623
|
-
(0,
|
|
2107
|
+
(0, import_vitest9.expect)(projections.sort()).toEqual([proj1, proj2].sort());
|
|
1624
2108
|
const exact = [];
|
|
1625
2109
|
await store.query_streams((p) => exact.push(p.stream), {
|
|
1626
2110
|
stream: dyn1,
|
|
1627
2111
|
stream_exact: true
|
|
1628
2112
|
});
|
|
1629
|
-
(0,
|
|
2113
|
+
(0, import_vitest9.expect)(exact).toEqual([dyn1]);
|
|
1630
2114
|
const by_source = [];
|
|
1631
2115
|
await store.query_streams((p) => by_source.push(p.stream), {
|
|
1632
2116
|
stream: `qs-${tag}-.*`,
|
|
1633
2117
|
source: `qs-${tag}-src-.*`
|
|
1634
2118
|
});
|
|
1635
|
-
(0,
|
|
2119
|
+
(0, import_vitest9.expect)(by_source.sort()).toEqual([dyn1, dyn2].sort());
|
|
1636
2120
|
const exact_source = [];
|
|
1637
2121
|
await store.query_streams((p) => exact_source.push(p.stream), {
|
|
1638
2122
|
stream: `qs-${tag}-.*`,
|
|
1639
2123
|
source: src2,
|
|
1640
2124
|
source_exact: true
|
|
1641
2125
|
});
|
|
1642
|
-
(0,
|
|
2126
|
+
(0, import_vitest9.expect)(exact_source).toEqual([dyn2]);
|
|
1643
2127
|
});
|
|
1644
|
-
(0,
|
|
2128
|
+
(0, import_vitest9.it)("paginates with limit + after (keyset)", async () => {
|
|
1645
2129
|
const tag = uid();
|
|
1646
2130
|
const streams = [
|
|
1647
2131
|
`qp-${tag}-a`,
|
|
@@ -1655,17 +2139,17 @@ var runStoreTck = (options) => {
|
|
|
1655
2139
|
stream: `qp-${tag}-.*`,
|
|
1656
2140
|
limit: 2
|
|
1657
2141
|
});
|
|
1658
|
-
(0,
|
|
2142
|
+
(0, import_vitest9.expect)(page1).toHaveLength(2);
|
|
1659
2143
|
const page2 = [];
|
|
1660
2144
|
await store.query_streams((p) => page2.push(p.stream), {
|
|
1661
2145
|
stream: `qp-${tag}-.*`,
|
|
1662
2146
|
limit: 2,
|
|
1663
2147
|
after: page1.at(-1)
|
|
1664
2148
|
});
|
|
1665
|
-
(0,
|
|
1666
|
-
(0,
|
|
2149
|
+
(0, import_vitest9.expect)(page2).toHaveLength(2);
|
|
2150
|
+
(0, import_vitest9.expect)([...page1, ...page2].sort()).toEqual([...streams].sort());
|
|
1667
2151
|
});
|
|
1668
|
-
(0,
|
|
2152
|
+
(0, import_vitest9.it)("filters by blocked status", async () => {
|
|
1669
2153
|
const tag = uid();
|
|
1670
2154
|
const s = `qb-${tag}`;
|
|
1671
2155
|
const sibling = `qb-${tag}-other`;
|
|
@@ -1685,18 +2169,18 @@ var runStoreTck = (options) => {
|
|
|
1685
2169
|
(p) => blocked.push({ stream: p.stream, error: p.error }),
|
|
1686
2170
|
{ stream: `qb-${tag}.*`, blocked: true }
|
|
1687
2171
|
);
|
|
1688
|
-
(0,
|
|
1689
|
-
(0,
|
|
2172
|
+
(0, import_vitest9.expect)(blocked).toHaveLength(1);
|
|
2173
|
+
(0, import_vitest9.expect)(blocked[0].error).toBe("boom");
|
|
1690
2174
|
const unblocked = [];
|
|
1691
2175
|
await store.query_streams((p) => unblocked.push(p.stream), {
|
|
1692
2176
|
stream: `qb-${tag}.*`,
|
|
1693
2177
|
blocked: false
|
|
1694
2178
|
});
|
|
1695
|
-
(0,
|
|
2179
|
+
(0, import_vitest9.expect)(unblocked).toEqual([sibling]);
|
|
1696
2180
|
});
|
|
1697
2181
|
});
|
|
1698
|
-
(0,
|
|
1699
|
-
(0,
|
|
2182
|
+
(0, import_vitest9.describe)("query_stats", () => {
|
|
2183
|
+
(0, import_vitest9.it)("array input \u2014 returns head per stream, absent when not in input", async () => {
|
|
1700
2184
|
const tag = uid();
|
|
1701
2185
|
const sA = `qst-${tag}-a`;
|
|
1702
2186
|
const sB = `qst-${tag}-b`;
|
|
@@ -1717,18 +2201,18 @@ var runStoreTck = (options) => {
|
|
|
1717
2201
|
make_meta({ stream: sUnasked })
|
|
1718
2202
|
);
|
|
1719
2203
|
const stats = await store.query_stats([sA, sB]);
|
|
1720
|
-
(0,
|
|
1721
|
-
(0,
|
|
1722
|
-
(0,
|
|
1723
|
-
(0,
|
|
1724
|
-
(0,
|
|
1725
|
-
(0,
|
|
2204
|
+
(0, import_vitest9.expect)(stats.size).toBe(2);
|
|
2205
|
+
(0, import_vitest9.expect)(stats.get(sA)?.head.name).toBe("Incremented");
|
|
2206
|
+
(0, import_vitest9.expect)((stats.get(sA)?.head.data).amount).toBe(2);
|
|
2207
|
+
(0, import_vitest9.expect)(stats.get(sB)?.head.name).toBe("Decremented");
|
|
2208
|
+
(0, import_vitest9.expect)((stats.get(sB)?.head.data).amount).toBe(5);
|
|
2209
|
+
(0, import_vitest9.expect)(stats.has(sUnasked)).toBe(false);
|
|
1726
2210
|
const empty = await store.query_stats([]);
|
|
1727
|
-
(0,
|
|
2211
|
+
(0, import_vitest9.expect)(empty.size).toBe(0);
|
|
1728
2212
|
const unknown = await store.query_stats([`qst-${tag}-missing`]);
|
|
1729
|
-
(0,
|
|
2213
|
+
(0, import_vitest9.expect)(unknown.size).toBe(0);
|
|
1730
2214
|
});
|
|
1731
|
-
(0,
|
|
2215
|
+
(0, import_vitest9.it)("tail returns the earliest event per stream", async () => {
|
|
1732
2216
|
const tag = uid();
|
|
1733
2217
|
const s = `qst-tail-${tag}`;
|
|
1734
2218
|
await store.commit(
|
|
@@ -1750,12 +2234,12 @@ var runStoreTck = (options) => {
|
|
|
1750
2234
|
tail: true
|
|
1751
2235
|
});
|
|
1752
2236
|
const r = stats.get(s);
|
|
1753
|
-
(0,
|
|
1754
|
-
(0,
|
|
1755
|
-
(0,
|
|
1756
|
-
(0,
|
|
2237
|
+
(0, import_vitest9.expect)(r?.head.name).toBe("Incremented");
|
|
2238
|
+
(0, import_vitest9.expect)((r?.head.data).amount).toBe(3);
|
|
2239
|
+
(0, import_vitest9.expect)(r?.tail?.name).toBe("Incremented");
|
|
2240
|
+
(0, import_vitest9.expect)((r?.tail?.data).amount).toBe(1);
|
|
1757
2241
|
});
|
|
1758
|
-
(0,
|
|
2242
|
+
(0, import_vitest9.it)("count + names \u2014 full aggregates including framework markers", async () => {
|
|
1759
2243
|
const tag = uid();
|
|
1760
2244
|
const s = `qst-cn-${tag}`;
|
|
1761
2245
|
await store.commit(
|
|
@@ -1774,13 +2258,13 @@ var runStoreTck = (options) => {
|
|
|
1774
2258
|
names: true
|
|
1775
2259
|
});
|
|
1776
2260
|
const r = stats.get(s);
|
|
1777
|
-
(0,
|
|
1778
|
-
(0,
|
|
1779
|
-
(0,
|
|
1780
|
-
(0,
|
|
1781
|
-
(0,
|
|
2261
|
+
(0, import_vitest9.expect)(r?.count).toBe(4);
|
|
2262
|
+
(0, import_vitest9.expect)(r?.names?.[import_act2.SNAP_EVENT]).toBe(1);
|
|
2263
|
+
(0, import_vitest9.expect)(r?.names?.Incremented).toBe(2);
|
|
2264
|
+
(0, import_vitest9.expect)(r?.names?.Decremented).toBe(1);
|
|
2265
|
+
(0, import_vitest9.expect)(r?.names?.[import_act2.SNAP_EVENT]).toBe(1);
|
|
1782
2266
|
});
|
|
1783
|
-
(0,
|
|
2267
|
+
(0, import_vitest9.it)("exclude shifts head past filtered events; stream absent when all filtered", async () => {
|
|
1784
2268
|
const tag = uid();
|
|
1785
2269
|
const s = `qst-excl-${tag}`;
|
|
1786
2270
|
const sAllOut = `qst-allout-${tag}`;
|
|
@@ -1795,23 +2279,23 @@ var runStoreTck = (options) => {
|
|
|
1795
2279
|
make_meta({ stream: sAllOut })
|
|
1796
2280
|
);
|
|
1797
2281
|
const all = await store.query_stats([s]);
|
|
1798
|
-
(0,
|
|
1799
|
-
(0,
|
|
2282
|
+
(0, import_vitest9.expect)(all.get(s)?.head.name).toBe("Incremented");
|
|
2283
|
+
(0, import_vitest9.expect)((all.get(s)?.head.data).amount).toBe(3);
|
|
1800
2284
|
const excl = await store.query_stats([s], {
|
|
1801
2285
|
exclude: ["Incremented"]
|
|
1802
2286
|
});
|
|
1803
|
-
(0,
|
|
1804
|
-
(0,
|
|
2287
|
+
(0, import_vitest9.expect)(excl.get(s)?.head.name).toBe("Decremented");
|
|
2288
|
+
(0, import_vitest9.expect)((excl.get(s)?.head.data).amount).toBe(2);
|
|
1805
2289
|
const wipe = await store.query_stats([sAllOut], {
|
|
1806
2290
|
exclude: ["Incremented", "Decremented", "Reset"]
|
|
1807
2291
|
});
|
|
1808
|
-
(0,
|
|
2292
|
+
(0, import_vitest9.expect)(wipe.has(sAllOut)).toBe(false);
|
|
1809
2293
|
const no_tomb = await store.query_stats([s], {
|
|
1810
|
-
exclude: [
|
|
2294
|
+
exclude: [import_act2.TOMBSTONE_EVENT]
|
|
1811
2295
|
});
|
|
1812
|
-
(0,
|
|
2296
|
+
(0, import_vitest9.expect)(no_tomb.get(s)?.head.name).toBe("Incremented");
|
|
1813
2297
|
});
|
|
1814
|
-
(0,
|
|
2298
|
+
(0, import_vitest9.it)("before \u2014 time travel narrows head/tail/count", async () => {
|
|
1815
2299
|
const tag = uid();
|
|
1816
2300
|
const s = `qst-tt-${tag}`;
|
|
1817
2301
|
const c1 = await store.commit(
|
|
@@ -1836,15 +2320,15 @@ var runStoreTck = (options) => {
|
|
|
1836
2320
|
before
|
|
1837
2321
|
});
|
|
1838
2322
|
const r = stats.get(s);
|
|
1839
|
-
(0,
|
|
1840
|
-
(0,
|
|
1841
|
-
(0,
|
|
2323
|
+
(0, import_vitest9.expect)(r?.count).toBe(1);
|
|
2324
|
+
(0, import_vitest9.expect)(r?.head.id).toBe(c1[0].id);
|
|
2325
|
+
(0, import_vitest9.expect)(r?.tail?.id).toBe(c1[0].id);
|
|
1842
2326
|
const empty = await store.query_stats([s], {
|
|
1843
2327
|
before: 0
|
|
1844
2328
|
});
|
|
1845
|
-
(0,
|
|
2329
|
+
(0, import_vitest9.expect)(empty.has(s)).toBe(false);
|
|
1846
2330
|
});
|
|
1847
|
-
(0,
|
|
2331
|
+
(0, import_vitest9.it)("filter form \u2014 stream regex, stream_exact, empty {} match", async () => {
|
|
1848
2332
|
const tag = uid();
|
|
1849
2333
|
const sA = `qsf-${tag}-orders-1`;
|
|
1850
2334
|
const sB = `qsf-${tag}-orders-2`;
|
|
@@ -1867,18 +2351,18 @@ var runStoreTck = (options) => {
|
|
|
1867
2351
|
const orders = await store.query_stats({
|
|
1868
2352
|
stream: `^qsf-${tag}-orders-`
|
|
1869
2353
|
});
|
|
1870
|
-
(0,
|
|
2354
|
+
(0, import_vitest9.expect)([...orders.keys()].sort()).toEqual([sA, sB].sort());
|
|
1871
2355
|
const exact = await store.query_stats({
|
|
1872
2356
|
stream: sA,
|
|
1873
2357
|
stream_exact: true
|
|
1874
2358
|
});
|
|
1875
|
-
(0,
|
|
2359
|
+
(0, import_vitest9.expect)([...exact.keys()]).toEqual([sA]);
|
|
1876
2360
|
const all = await store.query_stats({
|
|
1877
2361
|
stream: `^qsf-${tag}-`
|
|
1878
2362
|
});
|
|
1879
|
-
(0,
|
|
2363
|
+
(0, import_vitest9.expect)([...all.keys()].sort()).toEqual([sA, sB, sOther].sort());
|
|
1880
2364
|
});
|
|
1881
|
-
(0,
|
|
2365
|
+
(0, import_vitest9.it)("compose with query_streams for subscription-level filters", async () => {
|
|
1882
2366
|
const tag = uid();
|
|
1883
2367
|
const a = `qsc-${tag}-a`;
|
|
1884
2368
|
const b = `qsc-${tag}-b`;
|
|
@@ -1895,7 +2379,7 @@ var runStoreTck = (options) => {
|
|
|
1895
2379
|
);
|
|
1896
2380
|
const leased = await store.claim(100, 0, `w-${uid()}`, 1e5);
|
|
1897
2381
|
const mine = leased.find((l) => l.stream === a);
|
|
1898
|
-
(0,
|
|
2382
|
+
(0, import_vitest9.expect)(mine).toBeDefined();
|
|
1899
2383
|
const others = leased.filter((l) => l.stream !== a);
|
|
1900
2384
|
await store.ack(others);
|
|
1901
2385
|
await store.block([{ ...mine, error: "boom" }]);
|
|
@@ -1904,12 +2388,12 @@ var runStoreTck = (options) => {
|
|
|
1904
2388
|
stream: `^qsc-${tag}-`,
|
|
1905
2389
|
blocked: true
|
|
1906
2390
|
});
|
|
1907
|
-
(0,
|
|
2391
|
+
(0, import_vitest9.expect)(blocked_names).toEqual([a]);
|
|
1908
2392
|
const stats = await store.query_stats(blocked_names);
|
|
1909
|
-
(0,
|
|
1910
|
-
(0,
|
|
2393
|
+
(0, import_vitest9.expect)(stats.get(a)?.head.name).toBe("Incremented");
|
|
2394
|
+
(0, import_vitest9.expect)(stats.has(b)).toBe(false);
|
|
1911
2395
|
});
|
|
1912
|
-
(0,
|
|
2396
|
+
(0, import_vitest9.it)("empty filter {} \u2014 matches every event-bearing stream", async () => {
|
|
1913
2397
|
const tag = uid();
|
|
1914
2398
|
const a = `qse-${tag}-a`;
|
|
1915
2399
|
const b = `qse-${tag}-b`;
|
|
@@ -1924,10 +2408,10 @@ var runStoreTck = (options) => {
|
|
|
1924
2408
|
make_meta({ stream: b })
|
|
1925
2409
|
);
|
|
1926
2410
|
const all = await store.query_stats({});
|
|
1927
|
-
(0,
|
|
1928
|
-
(0,
|
|
2411
|
+
(0, import_vitest9.expect)(all.has(a)).toBe(true);
|
|
2412
|
+
(0, import_vitest9.expect)(all.has(b)).toBe(true);
|
|
1929
2413
|
});
|
|
1930
|
-
(0,
|
|
2414
|
+
(0, import_vitest9.it)("stat-flag combinations \u2014 count-only, names-only, tail-only", async () => {
|
|
1931
2415
|
const tag = uid();
|
|
1932
2416
|
const s = `qsfl-${tag}`;
|
|
1933
2417
|
await store.commit(
|
|
@@ -1938,22 +2422,22 @@ var runStoreTck = (options) => {
|
|
|
1938
2422
|
const c = await store.query_stats([s], {
|
|
1939
2423
|
count: true
|
|
1940
2424
|
});
|
|
1941
|
-
(0,
|
|
1942
|
-
(0,
|
|
1943
|
-
(0,
|
|
2425
|
+
(0, import_vitest9.expect)(c.get(s)?.count).toBe(3);
|
|
2426
|
+
(0, import_vitest9.expect)(c.get(s)?.names).toBeUndefined();
|
|
2427
|
+
(0, import_vitest9.expect)(c.get(s)?.tail).toBeUndefined();
|
|
1944
2428
|
const n = await store.query_stats([s], {
|
|
1945
2429
|
names: true
|
|
1946
2430
|
});
|
|
1947
|
-
(0,
|
|
1948
|
-
(0,
|
|
1949
|
-
(0,
|
|
2431
|
+
(0, import_vitest9.expect)(n.get(s)?.names).toEqual({ Incremented: 2, Decremented: 1 });
|
|
2432
|
+
(0, import_vitest9.expect)(n.get(s)?.count).toBeUndefined();
|
|
2433
|
+
(0, import_vitest9.expect)(n.get(s)?.tail).toBeUndefined();
|
|
1950
2434
|
const t = await store.query_stats([s], { tail: true });
|
|
1951
|
-
(0,
|
|
1952
|
-
(0,
|
|
1953
|
-
(0,
|
|
1954
|
-
(0,
|
|
2435
|
+
(0, import_vitest9.expect)(t.get(s)?.tail?.name).toBe("Incremented");
|
|
2436
|
+
(0, import_vitest9.expect)((t.get(s)?.tail?.data).amount).toBe(1);
|
|
2437
|
+
(0, import_vitest9.expect)(t.get(s)?.count).toBeUndefined();
|
|
2438
|
+
(0, import_vitest9.expect)(t.get(s)?.names).toBeUndefined();
|
|
1955
2439
|
});
|
|
1956
|
-
(0,
|
|
2440
|
+
(0, import_vitest9.it)("paginates with limit + after (keyset), ordered by stream name", async () => {
|
|
1957
2441
|
const tag = uid();
|
|
1958
2442
|
const streams = [
|
|
1959
2443
|
`qsp-${tag}-a`,
|
|
@@ -1973,28 +2457,28 @@ var runStoreTck = (options) => {
|
|
|
1973
2457
|
{ limit: 2 }
|
|
1974
2458
|
);
|
|
1975
2459
|
const k1 = [...page1.keys()];
|
|
1976
|
-
(0,
|
|
2460
|
+
(0, import_vitest9.expect)(k1).toEqual([`qsp-${tag}-a`, `qsp-${tag}-b`]);
|
|
1977
2461
|
const page2 = await store.query_stats(
|
|
1978
2462
|
{ stream: `qsp-${tag}-.*` },
|
|
1979
2463
|
{ limit: 2, after: k1.at(-1) }
|
|
1980
2464
|
);
|
|
1981
2465
|
const k2 = [...page2.keys()];
|
|
1982
|
-
(0,
|
|
2466
|
+
(0, import_vitest9.expect)(k2).toEqual([`qsp-${tag}-c`, `qsp-${tag}-d`]);
|
|
1983
2467
|
const page3 = await store.query_stats(
|
|
1984
2468
|
{ stream: `qsp-${tag}-.*` },
|
|
1985
2469
|
{ limit: 2, after: k2.at(-1) }
|
|
1986
2470
|
);
|
|
1987
|
-
(0,
|
|
2471
|
+
(0, import_vitest9.expect)(page3.size).toBe(0);
|
|
1988
2472
|
const all = await store.query_stats({
|
|
1989
2473
|
stream: `qsp-${tag}-.*`
|
|
1990
2474
|
});
|
|
1991
|
-
(0,
|
|
2475
|
+
(0, import_vitest9.expect)([...all.keys()].sort()).toEqual([...streams].sort());
|
|
1992
2476
|
});
|
|
1993
2477
|
});
|
|
1994
|
-
|
|
2478
|
+
import_vitest9.describe.skipIf(!caps.source_matches)(
|
|
1995
2479
|
"query_streams source_matches (capability)",
|
|
1996
2480
|
() => {
|
|
1997
|
-
(0,
|
|
2481
|
+
(0, import_vitest9.it)("returns only subscriptions whose source pattern matches a name", async () => {
|
|
1998
2482
|
const tag = uid();
|
|
1999
2483
|
const subConcreteA = `sm-${tag}-sub-a`;
|
|
2000
2484
|
const subConcreteB = `sm-${tag}-sub-b`;
|
|
@@ -2015,7 +2499,7 @@ var runStoreTck = (options) => {
|
|
|
2015
2499
|
stream: `sm-${tag}-sub-.*`,
|
|
2016
2500
|
source_matches: [srcA]
|
|
2017
2501
|
});
|
|
2018
|
-
(0,
|
|
2502
|
+
(0, import_vitest9.expect)(matched.sort()).toEqual(
|
|
2019
2503
|
[subConcreteA, subRegex, subNoSource].sort()
|
|
2020
2504
|
);
|
|
2021
2505
|
const none = [];
|
|
@@ -2023,20 +2507,20 @@ var runStoreTck = (options) => {
|
|
|
2023
2507
|
stream: `sm-${tag}-sub-.*`,
|
|
2024
2508
|
source_matches: [`sm-${tag}-unrelated`]
|
|
2025
2509
|
});
|
|
2026
|
-
(0,
|
|
2510
|
+
(0, import_vitest9.expect)(none).toEqual([subNoSource]);
|
|
2027
2511
|
const both = [];
|
|
2028
2512
|
await store.query_streams((p) => both.push(p.stream), {
|
|
2029
2513
|
stream: `sm-${tag}-sub-.*`,
|
|
2030
2514
|
source_matches: [srcA, srcB]
|
|
2031
2515
|
});
|
|
2032
|
-
(0,
|
|
2516
|
+
(0, import_vitest9.expect)(both.sort()).toEqual(
|
|
2033
2517
|
[subConcreteA, subConcreteB, subRegex, subNoSource].sort()
|
|
2034
2518
|
);
|
|
2035
2519
|
});
|
|
2036
2520
|
}
|
|
2037
2521
|
);
|
|
2038
|
-
(0,
|
|
2039
|
-
(0,
|
|
2522
|
+
(0, import_vitest9.describe)("query_streams anchor contract", () => {
|
|
2523
|
+
(0, import_vitest9.it)("plain regex without anchors is a substring match", async () => {
|
|
2040
2524
|
const tag = uid();
|
|
2041
2525
|
const inner = `qsr-${tag}-inner`;
|
|
2042
2526
|
const longer = `qsr-${tag}-inner-extra`;
|
|
@@ -2050,9 +2534,9 @@ var runStoreTck = (options) => {
|
|
|
2050
2534
|
await store.query_streams((p) => seen.push(p.stream), {
|
|
2051
2535
|
stream: `qsr-${tag}-inner`
|
|
2052
2536
|
});
|
|
2053
|
-
(0,
|
|
2537
|
+
(0, import_vitest9.expect)(seen.sort()).toEqual([inner, longer].sort());
|
|
2054
2538
|
});
|
|
2055
|
-
(0,
|
|
2539
|
+
(0, import_vitest9.it)("caller-anchored `^name$` matches only the whole string", async () => {
|
|
2056
2540
|
const tag = uid();
|
|
2057
2541
|
const inner = `qsr-${tag}-anchor`;
|
|
2058
2542
|
const longer = `qsr-${tag}-anchor-extra`;
|
|
@@ -2061,9 +2545,9 @@ var runStoreTck = (options) => {
|
|
|
2061
2545
|
await store.query_streams((p) => seen.push(p.stream), {
|
|
2062
2546
|
stream: `^qsr-${tag}-anchor$`
|
|
2063
2547
|
});
|
|
2064
|
-
(0,
|
|
2548
|
+
(0, import_vitest9.expect)(seen).toEqual([inner]);
|
|
2065
2549
|
});
|
|
2066
|
-
(0,
|
|
2550
|
+
(0, import_vitest9.it)("caller-anchored `^prefix` matches by prefix", async () => {
|
|
2067
2551
|
const tag = uid();
|
|
2068
2552
|
const a = `qsr-${tag}-pfx-a`;
|
|
2069
2553
|
const b = `qsr-${tag}-pfx-b`;
|
|
@@ -2077,11 +2561,11 @@ var runStoreTck = (options) => {
|
|
|
2077
2561
|
await store.query_streams((p) => seen.push(p.stream), {
|
|
2078
2562
|
stream: `^qsr-${tag}-pfx-`
|
|
2079
2563
|
});
|
|
2080
|
-
(0,
|
|
2564
|
+
(0, import_vitest9.expect)(seen.sort()).toEqual([a, b].sort());
|
|
2081
2565
|
});
|
|
2082
2566
|
});
|
|
2083
|
-
(0,
|
|
2084
|
-
(0,
|
|
2567
|
+
(0, import_vitest9.describe)("prioritize anchor contract", () => {
|
|
2568
|
+
(0, import_vitest9.it)("caller-anchored `^name$` filter matches only the whole string", async () => {
|
|
2085
2569
|
const tag = uid();
|
|
2086
2570
|
const inner = `pr-${tag}-anchor`;
|
|
2087
2571
|
const longer = `pr-${tag}-anchor-extra`;
|
|
@@ -2093,17 +2577,17 @@ var runStoreTck = (options) => {
|
|
|
2093
2577
|
{ stream: `^pr-${tag}-anchor$` },
|
|
2094
2578
|
7
|
|
2095
2579
|
);
|
|
2096
|
-
(0,
|
|
2580
|
+
(0, import_vitest9.expect)(updated).toBe(1);
|
|
2097
2581
|
const seen = /* @__PURE__ */ new Map();
|
|
2098
2582
|
await store.query_streams((p) => seen.set(p.stream, p.priority), {
|
|
2099
2583
|
stream: `pr-${tag}-anchor`
|
|
2100
2584
|
});
|
|
2101
|
-
(0,
|
|
2102
|
-
(0,
|
|
2585
|
+
(0, import_vitest9.expect)(seen.get(inner)).toBe(7);
|
|
2586
|
+
(0, import_vitest9.expect)(seen.get(longer)).toBe(0);
|
|
2103
2587
|
});
|
|
2104
2588
|
});
|
|
2105
|
-
(0,
|
|
2106
|
-
(0,
|
|
2589
|
+
(0, import_vitest9.describe)("query_streams head", () => {
|
|
2590
|
+
(0, import_vitest9.it)("maxEventId tracks the highest committed id", async () => {
|
|
2107
2591
|
const s = `head-${uid()}`;
|
|
2108
2592
|
await store.subscribe([{ stream: s }]);
|
|
2109
2593
|
await store.commit(
|
|
@@ -2116,21 +2600,21 @@ var runStoreTck = (options) => {
|
|
|
2116
2600
|
(p) => positions.push(p.stream),
|
|
2117
2601
|
{ stream: s, stream_exact: true, limit: 1 }
|
|
2118
2602
|
);
|
|
2119
|
-
(0,
|
|
2120
|
-
(0,
|
|
2603
|
+
(0, import_vitest9.expect)(maxEventId).toBeGreaterThanOrEqual(0);
|
|
2604
|
+
(0, import_vitest9.expect)(positions).toEqual([s]);
|
|
2121
2605
|
});
|
|
2122
2606
|
});
|
|
2123
|
-
(0,
|
|
2124
|
-
(0,
|
|
2607
|
+
(0, import_vitest9.describe)("seed_stream helper coverage", () => {
|
|
2608
|
+
(0, import_vitest9.it)("commits N events with monotonically increasing ids", async () => {
|
|
2125
2609
|
const s = `seed-${uid()}`;
|
|
2126
2610
|
const committed = await seed_stream(store, s, 3);
|
|
2127
|
-
(0,
|
|
2611
|
+
(0, import_vitest9.expect)(committed).toHaveLength(3);
|
|
2128
2612
|
for (let i = 1; i < committed.length; i++) {
|
|
2129
|
-
(0,
|
|
2613
|
+
(0, import_vitest9.expect)(committed[i].id).toBeGreaterThan(committed[i - 1].id);
|
|
2130
2614
|
}
|
|
2131
2615
|
});
|
|
2132
2616
|
});
|
|
2133
|
-
|
|
2617
|
+
import_vitest9.describe.skipIf(!caps.restore)("restore (capability)", () => {
|
|
2134
2618
|
beforeEach(async () => {
|
|
2135
2619
|
await store.drop();
|
|
2136
2620
|
await store.seed();
|
|
@@ -2158,8 +2642,8 @@ var runStoreTck = (options) => {
|
|
|
2158
2642
|
meta: { correlation: "restore-tck", causation: {} }
|
|
2159
2643
|
});
|
|
2160
2644
|
const restore = async (source, opts = {}) => {
|
|
2161
|
-
const cache = new
|
|
2162
|
-
const app = (0,
|
|
2645
|
+
const cache = new import_act2.InMemoryCache();
|
|
2646
|
+
const app = (0, import_act2.act)().build({ scoped: { store, cache } });
|
|
2163
2647
|
try {
|
|
2164
2648
|
return await app.restore(source, opts);
|
|
2165
2649
|
} finally {
|
|
@@ -2167,18 +2651,18 @@ var runStoreTck = (options) => {
|
|
|
2167
2651
|
await cache.dispose();
|
|
2168
2652
|
}
|
|
2169
2653
|
};
|
|
2170
|
-
(0,
|
|
2654
|
+
(0, import_vitest9.it)("returns kept=0 on an empty source", async () => {
|
|
2171
2655
|
const result = await restore(as_source([]));
|
|
2172
|
-
(0,
|
|
2173
|
-
(0,
|
|
2174
|
-
(0,
|
|
2656
|
+
(0, import_vitest9.expect)(result.kept).toBe(0);
|
|
2657
|
+
(0, import_vitest9.expect)(result.duration_ms).toBeGreaterThanOrEqual(0);
|
|
2658
|
+
(0, import_vitest9.expect)(result.dropped).toEqual({
|
|
2175
2659
|
closed_streams: 0,
|
|
2176
2660
|
snapshots: 0
|
|
2177
2661
|
});
|
|
2178
2662
|
const events2 = await collect(store, { limit: 10 });
|
|
2179
|
-
(0,
|
|
2663
|
+
(0, import_vitest9.expect)(events2).toHaveLength(0);
|
|
2180
2664
|
});
|
|
2181
|
-
(0,
|
|
2665
|
+
(0, import_vitest9.it)("rebuilds a single stream and preserves `created` verbatim", async () => {
|
|
2182
2666
|
const s = `restore-single-${uid()}`;
|
|
2183
2667
|
const t0 = /* @__PURE__ */ new Date("2020-01-01T00:00:00.000Z");
|
|
2184
2668
|
const t1 = /* @__PURE__ */ new Date("2020-01-02T00:00:00.000Z");
|
|
@@ -2189,7 +2673,7 @@ var runStoreTck = (options) => {
|
|
|
2189
2673
|
event(3, s, 2, "Decremented", t2, { amount: 1 })
|
|
2190
2674
|
];
|
|
2191
2675
|
const result = await restore(as_source(events2));
|
|
2192
|
-
(0,
|
|
2676
|
+
(0, import_vitest9.expect)(result.kept).toBe(3);
|
|
2193
2677
|
const back = [];
|
|
2194
2678
|
await store.query(
|
|
2195
2679
|
(e) => {
|
|
@@ -2197,8 +2681,8 @@ var runStoreTck = (options) => {
|
|
|
2197
2681
|
},
|
|
2198
2682
|
{ stream: s, stream_exact: true }
|
|
2199
2683
|
);
|
|
2200
|
-
(0,
|
|
2201
|
-
(0,
|
|
2684
|
+
(0, import_vitest9.expect)(back).toHaveLength(3);
|
|
2685
|
+
(0, import_vitest9.expect)(
|
|
2202
2686
|
back.map((e) => ({
|
|
2203
2687
|
stream: e.stream,
|
|
2204
2688
|
version: e.version,
|
|
@@ -2230,7 +2714,7 @@ var runStoreTck = (options) => {
|
|
|
2230
2714
|
}
|
|
2231
2715
|
]);
|
|
2232
2716
|
});
|
|
2233
|
-
(0,
|
|
2717
|
+
(0, import_vitest9.it)("rebuilds multiple streams interleaved", async () => {
|
|
2234
2718
|
const a = `restore-multi-a-${uid()}`;
|
|
2235
2719
|
const b = `restore-multi-b-${uid()}`;
|
|
2236
2720
|
const t = /* @__PURE__ */ new Date("2020-06-01T00:00:00.000Z");
|
|
@@ -2241,7 +2725,7 @@ var runStoreTck = (options) => {
|
|
|
2241
2725
|
event(4, b, 1, "Incremented", t, { amount: 30 })
|
|
2242
2726
|
];
|
|
2243
2727
|
const result = await restore(as_source(events2));
|
|
2244
|
-
(0,
|
|
2728
|
+
(0, import_vitest9.expect)(result.kept).toBe(4);
|
|
2245
2729
|
const aBack = [];
|
|
2246
2730
|
const bBack = [];
|
|
2247
2731
|
await store.query(
|
|
@@ -2256,10 +2740,10 @@ var runStoreTck = (options) => {
|
|
|
2256
2740
|
},
|
|
2257
2741
|
{ stream: b, stream_exact: true }
|
|
2258
2742
|
);
|
|
2259
|
-
(0,
|
|
2260
|
-
(0,
|
|
2743
|
+
(0, import_vitest9.expect)(aBack.map((e) => e.version)).toEqual([0, 1]);
|
|
2744
|
+
(0, import_vitest9.expect)(bBack.map((e) => e.version)).toEqual([0, 1]);
|
|
2261
2745
|
});
|
|
2262
|
-
(0,
|
|
2746
|
+
(0, import_vitest9.it)("preserves Date `created` verbatim", async () => {
|
|
2263
2747
|
const s = `restore-isoc-${uid()}`;
|
|
2264
2748
|
const iso = "2021-07-15T12:34:56.789Z";
|
|
2265
2749
|
await restore(
|
|
@@ -2282,10 +2766,10 @@ var runStoreTck = (options) => {
|
|
|
2282
2766
|
},
|
|
2283
2767
|
{ stream: s, stream_exact: true }
|
|
2284
2768
|
);
|
|
2285
|
-
(0,
|
|
2286
|
-
(0,
|
|
2769
|
+
(0, import_vitest9.expect)(back).toHaveLength(1);
|
|
2770
|
+
(0, import_vitest9.expect)(back[0].created.toISOString()).toBe(iso);
|
|
2287
2771
|
});
|
|
2288
|
-
(0,
|
|
2772
|
+
(0, import_vitest9.it)("wipes pre-existing events before inserting", async () => {
|
|
2289
2773
|
const old = `restore-old-${uid()}`;
|
|
2290
2774
|
await store.commit(
|
|
2291
2775
|
old,
|
|
@@ -2301,14 +2785,14 @@ var runStoreTck = (options) => {
|
|
|
2301
2785
|
stream: old,
|
|
2302
2786
|
stream_exact: true
|
|
2303
2787
|
});
|
|
2304
|
-
(0,
|
|
2788
|
+
(0, import_vitest9.expect)(old_back).toHaveLength(0);
|
|
2305
2789
|
const fresh_back = await collect(store, {
|
|
2306
2790
|
stream: fresh,
|
|
2307
2791
|
stream_exact: true
|
|
2308
2792
|
});
|
|
2309
|
-
(0,
|
|
2793
|
+
(0, import_vitest9.expect)(fresh_back).toHaveLength(1);
|
|
2310
2794
|
});
|
|
2311
|
-
(0,
|
|
2795
|
+
(0, import_vitest9.it)("clears subscription/stream-position metadata", async () => {
|
|
2312
2796
|
const sub = `restore-sub-${uid()}`;
|
|
2313
2797
|
await store.subscribe([{ stream: sub, source: "anything" }]);
|
|
2314
2798
|
const collect_streams = async () => {
|
|
@@ -2319,12 +2803,12 @@ var runStoreTck = (options) => {
|
|
|
2319
2803
|
return out;
|
|
2320
2804
|
};
|
|
2321
2805
|
const before = await collect_streams();
|
|
2322
|
-
(0,
|
|
2806
|
+
(0, import_vitest9.expect)(before.includes(sub)).toBe(true);
|
|
2323
2807
|
await restore(as_source([]));
|
|
2324
2808
|
const after = await collect_streams();
|
|
2325
|
-
(0,
|
|
2809
|
+
(0, import_vitest9.expect)(after.includes(sub)).toBe(false);
|
|
2326
2810
|
});
|
|
2327
|
-
(0,
|
|
2811
|
+
(0, import_vitest9.it)("preserves snapshot events through restore", async () => {
|
|
2328
2812
|
const s = `restore-snap-${uid()}`;
|
|
2329
2813
|
const t = /* @__PURE__ */ new Date("2020-04-01T00:00:00.000Z");
|
|
2330
2814
|
await restore(
|
|
@@ -2333,7 +2817,7 @@ var runStoreTck = (options) => {
|
|
|
2333
2817
|
id: 1,
|
|
2334
2818
|
stream: s,
|
|
2335
2819
|
version: 0,
|
|
2336
|
-
name:
|
|
2820
|
+
name: import_act2.SNAP_EVENT,
|
|
2337
2821
|
data: { count: 42 },
|
|
2338
2822
|
created: t,
|
|
2339
2823
|
meta: { correlation: "snap", causation: {} }
|
|
@@ -2345,10 +2829,10 @@ var runStoreTck = (options) => {
|
|
|
2345
2829
|
stream_exact: true,
|
|
2346
2830
|
with_snaps: true
|
|
2347
2831
|
});
|
|
2348
|
-
(0,
|
|
2349
|
-
(0,
|
|
2832
|
+
(0, import_vitest9.expect)(back).toHaveLength(1);
|
|
2833
|
+
(0, import_vitest9.expect)(back[0].name).toBe(import_act2.SNAP_EVENT);
|
|
2350
2834
|
});
|
|
2351
|
-
(0,
|
|
2835
|
+
(0, import_vitest9.it)("rewrites causation refs through the old\u2192new id map", async () => {
|
|
2352
2836
|
const s = `restore-caus-${uid()}`;
|
|
2353
2837
|
const t = /* @__PURE__ */ new Date("2020-08-01T00:00:00.000Z");
|
|
2354
2838
|
const events2 = [
|
|
@@ -2398,12 +2882,12 @@ var runStoreTck = (options) => {
|
|
|
2398
2882
|
},
|
|
2399
2883
|
{ stream: s, stream_exact: true }
|
|
2400
2884
|
);
|
|
2401
|
-
(0,
|
|
2402
|
-
(0,
|
|
2403
|
-
(0,
|
|
2404
|
-
(0,
|
|
2885
|
+
(0, import_vitest9.expect)(back).toHaveLength(3);
|
|
2886
|
+
(0, import_vitest9.expect)(back[0].meta.causation.event).toBeUndefined();
|
|
2887
|
+
(0, import_vitest9.expect)(back[1].meta.causation.event?.id).toBe(back[0].id);
|
|
2888
|
+
(0, import_vitest9.expect)(back[2].meta.causation.event?.id).toBe(back[1].id);
|
|
2405
2889
|
});
|
|
2406
|
-
(0,
|
|
2890
|
+
(0, import_vitest9.it)("leaves causation refs unmapped when the target isn't in the source", async () => {
|
|
2407
2891
|
const s = `restore-orphan-${uid()}`;
|
|
2408
2892
|
const t = /* @__PURE__ */ new Date("2020-09-01T00:00:00.000Z");
|
|
2409
2893
|
await restore(
|
|
@@ -2431,9 +2915,9 @@ var runStoreTck = (options) => {
|
|
|
2431
2915
|
},
|
|
2432
2916
|
{ stream: s, stream_exact: true }
|
|
2433
2917
|
);
|
|
2434
|
-
(0,
|
|
2918
|
+
(0, import_vitest9.expect)(back[0].meta.causation.event?.id).toBe(999);
|
|
2435
2919
|
});
|
|
2436
|
-
(0,
|
|
2920
|
+
(0, import_vitest9.it)("rolls back atomically when the source throws mid-iteration", async () => {
|
|
2437
2921
|
const original = `restore-pre-${uid()}`;
|
|
2438
2922
|
const committed = await store.commit(
|
|
2439
2923
|
original,
|
|
@@ -2459,7 +2943,7 @@ var runStoreTck = (options) => {
|
|
|
2459
2943
|
async dispose() {
|
|
2460
2944
|
}
|
|
2461
2945
|
};
|
|
2462
|
-
await (0,
|
|
2946
|
+
await (0, import_vitest9.expect)(restore(explosive)).rejects.toThrow("boom");
|
|
2463
2947
|
const back = [];
|
|
2464
2948
|
await store.query(
|
|
2465
2949
|
(e) => {
|
|
@@ -2467,10 +2951,10 @@ var runStoreTck = (options) => {
|
|
|
2467
2951
|
},
|
|
2468
2952
|
{ stream: original, stream_exact: true }
|
|
2469
2953
|
);
|
|
2470
|
-
(0,
|
|
2471
|
-
(0,
|
|
2954
|
+
(0, import_vitest9.expect)(back).toHaveLength(3);
|
|
2955
|
+
(0, import_vitest9.expect)(back.map((e) => e.id)).toEqual(committed.map((c) => c.id));
|
|
2472
2956
|
});
|
|
2473
|
-
(0,
|
|
2957
|
+
(0, import_vitest9.it)("drop_snapshots: skips SNAP_EVENT rows and counts them", async () => {
|
|
2474
2958
|
const s = `restore-drop-snap-${uid()}`;
|
|
2475
2959
|
const t = /* @__PURE__ */ new Date("2020-10-01T00:00:00.000Z");
|
|
2476
2960
|
const result = await restore(
|
|
@@ -2480,7 +2964,7 @@ var runStoreTck = (options) => {
|
|
|
2480
2964
|
id: 2,
|
|
2481
2965
|
stream: s,
|
|
2482
2966
|
version: 1,
|
|
2483
|
-
name:
|
|
2967
|
+
name: import_act2.SNAP_EVENT,
|
|
2484
2968
|
data: { count: 1 },
|
|
2485
2969
|
created: t,
|
|
2486
2970
|
meta: { correlation: "snap", causation: {} }
|
|
@@ -2489,19 +2973,19 @@ var runStoreTck = (options) => {
|
|
|
2489
2973
|
]),
|
|
2490
2974
|
{ drop_snapshots: true }
|
|
2491
2975
|
);
|
|
2492
|
-
(0,
|
|
2493
|
-
(0,
|
|
2976
|
+
(0, import_vitest9.expect)(result.kept).toBe(2);
|
|
2977
|
+
(0, import_vitest9.expect)(result.dropped.snapshots).toBe(1);
|
|
2494
2978
|
const back = await collect(store, {
|
|
2495
2979
|
stream: s,
|
|
2496
2980
|
stream_exact: true,
|
|
2497
2981
|
with_snaps: true
|
|
2498
2982
|
});
|
|
2499
|
-
(0,
|
|
2500
|
-
(0,
|
|
2501
|
-
back.every((e) => e.name !==
|
|
2983
|
+
(0, import_vitest9.expect)(back).toHaveLength(2);
|
|
2984
|
+
(0, import_vitest9.expect)(
|
|
2985
|
+
back.every((e) => e.name !== import_act2.SNAP_EVENT)
|
|
2502
2986
|
).toBe(true);
|
|
2503
2987
|
});
|
|
2504
|
-
(0,
|
|
2988
|
+
(0, import_vitest9.it)("on_progress fires once per event (caller throttles)", async () => {
|
|
2505
2989
|
const calls = [];
|
|
2506
2990
|
const s = `restore-progress-${uid()}`;
|
|
2507
2991
|
const t = /* @__PURE__ */ new Date("2021-02-01T00:00:00.000Z");
|
|
@@ -2512,11 +2996,11 @@ var runStoreTck = (options) => {
|
|
|
2512
2996
|
]),
|
|
2513
2997
|
{ on_progress: (p) => calls.push(p.processed) }
|
|
2514
2998
|
);
|
|
2515
|
-
(0,
|
|
2999
|
+
(0, import_vitest9.expect)(calls).toEqual([1, 2]);
|
|
2516
3000
|
});
|
|
2517
3001
|
});
|
|
2518
|
-
|
|
2519
|
-
(0,
|
|
3002
|
+
import_vitest9.describe.skipIf(!caps.pii_isolation)("pii_isolation (capability)", () => {
|
|
3003
|
+
(0, import_vitest9.it)("commits and loads pii alongside data", async () => {
|
|
2520
3004
|
const s = `pii-roundtrip-${uid()}`;
|
|
2521
3005
|
const committed = await store.commit(
|
|
2522
3006
|
s,
|
|
@@ -2529,8 +3013,8 @@ var runStoreTck = (options) => {
|
|
|
2529
3013
|
],
|
|
2530
3014
|
make_meta({ stream: s })
|
|
2531
3015
|
);
|
|
2532
|
-
(0,
|
|
2533
|
-
(0,
|
|
3016
|
+
(0, import_vitest9.expect)(committed).toHaveLength(1);
|
|
3017
|
+
(0, import_vitest9.expect)(committed[0].pii).toEqual({
|
|
2534
3018
|
email: "u@example.com",
|
|
2535
3019
|
name: "Ursula"
|
|
2536
3020
|
});
|
|
@@ -2541,11 +3025,11 @@ var runStoreTck = (options) => {
|
|
|
2541
3025
|
},
|
|
2542
3026
|
{ stream: s, stream_exact: true }
|
|
2543
3027
|
);
|
|
2544
|
-
(0,
|
|
2545
|
-
(0,
|
|
2546
|
-
(0,
|
|
3028
|
+
(0, import_vitest9.expect)(seen).toHaveLength(1);
|
|
3029
|
+
(0, import_vitest9.expect)(seen[0].pii).toEqual({ email: "u@example.com", name: "Ursula" });
|
|
3030
|
+
(0, import_vitest9.expect)(seen[0].data).toEqual({ amount: 1 });
|
|
2547
3031
|
});
|
|
2548
|
-
(0,
|
|
3032
|
+
(0, import_vitest9.it)("passes through events without pii (pii is null or undefined on load)", async () => {
|
|
2549
3033
|
const s = `pii-none-${uid()}`;
|
|
2550
3034
|
await store.commit(
|
|
2551
3035
|
s,
|
|
@@ -2559,10 +3043,10 @@ var runStoreTck = (options) => {
|
|
|
2559
3043
|
},
|
|
2560
3044
|
{ stream: s, stream_exact: true }
|
|
2561
3045
|
);
|
|
2562
|
-
(0,
|
|
2563
|
-
(0,
|
|
3046
|
+
(0, import_vitest9.expect)(seen).toHaveLength(1);
|
|
3047
|
+
(0, import_vitest9.expect)(seen[0].pii == null).toBe(true);
|
|
2564
3048
|
});
|
|
2565
|
-
(0,
|
|
3049
|
+
(0, import_vitest9.it)("wipes pii for every event on the stream via forget_pii", async () => {
|
|
2566
3050
|
const s = `pii-forget-${uid()}`;
|
|
2567
3051
|
await store.commit(
|
|
2568
3052
|
s,
|
|
@@ -2581,9 +3065,9 @@ var runStoreTck = (options) => {
|
|
|
2581
3065
|
make_meta({ stream: s })
|
|
2582
3066
|
);
|
|
2583
3067
|
const forget = store.forget_pii;
|
|
2584
|
-
(0,
|
|
3068
|
+
(0, import_vitest9.expect)(forget).toBeDefined();
|
|
2585
3069
|
const wiped = await forget.call(store, s);
|
|
2586
|
-
(0,
|
|
3070
|
+
(0, import_vitest9.expect)(wiped).toBe(2);
|
|
2587
3071
|
const seen = [];
|
|
2588
3072
|
await store.query(
|
|
2589
3073
|
(e) => {
|
|
@@ -2591,13 +3075,13 @@ var runStoreTck = (options) => {
|
|
|
2591
3075
|
},
|
|
2592
3076
|
{ stream: s, stream_exact: true }
|
|
2593
3077
|
);
|
|
2594
|
-
(0,
|
|
3078
|
+
(0, import_vitest9.expect)(seen).toHaveLength(2);
|
|
2595
3079
|
for (const e of seen) {
|
|
2596
|
-
(0,
|
|
2597
|
-
(0,
|
|
3080
|
+
(0, import_vitest9.expect)(e.pii == null).toBe(true);
|
|
3081
|
+
(0, import_vitest9.expect)(e.data).toBeDefined();
|
|
2598
3082
|
}
|
|
2599
3083
|
});
|
|
2600
|
-
(0,
|
|
3084
|
+
(0, import_vitest9.it)("is idempotent \u2014 second forget_pii returns 0, no error", async () => {
|
|
2601
3085
|
const s = `pii-forget-idem-${uid()}`;
|
|
2602
3086
|
await store.commit(
|
|
2603
3087
|
s,
|
|
@@ -2612,11 +3096,11 @@ var runStoreTck = (options) => {
|
|
|
2612
3096
|
);
|
|
2613
3097
|
const forget = store.forget_pii;
|
|
2614
3098
|
const first = await forget.call(store, s);
|
|
2615
|
-
(0,
|
|
3099
|
+
(0, import_vitest9.expect)(first).toBe(1);
|
|
2616
3100
|
const second = await forget.call(store, s);
|
|
2617
|
-
(0,
|
|
3101
|
+
(0, import_vitest9.expect)(second).toBe(0);
|
|
2618
3102
|
});
|
|
2619
|
-
(0,
|
|
3103
|
+
(0, import_vitest9.it)("only wipes the targeted stream \u2014 siblings untouched", async () => {
|
|
2620
3104
|
const sA = `pii-iso-a-${uid()}`;
|
|
2621
3105
|
const sB = `pii-iso-b-${uid()}`;
|
|
2622
3106
|
await store.commit(
|
|
@@ -2649,7 +3133,7 @@ var runStoreTck = (options) => {
|
|
|
2649
3133
|
},
|
|
2650
3134
|
{ stream: sA, stream_exact: true }
|
|
2651
3135
|
);
|
|
2652
|
-
(0,
|
|
3136
|
+
(0, import_vitest9.expect)(a[0].pii == null).toBe(true);
|
|
2653
3137
|
const b = [];
|
|
2654
3138
|
await store.query(
|
|
2655
3139
|
(e) => {
|
|
@@ -2657,9 +3141,9 @@ var runStoreTck = (options) => {
|
|
|
2657
3141
|
},
|
|
2658
3142
|
{ stream: sB, stream_exact: true }
|
|
2659
3143
|
);
|
|
2660
|
-
(0,
|
|
3144
|
+
(0, import_vitest9.expect)(b[0].pii).toEqual({ email: "bob@example.com" });
|
|
2661
3145
|
});
|
|
2662
|
-
(0,
|
|
3146
|
+
(0, import_vitest9.it)("forget_pii on a stream with no pii events returns 0", async () => {
|
|
2663
3147
|
const s = `pii-forget-empty-${uid()}`;
|
|
2664
3148
|
await store.commit(
|
|
2665
3149
|
s,
|
|
@@ -2667,14 +3151,14 @@ var runStoreTck = (options) => {
|
|
|
2667
3151
|
make_meta({ stream: s })
|
|
2668
3152
|
);
|
|
2669
3153
|
const wiped = await store.forget_pii.call(store, s);
|
|
2670
|
-
(0,
|
|
3154
|
+
(0, import_vitest9.expect)(wiped).toBe(0);
|
|
2671
3155
|
});
|
|
2672
3156
|
});
|
|
2673
3157
|
if (caps.notify) {
|
|
2674
|
-
(0,
|
|
2675
|
-
(0,
|
|
3158
|
+
(0, import_vitest9.describe)("notify (capability)", () => {
|
|
3159
|
+
(0, import_vitest9.it)("delivers a notification when a different instance commits", async () => {
|
|
2676
3160
|
const notify = store.notify;
|
|
2677
|
-
(0,
|
|
3161
|
+
(0, import_vitest9.expect)(notify).toBeDefined();
|
|
2678
3162
|
const received = [];
|
|
2679
3163
|
let resolve_arrived;
|
|
2680
3164
|
const arrived = new Promise((res) => {
|
|
@@ -2693,9 +3177,9 @@ var runStoreTck = (options) => {
|
|
|
2693
3177
|
make_meta({ stream })
|
|
2694
3178
|
);
|
|
2695
3179
|
await arrived;
|
|
2696
|
-
(0,
|
|
2697
|
-
(0,
|
|
2698
|
-
(0,
|
|
3180
|
+
(0, import_vitest9.expect)(received.length).toBeGreaterThanOrEqual(1);
|
|
3181
|
+
(0, import_vitest9.expect)(received[0].stream).toBe(stream);
|
|
3182
|
+
(0, import_vitest9.expect)(received[0].events.length).toBeGreaterThanOrEqual(1);
|
|
2699
3183
|
} finally {
|
|
2700
3184
|
await writer.dispose();
|
|
2701
3185
|
await Promise.resolve(disposer());
|
|
@@ -2717,9 +3201,12 @@ var runStoreTck = (options) => {
|
|
|
2717
3201
|
dec,
|
|
2718
3202
|
inc,
|
|
2719
3203
|
reset,
|
|
3204
|
+
runCacheDifferentialTck,
|
|
2720
3205
|
runCacheTck,
|
|
3206
|
+
runLoggerDifferentialTck,
|
|
2721
3207
|
runLoggerTck,
|
|
2722
3208
|
runStabilityTck,
|
|
3209
|
+
runStoreDifferentialTck,
|
|
2723
3210
|
runStorePropertyTck,
|
|
2724
3211
|
runStoreTck,
|
|
2725
3212
|
uid
|