@atlaspack/core 2.17.3 → 2.17.4

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,31 @@
1
1
  # @atlaspack/core
2
2
 
3
+ ## 2.17.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#588](https://github.com/atlassian-labs/atlaspack/pull/588) [`1940859`](https://github.com/atlassian-labs/atlaspack/commit/194085942f0e86532e9d039fc3f8039badce4594) Thanks [@yamadapc](https://github.com/yamadapc)! - Do not invalidate all javascript files when tsconfig files change
8
+
9
+ - [#592](https://github.com/atlassian-labs/atlaspack/pull/592) [`15b6155`](https://github.com/atlassian-labs/atlaspack/commit/15b61556e9114203ebbc9de94b864118ca764598) Thanks [@yamadapc](https://github.com/yamadapc)! - Report large file invalidations
10
+
11
+ - [#503](https://github.com/atlassian-labs/atlaspack/pull/503) [`209692f`](https://github.com/atlassian-labs/atlaspack/commit/209692ffb11eae103a0d65c5e1118a5aa1625818) Thanks [@JakeLane](https://github.com/JakeLane)! - Fix conditional bundling reporter when condition is reused
12
+
13
+ - [#562](https://github.com/atlassian-labs/atlaspack/pull/562) [`d04de26`](https://github.com/atlassian-labs/atlaspack/commit/d04de26af684d7abfba5091fbe3df16a12cd0ebc) Thanks [@yamadapc](https://github.com/yamadapc)! - Update with feature-flagged change to write packages into files rather than LMDB
14
+
15
+ - Updated dependencies [[`124b7ff`](https://github.com/atlassian-labs/atlaspack/commit/124b7fff44f71aac9fbad289a9a9509b3dfc9aaa), [`e052521`](https://github.com/atlassian-labs/atlaspack/commit/e0525210850ed1606146eb86991049cf567c5dec), [`15c6d70`](https://github.com/atlassian-labs/atlaspack/commit/15c6d7000bd89da876bc590aa75b17a619a41896), [`e4d966c`](https://github.com/atlassian-labs/atlaspack/commit/e4d966c3c9c4292c5013372ae65b10d19d4bacc6), [`209692f`](https://github.com/atlassian-labs/atlaspack/commit/209692ffb11eae103a0d65c5e1118a5aa1625818), [`42a775d`](https://github.com/atlassian-labs/atlaspack/commit/42a775de8eec638ad188f3271964170d8c04d84b), [`29c2f10`](https://github.com/atlassian-labs/atlaspack/commit/29c2f106de9679adfb5afa04e1910471dc65a427), [`f4da1e1`](https://github.com/atlassian-labs/atlaspack/commit/f4da1e120e73eeb5e8b8927f05e88f04d6148c7b), [`1ef91fc`](https://github.com/atlassian-labs/atlaspack/commit/1ef91fcc863fdd2831511937083dbbc1263b3d9d)]:
16
+ - @atlaspack/cache@3.2.4
17
+ - @atlaspack/rust@3.3.4
18
+ - @atlaspack/fs@2.15.4
19
+ - @atlaspack/feature-flags@2.16.0
20
+ - @atlaspack/logger@2.14.9
21
+ - @atlaspack/utils@2.14.9
22
+ - @atlaspack/package-manager@2.14.9
23
+ - @atlaspack/graph@3.4.7
24
+ - @atlaspack/workers@2.14.9
25
+ - @atlaspack/profiler@2.14.7
26
+ - @atlaspack/types@2.14.9
27
+ - @atlaspack/plugin@2.14.9
28
+
3
29
  ## 2.17.3
4
30
 
5
31
  ### Patch Changes
package/lib/Atlaspack.js CHANGED
@@ -510,7 +510,9 @@ class Atlaspack {
510
510
  if (this.rustAtlaspack) {
511
511
  nativeInvalid = await this.rustAtlaspack.respondToFsEvents(events);
512
512
  }
513
- let isInvalid = await this.#requestTracker.respondToFSEvents(events, Number.POSITIVE_INFINITY);
513
+ let {
514
+ didInvalidate: isInvalid
515
+ } = await this.#requestTracker.respondToFSEvents(events, Number.POSITIVE_INFINITY);
514
516
  if ((nativeInvalid || isInvalid) && this.#watchQueue.getNumWaiting() === 0) {
515
517
  if (this.#watchAbortController) {
516
518
  this.#watchAbortController.abort();
@@ -92,6 +92,13 @@ function _profiler() {
92
92
  };
93
93
  return data;
94
94
  }
95
+ function _featureFlags() {
96
+ const data = require("@atlaspack/feature-flags");
97
+ _featureFlags = function () {
98
+ return data;
99
+ };
100
+ return data;
101
+ }
95
102
  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); }
96
103
  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; }
97
104
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -434,6 +441,10 @@ class PackagerRunner {
434
441
  devDepHashes += await this.getDevDepHashes(inlineBundle);
435
442
  }
436
443
  let invalidationHash = await (0, _assetUtils.getInvalidationHash)(invalidations, this.options);
444
+ if ((0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
445
+ const hash = (0, _rust().hashString)(_constants.ATLASPACK_VERSION + devDepHashes + invalidationHash + bundle.target.publicUrl + bundleGraph.getHash(bundle) + JSON.stringify(configResults) + JSON.stringify(globalInfoResults) + this.options.mode + (this.options.shouldBuildLazily ? 'lazy' : 'eager'));
446
+ return _path().default.join(bundle.displayName ?? bundle.name ?? bundle.id, hash);
447
+ }
437
448
  return (0, _rust().hashString)(_constants.ATLASPACK_VERSION + devDepHashes + invalidationHash + bundle.target.publicUrl + bundleGraph.getHash(bundle) + JSON.stringify(configResults) + JSON.stringify(globalInfoResults) + this.options.mode + (this.options.shouldBuildLazily ? 'lazy' : 'eager'));
438
449
  }
439
450
  async getDevDepHashes(bundle) {
@@ -457,25 +468,27 @@ class PackagerRunner {
457
468
  let contentKey = PackagerRunner.getContentKey(cacheKey);
458
469
  let mapKey = PackagerRunner.getMapKey(cacheKey);
459
470
  let isLargeBlob = await this.options.cache.hasLargeBlob(contentKey);
460
- let contentExists = isLargeBlob || (await this.options.cache.has(contentKey));
471
+ let contentExists = (0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements') ? isLargeBlob : isLargeBlob || (await this.options.cache.has(contentKey));
461
472
  if (!contentExists) {
462
473
  return null;
463
474
  }
464
- let mapExists = await this.options.cache.has(mapKey);
475
+ let mapExists = (0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements') ? await this.options.cache.hasLargeBlob(mapKey) : await this.options.cache.has(mapKey);
465
476
  return {
466
477
  contents: isLargeBlob ? this.options.cache.getStream(contentKey) : (0, _utils().blobToStream)(await this.options.cache.getBlob(contentKey)),
467
- map: mapExists ? (0, _utils().blobToStream)(await this.options.cache.getBlob(mapKey)) : null
478
+ map: mapExists ? (0, _utils().blobToStream)((0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements') ? await this.options.cache.getLargeBlob(mapKey) : await this.options.cache.getBlob(mapKey)) : null
468
479
  };
469
480
  }
470
481
  async writeToCache(cacheKeys, type, contents, map) {
471
482
  let size = 0;
472
483
  let hash;
473
484
  let hashReferences = [];
474
- let isLargeBlob = false;
485
+ let isLargeBlob = (0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements');
475
486
 
476
487
  // TODO: don't replace hash references in binary files??
477
488
  if (contents instanceof _stream().Readable) {
478
- isLargeBlob = true;
489
+ if (!(0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
490
+ isLargeBlob = true;
491
+ }
479
492
  let boundaryStr = '';
480
493
  let h = new (_rust().Hash)();
481
494
  await this.options.cache.setStream(cacheKeys.content, (0, _utils().blobToStream)(contents).pipe(new (_utils().TapStream)(buf => {
@@ -491,15 +504,27 @@ class PackagerRunner {
491
504
  size = buffer.byteLength;
492
505
  hash = (0, _rust().hashBuffer)(buffer);
493
506
  hashReferences = contents.match(_constants.HASH_REF_REGEX) ?? [];
494
- await this.options.cache.setBlob(cacheKeys.content, buffer);
507
+ if ((0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
508
+ await this.options.cache.setLargeBlob(cacheKeys.content, buffer);
509
+ } else {
510
+ await this.options.cache.setBlob(cacheKeys.content, buffer);
511
+ }
495
512
  } else {
496
513
  size = contents.length;
497
514
  hash = (0, _rust().hashBuffer)(contents);
498
515
  hashReferences = contents.toString().match(_constants.HASH_REF_REGEX) ?? [];
499
- await this.options.cache.setBlob(cacheKeys.content, contents);
516
+ if ((0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
517
+ await this.options.cache.setLargeBlob(cacheKeys.content, contents);
518
+ } else {
519
+ await this.options.cache.setBlob(cacheKeys.content, contents);
520
+ }
500
521
  }
501
522
  if (map != null) {
502
- await this.options.cache.setBlob(cacheKeys.map, map);
523
+ if ((0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
524
+ await this.options.cache.setLargeBlob(cacheKeys.map, map);
525
+ } else {
526
+ await this.options.cache.setBlob(cacheKeys.map, map);
527
+ }
503
528
  }
504
529
  let info = {
505
530
  type,
@@ -513,12 +538,21 @@ class PackagerRunner {
513
538
  return info;
514
539
  }
515
540
  static getContentKey(cacheKey) {
541
+ if ((0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
542
+ return `PackagerRunner/${_constants.ATLASPACK_VERSION}/${cacheKey}/content`;
543
+ }
516
544
  return (0, _rust().hashString)(`${cacheKey}:content`);
517
545
  }
518
546
  static getMapKey(cacheKey) {
547
+ if ((0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
548
+ return `PackagerRunner/${_constants.ATLASPACK_VERSION}/${cacheKey}/map`;
549
+ }
519
550
  return (0, _rust().hashString)(`${cacheKey}:map`);
520
551
  }
521
552
  static getInfoKey(cacheKey) {
553
+ if ((0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
554
+ return `PackagerRunner/${_constants.ATLASPACK_VERSION}/${cacheKey}/info`;
555
+ }
522
556
  return (0, _rust().hashString)(`${cacheKey}:info`);
523
557
  }
524
558
  }
@@ -6,9 +6,13 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.RequestGraph = void 0;
7
7
  exports.cleanUpOrphans = cleanUpOrphans;
8
8
  exports.default = void 0;
9
+ exports.getBiggestFSEventsInvalidations = getBiggestFSEventsInvalidations;
9
10
  exports.getWatcherOptions = getWatcherOptions;
11
+ exports.invalidateRequestGraph = invalidateRequestGraph;
12
+ exports.invalidateRequestGraphFSEvents = invalidateRequestGraphFSEvents;
10
13
  exports.readAndDeserializeRequestGraph = readAndDeserializeRequestGraph;
11
14
  exports.requestTypes = exports.requestGraphEdgeTypes = void 0;
15
+ exports.runInvalidation = runInvalidation;
12
16
  function _assert() {
13
17
  const data = _interopRequireWildcard(require("assert"));
14
18
  _assert = function () {
@@ -84,6 +88,13 @@ var _projectPath = require("./projectPath");
84
88
  var _ReporterRunner = require("./ReporterRunner");
85
89
  var _ConfigRequest = require("./requests/ConfigRequest");
86
90
  var _utils2 = require("./utils");
91
+ function _perf_hooks() {
92
+ const data = require("perf_hooks");
93
+ _perf_hooks = function () {
94
+ return data;
95
+ };
96
+ return data;
97
+ }
87
98
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
88
99
  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); }
89
100
  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; }
@@ -582,10 +593,12 @@ class RequestGraph extends _graph().ContentGraph {
582
593
  aboveCache.set(fileNameNodeId, above);
583
594
  return above;
584
595
  };
596
+ const invalidationsByPath = new Map();
585
597
  for (let {
586
598
  path: _path,
587
599
  type
588
600
  } of events) {
601
+ const invalidationsBefore = this.getInvalidNodeCount();
589
602
  if (!enableOptimization && process.env.ATLASPACK_DISABLE_CACHE_TIMEOUT !== 'true' && ++count === 256) {
590
603
  let duration = Date.now() - startTime;
591
604
  predictedTime = duration * (events.length >> 8);
@@ -622,7 +635,10 @@ class RequestGraph extends _graph().ContentGraph {
622
635
  this.invalidNodeIds.add(id);
623
636
  }
624
637
  }
625
- return true;
638
+ return {
639
+ didInvalidate: true,
640
+ invalidationsByPath: new Map()
641
+ };
626
642
  }
627
643
 
628
644
  // sometimes mac os reports update events as create events.
@@ -697,6 +713,8 @@ class RequestGraph extends _graph().ContentGraph {
697
713
  }
698
714
  }
699
715
  }
716
+ const invalidationsAfter = this.getInvalidNodeCount();
717
+ invalidationsByPath.set(_path, (invalidationsByPath.get(_path) ?? 0) + (invalidationsAfter - invalidationsBefore));
700
718
  }
701
719
  if ((0, _featureFlags().getFeatureFlag)('fixQuadraticCacheInvalidation')) {
702
720
  cleanUpOrphans(this);
@@ -714,7 +732,10 @@ class RequestGraph extends _graph().ContentGraph {
714
732
  numberOfInvalidatedNodes: invalidatedNodes.size
715
733
  }
716
734
  });
717
- return didInvalidate && this.invalidNodeIds.size > 0;
735
+ return {
736
+ didInvalidate,
737
+ invalidationsByPath
738
+ };
718
739
  }
719
740
  hasCachedRequestChunk(index) {
720
741
  return this.cachedRequestChunks.has(index);
@@ -725,6 +746,13 @@ class RequestGraph extends _graph().ContentGraph {
725
746
  removeCachedRequestChunkForNode(nodeId) {
726
747
  this.cachedRequestChunks.delete(Math.floor(nodeId / this.nodesPerBlob));
727
748
  }
749
+
750
+ /**
751
+ * Returns the number of invalidated nodes in the graph.
752
+ */
753
+ getInvalidNodeCount() {
754
+ return this.invalidNodeIds.size;
755
+ }
728
756
  }
729
757
  exports.RequestGraph = RequestGraph;
730
758
  class RequestTracker {
@@ -970,84 +998,85 @@ class RequestTracker {
970
998
  return result;
971
999
  }
972
1000
  }
973
- await runCacheImprovements(async cache => {
974
- await cache.getNativeRef().startWriteTransaction();
975
- }, () => Promise.resolve());
976
1001
  let cacheKey = getCacheKey(this.options);
977
- let requestGraphKey = `requestGraph-${cacheKey}`;
1002
+ let requestGraphKey = (0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements') ? `${cacheKey}/RequestGraph` : `requestGraph-${cacheKey}`;
1003
+ let snapshotKey = (0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements') ? `${cacheKey}/snapshot` : `snapshot-${cacheKey}`;
978
1004
  if (this.options.shouldDisableCache) {
979
1005
  return;
980
1006
  }
981
1007
  let total = 0;
982
- (0, _ReporterRunner.report)({
983
- type: 'cache',
984
- phase: 'start',
985
- total,
986
- size: this.graph.nodes.length
987
- });
988
- let serialisedGraph = this.graph.serialize();
989
-
990
- // Delete an existing request graph cache, to prevent invalid states
991
- await this.options.cache.deleteLargeBlob(requestGraphKey);
992
- const serialiseAndSet = async (key, contents) => {
993
- if (signal !== null && signal !== void 0 && signal.aborted) {
994
- throw new Error('Serialization was aborted');
995
- }
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
- });
1006
- total += 1;
1008
+ await runCacheImprovements(async cache => {
1009
+ await cache.getNativeRef().startWriteTransaction();
1010
+ }, () => Promise.resolve());
1011
+ try {
1007
1012
  (0, _ReporterRunner.report)({
1008
1013
  type: 'cache',
1009
- phase: 'write',
1014
+ phase: 'start',
1010
1015
  total,
1011
1016
  size: this.graph.nodes.length
1012
1017
  });
1013
- };
1014
- let queue = new (_utils().PromiseQueue)({
1015
- maxConcurrent: 32
1016
- });
1018
+ let serialisedGraph = this.graph.serialize();
1019
+
1020
+ // Delete an existing request graph cache, to prevent invalid states
1021
+ await this.options.cache.deleteLargeBlob(requestGraphKey);
1022
+ const serialiseAndSet = async (key, contents) => {
1023
+ if (signal !== null && signal !== void 0 && signal.aborted) {
1024
+ throw new Error('Serialization was aborted');
1025
+ }
1026
+ await runCacheImprovements(cache => {
1027
+ (0, _logger().instrument)(`RequestTracker::writeToCache::cache.put(${key})`, () => {
1028
+ cache.getNativeRef().putNoConfirm(key, (0, _buildCache().serialize)(contents));
1029
+ });
1030
+ return Promise.resolve();
1031
+ }, async () => {
1032
+ await this.options.cache.setLargeBlob(key, (0, _buildCache().serialize)(contents), signal ? {
1033
+ signal: signal
1034
+ } : undefined);
1035
+ });
1036
+ total += 1;
1037
+ (0, _ReporterRunner.report)({
1038
+ type: 'cache',
1039
+ phase: 'write',
1040
+ total,
1041
+ size: this.graph.nodes.length
1042
+ });
1043
+ };
1044
+ let queue = new (_utils().PromiseQueue)({
1045
+ maxConcurrent: 32
1046
+ });
1017
1047
 
1018
- // Preallocating a sparse array is faster than pushing when N is high enough
1019
- let cacheableNodes = new Array(serialisedGraph.nodes.length);
1020
- for (let i = 0; i < serialisedGraph.nodes.length; i += 1) {
1021
- let node = serialisedGraph.nodes[i];
1022
- let resultCacheKey = node === null || node === void 0 ? void 0 : node.resultCacheKey;
1023
- if ((node === null || node === void 0 ? void 0 : node.type) === REQUEST && resultCacheKey != null && (node === null || node === void 0 ? void 0 : node.result) != null) {
1024
- queue.add(() => serialiseAndSet(resultCacheKey, node.result));
1048
+ // Preallocating a sparse array is faster than pushing when N is high enough
1049
+ let cacheableNodes = new Array(serialisedGraph.nodes.length);
1050
+ for (let i = 0; i < serialisedGraph.nodes.length; i += 1) {
1051
+ let node = serialisedGraph.nodes[i];
1052
+ let resultCacheKey = node === null || node === void 0 ? void 0 : node.resultCacheKey;
1053
+ if ((node === null || node === void 0 ? void 0 : node.type) === REQUEST && resultCacheKey != null && (node === null || node === void 0 ? void 0 : node.result) != null) {
1054
+ queue.add(() => serialiseAndSet(resultCacheKey, node.result));
1025
1055
 
1026
- // eslint-disable-next-line no-unused-vars
1027
- let {
1028
- result: _,
1029
- ...newNode
1030
- } = node;
1031
- cacheableNodes[i] = newNode;
1032
- } else {
1033
- cacheableNodes[i] = node;
1056
+ // eslint-disable-next-line no-unused-vars
1057
+ let {
1058
+ result: _,
1059
+ ...newNode
1060
+ } = node;
1061
+ cacheableNodes[i] = newNode;
1062
+ } else {
1063
+ cacheableNodes[i] = node;
1064
+ }
1034
1065
  }
1035
- }
1036
- let nodeCountsPerBlob = [];
1037
- for (let i = 0; i * this.graph.nodesPerBlob < cacheableNodes.length; i += 1) {
1038
- let nodesStartIndex = i * this.graph.nodesPerBlob;
1039
- let nodesEndIndex = Math.min((i + 1) * this.graph.nodesPerBlob, cacheableNodes.length);
1040
- nodeCountsPerBlob.push(nodesEndIndex - nodesStartIndex);
1041
- if (!this.graph.hasCachedRequestChunk(i)) {
1042
- // We assume the request graph nodes are immutable and won't change
1043
- let nodesToCache = cacheableNodes.slice(nodesStartIndex, nodesEndIndex);
1044
- queue.add(() => serialiseAndSet(getRequestGraphNodeKey(i, cacheKey), nodesToCache).then(() => {
1045
- // Succeeded in writing to disk, save that we have completed this chunk
1046
- this.graph.setCachedRequestChunk(i);
1047
- }));
1066
+ let nodeCountsPerBlob = [];
1067
+ for (let i = 0; i * this.graph.nodesPerBlob < cacheableNodes.length; i += 1) {
1068
+ let nodesStartIndex = i * this.graph.nodesPerBlob;
1069
+ let nodesEndIndex = Math.min((i + 1) * this.graph.nodesPerBlob, cacheableNodes.length);
1070
+ nodeCountsPerBlob.push(nodesEndIndex - nodesStartIndex);
1071
+ if (!this.graph.hasCachedRequestChunk(i)) {
1072
+ // We assume the request graph nodes are immutable and won't change
1073
+ let nodesToCache = cacheableNodes.slice(nodesStartIndex, nodesEndIndex);
1074
+ queue.add(() => serialiseAndSet(getRequestGraphNodeKey(i, cacheKey), nodesToCache).then(() => {
1075
+ // Succeeded in writing to disk, save that we have completed this chunk
1076
+ this.graph.setCachedRequestChunk(i);
1077
+ }));
1078
+ }
1048
1079
  }
1049
- }
1050
- try {
1051
1080
  await queue.run();
1052
1081
 
1053
1082
  // Set the request graph after the queue is flushed to avoid writing an invalid state
@@ -1056,7 +1085,7 @@ class RequestTracker {
1056
1085
  nodeCountsPerBlob,
1057
1086
  nodes: undefined
1058
1087
  });
1059
- await runCacheImprovements(() => serialiseAndSet(`request_tracker:cache_metadata:${cacheKey}`, {
1088
+ await runCacheImprovements(() => serialiseAndSet(`${cacheKey}/cache_metadata`, {
1060
1089
  version: _constants.ATLASPACK_VERSION,
1061
1090
  entries: this.options.entries,
1062
1091
  mode: this.options.mode,
@@ -1064,15 +1093,16 @@ class RequestTracker {
1064
1093
  watchBackend: this.options.watchBackend
1065
1094
  }), () => Promise.resolve());
1066
1095
  let opts = getWatcherOptions(this.options);
1067
- let snapshotPath = _path2().default.join(this.options.cacheDir, `snapshot-${cacheKey}` + '.txt');
1096
+ let snapshotPath = _path2().default.join(this.options.cacheDir, snapshotKey + '.txt');
1068
1097
  await this.options.outputFS.writeSnapshot(this.options.watchDir, snapshotPath, opts);
1069
1098
  } catch (err) {
1070
1099
  // If we have aborted, ignore the error and continue
1071
1100
  if (!(signal !== null && signal !== void 0 && signal.aborted)) throw err;
1101
+ } finally {
1102
+ await runCacheImprovements(async cache => {
1103
+ await cache.getNativeRef().commitWriteTransaction();
1104
+ }, () => Promise.resolve());
1072
1105
  }
1073
- await runCacheImprovements(async cache => {
1074
- await cache.getNativeRef().commitWriteTransaction();
1075
- }, () => Promise.resolve());
1076
1106
  (0, _ReporterRunner.report)({
1077
1107
  type: 'cache',
1078
1108
  phase: 'end',
@@ -1109,17 +1139,30 @@ function getWatcherOptions({
1109
1139
  };
1110
1140
  }
1111
1141
  function getCacheKey(options) {
1142
+ if ((0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
1143
+ const hash = (0, _rust().hashString)(`${_constants.ATLASPACK_VERSION}:${JSON.stringify(options.entries)}:${options.mode}:${options.shouldBuildLazily ? 'lazy' : 'eager'}:${options.watchBackend ?? ''}`);
1144
+ return `RequestTracker/${_constants.ATLASPACK_VERSION}/${hash}`;
1145
+ }
1112
1146
  return (0, _rust().hashString)(`${_constants.ATLASPACK_VERSION}:${JSON.stringify(options.entries)}:${options.mode}:${options.shouldBuildLazily ? 'lazy' : 'eager'}:${options.watchBackend ?? ''}`);
1113
1147
  }
1114
1148
  function getRequestGraphNodeKey(index, cacheKey) {
1149
+ if ((0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
1150
+ return `${cacheKey}/RequestGraph/nodes/${index}`;
1151
+ }
1115
1152
  return `requestGraph-nodes-${index}-${cacheKey}`;
1116
1153
  }
1117
1154
  async function readAndDeserializeRequestGraph(cache, requestGraphKey, cacheKey) {
1118
1155
  let bufferLength = 0;
1119
1156
  const getAndDeserialize = async key => {
1120
- let buffer = await cache.getLargeBlob(key);
1121
- bufferLength += Buffer.byteLength(buffer);
1122
- return (0, _buildCache().deserialize)(buffer);
1157
+ if ((0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
1158
+ const buffer = await cache.getBlob(key);
1159
+ bufferLength += Buffer.byteLength(buffer);
1160
+ return (0, _buildCache().deserialize)(buffer);
1161
+ } else {
1162
+ const buffer = await cache.getLargeBlob(key);
1163
+ bufferLength += Buffer.byteLength(buffer);
1164
+ return (0, _buildCache().deserialize)(buffer);
1165
+ }
1123
1166
  };
1124
1167
  let serializedRequestGraph = await getAndDeserialize(requestGraphKey);
1125
1168
  let nodePromises = serializedRequestGraph.nodeCountsPerBlob.map(async (nodesCount, i) => {
@@ -1141,9 +1184,9 @@ async function loadRequestGraph(options) {
1141
1184
  return new RequestGraph();
1142
1185
  }
1143
1186
  let cacheKey = getCacheKey(options);
1144
- let requestGraphKey = `requestGraph-${cacheKey}`;
1187
+ let requestGraphKey = (0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements') ? `${cacheKey}/RequestGraph` : `requestGraph-${cacheKey}`;
1145
1188
  let timeout;
1146
- const snapshotKey = `snapshot-${cacheKey}`;
1189
+ const snapshotKey = (0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements') ? `${cacheKey}/snapshot` : `snapshot-${cacheKey}`;
1147
1190
  const snapshotPath = _path2().default.join(options.cacheDir, snapshotKey + '.txt');
1148
1191
  const commonMeta = {
1149
1192
  cacheKey,
@@ -1163,7 +1206,8 @@ async function loadRequestGraph(options) {
1163
1206
  ...commonMeta
1164
1207
  }
1165
1208
  });
1166
- if (await options.cache.hasLargeBlob(requestGraphKey)) {
1209
+ const hasRequestGraphInCache = (0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements') ? await options.cache.has(requestGraphKey) : await options.cache.hasLargeBlob(requestGraphKey);
1210
+ if (hasRequestGraphInCache) {
1167
1211
  try {
1168
1212
  let {
1169
1213
  requestGraph
@@ -1230,6 +1274,20 @@ async function loadRequestGraph(options) {
1230
1274
  * A wrapper around an invalidation type / method
1231
1275
  */
1232
1276
 
1277
+ /**
1278
+ * Details about an invalidation.
1279
+ *
1280
+ * If this is a fs events invalidation, this key will contain statistics about invalidations
1281
+ * by path.
1282
+ *
1283
+ * If this is a env or option invalidation, this key will contain the list of changed environment
1284
+ * variables or options.
1285
+ */
1286
+
1287
+ /**
1288
+ * Number of invalidations for a given file-system event.
1289
+ */
1290
+
1233
1291
  /**
1234
1292
  * Information about a certain cache invalidation type.
1235
1293
  */
@@ -1255,9 +1313,7 @@ async function invalidateRequestGraph(requestGraph, options, events) {
1255
1313
  fn: () => requestGraph.invalidateOptionNodes(options)
1256
1314
  }, {
1257
1315
  key: 'fsEvents',
1258
- fn: async () => {
1259
- await requestGraph.respondToFSEvents(options.unstableFileInvalidations || events, options, 10000, true);
1260
- }
1316
+ fn: () => invalidateRequestGraphFSEvents(requestGraph, options, events)
1261
1317
  }];
1262
1318
  const invalidations = [];
1263
1319
  for (const invalidation of invalidationFns) {
@@ -1275,18 +1331,34 @@ async function invalidateRequestGraph(requestGraph, options, events) {
1275
1331
  requestInvalidationRatio: invalidatedCount / requestCount
1276
1332
  };
1277
1333
  }
1278
-
1334
+ /**
1335
+ * Invalidate the request graph based on file-system events.
1336
+ *
1337
+ * Returns statistics about the invalidations.
1338
+ */
1339
+ async function invalidateRequestGraphFSEvents(requestGraph, options, events) {
1340
+ const {
1341
+ invalidationsByPath
1342
+ } = await requestGraph.respondToFSEvents(options.unstableFileInvalidations || events, options, 10000, true);
1343
+ const biggestInvalidations = getBiggestFSEventsInvalidations(invalidationsByPath);
1344
+ return {
1345
+ biggestInvalidations
1346
+ };
1347
+ }
1279
1348
  /**
1280
1349
  * Runs an invalidation function and reports metrics.
1281
1350
  */
1282
1351
  async function runInvalidation(requestGraph, invalidationFn) {
1283
- const startInvalidationCount = requestGraph.invalidNodeIds.size;
1352
+ const start = _perf_hooks().performance.now();
1353
+ const startInvalidationCount = requestGraph.getInvalidNodeCount();
1284
1354
  const result = await invalidationFn.fn();
1285
- const count = requestGraph.invalidNodeIds.size - startInvalidationCount;
1355
+ const count = requestGraph.getInvalidNodeCount() - startInvalidationCount;
1356
+ const duration = _perf_hooks().performance.now() - start;
1286
1357
  return {
1287
1358
  key: invalidationFn.key,
1288
1359
  count,
1289
- changes: typeof result === 'object' && Array.isArray(result) ? result : null
1360
+ detail: result ?? null,
1361
+ duration
1290
1362
  };
1291
1363
  }
1292
1364
  function logErrorOnBailout(options, snapshotPath, e) {
@@ -1328,4 +1400,19 @@ function cleanUpOrphans(graph) {
1328
1400
  }
1329
1401
  });
1330
1402
  return removedNodeIds;
1403
+ }
1404
+
1405
+ /**
1406
+ * Returns paths that invalidated the most nodes
1407
+ */
1408
+ function getBiggestFSEventsInvalidations(invalidationsByPath, limit = 10) {
1409
+ const invalidations = [];
1410
+ for (const [path, count] of invalidationsByPath) {
1411
+ invalidations.push({
1412
+ path,
1413
+ count
1414
+ });
1415
+ }
1416
+ invalidations.sort((a, b) => b.count - a.count);
1417
+ return invalidations.slice(0, limit);
1331
1418
  }
@@ -53,6 +53,13 @@ var _assetUtils = require("./assetUtils");
53
53
  var _types = require("./types");
54
54
  var _utils2 = require("./utils");
55
55
  var _projectPath = require("./projectPath");
56
+ function _featureFlags() {
57
+ const data = require("@atlaspack/feature-flags");
58
+ _featureFlags = function () {
59
+ return data;
60
+ };
61
+ return data;
62
+ }
56
63
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
57
64
  class UncommittedAsset {
58
65
  constructor({
@@ -133,6 +140,8 @@ class UncommittedAsset {
133
140
  hash = (0, _rust().hashBuffer)(content);
134
141
  size = content.length;
135
142
  }
143
+
144
+ // Maybe we should just store this in a file instead of LMDB
136
145
  await this.options.cache.setBlob(contentKey, content);
137
146
  return {
138
147
  size,
@@ -184,6 +193,10 @@ class UncommittedAsset {
184
193
  this.content = buffer;
185
194
  this.clearAST();
186
195
  }
196
+
197
+ /**
198
+ * @deprecated This has been broken on any cache other than FSCache for a long time.
199
+ */
187
200
  setStream(stream) {
188
201
  this.content = stream;
189
202
  this.clearAST();
@@ -248,6 +261,10 @@ class UncommittedAsset {
248
261
  this.value.astGenerator = null;
249
262
  }
250
263
  getCacheKey(key) {
264
+ if ((0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
265
+ const filePath = (0, _projectPath.fromProjectPathRelative)(this.value.filePath);
266
+ return `Asset/${_constants.ATLASPACK_VERSION}/${filePath}/${this.value.id}/${key}`;
267
+ }
251
268
  return (0, _rust().hashString)(_constants.ATLASPACK_VERSION + key + this.value.id);
252
269
  }
253
270
  addDependency(opts) {
@@ -149,6 +149,14 @@ class AtlaspackWorker {
149
149
  }
150
150
  };
151
151
  }
152
+ if (result.isExcluded) {
153
+ return {
154
+ invalidations: [],
155
+ resolution: {
156
+ type: 'excluded'
157
+ }
158
+ };
159
+ }
152
160
  return {
153
161
  invalidations: [],
154
162
  resolution: {