ueberdb2 4.1.1 → 4.1.3

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.
Files changed (44) hide show
  1. package/package.json +5 -3
  2. package/.eslintignore +0 -2
  3. package/.eslintrc.cjs +0 -66
  4. package/.github/dependabot.yml +0 -11
  5. package/.github/workflows/npmpublish.yml +0 -134
  6. package/.travis.yml +0 -46
  7. package/CHANGELOG.md +0 -304
  8. package/CONTRIBUTING.md +0 -103
  9. package/SECURITY.md +0 -5
  10. package/databases/cassandra_db.ts +0 -265
  11. package/databases/couch_db.ts +0 -189
  12. package/databases/dirty_db.ts +0 -85
  13. package/databases/dirty_git_db.ts +0 -82
  14. package/databases/elasticsearch_db.ts +0 -257
  15. package/databases/memory_db.ts +0 -41
  16. package/databases/mock_db.ts +0 -43
  17. package/databases/mongodb_db.ts +0 -142
  18. package/databases/mssql_db.ts +0 -226
  19. package/databases/mysql_db.ts +0 -183
  20. package/databases/postgres_db.ts +0 -213
  21. package/databases/postgrespool_db.ts +0 -11
  22. package/databases/redis_db.ts +0 -129
  23. package/databases/rethink_db.ts +0 -114
  24. package/databases/sqlite_db.ts +0 -159
  25. package/docker-compose.yml +0 -44
  26. package/index.ts +0 -224
  27. package/lib/AbstractDatabase.ts +0 -79
  28. package/lib/CacheAndBufferLayer.ts +0 -665
  29. package/lib/logging.ts +0 -33
  30. package/test/lib/databases.ts +0 -73
  31. package/test/lib/mysql.sql +0 -84
  32. package/test/test.ts +0 -328
  33. package/test/test_bulk.ts +0 -69
  34. package/test/test_elasticsearch.ts +0 -128
  35. package/test/test_findKeys.ts +0 -41
  36. package/test/test_flush.ts +0 -55
  37. package/test/test_getSub.ts +0 -28
  38. package/test/test_lru.ts +0 -151
  39. package/test/test_memory.ts +0 -32
  40. package/test/test_metrics.ts +0 -734
  41. package/test/test_mysql.ts +0 -62
  42. package/test/test_postgres.ts +0 -16
  43. package/test/test_setSub.ts +0 -19
  44. package/test/test_tojson.ts +0 -34
