@fluidframework/container-runtime 2.0.0-internal.5.4.0 → 2.0.0-internal.6.1.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 +75 -0
- package/dist/batchTracker.d.ts +2 -1
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +4 -1
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +61 -26
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.js +10 -2
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +26 -11
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +189 -131
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +8 -2
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +24 -26
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +20 -4
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +107 -53
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerProxyBase.d.ts +35 -0
- package/dist/deltaManagerProxyBase.d.ts.map +1 -0
- package/dist/deltaManagerProxyBase.js +77 -0
- package/dist/deltaManagerProxyBase.js.map +1 -0
- package/dist/deltaManagerSummarizerProxy.d.ts +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js +2 -2
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/gc/garbageCollection.js +17 -20
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.js +13 -11
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcHelpers.js +4 -6
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +4 -6
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +55 -37
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/id-compressor/idCompressor.js +49 -51
- package/dist/id-compressor/idCompressor.js.map +1 -1
- package/dist/id-compressor/idRange.js +2 -2
- package/dist/id-compressor/idRange.js.map +1 -1
- package/dist/id-compressor/sessionIdNormalizer.js +11 -16
- package/dist/id-compressor/sessionIdNormalizer.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.js +10 -6
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/opCompressor.js +6 -1
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +11 -9
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +13 -5
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.js +10 -6
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.js +1 -2
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/opProperties.js +1 -2
- package/dist/opProperties.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 +2 -2
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +22 -22
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.js +14 -10
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +2 -1
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +17 -18
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +35 -57
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.js +4 -7
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.js +5 -9
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.js +8 -12
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +22 -15
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js +2 -4
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +17 -16
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summaryCollection.js +3 -5
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.js +1 -2
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +62 -21
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.js +3 -5
- package/dist/summary/summaryManager.js.map +1 -1
- package/lib/batchTracker.d.ts +2 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +4 -1
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +61 -26
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.js +10 -2
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +26 -11
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +189 -131
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js +8 -2
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +24 -26
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +20 -4
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +107 -53
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerProxyBase.d.ts +35 -0
- package/lib/deltaManagerProxyBase.d.ts.map +1 -0
- package/lib/deltaManagerProxyBase.js +73 -0
- package/lib/deltaManagerProxyBase.js.map +1 -0
- package/lib/deltaManagerSummarizerProxy.d.ts +1 -1
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/lib/deltaManagerSummarizerProxy.js +1 -1
- package/lib/deltaManagerSummarizerProxy.js.map +1 -1
- package/lib/gc/garbageCollection.js +17 -20
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.js +13 -11
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcHelpers.js +4 -6
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +4 -6
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +55 -37
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/id-compressor/idCompressor.js +49 -51
- package/lib/id-compressor/idCompressor.js.map +1 -1
- package/lib/id-compressor/idRange.js +2 -2
- package/lib/id-compressor/idRange.js.map +1 -1
- package/lib/id-compressor/sessionIdNormalizer.js +11 -16
- package/lib/id-compressor/sessionIdNormalizer.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/batchManager.js +10 -6
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/opCompressor.js +6 -1
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +11 -9
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +13 -5
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.js +10 -6
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.js +1 -2
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/opProperties.js +1 -2
- package/lib/opProperties.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 +2 -2
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +22 -22
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.js +14 -10
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +2 -1
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +17 -18
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +35 -57
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.js +4 -7
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.js +5 -9
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.js +8 -12
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +22 -15
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js +2 -4
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +17 -16
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summaryCollection.js +3 -5
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.js +1 -2
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +62 -21
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.js +3 -5
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +19 -19
- package/src/batchTracker.ts +2 -1
- package/src/blobManager.ts +43 -2
- package/src/containerRuntime.ts +95 -67
- package/src/dataStore.ts +7 -1
- package/src/dataStoreContext.ts +1 -2
- package/src/dataStores.ts +95 -55
- package/src/deltaManagerProxyBase.ts +111 -0
- package/src/deltaManagerSummarizerProxy.ts +2 -1
- package/src/gc/gcTelemetry.ts +1 -2
- package/src/index.ts +0 -1
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +12 -15
- package/src/summary/orderedClientElection.ts +2 -1
- package/src/summary/runningSummarizer.ts +9 -31
- package/src/summary/summaryGenerator.ts +0 -1
package/dist/containerRuntime.js
CHANGED
|
@@ -18,17 +18,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
22
|
-
var t = {};
|
|
23
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
24
|
-
t[p] = s[p];
|
|
25
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
26
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
27
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
28
|
-
t[p[i]] = s[p[i]];
|
|
29
|
-
}
|
|
30
|
-
return t;
|
|
31
|
-
};
|
|
32
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
22
|
exports.ContainerRuntime = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isRuntimeMessage = exports.RuntimeMessage = exports.CompressionAlgorithms = exports.defaultRuntimeHeaderData = exports.TombstoneResponseHeaderKey = exports.AllowTombstoneRequestHeaderKey = exports.RuntimeHeaders = exports.DefaultSummaryConfiguration = exports.ContainerMessageType = void 0;
|
|
34
23
|
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
@@ -174,7 +163,7 @@ function getDeviceSpec() {
|
|
|
174
163
|
};
|
|
175
164
|
}
|
|
176
165
|
}
|
|
177
|
-
catch
|
|
166
|
+
catch { }
|
|
178
167
|
return {};
|
|
179
168
|
}
|
|
180
169
|
exports.getDeviceSpec = getDeviceSpec;
|
|
@@ -201,9 +190,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
201
190
|
/**
|
|
202
191
|
* @internal
|
|
203
192
|
*/
|
|
204
|
-
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, idCompressor, requestHandler, summaryConfiguration
|
|
205
|
-
|
|
206
|
-
|
|
193
|
+
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, idCompressor, requestHandler, summaryConfiguration = {
|
|
194
|
+
// the defaults
|
|
195
|
+
...exports.DefaultSummaryConfiguration,
|
|
196
|
+
// the runtime configuration overrides
|
|
197
|
+
...runtimeOptions.summaryOptions?.summaryConfigOverrides,
|
|
198
|
+
}, initializeEntryPoint) {
|
|
207
199
|
super();
|
|
208
200
|
this.registry = registry;
|
|
209
201
|
this.runtimeOptions = runtimeOptions;
|
|
@@ -273,7 +265,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
273
265
|
this.options = options;
|
|
274
266
|
this.clientDetails = clientDetails;
|
|
275
267
|
this.isSummarizerClient = this.clientDetails.type === summary_1.summarizerClientType;
|
|
276
|
-
this.loadedFromVersionId =
|
|
268
|
+
this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
|
|
277
269
|
this._getClientId = () => context.clientId;
|
|
278
270
|
this._getAttachState = () => context.attachState;
|
|
279
271
|
this.getAbsoluteUrl = async (relativeUrl) => {
|
|
@@ -290,15 +282,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
290
282
|
this.on("dirty", () => context.updateDirtyContainerState(true));
|
|
291
283
|
this.on("saved", () => context.updateDirtyContainerState(false));
|
|
292
284
|
// In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
|
|
293
|
-
this.disposeFn = disposeFn
|
|
285
|
+
this.disposeFn = disposeFn ?? closeFn;
|
|
294
286
|
// In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
|
|
295
|
-
this.closeFn = this.isSummarizerClient
|
|
296
|
-
? this.disposeFn
|
|
297
|
-
: (error) => {
|
|
298
|
-
closeFn(error);
|
|
299
|
-
// Also call disposeFn to retain functionality of runtime being disposed on close
|
|
300
|
-
disposeFn === null || disposeFn === void 0 ? void 0 : disposeFn(error);
|
|
301
|
-
};
|
|
287
|
+
this.closeFn = this.isSummarizerClient ? this.disposeFn : closeFn;
|
|
302
288
|
this.mc = (0, telemetry_utils_1.createChildMonitoringContext)({
|
|
303
289
|
logger: this.logger,
|
|
304
290
|
namespace: "ContainerRuntime",
|
|
@@ -308,15 +294,15 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
308
294
|
// get the values from the metadata blob.
|
|
309
295
|
if (existing) {
|
|
310
296
|
this.createContainerMetadata = {
|
|
311
|
-
createContainerRuntimeVersion: metadata
|
|
312
|
-
createContainerTimestamp: metadata
|
|
297
|
+
createContainerRuntimeVersion: metadata?.createContainerRuntimeVersion,
|
|
298
|
+
createContainerTimestamp: metadata?.createContainerTimestamp,
|
|
313
299
|
};
|
|
314
300
|
// summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
|
|
315
301
|
// the count is reset to 0.
|
|
316
|
-
loadSummaryNumber =
|
|
302
|
+
loadSummaryNumber = metadata?.summaryNumber ?? 0;
|
|
317
303
|
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
318
304
|
// allow new containers to turn it on
|
|
319
|
-
this.idCompressorEnabled =
|
|
305
|
+
this.idCompressorEnabled = metadata?.idCompressorEnabled ?? false;
|
|
320
306
|
}
|
|
321
307
|
else {
|
|
322
308
|
this.createContainerMetadata = {
|
|
@@ -325,22 +311,23 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
325
311
|
};
|
|
326
312
|
loadSummaryNumber = 0;
|
|
327
313
|
this.idCompressorEnabled =
|
|
328
|
-
|
|
314
|
+
this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled") ??
|
|
315
|
+
idCompressor !== undefined;
|
|
329
316
|
}
|
|
330
317
|
this.nextSummaryNumber = loadSummaryNumber + 1;
|
|
331
|
-
this.messageAtLastSummary = metadata
|
|
318
|
+
this.messageAtLastSummary = metadata?.message;
|
|
332
319
|
// Note that we only need to pull the *initial* connected state from the context.
|
|
333
320
|
// Later updates come through calls to setConnectionState.
|
|
334
321
|
this._connected = connected;
|
|
335
|
-
this.gcTombstoneEnforcementAllowed = (0, gc_1.shouldAllowGcTombstoneEnforcement)(
|
|
322
|
+
this.gcTombstoneEnforcementAllowed = (0, gc_1.shouldAllowGcTombstoneEnforcement)(metadata?.gcFeatureMatrix?.tombstoneGeneration /* persisted */, this.runtimeOptions.gcOptions[gc_1.gcTombstoneGenerationOptionName] /* current */);
|
|
336
323
|
this.mc.logger.sendTelemetryEvent({
|
|
337
324
|
eventName: "GCFeatureMatrix",
|
|
338
|
-
metadataValue: JSON.stringify(metadata
|
|
325
|
+
metadataValue: JSON.stringify(metadata?.gcFeatureMatrix),
|
|
339
326
|
inputs: JSON.stringify({
|
|
340
327
|
gcOptions_gcTombstoneGeneration: this.runtimeOptions.gcOptions[gc_1.gcTombstoneGenerationOptionName],
|
|
341
328
|
}),
|
|
342
329
|
});
|
|
343
|
-
this.telemetryDocumentId =
|
|
330
|
+
this.telemetryDocumentId = metadata?.telemetryDocumentId ?? (0, uuid_1.v4)();
|
|
344
331
|
this.disableAttachReorder = this.mc.config.getBoolean("Fluid.ContainerRuntime.disableAttachOpReorder");
|
|
345
332
|
const disableChunking = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionChunkingDisabled");
|
|
346
333
|
const opGroupingManager = new opLifecycle_1.OpGroupingManager(this.groupedBatchingEnabled);
|
|
@@ -363,9 +350,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
363
350
|
this.idCompressor = idCompressor;
|
|
364
351
|
}
|
|
365
352
|
this.maxConsecutiveReconnects =
|
|
366
|
-
|
|
353
|
+
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
|
|
354
|
+
this.defaultMaxConsecutiveReconnects;
|
|
367
355
|
if (runtimeOptions.flushMode === runtime_definitions_1.FlushModeExperimental.Async &&
|
|
368
|
-
|
|
356
|
+
supportedFeatures?.get("referenceSequenceNumbers") !== true) {
|
|
369
357
|
// The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
|
|
370
358
|
this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
|
|
371
359
|
this._flushMode = runtime_definitions_1.FlushMode.TurnBased;
|
|
@@ -374,7 +362,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
374
362
|
this._flushMode = runtimeOptions.flushMode;
|
|
375
363
|
}
|
|
376
364
|
const pendingRuntimeState = pendingLocalState;
|
|
377
|
-
const maxSnapshotCacheDurationMs =
|
|
365
|
+
const maxSnapshotCacheDurationMs = this._storage?.policies?.maximumCacheDurationMs;
|
|
378
366
|
if (maxSnapshotCacheDurationMs !== undefined &&
|
|
379
367
|
maxSnapshotCacheDurationMs > 5 * 24 * 60 * 60 * 1000) {
|
|
380
368
|
// This is a runtime enforcement of what's already explicit in the policy's type itself,
|
|
@@ -392,7 +380,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
392
380
|
createContainerMetadata: this.createContainerMetadata,
|
|
393
381
|
isSummarizerClient: this.isSummarizerClient,
|
|
394
382
|
getNodePackagePath: async (nodePath) => this.getGCNodePackagePath(nodePath),
|
|
395
|
-
getLastSummaryTimestampMs: () =>
|
|
383
|
+
getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
|
|
396
384
|
readAndParseBlob: async (id) => (0, driver_utils_1.readAndParse)(this.storage, id),
|
|
397
385
|
// GC runs in summarizer client and needs access to the real (non-proxy) active information. The proxy
|
|
398
386
|
// delta manager would always return false for summarizer client.
|
|
@@ -430,7 +418,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
430
418
|
blobId,
|
|
431
419
|
});
|
|
432
420
|
}
|
|
433
|
-
}, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), (blobPath) => this.garbageCollector.isNodeDeleted(blobPath), this, pendingRuntimeState
|
|
421
|
+
}, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), (blobPath) => this.garbageCollector.isNodeDeleted(blobPath), this, pendingRuntimeState?.pendingAttachmentBlobs, (error) => this.closeFn(error));
|
|
434
422
|
this.scheduleManager = new scheduleManager_1.ScheduleManager(this.innerDeltaManager, this, () => this.clientId, (0, telemetry_utils_1.createChildLogger)({ logger: this.logger, namespace: "ScheduleManager" }));
|
|
435
423
|
this.pendingStateManager = new pendingStateManager_1.PendingStateManager({
|
|
436
424
|
applyStashedOp: this.applyStashedOp.bind(this),
|
|
@@ -440,7 +428,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
440
428
|
reSubmit: this.reSubmit.bind(this),
|
|
441
429
|
reSubmitBatch: this.reSubmitBatch.bind(this),
|
|
442
430
|
isActiveConnection: () => this.innerDeltaManager.active,
|
|
443
|
-
}, pendingRuntimeState
|
|
431
|
+
}, pendingRuntimeState?.pending, this.logger);
|
|
444
432
|
const disableCompression = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionDisabled");
|
|
445
433
|
const compressionOptions = disableCompression === true
|
|
446
434
|
? {
|
|
@@ -481,9 +469,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
481
469
|
this._audience = audience;
|
|
482
470
|
this.summaryStateUpdateMethod = this.mc.config.getString("Fluid.ContainerRuntime.Test.SummaryStateUpdateMethodV2");
|
|
483
471
|
const closeSummarizerDelayOverride = this.mc.config.getNumber("Fluid.ContainerRuntime.Test.CloseSummarizerDelayOverrideMs");
|
|
484
|
-
this.closeSummarizerDelayMs = closeSummarizerDelayOverride
|
|
472
|
+
this.closeSummarizerDelayMs = closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
|
|
485
473
|
this.validateSummaryBeforeUpload =
|
|
486
|
-
|
|
474
|
+
this.mc.config.getBoolean("Fluid.ContainerRuntime.Test.ValidateSummaryBeforeUpload") ??
|
|
475
|
+
false;
|
|
487
476
|
this.summaryCollection = new summary_1.SummaryCollection(this.deltaManager, this.logger);
|
|
488
477
|
this.dirtyContainer =
|
|
489
478
|
this.attachState !== container_definitions_1.AttachState.Attached ||
|
|
@@ -498,7 +487,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
498
487
|
namespace: "OrderedClientElection",
|
|
499
488
|
});
|
|
500
489
|
const orderedClientCollection = new summary_1.OrderedClientCollection(orderedClientLogger, this.innerDeltaManager, this._quorum);
|
|
501
|
-
const orderedClientElectionForSummarizer = new summary_1.OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData
|
|
490
|
+
const orderedClientElectionForSummarizer = new summary_1.OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData ?? this.innerDeltaManager.lastSequenceNumber, summary_1.SummarizerClientElection.isClientEligible);
|
|
502
491
|
this.summarizerClientElection = new summary_1.SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, this.maxOpsSinceLastSummary);
|
|
503
492
|
if (this.isSummarizerClient) {
|
|
504
493
|
this._summarizer = new summary_1.Summarizer(this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => summary_1.RunWhileConnectedCoordinator.create(runtime,
|
|
@@ -559,8 +548,20 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
559
548
|
this.replayPendingStates();
|
|
560
549
|
});
|
|
561
550
|
// logging hardware telemetry
|
|
562
|
-
logger.sendTelemetryEvent(
|
|
563
|
-
|
|
551
|
+
logger.sendTelemetryEvent({
|
|
552
|
+
eventName: "DeviceSpec",
|
|
553
|
+
...getDeviceSpec(),
|
|
554
|
+
});
|
|
555
|
+
this.mc.logger.sendTelemetryEvent({
|
|
556
|
+
eventName: "ContainerLoadStats",
|
|
557
|
+
...this.createContainerMetadata,
|
|
558
|
+
...this.dataStores.containerLoadStats,
|
|
559
|
+
summaryNumber: loadSummaryNumber,
|
|
560
|
+
summaryFormatVersion: metadata?.summaryFormatVersion,
|
|
561
|
+
disableIsolatedChannels: metadata?.disableIsolatedChannels,
|
|
562
|
+
gcVersion: metadata?.gcFeature,
|
|
563
|
+
options: JSON.stringify(runtimeOptions),
|
|
564
|
+
featureGates: JSON.stringify({
|
|
564
565
|
disableCompression,
|
|
565
566
|
disableOpReentryCheck,
|
|
566
567
|
disableChunking,
|
|
@@ -569,7 +570,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
569
570
|
idCompressorEnabled: this.idCompressorEnabled,
|
|
570
571
|
summaryStateUpdateMethod: this.summaryStateUpdateMethod,
|
|
571
572
|
closeSummarizerDelayOverride,
|
|
572
|
-
}),
|
|
573
|
+
}),
|
|
574
|
+
telemetryDocumentId: this.telemetryDocumentId,
|
|
575
|
+
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
576
|
+
});
|
|
573
577
|
(0, connectionTelemetry_1.ReportOpPerfTelemetry)(this.clientId, this.deltaManager, this.logger);
|
|
574
578
|
(0, batchTracker_1.BindBatchTracker)(this, this.logger);
|
|
575
579
|
this.entryPoint = new core_utils_1.LazyPromise(async () => {
|
|
@@ -577,9 +581,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
577
581
|
(0, common_utils_1.assert)(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
|
|
578
582
|
return this._summarizer;
|
|
579
583
|
}
|
|
580
|
-
return initializeEntryPoint
|
|
584
|
+
return initializeEntryPoint?.(this);
|
|
581
585
|
});
|
|
582
586
|
}
|
|
587
|
+
/**
|
|
588
|
+
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
589
|
+
*/
|
|
583
590
|
get IFluidRouter() {
|
|
584
591
|
return this;
|
|
585
592
|
}
|
|
@@ -625,12 +632,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
625
632
|
* This object should provide all the functionality that the Container is expected to provide to the loader layer.
|
|
626
633
|
*/
|
|
627
634
|
static async loadRuntime(params) {
|
|
628
|
-
var _a, _b, _c, _d, _e, _f;
|
|
629
635
|
const { context, registryEntries, existing, requestHandler, runtimeOptions = {}, containerScope = {}, containerRuntimeCtor = ContainerRuntime, initializeEntryPoint, } = params;
|
|
630
636
|
// If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
|
|
631
637
|
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
632
638
|
const backCompatContext = context;
|
|
633
|
-
const passLogger =
|
|
639
|
+
const passLogger = backCompatContext.taggedLogger ??
|
|
640
|
+
new telemetry_utils_1.TaggedLoggerAdapter(backCompatContext.logger);
|
|
634
641
|
const logger = (0, telemetry_utils_1.createChildLogger)({
|
|
635
642
|
logger: passLogger,
|
|
636
643
|
properties: {
|
|
@@ -642,8 +649,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
642
649
|
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor = false, chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, enableGroupedBatching = false, } = runtimeOptions;
|
|
643
650
|
const registry = new dataStoreRegistry_1.FluidDataStoreRegistry(registryEntries);
|
|
644
651
|
const tryFetchBlob = async (blobName) => {
|
|
645
|
-
|
|
646
|
-
const blobId = (_a = context.baseSnapshot) === null || _a === void 0 ? void 0 : _a.blobs[blobName];
|
|
652
|
+
const blobId = context.baseSnapshot?.blobs[blobName];
|
|
647
653
|
if (context.baseSnapshot && blobId) {
|
|
648
654
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
649
655
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
@@ -658,16 +664,15 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
658
664
|
tryFetchBlob(summary_1.aliasBlobName),
|
|
659
665
|
tryFetchBlob(summary_1.idCompressorBlobName),
|
|
660
666
|
]);
|
|
661
|
-
const loadExisting = existing === true || context.existing === true;
|
|
662
667
|
// read snapshot blobs needed for BlobManager to load
|
|
663
|
-
const blobManagerSnapshot = await blobManager_1.BlobManager.load(
|
|
668
|
+
const blobManagerSnapshot = await blobManager_1.BlobManager.load(context.baseSnapshot?.trees[summary_1.blobsTreeName], async (id) => {
|
|
664
669
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
665
670
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
666
671
|
(0, common_utils_1.assert)(context.storage !== undefined, 0x256 /* "storage undefined in attached container" */);
|
|
667
672
|
return (0, driver_utils_1.readAndParse)(context.storage, id);
|
|
668
673
|
});
|
|
669
674
|
// Verify summary runtime sequence number matches protocol sequence number.
|
|
670
|
-
const runtimeSequenceNumber =
|
|
675
|
+
const runtimeSequenceNumber = metadata?.message?.sequenceNumber;
|
|
671
676
|
// When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
|
|
672
677
|
if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
|
|
673
678
|
const protocolSequenceNumber = context.deltaManager.initialSequenceNumber;
|
|
@@ -682,13 +687,11 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
682
687
|
logger.sendErrorEvent({ eventName: "SequenceNumberMismatch" }, error);
|
|
683
688
|
}
|
|
684
689
|
else {
|
|
685
|
-
// Call both close and dispose as closeFn implementation will no longer dispose runtime in future
|
|
686
690
|
context.closeFn(error);
|
|
687
|
-
(_d = context.disposeFn) === null || _d === void 0 ? void 0 : _d.call(context, error);
|
|
688
691
|
}
|
|
689
692
|
}
|
|
690
693
|
}
|
|
691
|
-
const idCompressorEnabled =
|
|
694
|
+
const idCompressorEnabled = metadata?.idCompressorEnabled ?? runtimeOptions.enableRuntimeIdCompressor ?? false;
|
|
692
695
|
let idCompressor;
|
|
693
696
|
if (idCompressorEnabled) {
|
|
694
697
|
const { IdCompressor, createSessionId } = await Promise.resolve().then(() => __importStar(require("./id-compressor")));
|
|
@@ -697,7 +700,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
697
700
|
? IdCompressor.deserialize(serializedIdCompressor, createSessionId())
|
|
698
701
|
: new IdCompressor(createSessionId(), logger);
|
|
699
702
|
}
|
|
700
|
-
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks
|
|
703
|
+
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], {
|
|
701
704
|
summaryOptions,
|
|
702
705
|
gcOptions,
|
|
703
706
|
loadSequenceNumberVerification,
|
|
@@ -708,7 +711,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
708
711
|
enableRuntimeIdCompressor,
|
|
709
712
|
enableOpReentryCheck,
|
|
710
713
|
enableGroupedBatching,
|
|
711
|
-
}, containerScope, logger,
|
|
714
|
+
}, containerScope, logger, existing, blobManagerSnapshot, context.storage, idCompressor, requestHandler, undefined, // summaryConfiguration
|
|
712
715
|
initializeEntryPoint);
|
|
713
716
|
// It's possible to have ops with a reference sequence number of 0. Op sequence numbers start
|
|
714
717
|
// at 1, so we won't see a replayed saved op with a sequence number of 0.
|
|
@@ -764,8 +767,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
764
767
|
}
|
|
765
768
|
/** clientId of parent (non-summarizing) container that owns summarizer container */
|
|
766
769
|
get summarizerClientId() {
|
|
767
|
-
|
|
768
|
-
return (_a = this.summarizerClientElection) === null || _a === void 0 ? void 0 : _a.electedClientId;
|
|
770
|
+
return this.summarizerClientElection?.electedClientId;
|
|
769
771
|
}
|
|
770
772
|
get disposed() {
|
|
771
773
|
return this._disposed;
|
|
@@ -802,7 +804,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
802
804
|
await this.garbageCollector.initializeBaseState();
|
|
803
805
|
}
|
|
804
806
|
dispose(error) {
|
|
805
|
-
var _a;
|
|
806
807
|
if (this._disposed) {
|
|
807
808
|
return;
|
|
808
809
|
}
|
|
@@ -817,7 +818,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
817
818
|
this.summaryManager.dispose();
|
|
818
819
|
}
|
|
819
820
|
this.garbageCollector.dispose();
|
|
820
|
-
|
|
821
|
+
this._summarizer?.dispose();
|
|
821
822
|
this.dataStores.dispose();
|
|
822
823
|
this.pendingStateManager.dispose();
|
|
823
824
|
this.emit("dispose");
|
|
@@ -826,6 +827,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
826
827
|
/**
|
|
827
828
|
* Notifies this object about the request made to the container.
|
|
828
829
|
* @param request - Request made to the handler.
|
|
830
|
+
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
829
831
|
*/
|
|
830
832
|
async request(request) {
|
|
831
833
|
try {
|
|
@@ -892,19 +894,17 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
892
894
|
return this.entryPoint;
|
|
893
895
|
}
|
|
894
896
|
internalId(maybeAlias) {
|
|
895
|
-
|
|
896
|
-
return (_a = this.dataStores.aliases.get(maybeAlias)) !== null && _a !== void 0 ? _a : maybeAlias;
|
|
897
|
+
return this.dataStores.aliases.get(maybeAlias) ?? maybeAlias;
|
|
897
898
|
}
|
|
898
899
|
async getDataStoreFromRequest(id, request) {
|
|
899
|
-
var _a, _b, _c;
|
|
900
900
|
const headerData = {};
|
|
901
|
-
if (typeof
|
|
901
|
+
if (typeof request.headers?.[RuntimeHeaders.wait] === "boolean") {
|
|
902
902
|
headerData.wait = request.headers[RuntimeHeaders.wait];
|
|
903
903
|
}
|
|
904
|
-
if (typeof
|
|
904
|
+
if (typeof request.headers?.[RuntimeHeaders.viaHandle] === "boolean") {
|
|
905
905
|
headerData.viaHandle = request.headers[RuntimeHeaders.viaHandle];
|
|
906
906
|
}
|
|
907
|
-
if (typeof
|
|
907
|
+
if (typeof request.headers?.[exports.AllowTombstoneRequestHeaderKey] === "boolean") {
|
|
908
908
|
headerData.allowTombstone = request.headers[exports.AllowTombstoneRequestHeaderKey];
|
|
909
909
|
}
|
|
910
910
|
await this.dataStores.waitIfPendingAlias(id);
|
|
@@ -914,22 +914,27 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
914
914
|
// Remove query params, leading and trailing slashes from the url. This is done to make sure the format is
|
|
915
915
|
// the same as GC nodes id.
|
|
916
916
|
const urlWithoutQuery = (0, gc_1.trimLeadingAndTrailingSlashes)(request.url.split("?")[0]);
|
|
917
|
-
this.garbageCollector.nodeUpdated(`/${urlWithoutQuery}`, "Loaded", undefined /* timestampMs */, dataStoreContext.packagePath, request
|
|
917
|
+
this.garbageCollector.nodeUpdated(`/${urlWithoutQuery}`, "Loaded", undefined /* timestampMs */, dataStoreContext.packagePath, request?.headers);
|
|
918
918
|
return dataStoreChannel;
|
|
919
919
|
}
|
|
920
920
|
/** Adds the container's metadata to the given summary tree. */
|
|
921
921
|
addMetadataToSummary(summaryTree) {
|
|
922
|
-
|
|
923
|
-
|
|
922
|
+
const metadata = {
|
|
923
|
+
...this.createContainerMetadata,
|
|
924
924
|
// Increment the summary number for the next summary that will be generated.
|
|
925
|
-
summaryNumber: this.nextSummaryNumber++,
|
|
925
|
+
summaryNumber: this.nextSummaryNumber++,
|
|
926
|
+
summaryFormatVersion: 1,
|
|
927
|
+
...this.garbageCollector.getMetadata(),
|
|
926
928
|
// The last message processed at the time of summary. If there are no new messages, use the message from the
|
|
927
929
|
// last summary.
|
|
928
|
-
message: (
|
|
930
|
+
message: (0, summary_1.extractSummaryMetadataMessage)(this.deltaManager.lastMessage) ??
|
|
931
|
+
this.messageAtLastSummary,
|
|
932
|
+
telemetryDocumentId: this.telemetryDocumentId,
|
|
933
|
+
idCompressorEnabled: this.idCompressorEnabled ? true : undefined,
|
|
934
|
+
};
|
|
929
935
|
(0, runtime_utils_1.addBlobToSummary)(summaryTree, summary_1.metadataBlobName, JSON.stringify(metadata));
|
|
930
936
|
}
|
|
931
937
|
addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext) {
|
|
932
|
-
var _a;
|
|
933
938
|
this.addMetadataToSummary(summaryTree);
|
|
934
939
|
if (this.idCompressorEnabled) {
|
|
935
940
|
(0, common_utils_1.assert)(this.idCompressor !== undefined, 0x67a /* IdCompressor should be defined if enabled */);
|
|
@@ -945,7 +950,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
945
950
|
(0, runtime_utils_1.addBlobToSummary)(summaryTree, summary_1.aliasBlobName, JSON.stringify([...dataStoreAliases]));
|
|
946
951
|
}
|
|
947
952
|
if (this.summarizerClientElection) {
|
|
948
|
-
const electedSummarizerContent = JSON.stringify(
|
|
953
|
+
const electedSummarizerContent = JSON.stringify(this.summarizerClientElection?.serialize());
|
|
949
954
|
(0, runtime_utils_1.addBlobToSummary)(summaryTree, summary_1.electedSummarizerBlobName, electedSummarizerContent);
|
|
950
955
|
}
|
|
951
956
|
const blobManagerSummary = this.blobManager.summarize();
|
|
@@ -992,7 +997,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
992
997
|
// in their own batches before the originating batch is sent.
|
|
993
998
|
// Therefore, receiving them while attempting to send the originating batch
|
|
994
999
|
// does not mean that the container is making any progress.
|
|
995
|
-
if (
|
|
1000
|
+
if (message?.type !== ContainerMessageType.ChunkedOp) {
|
|
996
1001
|
this.consecutiveReconnects = 0;
|
|
997
1002
|
}
|
|
998
1003
|
}
|
|
@@ -1147,7 +1152,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1147
1152
|
// or something different, like a system message.
|
|
1148
1153
|
const runtimeMessage = messageArg.type === protocol_definitions_1.MessageType.Operation;
|
|
1149
1154
|
// Do shallow copy of message, as the processing flow will modify it.
|
|
1150
|
-
const messageCopy =
|
|
1155
|
+
const messageCopy = { ...messageArg };
|
|
1151
1156
|
for (const message of this.remoteMessageProcessor.process(messageCopy)) {
|
|
1152
1157
|
this.processCore(message, local, runtimeMessage);
|
|
1153
1158
|
}
|
|
@@ -1159,7 +1164,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1159
1164
|
* @param runtimeMessage - Does this appear like a current ContainerRuntimeMessage? If true, certain validation will occur.
|
|
1160
1165
|
*/
|
|
1161
1166
|
processCore(message, local, runtimeMessage) {
|
|
1162
|
-
var _a;
|
|
1163
1167
|
// Surround the actual processing of the operation with messages to the schedule manager indicating
|
|
1164
1168
|
// the beginning and end. This allows it to emit appropriate events and/or pause the processing of new
|
|
1165
1169
|
// messages once a batch has been fully processed.
|
|
@@ -1204,7 +1208,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1204
1208
|
local,
|
|
1205
1209
|
type: message.type,
|
|
1206
1210
|
contentType: typeof message.contents,
|
|
1207
|
-
batch:
|
|
1211
|
+
batch: message.metadata?.batch,
|
|
1208
1212
|
compression: message.compression,
|
|
1209
1213
|
});
|
|
1210
1214
|
this.closeFn(error);
|
|
@@ -1281,6 +1285,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1281
1285
|
}
|
|
1282
1286
|
this.dataStores.processSignal(envelope.address, transformed, local);
|
|
1283
1287
|
}
|
|
1288
|
+
/**
|
|
1289
|
+
* Returns the runtime of the data store.
|
|
1290
|
+
* @param id - Id supplied during creating the data store.
|
|
1291
|
+
* @param wait - True if you want to wait for it.
|
|
1292
|
+
* @deprecated - Use getAliasedDataStoreEntryPoint instead to get an aliased data store's entry point.
|
|
1293
|
+
*/
|
|
1284
1294
|
async getRootDataStore(id, wait = true) {
|
|
1285
1295
|
return this.getRootDataStoreChannel(id, wait);
|
|
1286
1296
|
}
|
|
@@ -1342,9 +1352,25 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1342
1352
|
}
|
|
1343
1353
|
return result;
|
|
1344
1354
|
}
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1355
|
+
/**
|
|
1356
|
+
* Returns the aliased data store's entryPoint, given the alias.
|
|
1357
|
+
* @param alias - The alias for the data store.
|
|
1358
|
+
* @returns - The data store's entry point (IFluidHandle) if it exists and is aliased. Returns undefined if no
|
|
1359
|
+
* data store has been assigned the given alias.
|
|
1360
|
+
*/
|
|
1361
|
+
async getAliasedDataStoreEntryPoint(alias) {
|
|
1362
|
+
await this.dataStores.waitIfPendingAlias(alias);
|
|
1363
|
+
const internalId = this.internalId(alias);
|
|
1364
|
+
const context = await this.dataStores.getDataStoreIfAvailable(internalId, { wait: false });
|
|
1365
|
+
// If the data store is not available or not an alias, return undefined.
|
|
1366
|
+
if (context === undefined || !(await context.isRoot())) {
|
|
1367
|
+
return undefined;
|
|
1368
|
+
}
|
|
1369
|
+
const channel = await context.realize();
|
|
1370
|
+
if (channel.entryPoint === undefined) {
|
|
1371
|
+
throw new container_utils_1.UsageError("entryPoint must be defined on data store runtime for using getAliasedDataStoreEntryPoint");
|
|
1372
|
+
}
|
|
1373
|
+
return channel.entryPoint;
|
|
1348
1374
|
}
|
|
1349
1375
|
createDetachedRootDataStore(pkg, rootDataStoreId) {
|
|
1350
1376
|
if (rootDataStoreId.includes("/")) {
|
|
@@ -1355,16 +1381,20 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1355
1381
|
createDetachedDataStore(pkg) {
|
|
1356
1382
|
return this.dataStores.createDetachedDataStoreCore(pkg, false);
|
|
1357
1383
|
}
|
|
1358
|
-
async
|
|
1359
|
-
const
|
|
1360
|
-
|
|
1361
|
-
.
|
|
1362
|
-
|
|
1384
|
+
async createDataStore(pkg) {
|
|
1385
|
+
const id = (0, uuid_1.v4)();
|
|
1386
|
+
return (0, dataStore_1.channelToDataStore)(await this.dataStores
|
|
1387
|
+
._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id)
|
|
1388
|
+
.realize(), id, this, this.dataStores, this.mc.logger);
|
|
1363
1389
|
}
|
|
1364
|
-
|
|
1365
|
-
|
|
1390
|
+
/**
|
|
1391
|
+
* @deprecated 0.16 Issue #1537, #3631
|
|
1392
|
+
* @internal
|
|
1393
|
+
*/
|
|
1394
|
+
async _createDataStoreWithProps(pkg, props, id = (0, uuid_1.v4)()) {
|
|
1395
|
+
return (0, dataStore_1.channelToDataStore)(await this.dataStores
|
|
1366
1396
|
._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, props)
|
|
1367
|
-
.realize();
|
|
1397
|
+
.realize(), id, this, this.dataStores, this.mc.logger);
|
|
1368
1398
|
}
|
|
1369
1399
|
canSendOps() {
|
|
1370
1400
|
// Note that the real (non-proxy) delta manager is needed here to get the readonly info. This is because
|
|
@@ -1473,7 +1503,11 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1473
1503
|
(0, summary_1.wrapSummaryInChannelsTree)(summarizeResult);
|
|
1474
1504
|
const pathPartsForChildren = [runtime_definitions_1.channelsTreeName];
|
|
1475
1505
|
this.addContainerStateToSummary(summarizeResult, fullTree, trackState, telemetryContext);
|
|
1476
|
-
return
|
|
1506
|
+
return {
|
|
1507
|
+
...summarizeResult,
|
|
1508
|
+
id: "",
|
|
1509
|
+
pathPartsForChildren,
|
|
1510
|
+
};
|
|
1477
1511
|
}
|
|
1478
1512
|
/**
|
|
1479
1513
|
* Returns a summary of the runtime at the current sequence number.
|
|
@@ -1491,13 +1525,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1491
1525
|
runSweep,
|
|
1492
1526
|
});
|
|
1493
1527
|
try {
|
|
1494
|
-
let gcStats;
|
|
1495
1528
|
if (runGC) {
|
|
1496
|
-
|
|
1529
|
+
await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC }, telemetryContext);
|
|
1497
1530
|
}
|
|
1498
1531
|
const { stats, summary } = await this.summarizerNode.summarize(fullTree, trackState, telemetryContext);
|
|
1499
1532
|
(0, common_utils_1.assert)(summary.type === protocol_definitions_1.SummaryType.Tree, 0x12f /* "Container Runtime's summarize should always return a tree" */);
|
|
1500
|
-
return { stats, summary
|
|
1533
|
+
return { stats, summary };
|
|
1501
1534
|
}
|
|
1502
1535
|
finally {
|
|
1503
1536
|
this.mc.logger.sendTelemetryEvent({
|
|
@@ -1582,21 +1615,19 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1582
1615
|
* Returns a server generated referenced timestamp to be used to track unreferenced nodes by GC.
|
|
1583
1616
|
*/
|
|
1584
1617
|
getCurrentReferenceTimestampMs() {
|
|
1585
|
-
var _a, _b, _c;
|
|
1586
1618
|
// Use the timestamp of the last message seen by this client as that is server generated. If no messages have
|
|
1587
1619
|
// been processed, use the timestamp of the message from the last summary.
|
|
1588
|
-
return
|
|
1620
|
+
return this.deltaManager.lastMessage?.timestamp ?? this.messageAtLastSummary?.timestamp;
|
|
1589
1621
|
}
|
|
1590
1622
|
/**
|
|
1591
1623
|
* Returns the type of the GC node. Currently, there are nodes that belong to the root ("/"), data stores or
|
|
1592
1624
|
* blob manager.
|
|
1593
1625
|
*/
|
|
1594
1626
|
getNodeType(nodePath) {
|
|
1595
|
-
var _a;
|
|
1596
1627
|
if (this.isBlobPath(nodePath)) {
|
|
1597
1628
|
return gc_1.GCNodeType.Blob;
|
|
1598
1629
|
}
|
|
1599
|
-
return
|
|
1630
|
+
return this.dataStores.getGCNodeType(nodePath) ?? gc_1.GCNodeType.Other;
|
|
1600
1631
|
}
|
|
1601
1632
|
/**
|
|
1602
1633
|
* Called by GC to retrieve the package path of the node with the given path. The node should belong to a
|
|
@@ -1667,7 +1698,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1667
1698
|
* @param options - options controlling how the summary is generated or submitted
|
|
1668
1699
|
*/
|
|
1669
1700
|
async submitSummary(options) {
|
|
1670
|
-
var _a, _b;
|
|
1671
1701
|
const { fullTree = false, refreshLatestAck, summaryLogger } = options;
|
|
1672
1702
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
1673
1703
|
// use it for all events logged during this summary.
|
|
@@ -1683,7 +1713,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1683
1713
|
if (refreshLatestAck) {
|
|
1684
1714
|
const latestSnapshotInfo = await this.refreshLatestSummaryAckFromServer((0, telemetry_utils_1.createChildLogger)({
|
|
1685
1715
|
logger: summaryNumberLogger,
|
|
1686
|
-
namespace: undefined,
|
|
1687
1716
|
properties: { all: { safeSummary: true } },
|
|
1688
1717
|
}));
|
|
1689
1718
|
const latestSnapshotRefSeq = latestSnapshotInfo.latestSnapshotRefSeq;
|
|
@@ -1705,7 +1734,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1705
1734
|
this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger);
|
|
1706
1735
|
// Helper function to check whether we should still continue between each async step.
|
|
1707
1736
|
const checkContinue = () => {
|
|
1708
|
-
var _a;
|
|
1709
1737
|
// Do not check for loss of connectivity directly! Instead leave it up to
|
|
1710
1738
|
// RunWhileConnectedCoordinator to control policy in a single place.
|
|
1711
1739
|
// This will allow easier change of design if we chose to. For example, we may chose to allow
|
|
@@ -1728,7 +1756,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1728
1756
|
error: `lastSequenceNumber changed before uploading to storage. ${this.deltaManager.lastSequenceNumber} !== ${summaryRefSeqNum}`,
|
|
1729
1757
|
};
|
|
1730
1758
|
}
|
|
1731
|
-
(0, common_utils_1.assert)(summaryRefSeqNum ===
|
|
1759
|
+
(0, common_utils_1.assert)(summaryRefSeqNum === this.deltaManager.lastMessage?.sequenceNumber, 0x395 /* it's one and the same thing */);
|
|
1732
1760
|
if (lastAck !== this.summaryCollection.latestAck) {
|
|
1733
1761
|
return {
|
|
1734
1762
|
continue: false,
|
|
@@ -1767,6 +1795,21 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1767
1795
|
error,
|
|
1768
1796
|
};
|
|
1769
1797
|
}
|
|
1798
|
+
// If validateSummaryBeforeUpload is true, validate that the summary generated by the summarizer nodes is
|
|
1799
|
+
// correct before this summary is uploaded.
|
|
1800
|
+
if (this.validateSummaryBeforeUpload) {
|
|
1801
|
+
const validateResult = this.summarizerNode.validateSummary();
|
|
1802
|
+
if (!validateResult.success) {
|
|
1803
|
+
const { success, ...loggingProps } = validateResult;
|
|
1804
|
+
const error = new summary_1.RetriableSummaryError(validateResult.reason, validateResult.retryAfterSeconds, { ...loggingProps });
|
|
1805
|
+
return {
|
|
1806
|
+
stage: "base",
|
|
1807
|
+
referenceSequenceNumber: summaryRefSeqNum,
|
|
1808
|
+
minimumSequenceNumber,
|
|
1809
|
+
error,
|
|
1810
|
+
};
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1770
1813
|
const { summary: summaryTree, stats: partialStats } = summarizeResult;
|
|
1771
1814
|
// Now that we have generated the summary, update the message at last summary to the last message processed.
|
|
1772
1815
|
this.messageAtLastSummary = this.deltaManager.lastMessage;
|
|
@@ -1779,7 +1822,15 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1779
1822
|
const gcSummaryTreeStats = summaryTree.tree[runtime_definitions_1.gcTreeKey]
|
|
1780
1823
|
? (0, runtime_utils_1.calculateStats)(summaryTree.tree[runtime_definitions_1.gcTreeKey])
|
|
1781
1824
|
: undefined;
|
|
1782
|
-
const summaryStats =
|
|
1825
|
+
const summaryStats = {
|
|
1826
|
+
dataStoreCount: this.dataStores.size,
|
|
1827
|
+
summarizedDataStoreCount: this.dataStores.size - handleCount,
|
|
1828
|
+
gcStateUpdatedDataStoreCount: this.garbageCollector.updatedDSCountSinceLastSummary,
|
|
1829
|
+
gcBlobNodeCount: gcSummaryTreeStats?.blobNodeCount,
|
|
1830
|
+
gcTotalBlobsSize: gcSummaryTreeStats?.totalBlobSize,
|
|
1831
|
+
summaryNumber,
|
|
1832
|
+
...partialStats,
|
|
1833
|
+
};
|
|
1783
1834
|
const generateSummaryData = {
|
|
1784
1835
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
1785
1836
|
minimumSequenceNumber,
|
|
@@ -1788,19 +1839,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1788
1839
|
generateDuration: trace.trace().duration,
|
|
1789
1840
|
forcedFullTree,
|
|
1790
1841
|
};
|
|
1791
|
-
// If validateSummaryBeforeUpload is true, validate that the summary generated by the summarizer nodes is
|
|
1792
|
-
// correct before this summary is uploaded.
|
|
1793
|
-
if (this.validateSummaryBeforeUpload) {
|
|
1794
|
-
const validateResult = this.summarizerNode.validateSummary();
|
|
1795
|
-
if (!validateResult.success) {
|
|
1796
|
-
const { success } = validateResult, loggingProps = __rest(validateResult, ["success"]);
|
|
1797
|
-
const error = new summary_1.RetriableSummaryError(validateResult.reason, validateResult.retryAfterSeconds, Object.assign({}, loggingProps));
|
|
1798
|
-
return Object.assign(Object.assign({ stage: "base" }, generateSummaryData), { error });
|
|
1799
|
-
}
|
|
1800
|
-
}
|
|
1801
1842
|
continueResult = checkContinue();
|
|
1802
1843
|
if (!continueResult.continue) {
|
|
1803
|
-
return
|
|
1844
|
+
return { stage: "generate", ...generateSummaryData, error: continueResult.error };
|
|
1804
1845
|
}
|
|
1805
1846
|
// It may happen that the lastAck it not correct due to missing summaryAck in case of single commit
|
|
1806
1847
|
// summary. So if the previous summarizer closes just after submitting the summary and before
|
|
@@ -1808,7 +1849,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1808
1849
|
// latestSnapshotVersionId from storage and it does not match with the lastAck ackHandle, then use
|
|
1809
1850
|
// the one fetched from storage as parent as that is the latest.
|
|
1810
1851
|
let summaryContext;
|
|
1811
|
-
if (
|
|
1852
|
+
if (lastAck?.summaryAck.contents.handle !== latestSnapshotVersionId &&
|
|
1812
1853
|
latestSnapshotVersionId !== undefined) {
|
|
1813
1854
|
summaryContext = {
|
|
1814
1855
|
proposalHandle: undefined,
|
|
@@ -1835,7 +1876,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1835
1876
|
handle = await this.storage.uploadSummaryWithContext(summarizeResult.summary, summaryContext);
|
|
1836
1877
|
}
|
|
1837
1878
|
catch (error) {
|
|
1838
|
-
return
|
|
1879
|
+
return { stage: "generate", ...generateSummaryData, error };
|
|
1839
1880
|
}
|
|
1840
1881
|
const parent = summaryContext.ackHandle;
|
|
1841
1882
|
const summaryMessage = {
|
|
@@ -1845,25 +1886,34 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1845
1886
|
message,
|
|
1846
1887
|
parents: parent ? [parent] : [],
|
|
1847
1888
|
};
|
|
1848
|
-
const uploadData =
|
|
1889
|
+
const uploadData = {
|
|
1890
|
+
...generateSummaryData,
|
|
1891
|
+
handle,
|
|
1892
|
+
uploadDuration: trace.trace().duration,
|
|
1893
|
+
};
|
|
1849
1894
|
continueResult = checkContinue();
|
|
1850
1895
|
if (!continueResult.continue) {
|
|
1851
|
-
return
|
|
1896
|
+
return { stage: "upload", ...uploadData, error: continueResult.error };
|
|
1852
1897
|
}
|
|
1853
1898
|
let clientSequenceNumber;
|
|
1854
1899
|
try {
|
|
1855
1900
|
clientSequenceNumber = this.submitSummaryMessage(summaryMessage, summaryRefSeqNum);
|
|
1856
1901
|
}
|
|
1857
1902
|
catch (error) {
|
|
1858
|
-
return
|
|
1903
|
+
return { stage: "upload", ...uploadData, error };
|
|
1859
1904
|
}
|
|
1860
|
-
const submitData =
|
|
1905
|
+
const submitData = {
|
|
1906
|
+
stage: "submit",
|
|
1907
|
+
...uploadData,
|
|
1908
|
+
clientSequenceNumber,
|
|
1909
|
+
submitOpDuration: trace.trace().duration,
|
|
1910
|
+
};
|
|
1861
1911
|
try {
|
|
1862
1912
|
// If validateSummaryBeforeUpload is false, the summary should be validated in this step.
|
|
1863
1913
|
this.summarizerNode.completeSummary(handle, !this.validateSummaryBeforeUpload /* validate */);
|
|
1864
1914
|
}
|
|
1865
1915
|
catch (error) {
|
|
1866
|
-
return
|
|
1916
|
+
return { stage: "upload", ...uploadData, error };
|
|
1867
1917
|
}
|
|
1868
1918
|
return submitData;
|
|
1869
1919
|
}
|
|
@@ -1871,7 +1921,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1871
1921
|
// Cleanup wip summary in case of failure
|
|
1872
1922
|
this.summarizerNode.clearSummary();
|
|
1873
1923
|
// ! This needs to happen before we resume inbound queues to ensure heuristics are tracked correctly
|
|
1874
|
-
|
|
1924
|
+
this._summarizer?.recordSummaryAttempt?.(summaryRefSeqNum);
|
|
1875
1925
|
// Restart the delta manager
|
|
1876
1926
|
this.deltaManager.inbound.resume();
|
|
1877
1927
|
if (shouldPauseInboundSignal) {
|
|
@@ -1917,7 +1967,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1917
1967
|
return this.blobManager.createBlob(blob, signal);
|
|
1918
1968
|
}
|
|
1919
1969
|
maybeSubmitIdAllocationOp(type) {
|
|
1920
|
-
var _a, _b;
|
|
1921
1970
|
if (type !== ContainerMessageType.IdAllocation) {
|
|
1922
1971
|
let idAllocationBatchMessage;
|
|
1923
1972
|
let idRange;
|
|
@@ -1925,7 +1974,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1925
1974
|
(0, common_utils_1.assert)(this.idCompressor !== undefined, 0x67d /* IdCompressor should be defined if enabled */);
|
|
1926
1975
|
idRange = this.idCompressor.takeNextCreationRange();
|
|
1927
1976
|
// Don't include the idRange if there weren't any Ids allocated
|
|
1928
|
-
idRange =
|
|
1977
|
+
idRange = idRange?.ids?.first !== undefined ? idRange : undefined;
|
|
1929
1978
|
}
|
|
1930
1979
|
if (idRange !== undefined) {
|
|
1931
1980
|
const idAllocationMessage = {
|
|
@@ -1936,7 +1985,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1936
1985
|
contents: JSON.stringify(idAllocationMessage),
|
|
1937
1986
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
1938
1987
|
metadata: undefined,
|
|
1939
|
-
localOpMetadata:
|
|
1988
|
+
localOpMetadata: this.idCompressor?.serialize(true),
|
|
1940
1989
|
type: ContainerMessageType.IdAllocation,
|
|
1941
1990
|
};
|
|
1942
1991
|
}
|
|
@@ -2214,7 +2263,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
2214
2263
|
summaryRefSeq,
|
|
2215
2264
|
fetchedSnapshotRefSeq: fetchResult.latestSnapshotRefSeq,
|
|
2216
2265
|
});
|
|
2217
|
-
this.
|
|
2266
|
+
this.disposeFn(error);
|
|
2218
2267
|
throw error;
|
|
2219
2268
|
}
|
|
2220
2269
|
// In case we had to retrieve the latest snapshot and it is different than summaryRefSeq,
|
|
@@ -2253,7 +2302,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
2253
2302
|
return this.fetchSnapshotFromStorageAndClose(logger, event, readAndParseBlob, null /* latest */);
|
|
2254
2303
|
}
|
|
2255
2304
|
async fetchSnapshotFromStorageAndClose(logger, event, readAndParseBlob, versionId) {
|
|
2256
|
-
var _a;
|
|
2257
2305
|
const snapshotResults = await telemetry_utils_1.PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
|
|
2258
2306
|
const stats = {};
|
|
2259
2307
|
const trace = common_utils_1.Trace.start();
|
|
@@ -2277,26 +2325,36 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
2277
2325
|
// situations which the main client (which is likely to be re-elected as the leader again)
|
|
2278
2326
|
// loads the summarizer from cache.
|
|
2279
2327
|
if (this.summaryStateUpdateMethod !== "refreshFromSnapshot") {
|
|
2280
|
-
this.mc.logger.sendTelemetryEvent(
|
|
2328
|
+
this.mc.logger.sendTelemetryEvent({
|
|
2329
|
+
...event,
|
|
2330
|
+
eventName: "ClosingSummarizerOnSummaryStale",
|
|
2331
|
+
codePath: event.eventName,
|
|
2332
|
+
message: "Stopping fetch from storage",
|
|
2333
|
+
versionId: versionId != null ? versionId : undefined,
|
|
2334
|
+
closeSummarizerDelayMs: this.closeSummarizerDelayMs,
|
|
2335
|
+
}, new container_utils_1.GenericError("Restarting summarizer instead of refreshing"));
|
|
2281
2336
|
// Delay before restarting summarizer to prevent the summarizer from restarting too frequently.
|
|
2282
2337
|
await (0, common_utils_1.delay)(this.closeSummarizerDelayMs);
|
|
2283
|
-
|
|
2338
|
+
this._summarizer?.stop("latestSummaryStateStale");
|
|
2284
2339
|
this.disposeFn();
|
|
2285
2340
|
}
|
|
2286
2341
|
return snapshotResults;
|
|
2287
2342
|
}
|
|
2288
2343
|
notifyAttaching() { } // do nothing (deprecated method)
|
|
2289
|
-
getPendingLocalState() {
|
|
2344
|
+
async getPendingLocalState(props) {
|
|
2345
|
+
this.verifyNotClosed();
|
|
2346
|
+
const waitBlobsToAttach = props?.notifyImminentClosure;
|
|
2290
2347
|
if (this._orderSequentiallyCalls !== 0) {
|
|
2291
2348
|
throw new container_utils_1.UsageError("can't get state during orderSequentially");
|
|
2292
2349
|
}
|
|
2350
|
+
const pendingAttachmentBlobs = await this.blobManager.getPendingBlobs(waitBlobsToAttach);
|
|
2293
2351
|
// Flush pending batch.
|
|
2294
2352
|
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
2295
2353
|
// to close current batch.
|
|
2296
2354
|
this.flush();
|
|
2297
2355
|
return {
|
|
2298
2356
|
pending: this.pendingStateManager.getLocalState(),
|
|
2299
|
-
pendingAttachmentBlobs
|
|
2357
|
+
pendingAttachmentBlobs,
|
|
2300
2358
|
};
|
|
2301
2359
|
}
|
|
2302
2360
|
/**
|