@atlaspack/core 2.14.1-dev.142 → 2.14.1-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 CHANGED
@@ -1,5 +1,147 @@
1
1
  # @atlaspack/core
2
2
 
3
+ ## 2.17.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#551](https://github.com/atlassian-labs/atlaspack/pull/551) [`30f6017`](https://github.com/atlassian-labs/atlaspack/commit/30f60175ba4d272c5fc193973c63bc298584775b) Thanks [@yamadapc](https://github.com/yamadapc)! - Log request tracker invalidation counts on start-up
8
+
9
+ - [#550](https://github.com/atlassian-labs/atlaspack/pull/550) [`3a3e8e7`](https://github.com/atlassian-labs/atlaspack/commit/3a3e8e7be9e2dffd7304436d792f0f595d59665a) Thanks [@yamadapc](https://github.com/yamadapc)! - Fix typescript declaration files
10
+
11
+ - [#555](https://github.com/atlassian-labs/atlaspack/pull/555) [`15c1e3c`](https://github.com/atlassian-labs/atlaspack/commit/15c1e3c0628bae4c768d76cf3afc53d6d0d7ce7c) Thanks [@alshdavid](https://github.com/alshdavid)! - Added ATLASPACK_NATIVE_THREADS env variable to control the number of threads used by the native thread schedular
12
+
13
+ - 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)]:
14
+ - @atlaspack/feature-flags@2.15.1
15
+ - @atlaspack/fs@2.15.3
16
+ - @atlaspack/rust@3.3.3
17
+ - @atlaspack/cache@3.2.3
18
+ - @atlaspack/graph@3.4.6
19
+ - @atlaspack/utils@2.14.8
20
+ - @atlaspack/package-manager@2.14.8
21
+ - @atlaspack/logger@2.14.8
22
+ - @atlaspack/profiler@2.14.6
23
+ - @atlaspack/types@2.14.8
24
+ - @atlaspack/workers@2.14.8
25
+ - @atlaspack/plugin@2.14.8
26
+
27
+ ## 2.17.2
28
+
29
+ ### Patch Changes
30
+
31
+ - Updated dependencies [[`a1773d2`](https://github.com/atlassian-labs/atlaspack/commit/a1773d2a62d0ef7805ac7524621dcabcc1afe929), [`556d6ab`](https://github.com/atlassian-labs/atlaspack/commit/556d6ab8ede759fa7f37fcd3f4da336ef1c55e8f)]:
32
+ - @atlaspack/feature-flags@2.15.0
33
+ - @atlaspack/logger@2.14.7
34
+ - @atlaspack/rust@3.3.2
35
+ - @atlaspack/cache@3.2.2
36
+ - @atlaspack/fs@2.15.2
37
+ - @atlaspack/graph@3.4.5
38
+ - @atlaspack/utils@2.14.7
39
+ - @atlaspack/package-manager@2.14.7
40
+ - @atlaspack/workers@2.14.7
41
+ - @atlaspack/profiler@2.14.5
42
+ - @atlaspack/types@2.14.7
43
+ - @atlaspack/plugin@2.14.7
44
+
45
+ ## 2.17.1
46
+
47
+ ### Patch Changes
48
+
49
+ - Updated dependencies [[`e0f5337`](https://github.com/atlassian-labs/atlaspack/commit/e0f533757bd1019dbd108a04952c87da15286e09)]:
50
+ - @atlaspack/feature-flags@2.14.4
51
+ - @atlaspack/rust@3.3.1
52
+ - @atlaspack/cache@3.2.1
53
+ - @atlaspack/fs@2.15.1
54
+ - @atlaspack/graph@3.4.4
55
+ - @atlaspack/utils@2.14.6
56
+ - @atlaspack/logger@2.14.6
57
+ - @atlaspack/package-manager@2.14.6
58
+ - @atlaspack/profiler@2.14.4
59
+ - @atlaspack/types@2.14.6
60
+ - @atlaspack/workers@2.14.6
61
+ - @atlaspack/plugin@2.14.6
62
+
63
+ ## 2.17.0
64
+
65
+ ### Minor Changes
66
+
67
+ - [#541](https://github.com/atlassian-labs/atlaspack/pull/541) [`e2ba0f6`](https://github.com/atlassian-labs/atlaspack/commit/e2ba0f69702656f3d1ce95ab1454e35062b13b39) Thanks [@yamadapc](https://github.com/yamadapc)! - Add database compaction debug command
68
+
69
+ ### Patch Changes
70
+
71
+ - [#530](https://github.com/atlassian-labs/atlaspack/pull/530) [`2e90c9b`](https://github.com/atlassian-labs/atlaspack/commit/2e90c9bd07d7eb52645f9d84ccbb7f82685cbc8c) Thanks [@yamadapc](https://github.com/yamadapc)! - Write metadata about the cache in a new entry
72
+
73
+ - [#511](https://github.com/atlassian-labs/atlaspack/pull/511) [`11d6f16`](https://github.com/atlassian-labs/atlaspack/commit/11d6f16b6397dee2f217167e5c98b39edb63f7a7) Thanks [@yamadapc](https://github.com/yamadapc)! - Clean-up dylib worker threads segmentation fault bug fix feature-flag
74
+
75
+ - 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)]:
76
+ - @atlaspack/feature-flags@2.14.3
77
+ - @atlaspack/rust@3.3.0
78
+ - @atlaspack/cache@3.2.0
79
+ - @atlaspack/fs@2.15.0
80
+ - @atlaspack/graph@3.4.3
81
+ - @atlaspack/utils@2.14.5
82
+ - @atlaspack/logger@2.14.5
83
+ - @atlaspack/package-manager@2.14.5
84
+ - @atlaspack/profiler@2.14.3
85
+ - @atlaspack/types@2.14.5
86
+ - @atlaspack/workers@2.14.5
87
+ - @atlaspack/plugin@2.14.5
88
+
89
+ ## 2.16.1
90
+
91
+ ### Patch Changes
92
+
93
+ - [#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
94
+
95
+ - Updated dependencies [[`1a2c14c`](https://github.com/atlassian-labs/atlaspack/commit/1a2c14c3cd4587551cc12e94d0680c8b71ea12bf), [`cb9da16`](https://github.com/atlassian-labs/atlaspack/commit/cb9da16fb2648e7f53c64df0313f60d5fb8970cc)]:
96
+ - @atlaspack/rust@3.2.0
97
+ - @atlaspack/cache@3.1.0
98
+ - @atlaspack/fs@2.14.4
99
+ - @atlaspack/logger@2.14.4
100
+ - @atlaspack/utils@2.14.4
101
+ - @atlaspack/package-manager@2.14.4
102
+ - @atlaspack/workers@2.14.4
103
+ - @atlaspack/types@2.14.4
104
+ - @atlaspack/plugin@2.14.4
105
+
106
+ ## 2.16.0
107
+
108
+ ### Minor Changes
109
+
110
+ - [#520](https://github.com/atlassian-labs/atlaspack/pull/520) [`90150df`](https://github.com/atlassian-labs/atlaspack/commit/90150dfb68236e1d1c11813108ecabd92cff9366) Thanks [@pancaspe87](https://github.com/pancaspe87)! - Modify "large blobs" to be written to the LMDB cache
111
+
112
+ ### Patch Changes
113
+
114
+ - Updated dependencies [[`f27d39e`](https://github.com/atlassian-labs/atlaspack/commit/f27d39e767b06def059944b3bc5fd50797eaea96)]:
115
+ - @atlaspack/rust@3.1.1
116
+ - @atlaspack/cache@3.0.1
117
+ - @atlaspack/fs@2.14.3
118
+ - @atlaspack/logger@2.14.3
119
+ - @atlaspack/utils@2.14.3
120
+ - @atlaspack/package-manager@2.14.3
121
+ - @atlaspack/workers@2.14.3
122
+ - @atlaspack/types@2.14.3
123
+ - @atlaspack/plugin@2.14.3
124
+
125
+ ## 2.15.1
126
+
127
+ ### Patch Changes
128
+
129
+ - [#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
130
+
131
+ - Updated dependencies [[`9b85d3e`](https://github.com/atlassian-labs/atlaspack/commit/9b85d3e645b10bd027eed2304afc970a5ba40062), [`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), [`17b9579`](https://github.com/atlassian-labs/atlaspack/commit/17b9579484eced0ed8f23e2aba6d23b3c7238c39), [`8f4e6c1`](https://github.com/atlassian-labs/atlaspack/commit/8f4e6c1b0e7c1fd48624afda48c1dcc599f1460f)]:
132
+ - @atlaspack/feature-flags@2.14.2
133
+ - @atlaspack/rust@3.1.0
134
+ - @atlaspack/cache@3.0.0
135
+ - @atlaspack/fs@2.14.2
136
+ - @atlaspack/graph@3.4.2
137
+ - @atlaspack/utils@2.14.2
138
+ - @atlaspack/logger@2.14.2
139
+ - @atlaspack/package-manager@2.14.2
140
+ - @atlaspack/profiler@2.14.2
141
+ - @atlaspack/types@2.14.2
142
+ - @atlaspack/workers@2.14.2
143
+ - @atlaspack/plugin@2.14.2
144
+
3
145
  ## 2.15.0
4
146
 
5
147
  ### Minor Changes
package/lib/Atlaspack.js CHANGED
@@ -166,9 +166,7 @@ class Atlaspack {
166
166
  ...this.#initialOptions.featureFlags
167
167
  };
168
168
  (0, _featureFlags().setFeatureFlags)(featureFlags);
169
- if ((0, _featureFlags().getFeatureFlag)('enableRustWorkerThreadDylibHack')) {
170
- (0, _rustWorkerThreadDylibHack.loadRustWorkerThreadDylibHack)();
171
- }
169
+ (0, _rustWorkerThreadDylibHack.loadRustWorkerThreadDylibHack)();
172
170
  await _sourceMap().init;
173
171
  await (_rust().init === null || _rust().init === void 0 ? void 0 : (0, _rust().init)());
174
172
  this.#disposable = new (_events().Disposable)();
@@ -209,9 +207,15 @@ class Atlaspack {
209
207
  // $FlowFixMe
210
208
  const version = require('../package.json').version;
211
209
  await lmdb.put('current_session_version', Buffer.from(version));
210
+ let threads = undefined;
211
+ if (process.env.ATLASPACK_NATIVE_THREADS !== undefined) {
212
+ threads = parseInt(process.env.ATLASPACK_NATIVE_THREADS, 10);
213
+ } else if (process.env.NODE_ENV === 'test') {
214
+ threads = 2;
215
+ }
212
216
  rustAtlaspack = await _atlaspackV.AtlaspackV3.create({
213
217
  ...options,
214
- threads: process.env.NODE_ENV === 'test' ? 2 : undefined,
218
+ threads,
215
219
  entries: Array.isArray(entries) ? entries : entries == null ? undefined : [entries],
216
220
  env: resolvedOptions.env,
217
221
  fs: inputFS && new _atlaspackV.FileSystemV3(inputFS),
@@ -602,6 +606,19 @@ class Atlaspack {
602
606
  }
603
607
  return result;
604
608
  }
609
+
610
+ /**
611
+ * Copy the cache to a new directory and compact it.
612
+ */
613
+ async unstable_compactCache() {
614
+ await this._init();
615
+ const cache = (0, _nullthrows().default)(this.#resolvedOptions).cache;
616
+ if (cache instanceof _cache().LMDBLiteCache) {
617
+ await cache.compact('parcel-cache-compacted');
618
+ } else {
619
+ throw new Error('Cache is not an LMDBLiteCache');
620
+ }
621
+ }
605
622
  async unstable_transform(options) {
606
623
  var _options$env;
607
624
  if (!this.#initialized) {
@@ -30,6 +30,13 @@ function _buildCache() {
30
30
  };
31
31
  return data;
32
32
  }
33
+ function _cache() {
34
+ const data = require("@atlaspack/cache");
35
+ _cache = function () {
36
+ return data;
37
+ };
38
+ return data;
39
+ }
33
40
  function _featureFlags() {
34
41
  const data = require("@atlaspack/feature-flags");
35
42
  _featureFlags = function () {
@@ -45,7 +52,7 @@ function _graph() {
45
52
  return data;
46
53
  }
47
54
  function _logger() {
48
- const data = _interopRequireDefault(require("@atlaspack/logger"));
55
+ const data = _interopRequireWildcard(require("@atlaspack/logger"));
49
56
  _logger = function () {
50
57
  return data;
51
58
  };
@@ -272,6 +279,12 @@ class RequestGraph extends _graph().ContentGraph {
272
279
  // If the node is invalidated, the cached request chunk on disk needs to be re-written
273
280
  this.removeCachedRequestChunkForNode(nodeId);
274
281
  }
282
+
283
+ /**
284
+ * Nodes that are invalidated on start-up, such as JavaScript babel configuration files which are
285
+ * imported when the build kicks-off and might doing arbitrary work such as reading from the file
286
+ * system.
287
+ */
275
288
  invalidateUnpredictableNodes() {
276
289
  for (let nodeId of this.unpredicatableNodeIds) {
277
290
  let node = (0, _nullthrows().default)(this.getNode(nodeId));
@@ -279,6 +292,10 @@ class RequestGraph extends _graph().ContentGraph {
279
292
  this.invalidateNode(nodeId, _constants.STARTUP);
280
293
  }
281
294
  }
295
+
296
+ /**
297
+ * Effectively uncacheable nodes.
298
+ */
282
299
  invalidateOnBuildNodes() {
283
300
  for (let nodeId of this.invalidateOnBuildNodeIds) {
284
301
  let node = (0, _nullthrows().default)(this.getNode(nodeId));
@@ -286,29 +303,45 @@ class RequestGraph extends _graph().ContentGraph {
286
303
  this.invalidateNode(nodeId, _constants.STARTUP);
287
304
  }
288
305
  }
306
+
307
+ /**
308
+ * Nodes invalidated by environment changes, corresponds to `env: ...` inputs.
309
+ */
289
310
  invalidateEnvNodes(env) {
311
+ const invalidatedKeys = [];
290
312
  for (let nodeId of this.envNodeIds) {
291
313
  let node = (0, _nullthrows().default)(this.getNode(nodeId));
292
314
  (0, _assert().default)(node.type === ENV);
293
- if (env[keyFromEnvContentKey(node.id)] !== node.value) {
315
+ const key = keyFromEnvContentKey(node.id);
316
+ if (env[key] !== node.value) {
317
+ invalidatedKeys.push(key);
294
318
  let parentNodes = this.getNodeIdsConnectedTo(nodeId, requestGraphEdgeTypes.invalidated_by_update);
295
319
  for (let parentNode of parentNodes) {
296
320
  this.invalidateNode(parentNode, _constants.ENV_CHANGE);
297
321
  }
298
322
  }
299
323
  }
324
+ return invalidatedKeys;
300
325
  }
326
+
327
+ /**
328
+ * Nodes invalidated by option changes.
329
+ */
301
330
  invalidateOptionNodes(options) {
331
+ const invalidatedKeys = [];
302
332
  for (let nodeId of this.optionNodeIds) {
303
333
  let node = (0, _nullthrows().default)(this.getNode(nodeId));
304
334
  (0, _assert().default)(node.type === OPTION);
305
- if ((0, _utils2.hashFromOption)(options[keyFromOptionContentKey(node.id)]) !== node.hash) {
335
+ const key = keyFromOptionContentKey(node.id);
336
+ if ((0, _utils2.hashFromOption)(options[key]) !== node.hash) {
337
+ invalidatedKeys.push(key);
306
338
  let parentNodes = this.getNodeIdsConnectedTo(nodeId, requestGraphEdgeTypes.invalidated_by_update);
307
339
  for (let parentNode of parentNodes) {
308
340
  this.invalidateNode(parentNode, _constants.OPTION_CHANGE);
309
341
  }
310
342
  }
311
343
  }
344
+ return invalidatedKeys;
312
345
  }
313
346
  invalidateOnConfigKeyChange(requestNodeId, filePath, configKey, contentHash) {
314
347
  let configKeyNodeId = this.addNode(nodeFromConfigKey(filePath, configKey, contentHash));
@@ -759,8 +792,10 @@ class RequestTracker {
759
792
  return result;
760
793
  } else if (node.resultCacheKey != null && ifMatch == null) {
761
794
  let key = node.resultCacheKey;
762
- (0, _assert().default)(this.options.cache.hasLargeBlob(key));
763
- let cachedResult = (0, _buildCache().deserialize)(await this.options.cache.getLargeBlob(key));
795
+ if (!(0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
796
+ (0, _assert().default)(this.options.cache.hasLargeBlob(key));
797
+ }
798
+ let cachedResult = (0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements') ? (0, _nullthrows().default)(await this.options.cache.get(key)) : (0, _buildCache().deserialize)(await this.options.cache.getLargeBlob(key));
764
799
  node.result = cachedResult;
765
800
  return cachedResult;
766
801
  }
@@ -924,6 +959,20 @@ class RequestTracker {
924
959
  };
925
960
  }
926
961
  async writeToCache(signal) {
962
+ const options = this.options;
963
+ async function runCacheImprovements(newPath, oldPath) {
964
+ if ((0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
965
+ (0, _assert().default)(options.cache instanceof _cache().LMDBLiteCache);
966
+ const result = await newPath(options.cache);
967
+ return result;
968
+ } else {
969
+ const result = await oldPath();
970
+ return result;
971
+ }
972
+ }
973
+ await runCacheImprovements(async cache => {
974
+ await cache.getNativeRef().startWriteTransaction();
975
+ }, () => Promise.resolve());
927
976
  let cacheKey = getCacheKey(this.options);
928
977
  let requestGraphKey = `requestGraph-${cacheKey}`;
929
978
  if (this.options.shouldDisableCache) {
@@ -944,9 +993,16 @@ class RequestTracker {
944
993
  if (signal !== null && signal !== void 0 && signal.aborted) {
945
994
  throw new Error('Serialization was aborted');
946
995
  }
947
- await this.options.cache.setLargeBlob(key, (0, _buildCache().serialize)(contents), signal ? {
948
- signal: signal
949
- } : undefined);
996
+ await runCacheImprovements(cache => {
997
+ (0, _logger().instrument)(`cache.put(${key})`, () => {
998
+ cache.getNativeRef().putNoConfirm(key, (0, _buildCache().serialize)(contents));
999
+ });
1000
+ return Promise.resolve();
1001
+ }, async () => {
1002
+ await this.options.cache.setLargeBlob(key, (0, _buildCache().serialize)(contents), signal ? {
1003
+ signal: signal
1004
+ } : undefined);
1005
+ });
950
1006
  total += 1;
951
1007
  (0, _ReporterRunner.report)({
952
1008
  type: 'cache',
@@ -1000,6 +1056,13 @@ class RequestTracker {
1000
1056
  nodeCountsPerBlob,
1001
1057
  nodes: undefined
1002
1058
  });
1059
+ await runCacheImprovements(() => serialiseAndSet(`request_tracker:cache_metadata:${cacheKey}`, {
1060
+ version: _constants.ATLASPACK_VERSION,
1061
+ entries: this.options.entries,
1062
+ mode: this.options.mode,
1063
+ shouldBuildLazily: this.options.shouldBuildLazily,
1064
+ watchBackend: this.options.watchBackend
1065
+ }), () => Promise.resolve());
1003
1066
  let opts = getWatcherOptions(this.options);
1004
1067
  let snapshotPath = _path2().default.join(this.options.cacheDir, `snapshot-${cacheKey}` + '.txt');
1005
1068
  await this.options.outputFS.writeSnapshot(this.options.watchDir, snapshotPath, opts);
@@ -1007,6 +1070,9 @@ class RequestTracker {
1007
1070
  // If we have aborted, ignore the error and continue
1008
1071
  if (!(signal !== null && signal !== void 0 && signal.aborted)) throw err;
1009
1072
  }
1073
+ await runCacheImprovements(async cache => {
1074
+ await cache.getNativeRef().commitWriteTransaction();
1075
+ }, () => Promise.resolve());
1010
1076
  (0, _ReporterRunner.report)({
1011
1077
  type: 'cache',
1012
1078
  phase: 'end',
@@ -1079,12 +1145,22 @@ async function loadRequestGraph(options) {
1079
1145
  let timeout;
1080
1146
  const snapshotKey = `snapshot-${cacheKey}`;
1081
1147
  const snapshotPath = _path2().default.join(options.cacheDir, snapshotKey + '.txt');
1148
+ const commonMeta = {
1149
+ cacheKey,
1150
+ snapshotKey,
1151
+ cacheKeyOptions: {
1152
+ version: _constants.ATLASPACK_VERSION,
1153
+ entries: options.entries,
1154
+ mode: options.mode,
1155
+ shouldBuildLazily: options.shouldBuildLazily,
1156
+ watchBackend: options.watchBackend
1157
+ }
1158
+ };
1082
1159
  _logger().default.verbose({
1083
1160
  origin: '@atlaspack/core',
1084
1161
  message: 'Loading request graph',
1085
1162
  meta: {
1086
- cacheKey,
1087
- snapshotKey
1163
+ ...commonMeta
1088
1164
  }
1089
1165
  });
1090
1166
  if (await options.cache.hasLargeBlob(requestGraphKey)) {
@@ -1106,16 +1182,29 @@ async function loadRequestGraph(options) {
1106
1182
  origin: '@atlaspack/core',
1107
1183
  message: `File system event count: ${events.length}`,
1108
1184
  meta: {
1185
+ ...commonMeta,
1109
1186
  trackableEvent: 'watcher_events_count',
1110
1187
  watcherEventCount: events.length,
1111
1188
  duration: Date.now() - startTime
1112
1189
  }
1113
1190
  });
1114
- requestGraph.invalidateUnpredictableNodes();
1115
- requestGraph.invalidateOnBuildNodes();
1116
- requestGraph.invalidateEnvNodes(options.env);
1117
- requestGraph.invalidateOptionNodes(options);
1118
- await requestGraph.respondToFSEvents(options.unstableFileInvalidations || events, options, 10000, true);
1191
+ if ((0, _featureFlags().getFeatureFlag)('verboseRequestInvalidationStats')) {
1192
+ const invalidationStats = await invalidateRequestGraph(requestGraph, options, events);
1193
+ _logger().default.verbose({
1194
+ origin: '@atlaspack/core',
1195
+ message: 'Request track loaded from cache',
1196
+ meta: {
1197
+ ...commonMeta,
1198
+ trackableEvent: 'request_tracker_cache_key_hit',
1199
+ invalidationStats
1200
+ }
1201
+ });
1202
+ } else {
1203
+ requestGraph.invalidateUnpredictableNodes();
1204
+ requestGraph.invalidateOnBuildNodes();
1205
+ requestGraph.invalidateEnvNodes(options.env);
1206
+ requestGraph.invalidateOptionNodes(options);
1207
+ }
1119
1208
  return requestGraph;
1120
1209
  } catch (e) {
1121
1210
  // Prevent logging fs events took too long warning
@@ -1130,12 +1219,76 @@ async function loadRequestGraph(options) {
1130
1219
  origin: '@atlaspack/core',
1131
1220
  message: 'Cache entry for request tracker was not found, initializing a clean cache.',
1132
1221
  meta: {
1133
- cacheKey,
1134
- snapshotKey
1222
+ ...commonMeta,
1223
+ trackableEvent: 'request_tracker_cache_key_miss'
1135
1224
  }
1136
1225
  });
1137
1226
  return new RequestGraph();
1138
1227
  }
1228
+
1229
+ /**
1230
+ * A wrapper around an invalidation type / method
1231
+ */
1232
+
1233
+ /**
1234
+ * Information about a certain cache invalidation type.
1235
+ */
1236
+
1237
+ /**
1238
+ * Respond to unpredictable, build, environment changes, option changes and file-system events
1239
+ * invalidating RequestGraph nodes.
1240
+ *
1241
+ * Returns the count of nodes invalidated by each invalidation type.
1242
+ */
1243
+ async function invalidateRequestGraph(requestGraph, options, events) {
1244
+ const invalidationFns = [{
1245
+ key: 'unpredictable',
1246
+ fn: () => requestGraph.invalidateUnpredictableNodes()
1247
+ }, {
1248
+ key: 'onBuild',
1249
+ fn: () => requestGraph.invalidateOnBuildNodes()
1250
+ }, {
1251
+ key: 'env',
1252
+ fn: () => requestGraph.invalidateEnvNodes(options.env)
1253
+ }, {
1254
+ key: 'option',
1255
+ fn: () => requestGraph.invalidateOptionNodes(options)
1256
+ }, {
1257
+ key: 'fsEvents',
1258
+ fn: async () => {
1259
+ await requestGraph.respondToFSEvents(options.unstableFileInvalidations || events, options, 10000, true);
1260
+ }
1261
+ }];
1262
+ const invalidations = [];
1263
+ for (const invalidation of invalidationFns) {
1264
+ invalidations.push(await runInvalidation(requestGraph, invalidation));
1265
+ }
1266
+ const invalidatedCount = invalidations.reduce((acc, invalidation) => acc + invalidation.count, 0);
1267
+ const requestCount = requestGraph.nodes.reduce((acc, node) => acc + ((node === null || node === void 0 ? void 0 : node.type) === REQUEST ? 1 : 0), 0);
1268
+ const nodeCount = requestGraph.nodes.length;
1269
+ return {
1270
+ invalidations,
1271
+ nodeCount,
1272
+ requestCount,
1273
+ invalidatedCount,
1274
+ nodeInvalidationRatio: invalidatedCount / nodeCount,
1275
+ requestInvalidationRatio: invalidatedCount / requestCount
1276
+ };
1277
+ }
1278
+
1279
+ /**
1280
+ * Runs an invalidation function and reports metrics.
1281
+ */
1282
+ async function runInvalidation(requestGraph, invalidationFn) {
1283
+ const startInvalidationCount = requestGraph.invalidNodeIds.size;
1284
+ const result = await invalidationFn.fn();
1285
+ const count = requestGraph.invalidNodeIds.size - startInvalidationCount;
1286
+ return {
1287
+ key: invalidationFn.key,
1288
+ count,
1289
+ changes: typeof result === 'object' && Array.isArray(result) ? result : null
1290
+ };
1291
+ }
1139
1292
  function logErrorOnBailout(options, snapshotPath, e) {
1140
1293
  if (e.message && e.message.includes('invalid clockspec')) {
1141
1294
  const snapshotContents = options.inputFS.readFileSync(snapshotPath, 'utf-8');
@@ -156,6 +156,14 @@ class AtlaspackWorker {
156
156
  }
157
157
  };
158
158
  }
159
+ if (result.isExcluded) {
160
+ return {
161
+ invalidations: [],
162
+ resolution: {
163
+ type: 'excluded'
164
+ }
165
+ };
166
+ }
159
167
  return {
160
168
  invalidations: [],
161
169
  resolution: {
@@ -32,6 +32,13 @@ var _Dependency = _interopRequireWildcard(require("./Dependency"));
32
32
  var _Target = require("./Target");
33
33
  var _utils = require("../utils");
34
34
  var _BundleGroup = _interopRequireWildcard(require("./BundleGroup"));
35
+ function _featureFlags() {
36
+ const data = require("@atlaspack/feature-flags");
37
+ _featureFlags = function () {
38
+ return data;
39
+ };
40
+ return data;
41
+ }
35
42
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
36
43
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
37
44
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -263,11 +270,20 @@ class BundleGraph {
263
270
  }
264
271
  for (let bundle of bundles) {
265
272
  const conditions = bundleConditions.get(bundle.id) ?? new Map();
266
- conditions.set(cond.key, {
267
- bundle,
268
- ifTrueBundles,
269
- ifFalseBundles
270
- });
273
+ const currentCondition = conditions.get(cond.key);
274
+ if ((0, _featureFlags().getFeatureFlag)('conditionalBundlingReporterSameConditionFix')) {
275
+ conditions.set(cond.key, {
276
+ bundle,
277
+ ifTrueBundles: [...((currentCondition === null || currentCondition === void 0 ? void 0 : currentCondition.ifTrueBundles) ?? []), ...ifTrueBundles],
278
+ ifFalseBundles: [...((currentCondition === null || currentCondition === void 0 ? void 0 : currentCondition.ifFalseBundles) ?? []), ...ifFalseBundles]
279
+ });
280
+ } else {
281
+ conditions.set(cond.key, {
282
+ bundle,
283
+ ifTrueBundles,
284
+ ifFalseBundles
285
+ });
286
+ }
271
287
  bundleConditions.set(bundle.id, conditions);
272
288
  }
273
289
  }
@@ -148,10 +148,7 @@ async function resolveOptions(initialOptions) {
148
148
  if (!needsRustLmdbCache && !(outputFS instanceof _fs().NodeFS)) {
149
149
  return new (_cache().FSCache)(outputFS, cacheDir);
150
150
  }
151
- if (needsRustLmdbCache || (0, _featureFlags().getFeatureFlag)('useLmdbJsLite')) {
152
- return new (_cache().LMDBLiteCache)(cacheDir);
153
- }
154
- return new (_cache().LMDBCache)(cacheDir);
151
+ return new (_cache().LMDBLiteCache)(cacheDir);
155
152
  }();
156
153
  let mode = initialOptions.mode ?? 'development';
157
154
  let shouldOptimize = (initialOptions === null || initialOptions === void 0 || (_initialOptions$defau = initialOptions.defaultTargetOptions) === null || _initialOptions$defau === void 0 ? void 0 : _initialOptions$defau.shouldOptimize) ?? mode === 'production';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaspack/core",
3
- "version": "2.14.1-dev.142+529a21a40",
3
+ "version": "2.14.1-dev.145+fa4d24840",
4
4
  "license": "(MIT OR Apache-2.0)",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -10,6 +10,7 @@
10
10
  "url": "https://github.com/atlassian-labs/atlaspack.git"
11
11
  },
12
12
  "main": "lib/index.js",
13
+ "types": "index.d.ts",
13
14
  "source": "src/index.js",
14
15
  "engines": {
15
16
  "node": ">= 16.0.0"
@@ -20,21 +21,21 @@
20
21
  "check-ts": "tsc --noEmit index.d.ts"
21
22
  },
22
23
  "dependencies": {
23
- "@atlaspack/build-cache": "2.13.3-dev.142+529a21a40",
24
- "@atlaspack/cache": "2.13.3-dev.142+529a21a40",
25
- "@atlaspack/diagnostic": "2.14.1-dev.142+529a21a40",
26
- "@atlaspack/events": "2.14.1-dev.142+529a21a40",
27
- "@atlaspack/feature-flags": "2.14.1-dev.142+529a21a40",
28
- "@atlaspack/fs": "2.14.1-dev.142+529a21a40",
29
- "@atlaspack/graph": "3.4.1-dev.142+529a21a40",
30
- "@atlaspack/logger": "2.14.1-dev.142+529a21a40",
31
- "@atlaspack/package-manager": "2.14.1-dev.142+529a21a40",
32
- "@atlaspack/plugin": "2.14.1-dev.142+529a21a40",
33
- "@atlaspack/profiler": "2.14.1-dev.142+529a21a40",
34
- "@atlaspack/rust": "3.0.1-dev.142+529a21a40",
35
- "@atlaspack/types": "2.14.1-dev.142+529a21a40",
36
- "@atlaspack/utils": "2.14.1-dev.142+529a21a40",
37
- "@atlaspack/workers": "2.14.1-dev.142+529a21a40",
24
+ "@atlaspack/build-cache": "2.13.3-dev.145+fa4d24840",
25
+ "@atlaspack/cache": "2.13.3-dev.145+fa4d24840",
26
+ "@atlaspack/diagnostic": "2.14.1-dev.145+fa4d24840",
27
+ "@atlaspack/events": "2.14.1-dev.145+fa4d24840",
28
+ "@atlaspack/feature-flags": "2.14.1-dev.145+fa4d24840",
29
+ "@atlaspack/fs": "2.14.1-dev.145+fa4d24840",
30
+ "@atlaspack/graph": "3.4.1-dev.145+fa4d24840",
31
+ "@atlaspack/logger": "2.14.1-dev.145+fa4d24840",
32
+ "@atlaspack/package-manager": "2.14.1-dev.145+fa4d24840",
33
+ "@atlaspack/plugin": "2.14.1-dev.145+fa4d24840",
34
+ "@atlaspack/profiler": "2.14.1-dev.145+fa4d24840",
35
+ "@atlaspack/rust": "3.0.1-dev.145+fa4d24840",
36
+ "@atlaspack/types": "2.14.1-dev.145+fa4d24840",
37
+ "@atlaspack/utils": "2.14.1-dev.145+fa4d24840",
38
+ "@atlaspack/workers": "2.14.1-dev.145+fa4d24840",
38
39
  "@mischnic/json-sourcemap": "^0.1.0",
39
40
  "@parcel/source-map": "^2.1.1",
40
41
  "base-x": "^3.0.8",
@@ -57,7 +58,10 @@
57
58
  },
58
59
  "exports": {
59
60
  "./*": "./*",
60
- ".": "./lib/index.js",
61
+ ".": {
62
+ "types": "./index.d.ts",
63
+ "default": "./lib/index.js"
64
+ },
61
65
  "./worker": {
62
66
  "@atlaspack::sources": "./src/worker.js",
63
67
  "default": "./lib/worker.js"
@@ -70,5 +74,5 @@
70
74
  "./src/serializerCore.js": "./src/serializerCore.browser.js"
71
75
  },
72
76
  "type": "commonjs",
73
- "gitHead": "529a21a40d655a8a92dbc8a4a91e0992d0e9e60e"
77
+ "gitHead": "fa4d24840815e7048a21d74caf01e2df633fabe3"
74
78
  }
package/src/Atlaspack.js CHANGED
@@ -58,11 +58,7 @@ import {
58
58
  fromProjectPathRelative,
59
59
  } from './projectPath';
60
60
  import {tracer} from '@atlaspack/profiler';
61
- import {
62
- getFeatureFlag,
63
- setFeatureFlags,
64
- DEFAULT_FEATURE_FLAGS,
65
- } from '@atlaspack/feature-flags';
61
+ import {setFeatureFlags, DEFAULT_FEATURE_FLAGS} from '@atlaspack/feature-flags';
66
62
  import {AtlaspackV3, FileSystemV3} from './atlaspack-v3';
67
63
  import createAssetGraphRequestJS from './requests/AssetGraphRequest';
68
64
  import {createAssetGraphRequestRust} from './requests/AssetGraphRequestRust';
@@ -125,9 +121,7 @@ export default class Atlaspack {
125
121
  };
126
122
  setFeatureFlags(featureFlags);
127
123
 
128
- if (getFeatureFlag('enableRustWorkerThreadDylibHack')) {
129
- loadRustWorkerThreadDylibHack();
130
- }
124
+ loadRustWorkerThreadDylibHack();
131
125
 
132
126
  await initSourcemaps;
133
127
  await initRust?.();
@@ -174,9 +168,16 @@ export default class Atlaspack {
174
168
  const version = require('../package.json').version;
175
169
  await lmdb.put('current_session_version', Buffer.from(version));
176
170
 
171
+ let threads = undefined;
172
+ if (process.env.ATLASPACK_NATIVE_THREADS !== undefined) {
173
+ threads = parseInt(process.env.ATLASPACK_NATIVE_THREADS, 10);
174
+ } else if (process.env.NODE_ENV === 'test') {
175
+ threads = 2;
176
+ }
177
+
177
178
  rustAtlaspack = await AtlaspackV3.create({
178
179
  ...options,
179
- threads: process.env.NODE_ENV === 'test' ? 2 : undefined,
180
+ threads,
180
181
  entries: Array.isArray(entries)
181
182
  ? entries
182
183
  : entries == null
@@ -647,6 +648,20 @@ export default class Atlaspack {
647
648
  return result;
648
649
  }
649
650
 
651
+ /**
652
+ * Copy the cache to a new directory and compact it.
653
+ */
654
+ async unstable_compactCache(): Promise<void> {
655
+ await this._init();
656
+
657
+ const cache = nullthrows(this.#resolvedOptions).cache;
658
+ if (cache instanceof LMDBLiteCache) {
659
+ await cache.compact('parcel-cache-compacted');
660
+ } else {
661
+ throw new Error('Cache is not an LMDBLiteCache');
662
+ }
663
+ }
664
+
650
665
  async unstable_transform(
651
666
  options: AtlaspackTransformOptions,
652
667
  ): Promise<Array<Asset>> {
@@ -4,7 +4,7 @@ import invariant, {AssertionError} from 'assert';
4
4
  import path from 'path';
5
5
 
6
6
  import {deserialize, serialize} from '@atlaspack/build-cache';
7
- import type {Cache} from '@atlaspack/cache';
7
+ import {LMDBLiteCache, type Cache} from '@atlaspack/cache';
8
8
  import {getFeatureFlag} from '@atlaspack/feature-flags';
9
9
  import {ContentGraph} from '@atlaspack/graph';
10
10
  import type {
@@ -14,7 +14,7 @@ import type {
14
14
  SerializedContentGraph,
15
15
  Graph,
16
16
  } from '@atlaspack/graph';
17
- import logger from '@atlaspack/logger';
17
+ import logger, {instrument} from '@atlaspack/logger';
18
18
  import {hashString} from '@atlaspack/rust';
19
19
  import type {Async, EnvMap} from '@atlaspack/types';
20
20
  import {
@@ -446,6 +446,11 @@ export class RequestGraph extends ContentGraph<
446
446
  this.removeCachedRequestChunkForNode(nodeId);
447
447
  }
448
448
 
449
+ /**
450
+ * Nodes that are invalidated on start-up, such as JavaScript babel configuration files which are
451
+ * imported when the build kicks-off and might doing arbitrary work such as reading from the file
452
+ * system.
453
+ */
449
454
  invalidateUnpredictableNodes() {
450
455
  for (let nodeId of this.unpredicatableNodeIds) {
451
456
  let node = nullthrows(this.getNode(nodeId));
@@ -454,6 +459,9 @@ export class RequestGraph extends ContentGraph<
454
459
  }
455
460
  }
456
461
 
462
+ /**
463
+ * Effectively uncacheable nodes.
464
+ */
457
465
  invalidateOnBuildNodes() {
458
466
  for (let nodeId of this.invalidateOnBuildNodeIds) {
459
467
  let node = nullthrows(this.getNode(nodeId));
@@ -462,11 +470,20 @@ export class RequestGraph extends ContentGraph<
462
470
  }
463
471
  }
464
472
 
465
- invalidateEnvNodes(env: EnvMap) {
473
+ /**
474
+ * Nodes invalidated by environment changes, corresponds to `env: ...` inputs.
475
+ */
476
+ invalidateEnvNodes(env: EnvMap): string[] {
477
+ const invalidatedKeys = [];
478
+
466
479
  for (let nodeId of this.envNodeIds) {
467
480
  let node = nullthrows(this.getNode(nodeId));
468
481
  invariant(node.type === ENV);
469
- if (env[keyFromEnvContentKey(node.id)] !== node.value) {
482
+
483
+ const key = keyFromEnvContentKey(node.id);
484
+ if (env[key] !== node.value) {
485
+ invalidatedKeys.push(key);
486
+
470
487
  let parentNodes = this.getNodeIdsConnectedTo(
471
488
  nodeId,
472
489
  requestGraphEdgeTypes.invalidated_by_update,
@@ -476,15 +493,23 @@ export class RequestGraph extends ContentGraph<
476
493
  }
477
494
  }
478
495
  }
496
+
497
+ return invalidatedKeys;
479
498
  }
480
499
 
481
- invalidateOptionNodes(options: AtlaspackOptions) {
500
+ /**
501
+ * Nodes invalidated by option changes.
502
+ */
503
+ invalidateOptionNodes(options: AtlaspackOptions): string[] {
504
+ const invalidatedKeys = [];
505
+
482
506
  for (let nodeId of this.optionNodeIds) {
483
507
  let node = nullthrows(this.getNode(nodeId));
484
508
  invariant(node.type === OPTION);
485
- if (
486
- hashFromOption(options[keyFromOptionContentKey(node.id)]) !== node.hash
487
- ) {
509
+ const key = keyFromOptionContentKey(node.id);
510
+
511
+ if (hashFromOption(options[key]) !== node.hash) {
512
+ invalidatedKeys.push(key);
488
513
  let parentNodes = this.getNodeIdsConnectedTo(
489
514
  nodeId,
490
515
  requestGraphEdgeTypes.invalidated_by_update,
@@ -494,6 +519,8 @@ export class RequestGraph extends ContentGraph<
494
519
  }
495
520
  }
496
521
  }
522
+
523
+ return invalidatedKeys;
497
524
  }
498
525
 
499
526
  invalidateOnConfigKeyChange(
@@ -1228,10 +1255,13 @@ export default class RequestTracker {
1228
1255
  return result;
1229
1256
  } else if (node.resultCacheKey != null && ifMatch == null) {
1230
1257
  let key = node.resultCacheKey;
1231
- invariant(this.options.cache.hasLargeBlob(key));
1232
- let cachedResult: T = deserialize(
1233
- await this.options.cache.getLargeBlob(key),
1234
- );
1258
+ if (!getFeatureFlag('cachePerformanceImprovements')) {
1259
+ invariant(this.options.cache.hasLargeBlob(key));
1260
+ }
1261
+
1262
+ let cachedResult: T = getFeatureFlag('cachePerformanceImprovements')
1263
+ ? nullthrows(await this.options.cache.get<T>(key))
1264
+ : deserialize(await this.options.cache.getLargeBlob(key));
1235
1265
  node.result = cachedResult;
1236
1266
  return cachedResult;
1237
1267
  }
@@ -1454,6 +1484,28 @@ export default class RequestTracker {
1454
1484
  }
1455
1485
 
1456
1486
  async writeToCache(signal?: AbortSignal) {
1487
+ const options = this.options;
1488
+ async function runCacheImprovements<T>(
1489
+ newPath: (cache: LMDBLiteCache) => Promise<T>,
1490
+ oldPath: () => Promise<T>,
1491
+ ): Promise<T> {
1492
+ if (getFeatureFlag('cachePerformanceImprovements')) {
1493
+ invariant(options.cache instanceof LMDBLiteCache);
1494
+ const result = await newPath(options.cache);
1495
+ return result;
1496
+ } else {
1497
+ const result = await oldPath();
1498
+ return result;
1499
+ }
1500
+ }
1501
+
1502
+ await runCacheImprovements(
1503
+ async (cache) => {
1504
+ await cache.getNativeRef().startWriteTransaction();
1505
+ },
1506
+ () => Promise.resolve(),
1507
+ );
1508
+
1457
1509
  let cacheKey = getCacheKey(this.options);
1458
1510
  let requestGraphKey = `requestGraph-${cacheKey}`;
1459
1511
  let snapshotKey = `snapshot-${cacheKey}`;
@@ -1484,14 +1536,24 @@ export default class RequestTracker {
1484
1536
  throw new Error('Serialization was aborted');
1485
1537
  }
1486
1538
 
1487
- await this.options.cache.setLargeBlob(
1488
- key,
1489
- serialize(contents),
1490
- signal
1491
- ? {
1492
- signal: signal,
1493
- }
1494
- : undefined,
1539
+ await runCacheImprovements(
1540
+ (cache) => {
1541
+ instrument(`cache.put(${key})`, () => {
1542
+ cache.getNativeRef().putNoConfirm(key, serialize(contents));
1543
+ });
1544
+ return Promise.resolve();
1545
+ },
1546
+ async () => {
1547
+ await this.options.cache.setLargeBlob(
1548
+ key,
1549
+ serialize(contents),
1550
+ signal
1551
+ ? {
1552
+ signal: signal,
1553
+ }
1554
+ : undefined,
1555
+ );
1556
+ },
1495
1557
  );
1496
1558
 
1497
1559
  total += 1;
@@ -1570,6 +1632,18 @@ export default class RequestTracker {
1570
1632
  nodes: undefined,
1571
1633
  });
1572
1634
 
1635
+ await runCacheImprovements(
1636
+ () =>
1637
+ serialiseAndSet(`request_tracker:cache_metadata:${cacheKey}`, {
1638
+ version: ATLASPACK_VERSION,
1639
+ entries: this.options.entries,
1640
+ mode: this.options.mode,
1641
+ shouldBuildLazily: this.options.shouldBuildLazily,
1642
+ watchBackend: this.options.watchBackend,
1643
+ }),
1644
+ () => Promise.resolve(),
1645
+ );
1646
+
1573
1647
  let opts = getWatcherOptions(this.options);
1574
1648
  let snapshotPath = path.join(this.options.cacheDir, snapshotKey + '.txt');
1575
1649
 
@@ -1583,6 +1657,13 @@ export default class RequestTracker {
1583
1657
  if (!signal?.aborted) throw err;
1584
1658
  }
1585
1659
 
1660
+ await runCacheImprovements(
1661
+ async (cache) => {
1662
+ await cache.getNativeRef().commitWriteTransaction();
1663
+ },
1664
+ () => Promise.resolve(),
1665
+ );
1666
+
1586
1667
  report({type: 'cache', phase: 'end', total, size: this.graph.nodes.length});
1587
1668
  }
1588
1669
 
@@ -1631,6 +1712,7 @@ export async function readAndDeserializeRequestGraph(
1631
1712
  cacheKey: string,
1632
1713
  ): Async<{|requestGraph: RequestGraph, bufferLength: number|}> {
1633
1714
  let bufferLength = 0;
1715
+
1634
1716
  const getAndDeserialize = async (key: string) => {
1635
1717
  let buffer = await cache.getLargeBlob(key);
1636
1718
  bufferLength += Buffer.byteLength(buffer);
@@ -1672,14 +1754,26 @@ async function loadRequestGraph(options): Async<RequestGraph> {
1672
1754
  const snapshotKey = `snapshot-${cacheKey}`;
1673
1755
  const snapshotPath = path.join(options.cacheDir, snapshotKey + '.txt');
1674
1756
 
1757
+ const commonMeta = {
1758
+ cacheKey,
1759
+ snapshotKey,
1760
+ cacheKeyOptions: {
1761
+ version: ATLASPACK_VERSION,
1762
+ entries: options.entries,
1763
+ mode: options.mode,
1764
+ shouldBuildLazily: options.shouldBuildLazily,
1765
+ watchBackend: options.watchBackend,
1766
+ },
1767
+ };
1768
+
1675
1769
  logger.verbose({
1676
1770
  origin: '@atlaspack/core',
1677
1771
  message: 'Loading request graph',
1678
1772
  meta: {
1679
- cacheKey,
1680
- snapshotKey,
1773
+ ...commonMeta,
1681
1774
  },
1682
1775
  });
1776
+
1683
1777
  if (await options.cache.hasLargeBlob(requestGraphKey)) {
1684
1778
  try {
1685
1779
  let {requestGraph} = await readAndDeserializeRequestGraph(
@@ -1711,23 +1805,36 @@ async function loadRequestGraph(options): Async<RequestGraph> {
1711
1805
  origin: '@atlaspack/core',
1712
1806
  message: `File system event count: ${events.length}`,
1713
1807
  meta: {
1808
+ ...commonMeta,
1714
1809
  trackableEvent: 'watcher_events_count',
1715
1810
  watcherEventCount: events.length,
1716
1811
  duration: Date.now() - startTime,
1717
1812
  },
1718
1813
  });
1719
1814
 
1720
- requestGraph.invalidateUnpredictableNodes();
1721
- requestGraph.invalidateOnBuildNodes();
1722
- requestGraph.invalidateEnvNodes(options.env);
1723
- requestGraph.invalidateOptionNodes(options);
1815
+ if (getFeatureFlag('verboseRequestInvalidationStats')) {
1816
+ const invalidationStats = await invalidateRequestGraph(
1817
+ requestGraph,
1818
+ options,
1819
+ events,
1820
+ );
1821
+
1822
+ logger.verbose({
1823
+ origin: '@atlaspack/core',
1824
+ message: 'Request track loaded from cache',
1825
+ meta: {
1826
+ ...commonMeta,
1827
+ trackableEvent: 'request_tracker_cache_key_hit',
1828
+ invalidationStats,
1829
+ },
1830
+ });
1831
+ } else {
1832
+ requestGraph.invalidateUnpredictableNodes();
1833
+ requestGraph.invalidateOnBuildNodes();
1834
+ requestGraph.invalidateEnvNodes(options.env);
1835
+ requestGraph.invalidateOptionNodes(options);
1836
+ }
1724
1837
 
1725
- await requestGraph.respondToFSEvents(
1726
- options.unstableFileInvalidations || events,
1727
- options,
1728
- 10000,
1729
- true,
1730
- );
1731
1838
  return requestGraph;
1732
1839
  } catch (e) {
1733
1840
  // Prevent logging fs events took too long warning
@@ -1744,13 +1851,158 @@ async function loadRequestGraph(options): Async<RequestGraph> {
1744
1851
  message:
1745
1852
  'Cache entry for request tracker was not found, initializing a clean cache.',
1746
1853
  meta: {
1747
- cacheKey,
1748
- snapshotKey,
1854
+ ...commonMeta,
1855
+ trackableEvent: 'request_tracker_cache_key_miss',
1749
1856
  },
1750
1857
  });
1751
1858
  return new RequestGraph();
1752
1859
  }
1753
1860
 
1861
+ /**
1862
+ * A wrapper around an invalidation type / method
1863
+ */
1864
+ type InvalidationFn = {|
1865
+ key: string,
1866
+ fn: () => string[] | void | Promise<void>,
1867
+ |};
1868
+
1869
+ type InvalidationStats = {|
1870
+ /**
1871
+ * Total number of request graph nodes
1872
+ */
1873
+ nodeCount: number,
1874
+ /**
1875
+ * Number of requests in RequestGraph
1876
+ */
1877
+ requestCount: number,
1878
+ /**
1879
+ * Number of nodes that have been invalidated.
1880
+ */
1881
+ invalidatedCount: number,
1882
+ /**
1883
+ * Percentage of requests that have been invalidated
1884
+ */
1885
+ requestInvalidationRatio: number,
1886
+ /**
1887
+ * Percentage of nodes that have been invalidated
1888
+ */
1889
+ nodeInvalidationRatio: number,
1890
+ /**
1891
+ * Details for each invalidation type
1892
+ */
1893
+ invalidations: InvalidationFnStats[],
1894
+ |};
1895
+
1896
+ /**
1897
+ * Information about a certain cache invalidation type.
1898
+ */
1899
+ type InvalidationFnStats = {|
1900
+ /**
1901
+ * Invalidation type, one of:
1902
+ *
1903
+ * - unpredictable
1904
+ * - onBuild
1905
+ * - env
1906
+ * - option
1907
+ * - fsEvents
1908
+ */
1909
+ key: string,
1910
+ /**
1911
+ * Number of invalidated nodes coming from this invalidation type.
1912
+ */
1913
+ count: number,
1914
+ /**
1915
+ * If this is a env or option invalidation, this key will contain the list of changed values.
1916
+ */
1917
+ changes: null | string[],
1918
+ |};
1919
+
1920
+ /**
1921
+ * Respond to unpredictable, build, environment changes, option changes and file-system events
1922
+ * invalidating RequestGraph nodes.
1923
+ *
1924
+ * Returns the count of nodes invalidated by each invalidation type.
1925
+ */
1926
+ async function invalidateRequestGraph(
1927
+ requestGraph: RequestGraph,
1928
+ options: AtlaspackOptions,
1929
+ events: Event[],
1930
+ ): Promise<InvalidationStats> {
1931
+ const invalidationFns: InvalidationFn[] = [
1932
+ {
1933
+ key: 'unpredictable',
1934
+ fn: () => requestGraph.invalidateUnpredictableNodes(),
1935
+ },
1936
+ {
1937
+ key: 'onBuild',
1938
+ fn: () => requestGraph.invalidateOnBuildNodes(),
1939
+ },
1940
+ {
1941
+ key: 'env',
1942
+ fn: () => requestGraph.invalidateEnvNodes(options.env),
1943
+ },
1944
+ {
1945
+ key: 'option',
1946
+ fn: () => requestGraph.invalidateOptionNodes(options),
1947
+ },
1948
+ {
1949
+ key: 'fsEvents',
1950
+ fn: async () => {
1951
+ await requestGraph.respondToFSEvents(
1952
+ options.unstableFileInvalidations || events,
1953
+ options,
1954
+ 10000,
1955
+ true,
1956
+ );
1957
+ },
1958
+ },
1959
+ ];
1960
+
1961
+ const invalidations = [];
1962
+ for (const invalidation of invalidationFns) {
1963
+ invalidations.push(await runInvalidation(requestGraph, invalidation));
1964
+ }
1965
+ const invalidatedCount = invalidations.reduce(
1966
+ (acc, invalidation) => acc + invalidation.count,
1967
+ 0,
1968
+ );
1969
+ const requestCount = requestGraph.nodes.reduce(
1970
+ (acc, node) => acc + (node?.type === REQUEST ? 1 : 0),
1971
+ 0,
1972
+ );
1973
+ const nodeCount = requestGraph.nodes.length;
1974
+ const nodeInvalidationRatio = invalidatedCount / nodeCount;
1975
+ const requestInvalidationRatio = invalidatedCount / requestCount;
1976
+
1977
+ return {
1978
+ invalidations,
1979
+ nodeCount,
1980
+ requestCount,
1981
+ invalidatedCount,
1982
+ nodeInvalidationRatio,
1983
+ requestInvalidationRatio,
1984
+ };
1985
+ }
1986
+
1987
+ /**
1988
+ * Runs an invalidation function and reports metrics.
1989
+ */
1990
+ async function runInvalidation(
1991
+ requestGraph: RequestGraph,
1992
+ invalidationFn: InvalidationFn,
1993
+ ): Promise<InvalidationFnStats> {
1994
+ const startInvalidationCount = requestGraph.invalidNodeIds.size;
1995
+ const result = await invalidationFn.fn();
1996
+ const count = requestGraph.invalidNodeIds.size - startInvalidationCount;
1997
+
1998
+ return {
1999
+ key: invalidationFn.key,
2000
+ count,
2001
+ changes:
2002
+ typeof result === 'object' && Array.isArray(result) ? result : null,
2003
+ };
2004
+ }
2005
+
1754
2006
  function logErrorOnBailout(
1755
2007
  options: AtlaspackOptions,
1756
2008
  snapshotPath: string,
@@ -148,6 +148,13 @@ export class AtlaspackWorker {
148
148
  };
149
149
  }
150
150
 
151
+ if (result.isExcluded) {
152
+ return {
153
+ invalidations: [],
154
+ resolution: {type: 'excluded'},
155
+ };
156
+ }
157
+
151
158
  return {
152
159
  invalidations: [],
153
160
  resolution: {
@@ -31,6 +31,7 @@ import Dependency, {
31
31
  import {targetToInternalTarget} from './Target';
32
32
  import {fromInternalSourceLocation} from '../utils';
33
33
  import BundleGroup, {bundleGroupToInternalBundleGroup} from './BundleGroup';
34
+ import {getFeatureFlag} from '@atlaspack/feature-flags';
34
35
 
35
36
  // Friendly access for other modules within this package that need access
36
37
  // to the internal bundle.
@@ -489,11 +490,27 @@ export default class BundleGraph<TBundle: IBundle>
489
490
  for (let bundle of bundles) {
490
491
  const conditions = bundleConditions.get(bundle.id) ?? new Map();
491
492
 
492
- conditions.set(cond.key, {
493
- bundle,
494
- ifTrueBundles,
495
- ifFalseBundles,
496
- });
493
+ const currentCondition = conditions.get(cond.key);
494
+
495
+ if (getFeatureFlag('conditionalBundlingReporterSameConditionFix')) {
496
+ conditions.set(cond.key, {
497
+ bundle,
498
+ ifTrueBundles: [
499
+ ...(currentCondition?.ifTrueBundles ?? []),
500
+ ...ifTrueBundles,
501
+ ],
502
+ ifFalseBundles: [
503
+ ...(currentCondition?.ifFalseBundles ?? []),
504
+ ...ifFalseBundles,
505
+ ],
506
+ });
507
+ } else {
508
+ conditions.set(cond.key, {
509
+ bundle,
510
+ ifTrueBundles,
511
+ ifFalseBundles,
512
+ });
513
+ }
497
514
 
498
515
  bundleConditions.set(bundle.id, conditions);
499
516
  }
@@ -12,7 +12,7 @@ import type {AtlaspackOptions} from './types';
12
12
  import path from 'path';
13
13
  import {hashString} from '@atlaspack/rust';
14
14
  import {NodeFS, NodeVCSAwareFS} from '@atlaspack/fs';
15
- import {LMDBCache, LMDBLiteCache, FSCache} from '@atlaspack/cache';
15
+ import {LMDBLiteCache, FSCache} from '@atlaspack/cache';
16
16
  import {getFeatureFlag, getFeatureFlagValue} from '@atlaspack/feature-flags';
17
17
  import {NodePackageManager} from '@atlaspack/package-manager';
18
18
  import {
@@ -158,11 +158,7 @@ export default async function resolveOptions(
158
158
  return new FSCache(outputFS, cacheDir);
159
159
  }
160
160
 
161
- if (needsRustLmdbCache || getFeatureFlag('useLmdbJsLite')) {
162
- return new LMDBLiteCache(cacheDir);
163
- }
164
-
165
- return new LMDBCache(cacheDir);
161
+ return new LMDBLiteCache(cacheDir);
166
162
  }
167
163
 
168
164
  let cache = createCache();