@atlaspack/cache 3.1.1-canary.44 → 3.1.1-canary.46

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