@atlaspack/core 2.16.2-canary.58 → 2.16.2-canary.59

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.
@@ -4,8 +4,10 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.fromEnvironmentId = fromEnvironmentId;
7
+ exports.loadEnvironmentsFromCache = loadEnvironmentsFromCache;
7
8
  exports.toEnvironmentId = toEnvironmentId;
8
9
  exports.toEnvironmentRef = toEnvironmentRef;
10
+ exports.writeEnvironmentsToCache = writeEnvironmentsToCache;
9
11
  function _rust() {
10
12
  const data = require("@atlaspack/rust");
11
13
  _rust = function () {
@@ -20,6 +22,14 @@ function _featureFlags() {
20
22
  };
21
23
  return data;
22
24
  }
25
+ function _logger() {
26
+ const data = require("@atlaspack/logger");
27
+ _logger = function () {
28
+ return data;
29
+ };
30
+ return data;
31
+ }
32
+ var _constants = require("./constants");
23
33
  /*!
24
34
  * At the moment we're doing this change for `CoreEnvironment`,
25
35
  * but the same change must be made for `TypesEnvironment` in @atlaspack/types.
@@ -77,4 +87,51 @@ function fromEnvironmentId(id) {
77
87
  const env = Object.freeze((0, _rust().getEnvironment)(id));
78
88
  localEnvironmentCache.set(id, env);
79
89
  return env;
90
+ }
91
+
92
+ /**
93
+ * Writes all environments and their IDs to the cache
94
+ * @param {Cache} cache
95
+ * @returns {Promise<void>}
96
+ */
97
+ async function writeEnvironmentsToCache(cache) {
98
+ const environments = (0, _rust().getAllEnvironments)();
99
+ const environmentIds = new Set();
100
+
101
+ // Store each environment individually
102
+ for (const env of environments) {
103
+ environmentIds.add(env.id);
104
+ const envKey = `Environment/${_constants.ATLASPACK_VERSION}/${env.id}`;
105
+ await (0, _logger().instrument)(`RequestTracker::writeToCache::cache.put(${envKey})`, async () => {
106
+ await cache.set(envKey, env);
107
+ });
108
+ }
109
+
110
+ // Store the list of environment IDs
111
+ await (0, _logger().instrument)(`RequestTracker::writeToCache::cache.put(${`EnvironmentManager/${_constants.ATLASPACK_VERSION}`})`, async () => {
112
+ await cache.set(`EnvironmentManager/${_constants.ATLASPACK_VERSION}`, Array.from(environmentIds));
113
+ });
114
+ }
115
+
116
+ /**
117
+ * Loads all environments and their IDs from the cache
118
+ * @param {Cache} cache
119
+ * @returns {Promise<void>}
120
+ */
121
+ async function loadEnvironmentsFromCache(cache) {
122
+ const cachedEnvIds = await cache.get(`EnvironmentManager/${_constants.ATLASPACK_VERSION}`);
123
+ if (cachedEnvIds == null) {
124
+ return;
125
+ }
126
+ const environments = [];
127
+ for (const envId of cachedEnvIds) {
128
+ const envKey = `Environment/${_constants.ATLASPACK_VERSION}/${envId}`;
129
+ const cachedEnv = await cache.get(envKey);
130
+ if (cachedEnv != null) {
131
+ environments.push(cachedEnv);
132
+ }
133
+ }
134
+ if (environments.length > 0) {
135
+ (0, _rust().setAllEnvironments)(environments);
136
+ }
80
137
  }
@@ -95,6 +95,7 @@ function _perf_hooks() {
95
95
  };
96
96
  return data;
97
97
  }
98
+ var _EnvironmentManager = require("./EnvironmentManager");
98
99
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
99
100
  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); }
100
101
  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; }
@@ -1023,6 +1024,9 @@ class RequestTracker {
1023
1024
  total,
1024
1025
  size: this.graph.nodes.length
1025
1026
  });
1027
+ if ((0, _featureFlags().getFeatureFlag)('environmentDeduplication')) {
1028
+ await (0, _EnvironmentManager.writeEnvironmentsToCache)(options.cache);
1029
+ }
1026
1030
  let serialisedGraph = this.graph.serialize();
1027
1031
 
1028
1032
  // Delete an existing request graph cache, to prevent invalid states
@@ -1214,6 +1218,9 @@ async function loadRequestGraph(options) {
1214
1218
  ...commonMeta
1215
1219
  }
