@fluidframework/container-runtime 2.0.0-internal.2.3.1 → 2.0.0-internal.3.0.0
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/blobManager.d.ts +3 -1
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +35 -2
- package/dist/blobManager.js.map +1 -1
- package/dist/containerRuntime.d.ts +45 -42
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +89 -40
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +1 -0
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +7 -2
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/garbageCollection.d.ts +15 -7
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +96 -36
- package/dist/garbageCollection.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +0 -1
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +4 -13
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +130 -160
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/summarizer.js.map +1 -1
- package/dist/summarizerClientElection.d.ts +1 -2
- package/dist/summarizerClientElection.d.ts.map +1 -1
- package/dist/summarizerClientElection.js +3 -30
- package/dist/summarizerClientElection.js.map +1 -1
- package/dist/summarizerTypes.d.ts +0 -4
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/lib/blobManager.d.ts +3 -1
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +35 -2
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +45 -42
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +89 -40
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +1 -0
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +7 -2
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/garbageCollection.d.ts +15 -7
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +97 -37
- package/lib/garbageCollection.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +0 -1
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +4 -13
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +130 -160
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/summarizer.js.map +1 -1
- package/lib/summarizerClientElection.d.ts +1 -2
- package/lib/summarizerClientElection.d.ts.map +1 -1
- package/lib/summarizerClientElection.js +3 -30
- package/lib/summarizerClientElection.js.map +1 -1
- package/lib/summarizerTypes.d.ts +0 -4
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/package.json +55 -20
- package/src/blobManager.ts +41 -2
- package/src/containerRuntime.ts +118 -85
- package/src/dataStoreContext.ts +12 -6
- package/src/garbageCollection.ts +103 -34
- package/src/opLifecycle/outbox.ts +0 -2
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +146 -187
- package/src/summarizer.ts +1 -1
- package/src/summarizerClientElection.ts +1 -30
- package/src/summarizerTypes.ts +0 -4
package/dist/containerRuntime.js
CHANGED
|
@@ -58,7 +58,6 @@ exports.DefaultSummaryConfiguration = {
|
|
|
58
58
|
maxAckWaitTime: 10 * 60 * 1000,
|
|
59
59
|
maxOpsSinceLastSummary: 7000,
|
|
60
60
|
initialSummarizerDelayMs: 5 * 1000,
|
|
61
|
-
summarizerClientElection: false,
|
|
62
61
|
nonRuntimeOpWeight: 0.1,
|
|
63
62
|
runtimeOpWeight: 1.0,
|
|
64
63
|
nonRuntimeHeuristicThreshold: 20,
|
|
@@ -169,6 +168,14 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
169
168
|
this.flushMicroTaskExists = false;
|
|
170
169
|
this.savedOps = [];
|
|
171
170
|
this.consecutiveReconnects = 0;
|
|
171
|
+
this.ensureNoDataModelChangesCalls = 0;
|
|
172
|
+
/**
|
|
173
|
+
* Tracks the number of detected reentrant ops to report,
|
|
174
|
+
* in order to self-throttle the telemetry events.
|
|
175
|
+
*
|
|
176
|
+
* This should be removed as part of ADO:2322
|
|
177
|
+
*/
|
|
178
|
+
this.opReentryCallsToReport = 5;
|
|
172
179
|
this._disposed = false;
|
|
173
180
|
this.emitDirtyDocumentEvent = true;
|
|
174
181
|
this.defaultTelemetrySignalSampleCount = 100;
|
|
@@ -241,7 +248,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
241
248
|
&& this.mc.config.getBoolean("Fluid.ContainerRuntime.DisableOpReentryCheck") !== true;
|
|
242
249
|
this.summariesDisabled = this.isSummariesDisabled();
|
|
243
250
|
this.heuristicsDisabled = this.isHeuristicsDisabled();
|
|
244
|
-
this.summarizerClientElectionEnabled = this.isSummarizerClientElectionEnabled();
|
|
245
251
|
this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
|
|
246
252
|
this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
|
|
247
253
|
this.maxConsecutiveReconnects =
|
|
@@ -300,14 +306,13 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
300
306
|
if (!this.disposed) {
|
|
301
307
|
this.submit(ContainerMessageType.BlobAttach, undefined, undefined, { localId, blobId });
|
|
302
308
|
}
|
|
303
|
-
}, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), (fromPath, toPath) => this.garbageCollector.addedOutboundReference(fromPath, toPath), this, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pendingAttachmentBlobs);
|
|
309
|
+
}, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), (fromPath, toPath) => this.garbageCollector.addedOutboundReference(fromPath, toPath), this, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pendingAttachmentBlobs, () => this.getCurrentReferenceTimestampMs());
|
|
304
310
|
this.scheduleManager = new scheduleManager_1.ScheduleManager(context.deltaManager, this, () => this.clientId, telemetry_utils_1.ChildLogger.create(this.logger, "ScheduleManager"));
|
|
305
311
|
this.pendingStateManager = new pendingStateManager_1.PendingStateManager({
|
|
306
312
|
applyStashedOp: this.applyStashedOp.bind(this),
|
|
307
313
|
clientId: () => this.clientId,
|
|
308
314
|
close: this.closeFn,
|
|
309
315
|
connected: () => this.connected,
|
|
310
|
-
flush: this.flush.bind(this),
|
|
311
316
|
reSubmit: this.reSubmit.bind(this),
|
|
312
317
|
rollback: this.rollback.bind(this),
|
|
313
318
|
orderSequentially: this.orderSequentially.bind(this),
|
|
@@ -344,7 +349,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
344
349
|
const orderedClientLogger = telemetry_utils_1.ChildLogger.create(this.logger, "OrderedClientElection");
|
|
345
350
|
const orderedClientCollection = new orderedClientElection_1.OrderedClientCollection(orderedClientLogger, this.context.deltaManager, this.context.quorum);
|
|
346
351
|
const orderedClientElectionForSummarizer = new orderedClientElection_1.OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData !== null && electedSummarizerData !== void 0 ? electedSummarizerData : this.context.deltaManager.lastSequenceNumber, summarizerClientElection_1.SummarizerClientElection.isClientEligible);
|
|
347
|
-
this.summarizerClientElection = new summarizerClientElection_1.SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, this.maxOpsSinceLastSummary
|
|
352
|
+
this.summarizerClientElection = new summarizerClientElection_1.SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, this.maxOpsSinceLastSummary);
|
|
348
353
|
if (this.context.clientDetails.type === summarizerClientElection_1.summarizerClientType) {
|
|
349
354
|
this._summarizer = new summarizer_1.Summarizer("/_summarizer", this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => runWhileConnectedCoordinator_1.RunWhileConnectedCoordinator.create(runtime));
|
|
350
355
|
}
|
|
@@ -406,6 +411,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
406
411
|
get IContainerRuntime() { return this; }
|
|
407
412
|
get IFluidRouter() { return this; }
|
|
408
413
|
/**
|
|
414
|
+
* @deprecated - use loadRuntime instead.
|
|
409
415
|
* Load the stores from a snapshot and returns the runtime.
|
|
410
416
|
* @param context - Context of the container.
|
|
411
417
|
* @param registryEntries - Mapping to the stores.
|
|
@@ -416,7 +422,35 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
416
422
|
* allows mixin classes to leverage this method to define their own async initializer.
|
|
417
423
|
*/
|
|
418
424
|
static async load(context, registryEntries, requestHandler, runtimeOptions = {}, containerScope = context.scope, existing, containerRuntimeCtor = ContainerRuntime) {
|
|
425
|
+
let existingFlag = true;
|
|
426
|
+
if (!existing) {
|
|
427
|
+
existingFlag = false;
|
|
428
|
+
}
|
|
429
|
+
return this.loadRuntime({
|
|
430
|
+
context,
|
|
431
|
+
registryEntries,
|
|
432
|
+
existing: existingFlag,
|
|
433
|
+
requestHandler,
|
|
434
|
+
runtimeOptions,
|
|
435
|
+
containerScope,
|
|
436
|
+
containerRuntimeCtor,
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Load the stores from a snapshot and returns the runtime.
|
|
441
|
+
* @param params - An object housing the runtime properties:
|
|
442
|
+
* - context - Context of the container.
|
|
443
|
+
* - registryEntries - Mapping to the stores.
|
|
444
|
+
* - existing - When loading from an existing snapshot
|
|
445
|
+
* - requestHandler - Request handlers for the container runtime
|
|
446
|
+
* - runtimeOptions - Additional options to be passed to the runtime
|
|
447
|
+
* - containerScope - runtime services provided with context
|
|
448
|
+
* - containerRuntimeCtor - Constructor to use to create the ContainerRuntime instance.
|
|
449
|
+
* This allows mixin classes to leverage this method to define their own async initializer.
|
|
450
|
+
*/
|
|
451
|
+
static async loadRuntime(params) {
|
|
419
452
|
var _a, _b, _c, _d;
|
|
453
|
+
const { context, registryEntries, existing, requestHandler, runtimeOptions = {}, containerScope = {}, containerRuntimeCtor = ContainerRuntime } = params;
|
|
420
454
|
// If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
|
|
421
455
|
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
422
456
|
const backCompatContext = context;
|
|
@@ -474,7 +508,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
474
508
|
logger.sendErrorEvent({ eventName: "SequenceNumberMismatch" }, error);
|
|
475
509
|
}
|
|
476
510
|
else {
|
|
477
|
-
// Call both close and dispose as
|
|
511
|
+
// Call both close and dispose as closeFn implementation will no longer dispose runtime in future
|
|
478
512
|
context.closeFn(error);
|
|
479
513
|
(_d = context.disposeFn) === null || _d === void 0 ? void 0 : _d.call(context, error);
|
|
480
514
|
}
|
|
@@ -547,6 +581,23 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
547
581
|
get IFluidHandleContext() {
|
|
548
582
|
return this.handleContext;
|
|
549
583
|
}
|
|
584
|
+
/**
|
|
585
|
+
* Invokes the given callback and expects that no ops are submitted
|
|
586
|
+
* until execution finishes. If an op is submitted, an error will be raised.
|
|
587
|
+
*
|
|
588
|
+
* Can be disabled by feature gate `Fluid.ContainerRuntime.DisableOpReentryCheck`
|
|
589
|
+
*
|
|
590
|
+
* @param callback - the callback to be invoked
|
|
591
|
+
*/
|
|
592
|
+
ensureNoDataModelChanges(callback) {
|
|
593
|
+
this.ensureNoDataModelChangesCalls++;
|
|
594
|
+
try {
|
|
595
|
+
return callback();
|
|
596
|
+
}
|
|
597
|
+
finally {
|
|
598
|
+
this.ensureNoDataModelChangesCalls--;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
550
601
|
get connected() {
|
|
551
602
|
return this._connected;
|
|
552
603
|
}
|
|
@@ -561,42 +612,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
561
612
|
return this._summarizer;
|
|
562
613
|
}
|
|
563
614
|
isSummariesDisabled() {
|
|
564
|
-
// back-compat: disableSummaries was moved from ISummaryRuntimeOptions
|
|
565
|
-
// to ISummaryConfiguration in 0.60.
|
|
566
|
-
if (this.runtimeOptions.summaryOptions.disableSummaries === true) {
|
|
567
|
-
return true;
|
|
568
|
-
}
|
|
569
615
|
return this.summaryConfiguration.state === "disabled";
|
|
570
616
|
}
|
|
571
617
|
isHeuristicsDisabled() {
|
|
572
|
-
var _a;
|
|
573
|
-
// back-compat: disableHeuristics was moved from ISummarizerOptions
|
|
574
|
-
// to ISummaryConfiguration in 0.60.
|
|
575
|
-
if (((_a = this.runtimeOptions.summaryOptions.summarizerOptions) === null || _a === void 0 ? void 0 : _a.disableHeuristics) === true) {
|
|
576
|
-
return true;
|
|
577
|
-
}
|
|
578
618
|
return this.summaryConfiguration.state === "disableHeuristics";
|
|
579
619
|
}
|
|
580
|
-
isSummarizerClientElectionEnabled() {
|
|
581
|
-
var _a;
|
|
582
|
-
if (this.mc.config.getBoolean("Fluid.ContainerRuntime.summarizerClientElection")) {
|
|
583
|
-
return (_a = this.mc.config.getBoolean("Fluid.ContainerRuntime.summarizerClientElection")) !== null && _a !== void 0 ? _a : true;
|
|
584
|
-
}
|
|
585
|
-
// back-compat: summarizerClientElection was moved from ISummaryRuntimeOptions
|
|
586
|
-
// to ISummaryConfiguration in 0.60.
|
|
587
|
-
if (this.runtimeOptions.summaryOptions.summarizerClientElection === true) {
|
|
588
|
-
return true;
|
|
589
|
-
}
|
|
590
|
-
return this.summaryConfiguration.state !== "disabled"
|
|
591
|
-
? this.summaryConfiguration.summarizerClientElection === true
|
|
592
|
-
: false;
|
|
593
|
-
}
|
|
594
620
|
getMaxOpsSinceLastSummary() {
|
|
595
|
-
// back-compat: maxOpsSinceLastSummary was moved from ISummaryRuntimeOptions
|
|
596
|
-
// to ISummaryConfiguration in 0.60.
|
|
597
|
-
if (this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary !== undefined) {
|
|
598
|
-
return this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary;
|
|
599
|
-
}
|
|
600
621
|
return this.summaryConfiguration.state !== "disabled"
|
|
601
622
|
? this.summaryConfiguration.maxOpsSinceLastSummary
|
|
602
623
|
: 0;
|
|
@@ -1097,7 +1118,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1097
1118
|
finally {
|
|
1098
1119
|
this._orderSequentiallyCalls--;
|
|
1099
1120
|
}
|
|
1100
|
-
|
|
1121
|
+
// We don't flush on TurnBased since we expect all messages in the same JS turn to be part of the same batch
|
|
1122
|
+
if (this.flushMode !== runtime_definitions_1.FlushMode.TurnBased && this._orderSequentiallyCalls === 0) {
|
|
1101
1123
|
this.flush();
|
|
1102
1124
|
}
|
|
1103
1125
|
return result;
|
|
@@ -1621,6 +1643,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1621
1643
|
}
|
|
1622
1644
|
submit(type, contents, localOpMetadata = undefined, metadata = undefined) {
|
|
1623
1645
|
this.verifyNotClosed();
|
|
1646
|
+
this.verifyCanSubmitOps();
|
|
1624
1647
|
// There should be no ops in detached container state!
|
|
1625
1648
|
(0, common_utils_1.assert)(this.attachState !== container_definitions_1.AttachState.Detached, 0x132 /* "sending ops in detached container" */);
|
|
1626
1649
|
const deserializedContent = { type, contents };
|
|
@@ -1702,6 +1725,32 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1702
1725
|
throw new Error("Runtime is closed");
|
|
1703
1726
|
}
|
|
1704
1727
|
}
|
|
1728
|
+
verifyCanSubmitOps() {
|
|
1729
|
+
if (this.ensureNoDataModelChangesCalls > 0) {
|
|
1730
|
+
const errorMessage = "Op was submitted from within a `ensureNoDataModelChanges` callback";
|
|
1731
|
+
if (this.opReentryCallsToReport > 0) {
|
|
1732
|
+
this.mc.logger.sendTelemetryEvent({ eventName: "OpReentry" },
|
|
1733
|
+
// We need to capture the call stack in order to inspect the source of this usage pattern
|
|
1734
|
+
new container_utils_1.UsageError(errorMessage));
|
|
1735
|
+
this.opReentryCallsToReport--;
|
|
1736
|
+
}
|
|
1737
|
+
// Creating ops while processing ops can lead
|
|
1738
|
+
// to undefined behavior and events observed in the wrong order.
|
|
1739
|
+
// For example, we have two callbacks registered for a DDS, A and B.
|
|
1740
|
+
// Then if on change #1 callback A creates change #2, the invocation flow will be:
|
|
1741
|
+
//
|
|
1742
|
+
// A because of #1
|
|
1743
|
+
// A because of #2
|
|
1744
|
+
// B because of #2
|
|
1745
|
+
// B because of #1
|
|
1746
|
+
//
|
|
1747
|
+
// The runtime must enforce op coherence by not allowing ops to be submitted
|
|
1748
|
+
// while ops are being processed.
|
|
1749
|
+
if (this.enableOpReentryCheck) {
|
|
1750
|
+
throw new container_utils_1.UsageError(errorMessage);
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1705
1754
|
/**
|
|
1706
1755
|
* Finds the right store and asks it to resubmit the message. This typically happens when we
|
|
1707
1756
|
* reconnect and there are pending messages.
|
|
@@ -1854,13 +1903,13 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1854
1903
|
if (!((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad)) {
|
|
1855
1904
|
throw new container_utils_1.UsageError("can't get state when offline load disabled");
|
|
1856
1905
|
}
|
|
1906
|
+
if (this._orderSequentiallyCalls !== 0) {
|
|
1907
|
+
throw new container_utils_1.UsageError("can't get state during orderSequentially");
|
|
1908
|
+
}
|
|
1857
1909
|
// Flush pending batch.
|
|
1858
1910
|
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
1859
1911
|
// to close current batch.
|
|
1860
1912
|
this.flush();
|
|
1861
|
-
if (this._orderSequentiallyCalls !== 0) {
|
|
1862
|
-
throw new container_utils_1.UsageError("can't get state during orderSequentially");
|
|
1863
|
-
}
|
|
1864
1913
|
const previousPendingState = this.context.pendingLocalState;
|
|
1865
1914
|
if (previousPendingState) {
|
|
1866
1915
|
return {
|