@fluidframework/container-runtime 0.59.4000 → 1.0.1
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/.eslintrc.js +1 -1
- package/dist/blobManager.d.ts +2 -2
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +12 -11
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.js +3 -3
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +125 -29
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +242 -110
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +4 -2
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +16 -5
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +4 -3
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +9 -3
- package/dist/dataStores.js.map +1 -1
- package/dist/garbageCollection.d.ts +14 -3
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +56 -26
- package/dist/garbageCollection.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/orderedClientElection.js +0 -4
- package/dist/orderedClientElection.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/dist/pendingStateManager.d.ts +30 -29
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +72 -109
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/runningSummarizer.d.ts +4 -3
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +11 -6
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/serializedSnapshotStorage.d.ts +58 -0
- package/dist/serializedSnapshotStorage.d.ts.map +1 -0
- package/dist/serializedSnapshotStorage.js +108 -0
- package/dist/serializedSnapshotStorage.js.map +1 -0
- package/dist/summarizer.d.ts +11 -4
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +18 -9
- package/dist/summarizer.js.map +1 -1
- package/dist/summarizerHeuristics.d.ts +5 -3
- package/dist/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summarizerHeuristics.js +10 -3
- package/dist/summarizerHeuristics.js.map +1 -1
- package/dist/summarizerTypes.d.ts +4 -2
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryManager.d.ts +3 -3
- package/dist/summaryManager.d.ts.map +1 -1
- package/dist/summaryManager.js +7 -7
- package/dist/summaryManager.js.map +1 -1
- package/garbageCollection.md +9 -1
- package/lib/blobManager.d.ts +2 -2
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +12 -11
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.js +3 -3
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +125 -29
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +243 -111
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +4 -2
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +16 -5
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +4 -3
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +9 -3
- package/lib/dataStores.js.map +1 -1
- package/lib/garbageCollection.d.ts +14 -3
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +54 -6
- package/lib/garbageCollection.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/orderedClientElection.js +0 -4
- package/lib/orderedClientElection.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/lib/pendingStateManager.d.ts +30 -29
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +72 -109
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/runningSummarizer.d.ts +4 -3
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +11 -6
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/serializedSnapshotStorage.d.ts +58 -0
- package/lib/serializedSnapshotStorage.d.ts.map +1 -0
- package/lib/serializedSnapshotStorage.js +104 -0
- package/lib/serializedSnapshotStorage.js.map +1 -0
- package/lib/summarizer.d.ts +11 -4
- package/lib/summarizer.d.ts.map +1 -1
- package/lib/summarizer.js +18 -9
- package/lib/summarizer.js.map +1 -1
- package/lib/summarizerHeuristics.d.ts +5 -3
- package/lib/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summarizerHeuristics.js +10 -3
- package/lib/summarizerHeuristics.js.map +1 -1
- package/lib/summarizerTypes.d.ts +4 -2
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryManager.d.ts +3 -3
- package/lib/summaryManager.d.ts.map +1 -1
- package/lib/summaryManager.js +7 -7
- package/lib/summaryManager.js.map +1 -1
- package/package.json +45 -31
- package/src/blobManager.ts +29 -15
- package/src/connectionTelemetry.ts +3 -3
- package/src/containerRuntime.ts +388 -135
- package/src/dataStoreContext.ts +27 -5
- package/src/dataStores.ts +15 -3
- package/src/garbageCollection.ts +69 -12
- package/src/index.ts +7 -1
- package/src/orderedClientElection.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +104 -123
- package/src/runningSummarizer.ts +20 -10
- package/src/serializedSnapshotStorage.ts +146 -0
- package/src/summarizer.ts +20 -16
- package/src/summarizerHeuristics.ts +21 -5
- package/src/summarizerTypes.ts +4 -2
- package/src/summaryManager.ts +5 -6
package/dist/containerRuntime.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ContainerRuntime = exports.getDeviceSpec = exports.agentSchedulerId = exports.ScheduleManager = exports.unpackRuntimeMessage = exports.isRuntimeMessage = exports.RuntimeMessage = exports.RuntimeHeaders = exports.ContainerMessageType = void 0;
|
|
3
|
+
exports.ContainerRuntime = exports.getDeviceSpec = exports.agentSchedulerId = exports.ScheduleManager = exports.unpackRuntimeMessage = exports.isRuntimeMessage = exports.RuntimeMessage = exports.RuntimeHeaders = exports.DefaultSummaryConfiguration = exports.ContainerMessageType = void 0;
|
|
4
4
|
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
5
5
|
const common_utils_1 = require("@fluidframework/common-utils");
|
|
6
6
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
@@ -31,6 +31,7 @@ const runWhileConnectedCoordinator_1 = require("./runWhileConnectedCoordinator")
|
|
|
31
31
|
const garbageCollection_1 = require("./garbageCollection");
|
|
32
32
|
const dataStore_1 = require("./dataStore");
|
|
33
33
|
const batchTracker_1 = require("./batchTracker");
|
|
34
|
+
const serializedSnapshotStorage_1 = require("./serializedSnapshotStorage");
|
|
34
35
|
const opTelemetry_1 = require("./opTelemetry");
|
|
35
36
|
var ContainerMessageType;
|
|
36
37
|
(function (ContainerMessageType) {
|
|
@@ -47,17 +48,16 @@ var ContainerMessageType;
|
|
|
47
48
|
// Sets the alias of a root data store
|
|
48
49
|
ContainerMessageType["Alias"] = "alias";
|
|
49
50
|
})(ContainerMessageType = exports.ContainerMessageType || (exports.ContainerMessageType = {}));
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
maxAckWaitTime: 600000,
|
|
51
|
+
exports.DefaultSummaryConfiguration = {
|
|
52
|
+
state: "enabled",
|
|
53
|
+
idleTime: 5000 * 3,
|
|
54
|
+
maxTime: 5000 * 12,
|
|
55
|
+
maxOps: 100,
|
|
56
|
+
minOpsForLastSummaryAttempt: 10,
|
|
57
|
+
maxAckWaitTime: 6 * 10 * 1000,
|
|
58
|
+
maxOpsSinceLastSummary: 7000,
|
|
59
|
+
initialSummarizerDelayMs: 5000,
|
|
60
|
+
summarizerClientElection: false,
|
|
61
61
|
};
|
|
62
62
|
/**
|
|
63
63
|
* Accepted header keys for requests coming to the runtime.
|
|
@@ -379,44 +379,26 @@ exports.getDeviceSpec = getDeviceSpec;
|
|
|
379
379
|
* It will define the store level mappings.
|
|
380
380
|
*/
|
|
381
381
|
class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
382
|
-
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, requestHandler) {
|
|
383
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j
|
|
382
|
+
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, requestHandler, summaryConfiguration) {
|
|
383
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
384
|
+
if (summaryConfiguration === void 0) { summaryConfiguration = Object.assign(Object.assign({}, exports.DefaultSummaryConfiguration), (_a = runtimeOptions.summaryOptions) === null || _a === void 0 ? void 0 : _a.summaryConfigOverrides); }
|
|
384
385
|
super();
|
|
385
386
|
this.context = context;
|
|
386
387
|
this.registry = registry;
|
|
387
388
|
this.runtimeOptions = runtimeOptions;
|
|
388
389
|
this.containerScope = containerScope;
|
|
389
390
|
this.logger = logger;
|
|
391
|
+
this._storage = _storage;
|
|
390
392
|
this.requestHandler = requestHandler;
|
|
393
|
+
this.summaryConfiguration = summaryConfiguration;
|
|
391
394
|
this.defaultMaxConsecutiveReconnects = 15;
|
|
392
395
|
this._orderSequentiallyCalls = 0;
|
|
393
396
|
this.needsFlush = false;
|
|
394
397
|
this.flushTrigger = false;
|
|
395
|
-
this.
|
|
398
|
+
this.savedOps = [];
|
|
396
399
|
this.consecutiveReconnects = 0;
|
|
397
400
|
this._disposed = false;
|
|
398
401
|
this.emitDirtyDocumentEvent = true;
|
|
399
|
-
/**
|
|
400
|
-
* Used to apply stashed ops at their reference sequence number.
|
|
401
|
-
* Normal op processing is synchronous, but applying stashed ops is async since the
|
|
402
|
-
* data store may not be loaded yet, so we pause DeltaManager between ops.
|
|
403
|
-
* It's also important that we see each op so we know all stashed ops have
|
|
404
|
-
* been applied by "connected" event, but process() doesn't see system ops,
|
|
405
|
-
* so we listen directly from DeltaManager instead.
|
|
406
|
-
*/
|
|
407
|
-
this.onOp = (op) => {
|
|
408
|
-
(0, common_utils_1.assert)(!this.paused, 0x128 /* "Container should not already be paused before applying stashed ops" */);
|
|
409
|
-
this.paused = true;
|
|
410
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
411
|
-
this.context.deltaManager.inbound.pause();
|
|
412
|
-
const stashP = this.pendingStateManager.applyStashedOpsAt(op.sequenceNumber);
|
|
413
|
-
stashP.then(() => {
|
|
414
|
-
this.paused = false;
|
|
415
|
-
this.context.deltaManager.inbound.resume();
|
|
416
|
-
}, (error) => {
|
|
417
|
-
this.closeFn((0, telemetry_utils_1.normalizeError)(error));
|
|
418
|
-
});
|
|
419
|
-
};
|
|
420
402
|
this.summarizeOnDemand = (...args) => {
|
|
421
403
|
if (this.clientDetails.type === summarizerClientElection_1.summarizerClientType) {
|
|
422
404
|
return this.summarizer.summarizeOnDemand(...args);
|
|
@@ -447,27 +429,34 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
447
429
|
};
|
|
448
430
|
this.messageAtLastSummary = metadata === null || metadata === void 0 ? void 0 : metadata.message;
|
|
449
431
|
// Default to false (enabled).
|
|
450
|
-
this.disableIsolatedChannels = (
|
|
432
|
+
this.disableIsolatedChannels = (_b = this.runtimeOptions.summaryOptions.disableIsolatedChannels) !== null && _b !== void 0 ? _b : false;
|
|
451
433
|
this._connected = this.context.connected;
|
|
452
434
|
this.chunkMap = new Map(chunks);
|
|
453
435
|
this.handleContext = new containerHandleContext_1.ContainerFluidHandleContext("", this);
|
|
454
436
|
this.mc = (0, telemetry_utils_1.loggerToMonitoringContext)(telemetry_utils_1.ChildLogger.create(this.logger, "ContainerRuntime"));
|
|
437
|
+
this.summariesDisabled = this.isSummariesDisabled();
|
|
438
|
+
this.heuristicsDisabled = this.isHeuristicsDisabled();
|
|
439
|
+
this.summarizerClientElectionEnabled = this.isSummarizerClientElectionEnabled();
|
|
440
|
+
this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
|
|
441
|
+
this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
|
|
455
442
|
this._aliasingEnabled =
|
|
456
|
-
((
|
|
457
|
-
((
|
|
458
|
-
this._maxOpSizeInBytes = ((
|
|
443
|
+
((_c = this.mc.config.getBoolean(useDataStoreAliasingKey)) !== null && _c !== void 0 ? _c : false) ||
|
|
444
|
+
((_d = runtimeOptions.useDataStoreAliasing) !== null && _d !== void 0 ? _d : false);
|
|
445
|
+
this._maxOpSizeInBytes = ((_e = this.mc.config.getNumber(maxOpSizeInBytesKey)) !== null && _e !== void 0 ? _e : defaultMaxOpSizeInBytes);
|
|
459
446
|
this.maxConsecutiveReconnects =
|
|
460
|
-
(
|
|
447
|
+
(_f = this.mc.config.getNumber(maxConsecutiveReconnectsKey)) !== null && _f !== void 0 ? _f : this.defaultMaxConsecutiveReconnects;
|
|
461
448
|
this._flushMode = runtimeOptions.flushMode;
|
|
462
|
-
|
|
449
|
+
const pendingRuntimeState = context.pendingLocalState;
|
|
450
|
+
const baseSnapshot = (_g = pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.baseSnapshot) !== null && _g !== void 0 ? _g : context.baseSnapshot;
|
|
451
|
+
this.garbageCollector = garbageCollection_1.GarbageCollector.create(this, this.runtimeOptions.gcOptions, (nodePath) => this.getGCNodePackagePath(nodePath), () => { var _a; return (_a = this.messageAtLastSummary) === null || _a === void 0 ? void 0 : _a.timestamp; }, baseSnapshot, async (id) => (0, driver_utils_1.readAndParse)(this.storage, id), this.mc.logger, existing, metadata, this.context.clientDetails.type === summarizerClientElection_1.summarizerClientType);
|
|
463
452
|
const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
|
|
464
453
|
this.summarizerNode = (0, runtime_utils_1.createRootSummarizerNodeWithGC)(telemetry_utils_1.ChildLogger.create(this.logger, "SummarizerNode"),
|
|
465
454
|
// Summarize function to call when summarize is called. Summarizer node always tracks summary state.
|
|
466
|
-
async (fullTree, trackState) => this.summarizeInternal(fullTree, trackState),
|
|
455
|
+
async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext),
|
|
467
456
|
// Latest change sequence number, no changes since summary applied yet
|
|
468
457
|
loadedFromSequenceNumber,
|
|
469
458
|
// Summary reference sequence number, undefined if no summary yet
|
|
470
|
-
|
|
459
|
+
baseSnapshot ? loadedFromSequenceNumber : undefined, {
|
|
471
460
|
// Must set to false to prevent sending summary handle which would be pointing to
|
|
472
461
|
// a summary with an older protocol state.
|
|
473
462
|
canReuseHandle: false,
|
|
@@ -477,26 +466,31 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
477
466
|
// If GC should not run, let the summarizer node know so that it does not track GC state.
|
|
478
467
|
gcDisabled: !this.garbageCollector.shouldRunGC,
|
|
479
468
|
});
|
|
480
|
-
if (
|
|
481
|
-
this.summarizerNode.loadBaseSummaryWithoutDifferential(
|
|
469
|
+
if (baseSnapshot) {
|
|
470
|
+
this.summarizerNode.loadBaseSummaryWithoutDifferential(baseSnapshot);
|
|
482
471
|
}
|
|
483
|
-
this.dataStores = new dataStores_1.DataStores((0, dataStores_1.getSummaryForDatastores)(
|
|
472
|
+
this.dataStores = new dataStores_1.DataStores((0, dataStores_1.getSummaryForDatastores)(baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn, getBaseGCDetailsFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn, getBaseGCDetailsFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, async () => this.garbageCollector.getBaseGCDetails(), (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), new Map(dataStoreAliasMap), this.garbageCollector.writeDataAtRoot);
|
|
484
473
|
this.blobManager = new blobManager_1.BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (blobId) => this.submit(ContainerMessageType.BlobAttach, undefined, undefined, { blobId }), (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), this, this.logger);
|
|
485
474
|
this.scheduleManager = new ScheduleManager(context.deltaManager, this, telemetry_utils_1.ChildLogger.create(this.logger, "ScheduleManager"));
|
|
486
475
|
this.deltaSender = this.deltaManager;
|
|
487
|
-
this.pendingStateManager = new pendingStateManager_1.PendingStateManager(
|
|
476
|
+
this.pendingStateManager = new pendingStateManager_1.PendingStateManager({
|
|
477
|
+
applyStashedOp: this.applyStashedOp.bind(this),
|
|
478
|
+
clientId: () => this.clientId,
|
|
479
|
+
close: this.closeFn,
|
|
480
|
+
connected: () => this.connected,
|
|
481
|
+
flush: this.flush.bind(this),
|
|
482
|
+
flushMode: () => this.flushMode,
|
|
483
|
+
reSubmit: this.reSubmit.bind(this),
|
|
484
|
+
rollback: this.rollback.bind(this),
|
|
485
|
+
setFlushMode: (mode) => this.setFlushMode(mode),
|
|
486
|
+
}, this._flushMode, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pending);
|
|
488
487
|
this.context.quorum.on("removeMember", (clientId) => {
|
|
489
488
|
this.clearPartialChunks(clientId);
|
|
490
489
|
});
|
|
491
490
|
this.summaryCollection = new summaryCollection_1.SummaryCollection(this.deltaManager, this.logger);
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|| ((_f = pendingLocalState) === null || _f === void 0 ? void 0 : _f.pendingStates.length) > 0;
|
|
491
|
+
this.dirtyContainer = this.context.attachState !== container_definitions_1.AttachState.Attached
|
|
492
|
+
|| this.pendingStateManager.hasPendingMessages();
|
|
495
493
|
this.context.updateDirtyContainerState(this.dirtyContainer);
|
|
496
|
-
// Map the deprecated generateSummaries flag to disableSummaries.
|
|
497
|
-
if (this.runtimeOptions.summaryOptions.generateSummaries === false) {
|
|
498
|
-
this.runtimeOptions.summaryOptions.disableSummaries = true;
|
|
499
|
-
}
|
|
500
494
|
if (this.summariesDisabled) {
|
|
501
495
|
this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
|
|
502
496
|
}
|
|
@@ -504,9 +498,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
504
498
|
const orderedClientLogger = telemetry_utils_1.ChildLogger.create(this.logger, "OrderedClientElection");
|
|
505
499
|
const orderedClientCollection = new orderedClientElection_1.OrderedClientCollection(orderedClientLogger, this.context.deltaManager, this.context.quorum);
|
|
506
500
|
const orderedClientElectionForSummarizer = new orderedClientElection_1.OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData !== null && electedSummarizerData !== void 0 ? electedSummarizerData : this.context.deltaManager.lastSequenceNumber, summarizerClientElection_1.SummarizerClientElection.isClientEligible);
|
|
507
|
-
|
|
508
|
-
const maxOpsSinceLastSummary = (_j = this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary) !== null && _j !== void 0 ? _j : 7000;
|
|
509
|
-
this.summarizerClientElection = new summarizerClientElection_1.SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, maxOpsSinceLastSummary, summarizerClientElectionEnabled);
|
|
501
|
+
this.summarizerClientElection = new summarizerClientElection_1.SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, this.maxOpsSinceLastSummary, this.summarizerClientElectionEnabled);
|
|
510
502
|
if (this.context.clientDetails.type === summarizerClientElection_1.summarizerClientType) {
|
|
511
503
|
this._summarizer = new summarizer_1.Summarizer("/_summarizer", this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => runWhileConnectedCoordinator_1.RunWhileConnectedCoordinator.create(runtime));
|
|
512
504
|
}
|
|
@@ -514,7 +506,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
514
506
|
// Only create a SummaryManager and SummarizerClientElection
|
|
515
507
|
// if summaries are enabled and we are not the summarizer client.
|
|
516
508
|
const defaultAction = () => {
|
|
517
|
-
if (this.summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
|
|
509
|
+
if (this.summaryCollection.opsSinceLastAck > this.maxOpsSinceLastSummary) {
|
|
518
510
|
this.logger.sendErrorEvent({ eventName: "SummaryStatus:Behind" });
|
|
519
511
|
// unregister default to no log on every op after falling behind
|
|
520
512
|
// and register summary ack handler to re-register this handler
|
|
@@ -535,8 +527,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
535
527
|
30 * 1000, // 30 sec max delay
|
|
536
528
|
// throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
|
|
537
529
|
(0, throttler_1.formExponentialFn)({ coefficient: 20, initialDelay: 0 })), {
|
|
538
|
-
initialDelayMs: this.
|
|
539
|
-
}, this.
|
|
530
|
+
initialDelayMs: this.initialSummarizerDelayMs,
|
|
531
|
+
}, this.heuristicsDisabled);
|
|
540
532
|
this.summaryManager.start();
|
|
541
533
|
}
|
|
542
534
|
}
|
|
@@ -559,9 +551,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
559
551
|
(0, common_utils_1.assert)(!readonly || !this.connected, 0x125 /* "Unsafe to transition to read-only state!" */);
|
|
560
552
|
this.replayPendingStates();
|
|
561
553
|
});
|
|
562
|
-
if (context.pendingLocalState !== undefined) {
|
|
563
|
-
this.deltaManager.on("op", this.onOp);
|
|
564
|
-
}
|
|
565
554
|
// logging hardware telemetry
|
|
566
555
|
logger.sendTelemetryEvent(Object.assign({ eventName: "DeviceSpec" }, getDeviceSpec()));
|
|
567
556
|
let loadSummaryNumber;
|
|
@@ -574,7 +563,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
574
563
|
};
|
|
575
564
|
// back-compat 0.59.3000 - Older document may either write summaryCount or not write it at all. If it does
|
|
576
565
|
// not write it, initialize summaryNumber to 0.
|
|
577
|
-
loadSummaryNumber = (
|
|
566
|
+
loadSummaryNumber = (_j = (_h = metadata === null || metadata === void 0 ? void 0 : metadata.summaryNumber) !== null && _h !== void 0 ? _h : metadata === null || metadata === void 0 ? void 0 : metadata.summaryCount) !== null && _j !== void 0 ? _j : 0;
|
|
578
567
|
}
|
|
579
568
|
else {
|
|
580
569
|
this.createContainerMetadata = {
|
|
@@ -610,13 +599,16 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
610
599
|
runtimeVersion: packageVersion_1.pkgVersion,
|
|
611
600
|
},
|
|
612
601
|
});
|
|
613
|
-
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", useDataStoreAliasing = false, flushMode = defaultFlushMode, } = runtimeOptions;
|
|
614
|
-
const
|
|
602
|
+
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", useDataStoreAliasing = false, flushMode = defaultFlushMode, enableOfflineLoad = false, } = runtimeOptions;
|
|
603
|
+
const pendingRuntimeState = context.pendingLocalState;
|
|
604
|
+
const baseSnapshot = (_b = pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.baseSnapshot) !== null && _b !== void 0 ? _b : context.baseSnapshot;
|
|
605
|
+
const storage = !pendingRuntimeState ?
|
|
606
|
+
context.storage :
|
|
607
|
+
new serializedSnapshotStorage_1.SerializedSnapshotStorage(() => { return context.storage; }, pendingRuntimeState.snapshotBlobs);
|
|
615
608
|
const registry = new dataStoreRegistry_1.FluidDataStoreRegistry(registryEntries);
|
|
616
609
|
const tryFetchBlob = async (blobName) => {
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
if (context.baseSnapshot && blobId) {
|
|
610
|
+
const blobId = baseSnapshot === null || baseSnapshot === void 0 ? void 0 : baseSnapshot.blobs[blobName];
|
|
611
|
+
if (baseSnapshot && blobId) {
|
|
620
612
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
621
613
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
622
614
|
(0, common_utils_1.assert)(storage !== undefined, 0x1f5 /* "Attached state should have storage" */);
|
|
@@ -631,7 +623,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
631
623
|
]);
|
|
632
624
|
const loadExisting = existing === true || context.existing === true;
|
|
633
625
|
// read snapshot blobs needed for BlobManager to load
|
|
634
|
-
const blobManagerSnapshot = await blobManager_1.BlobManager.load(
|
|
626
|
+
const blobManagerSnapshot = await blobManager_1.BlobManager.load(baseSnapshot === null || baseSnapshot === void 0 ? void 0 : baseSnapshot.trees[summaryFormat_1.blobsTreeName], async (id) => {
|
|
635
627
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
636
628
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
637
629
|
(0, common_utils_1.assert)(storage !== undefined, 0x256 /* "storage undefined in attached container" */);
|
|
@@ -661,7 +653,14 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
661
653
|
loadSequenceNumberVerification,
|
|
662
654
|
useDataStoreAliasing,
|
|
663
655
|
flushMode,
|
|
664
|
-
|
|
656
|
+
enableOfflineLoad,
|
|
657
|
+
}, containerScope, logger, loadExisting, blobManagerSnapshot, storage, requestHandler);
|
|
658
|
+
if (pendingRuntimeState) {
|
|
659
|
+
await runtime.processSavedOps(pendingRuntimeState);
|
|
660
|
+
// delete these once runtime has seen them to save space
|
|
661
|
+
pendingRuntimeState.savedOps = [];
|
|
662
|
+
}
|
|
663
|
+
await runtime.getSnapshotBlobs();
|
|
665
664
|
return runtime;
|
|
666
665
|
}
|
|
667
666
|
get options() {
|
|
@@ -677,7 +676,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
677
676
|
return this.context.deltaManager;
|
|
678
677
|
}
|
|
679
678
|
get storage() {
|
|
680
|
-
return this.
|
|
679
|
+
return this._storage;
|
|
681
680
|
}
|
|
682
681
|
get reSubmitFn() {
|
|
683
682
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
@@ -709,19 +708,70 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
709
708
|
var _a;
|
|
710
709
|
return (_a = this.summarizerClientElection) === null || _a === void 0 ? void 0 : _a.electedClientId;
|
|
711
710
|
}
|
|
712
|
-
get summaryConfiguration() {
|
|
713
|
-
var _a;
|
|
714
|
-
return Object.assign(Object.assign({}, DefaultSummaryConfiguration), (_a = this.runtimeOptions.summaryOptions) === null || _a === void 0 ? void 0 : _a.summaryConfigOverrides);
|
|
715
|
-
}
|
|
716
711
|
get disposed() { return this._disposed; }
|
|
717
712
|
get summarizer() {
|
|
718
713
|
(0, common_utils_1.assert)(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
|
|
719
714
|
return this._summarizer;
|
|
720
715
|
}
|
|
721
|
-
|
|
716
|
+
isSummariesDisabled() {
|
|
717
|
+
// back-compat: disableSummaries was moved from ISummaryRuntimeOptions
|
|
718
|
+
// to ISummaryConfiguration in 0.60.
|
|
719
|
+
if (this.runtimeOptions.summaryOptions.disableSummaries === true) {
|
|
720
|
+
return true;
|
|
721
|
+
}
|
|
722
|
+
return this.summaryConfiguration.state === "disabled";
|
|
723
|
+
}
|
|
724
|
+
isHeuristicsDisabled() {
|
|
722
725
|
var _a;
|
|
723
|
-
|
|
724
|
-
|
|
726
|
+
// back-compat: disableHeuristics was moved from ISummarizerOptions
|
|
727
|
+
// to ISummaryConfiguration in 0.60.
|
|
728
|
+
if (((_a = this.runtimeOptions.summaryOptions.summarizerOptions) === null || _a === void 0 ? void 0 : _a.disableHeuristics) === true) {
|
|
729
|
+
return true;
|
|
730
|
+
}
|
|
731
|
+
return this.summaryConfiguration.state === "disableHeuristics";
|
|
732
|
+
}
|
|
733
|
+
isSummarizerClientElectionEnabled() {
|
|
734
|
+
var _a;
|
|
735
|
+
if (this.mc.config.getBoolean("Fluid.ContainerRuntime.summarizerClientElection")) {
|
|
736
|
+
return (_a = this.mc.config.getBoolean("Fluid.ContainerRuntime.summarizerClientElection")) !== null && _a !== void 0 ? _a : true;
|
|
737
|
+
}
|
|
738
|
+
// back-compat: summarizerClientElection was moved from ISummaryRuntimeOptions
|
|
739
|
+
// to ISummaryConfiguration in 0.60.
|
|
740
|
+
if (this.runtimeOptions.summaryOptions.summarizerClientElection === true) {
|
|
741
|
+
return true;
|
|
742
|
+
}
|
|
743
|
+
if (this.summaryConfiguration.state !== "disabled") {
|
|
744
|
+
return this.summaryConfiguration.summarizerClientElection === true;
|
|
745
|
+
}
|
|
746
|
+
else {
|
|
747
|
+
return false;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
getMaxOpsSinceLastSummary() {
|
|
751
|
+
// back-compat: maxOpsSinceLastSummary was moved from ISummaryRuntimeOptions
|
|
752
|
+
// to ISummaryConfiguration in 0.60.
|
|
753
|
+
if (this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary !== undefined) {
|
|
754
|
+
return this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary;
|
|
755
|
+
}
|
|
756
|
+
if (this.summaryConfiguration.state !== "disabled") {
|
|
757
|
+
return this.summaryConfiguration.maxOpsSinceLastSummary;
|
|
758
|
+
}
|
|
759
|
+
else {
|
|
760
|
+
return 0;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
getInitialSummarizerDelayMs() {
|
|
764
|
+
// back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
|
|
765
|
+
// to ISummaryConfiguration in 0.60.
|
|
766
|
+
if (this.runtimeOptions.summaryOptions.initialSummarizerDelayMs !== undefined) {
|
|
767
|
+
return this.runtimeOptions.summaryOptions.initialSummarizerDelayMs;
|
|
768
|
+
}
|
|
769
|
+
if (this.summaryConfiguration.state !== "disabled") {
|
|
770
|
+
return this.summaryConfiguration.initialSummarizerDelayMs;
|
|
771
|
+
}
|
|
772
|
+
else {
|
|
773
|
+
return 0;
|
|
774
|
+
}
|
|
725
775
|
}
|
|
726
776
|
dispose(error) {
|
|
727
777
|
var _a;
|
|
@@ -862,7 +912,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
862
912
|
message: (_a = (0, summaryFormat_1.extractSummaryMetadataMessage)(this.deltaManager.lastMessage)) !== null && _a !== void 0 ? _a : this.messageAtLastSummary });
|
|
863
913
|
(0, runtime_utils_1.addBlobToSummary)(summaryTree, summaryFormat_1.metadataBlobName, JSON.stringify(metadata));
|
|
864
914
|
}
|
|
865
|
-
addContainerStateToSummary(summaryTree, fullTree, trackState) {
|
|
915
|
+
addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext) {
|
|
866
916
|
var _a;
|
|
867
917
|
this.addMetadataToSummary(summaryTree);
|
|
868
918
|
if (this.chunkMap.size > 0) {
|
|
@@ -884,7 +934,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
884
934
|
(0, runtime_utils_1.addTreeToSummary)(summaryTree, summaryFormat_1.blobsTreeName, blobManagerSummary);
|
|
885
935
|
}
|
|
886
936
|
if (this.garbageCollector.writeDataAtRoot) {
|
|
887
|
-
const gcSummary = this.garbageCollector.summarize(fullTree, trackState);
|
|
937
|
+
const gcSummary = this.garbageCollector.summarize(fullTree, trackState, telemetryContext);
|
|
888
938
|
if (gcSummary !== undefined) {
|
|
889
939
|
(0, runtime_utils_1.addSummarizeResultToSummary)(summaryTree, garbageCollection_1.gcTreeKey, gcSummary);
|
|
890
940
|
}
|
|
@@ -905,7 +955,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
905
955
|
this.resetReconnectCount();
|
|
906
956
|
return true;
|
|
907
957
|
}
|
|
908
|
-
this.consecutiveReconnects++;
|
|
909
958
|
if (this.consecutiveReconnects === Math.floor(this.maxConsecutiveReconnects / 2)) {
|
|
910
959
|
// If we're halfway through the max reconnects, send an event in order
|
|
911
960
|
// to better identify false positives, if any. If the rate of this event
|
|
@@ -914,6 +963,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
914
963
|
this.mc.logger.sendTelemetryEvent({
|
|
915
964
|
eventName: "ReconnectsWithNoProgress",
|
|
916
965
|
attempts: this.consecutiveReconnects,
|
|
966
|
+
pendingMessages: this.pendingStateManager.pendingMessagesCount,
|
|
917
967
|
});
|
|
918
968
|
}
|
|
919
969
|
return this.consecutiveReconnects < this.maxConsecutiveReconnects;
|
|
@@ -969,29 +1019,37 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
969
1019
|
this.verifyNotClosed();
|
|
970
1020
|
// There might be no change of state due to Container calling this API after loading runtime.
|
|
971
1021
|
const changeOfState = this._connected !== connected;
|
|
1022
|
+
const reconnection = changeOfState && connected;
|
|
972
1023
|
this._connected = connected;
|
|
973
|
-
if (
|
|
974
|
-
this.
|
|
975
|
-
this.context.pendingLocalState = undefined;
|
|
1024
|
+
if (reconnection) {
|
|
1025
|
+
this.consecutiveReconnects++;
|
|
976
1026
|
if (!this.shouldContinueReconnecting()) {
|
|
977
1027
|
this.closeFn(new container_utils_1.GenericError(
|
|
978
1028
|
// pre-0.58 error message: MaxReconnectsWithNoProgress
|
|
979
1029
|
"Runtime detected too many reconnects with no progress syncing local ops", undefined, // error
|
|
980
|
-
{
|
|
1030
|
+
{
|
|
1031
|
+
attempts: this.consecutiveReconnects,
|
|
1032
|
+
pendingMessages: this.pendingStateManager.pendingMessagesCount,
|
|
1033
|
+
}));
|
|
981
1034
|
return;
|
|
982
1035
|
}
|
|
1036
|
+
}
|
|
1037
|
+
if (changeOfState) {
|
|
983
1038
|
this.replayPendingStates();
|
|
984
1039
|
}
|
|
985
1040
|
this.dataStores.setConnectionState(connected, clientId);
|
|
986
1041
|
(0, telemetry_utils_1.raiseConnectedEvent)(this.mc.logger, this, connected, clientId);
|
|
987
1042
|
}
|
|
988
1043
|
process(messageArg, local) {
|
|
989
|
-
var _a;
|
|
1044
|
+
var _a, _b;
|
|
990
1045
|
this.verifyNotClosed();
|
|
991
1046
|
// If it's not message for runtime, bail out right away.
|
|
992
1047
|
if (!isRuntimeMessage(messageArg)) {
|
|
993
1048
|
return;
|
|
994
1049
|
}
|
|
1050
|
+
if ((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad) {
|
|
1051
|
+
this.savedOps.push(messageArg);
|
|
1052
|
+
}
|
|
995
1053
|
// Do shallow copy of message, as methods below will modify it.
|
|
996
1054
|
// There might be multiple container instances receiving same message
|
|
997
1055
|
// We do not need to make deep copy, as each layer will just replace message.content itself,
|
|
@@ -1006,8 +1064,14 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1006
1064
|
// Chunk processing must come first given that we will transform the message to the unchunked version
|
|
1007
1065
|
// once all pieces are available
|
|
1008
1066
|
message = this.processRemoteChunkedMessage(message);
|
|
1009
|
-
|
|
1010
|
-
|
|
1067
|
+
let localOpMetadata;
|
|
1068
|
+
if (local) {
|
|
1069
|
+
// Call the PendingStateManager to process local messages.
|
|
1070
|
+
// Do not process local chunked ops until all pieces are available.
|
|
1071
|
+
if (message.type !== ContainerMessageType.ChunkedOp) {
|
|
1072
|
+
localOpMetadata = this.pendingStateManager.processPendingLocalMessage(message);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1011
1075
|
// If there are no more pending messages after processing a local message,
|
|
1012
1076
|
// the document is no longer dirty.
|
|
1013
1077
|
if (!this.pendingStateManager.hasPendingMessages()) {
|
|
@@ -1015,17 +1079,16 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1015
1079
|
}
|
|
1016
1080
|
switch (message.type) {
|
|
1017
1081
|
case ContainerMessageType.Attach:
|
|
1018
|
-
this.dataStores.processAttachMessage(message, local
|
|
1082
|
+
this.dataStores.processAttachMessage(message, local);
|
|
1019
1083
|
break;
|
|
1020
1084
|
case ContainerMessageType.Alias:
|
|
1021
1085
|
this.processAliasMessage(message, localOpMetadata, local);
|
|
1022
1086
|
break;
|
|
1023
1087
|
case ContainerMessageType.FluidDataStoreOp:
|
|
1024
|
-
|
|
1025
|
-
this.dataStores.processFluidDataStoreOp(message, local || localAck, localOpMetadata);
|
|
1088
|
+
this.dataStores.processFluidDataStoreOp(message, local, localOpMetadata);
|
|
1026
1089
|
break;
|
|
1027
1090
|
case ContainerMessageType.BlobAttach:
|
|
1028
|
-
(0, common_utils_1.assert)((
|
|
1091
|
+
(0, common_utils_1.assert)((_b = message === null || message === void 0 ? void 0 : message.metadata) === null || _b === void 0 ? void 0 : _b.blobId, 0x12a /* "Missing blob id on metadata" */);
|
|
1029
1092
|
this.blobManager.processBlobAttachOp(message.metadata.blobId, local);
|
|
1030
1093
|
break;
|
|
1031
1094
|
default:
|
|
@@ -1117,18 +1180,32 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1117
1180
|
}
|
|
1118
1181
|
const savedFlushMode = this.flushMode;
|
|
1119
1182
|
this.setFlushMode(runtime_definitions_1.FlushMode.TurnBased);
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1183
|
+
try {
|
|
1184
|
+
this.trackOrderSequentiallyCalls(callback);
|
|
1185
|
+
this.flush();
|
|
1186
|
+
}
|
|
1187
|
+
finally {
|
|
1188
|
+
this.setFlushMode(savedFlushMode);
|
|
1189
|
+
}
|
|
1123
1190
|
}
|
|
1124
1191
|
trackOrderSequentiallyCalls(callback) {
|
|
1192
|
+
let checkpoint;
|
|
1193
|
+
if (this.mc.config.getBoolean("Fluid.ContainerRuntime.EnableRollback")) {
|
|
1194
|
+
checkpoint = this.pendingStateManager.checkpoint();
|
|
1195
|
+
}
|
|
1125
1196
|
try {
|
|
1126
1197
|
this._orderSequentiallyCalls++;
|
|
1127
1198
|
callback();
|
|
1128
1199
|
}
|
|
1129
1200
|
catch (error) {
|
|
1130
|
-
|
|
1131
|
-
|
|
1201
|
+
if (checkpoint) {
|
|
1202
|
+
// This will throw and close the container if rollback fails
|
|
1203
|
+
checkpoint.rollback();
|
|
1204
|
+
}
|
|
1205
|
+
else {
|
|
1206
|
+
// pre-0.58 error message: orderSequentiallyCallbackException
|
|
1207
|
+
this.closeFn(new container_utils_1.GenericError("orderSequentially callback exception", error));
|
|
1208
|
+
}
|
|
1132
1209
|
throw error; // throw the original error for the consumer of the runtime
|
|
1133
1210
|
}
|
|
1134
1211
|
finally {
|
|
@@ -1300,17 +1377,18 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1300
1377
|
* @param blobRedirectTable - A table passed during the attach process. While detached, blob upload is supported
|
|
1301
1378
|
* using IDs generated locally. After attach, these IDs cannot be used, so this table maps the old local IDs to the
|
|
1302
1379
|
* new storage IDs so requests can be redirected.
|
|
1380
|
+
* @param telemetryContext - summary data passed through the layers for telemetry purposes
|
|
1303
1381
|
*/
|
|
1304
|
-
createSummary(blobRedirectTable) {
|
|
1382
|
+
createSummary(blobRedirectTable, telemetryContext) {
|
|
1305
1383
|
if (blobRedirectTable) {
|
|
1306
1384
|
this.blobManager.setRedirectTable(blobRedirectTable);
|
|
1307
1385
|
}
|
|
1308
|
-
const summarizeResult = this.dataStores.createSummary();
|
|
1386
|
+
const summarizeResult = this.dataStores.createSummary(telemetryContext);
|
|
1309
1387
|
if (!this.disableIsolatedChannels) {
|
|
1310
1388
|
// Wrap data store summaries in .channels subtree.
|
|
1311
1389
|
(0, summaryFormat_1.wrapSummaryInChannelsTree)(summarizeResult);
|
|
1312
1390
|
}
|
|
1313
|
-
this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState
|
|
1391
|
+
this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
|
|
1314
1392
|
return summarizeResult.summary;
|
|
1315
1393
|
}
|
|
1316
1394
|
async getAbsoluteUrl(relativeUrl) {
|
|
@@ -1322,15 +1400,15 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1322
1400
|
}
|
|
1323
1401
|
return this.context.getAbsoluteUrl(relativeUrl);
|
|
1324
1402
|
}
|
|
1325
|
-
async summarizeInternal(fullTree, trackState) {
|
|
1326
|
-
const summarizeResult = await this.dataStores.summarize(fullTree, trackState);
|
|
1403
|
+
async summarizeInternal(fullTree, trackState, telemetryContext) {
|
|
1404
|
+
const summarizeResult = await this.dataStores.summarize(fullTree, trackState, telemetryContext);
|
|
1327
1405
|
let pathPartsForChildren;
|
|
1328
1406
|
if (!this.disableIsolatedChannels) {
|
|
1329
1407
|
// Wrap data store summaries in .channels subtree.
|
|
1330
1408
|
(0, summaryFormat_1.wrapSummaryInChannelsTree)(summarizeResult);
|
|
1331
1409
|
pathPartsForChildren = [runtime_definitions_1.channelsTreeName];
|
|
1332
1410
|
}
|
|
1333
|
-
this.addContainerStateToSummary(summarizeResult, fullTree, trackState);
|
|
1411
|
+
this.addContainerStateToSummary(summarizeResult, fullTree, trackState, telemetryContext);
|
|
1334
1412
|
return Object.assign(Object.assign({}, summarizeResult), { id: "", pathPartsForChildren });
|
|
1335
1413
|
}
|
|
1336
1414
|
/**
|
|
@@ -1343,7 +1421,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1343
1421
|
if (runGC) {
|
|
1344
1422
|
gcStats = await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC });
|
|
1345
1423
|
}
|
|
1346
|
-
const
|
|
1424
|
+
const telemetryContext = new runtime_utils_1.TelemetryContext();
|
|
1425
|
+
const { stats, summary } = await this.summarizerNode.summarize(fullTree, trackState, telemetryContext);
|
|
1426
|
+
this.logger.sendTelemetryEvent({ eventName: "SummarizeTelemetry", details: telemetryContext.serialize() });
|
|
1347
1427
|
(0, common_utils_1.assert)(summary.type === protocol_definitions_1.SummaryType.Tree, 0x12f /* "Container Runtime's summarize should always return a tree" */);
|
|
1348
1428
|
return { stats, summary, gcStats };
|
|
1349
1429
|
}
|
|
@@ -1707,9 +1787,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1707
1787
|
}
|
|
1708
1788
|
submit(type, content, localOpMetadata = undefined, opMetadata = undefined) {
|
|
1709
1789
|
this.verifyNotClosed();
|
|
1710
|
-
if (this.context.pendingLocalState !== undefined) {
|
|
1711
|
-
this.closeFn(new container_utils_1.GenericError("containerRuntimeSubmitWithPendingLocalState"));
|
|
1712
|
-
}
|
|
1713
1790
|
// There should be no ops in detached container state!
|
|
1714
1791
|
(0, common_utils_1.assert)(this.attachState !== container_definitions_1.AttachState.Detached, 0x132 /* "sending ops in detached container" */);
|
|
1715
1792
|
let clientSequenceNumber = -1;
|
|
@@ -1840,6 +1917,17 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1840
1917
|
(0, common_utils_1.unreachableCase)(type, `Unknown ContainerMessageType: ${type}`);
|
|
1841
1918
|
}
|
|
1842
1919
|
}
|
|
1920
|
+
rollback(type, content, localOpMetadata) {
|
|
1921
|
+
switch (type) {
|
|
1922
|
+
case ContainerMessageType.FluidDataStoreOp:
|
|
1923
|
+
// For operations, call rollbackDataStoreOp which will find the right store
|
|
1924
|
+
// and trigger rollback on it.
|
|
1925
|
+
this.dataStores.rollbackDataStoreOp(content, localOpMetadata);
|
|
1926
|
+
break;
|
|
1927
|
+
default:
|
|
1928
|
+
throw new Error(`Can't rollback ${type}`);
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1843
1931
|
/** Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck */
|
|
1844
1932
|
async refreshLatestSummaryAck(proposalHandle, ackHandle, summaryRefSeq, summaryLogger) {
|
|
1845
1933
|
const readAndParseBlob = async (id) => (0, driver_utils_1.readAndParse)(this.storage, id);
|
|
@@ -1884,8 +1972,43 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1884
1972
|
return maybeSnapshot;
|
|
1885
1973
|
});
|
|
1886
1974
|
}
|
|
1975
|
+
notifyAttaching(snapshot) {
|
|
1976
|
+
var _a;
|
|
1977
|
+
if ((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad) {
|
|
1978
|
+
this.baseSnapshotBlobs = serializedSnapshotStorage_1.SerializedSnapshotStorage.serializeTreeWithBlobContents(snapshot);
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
async getSnapshotBlobs() {
|
|
1982
|
+
var _a;
|
|
1983
|
+
if (!((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad) ||
|
|
1984
|
+
this.attachState !== container_definitions_1.AttachState.Attached || this.context.pendingLocalState) {
|
|
1985
|
+
return;
|
|
1986
|
+
}
|
|
1987
|
+
(0, common_utils_1.assert)(!!this.context.baseSnapshot, 0x2e5 /* "Must have a base snapshot" */);
|
|
1988
|
+
this.baseSnapshotBlobs = await serializedSnapshotStorage_1.SerializedSnapshotStorage.serializeTree(this.context.baseSnapshot, this.storage);
|
|
1989
|
+
}
|
|
1887
1990
|
getPendingLocalState() {
|
|
1888
|
-
|
|
1991
|
+
var _a;
|
|
1992
|
+
if (!((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad)) {
|
|
1993
|
+
throw new container_utils_1.UsageError("can't get state when offline load disabled");
|
|
1994
|
+
}
|
|
1995
|
+
const previousPendingState = this.context.pendingLocalState;
|
|
1996
|
+
if (previousPendingState) {
|
|
1997
|
+
return {
|
|
1998
|
+
pending: this.pendingStateManager.getLocalState(),
|
|
1999
|
+
snapshotBlobs: previousPendingState.snapshotBlobs,
|
|
2000
|
+
baseSnapshot: previousPendingState.baseSnapshot,
|
|
2001
|
+
savedOps: this.savedOps,
|
|
2002
|
+
};
|
|
2003
|
+
}
|
|
2004
|
+
(0, common_utils_1.assert)(!!this.context.baseSnapshot, 0x2e6 /* "Must have a base snapshot" */);
|
|
2005
|
+
(0, common_utils_1.assert)(!!this.baseSnapshotBlobs, 0x2e7 /* "Must serialize base snapshot blobs before getting runtime state" */);
|
|
2006
|
+
return {
|
|
2007
|
+
pending: this.pendingStateManager.getLocalState(),
|
|
2008
|
+
snapshotBlobs: this.baseSnapshotBlobs,
|
|
2009
|
+
baseSnapshot: this.context.baseSnapshot,
|
|
2010
|
+
savedOps: this.savedOps,
|
|
2011
|
+
};
|
|
1889
2012
|
}
|
|
1890
2013
|
/**
|
|
1891
2014
|
* * Forms a function that will request a Summarizer.
|
|
@@ -1913,6 +2036,15 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1913
2036
|
return summarizer;
|
|
1914
2037
|
};
|
|
1915
2038
|
}
|
|
2039
|
+
async processSavedOps(state) {
|
|
2040
|
+
for (const op of state.savedOps) {
|
|
2041
|
+
this.process(op, false);
|
|
2042
|
+
await this.pendingStateManager.applyStashedOpsAt(op.sequenceNumber);
|
|
2043
|
+
}
|
|
2044
|
+
// we may not have seen every sequence number (because of system ops) so apply everything once we
|
|
2045
|
+
// don't have any more saved ops
|
|
2046
|
+
await this.pendingStateManager.applyStashedOpsAt();
|
|
2047
|
+
}
|
|
1916
2048
|
}
|
|
1917
2049
|
exports.ContainerRuntime = ContainerRuntime;
|
|
1918
2050
|
/**
|