1216
1220
  });
1221
+ if ((0, _featureFlags().getFeatureFlag)('environmentDeduplication')) {
1222
+ await (0, _EnvironmentManager.loadEnvironmentsFromCache)(options.cache);
1223
+ }
1217
1224
  const hasRequestGraphInCache = (0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements') ? await options.cache.has(requestGraphKey) : await options.cache.hasLargeBlob(requestGraphKey);
1218
1225
  if (hasRequestGraphInCache) {
1219
1226
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaspack/core",
3
- "version": "2.16.2-canary.58+1e32d4eae",
3
+ "version": "2.16.2-canary.59+0b2f6f557",
4
4
  "license": "(MIT OR Apache-2.0)",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -21,21 +21,21 @@
21
21
  "check-ts": "tsc --noEmit index.d.ts"
22
22
  },
23
23
  "dependencies": {
24
- "@atlaspack/build-cache": "2.13.3-canary.126+1e32d4eae",
25
- "@atlaspack/cache": "3.1.1-canary.58+1e32d4eae",
26
- "@atlaspack/diagnostic": "2.14.1-canary.126+1e32d4eae",
27
- "@atlaspack/events": "2.14.1-canary.126+1e32d4eae",
28
- "@atlaspack/feature-flags": "2.14.1-canary.126+1e32d4eae",
29
- "@atlaspack/fs": "2.14.5-canary.58+1e32d4eae",
30
- "@atlaspack/graph": "3.4.1-canary.126+1e32d4eae",
31
- "@atlaspack/logger": "2.14.5-canary.58+1e32d4eae",
32
- "@atlaspack/package-manager": "2.14.5-canary.58+1e32d4eae",
33
- "@atlaspack/plugin": "2.14.5-canary.58+1e32d4eae",
34
- "@atlaspack/profiler": "2.14.1-canary.126+1e32d4eae",
35
- "@atlaspack/rust": "3.2.1-canary.58+1e32d4eae",
36
- "@atlaspack/types": "2.14.5-canary.58+1e32d4eae",
37
- "@atlaspack/utils": "2.14.5-canary.58+1e32d4eae",
38
- "@atlaspack/workers": "2.14.5-canary.58+1e32d4eae",
24
+ "@atlaspack/build-cache": "2.13.3-canary.127+0b2f6f557",
25
+ "@atlaspack/cache": "3.1.1-canary.59+0b2f6f557",
26
+ "@atlaspack/diagnostic": "2.14.1-canary.127+0b2f6f557",
27
+ "@atlaspack/events": "2.14.1-canary.127+0b2f6f557",
28
+ "@atlaspack/feature-flags": "2.14.1-canary.127+0b2f6f557",
29
+ "@atlaspack/fs": "2.14.5-canary.59+0b2f6f557",
30
+ "@atlaspack/graph": "3.4.1-canary.127+0b2f6f557",
31
+ "@atlaspack/logger": "2.14.5-canary.59+0b2f6f557",
32
+ "@atlaspack/package-manager": "2.14.5-canary.59+0b2f6f557",
33
+ "@atlaspack/plugin": "2.14.5-canary.59+0b2f6f557",
34
+ "@atlaspack/profiler": "2.14.1-canary.127+0b2f6f557",
35
+ "@atlaspack/rust": "3.2.1-canary.59+0b2f6f557",
36
+ "@atlaspack/types": "2.14.5-canary.59+0b2f6f557",
37
+ "@atlaspack/utils": "2.14.5-canary.59+0b2f6f557",
38
+ "@atlaspack/workers": "2.14.5-canary.59+0b2f6f557",
39
39
  "@mischnic/json-sourcemap": "^0.1.0",
40
40
  "@parcel/source-map": "^2.1.1",
41
41
  "base-x": "^3.0.8",
@@ -71,5 +71,5 @@
71
71
  "./src/serializerCore.js": "./src/serializerCore.browser.js"
72
72
  },
73
73
  "type": "commonjs",
74
- "gitHead": "1e32d4eae6b3af3968e8a0ef97d35b4347fd4196"
74
+ "gitHead": "0b2f6f55794d3ff6e2f5a41f963e7e5dd8ad9f8d"
75
75
  }
@@ -4,8 +4,16 @@
4
4
  * but the same change must be made for `TypesEnvironment` in @atlaspack/types.
5
5
  */
6
6
  import type {Environment as CoreEnvironment} from './types';
