@fluidframework/container-runtime 2.0.0-internal.5.3.1 → 2.0.0-internal.5.4.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/CHANGELOG.md +9 -0
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +9 -1
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +55 -12
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +2 -2
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +43 -11
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +189 -137
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +3 -0
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +24 -27
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.js +1 -1
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStores.d.ts +1 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +14 -24
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js +2 -0
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +5 -5
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +12 -5
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +1 -0
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +1 -0
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +15 -22
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/id-compressor/idCompressor.d.ts +3 -3
- package/dist/id-compressor/idCompressor.d.ts.map +1 -1
- package/dist/id-compressor/idCompressor.js +3 -1
- package/dist/id-compressor/idCompressor.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts +2 -2
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +1 -1
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +2 -2
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +1 -1
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +2 -2
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +1 -1
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +6 -5
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +5 -12
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +6 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +7 -1
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +4 -1
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +21 -12
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +1 -1
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +1 -1
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +3 -5
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +10 -28
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.js +1 -1
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +5 -5
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +7 -10
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +4 -3
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +4 -8
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +5 -1
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +2 -3
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +6 -2
- package/dist/summary/summaryManager.js.map +1 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -2
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +9 -1
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +55 -12
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +3 -3
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +43 -11
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +188 -137
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js +3 -0
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +26 -29
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.js +2 -2
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStores.d.ts +1 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +15 -25
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/lib/deltaManagerSummarizerProxy.js +2 -0
- package/lib/deltaManagerSummarizerProxy.js.map +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +6 -6
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +13 -6
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +1 -0
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +1 -0
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +16 -23
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/id-compressor/idCompressor.d.ts +3 -3
- package/lib/id-compressor/idCompressor.d.ts.map +1 -1
- package/lib/id-compressor/idCompressor.js +3 -1
- package/lib/id-compressor/idCompressor.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts +2 -2
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +2 -2
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts +2 -2
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +2 -2
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +2 -2
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +2 -2
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +6 -5
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +6 -13
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +6 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +7 -1
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +4 -1
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +21 -12
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +2 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +2 -2
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +3 -5
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +11 -29
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.js +2 -2
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +5 -5
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +8 -11
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +4 -3
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +5 -9
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +6 -2
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +2 -3
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +7 -3
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +16 -16
- package/src/batchTracker.ts +2 -2
- package/src/blobManager.ts +70 -13
- package/src/connectionTelemetry.ts +7 -3
- package/src/containerRuntime.ts +287 -150
- package/src/dataStore.ts +3 -0
- package/src/dataStoreContext.ts +31 -33
- package/src/dataStoreContexts.ts +2 -2
- package/src/dataStores.ts +15 -18
- package/src/deltaManagerSummarizerProxy.ts +2 -0
- package/src/deltaScheduler.ts +6 -10
- package/src/gc/garbageCollection.ts +13 -8
- package/src/gc/gcHelpers.ts +1 -0
- package/src/gc/gcTelemetry.ts +12 -8
- package/src/id-compressor/idCompressor.ts +6 -5
- package/src/opLifecycle/opCompressor.ts +4 -3
- package/src/opLifecycle/opDecompressor.ts +4 -3
- package/src/opLifecycle/opSplitter.ts +4 -3
- package/src/opLifecycle/outbox.ts +13 -25
- package/src/opLifecycle/remoteMessageProcessor.ts +8 -2
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +22 -10
- package/src/scheduleManager.ts +2 -2
- package/src/summary/orderedClientElection.ts +2 -2
- package/src/summary/runningSummarizer.ts +18 -44
- package/src/summary/summarizer.ts +2 -2
- package/src/summary/summarizerNode/summarizerNode.ts +13 -15
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +8 -7
- package/src/summary/summaryGenerator.ts +6 -2
- package/src/summary/summaryManager.ts +9 -5
package/lib/containerRuntime.js
CHANGED
|
@@ -12,7 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import { AttachState, LoaderHeader, } from "@fluidframework/container-definitions";
|
|
13
13
|
import { assert, delay, Trace, TypedEventEmitter, unreachableCase, } from "@fluidframework/common-utils";
|
|
14
14
|
import { LazyPromise } from "@fluidframework/core-utils";
|
|
15
|
-
import {
|
|
15
|
+
import { createChildLogger, raiseConnectedEvent, PerformanceEvent, TaggedLoggerAdapter, wrapError, createChildMonitoringContext, } from "@fluidframework/telemetry-utils";
|
|
16
16
|
import { DriverHeader, FetchSource, } from "@fluidframework/driver-definitions";
|
|
17
17
|
import { readAndParse } from "@fluidframework/driver-utils";
|
|
18
18
|
import { DataCorruptionError, DataProcessingError, GenericError, UsageError, } from "@fluidframework/container-utils";
|
|
@@ -115,7 +115,7 @@ const defaultChunkSizeInBytes = 204800;
|
|
|
115
115
|
* of the current system, we should close the summarizer and let it recover.
|
|
116
116
|
* This delay's goal is to prevent tight restart loops
|
|
117
117
|
*/
|
|
118
|
-
const defaultCloseSummarizerDelayMs =
|
|
118
|
+
const defaultCloseSummarizerDelayMs = 5000; // 5 seconds
|
|
119
119
|
/**
|
|
120
120
|
* @deprecated - use ContainerRuntimeMessage instead
|
|
121
121
|
*/
|
|
@@ -154,6 +154,20 @@ export function getDeviceSpec() {
|
|
|
154
154
|
catch (_a) { }
|
|
155
155
|
return {};
|
|
156
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Older loader doesn't have a submitBatchFn member, this is the older way of submitting a batch.
|
|
159
|
+
* Rather than exposing the submitFn (now deprecated) and IDeltaManager (dangerous to hand out) to the Outbox,
|
|
160
|
+
* we can provide a partially-applied function to keep those items private to the ContainerRuntime.
|
|
161
|
+
*/
|
|
162
|
+
export const makeLegacySendBatchFn = (submitFn, deltaManager) => (batch) => {
|
|
163
|
+
for (const message of batch.content) {
|
|
164
|
+
submitFn(MessageType.Operation,
|
|
165
|
+
// For back-compat (submitFn only works on deserialized content)
|
|
166
|
+
message.contents === undefined ? undefined : JSON.parse(message.contents), true, // batch
|
|
167
|
+
message.metadata);
|
|
168
|
+
}
|
|
169
|
+
deltaManager.flush();
|
|
170
|
+
};
|
|
157
171
|
/**
|
|
158
172
|
* Represents the runtime of the container. Contains helper functions/state of the container.
|
|
159
173
|
* It will define the store level mappings.
|
|
@@ -166,7 +180,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
166
180
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
167
181
|
if (summaryConfiguration === void 0) { summaryConfiguration = Object.assign(Object.assign({}, DefaultSummaryConfiguration), (_a = runtimeOptions.summaryOptions) === null || _a === void 0 ? void 0 : _a.summaryConfigOverrides); }
|
|
168
182
|
super();
|
|
169
|
-
this.context = context;
|
|
170
183
|
this.registry = registry;
|
|
171
184
|
this.runtimeOptions = runtimeOptions;
|
|
172
185
|
this.containerScope = containerScope;
|
|
@@ -196,7 +209,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
196
209
|
trackingSignalSequenceNumber: undefined,
|
|
197
210
|
};
|
|
198
211
|
this.summarizeOnDemand = (...args) => {
|
|
199
|
-
if (this.
|
|
212
|
+
if (this.isSummarizerClient) {
|
|
200
213
|
return this.summarizer.summarizeOnDemand(...args);
|
|
201
214
|
}
|
|
202
215
|
else if (this.summaryManager !== undefined) {
|
|
@@ -210,7 +223,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
210
223
|
}
|
|
211
224
|
};
|
|
212
225
|
this.enqueueSummarize = (...args) => {
|
|
213
|
-
if (this.
|
|
226
|
+
if (this.isSummarizerClient) {
|
|
214
227
|
return this.summarizer.enqueueSummarize(...args);
|
|
215
228
|
}
|
|
216
229
|
else if (this.summaryManager !== undefined) {
|
|
@@ -223,9 +236,48 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
223
236
|
throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
224
237
|
}
|
|
225
238
|
};
|
|
226
|
-
|
|
227
|
-
this.
|
|
228
|
-
this.
|
|
239
|
+
const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, loader, pendingLocalState, supportedFeatures, } = context;
|
|
240
|
+
this.innerDeltaManager = deltaManager;
|
|
241
|
+
this.deltaManager = new DeltaManagerSummarizerProxy(this.innerDeltaManager);
|
|
242
|
+
// Here we could wrap/intercept on these functions to block/modify outgoing messages if needed.
|
|
243
|
+
// This makes ContainerRuntime the final gatekeeper for outgoing messages.
|
|
244
|
+
this.submitFn = submitFn;
|
|
245
|
+
this.submitBatchFn = submitBatchFn;
|
|
246
|
+
this.submitSummaryFn = submitSummaryFn;
|
|
247
|
+
this.submitSignalFn = submitSignalFn;
|
|
248
|
+
this.options = options;
|
|
249
|
+
this.clientDetails = clientDetails;
|
|
250
|
+
this.isSummarizerClient = this.clientDetails.type === summarizerClientType;
|
|
251
|
+
this.loadedFromVersionId = (_b = context.getLoadedFromVersion()) === null || _b === void 0 ? void 0 : _b.id;
|
|
252
|
+
this._getClientId = () => context.clientId;
|
|
253
|
+
this._getAttachState = () => context.attachState;
|
|
254
|
+
this.getAbsoluteUrl = async (relativeUrl) => {
|
|
255
|
+
if (context.getAbsoluteUrl === undefined) {
|
|
256
|
+
throw new Error("Driver does not implement getAbsoluteUrl");
|
|
257
|
+
}
|
|
258
|
+
if (this.attachState !== AttachState.Attached) {
|
|
259
|
+
return undefined;
|
|
260
|
+
}
|
|
261
|
+
return context.getAbsoluteUrl(relativeUrl);
|
|
262
|
+
};
|
|
263
|
+
// TODO: Consider that the Container could just listen to these events itself, or even more appropriately maybe the
|
|
264
|
+
// customer should observe dirty state on the runtime (the owner of dirty state) directly, rather than on the IContainer.
|
|
265
|
+
this.on("dirty", () => context.updateDirtyContainerState(true));
|
|
266
|
+
this.on("saved", () => context.updateDirtyContainerState(false));
|
|
267
|
+
// In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
|
|
268
|
+
this.disposeFn = disposeFn !== null && disposeFn !== void 0 ? disposeFn : closeFn;
|
|
269
|
+
// In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
|
|
270
|
+
this.closeFn = this.isSummarizerClient
|
|
271
|
+
? this.disposeFn
|
|
272
|
+
: (error) => {
|
|
273
|
+
closeFn(error);
|
|
274
|
+
// Also call disposeFn to retain functionality of runtime being disposed on close
|
|
275
|
+
disposeFn === null || disposeFn === void 0 ? void 0 : disposeFn(error);
|
|
276
|
+
};
|
|
277
|
+
this.mc = createChildMonitoringContext({
|
|
278
|
+
logger: this.logger,
|
|
279
|
+
namespace: "ContainerRuntime",
|
|
280
|
+
});
|
|
229
281
|
let loadSummaryNumber;
|
|
230
282
|
// Get the container creation metadata. For new container, we initialize these. For existing containers,
|
|
231
283
|
// get the values from the metadata blob.
|
|
@@ -236,10 +288,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
236
288
|
};
|
|
237
289
|
// summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
|
|
238
290
|
// the count is reset to 0.
|
|
239
|
-
loadSummaryNumber = (
|
|
291
|
+
loadSummaryNumber = (_c = metadata === null || metadata === void 0 ? void 0 : metadata.summaryNumber) !== null && _c !== void 0 ? _c : 0;
|
|
240
292
|
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
241
293
|
// allow new containers to turn it on
|
|
242
|
-
this.idCompressorEnabled = (
|
|
294
|
+
this.idCompressorEnabled = (_d = metadata === null || metadata === void 0 ? void 0 : metadata.idCompressorEnabled) !== null && _d !== void 0 ? _d : false;
|
|
243
295
|
}
|
|
244
296
|
else {
|
|
245
297
|
this.createContainerMetadata = {
|
|
@@ -248,12 +300,14 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
248
300
|
};
|
|
249
301
|
loadSummaryNumber = 0;
|
|
250
302
|
this.idCompressorEnabled =
|
|
251
|
-
(
|
|
303
|
+
(_e = this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled")) !== null && _e !== void 0 ? _e : idCompressor !== undefined;
|
|
252
304
|
}
|
|
253
305
|
this.nextSummaryNumber = loadSummaryNumber + 1;
|
|
254
306
|
this.messageAtLastSummary = metadata === null || metadata === void 0 ? void 0 : metadata.message;
|
|
255
|
-
|
|
256
|
-
|
|
307
|
+
// Note that we only need to pull the *initial* connected state from the context.
|
|
308
|
+
// Later updates come through calls to setConnectionState.
|
|
309
|
+
this._connected = connected;
|
|
310
|
+
this.gcTombstoneEnforcementAllowed = shouldAllowGcTombstoneEnforcement((_f = metadata === null || metadata === void 0 ? void 0 : metadata.gcFeatureMatrix) === null || _f === void 0 ? void 0 : _f.tombstoneGeneration /* persisted */, this.runtimeOptions.gcOptions[gcTombstoneGenerationOptionName] /* current */);
|
|
257
311
|
this.mc.logger.sendTelemetryEvent({
|
|
258
312
|
eventName: "GCFeatureMatrix",
|
|
259
313
|
metadataValue: JSON.stringify(metadata === null || metadata === void 0 ? void 0 : metadata.gcFeatureMatrix),
|
|
@@ -261,11 +315,11 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
261
315
|
gcOptions_gcTombstoneGeneration: this.runtimeOptions.gcOptions[gcTombstoneGenerationOptionName],
|
|
262
316
|
}),
|
|
263
317
|
});
|
|
264
|
-
this.telemetryDocumentId = (
|
|
318
|
+
this.telemetryDocumentId = (_g = metadata === null || metadata === void 0 ? void 0 : metadata.telemetryDocumentId) !== null && _g !== void 0 ? _g : uuid();
|
|
265
319
|
this.disableAttachReorder = this.mc.config.getBoolean("Fluid.ContainerRuntime.disableAttachOpReorder");
|
|
266
320
|
const disableChunking = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionChunkingDisabled");
|
|
267
321
|
const opGroupingManager = new OpGroupingManager(this.groupedBatchingEnabled);
|
|
268
|
-
const opSplitter = new OpSplitter(chunks, this.
|
|
322
|
+
const opSplitter = new OpSplitter(chunks, this.submitBatchFn, disableChunking === true ? Number.POSITIVE_INFINITY : runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
|
|
269
323
|
this.remoteMessageProcessor = new RemoteMessageProcessor(opSplitter, new OpDecompressor(this.mc.logger), opGroupingManager);
|
|
270
324
|
this.handleContext = new ContainerFluidHandleContext("", this);
|
|
271
325
|
if (this.summaryConfiguration.state === "enabled") {
|
|
@@ -284,9 +338,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
284
338
|
this.idCompressor = idCompressor;
|
|
285
339
|
}
|
|
286
340
|
this.maxConsecutiveReconnects =
|
|
287
|
-
(
|
|
341
|
+
(_h = this.mc.config.getNumber(maxConsecutiveReconnectsKey)) !== null && _h !== void 0 ? _h : this.defaultMaxConsecutiveReconnects;
|
|
288
342
|
if (runtimeOptions.flushMode === FlushModeExperimental.Async &&
|
|
289
|
-
(
|
|
343
|
+
(supportedFeatures === null || supportedFeatures === void 0 ? void 0 : supportedFeatures.get("referenceSequenceNumbers")) !== true) {
|
|
290
344
|
// The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
|
|
291
345
|
this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
|
|
292
346
|
this._flushMode = FlushMode.TurnBased;
|
|
@@ -294,7 +348,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
294
348
|
else {
|
|
295
349
|
this._flushMode = runtimeOptions.flushMode;
|
|
296
350
|
}
|
|
297
|
-
const pendingRuntimeState =
|
|
351
|
+
const pendingRuntimeState = pendingLocalState;
|
|
298
352
|
const maxSnapshotCacheDurationMs = (_k = (_j = this._storage) === null || _j === void 0 ? void 0 : _j.policies) === null || _k === void 0 ? void 0 : _k.maximumCacheDurationMs;
|
|
299
353
|
if (maxSnapshotCacheDurationMs !== undefined &&
|
|
300
354
|
maxSnapshotCacheDurationMs > 5 * 24 * 60 * 60 * 1000) {
|
|
@@ -306,12 +360,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
306
360
|
this.garbageCollector = GarbageCollector.create({
|
|
307
361
|
runtime: this,
|
|
308
362
|
gcOptions: this.runtimeOptions.gcOptions,
|
|
309
|
-
baseSnapshot
|
|
363
|
+
baseSnapshot,
|
|
310
364
|
baseLogger: this.mc.logger,
|
|
311
365
|
existing,
|
|
312
366
|
metadata,
|
|
313
367
|
createContainerMetadata: this.createContainerMetadata,
|
|
314
|
-
isSummarizerClient: this.
|
|
368
|
+
isSummarizerClient: this.isSummarizerClient,
|
|
315
369
|
getNodePackagePath: async (nodePath) => this.getGCNodePackagePath(nodePath),
|
|
316
370
|
getLastSummaryTimestampMs: () => { var _a; return (_a = this.messageAtLastSummary) === null || _a === void 0 ? void 0 : _a.timestamp; },
|
|
317
371
|
readAndParseBlob: async (id) => readAndParse(this.storage, id),
|
|
@@ -320,13 +374,13 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
320
374
|
activeConnection: () => this.innerDeltaManager.active,
|
|
321
375
|
});
|
|
322
376
|
const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
|
|
323
|
-
this.summarizerNode = createRootSummarizerNodeWithGC(
|
|
377
|
+
this.summarizerNode = createRootSummarizerNodeWithGC(createChildLogger({ logger: this.logger, namespace: "SummarizerNode" }),
|
|
324
378
|
// Summarize function to call when summarize is called. Summarizer node always tracks summary state.
|
|
325
379
|
async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext),
|
|
326
380
|
// Latest change sequence number, no changes since summary applied yet
|
|
327
381
|
loadedFromSequenceNumber,
|
|
328
382
|
// Summary reference sequence number, undefined if no summary yet
|
|
329
|
-
|
|
383
|
+
baseSnapshot !== undefined ? loadedFromSequenceNumber : undefined, {
|
|
330
384
|
// Must set to false to prevent sending summary handle which would be pointing to
|
|
331
385
|
// a summary with an older protocol state.
|
|
332
386
|
canReuseHandle: false,
|
|
@@ -340,19 +394,19 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
340
394
|
async (fullGC) => this.getGCDataInternal(fullGC),
|
|
341
395
|
// Function to get the GC details from the base snapshot we loaded from.
|
|
342
396
|
async () => this.garbageCollector.getBaseGCDetails());
|
|
343
|
-
if (
|
|
344
|
-
this.summarizerNode.updateBaseSummaryState(
|
|
397
|
+
if (baseSnapshot) {
|
|
398
|
+
this.summarizerNode.updateBaseSummaryState(baseSnapshot);
|
|
345
399
|
}
|
|
346
|
-
this.dataStores = new DataStores(getSummaryForDatastores(
|
|
400
|
+
this.dataStores = new DataStores(getSummaryForDatastores(baseSnapshot, metadata), this, (attachMsg) => this.submit({ type: ContainerMessageType.Attach, contents: attachMsg }), (id, createParam) => (summarizeInternal, getGCDataFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), (path) => this.garbageCollector.isNodeDeleted(path), new Map(dataStoreAliasMap));
|
|
347
401
|
this.blobManager = new BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (localId, blobId) => {
|
|
348
402
|
if (!this.disposed) {
|
|
349
|
-
this.submit(ContainerMessageType.BlobAttach, undefined, undefined, {
|
|
403
|
+
this.submit({ type: ContainerMessageType.BlobAttach, contents: undefined }, undefined, {
|
|
350
404
|
localId,
|
|
351
405
|
blobId,
|
|
352
406
|
});
|
|
353
407
|
}
|
|
354
408
|
}, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), (blobPath) => this.garbageCollector.isNodeDeleted(blobPath), this, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pendingAttachmentBlobs, (error) => this.closeFn(error));
|
|
355
|
-
this.scheduleManager = new ScheduleManager(
|
|
409
|
+
this.scheduleManager = new ScheduleManager(this.innerDeltaManager, this, () => this.clientId, createChildLogger({ logger: this.logger, namespace: "ScheduleManager" }));
|
|
356
410
|
this.pendingStateManager = new PendingStateManager({
|
|
357
411
|
applyStashedOp: this.applyStashedOp.bind(this),
|
|
358
412
|
clientId: () => this.clientId,
|
|
@@ -360,7 +414,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
360
414
|
connected: () => this.connected,
|
|
361
415
|
reSubmit: this.reSubmit.bind(this),
|
|
362
416
|
reSubmitBatch: this.reSubmitBatch.bind(this),
|
|
363
|
-
|
|
417
|
+
isActiveConnection: () => this.innerDeltaManager.active,
|
|
418
|
+
}, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pending, this.logger);
|
|
364
419
|
const disableCompression = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionDisabled");
|
|
365
420
|
const compressionOptions = disableCompression === true
|
|
366
421
|
? {
|
|
@@ -369,10 +424,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
369
424
|
}
|
|
370
425
|
: runtimeOptions.compressionOptions;
|
|
371
426
|
const disablePartialFlush = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisablePartialFlush");
|
|
427
|
+
const legacySendBatchFn = makeLegacySendBatchFn(this.submitFn, this.innerDeltaManager);
|
|
372
428
|
this.outbox = new Outbox({
|
|
373
429
|
shouldSend: () => this.canSendOps(),
|
|
374
430
|
pendingStateManager: this.pendingStateManager,
|
|
375
|
-
|
|
431
|
+
submitBatchFn: this.submitBatchFn,
|
|
432
|
+
legacySendBatchFn,
|
|
376
433
|
compressor: new OpCompressor(this.mc.logger),
|
|
377
434
|
splitter: opSplitter,
|
|
378
435
|
config: {
|
|
@@ -391,9 +448,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
391
448
|
opReentrancy: () => this.ensureNoDataModelChangesCalls > 0,
|
|
392
449
|
closeContainer: this.closeFn,
|
|
393
450
|
});
|
|
394
|
-
this.
|
|
451
|
+
this._quorum = quorum;
|
|
452
|
+
this._quorum.on("removeMember", (clientId) => {
|
|
395
453
|
this.remoteMessageProcessor.clearPartialMessagesFor(clientId);
|
|
396
454
|
});
|
|
455
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
456
|
+
this._audience = audience;
|
|
397
457
|
this.summaryStateUpdateMethod = this.mc.config.getString("Fluid.ContainerRuntime.Test.SummaryStateUpdateMethodV2");
|
|
398
458
|
const closeSummarizerDelayOverride = this.mc.config.getNumber("Fluid.ContainerRuntime.Test.CloseSummarizerDelayOverrideMs");
|
|
399
459
|
this.closeSummarizerDelayMs = closeSummarizerDelayOverride !== null && closeSummarizerDelayOverride !== void 0 ? closeSummarizerDelayOverride : defaultCloseSummarizerDelayMs;
|
|
@@ -401,34 +461,39 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
401
461
|
(_l = this.mc.config.getBoolean("Fluid.ContainerRuntime.Test.ValidateSummaryBeforeUpload")) !== null && _l !== void 0 ? _l : false;
|
|
402
462
|
this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
|
|
403
463
|
this.dirtyContainer =
|
|
404
|
-
this.
|
|
464
|
+
this.attachState !== AttachState.Attached ||
|
|
405
465
|
this.pendingStateManager.hasPendingMessages();
|
|
406
|
-
|
|
466
|
+
context.updateDirtyContainerState(this.dirtyContainer);
|
|
407
467
|
if (this.summariesDisabled) {
|
|
408
468
|
this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
|
|
409
469
|
}
|
|
410
470
|
else {
|
|
411
|
-
const orderedClientLogger =
|
|
412
|
-
|
|
413
|
-
|
|
471
|
+
const orderedClientLogger = createChildLogger({
|
|
472
|
+
logger: this.logger,
|
|
473
|
+
namespace: "OrderedClientElection",
|
|
474
|
+
});
|
|
475
|
+
const orderedClientCollection = new OrderedClientCollection(orderedClientLogger, this.innerDeltaManager, this._quorum);
|
|
476
|
+
const orderedClientElectionForSummarizer = new OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData !== null && electedSummarizerData !== void 0 ? electedSummarizerData : this.innerDeltaManager.lastSequenceNumber, SummarizerClientElection.isClientEligible);
|
|
414
477
|
this.summarizerClientElection = new SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, this.maxOpsSinceLastSummary);
|
|
415
|
-
if (this.
|
|
478
|
+
if (this.isSummarizerClient) {
|
|
416
479
|
this._summarizer = new Summarizer(this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => RunWhileConnectedCoordinator.create(runtime,
|
|
417
480
|
// Summarization runs in summarizer client and needs access to the real (non-proxy) active
|
|
418
481
|
// information. The proxy delta manager would always return false for summarizer client.
|
|
419
482
|
() => this.innerDeltaManager.active));
|
|
420
483
|
}
|
|
421
|
-
else if (SummarizerClientElection.clientDetailsPermitElection(this.
|
|
484
|
+
else if (SummarizerClientElection.clientDetailsPermitElection(this.clientDetails)) {
|
|
422
485
|
// Only create a SummaryManager and SummarizerClientElection
|
|
423
486
|
// if summaries are enabled and we are not the summarizer client.
|
|
424
487
|
const defaultAction = () => {
|
|
425
488
|
if (this.summaryCollection.opsSinceLastAck > this.maxOpsSinceLastSummary) {
|
|
426
|
-
this.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
|
|
489
|
+
this.mc.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
|
|
427
490
|
// unregister default to no log on every op after falling behind
|
|
428
491
|
// and register summary ack handler to re-register this handler
|
|
429
492
|
// after successful summary
|
|
430
493
|
this.summaryCollection.once(MessageType.SummaryAck, () => {
|
|
431
|
-
this.logger.sendTelemetryEvent({
|
|
494
|
+
this.mc.logger.sendTelemetryEvent({
|
|
495
|
+
eventName: "SummaryStatus:CaughtUp",
|
|
496
|
+
});
|
|
432
497
|
// we've caught up, so re-register the default action to monitor for
|
|
433
498
|
// falling behind, and unregister ourself
|
|
434
499
|
this.summaryCollection.on("default", defaultAction);
|
|
@@ -439,7 +504,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
439
504
|
this.summaryCollection.on("default", defaultAction);
|
|
440
505
|
// Create the SummaryManager and mark the initial state
|
|
441
506
|
this.summaryManager = new SummaryManager(this.summarizerClientElection, this, // IConnectedState
|
|
442
|
-
this.summaryCollection, this.logger, this.formRequestSummarizerFn(
|
|
507
|
+
this.summaryCollection, this.logger, this.formRequestSummarizerFn(loader), new Throttler(60 * 1000, // 60 sec delay window
|
|
443
508
|
30 * 1000, // 30 sec max delay
|
|
444
509
|
// throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
|
|
445
510
|
formExponentialFn({ coefficient: 20, initialDelay: 0 })), {
|
|
@@ -470,7 +535,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
470
535
|
});
|
|
471
536
|
// logging hardware telemetry
|
|
472
537
|
logger.sendTelemetryEvent(Object.assign({ eventName: "DeviceSpec" }, getDeviceSpec()));
|
|
473
|
-
this.logger.sendTelemetryEvent(Object.assign(Object.assign(Object.assign({ eventName: "ContainerLoadStats" }, this.createContainerMetadata), this.dataStores.containerLoadStats), { summaryNumber: loadSummaryNumber, 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, options: JSON.stringify(runtimeOptions), featureGates: JSON.stringify({
|
|
538
|
+
this.mc.logger.sendTelemetryEvent(Object.assign(Object.assign(Object.assign({ eventName: "ContainerLoadStats" }, this.createContainerMetadata), this.dataStores.containerLoadStats), { summaryNumber: loadSummaryNumber, 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, options: JSON.stringify(runtimeOptions), featureGates: JSON.stringify({
|
|
474
539
|
disableCompression,
|
|
475
540
|
disableOpReentryCheck,
|
|
476
541
|
disableChunking,
|
|
@@ -480,10 +545,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
480
545
|
summaryStateUpdateMethod: this.summaryStateUpdateMethod,
|
|
481
546
|
closeSummarizerDelayOverride,
|
|
482
547
|
}), telemetryDocumentId: this.telemetryDocumentId, groupedBatchingEnabled: this.groupedBatchingEnabled }));
|
|
483
|
-
ReportOpPerfTelemetry(this.
|
|
548
|
+
ReportOpPerfTelemetry(this.clientId, this.deltaManager, this.logger);
|
|
484
549
|
BindBatchTracker(this, this.logger);
|
|
485
550
|
this.entryPoint = new LazyPromise(async () => {
|
|
486
|
-
if (this.
|
|
551
|
+
if (this.isSummarizerClient) {
|
|
487
552
|
assert(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
|
|
488
553
|
return this._summarizer;
|
|
489
554
|
}
|
|
@@ -541,9 +606,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
541
606
|
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
542
607
|
const backCompatContext = context;
|
|
543
608
|
const passLogger = (_a = backCompatContext.taggedLogger) !== null && _a !== void 0 ? _a : new TaggedLoggerAdapter(backCompatContext.logger);
|
|
544
|
-
const logger =
|
|
545
|
-
|
|
546
|
-
|
|
609
|
+
const logger = createChildLogger({
|
|
610
|
+
logger: passLogger,
|
|
611
|
+
properties: {
|
|
612
|
+
all: {
|
|
613
|
+
runtimeVersion: pkgVersion,
|
|
614
|
+
},
|
|
547
615
|
},
|
|
548
616
|
});
|
|
549
617
|
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor = false, chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, enableGroupedBatching = false, } = runtimeOptions;
|
|
@@ -624,38 +692,15 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
624
692
|
await runtime.initializeBaseState();
|
|
625
693
|
return runtime;
|
|
626
694
|
}
|
|
627
|
-
get options() {
|
|
628
|
-
return this.context.options;
|
|
629
|
-
}
|
|
630
695
|
get clientId() {
|
|
631
|
-
return this.
|
|
632
|
-
}
|
|
633
|
-
get clientDetails() {
|
|
634
|
-
return this.context.clientDetails;
|
|
696
|
+
return this._getClientId();
|
|
635
697
|
}
|
|
636
698
|
get storage() {
|
|
637
699
|
return this._storage;
|
|
638
700
|
}
|
|
701
|
+
/** @deprecated - The functionality is no longer exposed publicly */
|
|
639
702
|
get reSubmitFn() {
|
|
640
|
-
|
|
641
|
-
return this.reSubmitCore;
|
|
642
|
-
}
|
|
643
|
-
get disposeFn() {
|
|
644
|
-
var _a;
|
|
645
|
-
// In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
|
|
646
|
-
return (_a = this.context.disposeFn) !== null && _a !== void 0 ? _a : this.context.closeFn;
|
|
647
|
-
}
|
|
648
|
-
get closeFn() {
|
|
649
|
-
if (this._summarizer !== undefined) {
|
|
650
|
-
// In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
|
|
651
|
-
return this.disposeFn;
|
|
652
|
-
}
|
|
653
|
-
// Also call disposeFn to retain functionality of runtime being disposed on close
|
|
654
|
-
return (error) => {
|
|
655
|
-
var _a, _b;
|
|
656
|
-
this.context.closeFn(error);
|
|
657
|
-
(_b = (_a = this.context).disposeFn) === null || _b === void 0 ? void 0 : _b.call(_a, error);
|
|
658
|
-
};
|
|
703
|
+
return (type, contents, localOpMetadata, opMetadata) => this.reSubmitCore({ type, contents }, localOpMetadata, opMetadata);
|
|
659
704
|
}
|
|
660
705
|
get flushMode() {
|
|
661
706
|
return this._flushMode;
|
|
@@ -667,7 +712,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
667
712
|
return this.registry;
|
|
668
713
|
}
|
|
669
714
|
get attachState() {
|
|
670
|
-
return this.
|
|
715
|
+
return this._getAttachState();
|
|
671
716
|
}
|
|
672
717
|
get IFluidHandleContext() {
|
|
673
718
|
return this.handleContext;
|
|
@@ -737,7 +782,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
737
782
|
return;
|
|
738
783
|
}
|
|
739
784
|
this._disposed = true;
|
|
740
|
-
this.logger.sendTelemetryEvent({
|
|
785
|
+
this.mc.logger.sendTelemetryEvent({
|
|
741
786
|
eventName: "ContainerRuntimeDisposed",
|
|
742
787
|
isDirty: this.isDirty,
|
|
743
788
|
lastSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
@@ -972,9 +1017,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
972
1017
|
*/
|
|
973
1018
|
parseOpContent(serializedContent) {
|
|
974
1019
|
assert(serializedContent !== undefined, 0x6d5 /* content must be defined */);
|
|
975
|
-
const
|
|
976
|
-
assert(
|
|
977
|
-
return { type
|
|
1020
|
+
const { type, contents } = JSON.parse(serializedContent);
|
|
1021
|
+
assert(type !== undefined, 0x6d6 /* incorrect op content format */);
|
|
1022
|
+
return { type, contents };
|
|
978
1023
|
}
|
|
979
1024
|
async applyStashedOp(op) {
|
|
980
1025
|
// Need to parse from string for back-compat
|
|
@@ -1033,6 +1078,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1033
1078
|
// There might be no change of state due to Container calling this API after loading runtime.
|
|
1034
1079
|
const changeOfState = this._connected !== connected;
|
|
1035
1080
|
const reconnection = changeOfState && !connected;
|
|
1081
|
+
// We need to flush the ops currently collected by Outbox to preserve original order.
|
|
1082
|
+
// This flush NEEDS to happen before we set the ContainerRuntime to "connected".
|
|
1083
|
+
// We want these ops to get to the PendingStateManager without sending to service and have them return to the Outbox upon calling "replayPendingStates".
|
|
1084
|
+
if (changeOfState && connected) {
|
|
1085
|
+
this.flush();
|
|
1086
|
+
}
|
|
1036
1087
|
this._connected = connected;
|
|
1037
1088
|
if (!connected) {
|
|
1038
1089
|
this._perfSignalData.signalsLost = 0;
|
|
@@ -1076,6 +1127,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1076
1127
|
this.processCore(message, local, runtimeMessage);
|
|
1077
1128
|
}
|
|
1078
1129
|
}
|
|
1130
|
+
/**
|
|
1131
|
+
* Direct the message to the correct subsystem for processing, and implement other side effects
|
|
1132
|
+
* @param message - The unpacked message. Likely a ContainerRuntimeMessage, but could also be a system op
|
|
1133
|
+
* @param local - Did this client send the op?
|
|
1134
|
+
* @param runtimeMessage - Does this appear like a current ContainerRuntimeMessage? If true, certain validation will occur.
|
|
1135
|
+
*/
|
|
1079
1136
|
processCore(message, local, runtimeMessage) {
|
|
1080
1137
|
var _a;
|
|
1081
1138
|
// Surround the actual processing of the operation with messages to the schedule manager indicating
|
|
@@ -1129,9 +1186,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1129
1186
|
throw error;
|
|
1130
1187
|
}
|
|
1131
1188
|
}
|
|
1132
|
-
|
|
1133
|
-
this.emit("op", message, runtimeMessage);
|
|
1134
|
-
}
|
|
1189
|
+
this.emit("op", message, runtimeMessage);
|
|
1135
1190
|
this.scheduleManager.afterOpProcessing(undefined, message);
|
|
1136
1191
|
if (local) {
|
|
1137
1192
|
// If we have processed a local op, this means that the container is
|
|
@@ -1154,7 +1209,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1154
1209
|
*/
|
|
1155
1210
|
sendSignalTelemetryEvent(clientSignalSequenceNumber) {
|
|
1156
1211
|
const duration = Date.now() - this._perfSignalData.signalTimestamp;
|
|
1157
|
-
this.logger.sendPerformanceEvent({
|
|
1212
|
+
this.mc.logger.sendPerformanceEvent({
|
|
1158
1213
|
eventName: "SignalLatency",
|
|
1159
1214
|
duration,
|
|
1160
1215
|
signalsLost: this._perfSignalData.signalsLost,
|
|
@@ -1177,7 +1232,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1177
1232
|
this._perfSignalData.trackingSignalSequenceNumber) {
|
|
1178
1233
|
this._perfSignalData.signalsLost++;
|
|
1179
1234
|
this._perfSignalData.trackingSignalSequenceNumber = undefined;
|
|
1180
|
-
this.logger.sendErrorEvent({
|
|
1235
|
+
this.mc.logger.sendErrorEvent({
|
|
1181
1236
|
eventName: "SignalLost",
|
|
1182
1237
|
type: envelope.contents.type,
|
|
1183
1238
|
signalsLost: this._perfSignalData.signalsLost,
|
|
@@ -1298,11 +1353,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1298
1353
|
return this.flushMode !== FlushMode.Immediate || this._orderSequentiallyCalls !== 0;
|
|
1299
1354
|
}
|
|
1300
1355
|
getQuorum() {
|
|
1301
|
-
return this.
|
|
1356
|
+
return this._quorum;
|
|
1302
1357
|
}
|
|
1303
1358
|
getAudience() {
|
|
1304
|
-
|
|
1305
|
-
return this.context.audience;
|
|
1359
|
+
return this._audience;
|
|
1306
1360
|
}
|
|
1307
1361
|
/**
|
|
1308
1362
|
* Returns true of container is dirty, i.e. there are some pending local changes that
|
|
@@ -1311,7 +1365,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1311
1365
|
get isDirty() {
|
|
1312
1366
|
return this.dirtyContainer;
|
|
1313
1367
|
}
|
|
1314
|
-
isContainerMessageDirtyable(type, contents) {
|
|
1368
|
+
isContainerMessageDirtyable({ type, contents }) {
|
|
1315
1369
|
// For legacy purposes, exclude the old built-in AgentScheduler from dirty consideration as a special-case.
|
|
1316
1370
|
// Ultimately we should have no special-cases from the ContainerRuntime's perspective.
|
|
1317
1371
|
if (type === ContainerMessageType.Attach) {
|
|
@@ -1351,11 +1405,11 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1351
1405
|
submitSignal(type, content) {
|
|
1352
1406
|
this.verifyNotClosed();
|
|
1353
1407
|
const envelope = this.createNewSignalEnvelope(undefined /* address */, type, content);
|
|
1354
|
-
return this.
|
|
1408
|
+
return this.submitSignalFn(envelope);
|
|
1355
1409
|
}
|
|
1356
1410
|
submitDataStoreSignal(address, type, content) {
|
|
1357
1411
|
const envelope = this.createNewSignalEnvelope(address, type, content);
|
|
1358
|
-
return this.
|
|
1412
|
+
return this.submitSignalFn(envelope);
|
|
1359
1413
|
}
|
|
1360
1414
|
setAttachState(attachState) {
|
|
1361
1415
|
if (attachState === AttachState.Attaching) {
|
|
@@ -1388,15 +1442,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1388
1442
|
this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
|
|
1389
1443
|
return summarizeResult.summary;
|
|
1390
1444
|
}
|
|
1391
|
-
async getAbsoluteUrl(relativeUrl) {
|
|
1392
|
-
if (this.context.getAbsoluteUrl === undefined) {
|
|
1393
|
-
throw new Error("Driver does not implement getAbsoluteUrl");
|
|
1394
|
-
}
|
|
1395
|
-
if (this.attachState !== AttachState.Attached) {
|
|
1396
|
-
return undefined;
|
|
1397
|
-
}
|
|
1398
|
-
return this.context.getAbsoluteUrl(relativeUrl);
|
|
1399
|
-
}
|
|
1400
1445
|
async summarizeInternal(fullTree, trackState, telemetryContext) {
|
|
1401
1446
|
const summarizeResult = await this.dataStores.summarize(fullTree, trackState, telemetryContext);
|
|
1402
1447
|
// Wrap data store summaries in .channels subtree.
|
|
@@ -1430,7 +1475,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1430
1475
|
return { stats, summary, gcStats };
|
|
1431
1476
|
}
|
|
1432
1477
|
finally {
|
|
1433
|
-
this.logger.sendTelemetryEvent({
|
|
1478
|
+
this.mc.logger.sendTelemetryEvent({
|
|
1434
1479
|
eventName: "SummarizeTelemetry",
|
|
1435
1480
|
details: telemetryContext.serialize(),
|
|
1436
1481
|
});
|
|
@@ -1597,18 +1642,25 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1597
1642
|
* @param options - options controlling how the summary is generated or submitted
|
|
1598
1643
|
*/
|
|
1599
1644
|
async submitSummary(options) {
|
|
1600
|
-
var _a, _b
|
|
1645
|
+
var _a, _b;
|
|
1601
1646
|
const { fullTree = false, refreshLatestAck, summaryLogger } = options;
|
|
1602
1647
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
1603
1648
|
// use it for all events logged during this summary.
|
|
1604
1649
|
const summaryNumber = this.nextSummaryNumber;
|
|
1605
|
-
const summaryNumberLogger =
|
|
1606
|
-
|
|
1650
|
+
const summaryNumberLogger = createChildLogger({
|
|
1651
|
+
logger: summaryLogger,
|
|
1652
|
+
properties: {
|
|
1653
|
+
all: { summaryNumber },
|
|
1654
|
+
},
|
|
1607
1655
|
});
|
|
1608
1656
|
assert(this.outbox.isEmpty, 0x3d1 /* Can't trigger summary in the middle of a batch */);
|
|
1609
1657
|
let latestSnapshotVersionId;
|
|
1610
1658
|
if (refreshLatestAck) {
|
|
1611
|
-
const latestSnapshotInfo = await this.refreshLatestSummaryAckFromServer(
|
|
1659
|
+
const latestSnapshotInfo = await this.refreshLatestSummaryAckFromServer(createChildLogger({
|
|
1660
|
+
logger: summaryNumberLogger,
|
|
1661
|
+
namespace: undefined,
|
|
1662
|
+
properties: { all: { safeSummary: true } },
|
|
1663
|
+
}));
|
|
1612
1664
|
const latestSnapshotRefSeq = latestSnapshotInfo.latestSnapshotRefSeq;
|
|
1613
1665
|
latestSnapshotVersionId = latestSnapshotInfo.latestSnapshotVersionId;
|
|
1614
1666
|
// We might need to catch up to the latest summary's reference sequence number before pausing.
|
|
@@ -1742,7 +1794,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1742
1794
|
else if (lastAck === undefined) {
|
|
1743
1795
|
summaryContext = {
|
|
1744
1796
|
proposalHandle: undefined,
|
|
1745
|
-
ackHandle:
|
|
1797
|
+
ackHandle: this.loadedFromVersionId,
|
|
1746
1798
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
1747
1799
|
};
|
|
1748
1800
|
}
|
|
@@ -1794,7 +1846,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1794
1846
|
// Cleanup wip summary in case of failure
|
|
1795
1847
|
this.summarizerNode.clearSummary();
|
|
1796
1848
|
// ! This needs to happen before we resume inbound queues to ensure heuristics are tracked correctly
|
|
1797
|
-
(
|
|
1849
|
+
(_b = (_a = this._summarizer) === null || _a === void 0 ? void 0 : _a.recordSummaryAttempt) === null || _b === void 0 ? void 0 : _b.call(_a, summaryRefSeqNum);
|
|
1798
1850
|
// Restart the delta manager
|
|
1799
1851
|
this.deltaManager.inbound.resume();
|
|
1800
1852
|
if (shouldPauseInboundSignal) {
|
|
@@ -1819,7 +1871,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1819
1871
|
this.dirtyContainer = dirty;
|
|
1820
1872
|
if (this.emitDirtyDocumentEvent) {
|
|
1821
1873
|
this.emit(dirty ? "dirty" : "saved");
|
|
1822
|
-
this.context.updateDirtyContainerState(dirty);
|
|
1823
1874
|
}
|
|
1824
1875
|
}
|
|
1825
1876
|
submitDataStoreOp(id, contents, localOpMetadata = undefined) {
|
|
@@ -1827,18 +1878,18 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1827
1878
|
address: id,
|
|
1828
1879
|
contents,
|
|
1829
1880
|
};
|
|
1830
|
-
this.submit(ContainerMessageType.FluidDataStoreOp, envelope, localOpMetadata);
|
|
1881
|
+
this.submit({ type: ContainerMessageType.FluidDataStoreOp, contents: envelope }, localOpMetadata);
|
|
1831
1882
|
}
|
|
1832
1883
|
submitDataStoreAliasOp(contents, localOpMetadata) {
|
|
1833
1884
|
const aliasMessage = contents;
|
|
1834
1885
|
if (!isDataStoreAliasMessage(aliasMessage)) {
|
|
1835
1886
|
throw new UsageError("malformedDataStoreAliasMessage");
|
|
1836
1887
|
}
|
|
1837
|
-
this.submit(ContainerMessageType.Alias, contents, localOpMetadata);
|
|
1888
|
+
this.submit({ type: ContainerMessageType.Alias, contents }, localOpMetadata);
|
|
1838
1889
|
}
|
|
1839
|
-
async uploadBlob(blob) {
|
|
1890
|
+
async uploadBlob(blob, signal) {
|
|
1840
1891
|
this.verifyNotClosed();
|
|
1841
|
-
return this.blobManager.createBlob(blob);
|
|
1892
|
+
return this.blobManager.createBlob(blob, signal);
|
|
1842
1893
|
}
|
|
1843
1894
|
maybeSubmitIdAllocationOp(type) {
|
|
1844
1895
|
var _a, _b;
|
|
@@ -1869,20 +1920,21 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1869
1920
|
}
|
|
1870
1921
|
}
|
|
1871
1922
|
}
|
|
1872
|
-
submit(
|
|
1923
|
+
submit(containerRuntimeMessage, localOpMetadata = undefined, metadata = undefined) {
|
|
1873
1924
|
this.verifyNotClosed();
|
|
1874
1925
|
this.verifyCanSubmitOps();
|
|
1875
1926
|
// There should be no ops in detached container state!
|
|
1876
1927
|
assert(this.attachState !== AttachState.Detached, 0x132 /* "sending ops in detached container" */);
|
|
1877
|
-
const serializedContent = JSON.stringify(
|
|
1928
|
+
const serializedContent = JSON.stringify(containerRuntimeMessage);
|
|
1878
1929
|
// Note that the real (non-proxy) delta manager is used here to get the readonly info. This is because
|
|
1879
1930
|
// container runtime's ability to submit ops depend on the actual readonly state of the delta manager.
|
|
1880
1931
|
if (this.innerDeltaManager.readOnlyInfo.readonly) {
|
|
1881
|
-
this.logger.sendTelemetryEvent({
|
|
1932
|
+
this.mc.logger.sendTelemetryEvent({
|
|
1882
1933
|
eventName: "SubmitOpInReadonly",
|
|
1883
1934
|
connected: this.connected,
|
|
1884
1935
|
});
|
|
1885
1936
|
}
|
|
1937
|
+
const type = containerRuntimeMessage.type;
|
|
1886
1938
|
const message = {
|
|
1887
1939
|
contents: serializedContent,
|
|
1888
1940
|
type,
|
|
@@ -1939,7 +1991,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1939
1991
|
this.closeFn(error);
|
|
1940
1992
|
throw error;
|
|
1941
1993
|
}
|
|
1942
|
-
if (this.isContainerMessageDirtyable(
|
|
1994
|
+
if (this.isContainerMessageDirtyable(containerRuntimeMessage)) {
|
|
1943
1995
|
this.updateDocumentDirtyState(true);
|
|
1944
1996
|
}
|
|
1945
1997
|
}
|
|
@@ -1982,9 +2034,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1982
2034
|
// System message should not be sent in the middle of the batch.
|
|
1983
2035
|
assert(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
|
|
1984
2036
|
// back-compat: ADO #1385: Make this call unconditional in the future
|
|
1985
|
-
return this.
|
|
1986
|
-
? this.
|
|
1987
|
-
: this.
|
|
2037
|
+
return this.submitSummaryFn !== undefined
|
|
2038
|
+
? this.submitSummaryFn(contents, referenceSequenceNumber)
|
|
2039
|
+
: this.submitFn(MessageType.Summarize, contents, false);
|
|
1988
2040
|
}
|
|
1989
2041
|
/**
|
|
1990
2042
|
* Throw an error if the runtime is closed. Methods that are expected to potentially
|
|
@@ -2031,32 +2083,33 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2031
2083
|
}
|
|
2032
2084
|
reSubmit(message) {
|
|
2033
2085
|
// Need to parse from string for back-compat
|
|
2034
|
-
const
|
|
2035
|
-
this.reSubmitCore(
|
|
2086
|
+
const containerRuntimeMessage = this.parseOpContent(message.content);
|
|
2087
|
+
this.reSubmitCore(containerRuntimeMessage, message.localOpMetadata, message.opMetadata);
|
|
2036
2088
|
}
|
|
2037
2089
|
/**
|
|
2038
2090
|
* Finds the right store and asks it to resubmit the message. This typically happens when we
|
|
2039
2091
|
* reconnect and there are pending messages.
|
|
2040
|
-
* @param
|
|
2092
|
+
* @param message - The original ContainerRuntimeMessage.
|
|
2041
2093
|
* @param localOpMetadata - The local metadata associated with the original message.
|
|
2042
2094
|
*/
|
|
2043
|
-
reSubmitCore(
|
|
2044
|
-
|
|
2095
|
+
reSubmitCore(message, localOpMetadata, opMetadata) {
|
|
2096
|
+
const contents = message.contents;
|
|
2097
|
+
switch (message.type) {
|
|
2045
2098
|
case ContainerMessageType.FluidDataStoreOp:
|
|
2046
2099
|
// For Operations, call resubmitDataStoreOp which will find the right store
|
|
2047
2100
|
// and trigger resubmission on it.
|
|
2048
|
-
this.dataStores.resubmitDataStoreOp(
|
|
2101
|
+
this.dataStores.resubmitDataStoreOp(contents, localOpMetadata);
|
|
2049
2102
|
break;
|
|
2050
2103
|
case ContainerMessageType.Attach:
|
|
2051
2104
|
case ContainerMessageType.Alias:
|
|
2052
|
-
this.submit(
|
|
2105
|
+
this.submit(message, localOpMetadata);
|
|
2053
2106
|
break;
|
|
2054
2107
|
case ContainerMessageType.IdAllocation:
|
|
2055
2108
|
// Remove the stashedState from the op if it's a stashed op
|
|
2056
|
-
if (
|
|
2057
|
-
delete
|
|
2109
|
+
if (contents.stashedState !== undefined) {
|
|
2110
|
+
delete contents.stashedState;
|
|
2058
2111
|
}
|
|
2059
|
-
this.submit(
|
|
2112
|
+
this.submit(message, localOpMetadata);
|
|
2060
2113
|
break;
|
|
2061
2114
|
case ContainerMessageType.ChunkedOp:
|
|
2062
2115
|
throw new Error(`chunkedOp not expected here`);
|
|
@@ -2064,10 +2117,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2064
2117
|
this.blobManager.reSubmit(opMetadata);
|
|
2065
2118
|
break;
|
|
2066
2119
|
case ContainerMessageType.Rejoin:
|
|
2067
|
-
this.submit(
|
|
2120
|
+
this.submit(message);
|
|
2068
2121
|
break;
|
|
2069
2122
|
default:
|
|
2070
|
-
unreachableCase(type, `Unknown ContainerMessageType: ${type}`);
|
|
2123
|
+
unreachableCase(message.type, `Unknown ContainerMessageType [type: ${message.type}]`);
|
|
2071
2124
|
}
|
|
2072
2125
|
}
|
|
2073
2126
|
rollback(content, localOpMetadata) {
|
|
@@ -2114,7 +2167,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2114
2167
|
* change that started fetching latest snapshot always.
|
|
2115
2168
|
*/
|
|
2116
2169
|
if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
|
|
2117
|
-
fetchResult = await this.
|
|
2170
|
+
fetchResult = await this.fetchSnapshotFromStorageAndClose(summaryLogger, {
|
|
2118
2171
|
eventName: "RefreshLatestSummaryAckFetchBackCompat",
|
|
2119
2172
|
ackHandle,
|
|
2120
2173
|
targetSequenceNumber: summaryRefSeq,
|
|
@@ -2172,9 +2225,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2172
2225
|
return { latestSnapshotRefSeq, latestSnapshotVersionId: versionId };
|
|
2173
2226
|
}
|
|
2174
2227
|
async fetchLatestSnapshotFromStorage(logger, event, readAndParseBlob) {
|
|
2175
|
-
return this.
|
|
2228
|
+
return this.fetchSnapshotFromStorageAndClose(logger, event, readAndParseBlob, null /* latest */);
|
|
2176
2229
|
}
|
|
2177
|
-
async
|
|
2230
|
+
async fetchSnapshotFromStorageAndClose(logger, event, readAndParseBlob, versionId) {
|
|
2178
2231
|
var _a;
|
|
2179
2232
|
const snapshotResults = await PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
|
|
2180
2233
|
const stats = {};
|
|
@@ -2198,14 +2251,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2198
2251
|
// We choose to close the summarizer after the snapshot cache is updated to avoid
|
|
2199
2252
|
// situations which the main client (which is likely to be re-elected as the leader again)
|
|
2200
2253
|
// loads the summarizer from cache.
|
|
2201
|
-
if (this.summaryStateUpdateMethod
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
// Delay 10 seconds before restarting summarizer to prevent the summarizer from restarting too frequently.
|
|
2254
|
+
if (this.summaryStateUpdateMethod !== "refreshFromSnapshot") {
|
|
2255
|
+
this.mc.logger.sendTelemetryEvent(Object.assign(Object.assign({}, event), { eventName: "ClosingSummarizerOnSummaryStale", codePath: event.eventName, message: "Stopping fetch from storage", versionId: versionId != null ? versionId : undefined, closeSummarizerDelayMs: this.closeSummarizerDelayMs }), new GenericError("Restarting summarizer instead of refreshing"));
|
|
2256
|
+
// Delay before restarting summarizer to prevent the summarizer from restarting too frequently.
|
|
2205
2257
|
await delay(this.closeSummarizerDelayMs);
|
|
2206
2258
|
(_a = this._summarizer) === null || _a === void 0 ? void 0 : _a.stop("latestSummaryStateStale");
|
|
2207
|
-
this.
|
|
2208
|
-
throw error;
|
|
2259
|
+
this.disposeFn();
|
|
2209
2260
|
}
|
|
2210
2261
|
return snapshotResults;
|
|
2211
2262
|
}
|