@@ -1,734 +0,0 @@
1
- import assert$0 from 'assert';
2
- import * as ueberdb from '../index';
3
- 'use strict';
4
- const assert = assert$0.strict;
5
- // Gate is a normal Promise that resolves when its open() method is called.
6
- // @ts-expect-error TS(2508): No base constructor has the specified number of ty... Remove this comment to see the full error message
7
- class Gate extends Promise {
8
- open: any;
9
- constructor(executor = null) {
10
- let open;
11
- super((resolve: any, reject: any) => {
12
- open = resolve;
13
- if (executor != null)
14
- // @ts-expect-error TS(2349): This expression is not callable.
15
- { executor(resolve, reject); }
16
- });
17
- this.open = open;
18
- }
19
- }
20
- const diffMetrics = (before: any, after: any) => {
21
- const diff = {};
22
- // @ts-expect-error TS(2775): Assertions require every name in the call target t... Remove this comment to see the full error message
23
- assert.equal(Object.keys(before).length, Object.keys(after).length);
24
- for (const [k, bv] of Object.entries(before)) {
25
- // @ts-expect-error TS(2775): Assertions require every name in the call target t... Remove this comment to see the full error message
26
- assert(bv != null);
27
- const av = after[k];
28
- // @ts-expect-error TS(2775): Assertions require every name in the call target t... Remove this comment to see the full error message
29
- assert(av != null);
30
- // @ts-expect-error TS(2571): Object is of type 'unknown'.
31
- if (av - bv > 0)
32
- // @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
33
- { diff[k] = av - bv; }
34
- }
35
- return diff;
36
- };
37
- const assertMetricsDelta = (before: any, after: any, wantDelta: any) => {
38
- wantDelta = {...wantDelta};
39
- for (const [k, v] of Object.entries(wantDelta)) {
40
- if (v === 0) delete wantDelta[k];
41
- }
42
- // @ts-expect-error TS(2775): Assertions require every name in the call target t... Remove this comment to see the full error message
43
- assert.deepEqual(diffMetrics(before, after), wantDelta);
44
- };
45
- describe(__filename, () => {
46
- let db: any;
47
- let key: any;
48
- let mock: any;
49
- before(async () => {
50
- const settings = {};
51
- db = new ueberdb.Database('mock', settings);
52
- // @ts-expect-error TS(2339): Property 'mock' does not exist on type '{}'.
53
- mock = settings.mock;
54
- mock.once('init', (cb: any) => cb());
55
- await db.init();
56
- });
57
- after(async () => {
58
- mock.once('close', (cb: any) => cb());
59
- await db.close();
60
- });
61
- beforeEach(async function (this: any) {
62
- key = this.currentTest.fullTitle(); // Use test title to avoid collisions with other tests.
63
- });
64
- afterEach(async () => {
65
- mock.removeAllListeners();
66
- });
67
- describe('reads', () => {
68
- const tcs = [
69
- {name: 'get', f: (key: any) => db.get(key)},
70
- {name: 'getSub', f: (key: any) => db.getSub(key, ['s'])},
71
- ];
72
- for (const tc of tcs) {
73
- describe(tc.name, () => {
74
- const subtcs = [
75
- {
76
- name: 'cache miss',
77
- val: '{"s": "v"}',
78
- wantMetrics: {
79
- lockReleases: 1,
80
- readsFinished: 1,
81
- readsFromDbFinished: 1,
82
- },
83
- },
84
- {
85
- name: 'cache hit',
86
- cacheHit: true,
87
- val: '{"s": "v"}',
88
- wantMetrics: {
89
- lockAcquires: 1,
90
- lockReleases: 1,
91
- reads: 1,
92
- readsFinished: 1,
93
- readsFromCache: 1,
94
- },
95
- },
96
- {
97
- name: 'read error',
98
- err: new Error('test'),
99
- wantMetrics: {
100
- lockReleases: 1,
101
- readsFailed: 1,
102
- readsFinished: 1,
103
- readsFromDbFailed: 1,
104
- readsFromDbFinished: 1,
105
- },
106
- },
107
- {
108
- name: 'json error',
109
- val: 'ignore me -- this is intentionally invalid json',
110
- wantJsonErr: true,
111
- wantMetrics: {
112
- lockReleases: 1,
113
- readsFailed: 1,
114
- readsFinished: 1,
115
- readsFromDbFinished: 1,
116
- },
117
- },
118
- ];
119
- for (const subtc of subtcs) {
120
- it(subtc.name, async () => {
121
- if (subtc.cacheHit) {
122
- mock.once('get', (key: any, cb: any) => { cb(null, subtc.val); });
123
- await tc.f(key);
124
- }
125
- let finishDbRead;
126
- const dbReadStarted = new Promise((resolve) => {
127
- mock.once('get', (key: any, cb: any) => {
128
- // @ts-expect-error TS(2775): Assertions require every name in the call target t... Remove this comment to see the full error message
129
- assert(!subtc.cacheHit, 'value should have been cached');
130
- // @ts-expect-error TS(2794): Expected 1 arguments, but got 0. Did you forget to... Remove this comment to see the full error message
131
- resolve();
132
- new Promise((resolve) => { finishDbRead = resolve; })
133
- .then(() => cb(subtc.err, subtc.val));
134
- });
135
- });
136
- let before = {...db.metrics};
137
- let readFinished = tc.f(key);
138
- if (!subtc.cacheHit) {
139
- await dbReadStarted;
140
- assertMetricsDelta(before, db.metrics, {
141
- lockAcquires: 1,
142
- reads: 1,
143
- readsFromDb: 1,
144
- });
145
- before = {...db.metrics};
146
- // @ts-expect-error TS(2722): Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
147
- finishDbRead();
148
- }
149
- if (subtc.err) readFinished = assert.rejects(readFinished, subtc.err);
150
- if (subtc.wantJsonErr) readFinished = assert.rejects(readFinished, {message: /JSON/});
151
- await readFinished;
152
- assertMetricsDelta(before, db.metrics, subtc.wantMetrics);
153
- });
154
- }
155
- it('read of in-progress write', async () => {
156
- let finishWrite;
157
- const writeStarted = new Promise((resolve) => {
158
- mock.once('set', (key: any, val: any, cb: any) => {
159
- // @ts-expect-error TS(2794): Expected 1 arguments, but got 0. Did you forget to... Remove this comment to see the full error message
160
- resolve();
161
- new Promise((resolve) => { finishWrite = resolve; }).then(() => cb());
162
- });
163
- });
164
- const writeFinished = db.set(key, {s: 'v'});
165
- const flushed = db.flush(); // Speed up the tests.
166
- await writeStarted;
167
- mock.once('get', (key: any, cb: any) => { assert.fail('value should be cached'); });
168
- const before = {...db.metrics};
169
- await tc.f(key);
170
- assertMetricsDelta(before, db.metrics, {
171
- lockAcquires: 1,
172
- lockReleases: 1,
173
- reads: 1,
174
- readsFinished: 1,
175
- readsFromCache: 1,
176
- });
177
- // @ts-expect-error TS(2722): Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
178
- finishWrite();
179
- await writeFinished;
180
- await flushed;
181
- });
182
- });
183
- }
184
- });
185
- describe('writes', () => {
186
- const tcs = [
187
- {
188
- name: 'remove ok',
189
- action: async () => await db.remove(key),
190
- wantOps: [
191
- {
192
- wantFns: ['remove'],
193
- wantMetricsDelta: {
194
- lockAcquires: 1,
195
- lockReleases: 1,
196
- writes: 1,
197
- writesToDb: 1,
198
- },
199
- cbArgs: [[null]],
200
- },
201
- ],
202
- wantErr: null,
203
- wantMetricsDelta: {
204
- writesFinished: 1,
205
- writesToDbFinished: 1,
206
- },
207
- },
208
- {
209
- name: 'remove error',
210
- action: async () => await db.remove(key),
211
- wantOps: [
212
- {
213
- wantFns: ['remove'],
214
- wantMetricsDelta: {
215
- lockAcquires: 1,
216
- lockReleases: 1,
217
- writes: 1,
218
- writesToDb: 1,
219
- },
220
- cbArgs: [[new Error('test')]],
221
- },
222
- ],
223
- wantErr: {message: 'test'},
224
- wantMetricsDelta: {
225
- writesFailed: 1,
226
- writesFinished: 1,
227
- writesToDbFailed: 1,
228
- writesToDbFinished: 1,
229
- },
230
- },
231
- {
232
- name: 'set ok',
233
- action: async () => await db.set(key, 'v'),
234
- wantOps: [
235
- {
236
- wantFns: ['set'],
237
- wantMetricsDelta: {
238
- lockAcquires: 1,
239
- lockReleases: 1,
240
- writes: 1,
241
- writesToDb: 1,
242
- },
243
- cbArgs: [[null]],
244
- },
245
- ],
246
- wantErr: null,
247
- wantMetricsDelta: {
248
- writesFinished: 1,
249
- writesToDbFinished: 1,
250
- },
251
- },
252
- {
253
- name: 'set db error',
254
- action: async () => await db.set(key, 'v'),
255
- wantOps: [
256
- {
257
- wantFns: ['set'],
258
- wantMetricsDelta: {
259
- lockAcquires: 1,
260
- lockReleases: 1,
261
- writes: 1,
262
- writesToDb: 1,
263
- },
264
- cbArgs: [[new Error('test')]],
265
- },
266
- ],
267
- wantErr: {message: 'test'},
268
- wantMetricsDelta: {
269
- writesFailed: 1,
270
- writesFinished: 1,
271
- writesToDbFailed: 1,
272
- writesToDbFinished: 1,
273
- },
274
- },
275
- {
276
- name: 'set json error',
277
- action: async () => await db.set(key, BigInt(1)),
278
- wantOps: [],
279
- wantErr: {name: 'TypeError'},
280
- wantMetricsDelta: {
281
- lockAcquires: 1,
282
- lockReleases: 1,
283
- writes: 1,
284
- writesFailed: 1,
285
- writesFinished: 1,
286
- },
287
- },
288
- {
289
- name: 'setSub ok',
290
- action: async () => await db.setSub(key, ['s'], 'v2'),
291
- wantOps: [
292
- {
293
- wantFns: ['get'],
294
- wantMetricsDelta: {
295
- lockAcquires: 1,
296
- reads: 1,
297
- readsFromDb: 1,
298
- },
299
- cbArgs: [[null, '{"s": "v1"}']],
300
- },
301
- {
302
- wantFns: ['set'],
303
- wantMetricsDelta: {
304
- lockReleases: 1,
305
- readsFinished: 1,
306
- readsFromDbFinished: 1,
307
- writes: 1,
308
- writesToDb: 1,
309
- },
310
- cbArgs: [[null]],
311
- },
312
- ],
313
- wantErr: null,
314
- wantMetricsDelta: {
315
- writesFinished: 1,
316
- writesToDbFinished: 1,
317
- },
318
- },
319
- {
320
- name: 'setSub db write error',
321
- action: async () => await db.setSub(key, ['s'], 'v2'),
322
- wantOps: [
323
- {
324
- wantFns: ['get'],
325
- wantMetricsDelta: {
326
- lockAcquires: 1,
327
- reads: 1,
328
- readsFromDb: 1,
329
- },
330
- cbArgs: [[null, '{"s": "v1"}']],
331
- },
332
- {
333
- wantFns: ['set'],
334
- wantMetricsDelta: {
335
- lockReleases: 1,
336
- readsFinished: 1,
337
- readsFromDbFinished: 1,
338
- writes: 1,
339
- writesToDb: 1,
340
- },
341
- cbArgs: [[new Error('test')]],
342
- },
343
- ],
344
- wantErr: {message: 'test'},
345
- wantMetricsDelta: {
346
- writesFailed: 1,
347
- writesFinished: 1,
348
- writesToDbFailed: 1,
349
- writesToDbFinished: 1,
350
- },
351
- },
352
- {
353
- name: 'setSub db read error',
354
- action: async () => await db.setSub(key, ['s'], 'v2'),
355
- wantOps: [
356
- {
357
- wantFns: ['get'],
358
- wantMetricsDelta: {
359
- lockAcquires: 1,
360
- reads: 1,
361
- readsFromDb: 1,
362
- },
363
- cbArgs: [[new Error('test')]],
364
- },
365
- ],
366
- wantErr: {message: 'test'},
367
- wantMetricsDelta: {
368
- lockReleases: 1,
369
- readsFailed: 1,
370
- readsFinished: 1,
371
- readsFromDbFailed: 1,
372
- readsFromDbFinished: 1,
373
- writes: 1,
374
- writesFailed: 1,
375
- writesFinished: 1,
376
- },
377
- },
378
- {
379
- name: 'setSub json read error',
380
- action: async () => await db.setSub(key, ['s'], 'v2'),
381
- wantOps: [
382
- {
383
- wantFns: ['get'],
384
- wantMetricsDelta: {
385
- lockAcquires: 1,
386
- reads: 1,
387
- readsFromDb: 1,
388
- },
389
- cbArgs: [[null, 'ignore me -- this is intentionally invalid json']],
390
- },
391
- ],
392
- wantErr: {name: 'SyntaxError'},
393
- wantMetricsDelta: {
394
- lockReleases: 1,
395
- readsFailed: 1,
396
- readsFinished: 1,
397
- readsFromDbFinished: 1,
398
- writes: 1,
399
- writesFailed: 1,
400
- writesFinished: 1,
401
- },
402
- },
403
- {
404
- name: 'setSub update non-object error',
405
- action: async () => await db.setSub(key, ['s'], 'v2'),
406
- wantOps: [
407
- {
408
- wantFns: ['get'],
409
- wantMetricsDelta: {
410
- lockAcquires: 1,
411
- reads: 1,
412
- readsFromDb: 1,
413
- },
414
- cbArgs: [[null, '"foo"']],
415
- },
416
- ],
417
- wantErr: {message: /non-object/},
418
- wantMetricsDelta: {
419
- lockReleases: 1,
420
- readsFinished: 1,
421
- readsFromDbFinished: 1,
422
- writes: 1,
423
- writesFailed: 1,
424
- writesFinished: 1,
425
- },
426
- },
427
- {
428
- name: 'setSub json write error',
429
- action: async () => await db.setSub(key, ['s'], BigInt(1)),
430
- wantOps: [
431
- {
432
- wantFns: ['get'],
433
- wantMetricsDelta: {
434
- lockAcquires: 1,
435
- reads: 1,
436
- readsFromDb: 1,
437
- },
438
- cbArgs: [[null, '{"s": "v1"}']],
439
- },
440
- ],
441
- wantErr: {name: 'TypeError'},
442
- wantMetricsDelta: {
443
- lockReleases: 1,
444
- readsFinished: 1,
445
- readsFromDbFinished: 1,
446
- writes: 1,
447
- writesFailed: 1,
448
- writesFinished: 1,
449
- },
450
- },
451
- {
452
- name: 'doBulk ok',
453
- action: async () => await Promise.all([db.set(key, 'v'), db.set(`${key} second op`, 'v')]),
454
- wantOps: [
455
- {
456
- wantFns: ['doBulk'],
457
- wantMetricsDelta: {
458
- lockAcquires: 2,
459
- lockReleases: 2,
460
- writes: 2,
461
- writesToDb: 2,
462
- },
463
- cbArgs: [[null]],
464
- },
465
- ],
466
- wantErr: null,
467
- wantMetricsDelta: {
468
- writesFinished: 2,
469
- writesToDbFinished: 2,
470
- },
471
- },
472
- {
473
- name: 'doBulk error, all retries ok',
474
- action: async () => await Promise.all([db.set(key, 'v'), db.set(`${key} second op`, 'v')]),
475
- wantOps: [
476
- {
477
- wantFns: ['doBulk'],
478
- wantMetricsDelta: {
479
- lockAcquires: 2,
480
- lockReleases: 2,
481
- writes: 2,
482
- writesToDb: 2,
483
- },
484
- cbArgs: [[new Error('injected doBulk error')]],
485
- },
486
- {
487
- wantFns: ['set', 'set'],
488
- wantMetricsDelta: {
489
- writesToDbRetried: 2,
490
- },
491
- cbArgs: [[null], [null]],
492
- },
493
- ],
494
- wantErr: null,
495
- wantMetricsDelta: {
496
- writesFinished: 2,
497
- writesToDbFinished: 2,
498
- },
499
- },
500
- {
501
- name: 'doBulk error, one of the retries fails',
502
- action: async () => await Promise.all([db.set(key, 'v'), db.set(`${key} second op`, 'v')]),
503
- wantOps: [
504
- {
505
- wantFns: ['doBulk'],
506
- wantMetricsDelta: {
507
- lockAcquires: 2,
508
- lockReleases: 2,
509
- writes: 2,
510
- writesToDb: 2,
511
- },
512
- cbArgs: [[new Error('injected doBulk error')]],
513
- },
514
- {
515
- wantFns: ['set', 'set'],
516
- wantMetricsDelta: {
517
- writesToDbRetried: 2,
518
- },
519
- cbArgs: [[new Error('test')], [null]],
520
- },
521
- ],
522
- wantErr: {message: 'test'},
523
- wantMetricsDelta: {
524
- writesFailed: 1,
525
- writesFinished: 2,
526
- writesToDbFailed: 1,
527
- writesToDbFinished: 2,
528
- },
529
- },
530
- {
531
- name: 'doBulk error, all retries fail',
532
- action: async () => await Promise.all([db.set(key, 'v'), db.set(`${key} second op`, 'v')]),
533
- wantOps: [
534
- {
535
- wantFns: ['doBulk'],
536
- wantMetricsDelta: {
537
- lockAcquires: 2,
538
- lockReleases: 2,
539
- writes: 2,
540
- writesToDb: 2,
541
- },
542
- cbArgs: [[new Error('injected doBulk error')]],
543
- },
544
- {
545
- wantFns: ['set', 'set'],
546
- wantMetricsDelta: {
547
- writesToDbRetried: 2,
548
- },
549
- cbArgs: [[new Error('test1')], [new Error('test2')]],
550
- },
551
- ],
552
- wantErr: (err: any) => ['test1', 'test2'].includes(err.message),
553
- wantMetricsDelta: {
554
- writesFailed: 2,
555
- writesFinished: 2,
556
- writesToDbFailed: 2,
557
- writesToDbFinished: 2,
558
- },
559
- },
560
- {
561
- name: 'obsoleted ok',
562
- action: async () => await Promise.all([db.set(key, 'v'), db.set(key, 'v2')]),
563
- wantOps: [
564
- {
565
- wantFns: ['set'],
566
- wantMetricsDelta: {
567
- lockAcquires: 2,
568
- lockAwaits: 1,
569
- lockReleases: 2,
570
- writes: 2,
571
- writesObsoleted: 1,
572
- writesToDb: 1,
573
- },
574
- cbArgs: [[null]],
575
- },
576
- ],
577
- wantErr: null,
578
- wantMetricsDelta: {
579
- writesFinished: 2,
580
- writesToDbFinished: 1,
581
- },
582
- },
583
- {
584
- name: 'obsoleted error',
585
- action: async () => await Promise.all([db.set(key, 'v'), db.set(key, 'v2')]),
586
- wantOps: [
587
- {
588
- wantFns: ['set'],
589
- wantMetricsDelta: {
590
- lockAcquires: 2,
591
- lockAwaits: 1,
592
- lockReleases: 2,
593
- writes: 2,
594
- writesObsoleted: 1,
595
- writesToDb: 1,
596
- },
597
- cbArgs: [[new Error('test')]],
598
- },
599
- ],
600
- wantErr: {message: 'test'},
601
- wantMetricsDelta: {
602
- writesFailed: 2,
603
- writesFinished: 2,
604
- writesToDbFailed: 1,
605
- writesToDbFinished: 1,
606
- },
607
- },
608
- ];
609
- for (const tc of tcs) {
610
- it(tc.name, async () => {
611
- const opStarts: any = [];
612
- for (const fn of ['doBulk', 'get', 'remove', 'set']) {
613
- mock.on(fn, (...args: any[]) => {
614
- const opStart = opStarts.shift();
615
- const cb = args.pop();
616
- opStart.open([fn, cb]);
617
- });
618
- }
619
- let before = {...db.metrics};
620
- let actionDone;
621
- // advance() triggers the next database operation(s), either by starting tc.action (if
622
- // tc.action has not yet been started) or completing the previous operation(s) (if tc.action
623
- // has been started).
624
- let advance = () => { actionDone = tc.action(); };
625
- for (const ops of tc.wantOps) {
626
- // Provide a way for the mock database to tell us that a mocked database method has been
627
- // called. The number of expected parallel operations for this iteration is
628
- // ops.wantFns.length, so that is the number of Gates that are added to opStarts. Each
629
- // Gate resolves to [fn, cb] where fn is the name of the mocked database method and cb is
630
- // the mocked database method's callback.
631
- for (let i = 0; i < ops.wantFns.length; ++i) opStarts.push(new Gate());
632
- // Trigger the call(s) to the mock database method(s). This is scheduled to run in the
633
- // future to ensure that advance() does not empty the opStarts array until after the
634
- // Promise.all() call below has a chance to see all of the Promises in opStarts.
635
- setImmediate(advance);
636
- // Wait until the expected number of parallel database method calls have started.
637
- const gotOps = await Promise.all(opStarts);
638
- assertMetricsDelta(before, db.metrics, ops.wantMetricsDelta);
639
- before = {...db.metrics};
640
- const advanceFns: any = [];
641
- for (const [gotFn, cb] of gotOps) {
642
- const i = ops.wantFns.indexOf(gotFn);
643
- // @ts-expect-error TS(2775): Assertions require every name in the call target t... Remove this comment to see the full error message
644
- assert(i >= 0, `unexpected mock database method call: ${gotFn}`);
645
- ops.wantFns.splice(i, 1);
646
- const [cbArgs] = ops.cbArgs.splice(i, 1);
647
- advanceFns.push(() => cb(...cbArgs));
648
- }
649
- // @ts-expect-error TS(2775): Assertions require every name in the call target t... Remove this comment to see the full error message
650
- assert.equal(ops.wantFns.length, 0, `missing call(s): ${ops.wantFns.join(', ')}`);
651
- // @ts-expect-error TS(7006): Parameter 'f' implicitly has an 'any' type.
652
- advance = () => advanceFns.forEach((f) => f());
653
- }
654
- advance();
655
- // @ts-expect-error TS(2769): No overload matches this call.
656
- await (tc.wantErr ? assert.rejects(actionDone, tc.wantErr) : actionDone);
657
- assertMetricsDelta(before, db.metrics, tc.wantMetricsDelta);
658
- });
659
- }
660
- });
661
- describe('lock contention', () => {
662
- const tcs = [
663
- {
664
- name: 'get',
665
- f: (key: any) => db.get(key),
666
- wantMetrics: {lockAwaits: 1},
667
- },
668
- {
669
- name: 'getSub',
670
- fn: 'get',
671
- f: (key: any) => db.getSub(key, ['s']),
672
- wantMetrics: {lockAwaits: 1},
673
- },
674
- {
675
- name: 'remove',
676
- f: (key: any) => db.remove(key),
677
- wantMetrics: {lockAwaits: 1},
678
- },
679
- {
680
- name: 'set',
681
- f: (key: any) => db.set(key, 'v'),
682
- wantMetrics: {lockAwaits: 1},
683
- },
684
- {
685
- name: 'setSub',
686
- fn: 'set',
687
- f: (key: any) => db.setSub(key, ['s'], 'v'),
688
- wantMetrics: {lockAwaits: 1},
689
- },
690
- {
691
- name: 'doBulk',
692
- f: (key: any) => Promise.all([
693
- db.set(key, 'v'),
694
- db.set(`${key} second op`, 'v'),
695
- ]),
696
- wantMetrics: {lockAcquires: 1, lockAwaits: 1},
697
- },
698
- ];
699
- for (const tc of tcs) {
700
- if (tc.fn == null)
701
- // @ts-expect-error TS(2322): Type 'string' is not assignable to type 'undefined... Remove this comment to see the full error message
702
- { tc.fn = tc.name; }
703
- it(tc.name, async () => {
704
- let finishRead;
705
- const readStarted = new Promise((resolve) => {
706
- mock.once('get', (key: any, cb: any) => {
707
- // @ts-expect-error TS(2794): Expected 1 arguments, but got 0. Did you forget to... Remove this comment to see the full error message
708
- resolve();
709
- const val = '{"s": "v"}';
710
- new Promise((resolve) => { finishRead = resolve; }).then(() => cb(null, val));
711
- });
712
- });
713
- // Note: All contention tests should be with get() to ensure that all functions lock using
714
- // the record's key.
715
- const getP = db.get(key);
716
- await readStarted;
717
- mock.once(tc.fn, (...args: any[]) => {
718
- // @ts-expect-error TS(2775): Assertions require every name in the call target t... Remove this comment to see the full error message
719
- assert(tc.fn !== 'get', 'value should have been cached');
720
- args.pop()();
721
- });
722
- const before = {...db.metrics};
723
- const opFinished = tc.f(key);
724
- const flushed = db.flush(); // Speed up tests.
725
- assertMetricsDelta(before, db.metrics, tc.wantMetrics);
726
- // @ts-expect-error TS(2722): Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
727
- finishRead();
728
- await getP;
729
- await opFinished;
730
- await flushed;
731
- });
732
- }
733
- });
734
- });