7
- import {addEnvironment, getEnvironment} from '@atlaspack/rust';
7
+ import {type Cache} from '@atlaspack/cache';
8
+ import {
9
+ addEnvironment,
10
+ getEnvironment,
11
+ getAllEnvironments,
12
+ setAllEnvironments,
13
+ } from '@atlaspack/rust';
8
14
  import {getFeatureFlag} from '@atlaspack/feature-flags';
15
+ import {instrument} from '@atlaspack/logger';
16
+ import {ATLASPACK_VERSION} from './constants';
9
17
 
10
18
  const localEnvironmentCache = new Map<string, CoreEnvironment>();
11
19
 
@@ -74,3 +82,64 @@ export function fromEnvironmentId(id: EnvironmentRef): CoreEnvironment {
74
82
  localEnvironmentCache.set(id, env);
75
83
  return env;
76
84
  }
85
+
86
+ /**
87
+ * Writes all environments and their IDs to the cache
88
+ * @param {Cache} cache
89
+ * @returns {Promise<void>}
90
+ */
91
+ export async function writeEnvironmentsToCache(cache: Cache): Promise<void> {
92
+ const environments = getAllEnvironments();
93
+ const environmentIds = new Set<string>();
94
+
95
+ // Store each environment individually
96
+ for (const env of environments) {
97
+ environmentIds.add(env.id);
98
+ const envKey = `Environment/${ATLASPACK_VERSION}/${env.id}`;
99
+
100
+ await instrument(
101
+ `RequestTracker::writeToCache::cache.put(${envKey})`,
102
+ async () => {
103
+ await cache.set(envKey, env);
104
+ },
105
+ );
106
+ }
107
+
108
+ // Store the list of environment IDs
109
+ await instrument(
110
+ `RequestTracker::writeToCache::cache.put(${`EnvironmentManager/${ATLASPACK_VERSION}`})`,
111
+ async () => {
112
+ await cache.set(
113
+ `EnvironmentManager/${ATLASPACK_VERSION}`,
114
+ Array.from(environmentIds),
115
+ );
116
+ },
117
+ );
118
+ }
119
+
120
+ /**
121
+ * Loads all environments and their IDs from the cache
122
+ * @param {Cache} cache
123
+ * @returns {Promise<void>}
124
+ */
125
+ export async function loadEnvironmentsFromCache(cache: Cache): Promise<void> {
126
+ const cachedEnvIds = await cache.get(
127
+ `EnvironmentManager/${ATLASPACK_VERSION}`,
128
+ );
129
+
130
+ if (cachedEnvIds == null) {
131
+ return;
132
+ }
133
+
134
+ const environments = [];
135
+ for (const envId of cachedEnvIds) {
136
+ const envKey = `Environment/${ATLASPACK_VERSION}/${envId}`;
137
+ const cachedEnv = await cache.get(envKey);
138
+ if (cachedEnv != null) {
139
+ environments.push(cachedEnv);
140
+ }
141
+ }
142
+ if (environments.length > 0) {
143
+ setAllEnvironments(environments);
144
+ }
145
+ }
@@ -30,15 +30,15 @@ import nullthrows from 'nullthrows';
30
30
 
31
31
  import {
32
32
  ATLASPACK_VERSION,
33
- VALID,
34
- INITIAL_BUILD,
35
33
  FILE_CREATE,
36
- FILE_UPDATE,
37
34
  FILE_DELETE,
35
+ FILE_UPDATE,
38
36
  ENV_CHANGE,
37
+ ERROR,
38
+ INITIAL_BUILD,
39
39
  OPTION_CHANGE,
40
40
  STARTUP,
41
- ERROR,
41
+ VALID,
42
42
  } from './constants';
43
43
  import type {AtlaspackV3} from './atlaspack-v3/AtlaspackV3';
44
44
  import {
@@ -71,6 +71,11 @@ import type {
71
71
  import {BuildAbortError, assertSignalNotAborted, hashFromOption} from './utils';
72
72
  import {performance} from 'perf_hooks';
73
73
 
74
+ import {
75
+ loadEnvironmentsFromCache,
76
+ writeEnvironmentsToCache,
77
+ } from './EnvironmentManager';
78
+
74
79
  export const requestGraphEdgeTypes = {
75
80
  subrequest: 2,
76
81
  invalidated_by_update: 3,
@@ -1572,6 +1577,10 @@ export default class RequestTracker {
1572
1577
  size: this.graph.nodes.length,
1573
1578
  });
1574
1579
 
1580
+ if (getFeatureFlag('environmentDeduplication')) {
1581
+ await writeEnvironmentsToCache(options.cache);
1582
+ }
1583
+
1575
1584
  let serialisedGraph = this.graph.serialize();
1576
1585
 
1577
1586
  // Delete an existing request graph cache, to prevent invalid states
@@ -1856,6 +1865,10 @@ async function loadRequestGraph(options): Async<RequestGraph> {
1856
1865
  },
1857
1866
  });
