@atlaspack/cache 2.13.3-dev.144 → 2.13.3-dev.145
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/CHANGELOG.md +86 -0
- package/index.d.ts +0 -4
- package/lib/LMDBLiteCache.js +100 -26
- package/lib/index.js +0 -11
- package/package.json +10 -10
- package/src/LMDBLiteCache.js +83 -22
- package/src/index.js +0 -1
- package/test/LMDBLiteCache.test.js +40 -4
- package/lib/LMDBCache.js +0 -136
- package/src/LMDBCache.js +0 -139
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,91 @@
|
|
1
1
|
# @atlaspack/cache
|
2
2
|
|
3
|
+
## 3.2.3
|
4
|
+
|
5
|
+
### Patch Changes
|
6
|
+
|
7
|
+
- Updated dependencies [[`30f6017`](https://github.com/atlassian-labs/atlaspack/commit/30f60175ba4d272c5fc193973c63bc298584775b), [`3a3e8e7`](https://github.com/atlassian-labs/atlaspack/commit/3a3e8e7be9e2dffd7304436d792f0f595d59665a), [`1ab0a27`](https://github.com/atlassian-labs/atlaspack/commit/1ab0a275aeca40350415e2b03e7440d1dddc6228), [`b8a4ae8`](https://github.com/atlassian-labs/atlaspack/commit/b8a4ae8f83dc0a83d8b145c5f729936ce52080a3)]:
|
8
|
+
- @atlaspack/feature-flags@2.15.1
|
9
|
+
- @atlaspack/fs@2.15.3
|
10
|
+
- @atlaspack/rust@3.3.3
|
11
|
+
- @atlaspack/utils@2.14.8
|
12
|
+
- @atlaspack/logger@2.14.8
|
13
|
+
|
14
|
+
## 3.2.2
|
15
|
+
|
16
|
+
### Patch Changes
|
17
|
+
|
18
|
+
- Updated dependencies [[`a1773d2`](https://github.com/atlassian-labs/atlaspack/commit/a1773d2a62d0ef7805ac7524621dcabcc1afe929), [`556d6ab`](https://github.com/atlassian-labs/atlaspack/commit/556d6ab8ede759fa7f37fcd3f4da336ef1c55e8f)]:
|
19
|
+
- @atlaspack/feature-flags@2.15.0
|
20
|
+
- @atlaspack/logger@2.14.7
|
21
|
+
- @atlaspack/rust@3.3.2
|
22
|
+
- @atlaspack/fs@2.15.2
|
23
|
+
- @atlaspack/utils@2.14.7
|
24
|
+
|
25
|
+
## 3.2.1
|
26
|
+
|
27
|
+
### Patch Changes
|
28
|
+
|
29
|
+
- Updated dependencies [[`e0f5337`](https://github.com/atlassian-labs/atlaspack/commit/e0f533757bd1019dbd108a04952c87da15286e09)]:
|
30
|
+
- @atlaspack/feature-flags@2.14.4
|
31
|
+
- @atlaspack/rust@3.3.1
|
32
|
+
- @atlaspack/fs@2.15.1
|
33
|
+
- @atlaspack/utils@2.14.6
|
34
|
+
- @atlaspack/logger@2.14.6
|
35
|
+
|
36
|
+
## 3.2.0
|
37
|
+
|
38
|
+
### Minor Changes
|
39
|
+
|
40
|
+
- [#531](https://github.com/atlassian-labs/atlaspack/pull/531) [`d2c50c2`](https://github.com/atlassian-labs/atlaspack/commit/d2c50c2c020888b33bb25b8690d9320c2b69e2a6) Thanks [@yamadapc](https://github.com/yamadapc)! - Add way to iterate LMDB cache keys
|
41
|
+
|
42
|
+
### Patch Changes
|
43
|
+
|
44
|
+
- Updated dependencies [[`11d6f16`](https://github.com/atlassian-labs/atlaspack/commit/11d6f16b6397dee2f217167e5c98b39edb63f7a7), [`e2ba0f6`](https://github.com/atlassian-labs/atlaspack/commit/e2ba0f69702656f3d1ce95ab1454e35062b13b39), [`d2c50c2`](https://github.com/atlassian-labs/atlaspack/commit/d2c50c2c020888b33bb25b8690d9320c2b69e2a6), [`46a90dc`](https://github.com/atlassian-labs/atlaspack/commit/46a90dccd019a26b222c878a92d23acc75dc67c5), [`4c17141`](https://github.com/atlassian-labs/atlaspack/commit/4c1714103dab2aa9039c488f381551d2b65d1d01)]:
|
45
|
+
- @atlaspack/feature-flags@2.14.3
|
46
|
+
- @atlaspack/rust@3.3.0
|
47
|
+
- @atlaspack/fs@2.15.0
|
48
|
+
- @atlaspack/utils@2.14.5
|
49
|
+
- @atlaspack/logger@2.14.5
|
50
|
+
|
51
|
+
## 3.1.0
|
52
|
+
|
53
|
+
### Minor Changes
|
54
|
+
|
55
|
+
- [#525](https://github.com/atlassian-labs/atlaspack/pull/525) [`cb9da16`](https://github.com/atlassian-labs/atlaspack/commit/cb9da16fb2648e7f53c64df0313f60d5fb8970cc) Thanks [@yamadapc](https://github.com/yamadapc)! - Fix issues with large blob cache writes, run cache writes in a write transaction
|
56
|
+
|
57
|
+
### Patch Changes
|
58
|
+
|
59
|
+
- Updated dependencies [[`1a2c14c`](https://github.com/atlassian-labs/atlaspack/commit/1a2c14c3cd4587551cc12e94d0680c8b71ea12bf), [`cb9da16`](https://github.com/atlassian-labs/atlaspack/commit/cb9da16fb2648e7f53c64df0313f60d5fb8970cc)]:
|
60
|
+
- @atlaspack/rust@3.2.0
|
61
|
+
- @atlaspack/fs@2.14.4
|
62
|
+
- @atlaspack/logger@2.14.4
|
63
|
+
- @atlaspack/utils@2.14.4
|
64
|
+
|
65
|
+
## 3.0.1
|
66
|
+
|
67
|
+
### Patch Changes
|
68
|
+
|
69
|
+
- Updated dependencies [[`f27d39e`](https://github.com/atlassian-labs/atlaspack/commit/f27d39e767b06def059944b3bc5fd50797eaea96)]:
|
70
|
+
- @atlaspack/rust@3.1.1
|
71
|
+
- @atlaspack/fs@2.14.3
|
72
|
+
- @atlaspack/logger@2.14.3
|
73
|
+
- @atlaspack/utils@2.14.3
|
74
|
+
|
75
|
+
## 3.0.0
|
76
|
+
|
77
|
+
### Major Changes
|
78
|
+
|
79
|
+
- [#512](https://github.com/atlassian-labs/atlaspack/pull/512) [`8f4e6c1`](https://github.com/atlassian-labs/atlaspack/commit/8f4e6c1b0e7c1fd48624afda48c1dcc599f1460f) Thanks [@yamadapc](https://github.com/yamadapc)! - Remove LMDB cache back-end
|
80
|
+
|
81
|
+
### Patch Changes
|
82
|
+
|
83
|
+
- Updated dependencies [[`a891d65`](https://github.com/atlassian-labs/atlaspack/commit/a891d652bc4eb3d757d381adf65c5083f706effc), [`d02eab9`](https://github.com/atlassian-labs/atlaspack/commit/d02eab95eb60bf7457e0869af0b773608592c0e6), [`fb87a90`](https://github.com/atlassian-labs/atlaspack/commit/fb87a901973776b33ca4ce530e9d71669a9bd36d), [`7b9e8cf`](https://github.com/atlassian-labs/atlaspack/commit/7b9e8cf29e01a98e72e46b2b2fb74ccc514f4463)]:
|
84
|
+
- @atlaspack/rust@3.1.0
|
85
|
+
- @atlaspack/fs@2.14.2
|
86
|
+
- @atlaspack/utils@2.14.2
|
87
|
+
- @atlaspack/logger@2.14.2
|
88
|
+
|
3
89
|
## 2.13.3
|
4
90
|
|
5
91
|
### Patch Changes
|
package/index.d.ts
CHANGED
package/lib/LMDBLiteCache.js
CHANGED
@@ -12,6 +12,13 @@ function _buildCache() {
|
|
12
12
|
};
|
13
13
|
return data;
|
14
14
|
}
|
15
|
+
function _featureFlags() {
|
16
|
+
const data = require("@atlaspack/feature-flags");
|
17
|
+
_featureFlags = function () {
|
18
|
+
return data;
|
19
|
+
};
|
20
|
+
return data;
|
21
|
+
}
|
15
22
|
function _rust() {
|
16
23
|
const data = require("@atlaspack/rust");
|
17
24
|
_rust = function () {
|
@@ -19,16 +26,16 @@ function _rust() {
|
|
19
26
|
};
|
20
27
|
return data;
|
21
28
|
}
|
22
|
-
function
|
23
|
-
const data = _interopRequireDefault(require("
|
24
|
-
|
29
|
+
function _fs() {
|
30
|
+
const data = _interopRequireDefault(require("fs"));
|
31
|
+
_fs = function () {
|
25
32
|
return data;
|
26
33
|
};
|
27
34
|
return data;
|
28
35
|
}
|
29
|
-
function
|
30
|
-
const data = _interopRequireDefault(require("
|
31
|
-
|
36
|
+
function _ncp() {
|
37
|
+
const data = _interopRequireDefault(require("ncp"));
|
38
|
+
_ncp = function () {
|
32
39
|
return data;
|
33
40
|
};
|
34
41
|
return data;
|
@@ -40,9 +47,23 @@ function _util() {
|
|
40
47
|
};
|
41
48
|
return data;
|
42
49
|
}
|
43
|
-
function
|
50
|
+
function _stream() {
|
51
|
+
const data = _interopRequireDefault(require("stream"));
|
52
|
+
_stream = function () {
|
53
|
+
return data;
|
54
|
+
};
|
55
|
+
return data;
|
56
|
+
}
|
57
|
+
function _path() {
|
58
|
+
const data = _interopRequireDefault(require("path"));
|
59
|
+
_path = function () {
|
60
|
+
return data;
|
61
|
+
};
|
62
|
+
return data;
|
63
|
+
}
|
64
|
+
function _fs2() {
|
44
65
|
const data = require("@atlaspack/fs");
|
45
|
-
|
66
|
+
_fs2 = function () {
|
46
67
|
return data;
|
47
68
|
};
|
48
69
|
return data;
|
@@ -51,6 +72,7 @@ var _package = _interopRequireDefault(require("../package.json"));
|
|
51
72
|
var _FSCache = require("./FSCache");
|
52
73
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
53
74
|
// $FlowFixMe
|
75
|
+
const ncpAsync = (0, _util().promisify)(_ncp().default);
|
54
76
|
class LmdbWrapper {
|
55
77
|
constructor(lmdb) {
|
56
78
|
this.lmdb = lmdb;
|
@@ -60,6 +82,12 @@ class LmdbWrapper {
|
|
60
82
|
this.lmdb.close();
|
61
83
|
};
|
62
84
|
}
|
85
|
+
has(key) {
|
86
|
+
return this.lmdb.hasSync(key);
|
87
|
+
}
|
88
|
+
async delete(key) {
|
89
|
+
await this.lmdb.delete(key);
|
90
|
+
}
|
63
91
|
get(key) {
|
64
92
|
return this.lmdb.getSync(key);
|
65
93
|
}
|
@@ -67,7 +95,19 @@ class LmdbWrapper {
|
|
67
95
|
const buffer = typeof value === 'string' ? Buffer.from(value) : value;
|
68
96
|
await this.lmdb.put(key, buffer);
|
69
97
|
}
|
70
|
-
|
98
|
+
*keys() {
|
99
|
+
const PAGE_SIZE = 10000000;
|
100
|
+
let currentKeys = this.lmdb.keysSync(0, PAGE_SIZE);
|
101
|
+
while (currentKeys.length > 0) {
|
102
|
+
for (const key of currentKeys) {
|
103
|
+
yield key;
|
104
|
+
}
|
105
|
+
currentKeys = this.lmdb.keysSync(currentKeys.length, PAGE_SIZE);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
compact(targetPath) {
|
109
|
+
this.lmdb.compact(targetPath);
|
110
|
+
}
|
71
111
|
}
|
72
112
|
exports.LmdbWrapper = LmdbWrapper;
|
73
113
|
function open(directory
|
@@ -82,7 +122,7 @@ function open(directory
|
|
82
122
|
const pipeline = (0, _util().promisify)(_stream().default.pipeline);
|
83
123
|
class LMDBLiteCache {
|
84
124
|
constructor(cacheDir) {
|
85
|
-
this.fs = new (
|
125
|
+
this.fs = new (_fs2().NodeFS)();
|
86
126
|
this.dir = cacheDir;
|
87
127
|
this.fsCache = new _FSCache.FSCache(this.fs, cacheDir);
|
88
128
|
this.store = open(cacheDir, {
|
@@ -99,7 +139,9 @@ class LMDBLiteCache {
|
|
99
139
|
return this.store.lmdb;
|
100
140
|
}
|
101
141
|
async ensure() {
|
102
|
-
|
142
|
+
if (!(0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
|
143
|
+
await this.fsCache.ensure();
|
144
|
+
}
|
103
145
|
return Promise.resolve();
|
104
146
|
}
|
105
147
|
serialize() {
|
@@ -111,7 +153,7 @@ class LMDBLiteCache {
|
|
111
153
|
return new LMDBLiteCache(cache.dir);
|
112
154
|
}
|
113
155
|
has(key) {
|
114
|
-
return Promise.resolve(this.store.
|
156
|
+
return Promise.resolve(this.store.has(key));
|
115
157
|
}
|
116
158
|
get(key) {
|
117
159
|
let data = this.store.get(key);
|
@@ -151,28 +193,60 @@ class LMDBLiteCache {
|
|
151
193
|
return _path().default.join(this.dir, `${key}-${index}`);
|
152
194
|
}
|
153
195
|
hasLargeBlob(key) {
|
154
|
-
|
196
|
+
if (!(0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
|
197
|
+
return this.fsCache.hasLargeBlob(key);
|
198
|
+
}
|
199
|
+
return this.has(key);
|
155
200
|
}
|
156
201
|
|
157
|
-
|
158
|
-
|
159
|
-
|
202
|
+
/**
|
203
|
+
* @deprecated Use getBlob instead.
|
204
|
+
*/
|
205
|
+
getLargeBlob(key) {
|
206
|
+
if (!(0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
|
207
|
+
return this.fsCache.getLargeBlob(key);
|
208
|
+
}
|
209
|
+
return Promise.resolve(this.getBlobSync(key));
|
160
210
|
}
|
161
211
|
|
162
|
-
|
163
|
-
|
164
|
-
|
212
|
+
/**
|
213
|
+
* @deprecated Use setBlob instead.
|
214
|
+
*/
|
215
|
+
setLargeBlob(key, contents, options) {
|
216
|
+
if (!(0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
|
217
|
+
return this.fsCache.setLargeBlob(key, contents, options);
|
218
|
+
}
|
219
|
+
return this.setBlob(key, contents);
|
165
220
|
}
|
221
|
+
|
222
|
+
/**
|
223
|
+
* @deprecated Use store.delete instead.
|
224
|
+
*/
|
166
225
|
deleteLargeBlob(key) {
|
167
|
-
|
226
|
+
if (!(0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
|
227
|
+
return this.fsCache.deleteLargeBlob(key);
|
228
|
+
}
|
229
|
+
return this.store.delete(key);
|
168
230
|
}
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
231
|
+
keys() {
|
232
|
+
return this.store.keys();
|
233
|
+
}
|
234
|
+
async compact(targetPath) {
|
235
|
+
await _fs().default.promises.mkdir(targetPath, {
|
236
|
+
recursive: true
|
237
|
+
});
|
238
|
+
const files = await _fs().default.promises.readdir(this.dir);
|
239
|
+
// copy all files except data.mdb and lock.mdb to the target path (recursive)
|
240
|
+
for (const file of files) {
|
241
|
+
const filePath = _path().default.join(this.dir, file);
|
242
|
+
if (file === 'data.mdb' || file === 'lock.mdb') {
|
243
|
+
continue;
|
244
|
+
}
|
245
|
+
await ncpAsync(filePath, _path().default.join(targetPath, file));
|
246
|
+
}
|
247
|
+
this.store.compact(_path().default.join(targetPath, 'data.mdb'));
|
175
248
|
}
|
249
|
+
refresh() {}
|
176
250
|
}
|
177
251
|
exports.LMDBLiteCache = LMDBLiteCache;
|
178
252
|
(0, _buildCache().registerSerializableClass)(`${_package.default.version}:LMDBLiteCache`, LMDBLiteCache);
|
package/lib/index.js
CHANGED
@@ -25,17 +25,6 @@ Object.keys(_IDBCache).forEach(function (key) {
|
|
25
25
|
}
|
26
26
|
});
|
27
27
|
});
|
28
|
-
var _LMDBCache = require("./LMDBCache");
|
29
|
-
Object.keys(_LMDBCache).forEach(function (key) {
|
30
|
-
if (key === "default" || key === "__esModule") return;
|
31
|
-
if (key in exports && exports[key] === _LMDBCache[key]) return;
|
32
|
-
Object.defineProperty(exports, key, {
|
33
|
-
enumerable: true,
|
34
|
-
get: function () {
|
35
|
-
return _LMDBCache[key];
|
36
|
-
}
|
37
|
-
});
|
38
|
-
});
|
39
28
|
var _LMDBLiteCache = require("./LMDBLiteCache");
|
40
29
|
Object.keys(_LMDBLiteCache).forEach(function (key) {
|
41
30
|
if (key === "default" || key === "__esModule") return;
|
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": "2.13.3-dev.
|
4
|
+
"version": "2.13.3-dev.145+fa4d24840",
|
5
5
|
"license": "(MIT OR Apache-2.0)",
|
6
6
|
"type": "commonjs",
|
7
7
|
"publishConfig": {
|
@@ -23,19 +23,19 @@
|
|
23
23
|
"check-ts": "tsc --noEmit index.d.ts"
|
24
24
|
},
|
25
25
|
"dependencies": {
|
26
|
-
"@atlaspack/build-cache": "2.13.3-dev.
|
27
|
-
"@atlaspack/
|
28
|
-
"@atlaspack/
|
29
|
-
"@atlaspack/
|
30
|
-
"@atlaspack/
|
31
|
-
"
|
26
|
+
"@atlaspack/build-cache": "2.13.3-dev.145+fa4d24840",
|
27
|
+
"@atlaspack/feature-flags": "2.14.1-dev.145+fa4d24840",
|
28
|
+
"@atlaspack/fs": "2.14.1-dev.145+fa4d24840",
|
29
|
+
"@atlaspack/logger": "2.14.1-dev.145+fa4d24840",
|
30
|
+
"@atlaspack/rust": "3.0.1-dev.145+fa4d24840",
|
31
|
+
"@atlaspack/utils": "2.14.1-dev.145+fa4d24840",
|
32
|
+
"ncp": "^2.0.0"
|
32
33
|
},
|
33
34
|
"devDependencies": {
|
34
35
|
"idb": "^5.0.8"
|
35
36
|
},
|
36
37
|
"browser": {
|
37
|
-
"./src/IDBCache.js": "./src/IDBCache.browser.js"
|
38
|
-
"./src/LMDBCache.js": false
|
38
|
+
"./src/IDBCache.js": "./src/IDBCache.browser.js"
|
39
39
|
},
|
40
|
-
"gitHead": "
|
40
|
+
"gitHead": "fa4d24840815e7048a21d74caf01e2df633fabe3"
|
41
41
|
}
|
package/src/LMDBLiteCache.js
CHANGED
@@ -5,22 +5,23 @@ import {
|
|
5
5
|
registerSerializableClass,
|
6
6
|
serialize,
|
7
7
|
} from '@atlaspack/build-cache';
|
8
|
+
import {getFeatureFlag} from '@atlaspack/feature-flags';
|
8
9
|
import {Lmdb} from '@atlaspack/rust';
|
9
10
|
import type {FilePath} from '@atlaspack/types';
|
10
11
|
import type {Cache} from './types';
|
11
12
|
import type {Readable, Writable} from 'stream';
|
12
|
-
|
13
|
+
import fs from 'fs';
|
14
|
+
import ncp from 'ncp';
|
15
|
+
import {promisify} from 'util';
|
13
16
|
import stream from 'stream';
|
14
17
|
import path from 'path';
|
15
|
-
import {promisify} from 'util';
|
16
|
-
|
17
18
|
import {NodeFS} from '@atlaspack/fs';
|
18
|
-
|
19
19
|
// $FlowFixMe
|
20
20
|
import packageJson from '../package.json';
|
21
|
-
|
22
21
|
import {FSCache} from './FSCache';
|
23
22
|
|
23
|
+
const ncpAsync = promisify(ncp);
|
24
|
+
|
24
25
|
interface DBOpenOptions {
|
25
26
|
name: string;
|
26
27
|
// unused
|
@@ -41,6 +42,14 @@ export class LmdbWrapper {
|
|
41
42
|
};
|
42
43
|
}
|
43
44
|
|
45
|
+
has(key: string): boolean {
|
46
|
+
return this.lmdb.hasSync(key);
|
47
|
+
}
|
48
|
+
|
49
|
+
async delete(key: string): Promise<void> {
|
50
|
+
await this.lmdb.delete(key);
|
51
|
+
}
|
52
|
+
|
44
53
|
get(key: string): Buffer | null {
|
45
54
|
return this.lmdb.getSync(key);
|
46
55
|
}
|
@@ -51,7 +60,21 @@ export class LmdbWrapper {
|
|
51
60
|
await this.lmdb.put(key, buffer);
|
52
61
|
}
|
53
62
|
|
54
|
-
|
63
|
+
*keys(): Iterable<string> {
|
64
|
+
const PAGE_SIZE = 10000000;
|
65
|
+
|
66
|
+
let currentKeys = this.lmdb.keysSync(0, PAGE_SIZE);
|
67
|
+
while (currentKeys.length > 0) {
|
68
|
+
for (const key of currentKeys) {
|
69
|
+
yield key;
|
70
|
+
}
|
71
|
+
currentKeys = this.lmdb.keysSync(currentKeys.length, PAGE_SIZE);
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
compact(targetPath: string) {
|
76
|
+
this.lmdb.compact(targetPath);
|
77
|
+
}
|
55
78
|
}
|
56
79
|
|
57
80
|
export function open(
|
@@ -105,7 +128,9 @@ export class LMDBLiteCache implements Cache {
|
|
105
128
|
}
|
106
129
|
|
107
130
|
async ensure(): Promise<void> {
|
108
|
-
|
131
|
+
if (!getFeatureFlag('cachePerformanceImprovements')) {
|
132
|
+
await this.fsCache.ensure();
|
133
|
+
}
|
109
134
|
return Promise.resolve();
|
110
135
|
}
|
111
136
|
|
@@ -120,7 +145,7 @@ export class LMDBLiteCache implements Cache {
|
|
120
145
|
}
|
121
146
|
|
122
147
|
has(key: string): Promise<boolean> {
|
123
|
-
return Promise.resolve(this.store.
|
148
|
+
return Promise.resolve(this.store.has(key));
|
124
149
|
}
|
125
150
|
|
126
151
|
get<T>(key: string): Promise<?T> {
|
@@ -173,34 +198,70 @@ export class LMDBLiteCache implements Cache {
|
|
173
198
|
}
|
174
199
|
|
175
200
|
hasLargeBlob(key: string): Promise<boolean> {
|
176
|
-
|
201
|
+
if (!getFeatureFlag('cachePerformanceImprovements')) {
|
202
|
+
return this.fsCache.hasLargeBlob(key);
|
203
|
+
}
|
204
|
+
return this.has(key);
|
177
205
|
}
|
178
206
|
|
179
|
-
|
180
|
-
|
181
|
-
|
207
|
+
/**
|
208
|
+
* @deprecated Use getBlob instead.
|
209
|
+
*/
|
210
|
+
getLargeBlob(key: string): Promise<Buffer> {
|
211
|
+
if (!getFeatureFlag('cachePerformanceImprovements')) {
|
212
|
+
return this.fsCache.getLargeBlob(key);
|
213
|
+
}
|
214
|
+
return Promise.resolve(this.getBlobSync(key));
|
182
215
|
}
|
183
216
|
|
184
|
-
|
185
|
-
|
217
|
+
/**
|
218
|
+
* @deprecated Use setBlob instead.
|
219
|
+
*/
|
220
|
+
setLargeBlob(
|
186
221
|
key: string,
|
187
222
|
contents: Buffer | string,
|
188
223
|
options?: {|signal?: AbortSignal|},
|
189
224
|
): Promise<void> {
|
190
|
-
|
225
|
+
if (!getFeatureFlag('cachePerformanceImprovements')) {
|
226
|
+
return this.fsCache.setLargeBlob(key, contents, options);
|
227
|
+
}
|
228
|
+
return this.setBlob(key, contents);
|
191
229
|
}
|
192
230
|
|
231
|
+
/**
|
232
|
+
* @deprecated Use store.delete instead.
|
233
|
+
*/
|
193
234
|
deleteLargeBlob(key: string): Promise<void> {
|
194
|
-
|
235
|
+
if (!getFeatureFlag('cachePerformanceImprovements')) {
|
236
|
+
return this.fsCache.deleteLargeBlob(key);
|
237
|
+
}
|
238
|
+
|
239
|
+
return this.store.delete(key);
|
195
240
|
}
|
196
241
|
|
197
|
-
|
198
|
-
|
199
|
-
// the next read will see the latest changes to the store.
|
200
|
-
// Useful in scenarios where reads and writes are multi-threaded.
|
201
|
-
// See https://github.com/kriszyp/lmdb-js#resetreadtxn-void
|
202
|
-
this.store.resetReadTxn();
|
242
|
+
keys(): Iterable<string> {
|
243
|
+
return this.store.keys();
|
203
244
|
}
|
245
|
+
|
246
|
+
async compact(targetPath: string): Promise<void> {
|
247
|
+
await fs.promises.mkdir(targetPath, {recursive: true});
|
248
|
+
|
249
|
+
const files = await fs.promises.readdir(this.dir);
|
250
|
+
// copy all files except data.mdb and lock.mdb to the target path (recursive)
|
251
|
+
for (const file of files) {
|
252
|
+
const filePath = path.join(this.dir, file);
|
253
|
+
|
254
|
+
if (file === 'data.mdb' || file === 'lock.mdb') {
|
255
|
+
continue;
|
256
|
+
}
|
257
|
+
|
258
|
+
await ncpAsync(filePath, path.join(targetPath, file));
|
259
|
+
}
|
260
|
+
|
261
|
+
this.store.compact(path.join(targetPath, 'data.mdb'));
|
262
|
+
}
|
263
|
+
|
264
|
+
refresh(): void {}
|
204
265
|
}
|
205
266
|
|
206
267
|
registerSerializableClass(
|
package/src/index.js
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
// @flow
|
2
|
+
|
3
|
+
import * as fs from 'fs';
|
2
4
|
import * as path from 'path';
|
3
5
|
import {tmpdir} from 'os';
|
4
6
|
import {LMDBLiteCache} from '../src/index';
|
@@ -8,13 +10,23 @@ import assert from 'assert';
|
|
8
10
|
const cacheDir = path.join(tmpdir(), 'lmdb-lite-cache-tests');
|
9
11
|
|
10
12
|
describe('LMDBLiteCache', () => {
|
13
|
+
let cache;
|
14
|
+
|
15
|
+
beforeEach(async () => {
|
16
|
+
await fs.promises.rm(cacheDir, {recursive: true, force: true});
|
17
|
+
});
|
18
|
+
|
19
|
+
afterEach(() => {
|
20
|
+
cache.getNativeRef().close();
|
21
|
+
});
|
22
|
+
|
11
23
|
it('can be constructed', async () => {
|
12
|
-
|
24
|
+
cache = new LMDBLiteCache(cacheDir);
|
13
25
|
await cache.ensure();
|
14
26
|
});
|
15
27
|
|
16
28
|
it('can retrieve keys', async () => {
|
17
|
-
|
29
|
+
cache = new LMDBLiteCache(cacheDir);
|
18
30
|
await cache.ensure();
|
19
31
|
await cache.setBlob('key', Buffer.from(serialize({value: 42})));
|
20
32
|
const buffer = await cache.getBlob('key');
|
@@ -23,11 +35,35 @@ describe('LMDBLiteCache', () => {
|
|
23
35
|
});
|
24
36
|
|
25
37
|
it('can retrieve keys synchronously', async () => {
|
26
|
-
|
38
|
+
cache = new LMDBLiteCache(path.join(cacheDir, 'retrieve_keys_test'));
|
27
39
|
await cache.ensure();
|
28
|
-
cache.setBlob('key', Buffer.from(serialize({value: 42})));
|
40
|
+
await cache.setBlob('key', Buffer.from(serialize({value: 42})));
|
29
41
|
const buffer = cache.getBlobSync('key');
|
30
42
|
const result = deserialize(buffer);
|
31
43
|
assert.equal(result.value, 42);
|
32
44
|
});
|
45
|
+
|
46
|
+
it('can iterate over keys', async () => {
|
47
|
+
cache = new LMDBLiteCache(path.join(cacheDir, 'keys_test'));
|
48
|
+
await cache.ensure();
|
49
|
+
await cache.setBlob('key1', Buffer.from(serialize({value: 42})));
|
50
|
+
await cache.setBlob('key2', Buffer.from(serialize({value: 43})));
|
51
|
+
const keys = cache.keys();
|
52
|
+
assert.deepEqual(Array.from(keys), ['key1', 'key2']);
|
53
|
+
});
|
54
|
+
|
55
|
+
it('can compact databases', async () => {
|
56
|
+
cache = new LMDBLiteCache(path.join(cacheDir, 'compact_test'));
|
57
|
+
await cache.ensure();
|
58
|
+
await cache.setBlob('key1', Buffer.from(serialize({value: 42})));
|
59
|
+
await cache.setBlob('key2', Buffer.from(serialize({value: 43})));
|
60
|
+
await cache.compact(path.join(cacheDir, 'compact_test_compacted'));
|
61
|
+
|
62
|
+
cache.getNativeRef().close();
|
63
|
+
|
64
|
+
cache = new LMDBLiteCache(path.join(cacheDir, 'compact_test_compacted'));
|
65
|
+
await cache.ensure();
|
66
|
+
const keys = cache.keys();
|
67
|
+
assert.deepEqual(Array.from(keys), ['key1', 'key2']);
|
68
|
+
});
|
33
69
|
});
|
package/lib/LMDBCache.js
DELETED
@@ -1,136 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
4
|
-
value: true
|
5
|
-
});
|
6
|
-
exports.LMDBCache = void 0;
|
7
|
-
function _stream() {
|
8
|
-
const data = _interopRequireDefault(require("stream"));
|
9
|
-
_stream = function () {
|
10
|
-
return data;
|
11
|
-
};
|
12
|
-
return data;
|
13
|
-
}
|
14
|
-
function _path() {
|
15
|
-
const data = _interopRequireDefault(require("path"));
|
16
|
-
_path = function () {
|
17
|
-
return data;
|
18
|
-
};
|
19
|
-
return data;
|
20
|
-
}
|
21
|
-
function _util() {
|
22
|
-
const data = require("util");
|
23
|
-
_util = function () {
|
24
|
-
return data;
|
25
|
-
};
|
26
|
-
return data;
|
27
|
-
}
|
28
|
-
function _buildCache() {
|
29
|
-
const data = require("@atlaspack/build-cache");
|
30
|
-
_buildCache = function () {
|
31
|
-
return data;
|
32
|
-
};
|
33
|
-
return data;
|
34
|
-
}
|
35
|
-
function _fs() {
|
36
|
-
const data = require("@atlaspack/fs");
|
37
|
-
_fs = function () {
|
38
|
-
return data;
|
39
|
-
};
|
40
|
-
return data;
|
41
|
-
}
|
42
|
-
function _lmdb() {
|
43
|
-
const data = _interopRequireDefault(require("lmdb"));
|
44
|
-
_lmdb = function () {
|
45
|
-
return data;
|
46
|
-
};
|
47
|
-
return data;
|
48
|
-
}
|
49
|
-
var _package = _interopRequireDefault(require("../package.json"));
|
50
|
-
var _FSCache = require("./FSCache");
|
51
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
52
|
-
// flowlint-next-line untyped-import:off
|
53
|
-
// $FlowFixMe
|
54
|
-
const pipeline = (0, _util().promisify)(_stream().default.pipeline);
|
55
|
-
class LMDBCache {
|
56
|
-
// $FlowFixMe
|
57
|
-
|
58
|
-
constructor(cacheDir) {
|
59
|
-
this.fs = new (_fs().NodeFS)();
|
60
|
-
this.dir = cacheDir;
|
61
|
-
this.fsCache = new _FSCache.FSCache(this.fs, cacheDir);
|
62
|
-
this.store = _lmdb().default.open(cacheDir, {
|
63
|
-
name: 'parcel-cache',
|
64
|
-
encoding: 'binary',
|
65
|
-
compression: true
|
66
|
-
});
|
67
|
-
}
|
68
|
-
ensure() {
|
69
|
-
return Promise.resolve();
|
70
|
-
}
|
71
|
-
serialize() {
|
72
|
-
return {
|
73
|
-
dir: this.dir
|
74
|
-
};
|
75
|
-
}
|
76
|
-
static deserialize(opts) {
|
77
|
-
return new LMDBCache(opts.dir);
|
78
|
-
}
|
79
|
-
has(key) {
|
80
|
-
return Promise.resolve(this.store.get(key) != null);
|
81
|
-
}
|
82
|
-
get(key) {
|
83
|
-
let data = this.store.get(key);
|
84
|
-
if (data == null) {
|
85
|
-
return Promise.resolve(null);
|
86
|
-
}
|
87
|
-
return Promise.resolve((0, _buildCache().deserialize)(data));
|
88
|
-
}
|
89
|
-
async set(key, value) {
|
90
|
-
await this.setBlob(key, (0, _buildCache().serialize)(value));
|
91
|
-
}
|
92
|
-
getStream(key) {
|
93
|
-
return this.fs.createReadStream(_path().default.join(this.dir, key));
|
94
|
-
}
|
95
|
-
setStream(key, stream) {
|
96
|
-
return pipeline(stream, this.fs.createWriteStream(_path().default.join(this.dir, key)));
|
97
|
-
}
|
98
|
-
getBlob(key) {
|
99
|
-
let buffer = this.store.get(key);
|
100
|
-
return buffer != null ? Promise.resolve(buffer) : Promise.reject(new Error(`Key ${key} not found in cache`));
|
101
|
-
}
|
102
|
-
async setBlob(key, contents) {
|
103
|
-
await this.store.put(key, contents);
|
104
|
-
}
|
105
|
-
getBuffer(key) {
|
106
|
-
return Promise.resolve(this.store.get(key));
|
107
|
-
}
|
108
|
-
#getFilePath(key, index) {
|
109
|
-
return _path().default.join(this.dir, `${key}-${index}`);
|
110
|
-
}
|
111
|
-
hasLargeBlob(key) {
|
112
|
-
return this.fs.exists(this.#getFilePath(key, 0));
|
113
|
-
}
|
114
|
-
|
115
|
-
// eslint-disable-next-line require-await
|
116
|
-
async getLargeBlob(key) {
|
117
|
-
return this.fsCache.getLargeBlob(key);
|
118
|
-
}
|
119
|
-
|
120
|
-
// eslint-disable-next-line require-await
|
121
|
-
async setLargeBlob(key, contents, options) {
|
122
|
-
return this.fsCache.setLargeBlob(key, contents, options);
|
123
|
-
}
|
124
|
-
deleteLargeBlob(key) {
|
125
|
-
return this.fsCache.deleteLargeBlob(key);
|
126
|
-
}
|
127
|
-
refresh() {
|
128
|
-
// Reset the read transaction for the store. This guarantees that
|
129
|
-
// the next read will see the latest changes to the store.
|
130
|
-
// Useful in scenarios where reads and writes are multi-threaded.
|
131
|
-
// See https://github.com/kriszyp/lmdb-js#resetreadtxn-void
|
132
|
-
this.store.resetReadTxn();
|
133
|
-
}
|
134
|
-
}
|
135
|
-
exports.LMDBCache = LMDBCache;
|
136
|
-
(0, _buildCache().registerSerializableClass)(`${_package.default.version}:LMDBCache`, LMDBCache);
|
package/src/LMDBCache.js
DELETED
@@ -1,139 +0,0 @@
|
|
1
|
-
// @flow strict-local
|
2
|
-
import type {FilePath} from '@atlaspack/types';
|
3
|
-
import type {Cache} from './types';
|
4
|
-
import type {Readable, Writable} from 'stream';
|
5
|
-
|
6
|
-
import stream from 'stream';
|
7
|
-
import path from 'path';
|
8
|
-
import {promisify} from 'util';
|
9
|
-
|
10
|
-
import {
|
11
|
-
deserialize,
|
12
|
-
registerSerializableClass,
|
13
|
-
serialize,
|
14
|
-
} from '@atlaspack/build-cache';
|
15
|
-
import {NodeFS} from '@atlaspack/fs';
|
16
|
-
// flowlint-next-line untyped-import:off
|
17
|
-
import lmdb from 'lmdb';
|
18
|
-
|
19
|
-
// $FlowFixMe
|
20
|
-
import packageJson from '../package.json';
|
21
|
-
|
22
|
-
import {FSCache} from './FSCache';
|
23
|
-
|
24
|
-
const pipeline: (Readable, Writable) => Promise<void> = promisify(
|
25
|
-
stream.pipeline,
|
26
|
-
);
|
27
|
-
|
28
|
-
export class LMDBCache implements Cache {
|
29
|
-
fs: NodeFS;
|
30
|
-
dir: FilePath;
|
31
|
-
// $FlowFixMe
|
32
|
-
store: any;
|
33
|
-
fsCache: FSCache;
|
34
|
-
|
35
|
-
constructor(cacheDir: FilePath) {
|
36
|
-
this.fs = new NodeFS();
|
37
|
-
this.dir = cacheDir;
|
38
|
-
this.fsCache = new FSCache(this.fs, cacheDir);
|
39
|
-
|
40
|
-
this.store = lmdb.open(cacheDir, {
|
41
|
-
name: 'parcel-cache',
|
42
|
-
encoding: 'binary',
|
43
|
-
compression: true,
|
44
|
-
});
|
45
|
-
}
|
46
|
-
|
47
|
-
ensure(): Promise<void> {
|
48
|
-
return Promise.resolve();
|
49
|
-
}
|
50
|
-
|
51
|
-
serialize(): {|dir: FilePath|} {
|
52
|
-
return {
|
53
|
-
dir: this.dir,
|
54
|
-
};
|
55
|
-
}
|
56
|
-
|
57
|
-
static deserialize(opts: {|dir: FilePath|}): LMDBCache {
|
58
|
-
return new LMDBCache(opts.dir);
|
59
|
-
}
|
60
|
-
|
61
|
-
has(key: string): Promise<boolean> {
|
62
|
-
return Promise.resolve(this.store.get(key) != null);
|
63
|
-
}
|
64
|
-
|
65
|
-
get<T>(key: string): Promise<?T> {
|
66
|
-
let data = this.store.get(key);
|
67
|
-
if (data == null) {
|
68
|
-
return Promise.resolve(null);
|
69
|
-
}
|
70
|
-
|
71
|
-
return Promise.resolve(deserialize(data));
|
72
|
-
}
|
73
|
-
|
74
|
-
async set(key: string, value: mixed): Promise<void> {
|
75
|
-
await this.setBlob(key, serialize(value));
|
76
|
-
}
|
77
|
-
|
78
|
-
getStream(key: string): Readable {
|
79
|
-
return this.fs.createReadStream(path.join(this.dir, key));
|
80
|
-
}
|
81
|
-
|
82
|
-
setStream(key: string, stream: Readable): Promise<void> {
|
83
|
-
return pipeline(
|
84
|
-
stream,
|
85
|
-
this.fs.createWriteStream(path.join(this.dir, key)),
|
86
|
-
);
|
87
|
-
}
|
88
|
-
|
89
|
-
getBlob(key: string): Promise<Buffer> {
|
90
|
-
let buffer = this.store.get(key);
|
91
|
-
return buffer != null
|
92
|
-
? Promise.resolve(buffer)
|
93
|
-
: Promise.reject(new Error(`Key ${key} not found in cache`));
|
94
|
-
}
|
95
|
-
|
96
|
-
async setBlob(key: string, contents: Buffer | string): Promise<void> {
|
97
|
-
await this.store.put(key, contents);
|
98
|
-
}
|
99
|
-
|
100
|
-
getBuffer(key: string): Promise<?Buffer> {
|
101
|
-
return Promise.resolve(this.store.get(key));
|
102
|
-
}
|
103
|
-
|
104
|
-
#getFilePath(key: string, index: number): string {
|
105
|
-
return path.join(this.dir, `${key}-${index}`);
|
106
|
-
}
|
107
|
-
|
108
|
-
hasLargeBlob(key: string): Promise<boolean> {
|
109
|
-
return this.fs.exists(this.#getFilePath(key, 0));
|
110
|
-
}
|
111
|
-
|
112
|
-
// eslint-disable-next-line require-await
|
113
|
-
async getLargeBlob(key: string): Promise<Buffer> {
|
114
|
-
return this.fsCache.getLargeBlob(key);
|
115
|
-
}
|
116
|
-
|
117
|
-
// eslint-disable-next-line require-await
|
118
|
-
async setLargeBlob(
|
119
|
-
key: string,
|
120
|
-
contents: Buffer | string,
|
121
|
-
options?: {|signal?: AbortSignal|},
|
122
|
-
): Promise<void> {
|
123
|
-
return this.fsCache.setLargeBlob(key, contents, options);
|
124
|
-
}
|
125
|
-
|
126
|
-
deleteLargeBlob(key: string): Promise<void> {
|
127
|
-
return this.fsCache.deleteLargeBlob(key);
|
128
|
-
}
|
129
|
-
|
130
|
-
refresh(): void {
|
131
|
-
// Reset the read transaction for the store. This guarantees that
|
132
|
-
// the next read will see the latest changes to the store.
|
133
|
-
// Useful in scenarios where reads and writes are multi-threaded.
|
134
|
-
// See https://github.com/kriszyp/lmdb-js#resetreadtxn-void
|
135
|
-
this.store.resetReadTxn();
|
136
|
-
}
|
137
|
-
}
|
138
|
-
|
139
|
-
registerSerializableClass(`${packageJson.version}:LMDBCache`, LMDBCache);
|