-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathtxn-tracking.test.js
More file actions
121 lines (110 loc) · 3.92 KB
/
Copy pathtxn-tracking.test.js
File metadata and controls
121 lines (110 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
require('../testUtils');
const assert = require('assert');
const { setupTestDBPath } = require('../testUtils');
const { setTxnExpiration } = require('#src/resources/DatabaseTransaction');
const { setTxnExpiration: setLMDBTxnExpiration } = require('#src/resources/LMDBTransaction');
const { setReadTxnExpiration, checkReadTxnTimeouts } = require('#src/resources/RecordEncoder');
const { setMainIsWorker } = require('#js/server/threads/manageThreads');
const { table } = require('#src/resources/databases');
const { setTimeout: delay } = require('node:timers/promises');
const { RocksDatabase } = require('@harperfast/rocksdb-js');
describe('Txn Expiration', () => {
let SlowResource,
performedDBInteractions = false;
before(async function () {
setupTestDBPath();
setMainIsWorker(true); // TODO: Should be default until changed
let BasicTable = table({
table: 'BasicTable',
database: 'test',
attributes: [{ name: 'id', isPrimaryKey: true }, { name: 'name' }],
});
SlowResource = class extends BasicTable {
async get(query) {
await delay(40);
// at this point the read transaction should be expired, but we should still be able to do read/writes (in a
// new transaction)
await super.get(3);
await super.put(3, { name: 'three' });
performedDBInteractions = true;
await delay(500);
return super.get(query);
}
};
});
// Skipped (both engines): timing/ordering-sensitive flake — the tracked-txn baseline and expiration
// window make this assert intermittently off in the full suite. Restore once stabilized (5.1).
it.skip('Slow txn will expire', async function () {
await SlowResource.put(3, { name: 'three' });
let trackedTxns =
SlowResource.primaryStore instanceof RocksDatabase ? setTxnExpiration(20) : setLMDBTxnExpiration(20);
await delay(50);
let existingTxns = trackedTxns.size;
let result = SlowResource.get(3);
assert.equal(trackedTxns.size, existingTxns + 1);
const txns = Array.from(trackedTxns);
const lastTxn = txns[txns.length - 1];
if (SlowResource.primaryStore instanceof RocksDatabase) {
assert.equal(lastTxn.startedFrom.resourceName, 'SlowResource');
assert.equal(lastTxn.startedFrom.method, 'get');
assert.equal(lastTxn.timeout, 20);
}
await Promise.race([delay(50), result]);
assert(performedDBInteractions);
assert.equal(trackedTxns.size, existingTxns);
});
after(function () {
setTxnExpiration(30000);
});
});
describe('Read Txn Expiration', () => {
let SlowReadResource;
before(async function () {
setupTestDBPath();
setMainIsWorker(true);
let BasicTable = table({
table: 'ReadTxnTable',
database: 'test',
attributes: [{ name: 'id', isPrimaryKey: true }, { name: 'name' }],
});
SlowReadResource = class extends BasicTable {
async get(query) {
const result = super.get(query);
await delay(50);
return result;
}
};
if (SlowReadResource.primaryStore instanceof RocksDatabase) this.skip();
});
it('Read txn will be ended after timeout', async function () {
await SlowReadResource.put(1, { name: 'one' });
// set timeout to minimum, 15s = 1 tick, openTimer > 1 means txn is expired
const trackedTxns = setReadTxnExpiration(15000);
const readPromise = SlowReadResource.get(1);
await delay(20);
const before = trackedTxns.length;
checkReadTxnTimeouts();
checkReadTxnTimeouts();
checkReadTxnTimeouts();
checkReadTxnTimeouts();
checkReadTxnTimeouts();
assert.ok(
trackedTxns.length < before,
`expected a txn to be removed; trackedTxns went ${before} -> ${trackedTxns.length}`
);
await readPromise;
});
it('Read txn below threshold is not expired', async function () {
setReadTxnExpiration(60000);
await SlowReadResource.put(2, { name: 'two' });
const readPromise = SlowReadResource.get(2);
await delay(20);
// only 2 ticks
checkReadTxnTimeouts();
const result = await readPromise;
assert.equal(result.name, 'two');
});
after(function () {
setReadTxnExpiration(300000);
});
});