1858
1867
 
1868
+ if (getFeatureFlag('environmentDeduplication')) {
1869
+ await loadEnvironmentsFromCache(options.cache);
1870
+ }
1871
+
1859
1872
  const hasRequestGraphInCache = getFeatureFlag('cachePerformanceImprovements')
1860
1873
  ? await options.cache.has(requestGraphKey)
1861
1874
  : await options.cache.hasLargeBlob(requestGraphKey);
@@ -0,0 +1,192 @@
1
+ // @flow strict-local
2
+
3
+ import assert from 'assert';
4
+ import nullthrows from 'nullthrows';
5
+ import sinon from 'sinon';
6
+ import {ATLASPACK_VERSION} from '../src/constants';
7
+ import {DEFAULT_FEATURE_FLAGS, setFeatureFlags} from '@atlaspack/feature-flags';
8
+ import {setAllEnvironments, getAllEnvironments} from '@atlaspack/rust';
9
+ import {
10
+ loadEnvironmentsFromCache,
11
+ writeEnvironmentsToCache,
12
+ } from '../src/EnvironmentManager';
13
+ import {DEFAULT_OPTIONS} from './test-utils';
14
+ import {LMDBLiteCache} from '@atlaspack/cache';
15
+
16
+ const options = {
17
+ ...DEFAULT_OPTIONS,
18
+ cache: new LMDBLiteCache(DEFAULT_OPTIONS.cacheDir),
19
+ };
20
+
21
+ describe('EnvironmentManager', () => {
22
+ const env1 = {
23
+ id: 'd821e85f6b50315e',
24
+ context: 'browser',
25
+ engines: {browsers: ['> 0.25%']},
26
+ includeNodeModules: true,
27
+ outputFormat: 'global',
28
+ isLibrary: false,
29
+ shouldOptimize: false,
30
+ shouldScopeHoist: false,
31
+ loc: undefined,
32
+ sourceMap: undefined,
33
+ sourceType: 'module',
34
+ unstableSingleFileOutput: false,
35
+ };
36
+ const env2 = {
37
+ id: 'de92f48baa8448d2',
38
+ context: 'node',
39
+ engines: {
40
+ browsers: [],
41
+ node: '>= 8',
42
+ },
43
+ includeNodeModules: false,
44
+ outputFormat: 'commonjs',
45
+ isLibrary: true,
46
+ shouldOptimize: true,
47
+ shouldScopeHoist: true,
48
+ loc: null,
49
+ sourceMap: null,
50
+ sourceType: 'module',
51
+ unstableSingleFileOutput: false,
52
+ };
53
+
54
+ beforeEach(async () => {
55
+ await options.cache.ensure();
56
+
57
+ for (const key of options.cache.keys()) {
58
+ await options.cache.getNativeRef().delete(key);
59
+ }
60
+ setAllEnvironments([]);
61
+
62
+ setFeatureFlags({
63
+ ...DEFAULT_FEATURE_FLAGS,
64
+ environmentDeduplication: true,
65
+ });
66
+ });
67
+
68
+ it('should store environments by ID in the cache', async () => {
69
+ setAllEnvironments([env1]);
70
+ await writeEnvironmentsToCache(options.cache);
71
+
72
+ const cachedEnv1 = await options.cache.get(
73
+ `Environment/${ATLASPACK_VERSION}/${env1.id}`,
74
+ );
75
+ assert.deepEqual(cachedEnv1, env1, 'Environment 1 should be cached');
76
+ });
77
+
78
+ it('should list all environment IDs in the environment manager', async () => {
79
+ const environmentIds = [env1.id, env2.id];
80
+ setAllEnvironments([env1, env2]);
81
+ await writeEnvironmentsToCache(options.cache);
82
+
83
+ const cachedEnvIds = await options.cache.get(
84
+ `EnvironmentManager/${ATLASPACK_VERSION}`,
85
+ );
86
+ const cachedIdsArray = nullthrows(cachedEnvIds);
87
+ assert.equal(
88
+ cachedIdsArray.length,
89
+ environmentIds.length,
90
+ 'Should have same number of IDs',
91
+ );
92
+ assert(
93
+ environmentIds.every((id) => cachedIdsArray.includes(id)),
94
+ 'All environment IDs should be present in cache',
95
+ );
96
+ });
97
+
98
+ it('should write all environments to cache using writeEnvironmentsToCache', async () => {
99
+ setAllEnvironments([env1, env2]);
100
+ await writeEnvironmentsToCache(options.cache);
101
+
102
+ // Verify each environment was stored individually
103
+ const cachedEnv1 = await options.cache.get(
104
+ `Environment/${ATLASPACK_VERSION}/${env1.id}`,
105
+ );
106
+ const cachedEnv2 = await options.cache.get(
107
+ `Environment/${ATLASPACK_VERSION}/${env2.id}`,
108
+ );
109
+ assert.deepEqual(cachedEnv1, env1, 'Environment 1 should be cached');
110
+ assert.deepEqual(cachedEnv2, env2, 'Environment 2 should be cached');
111
+
112
+ // Verify environment IDs were stored in manager
113
+ const cachedEnvIds = await options.cache.get(
114
+ `EnvironmentManager/${ATLASPACK_VERSION}`,
115
+ );
116
+ const cachedIdsArray = nullthrows(cachedEnvIds);
117
+ assert(
118
+ cachedIdsArray.length === 2 &&
119
+ [env1.id, env2.id].every((id) => cachedIdsArray.includes(id)),
120
+ 'Environment IDs should be stored in manager',
121
+ );
122
+ });
123
+
124
+ it('should load environments from cache on loadRequestGraph on a subsequent build', async () => {
125
+ // Simulate cache written on a first build
126
+ setAllEnvironments([env1, env2]);
127
+ await writeEnvironmentsToCache(options.cache);
128
+
129
+ await loadEnvironmentsFromCache(options.cache);
130
+
131
+ const loadedEnvironments = getAllEnvironments();
132
+ assert.equal(
133
+ loadedEnvironments.length,
134
+ 2,
135
+ 'Should load 2 environments from cache',
136
+ );
137
+
138
+ const env1Loaded = loadedEnvironments.find((e) => e.id === env1.id);
139
+ const env2Loaded = loadedEnvironments.find((e) => e.id === env2.id);
140
+
141
+ assert.deepEqual(
142
+ env1Loaded,
143
+ env1,
144
+ 'First environment should match cached environment',
145
+ );
146
+ assert.deepEqual(
147
+ env2Loaded,
148
+ env2,
149
+ 'Second environment should match cached environment',
150
+ );
151
+ });
152
+
153
+ it('should handle empty cache gracefully without calling setAllEnvironments', async () => {
154
+ const setAllEnvironmentsSpy = sinon.spy(setAllEnvironments);
155
+
156
+ await assert.doesNotReject(
157
+ loadEnvironmentsFromCache(options.cache),
158
+ 'loadEnvironmentsFromCache should not throw when cache is empty',
159
+ );
160
+
161
+ assert.equal(
162
+ setAllEnvironmentsSpy.callCount,
163
+ 0,
164
+ 'setAllEnvironments should not be called when loading from empty cache',
165
+ );
166
+ });
167
+
168
+ it('should not load environments from a different version', async () => {
169
+ const setAllEnvironmentsSpy = sinon.spy(setAllEnvironments);
170
+ const differentVersion = '2.17.2'; // A different version than ATLASPACK_VERSION
171
+
172
+ // Store an environment with a different version
173
+ await options.cache.set(`Environment/${differentVersion}/${env1.id}`, env1);
174
+ await options.cache.set(`EnvironmentManager/${differentVersion}`, [
175
+ env1.id,
176
+ ]);
177
+
178
+ await loadEnvironmentsFromCache(options.cache);
179
+
180
+ assert.equal(
181
+ setAllEnvironmentsSpy.callCount,
182
+ 0,
183
+ 'setAllEnvironments should not be called when loading from different version',
184
+ );
185
+ const loadedEnvironments = getAllEnvironments();
186
+ assert.equal(
187
+ loadedEnvironments.length,
188
+ 0,
189
+ 'Should not load any environments from different version',
190
+ );
191
+ });
192
+ });