@atlaspack/cache 3.1.1-canary.44 → 3.1.1-canary.45
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/lib/LMDBLiteCache.js +0 -5
- package/package.json +8 -8
- package/src/LMDBLiteCache.js +0 -5
- package/test/LMDBLiteCache.test.js +152 -0
- package/test/workerThreadsTest.js +44 -0
package/lib/LMDBLiteCache.js
CHANGED
@@ -83,11 +83,6 @@ const ncpAsync = (0, _util().promisify)(_ncp().default);
|
|
83
83
|
class LmdbWrapper {
|
84
84
|
constructor(lmdb) {
|
85
85
|
this.lmdb = lmdb;
|
86
|
-
|
87
|
-
// $FlowFixMe
|
88
|
-
this[Symbol.dispose] = () => {
|
89
|
-
this.lmdb.close();
|
90
|
-
};
|
91
86
|
}
|
92
87
|
has(key) {
|
93
88
|
return this.lmdb.hasSync(key);
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@atlaspack/cache",
|
3
3
|
"description": "Interface for defining caches and file-system, IDB and LMDB implementations.",
|
4
|
-
"version": "3.1.1-canary.
|
4
|
+
"version": "3.1.1-canary.45+124b7fff4",
|
5
5
|
"license": "(MIT OR Apache-2.0)",
|
6
6
|
"type": "commonjs",
|
7
7
|
"publishConfig": {
|
@@ -23,12 +23,12 @@
|
|
23
23
|
"check-ts": "tsc --noEmit index.d.ts"
|
24
24
|
},
|
25
25
|
"dependencies": {
|
26
|
-
"@atlaspack/build-cache": "2.13.3-canary.
|
27
|
-
"@atlaspack/feature-flags": "2.14.1-canary.
|
28
|
-
"@atlaspack/fs": "2.14.5-canary.
|
29
|
-
"@atlaspack/logger": "2.14.5-canary.
|
30
|
-
"@atlaspack/rust": "3.2.1-canary.
|
31
|
-
"@atlaspack/utils": "2.14.5-canary.
|
26
|
+
"@atlaspack/build-cache": "2.13.3-canary.113+124b7fff4",
|
27
|
+
"@atlaspack/feature-flags": "2.14.1-canary.113+124b7fff4",
|
28
|
+
"@atlaspack/fs": "2.14.5-canary.45+124b7fff4",
|
29
|
+
"@atlaspack/logger": "2.14.5-canary.45+124b7fff4",
|
30
|
+
"@atlaspack/rust": "3.2.1-canary.45+124b7fff4",
|
31
|
+
"@atlaspack/utils": "2.14.5-canary.45+124b7fff4",
|
32
32
|
"ncp": "^2.0.0"
|
33
33
|
},
|
34
34
|
"devDependencies": {
|
@@ -37,5 +37,5 @@
|
|
37
37
|
"browser": {
|
38
38
|
"./src/IDBCache.js": "./src/IDBCache.browser.js"
|
39
39
|
},
|
40
|
-
"gitHead": "
|
40
|
+
"gitHead": "124b7fff44f71aac9fbad289a9a9509b3dfc9aaa"
|
41
41
|
}
|
package/src/LMDBLiteCache.js
CHANGED
@@ -6,6 +6,8 @@ import {tmpdir} from 'os';
|
|
6
6
|
import {LMDBLiteCache} from '../src/index';
|
7
7
|
import {deserialize, serialize} from 'v8';
|
8
8
|
import assert from 'assert';
|
9
|
+
import {Worker} from 'worker_threads';
|
10
|
+
import {initializeMonitoring} from '@atlaspack/rust';
|
9
11
|
|
10
12
|
const cacheDir = path.join(tmpdir(), 'lmdb-lite-cache-tests');
|
11
13
|
|
@@ -91,4 +93,154 @@ describe('LMDBLiteCache', () => {
|
|
91
93
|
const result = deserialize(buffer);
|
92
94
|
assert.equal(result.value, 42);
|
93
95
|
});
|
96
|
+
|
97
|
+
it('should NOT fail when trying to open the same database twice', async () => {
|
98
|
+
const testDir = path.join(cacheDir, 'double_open_test');
|
99
|
+
const cache1 = new LMDBLiteCache(testDir);
|
100
|
+
await cache1.ensure();
|
101
|
+
|
102
|
+
assert.doesNotThrow(() => {
|
103
|
+
new LMDBLiteCache(testDir);
|
104
|
+
});
|
105
|
+
});
|
106
|
+
|
107
|
+
it('should NOT fail when trying to open after GC', async () => {
|
108
|
+
const testDir = path.join(cacheDir, 'gc_test');
|
109
|
+
|
110
|
+
let cache1 = new LMDBLiteCache(testDir);
|
111
|
+
await cache1.ensure();
|
112
|
+
await cache1.setBlob('key', Buffer.from(serialize({value: 42})));
|
113
|
+
|
114
|
+
cache1 = null;
|
115
|
+
|
116
|
+
if (global.gc) {
|
117
|
+
global.gc();
|
118
|
+
}
|
119
|
+
|
120
|
+
assert.doesNotThrow(() => {
|
121
|
+
new LMDBLiteCache(testDir);
|
122
|
+
});
|
123
|
+
});
|
124
|
+
|
125
|
+
it('should handle rapid open/close cycles', async () => {
|
126
|
+
const testDir = path.join(cacheDir, 'rapid_cycles_test');
|
127
|
+
|
128
|
+
for (let i = 0; i < 10; i++) {
|
129
|
+
const cache = new LMDBLiteCache(testDir);
|
130
|
+
await cache.ensure();
|
131
|
+
await cache.setBlob(`key${i}`, Buffer.from(serialize({value: i})));
|
132
|
+
cache.getNativeRef().close();
|
133
|
+
|
134
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
135
|
+
}
|
136
|
+
|
137
|
+
const finalCache = new LMDBLiteCache(testDir);
|
138
|
+
await finalCache.ensure();
|
139
|
+
const buffer = await finalCache.getBlob('key9');
|
140
|
+
const result = deserialize(buffer);
|
141
|
+
assert.equal(result.value, 9);
|
142
|
+
});
|
143
|
+
|
144
|
+
it('should work when there are multiple node.js worker threads accessing the same database', async function () {
|
145
|
+
this.timeout(40000);
|
146
|
+
|
147
|
+
try {
|
148
|
+
initializeMonitoring();
|
149
|
+
} catch (error) {
|
150
|
+
/* empty */
|
151
|
+
}
|
152
|
+
|
153
|
+
const testDir = path.join(cacheDir, 'worker_threads_test');
|
154
|
+
|
155
|
+
let cache = new LMDBLiteCache(testDir);
|
156
|
+
await cache.set('main_thread_key', {
|
157
|
+
mainThreadId: 0,
|
158
|
+
hello: 'world',
|
159
|
+
});
|
160
|
+
setTimeout(() => {
|
161
|
+
cache?.getNativeRef().close();
|
162
|
+
cache = null;
|
163
|
+
|
164
|
+
if (global.gc) {
|
165
|
+
global.gc();
|
166
|
+
}
|
167
|
+
}, Math.random() * 300);
|
168
|
+
|
169
|
+
const numWorkers = 10;
|
170
|
+
|
171
|
+
const workers = [];
|
172
|
+
const responsePromises = [];
|
173
|
+
for (let i = 0; i < numWorkers; i++) {
|
174
|
+
const worker = new Worker(path.join(__dirname, 'workerThreadsTest.js'), {
|
175
|
+
workerData: {
|
176
|
+
cacheDir: testDir,
|
177
|
+
},
|
178
|
+
});
|
179
|
+
workers.push(worker);
|
180
|
+
|
181
|
+
const responsePromise = new Promise((resolve, reject) => {
|
182
|
+
worker.addListener('error', (error: Error) => {
|
183
|
+
reject(error);
|
184
|
+
});
|
185
|
+
worker.addListener('message', (message) => {
|
186
|
+
resolve(message);
|
187
|
+
});
|
188
|
+
});
|
189
|
+
|
190
|
+
worker.addListener('message', (message) => {
|
191
|
+
// eslint-disable-next-line no-console
|
192
|
+
console.log('Worker message', message);
|
193
|
+
});
|
194
|
+
worker.addListener('online', () => {
|
195
|
+
worker.postMessage({
|
196
|
+
type: 'go',
|
197
|
+
});
|
198
|
+
});
|
199
|
+
|
200
|
+
responsePromises.push(responsePromise);
|
201
|
+
}
|
202
|
+
|
203
|
+
// eslint-disable-next-line no-console
|
204
|
+
console.log('Waiting for responses');
|
205
|
+
const responses = await Promise.all(responsePromises);
|
206
|
+
|
207
|
+
// eslint-disable-next-line no-console
|
208
|
+
console.log('Responses received');
|
209
|
+
for (const [index, response] of responses.entries()) {
|
210
|
+
const worker = workers[index];
|
211
|
+
|
212
|
+
assert.deepEqual(
|
213
|
+
response,
|
214
|
+
{
|
215
|
+
mainThreadData: {
|
216
|
+
mainThreadId: 0,
|
217
|
+
hello: 'world',
|
218
|
+
},
|
219
|
+
workerId: worker.threadId,
|
220
|
+
},
|
221
|
+
`worker_${index} - Worker ${worker.threadId} should have received the correct data`,
|
222
|
+
);
|
223
|
+
}
|
224
|
+
|
225
|
+
// eslint-disable-next-line no-console
|
226
|
+
console.log('Getting main thread key');
|
227
|
+
cache = new LMDBLiteCache(testDir);
|
228
|
+
const data = await cache?.get('main_thread_key');
|
229
|
+
assert.deepEqual(data, {
|
230
|
+
mainThreadId: 0,
|
231
|
+
hello: 'world',
|
232
|
+
});
|
233
|
+
|
234
|
+
// eslint-disable-next-line no-console
|
235
|
+
console.log('Getting worker keys');
|
236
|
+
for (const worker of workers) {
|
237
|
+
const data = await cache?.get(`worker_key/${worker.threadId}`);
|
238
|
+
assert.deepEqual(data, {
|
239
|
+
workerId: worker.threadId,
|
240
|
+
});
|
241
|
+
|
242
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
243
|
+
worker.terminate();
|
244
|
+
}
|
245
|
+
});
|
94
246
|
});
|
@@ -0,0 +1,44 @@
|
|
1
|
+
/* eslint-disable no-inner-declarations */
|
2
|
+
|
3
|
+
require('@atlaspack/babel-register');
|
4
|
+
const {
|
5
|
+
workerData,
|
6
|
+
threadId,
|
7
|
+
parentPort,
|
8
|
+
isMainThread,
|
9
|
+
} = require('worker_threads');
|
10
|
+
const {LMDBLiteCache} = require('../src/index');
|
11
|
+
|
12
|
+
if (!isMainThread) {
|
13
|
+
const cache = new LMDBLiteCache(workerData.cacheDir);
|
14
|
+
|
15
|
+
async function onMessage() {
|
16
|
+
try {
|
17
|
+
cache.set(`worker_key/${threadId}`, {
|
18
|
+
workerId: threadId,
|
19
|
+
});
|
20
|
+
|
21
|
+
const data = await cache.get('main_thread_key');
|
22
|
+
|
23
|
+
parentPort.postMessage({
|
24
|
+
mainThreadData: data,
|
25
|
+
workerId: threadId,
|
26
|
+
});
|
27
|
+
|
28
|
+
setTimeout(() => {
|
29
|
+
cache.getNativeRef().close();
|
30
|
+
|
31
|
+
parentPort.postMessage({
|
32
|
+
type: 'close',
|
33
|
+
workerId: threadId,
|
34
|
+
});
|
35
|
+
}, Math.random() * 200);
|
36
|
+
} catch (error) {
|
37
|
+
parentPort.postMessage({
|
38
|
+
error: error.message,
|
39
|
+
});
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
parentPort.on('message', onMessage);
|
44
|
+
}
|