@fluidframework/container-runtime 0.52.1 → 0.54.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/containerHandleContext.d.ts +0 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js +0 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +43 -19
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +201 -111
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +33 -4
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +45 -17
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +14 -10
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +73 -41
- package/dist/dataStores.js.map +1 -1
- package/dist/garbageCollection.d.ts +82 -15
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +359 -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 +11 -2
- package/dist/index.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/runningSummarizer.d.ts +3 -2
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +6 -6
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/summarizer.d.ts +23 -3
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +135 -45
- package/dist/summarizer.js.map +1 -1
- package/dist/summarizerTypes.d.ts +3 -10
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryFormat.d.ts +10 -1
- package/dist/summaryFormat.d.ts.map +1 -1
- package/dist/summaryFormat.js +2 -1
- package/dist/summaryFormat.js.map +1 -1
- package/dist/summaryGenerator.d.ts.map +1 -1
- package/dist/summaryGenerator.js +1 -3
- package/dist/summaryGenerator.js.map +1 -1
- package/dist/summaryManager.d.ts +0 -15
- package/dist/summaryManager.d.ts.map +1 -1
- package/dist/summaryManager.js +1 -35
- package/dist/summaryManager.js.map +1 -1
- package/lib/containerHandleContext.d.ts +0 -1
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js +0 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +43 -19
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +206 -117
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +33 -4
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +45 -17
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +14 -10
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +76 -44
- package/lib/dataStores.js.map +1 -1
- package/lib/garbageCollection.d.ts +82 -15
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +361 -28
- 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 +2 -1
- package/lib/index.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/runningSummarizer.d.ts +3 -2
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +6 -6
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/summarizer.d.ts +23 -3
- package/lib/summarizer.d.ts.map +1 -1
- package/lib/summarizer.js +135 -45
- package/lib/summarizer.js.map +1 -1
- package/lib/summarizerTypes.d.ts +3 -10
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryFormat.d.ts +10 -1
- package/lib/summaryFormat.d.ts.map +1 -1
- package/lib/summaryFormat.js +1 -0
- package/lib/summaryFormat.js.map +1 -1
- package/lib/summaryGenerator.d.ts.map +1 -1
- package/lib/summaryGenerator.js +1 -3
- package/lib/summaryGenerator.js.map +1 -1
- package/lib/summaryManager.d.ts +0 -15
- package/lib/summaryManager.d.ts.map +1 -1
- package/lib/summaryManager.js +1 -34
- package/lib/summaryManager.js.map +1 -1
- package/package.json +14 -14
- package/src/containerHandleContext.ts +0 -1
- package/src/containerRuntime.ts +280 -140
- package/src/dataStoreContext.ts +59 -20
- package/src/dataStores.ts +116 -54
- package/src/garbageCollection.ts +492 -29
- package/src/index.ts +20 -2
- package/src/packageVersion.ts +1 -1
- package/src/runningSummarizer.ts +12 -10
- package/src/summarizer.ts +154 -53
- package/src/summarizerTypes.ts +3 -11
- package/src/summaryFormat.ts +11 -1
- package/src/summaryGenerator.ts +2 -3
- package/src/summaryManager.ts +2 -49
- package/dist/localStorageFeatureGates.d.ts +0 -13
- package/dist/localStorageFeatureGates.d.ts.map +0 -1
- package/dist/localStorageFeatureGates.js +0 -31
- package/dist/localStorageFeatureGates.js.map +0 -1
- package/lib/localStorageFeatureGates.d.ts +0 -13
- package/lib/localStorageFeatureGates.d.ts.map +0 -1
- package/lib/localStorageFeatureGates.js +0 -27
- package/lib/localStorageFeatureGates.js.map +0 -1
- package/src/localStorageFeatureGates.ts +0 -27
package/dist/containerRuntime.js
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.ContainerRuntime = exports.agentSchedulerId = exports.ScheduleManager = exports.unpackRuntimeMessage = exports.isRuntimeMessage = exports.ContainerMessageType = void 0;
|
|
7
|
+
exports.ContainerRuntime = exports.getDeviceSpec = exports.agentSchedulerId = exports.ScheduleManager = exports.unpackRuntimeMessage = exports.isRuntimeMessage = exports.ContainerMessageType = void 0;
|
|
8
8
|
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
9
9
|
const common_utils_1 = require("@fluidframework/common-utils");
|
|
10
10
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
11
|
+
const driver_definitions_1 = require("@fluidframework/driver-definitions");
|
|
11
12
|
const driver_utils_1 = require("@fluidframework/driver-utils");
|
|
12
13
|
const container_utils_1 = require("@fluidframework/container-utils");
|
|
13
|
-
const protocol_base_1 = require("@fluidframework/protocol-base");
|
|
14
14
|
const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
15
15
|
const runtime_definitions_1 = require("@fluidframework/runtime-definitions");
|
|
16
16
|
const runtime_utils_1 = require("@fluidframework/runtime-utils");
|
|
@@ -27,7 +27,6 @@ const blobManager_1 = require("./blobManager");
|
|
|
27
27
|
const dataStores_1 = require("./dataStores");
|
|
28
28
|
const summaryFormat_1 = require("./summaryFormat");
|
|
29
29
|
const summaryCollection_1 = require("./summaryCollection");
|
|
30
|
-
const localStorageFeatureGates_1 = require("./localStorageFeatureGates");
|
|
31
30
|
const orderedClientElection_1 = require("./orderedClientElection");
|
|
32
31
|
const summarizerClientElection_1 = require("./summarizerClientElection");
|
|
33
32
|
const throttler_1 = require("./throttler");
|
|
@@ -45,6 +44,8 @@ var ContainerMessageType;
|
|
|
45
44
|
ContainerMessageType["BlobAttach"] = "blobAttach";
|
|
46
45
|
// Ties our new clientId to our old one on reconnect
|
|
47
46
|
ContainerMessageType["Rejoin"] = "rejoin";
|
|
47
|
+
// Sets the alias of a root data store
|
|
48
|
+
ContainerMessageType["Alias"] = "alias";
|
|
48
49
|
})(ContainerMessageType = exports.ContainerMessageType || (exports.ContainerMessageType = {}));
|
|
49
50
|
// Consider idle 5s of no activity. And snapshot if a minute has gone by with no snapshot.
|
|
50
51
|
const IdleDetectionTime = 5000;
|
|
@@ -59,12 +60,13 @@ const DefaultSummaryConfiguration = {
|
|
|
59
60
|
maxAckWaitTime: 120000,
|
|
60
61
|
};
|
|
61
62
|
// Local storage key to set the default flush mode to TurnBased
|
|
62
|
-
const turnBasedFlushModeKey = "
|
|
63
|
+
const turnBasedFlushModeKey = "Fluid.ContainerRuntime.FlushModeTurnBased";
|
|
63
64
|
function isRuntimeMessage(message) {
|
|
64
65
|
switch (message.type) {
|
|
65
66
|
case ContainerMessageType.FluidDataStoreOp:
|
|
66
67
|
case ContainerMessageType.ChunkedOp:
|
|
67
68
|
case ContainerMessageType.Attach:
|
|
69
|
+
case ContainerMessageType.Alias:
|
|
68
70
|
case ContainerMessageType.BlobAttach:
|
|
69
71
|
case ContainerMessageType.Rejoin:
|
|
70
72
|
case protocol_definitions_1.MessageType.Operation:
|
|
@@ -312,13 +314,28 @@ exports.ScheduleManager = ScheduleManager;
|
|
|
312
314
|
* ContainerRuntime's perspective.
|
|
313
315
|
*/
|
|
314
316
|
exports.agentSchedulerId = "_scheduler";
|
|
317
|
+
// safely check navigator and get the hardware spec value
|
|
318
|
+
function getDeviceSpec() {
|
|
319
|
+
try {
|
|
320
|
+
if (typeof navigator === "object" && navigator !== null) {
|
|
321
|
+
return {
|
|
322
|
+
deviceMemory: navigator.deviceMemory,
|
|
323
|
+
hardwareConcurrency: navigator.hardwareConcurrency,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
catch (_a) {
|
|
328
|
+
}
|
|
329
|
+
return {};
|
|
330
|
+
}
|
|
331
|
+
exports.getDeviceSpec = getDeviceSpec;
|
|
315
332
|
/**
|
|
316
333
|
* Represents the runtime of the container. Contains helper functions/state of the container.
|
|
317
334
|
* It will define the store level mappings.
|
|
318
335
|
*/
|
|
319
336
|
class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
320
|
-
constructor(context, registry, metadata, electedSummarizerData, chunks, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, requestHandler, _storage) {
|
|
321
|
-
var _a, _b, _c, _d;
|
|
337
|
+
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, requestHandler, _storage) {
|
|
338
|
+
var _a, _b, _c, _d, _e;
|
|
322
339
|
super();
|
|
323
340
|
this.context = context;
|
|
324
341
|
this.registry = registry;
|
|
@@ -327,14 +344,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
327
344
|
this.logger = logger;
|
|
328
345
|
this.requestHandler = requestHandler;
|
|
329
346
|
this._storage = _storage;
|
|
330
|
-
// back-compat: Used by loader in <= 0.35
|
|
331
|
-
/**
|
|
332
|
-
* @internal
|
|
333
|
-
* @deprecated Back-compat only. Used by the loader in versions earlier than 0.35.
|
|
334
|
-
*/
|
|
335
|
-
this.runtimeVersion = packageVersion_1.pkgVersion;
|
|
336
347
|
this._orderSequentiallyCalls = 0;
|
|
337
|
-
this._flushMode = ContainerRuntime.defaultFlushMode;
|
|
338
348
|
this.needsFlush = false;
|
|
339
349
|
this.flushTrigger = false;
|
|
340
350
|
this.paused = false;
|
|
@@ -377,7 +387,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
377
387
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
378
388
|
// disableSummaries is turned on. We are throwing instead of returning a failure here,
|
|
379
389
|
// because it is a misuse of the API rather than an expected failure.
|
|
380
|
-
throw new
|
|
390
|
+
throw new container_utils_1.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
381
391
|
}
|
|
382
392
|
};
|
|
383
393
|
this.enqueueSummarize = (...args) => {
|
|
@@ -391,18 +401,47 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
391
401
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
392
402
|
// generateSummaries is turned off. We are throwing instead of returning a failure here,
|
|
393
403
|
// because it is a misuse of the API rather than an expected failure.
|
|
394
|
-
throw new
|
|
404
|
+
throw new container_utils_1.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
395
405
|
}
|
|
396
406
|
};
|
|
397
407
|
this.baseSummaryMessage = metadata === null || metadata === void 0 ? void 0 : metadata.message;
|
|
408
|
+
// If this is an existing container, we get values from metadata.
|
|
409
|
+
// otherwise, we initialize them.
|
|
410
|
+
if (existing) {
|
|
411
|
+
this.createContainerMetadata = {
|
|
412
|
+
createContainerRuntimeVersion: metadata === null || metadata === void 0 ? void 0 : metadata.createContainerRuntimeVersion,
|
|
413
|
+
createContainerTimestamp: metadata === null || metadata === void 0 ? void 0 : metadata.createContainerTimestamp,
|
|
414
|
+
};
|
|
415
|
+
this.summaryCount = metadata === null || metadata === void 0 ? void 0 : metadata.summaryCount;
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
this.createContainerMetadata = {
|
|
419
|
+
createContainerRuntimeVersion: packageVersion_1.pkgVersion,
|
|
420
|
+
createContainerTimestamp: Date.now(),
|
|
421
|
+
};
|
|
422
|
+
}
|
|
398
423
|
// Default to false (enabled).
|
|
399
424
|
this.disableIsolatedChannels = (_a = this.runtimeOptions.summaryOptions.disableIsolatedChannels) !== null && _a !== void 0 ? _a : false;
|
|
400
425
|
this._connected = this.context.connected;
|
|
401
426
|
this.chunkMap = new Map(chunks);
|
|
402
|
-
this.
|
|
403
|
-
this.
|
|
404
|
-
this.
|
|
405
|
-
|
|
427
|
+
this.handleContext = new containerHandleContext_1.ContainerFluidHandleContext("", this);
|
|
428
|
+
this.mc = telemetry_utils_1.loggerToMonitoringContext(telemetry_utils_1.ChildLogger.create(this.logger, "ContainerRuntime"));
|
|
429
|
+
this._flushMode =
|
|
430
|
+
((_b = this.mc.config.getBoolean(turnBasedFlushModeKey)) !== null && _b !== void 0 ? _b : false) ? runtime_definitions_1.FlushMode.TurnBased : runtime_definitions_1.FlushMode.Immediate;
|
|
431
|
+
/**
|
|
432
|
+
* Function that return the current server timestamp. This is used by the garbage collector to set the
|
|
433
|
+
* time when a node becomes unreferenced.
|
|
434
|
+
* We use the timestamp of the last op for current timestamp. However, there can be cases where
|
|
435
|
+
* we don't have an op (on demand summaries for instance). In those cases, we will use the timestamp
|
|
436
|
+
* of this client's connection.
|
|
437
|
+
*/
|
|
438
|
+
const getCurrentTimestamp = () => {
|
|
439
|
+
var _a, _b, _c;
|
|
440
|
+
const client = this.clientId !== undefined ? this.getAudience().getMember(this.clientId) : undefined;
|
|
441
|
+
const timestamp = client === null || client === void 0 ? void 0 : client.timestamp;
|
|
442
|
+
return (_c = (_b = (_a = this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.timestamp) !== null && _b !== void 0 ? _b : timestamp) !== null && _c !== void 0 ? _c : Date.now();
|
|
443
|
+
};
|
|
444
|
+
this.garbageCollector = garbageCollection_1.GarbageCollector.create(this, this.runtimeOptions.gcOptions, (unusedRoutes) => this.dataStores.deleteUnusedRoutes(unusedRoutes), getCurrentTimestamp, context.baseSnapshot, async (id) => driver_utils_1.readAndParse(this.storage, id), this.mc.logger, existing, metadata);
|
|
406
445
|
const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
|
|
407
446
|
this.summarizerNode = runtime_utils_1.createRootSummarizerNodeWithGC(telemetry_utils_1.ChildLogger.create(this.logger, "SummarizerNode"),
|
|
408
447
|
// Summarize function to call when summarize is called. Summarizer node always tracks summary state.
|
|
@@ -419,69 +458,58 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
419
458
|
throwOnFailure: true,
|
|
420
459
|
// If GC should not run, let the summarizer node know so that it does not track GC state.
|
|
421
460
|
gcDisabled: !this.garbageCollector.shouldRunGC,
|
|
422
|
-
// The max duration for which objects can be unreferenced before they are eligible for deletion.
|
|
423
|
-
maxUnreferencedDurationMs: this.runtimeOptions.gcOptions.maxUnreferencedDurationMs,
|
|
424
461
|
});
|
|
425
462
|
if (this.context.baseSnapshot) {
|
|
426
463
|
this.summarizerNode.loadBaseSummaryWithoutDifferential(this.context.baseSnapshot);
|
|
427
464
|
}
|
|
428
|
-
this.dataStores = new dataStores_1.DataStores(dataStores_1.getSummaryForDatastores(context.baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn, getInitialGCSummaryDetailsFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn, getInitialGCSummaryDetailsFn), (id) => this.summarizerNode.deleteChild(id), this.
|
|
429
|
-
this.blobManager = new blobManager_1.BlobManager(this.
|
|
465
|
+
this.dataStores = new dataStores_1.DataStores(dataStores_1.getSummaryForDatastores(context.baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn, getInitialGCSummaryDetailsFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn, getInitialGCSummaryDetailsFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, async () => this.garbageCollector.getDataStoreBaseGCDetails(), (id) => this.garbageCollector.nodeChanged(id), new Map(dataStoreAliasMap));
|
|
466
|
+
this.blobManager = new blobManager_1.BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (blobId) => this.submit(ContainerMessageType.BlobAttach, undefined, undefined, { blobId }), this, this.logger);
|
|
430
467
|
this.scheduleManager = new ScheduleManager(context.deltaManager, this, telemetry_utils_1.ChildLogger.create(this.logger, "ScheduleManager"));
|
|
431
468
|
this.deltaSender = this.deltaManager;
|
|
432
469
|
this.pendingStateManager = new pendingStateManager_1.PendingStateManager(this, async (type, content) => this.applyStashedOp(type, content), context.pendingLocalState);
|
|
433
470
|
this.context.quorum.on("removeMember", (clientId) => {
|
|
434
471
|
this.clearPartialChunks(clientId);
|
|
435
472
|
});
|
|
436
|
-
this.context.quorum.on("addProposal", (proposal) => {
|
|
437
|
-
if (proposal.key === "code" || proposal.key === "code2") {
|
|
438
|
-
this.emit("codeDetailsProposed", proposal.value, proposal);
|
|
439
|
-
}
|
|
440
|
-
});
|
|
441
473
|
this.summaryCollection = new summaryCollection_1.SummaryCollection(this.deltaManager, this.logger);
|
|
442
|
-
// Only create a SummaryManager if summaries are enabled and we are not the summarizer client
|
|
443
474
|
// Map the deprecated generateSummaries flag to disableSummaries.
|
|
444
475
|
if (this.runtimeOptions.summaryOptions.generateSummaries === false) {
|
|
445
476
|
this.runtimeOptions.summaryOptions.disableSummaries = true;
|
|
446
477
|
}
|
|
447
|
-
if (this.summariesDisabled
|
|
448
|
-
this.
|
|
478
|
+
if (this.summariesDisabled) {
|
|
479
|
+
this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
|
|
449
480
|
}
|
|
450
481
|
else {
|
|
451
|
-
const maxOpsSinceLastSummary = (_b = this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary) !== null && _b !== void 0 ? _b : 7000;
|
|
452
|
-
const defaultAction = () => {
|
|
453
|
-
if (this.summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
|
|
454
|
-
this.logger.sendErrorEvent({ eventName: "SummaryStatus:Behind" });
|
|
455
|
-
// unregister default to no log on every op after falling behind
|
|
456
|
-
// and register summary ack handler to re-register this handler
|
|
457
|
-
// after successful summary
|
|
458
|
-
this.summaryCollection.once(protocol_definitions_1.MessageType.SummaryAck, () => {
|
|
459
|
-
this.logger.sendTelemetryEvent({ eventName: "SummaryStatus:CaughtUp" });
|
|
460
|
-
// we've caught up, so re-register the default action to monitor for
|
|
461
|
-
// falling behind, and unregister ourself
|
|
462
|
-
this.summaryCollection.on("default", defaultAction);
|
|
463
|
-
});
|
|
464
|
-
this.summaryCollection.off("default", defaultAction);
|
|
465
|
-
}
|
|
466
|
-
};
|
|
467
|
-
this.summaryCollection.on("default", defaultAction);
|
|
468
482
|
const orderedClientLogger = telemetry_utils_1.ChildLogger.create(this.logger, "OrderedClientElection");
|
|
469
483
|
const orderedClientCollection = new orderedClientElection_1.OrderedClientCollection(orderedClientLogger, this.context.deltaManager, this.context.quorum);
|
|
470
484
|
const orderedClientElectionForSummarizer = new orderedClientElection_1.OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData !== null && electedSummarizerData !== void 0 ? electedSummarizerData : this.context.deltaManager.lastSequenceNumber, summarizerClientElection_1.SummarizerClientElection.isClientEligible);
|
|
471
|
-
const summarizerClientElectionEnabled = (_c =
|
|
485
|
+
const summarizerClientElectionEnabled = (_c = this.mc.config.getBoolean("Fluid.ContainerRuntime.summarizerClientElection")) !== null && _c !== void 0 ? _c : ((_d = this.runtimeOptions.summaryOptions) === null || _d === void 0 ? void 0 : _d.summarizerClientElection) === true;
|
|
486
|
+
const maxOpsSinceLastSummary = (_e = this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary) !== null && _e !== void 0 ? _e : 7000;
|
|
472
487
|
this.summarizerClientElection = new summarizerClientElection_1.SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, maxOpsSinceLastSummary, summarizerClientElectionEnabled);
|
|
473
488
|
if (this.context.clientDetails.type === summarizerClientElection_1.summarizerClientType) {
|
|
474
|
-
this._summarizer = new summarizer_1.Summarizer("/_summarizer", this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.
|
|
489
|
+
this._summarizer = new summarizer_1.Summarizer("/_summarizer", this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => runWhileConnectedCoordinator_1.RunWhileConnectedCoordinator.create(runtime));
|
|
475
490
|
}
|
|
476
491
|
else if (summarizerClientElection_1.SummarizerClientElection.clientDetailsPermitElection(this.context.clientDetails)) {
|
|
477
|
-
//
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
492
|
+
// Only create a SummaryManager and SummarizerClientElection
|
|
493
|
+
// if summaries are enabled and we are not the summarizer client.
|
|
494
|
+
const defaultAction = () => {
|
|
495
|
+
if (this.summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
|
|
496
|
+
this.logger.sendErrorEvent({ eventName: "SummaryStatus:Behind" });
|
|
497
|
+
// unregister default to no log on every op after falling behind
|
|
498
|
+
// and register summary ack handler to re-register this handler
|
|
499
|
+
// after successful summary
|
|
500
|
+
this.summaryCollection.once(protocol_definitions_1.MessageType.SummaryAck, () => {
|
|
501
|
+
this.logger.sendTelemetryEvent({ eventName: "SummaryStatus:CaughtUp" });
|
|
502
|
+
// we've caught up, so re-register the default action to monitor for
|
|
503
|
+
// falling behind, and unregister ourself
|
|
504
|
+
this.summaryCollection.on("default", defaultAction);
|
|
505
|
+
});
|
|
506
|
+
this.summaryCollection.off("default", defaultAction);
|
|
507
|
+
}
|
|
482
508
|
};
|
|
509
|
+
this.summaryCollection.on("default", defaultAction);
|
|
510
|
+
// Create the SummaryManager and mark the initial state
|
|
483
511
|
this.summaryManager = new summaryManager_1.SummaryManager(this.summarizerClientElection, this, // IConnectedState
|
|
484
|
-
this.summaryCollection, this.logger,
|
|
512
|
+
this.summaryCollection, this.logger, this.formRequestSummarizerFn(this.context.loader), new throttler_1.Throttler(60 * 1000, // 60 sec delay window
|
|
485
513
|
30 * 1000, // 30 sec max delay
|
|
486
514
|
// throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
|
|
487
515
|
throttler_1.formExponentialFn({ coefficient: 20, initialDelay: 0 })), {
|
|
@@ -494,7 +522,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
494
522
|
this.deltaManager.on("readonly", (readonly) => {
|
|
495
523
|
// we accumulate ops while being in read-only state.
|
|
496
524
|
// once user gets write permissions and we have active connection, flush all pending ops.
|
|
497
|
-
common_utils_1.assert(readonly === this.deltaManager.readonly, 0x124 /* "inconsistent readonly property/event state" */);
|
|
525
|
+
common_utils_1.assert(readonly === this.deltaManager.readOnlyInfo.readonly, 0x124 /* "inconsistent readonly property/event state" */);
|
|
498
526
|
// We need to be very careful with when we (re)send pending ops, to ensure that we only send ops
|
|
499
527
|
// when we either never send an op, or attempted to send it but we know for sure it was not
|
|
500
528
|
// sequenced by server and will never be sequenced (i.e. was lost)
|
|
@@ -513,6 +541,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
513
541
|
if (context.pendingLocalState !== undefined) {
|
|
514
542
|
this.deltaManager.on("op", this.onOp);
|
|
515
543
|
}
|
|
544
|
+
// logging hardware telemetry
|
|
545
|
+
logger.sendTelemetryEvent(Object.assign({ eventName: "DeviceSpec" }, getDeviceSpec()));
|
|
546
|
+
// logging container load stats
|
|
547
|
+
this.logger.sendTelemetryEvent(Object.assign(Object.assign(Object.assign({ eventName: "ContainerLoadStats" }, this.createContainerMetadata), this.dataStores.containerLoadStats), { summaryCount: this.summaryCount, summaryFormatVersion: metadata === null || metadata === void 0 ? void 0 : metadata.summaryFormatVersion, disableIsolatedChannels: metadata === null || metadata === void 0 ? void 0 : metadata.disableIsolatedChannels, gcVersion: metadata === null || metadata === void 0 ? void 0 : metadata.gcFeature }));
|
|
516
548
|
connectionTelemetry_1.ReportOpPerfTelemetry(this.context.clientId, this.deltaManager, this.logger);
|
|
517
549
|
}
|
|
518
550
|
get IContainerRuntime() { return this; }
|
|
@@ -526,7 +558,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
526
558
|
* @param existing - (optional) When loading from an existing snapshot. Precedes context.existing if provided
|
|
527
559
|
*/
|
|
528
560
|
static async load(context, registryEntries, requestHandler, runtimeOptions = {}, containerScope = context.scope, existing) {
|
|
529
|
-
var _a, _b, _c
|
|
561
|
+
var _a, _b, _c;
|
|
530
562
|
// If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
|
|
531
563
|
const passLogger = (_a = context.taggedLogger) !== null && _a !== void 0 ? _a : new telemetry_utils_1.TaggedLoggerAdapter(context.logger);
|
|
532
564
|
const logger = telemetry_utils_1.ChildLogger.create(passLogger, undefined, {
|
|
@@ -568,19 +600,22 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
568
600
|
return driver_utils_1.readAndParse(storage, blobId);
|
|
569
601
|
}
|
|
570
602
|
};
|
|
571
|
-
const chunks
|
|
572
|
-
|
|
573
|
-
|
|
603
|
+
const [chunks, metadata, electedSummarizerData, aliases] = await Promise.all([
|
|
604
|
+
tryFetchBlob(summaryFormat_1.chunksBlobName),
|
|
605
|
+
tryFetchBlob(summaryFormat_1.metadataBlobName),
|
|
606
|
+
tryFetchBlob(summaryFormat_1.electedSummarizerBlobName),
|
|
607
|
+
tryFetchBlob(summaryFormat_1.aliasBlobName),
|
|
608
|
+
]);
|
|
574
609
|
const loadExisting = existing === true || context.existing === true;
|
|
575
610
|
// read snapshot blobs needed for BlobManager to load
|
|
576
|
-
const blobManagerSnapshot = await blobManager_1.BlobManager.load((
|
|
611
|
+
const blobManagerSnapshot = await blobManager_1.BlobManager.load((_b = context.baseSnapshot) === null || _b === void 0 ? void 0 : _b.trees[summaryFormat_1.blobsTreeName], async (id) => {
|
|
577
612
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
578
613
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
579
614
|
common_utils_1.assert(storage !== undefined, 0x256 /* "storage undefined in attached container" */);
|
|
580
615
|
return driver_utils_1.readAndParse(storage, id);
|
|
581
616
|
});
|
|
582
617
|
// Verify summary runtime sequence number matches protocol sequence number.
|
|
583
|
-
const runtimeSequenceNumber = (
|
|
618
|
+
const runtimeSequenceNumber = (_c = metadata === null || metadata === void 0 ? void 0 : metadata.message) === null || _c === void 0 ? void 0 : _c.sequenceNumber;
|
|
584
619
|
if (runtimeSequenceNumber !== undefined) {
|
|
585
620
|
const protocolSequenceNumber = context.deltaManager.initialSequenceNumber;
|
|
586
621
|
// Unless bypass is explicitly set, then take action when sequence numbers mismatch.
|
|
@@ -595,13 +630,16 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
595
630
|
}
|
|
596
631
|
}
|
|
597
632
|
}
|
|
598
|
-
const runtime = new ContainerRuntime(context, registry, metadata, electedSummarizerData, chunks, {
|
|
633
|
+
const runtime = new ContainerRuntime(context, registry, metadata, electedSummarizerData, chunks !== null && chunks !== void 0 ? chunks : [], aliases !== null && aliases !== void 0 ? aliases : [], {
|
|
599
634
|
summaryOptions,
|
|
600
635
|
gcOptions,
|
|
601
636
|
loadSequenceNumberVerification,
|
|
602
637
|
}, containerScope, logger, loadExisting, blobManagerSnapshot, requestHandler, storage);
|
|
603
638
|
return runtime;
|
|
604
639
|
}
|
|
640
|
+
/**
|
|
641
|
+
* @deprecated This will be removed in a later release. Deprecated in 0.53
|
|
642
|
+
*/
|
|
605
643
|
get id() {
|
|
606
644
|
return this.context.id;
|
|
607
645
|
}
|
|
@@ -652,6 +690,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
652
690
|
get attachState() {
|
|
653
691
|
return this.context.attachState;
|
|
654
692
|
}
|
|
693
|
+
get IFluidHandleContext() {
|
|
694
|
+
return this.handleContext;
|
|
695
|
+
}
|
|
655
696
|
get connected() {
|
|
656
697
|
return this._connected;
|
|
657
698
|
}
|
|
@@ -665,13 +706,22 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
665
706
|
return Object.assign(Object.assign(Object.assign({}, DefaultSummaryConfiguration), (_b = (_a = this.context) === null || _a === void 0 ? void 0 : _a.serviceConfiguration) === null || _b === void 0 ? void 0 : _b.summary), (_c = this.runtimeOptions.summaryOptions) === null || _c === void 0 ? void 0 : _c.summaryConfigOverrides);
|
|
666
707
|
}
|
|
667
708
|
get disposed() { return this._disposed; }
|
|
668
|
-
|
|
669
|
-
|
|
709
|
+
/**
|
|
710
|
+
* True, if GC data should be written at root of the summary tree.
|
|
711
|
+
* False, if data stores should write GC blobs in their summary tree.
|
|
712
|
+
*/
|
|
713
|
+
get writeGCDataAtRoot() {
|
|
714
|
+
return this.garbageCollector.writeDataAtRoot;
|
|
670
715
|
}
|
|
671
716
|
get summarizer() {
|
|
672
717
|
common_utils_1.assert(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
|
|
673
718
|
return this._summarizer;
|
|
674
719
|
}
|
|
720
|
+
get summariesDisabled() {
|
|
721
|
+
var _a;
|
|
722
|
+
return this.runtimeOptions.summaryOptions.disableSummaries === true ||
|
|
723
|
+
((_a = this.runtimeOptions.summaryOptions.summaryConfigOverrides) === null || _a === void 0 ? void 0 : _a.disableSummaries) === true;
|
|
724
|
+
}
|
|
675
725
|
dispose(error) {
|
|
676
726
|
var _a;
|
|
677
727
|
if (this._disposed) {
|
|
@@ -785,14 +835,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
785
835
|
}
|
|
786
836
|
formMetadata() {
|
|
787
837
|
var _a;
|
|
788
|
-
return {
|
|
789
|
-
summaryFormatVersion: 1,
|
|
790
|
-
disableIsolatedChannels: this.disableIsolatedChannels || undefined,
|
|
791
|
-
gcFeature: this.garbageCollector.gcSummaryFeatureVersion,
|
|
838
|
+
return Object.assign(Object.assign({}, this.createContainerMetadata), { summaryCount: this.summaryCount, summaryFormatVersion: 1, disableIsolatedChannels: this.disableIsolatedChannels || undefined, gcFeature: this.garbageCollector.gcSummaryFeatureVersion,
|
|
792
839
|
// The last message processed at the time of summary. If there are no messages, nothing has changed from
|
|
793
840
|
// the base summary we loaded from. So, use the message from its metadata blob.
|
|
794
|
-
message: (_a = summaryFormat_1.extractSummaryMetadataMessage(this.deltaManager.lastMessage)) !== null && _a !== void 0 ? _a : this.baseSummaryMessage
|
|
795
|
-
};
|
|
841
|
+
message: (_a = summaryFormat_1.extractSummaryMetadataMessage(this.deltaManager.lastMessage)) !== null && _a !== void 0 ? _a : this.baseSummaryMessage });
|
|
796
842
|
}
|
|
797
843
|
/**
|
|
798
844
|
* Retrieves the runtime for a data store if it's referenced as per the initially summary that it is loaded with.
|
|
@@ -819,22 +865,14 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
819
865
|
* @deprecated - Use summarize to get summary of the container runtime.
|
|
820
866
|
*/
|
|
821
867
|
async snapshot() {
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
else {
|
|
831
|
-
root.entries.push(new protocol_base_1.TreeTreeEntry(runtime_definitions_1.channelsTreeName, { entries }));
|
|
832
|
-
}
|
|
833
|
-
root.entries.push(new protocol_base_1.BlobTreeEntry(summaryFormat_1.metadataBlobName, JSON.stringify(this.formMetadata())));
|
|
834
|
-
if (this.chunkMap.size > 0) {
|
|
835
|
-
root.entries.push(new protocol_base_1.BlobTreeEntry(summaryFormat_1.chunksBlobName, JSON.stringify([...this.chunkMap])));
|
|
836
|
-
}
|
|
837
|
-
return root;
|
|
868
|
+
const summaryResult = await this.summarize({
|
|
869
|
+
summaryLogger: this.logger,
|
|
870
|
+
fullTree: true,
|
|
871
|
+
trackState: false,
|
|
872
|
+
runGC: this.garbageCollector.shouldRunGC,
|
|
873
|
+
fullGC: true,
|
|
874
|
+
});
|
|
875
|
+
return runtime_utils_1.convertSummaryTreeToITree(summaryResult.summary);
|
|
838
876
|
}
|
|
839
877
|
addContainerBlobsToSummary(summaryTree) {
|
|
840
878
|
var _a;
|
|
@@ -843,6 +881,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
843
881
|
const content = JSON.stringify([...this.chunkMap]);
|
|
844
882
|
runtime_utils_1.addBlobToSummary(summaryTree, summaryFormat_1.chunksBlobName, content);
|
|
845
883
|
}
|
|
884
|
+
const dataStoreAliases = this.dataStores.aliases();
|
|
885
|
+
if (dataStoreAliases.size > 0) {
|
|
886
|
+
runtime_utils_1.addBlobToSummary(summaryTree, summaryFormat_1.aliasBlobName, JSON.stringify([...dataStoreAliases]));
|
|
887
|
+
}
|
|
846
888
|
if (this.summarizerClientElection) {
|
|
847
889
|
const electedSummarizerContent = JSON.stringify((_a = this.summarizerClientElection) === null || _a === void 0 ? void 0 : _a.serialize());
|
|
848
890
|
runtime_utils_1.addBlobToSummary(summaryTree, summaryFormat_1.electedSummarizerBlobName, electedSummarizerContent);
|
|
@@ -854,6 +896,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
854
896
|
const blobsTree = runtime_utils_1.convertToSummaryTree(snapshot, false);
|
|
855
897
|
runtime_utils_1.addTreeToSummary(summaryTree, summaryFormat_1.blobsTreeName, blobsTree);
|
|
856
898
|
}
|
|
899
|
+
if (this.writeGCDataAtRoot) {
|
|
900
|
+
const gcSummary = this.garbageCollector.summarize();
|
|
901
|
+
if (gcSummary !== undefined) {
|
|
902
|
+
runtime_utils_1.addTreeToSummary(summaryTree, garbageCollection_1.gcTreeKey, gcSummary);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
857
905
|
}
|
|
858
906
|
replayPendingStates() {
|
|
859
907
|
// We need to be able to send ops to replay states
|
|
@@ -888,6 +936,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
888
936
|
return this.dataStores.applyStashedOp(op);
|
|
889
937
|
case ContainerMessageType.Attach:
|
|
890
938
|
return this.dataStores.applyStashedAttachOp(op);
|
|
939
|
+
case ContainerMessageType.Alias:
|
|
891
940
|
case ContainerMessageType.BlobAttach:
|
|
892
941
|
return;
|
|
893
942
|
case ContainerMessageType.ChunkedOp:
|
|
@@ -909,7 +958,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
909
958
|
this.replayPendingStates();
|
|
910
959
|
}
|
|
911
960
|
this.dataStores.setConnectionState(connected, clientId);
|
|
912
|
-
telemetry_utils_1.raiseConnectedEvent(this.
|
|
961
|
+
telemetry_utils_1.raiseConnectedEvent(this.mc.logger, this, connected, clientId);
|
|
913
962
|
}
|
|
914
963
|
process(messageArg, local) {
|
|
915
964
|
var _a;
|
|
@@ -943,6 +992,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
943
992
|
case ContainerMessageType.Attach:
|
|
944
993
|
this.dataStores.processAttachMessage(message, local || localAck);
|
|
945
994
|
break;
|
|
995
|
+
case ContainerMessageType.Alias:
|
|
996
|
+
this.processAliasMessage(message, localOpMetadata, local);
|
|
997
|
+
break;
|
|
946
998
|
case ContainerMessageType.FluidDataStoreOp:
|
|
947
999
|
// if localAck === true, treat this as a local op because it's one we sent on a previous container
|
|
948
1000
|
this.dataStores.processFluidDataStoreOp(message, local || localAck, localOpMetadata);
|
|
@@ -961,6 +1013,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
961
1013
|
throw e;
|
|
962
1014
|
}
|
|
963
1015
|
}
|
|
1016
|
+
processAliasMessage(message, localOpMetadata, local) {
|
|
1017
|
+
this.dataStores.processAliasMessage(message, localOpMetadata, local);
|
|
1018
|
+
}
|
|
964
1019
|
processSignal(message, local) {
|
|
965
1020
|
const envelope = message.content;
|
|
966
1021
|
const transformed = {
|
|
@@ -1010,6 +1065,11 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1010
1065
|
return;
|
|
1011
1066
|
}
|
|
1012
1067
|
this.needsFlush = false;
|
|
1068
|
+
// Did we disconnect in the middle of turn-based batch?
|
|
1069
|
+
// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.
|
|
1070
|
+
if (!this.canSendOps()) {
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1013
1073
|
return this.deltaSender.flush();
|
|
1014
1074
|
}
|
|
1015
1075
|
orderSequentially(callback) {
|
|
@@ -1026,11 +1086,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1026
1086
|
this.setFlushMode(runtime_definitions_1.FlushMode.TurnBased);
|
|
1027
1087
|
try {
|
|
1028
1088
|
this.trackOrderSequentiallyCalls(callback);
|
|
1029
|
-
}
|
|
1030
|
-
finally {
|
|
1031
1089
|
this.flush();
|
|
1032
1090
|
this.setFlushMode(savedFlushMode);
|
|
1033
1091
|
}
|
|
1092
|
+
catch (error) {
|
|
1093
|
+
this.closeFn(container_utils_1.CreateProcessingError(error, "orderSequentially"));
|
|
1094
|
+
}
|
|
1034
1095
|
}
|
|
1035
1096
|
trackOrderSequentiallyCalls(callback) {
|
|
1036
1097
|
try {
|
|
@@ -1186,27 +1247,33 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1186
1247
|
* Implementation of IGarbageCollectionRuntime::updateUsedRoutes.
|
|
1187
1248
|
* After GC has run, called to notify this container's nodes of routes that are used in it.
|
|
1188
1249
|
* @param usedRoutes - The routes that are used in all nodes in this Container.
|
|
1250
|
+
* @param gcTimestamp - The time when GC was run that generated these used routes. If any node node becomes
|
|
1251
|
+
* unreferenced as part of this GC run, this should be used to update the time when it happens.
|
|
1189
1252
|
* @returns the statistics of the used state of the data stores.
|
|
1190
1253
|
*/
|
|
1191
|
-
updateUsedRoutes(usedRoutes) {
|
|
1192
|
-
var _a;
|
|
1254
|
+
updateUsedRoutes(usedRoutes, gcTimestamp) {
|
|
1193
1255
|
// Update our summarizer node's used routes. Updating used routes in summarizer node before
|
|
1194
1256
|
// summarizing is required and asserted by the the summarizer node. We are the root and are
|
|
1195
1257
|
// always referenced, so the used routes is only self-route (empty string).
|
|
1196
1258
|
this.summarizerNode.updateUsedRoutes([""]);
|
|
1197
|
-
return this.dataStores.updateUsedRoutes(usedRoutes,
|
|
1198
|
-
// For now, we use the timestamp of the last op for gcTimestamp. However, there can be cases where
|
|
1199
|
-
// we don't have an op (on demand summaries for instance). In those cases, we will use the timestamp
|
|
1200
|
-
// of this client's connection - https://github.com/microsoft/FluidFramework/issues/7152.
|
|
1201
|
-
this.deltaManager.lastMessage) === null || _a === void 0 ? void 0 : _a.timestamp);
|
|
1259
|
+
return this.dataStores.updateUsedRoutes(usedRoutes, gcTimestamp);
|
|
1202
1260
|
}
|
|
1203
1261
|
/**
|
|
1204
|
-
* Runs garbage collection and
|
|
1262
|
+
* Runs garbage collection and updates the reference / used state of the nodes in the container.
|
|
1205
1263
|
* @returns the statistics of the garbage collection run.
|
|
1206
1264
|
*/
|
|
1207
1265
|
async collectGarbage(options) {
|
|
1208
1266
|
return this.garbageCollector.collectGarbage(options);
|
|
1209
1267
|
}
|
|
1268
|
+
/**
|
|
1269
|
+
* Called when a new outbound reference is added to another node. This is used by garbage collection to identify
|
|
1270
|
+
* all references added in the system.
|
|
1271
|
+
* @param srcHandle - The handle of the node that added the reference.
|
|
1272
|
+
* @param outboundHandle - The handle of the outbound node that is referenced.
|
|
1273
|
+
*/
|
|
1274
|
+
addedGCOutboundReference(srcHandle, outboundHandle) {
|
|
1275
|
+
this.garbageCollector.addedOutboundReference(srcHandle.absolutePath, outboundHandle.absolutePath);
|
|
1276
|
+
}
|
|
1210
1277
|
/**
|
|
1211
1278
|
* Generates the summary tree, uploads it to storage, and then submits the summarize op.
|
|
1212
1279
|
* This is intended to be called by the summarizer, since it is the implementation of
|
|
@@ -1266,6 +1333,13 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1266
1333
|
if (!continueResult.continue) {
|
|
1267
1334
|
return { stage: "base", referenceSequenceNumber: summaryRefSeqNum, error: continueResult.error };
|
|
1268
1335
|
}
|
|
1336
|
+
// increment summary count
|
|
1337
|
+
if (this.summaryCount !== undefined) {
|
|
1338
|
+
this.summaryCount++;
|
|
1339
|
+
}
|
|
1340
|
+
else {
|
|
1341
|
+
this.summaryCount = 1;
|
|
1342
|
+
}
|
|
1269
1343
|
const trace = common_utils_1.Trace.start();
|
|
1270
1344
|
let summarizeResult;
|
|
1271
1345
|
try {
|
|
@@ -1389,10 +1463,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1389
1463
|
this.dirtyContainer = dirty;
|
|
1390
1464
|
if (this.emitDirtyDocumentEvent) {
|
|
1391
1465
|
this.emit(dirty ? "dirty" : "saved");
|
|
1392
|
-
|
|
1393
|
-
if (this.context.updateDirtyContainerState !== undefined) {
|
|
1394
|
-
this.context.updateDirtyContainerState(dirty);
|
|
1395
|
-
}
|
|
1466
|
+
this.context.updateDirtyContainerState(dirty);
|
|
1396
1467
|
}
|
|
1397
1468
|
}
|
|
1398
1469
|
submitDataStoreOp(id, contents, localOpMetadata = undefined) {
|
|
@@ -1473,7 +1544,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1473
1544
|
// That might be not what caller hopes to get, but we can look deeper if telemetry tells us it's a problem.
|
|
1474
1545
|
const middleOfBatch = this.flushMode === runtime_definitions_1.FlushMode.TurnBased && this.needsFlush;
|
|
1475
1546
|
if (middleOfBatch) {
|
|
1476
|
-
this.
|
|
1547
|
+
this.mc.logger.sendErrorEvent({ eventName: "submitSystemMessageError", type });
|
|
1477
1548
|
}
|
|
1478
1549
|
return this.context.submitFn(type, contents, middleOfBatch);
|
|
1479
1550
|
}
|
|
@@ -1506,6 +1577,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1506
1577
|
this.dataStores.resubmitDataStoreOp(content, localOpMetadata);
|
|
1507
1578
|
break;
|
|
1508
1579
|
case ContainerMessageType.Attach:
|
|
1580
|
+
case ContainerMessageType.Alias:
|
|
1509
1581
|
this.submit(type, content, localOpMetadata);
|
|
1510
1582
|
break;
|
|
1511
1583
|
case ContainerMessageType.ChunkedOp:
|
|
@@ -1537,7 +1609,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1537
1609
|
* @returns downloaded snapshot's reference sequence number
|
|
1538
1610
|
*/
|
|
1539
1611
|
async refreshLatestSummaryAckFromServer(summaryLogger) {
|
|
1540
|
-
const snapshot = await this.fetchSnapshotFromStorage(
|
|
1612
|
+
const snapshot = await this.fetchSnapshotFromStorage(null, summaryLogger, {
|
|
1541
1613
|
eventName: "RefreshLatestSummaryGetSnapshot",
|
|
1542
1614
|
fetchLatest: true,
|
|
1543
1615
|
});
|
|
@@ -1566,12 +1638,30 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1566
1638
|
return this.pendingStateManager.getLocalState();
|
|
1567
1639
|
}
|
|
1568
1640
|
/**
|
|
1569
|
-
*
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
return
|
|
1574
|
-
|
|
1641
|
+
* * Forms a function that will request a Summarizer.
|
|
1642
|
+
* @param loaderRouter - the loader acting as an IFluidRouter
|
|
1643
|
+
* */
|
|
1644
|
+
formRequestSummarizerFn(loaderRouter) {
|
|
1645
|
+
return async () => {
|
|
1646
|
+
const request = {
|
|
1647
|
+
headers: {
|
|
1648
|
+
[container_definitions_1.LoaderHeader.cache]: false,
|
|
1649
|
+
[container_definitions_1.LoaderHeader.clientDetails]: {
|
|
1650
|
+
capabilities: { interactive: false },
|
|
1651
|
+
type: summarizerClientElection_1.summarizerClientType,
|
|
1652
|
+
},
|
|
1653
|
+
[driver_definitions_1.DriverHeader.summarizingClient]: true,
|
|
1654
|
+
[container_definitions_1.LoaderHeader.reconnect]: false,
|
|
1655
|
+
},
|
|
1656
|
+
url: "/_summarizer",
|
|
1657
|
+
};
|
|
1658
|
+
const fluidObject = await runtime_utils_1.requestFluidObject(loaderRouter, request);
|
|
1659
|
+
const summarizer = fluidObject.ISummarizer;
|
|
1660
|
+
if (!summarizer) {
|
|
1661
|
+
throw new container_utils_1.UsageError("Fluid object does not implement ISummarizer");
|
|
1662
|
+
}
|
|
1663
|
+
return summarizer;
|
|
1664
|
+
};
|
|
1575
1665
|
}
|
|
1576
1666
|
}
|
|
1577
1667
|
exports.ContainerRuntime = ContainerRuntime;
|