@fluidframework/container-runtime 1.0.1 → 1.1.0-75972
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/dist/connectionTelemetry.d.ts +19 -0
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +21 -21
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +13 -1
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +99 -11
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +14 -3
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts +0 -4
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +12 -1
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +4 -4
- package/dist/dataStores.js.map +1 -1
- package/dist/garbageCollection.d.ts +20 -24
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +40 -117
- package/dist/garbageCollection.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/connectionTelemetry.d.ts +19 -0
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +21 -21
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +13 -1
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +101 -13
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +15 -4
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts +0 -4
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js +12 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +5 -5
- package/lib/dataStores.js.map +1 -1
- package/lib/garbageCollection.d.ts +20 -24
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +39 -115
- package/lib/garbageCollection.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +19 -47
- package/src/connectionTelemetry.ts +58 -37
- package/src/containerRuntime.ts +119 -26
- package/src/dataStore.ts +21 -4
- package/src/dataStoreRegistry.ts +8 -1
- package/src/dataStores.ts +6 -5
- package/src/garbageCollection.ts +66 -158
- package/src/packageVersion.ts +1 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.
|
|
7
|
+
exports.GarbageCollector = exports.GCNodeType = exports.defaultSessionExpiryDurationMs = exports.trackGCStateKey = exports.disableSessionExpiryKey = exports.runSessionExpiryKey = exports.gcBlobPrefix = exports.gcTreeKey = void 0;
|
|
8
8
|
const common_utils_1 = require("@fluidframework/common-utils");
|
|
9
9
|
const container_utils_1 = require("@fluidframework/container-utils");
|
|
10
10
|
const garbage_collector_1 = require("@fluidframework/garbage-collector");
|
|
@@ -14,7 +14,6 @@ const runtime_utils_1 = require("@fluidframework/runtime-utils");
|
|
|
14
14
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
15
15
|
const containerRuntime_1 = require("./containerRuntime");
|
|
16
16
|
const dataStores_1 = require("./dataStores");
|
|
17
|
-
const packageVersion_1 = require("./packageVersion");
|
|
18
17
|
const summaryFormat_1 = require("./summaryFormat");
|
|
19
18
|
/** This is the current version of garbage collection. */
|
|
20
19
|
const GCVersion = 1;
|
|
@@ -34,12 +33,8 @@ const writeAtRootKey = "Fluid.GarbageCollection.WriteDataAtRoot";
|
|
|
34
33
|
exports.runSessionExpiryKey = "Fluid.GarbageCollection.RunSessionExpiry";
|
|
35
34
|
// Feature gate key to disable expiring session after a set period of time, even if expiry value is present
|
|
36
35
|
exports.disableSessionExpiryKey = "Fluid.GarbageCollection.DisableSessionExpiry";
|
|
37
|
-
// Feature gate key to log error messages if GC reference validation fails.
|
|
38
|
-
exports.logUnknownOutboundReferencesKey = "Fluid.GarbageCollection.LogUnknownOutboundReferences";
|
|
39
36
|
// Feature gate key to write the gc blob as a handle if the data is the same.
|
|
40
37
|
exports.trackGCStateKey = "Fluid.GarbageCollection.TrackGCState";
|
|
41
|
-
// Feature gate key to limit which versions can write the gc blob as a handle if the data is the same.
|
|
42
|
-
exports.trackGCStateMinimumVersionKey = "Fluid.GarbageCollection.TrackGCState.MinVersion";
|
|
43
38
|
const defaultInactiveTimeoutMs = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
44
39
|
exports.defaultSessionExpiryDurationMs = 30 * 24 * 60 * 60 * 1000; // 30 days
|
|
45
40
|
/** The types of GC nodes in the GC reference graph. */
|
|
@@ -117,21 +112,12 @@ class UnreferencedStateTracker {
|
|
|
117
112
|
* NodeId = "dds1" NodeId = "dds2"
|
|
118
113
|
*/
|
|
119
114
|
class GarbageCollector {
|
|
120
|
-
constructor(
|
|
121
|
-
/** For a given node path, returns the node's package path. */
|
|
122
|
-
getNodePackagePath,
|
|
123
|
-
/** Returns the timestamp of the last summary generated for this container. */
|
|
124
|
-
getLastSummaryTimestampMs, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata, isSummarizerClient = true) {
|
|
115
|
+
constructor(createParams) {
|
|
125
116
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
126
|
-
this.runtime = runtime;
|
|
127
|
-
this.gcOptions = gcOptions;
|
|
128
|
-
this.getNodePackagePath = getNodePackagePath;
|
|
129
|
-
this.getLastSummaryTimestampMs = getLastSummaryTimestampMs;
|
|
130
|
-
this.isSummarizerClient = isSummarizerClient;
|
|
131
117
|
/**
|
|
132
118
|
* Tells whether the GC data should be written to the root of the summary tree.
|
|
133
119
|
*/
|
|
134
|
-
this._writeDataAtRoot =
|
|
120
|
+
this._writeDataAtRoot = true;
|
|
135
121
|
/**
|
|
136
122
|
* Tells whether the initial GC state needs to be reset. This can happen under 2 conditions:
|
|
137
123
|
* 1. The base snapshot contains GC state but GC is disabled. This will happen the first time GC is disabled after
|
|
@@ -157,7 +143,15 @@ class GarbageCollector {
|
|
|
157
143
|
this.pendingEventsQueue = [];
|
|
158
144
|
// The number of times GC has successfully completed on this instance of GarbageCollector.
|
|
159
145
|
this.completedRuns = 0;
|
|
160
|
-
this.
|
|
146
|
+
this.runtime = createParams.runtime;
|
|
147
|
+
this.isSummarizerClient = createParams.isSummarizerClient;
|
|
148
|
+
this.gcOptions = createParams.gcOptions;
|
|
149
|
+
this.getNodePackagePath = createParams.getNodePackagePath;
|
|
150
|
+
this.getLastSummaryTimestampMs = createParams.getLastSummaryTimestampMs;
|
|
151
|
+
const baseSnapshot = createParams.baseSnapshot;
|
|
152
|
+
const metadata = createParams.metadata;
|
|
153
|
+
const readAndParseBlob = createParams.readAndParseBlob;
|
|
154
|
+
this.mc = (0, telemetry_utils_1.loggerToMonitoringContext)(telemetry_utils_1.ChildLogger.create(createParams.baseLogger, "GarbageCollector", { all: { completedGCRuns: () => this.completedRuns } }));
|
|
161
155
|
let prevSummaryGCVersion;
|
|
162
156
|
/**
|
|
163
157
|
* The following GC state is enabled during container creation and cannot be changed throughout its lifetime:
|
|
@@ -166,7 +160,7 @@ class GarbageCollector {
|
|
|
166
160
|
* 3. Whether GC session expiry is enabled or not.
|
|
167
161
|
* For existing containers, we get this information from the metadata blob of its summary.
|
|
168
162
|
*/
|
|
169
|
-
if (existing) {
|
|
163
|
+
if (createParams.existing) {
|
|
170
164
|
prevSummaryGCVersion = (0, summaryFormat_1.getGCVersion)(metadata);
|
|
171
165
|
// Existing documents which did not have metadata blob or had GC disabled have version as 0. For all
|
|
172
166
|
// other existing documents, GC is enabled.
|
|
@@ -177,14 +171,14 @@ class GarbageCollector {
|
|
|
177
171
|
else {
|
|
178
172
|
// Sweep should not be enabled without enabling GC mark phase. We could silently disable sweep in this
|
|
179
173
|
// scenario but explicitly failing makes it clearer and promotes correct usage.
|
|
180
|
-
if (gcOptions.sweepAllowed && gcOptions.gcAllowed === false) {
|
|
174
|
+
if (this.gcOptions.sweepAllowed && this.gcOptions.gcAllowed === false) {
|
|
181
175
|
throw new container_utils_1.UsageError("GC sweep phase cannot be enabled without enabling GC mark phase");
|
|
182
176
|
}
|
|
183
177
|
// For new documents, GC is enabled by default. It can be explicitly disabled by setting the gcAllowed
|
|
184
178
|
// flag in GC options to false.
|
|
185
|
-
this.gcEnabled = gcOptions.gcAllowed !== false;
|
|
179
|
+
this.gcEnabled = this.gcOptions.gcAllowed !== false;
|
|
186
180
|
// The sweep phase has to be explicitly enabled by setting the sweepAllowed flag in GC options to true.
|
|
187
|
-
this.sweepEnabled = gcOptions.sweepAllowed === true;
|
|
181
|
+
this.sweepEnabled = this.gcOptions.sweepAllowed === true;
|
|
188
182
|
// Set the Session Expiry only if the flag is enabled or the test option is set.
|
|
189
183
|
if (this.mc.config.getBoolean(exports.runSessionExpiryKey) && this.gcEnabled) {
|
|
190
184
|
this.sessionExpiryTimeoutMs = exports.defaultSessionExpiryDurationMs;
|
|
@@ -218,10 +212,8 @@ class GarbageCollector {
|
|
|
218
212
|
// GC must be enabled for the document.
|
|
219
213
|
this.gcEnabled
|
|
220
214
|
// GC must not be disabled via GC options.
|
|
221
|
-
&& !gcOptions.disableGC);
|
|
222
|
-
|
|
223
|
-
const shouldTrackStateForVersion = meetsMinimumVersionRequirement(packageVersion_1.pkgVersion, minimumVersion);
|
|
224
|
-
this.trackGCState = this.mc.config.getBoolean(exports.trackGCStateKey) === true && shouldTrackStateForVersion;
|
|
215
|
+
&& !this.gcOptions.disableGC);
|
|
216
|
+
this.trackGCState = this.mc.config.getBoolean(exports.trackGCStateKey) === true;
|
|
225
217
|
/**
|
|
226
218
|
* Whether sweep should run or not. The following conditions have to be met to run sweep:
|
|
227
219
|
* 1. Overall GC or mark phase must be enabled (this.shouldRunGC).
|
|
@@ -233,19 +225,15 @@ class GarbageCollector {
|
|
|
233
225
|
this.inactiveTimeoutMs =
|
|
234
226
|
(_e = (_d = this.mc.config.getNumber("Fluid.GarbageCollection.TestOverride.InactiveTimeoutMs")) !== null && _d !== void 0 ? _d : this.gcOptions.inactiveTimeoutMs) !== null && _e !== void 0 ? _e : defaultInactiveTimeoutMs;
|
|
235
227
|
// Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.
|
|
236
|
-
this.testMode = (_f = this.mc.config.getBoolean(gcTestModeKey)) !== null && _f !== void 0 ? _f : gcOptions.runGCInTestMode === true;
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
// this.initialStateNeedsReset = gcTreePresent ? !this.shouldRunGC : this.shouldRunGC;
|
|
246
|
-
// If `writeDataAtRoot` setting is true, write the GC data into the root of the summary tree. We do this so that
|
|
247
|
-
// the roll out can be staged. Once its rolled out everywhere, we will start writing at root by default.
|
|
248
|
-
this._writeDataAtRoot = (_g = this.mc.config.getBoolean(writeAtRootKey)) !== null && _g !== void 0 ? _g : this.gcOptions.writeDataAtRoot === true;
|
|
228
|
+
this.testMode = (_f = this.mc.config.getBoolean(gcTestModeKey)) !== null && _f !== void 0 ? _f : this.gcOptions.runGCInTestMode === true;
|
|
229
|
+
// GC state is written into root of the summary tree by default. Can be overridden via feature flag for now.
|
|
230
|
+
this._writeDataAtRoot = (_g = this.mc.config.getBoolean(writeAtRootKey)) !== null && _g !== void 0 ? _g : true;
|
|
231
|
+
if (this._writeDataAtRoot) {
|
|
232
|
+
// The GC state needs to be reset if the base snapshot contains GC tree and GC is disabled or it doesn't
|
|
233
|
+
// contain GC tree and GC is enabled.
|
|
234
|
+
const gcTreePresent = (baseSnapshot === null || baseSnapshot === void 0 ? void 0 : baseSnapshot.trees[exports.gcTreeKey]) !== undefined;
|
|
235
|
+
this.initialStateNeedsReset = gcTreePresent !== this.shouldRunGC;
|
|
236
|
+
}
|
|
249
237
|
// Get the GC state from the GC blob in the base snapshot. Use LazyPromise because we only want to do
|
|
250
238
|
// this once since it involves fetching blobs from storage which is expensive.
|
|
251
239
|
const baseSummaryStateP = new common_utils_1.LazyPromise(async () => {
|
|
@@ -334,7 +322,7 @@ class GarbageCollector {
|
|
|
334
322
|
// Run GC on the nodes in the base summary to get the routes used in each node in the container.
|
|
335
323
|
// This is an optimization for space (vs performance) wherein we don't need to store the used routes of
|
|
336
324
|
// each node in the summary.
|
|
337
|
-
const usedRoutes = (0, garbage_collector_1.runGarbageCollection)(gcNodes, ["/"]
|
|
325
|
+
const usedRoutes = (0, garbage_collector_1.runGarbageCollection)(gcNodes, ["/"]).referencedNodeIds;
|
|
338
326
|
const baseGCDetailsMap = (0, garbage_collector_1.unpackChildNodesGCDetails)({ gcData: { gcNodes }, usedRoutes });
|
|
339
327
|
// Currently, the nodes may write the GC data. So, we need to update it's base GC details with the
|
|
340
328
|
// unreferenced timestamp. Once we start writing the GC data here, we won't need to do this anymore.
|
|
@@ -350,7 +338,7 @@ class GarbageCollector {
|
|
|
350
338
|
});
|
|
351
339
|
// Log all the GC options and the state determined by the garbage collector. This is interesting only for the
|
|
352
340
|
// summarizer client since it is the only one that runs GC. It also helps keep the telemetry less noisy.
|
|
353
|
-
const gcConfigProps = JSON.stringify(Object.assign({ gcEnabled: this.gcEnabled, sweepEnabled: this.sweepEnabled, runGC: this.shouldRunGC, runSweep: this.shouldRunSweep, writeAtRoot: this._writeDataAtRoot, testMode: this.testMode, sessionExpiry: this.sessionExpiryTimeoutMs, inactiveTimeout: this.inactiveTimeoutMs, existing }, this.gcOptions));
|
|
341
|
+
const gcConfigProps = JSON.stringify(Object.assign({ gcEnabled: this.gcEnabled, sweepEnabled: this.sweepEnabled, runGC: this.shouldRunGC, runSweep: this.shouldRunSweep, writeAtRoot: this._writeDataAtRoot, testMode: this.testMode, sessionExpiry: this.sessionExpiryTimeoutMs, inactiveTimeout: this.inactiveTimeoutMs, existing: createParams.existing }, this.gcOptions));
|
|
354
342
|
if (this.isSummarizerClient) {
|
|
355
343
|
this.mc.logger.sendTelemetryEvent({
|
|
356
344
|
eventName: "GarbageCollectorLoaded",
|
|
@@ -366,8 +354,8 @@ class GarbageCollector {
|
|
|
366
354
|
});
|
|
367
355
|
}
|
|
368
356
|
}
|
|
369
|
-
static create(
|
|
370
|
-
return new GarbageCollector(
|
|
357
|
+
static create(createParams) {
|
|
358
|
+
return new GarbageCollector(createParams);
|
|
371
359
|
}
|
|
372
360
|
/**
|
|
373
361
|
* Tells whether the GC state needs to be reset in the next summary. We need to do this if:
|
|
@@ -399,7 +387,7 @@ class GarbageCollector {
|
|
|
399
387
|
await this.runtime.updateStateBeforeGC();
|
|
400
388
|
// Get the runtime's GC data and run GC on the reference graph in it.
|
|
401
389
|
const gcData = await this.runtime.getGCData(fullGC);
|
|
402
|
-
const gcResult = (0, garbage_collector_1.runGarbageCollection)(gcData.gcNodes, ["/"]
|
|
390
|
+
const gcResult = (0, garbage_collector_1.runGarbageCollection)(gcData.gcNodes, ["/"]);
|
|
403
391
|
const gcStats = this.generateStatsAndLogEvents(gcResult, logger);
|
|
404
392
|
// Update the state since the last GC run. There can be nodes that were referenced between the last and
|
|
405
393
|
// the current run. We need to identify than and update their unreferenced state if needed.
|
|
@@ -488,9 +476,6 @@ class GarbageCollector {
|
|
|
488
476
|
* latest summary tracked.
|
|
489
477
|
*/
|
|
490
478
|
async latestSummaryStateRefreshed(result, readAndParseBlob) {
|
|
491
|
-
// After a summary is successfully submitted and ack'd by this client, the GC state should have been reset in
|
|
492
|
-
// the summary and doesn't need to be reset anymore.
|
|
493
|
-
this.initialStateNeedsReset = false;
|
|
494
479
|
if (!this.shouldRunGC || !result.latestSummaryUpdated) {
|
|
495
480
|
return;
|
|
496
481
|
}
|
|
@@ -498,6 +483,7 @@ class GarbageCollector {
|
|
|
498
483
|
// Basically, it was written in the current GC version.
|
|
499
484
|
if (result.wasSummaryTracked) {
|
|
500
485
|
this.latestSummaryGCVersion = this.currentGCVersion;
|
|
486
|
+
this.initialStateNeedsReset = false;
|
|
501
487
|
if (this.trackGCState) {
|
|
502
488
|
this.latestSerializedSummaryState = this.pendingSerializedSummaryState;
|
|
503
489
|
this.pendingSerializedSummaryState = undefined;
|
|
@@ -620,10 +606,7 @@ class GarbageCollector {
|
|
|
620
606
|
}
|
|
621
607
|
// Find any references that haven't been identified correctly.
|
|
622
608
|
const missingExplicitReferences = this.findMissingExplicitReferences(currentGCData, this.previousGCDataFromLastRun, this.newReferencesSinceLastRun);
|
|
623
|
-
|
|
624
|
-
// https://github.com/microsoft/FluidFramework/issues/8878.
|
|
625
|
-
if (this.mc.config.getBoolean(exports.logUnknownOutboundReferencesKey) === true
|
|
626
|
-
&& missingExplicitReferences.length > 0) {
|
|
609
|
+
if (this.writeDataAtRoot && missingExplicitReferences.length > 0) {
|
|
627
610
|
missingExplicitReferences.forEach((missingExplicitReference) => {
|
|
628
611
|
const event = {
|
|
629
612
|
eventName: "gcUnknownOutboundReferences",
|
|
@@ -667,7 +650,7 @@ class GarbageCollector {
|
|
|
667
650
|
* unreferenced, stop tracking them and remove from unreferenced list.
|
|
668
651
|
* Some of these nodes may be unreferenced now and if so, the current run will add unreferenced state for them.
|
|
669
652
|
*/
|
|
670
|
-
const gcResult = (0, garbage_collector_1.runGarbageCollection)(gcDataSuperSet.gcNodes, ["/"]
|
|
653
|
+
const gcResult = (0, garbage_collector_1.runGarbageCollection)(gcDataSuperSet.gcNodes, ["/"]);
|
|
671
654
|
for (const nodeId of gcResult.referencedNodeIds) {
|
|
672
655
|
const nodeStateTracker = this.unreferencedNodesState.get(nodeId);
|
|
673
656
|
if (nodeStateTracker !== undefined) {
|
|
@@ -747,11 +730,10 @@ class GarbageCollector {
|
|
|
747
730
|
};
|
|
748
731
|
const updateNodeStats = (nodeId, referenced) => {
|
|
749
732
|
gcStats.nodeCount++;
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
const stateUpdated = this.unreferencedNodesState.has(nodeId) ? referenced : !referenced;
|
|
733
|
+
// If there is no previous GC data, every node's state is generated and is considered as updated.
|
|
734
|
+
// Otherwise, find out if any node went from referenced to unreferenced or vice-versa.
|
|
735
|
+
const stateUpdated = this.previousGCDataFromLastRun === undefined ||
|
|
736
|
+
this.unreferencedNodesState.has(nodeId) === referenced;
|
|
755
737
|
if (stateUpdated) {
|
|
756
738
|
gcStats.updatedNodeCount++;
|
|
757
739
|
}
|
|
@@ -827,7 +809,7 @@ class GarbageCollector {
|
|
|
827
809
|
// next time GC runs as the package data should be available then.
|
|
828
810
|
const pkg = packagePath !== null && packagePath !== void 0 ? packagePath : this.getNodePackagePath(nodeId);
|
|
829
811
|
if (pkg !== undefined) {
|
|
830
|
-
this.mc.logger.sendErrorEvent(Object.assign(Object.assign({}, event), { pkg: { value:
|
|
812
|
+
this.mc.logger.sendErrorEvent(Object.assign(Object.assign({}, event), { pkg: { value: pkg.join("/"), tag: telemetry_utils_1.TelemetryDataTag.PackageData } }));
|
|
831
813
|
}
|
|
832
814
|
else {
|
|
833
815
|
this.pendingEventsQueue.push(event);
|
|
@@ -887,63 +869,4 @@ function setLongTimeout(timeoutMs, timeoutFn, setTimerFn) {
|
|
|
887
869
|
}
|
|
888
870
|
setTimerFn(timer);
|
|
889
871
|
}
|
|
890
|
-
/**
|
|
891
|
-
* meetsMinimumVersionRequirement is used determining if a feature version should be run. This is similar to feature
|
|
892
|
-
* flags. The advantage of this is that if we ship a bug in version 0.1.1 and fix it in version 0.2.1. We can keep this
|
|
893
|
-
* feature disabled for version 0.1.1 and enabled for 0.2.1. Older versions will run without the feature and new
|
|
894
|
-
* versions will run with the feature.
|
|
895
|
-
* @param currentVersion - the total time the timeout needs to last in ms
|
|
896
|
-
* @param minimumVersion - the function to execute when the timer ends
|
|
897
|
-
*/
|
|
898
|
-
function meetsMinimumVersionRequirement(currentVersion, minimumVersion) {
|
|
899
|
-
return minimumVersion === undefined || semverCompare(currentVersion, minimumVersion) >= 0;
|
|
900
|
-
}
|
|
901
|
-
/**
|
|
902
|
-
* Compare semver versions.
|
|
903
|
-
* @param currentVersion - assumed to be any valid semver version
|
|
904
|
-
* @param minimumVersion - must be [major].[minor].[patch], where major, minor, and patch are all numbers
|
|
905
|
-
* as it complicates the algorithm if we allow comparisons against minimum pre-release versions.
|
|
906
|
-
* @returns
|
|
907
|
-
* 0 if the currentVersion equals the minimumVersion
|
|
908
|
-
* 1 if the currentVersion is greater than the minimumVersion
|
|
909
|
-
* -1 if the minimumVersion is greater than the currentVersion
|
|
910
|
-
*/
|
|
911
|
-
function semverCompare(currentVersion, minimumVersion) {
|
|
912
|
-
const minimumValues = minimumVersion.split(".").map((value) => {
|
|
913
|
-
(0, common_utils_1.assert)(isNaN(+value) === false, 0x2f8 /* Expected real numbers in minimum version! */);
|
|
914
|
-
return Number.parseInt(value, 10);
|
|
915
|
-
});
|
|
916
|
-
(0, common_utils_1.assert)(minimumValues.length === 3, 0x2f9 /* Expected minimumVersion to be [major].[minor].[patch] */);
|
|
917
|
-
const [minMajor, minMinor, minPatch] = minimumValues;
|
|
918
|
-
const currentValuesString = currentVersion.split(/\W/);
|
|
919
|
-
(0, common_utils_1.assert)(currentValuesString.length >= 3, 0x2fa /* Expected version to match semver rules! */);
|
|
920
|
-
const currentValues = currentValuesString.slice(0, 3).map((value) => {
|
|
921
|
-
(0, common_utils_1.assert)(isNaN(+value) === false, 0x2fb /* Expected real numbers in minimum version! */);
|
|
922
|
-
return Number.parseInt(value, 10);
|
|
923
|
-
});
|
|
924
|
-
const [cMajor, cMinor, cPatch] = currentValues;
|
|
925
|
-
if (cMajor > minMajor) {
|
|
926
|
-
return 1;
|
|
927
|
-
}
|
|
928
|
-
else if (minMajor > cMajor) {
|
|
929
|
-
return -1;
|
|
930
|
-
}
|
|
931
|
-
if (cMinor > minMinor) {
|
|
932
|
-
return 1;
|
|
933
|
-
}
|
|
934
|
-
else if (minMinor > cMinor) {
|
|
935
|
-
return -1;
|
|
936
|
-
}
|
|
937
|
-
if (cPatch > minPatch) {
|
|
938
|
-
return 1;
|
|
939
|
-
}
|
|
940
|
-
else if (minPatch > cPatch) {
|
|
941
|
-
return -1;
|
|
942
|
-
}
|
|
943
|
-
if (currentValuesString.length === 3) {
|
|
944
|
-
return 0;
|
|
945
|
-
}
|
|
946
|
-
return -1;
|
|
947
|
-
}
|
|
948
|
-
exports.semverCompare = semverCompare;
|
|
949
872
|
//# sourceMappingURL=garbageCollection.js.map
|