@fluidframework/container-runtime 2.0.0-dev.6.4.0.192049 → 2.0.0-dev.7.2.0.204906
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 +119 -0
- package/api-extractor.json +1 -1
- package/api-report/container-runtime.api.md +866 -0
- package/dist/blobManager.d.ts +4 -6
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +56 -78
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +75 -42
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/container-runtime-alpha.d.ts +1744 -0
- package/dist/container-runtime-beta.d.ts +1744 -0
- package/dist/container-runtime-public.d.ts +1744 -0
- package/dist/container-runtime-untrimmed.d.ts +1805 -0
- package/dist/containerHandleContext.js +3 -3
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +94 -102
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +478 -454
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +11 -11
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +2 -4
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +56 -59
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts +3 -0
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +6 -3
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts +0 -2
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +3 -8
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerProxyBase.js +4 -4
- package/dist/deltaManagerProxyBase.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js +6 -6
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +6 -0
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +36 -25
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +1 -0
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +13 -3
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +48 -28
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +10 -7
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcSummaryDefinitions.d.ts +1 -1
- package/dist/gc/gcSummaryDefinitions.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +3 -4
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +7 -8
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +3 -3
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +2 -2
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +3 -7
- package/dist/gc/index.js.map +1 -1
- package/dist/id-compressor/appendOnlySortedMap.js.map +1 -1
- package/dist/id-compressor/idCompressor.js.map +1 -1
- package/dist/id-compressor/identifiers.d.ts +3 -3
- package/dist/id-compressor/identifiers.d.ts.map +1 -1
- package/dist/id-compressor/utilities.d.ts +3 -0
- package/dist/id-compressor/utilities.d.ts.map +1 -1
- package/dist/id-compressor/utilities.js +3 -0
- package/dist/id-compressor/utilities.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/messageTypes.d.ts +137 -0
- package/dist/messageTypes.d.ts.map +1 -0
- package/dist/messageTypes.js +32 -0
- package/dist/messageTypes.js.map +1 -0
- package/dist/opLifecycle/batchManager.js +6 -6
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +7 -3
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +0 -4
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.js +3 -3
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +7 -2
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +17 -3
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +38 -25
- 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 -20
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +36 -46
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.js +6 -2
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +7 -4
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +54 -54
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts +5 -0
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js +7 -6
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +40 -38
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +2 -0
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +18 -8
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.js +6 -6
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.js +9 -9
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +8 -8
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js +3 -3
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +2 -2
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +107 -22
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +18 -2
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +23 -21
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +15 -6
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +3 -3
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +2 -2
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +10 -10
- package/dist/summary/summaryManager.js.map +1 -1
- package/dist/throttler.js +16 -16
- package/dist/throttler.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/blobManager.d.ts +4 -6
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +58 -80
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +76 -43
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerHandleContext.js +3 -3
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +94 -102
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +437 -418
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js +11 -11
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +2 -4
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +57 -60
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts +3 -0
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js +6 -3
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts +0 -2
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +4 -9
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerProxyBase.js +4 -4
- package/lib/deltaManagerProxyBase.js.map +1 -1
- package/lib/deltaManagerSummarizerProxy.js +6 -6
- package/lib/deltaManagerSummarizerProxy.js.map +1 -1
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +6 -0
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +36 -25
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts +1 -0
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +15 -5
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +48 -28
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js +9 -6
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcSummaryDefinitions.d.ts +1 -1
- package/lib/gc/gcSummaryDefinitions.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +3 -4
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +7 -8
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.js +3 -3
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/lib/gc/index.d.ts +2 -2
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +2 -2
- package/lib/gc/index.js.map +1 -1
- package/lib/id-compressor/appendOnlySortedMap.js.map +1 -1
- package/lib/id-compressor/idCompressor.js.map +1 -1
- package/lib/id-compressor/identifiers.d.ts +3 -3
- package/lib/id-compressor/identifiers.d.ts.map +1 -1
- package/lib/id-compressor/utilities.d.ts +3 -0
- package/lib/id-compressor/utilities.d.ts.map +1 -1
- package/lib/id-compressor/utilities.js +3 -0
- package/lib/id-compressor/utilities.js.map +1 -1
- package/lib/index.d.ts +5 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -1
- package/lib/index.js.map +1 -1
- package/lib/messageTypes.d.ts +137 -0
- package/lib/messageTypes.d.ts.map +1 -0
- package/lib/messageTypes.js +29 -0
- package/lib/messageTypes.js.map +1 -0
- package/lib/opLifecycle/batchManager.js +6 -6
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +7 -3
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +0 -4
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.js +1 -1
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +7 -2
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +17 -3
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +37 -24
- 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 -20
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +35 -45
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.js +6 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +7 -4
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +54 -54
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.d.ts +5 -0
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js +7 -6
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +40 -38
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +2 -0
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +19 -9
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.js +6 -6
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.js +9 -9
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +8 -8
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js +3 -3
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +2 -2
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +107 -22
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +18 -2
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +23 -21
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +15 -6
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +3 -3
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +2 -2
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +9 -9
- package/lib/summary/summaryManager.js.map +1 -1
- package/lib/throttler.js +16 -16
- package/lib/throttler.js.map +1 -1
- package/package.json +32 -29
- package/src/blobManager.ts +67 -92
- package/src/connectionTelemetry.ts +97 -52
- package/src/containerRuntime.ts +351 -351
- package/src/dataStore.ts +3 -3
- package/src/dataStoreContext.ts +9 -13
- package/src/dataStoreRegistry.ts +3 -0
- package/src/dataStores.ts +5 -17
- package/src/error.ts +4 -1
- package/src/gc/garbageCollection.ts +25 -12
- package/src/gc/gcConfigs.ts +25 -7
- package/src/gc/gcDefinitions.ts +49 -29
- package/src/gc/gcSummaryDefinitions.ts +1 -1
- package/src/gc/gcTelemetry.ts +8 -8
- package/src/gc/index.ts +2 -6
- package/src/id-compressor/utilities.ts +3 -0
- package/src/index.ts +21 -5
- package/src/messageTypes.ts +228 -0
- package/src/opLifecycle/README.md +93 -68
- package/src/opLifecycle/definitions.ts +5 -1
- package/src/opLifecycle/opDecompressor.ts +0 -8
- package/src/opLifecycle/opGroupingManager.ts +2 -4
- package/src/opLifecycle/opSplitter.ts +2 -2
- package/src/opLifecycle/outbox.ts +3 -0
- package/src/opLifecycle/remoteMessageProcessor.ts +54 -33
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +31 -52
- package/src/scheduleManager.ts +2 -0
- package/src/summary/orderedClientElection.ts +4 -1
- package/src/summary/runWhileConnectedCoordinator.ts +5 -1
- package/src/summary/runningSummarizer.ts +3 -1
- package/src/summary/summarizer.ts +21 -7
- package/src/summary/summarizerNode/summarizerNode.ts +1 -1
- package/src/summary/summarizerTypes.ts +96 -11
- package/src/summary/summaryCollection.ts +19 -1
- package/src/summary/summaryFormat.ts +11 -1
- package/src/summary/summaryGenerator.ts +3 -3
- package/src/summary/summaryManager.ts +2 -2
- package/src/gc/gcEarlyAdoption.md +0 -145
package/src/containerRuntime.ts
CHANGED
|
@@ -8,9 +8,11 @@ import {
|
|
|
8
8
|
FluidObject,
|
|
9
9
|
IFluidHandle,
|
|
10
10
|
IFluidHandleContext,
|
|
11
|
+
// eslint-disable-next-line import/no-deprecated
|
|
11
12
|
IFluidRouter,
|
|
12
13
|
IRequest,
|
|
13
14
|
IResponse,
|
|
15
|
+
IProvideFluidHandleContext,
|
|
14
16
|
} from "@fluidframework/core-interfaces";
|
|
15
17
|
import {
|
|
16
18
|
IAudience,
|
|
@@ -21,6 +23,7 @@ import {
|
|
|
21
23
|
ICriticalContainerError,
|
|
22
24
|
AttachState,
|
|
23
25
|
ILoaderOptions,
|
|
26
|
+
ILoader,
|
|
24
27
|
LoaderHeader,
|
|
25
28
|
} from "@fluidframework/container-definitions";
|
|
26
29
|
import {
|
|
@@ -88,7 +91,6 @@ import {
|
|
|
88
91
|
IIdCompressorCore,
|
|
89
92
|
IdCreationRange,
|
|
90
93
|
IdCreationRangeWithStashedState,
|
|
91
|
-
IAttachMessage,
|
|
92
94
|
} from "@fluidframework/runtime-definitions";
|
|
93
95
|
import {
|
|
94
96
|
addBlobToSummary,
|
|
@@ -98,11 +100,11 @@ import {
|
|
|
98
100
|
create404Response,
|
|
99
101
|
exceptionToResponse,
|
|
100
102
|
GCDataBuilder,
|
|
101
|
-
requestFluidObject,
|
|
102
103
|
seqFromTree,
|
|
103
104
|
calculateStats,
|
|
104
105
|
TelemetryContext,
|
|
105
106
|
ReadAndParseBlob,
|
|
107
|
+
responseToException,
|
|
106
108
|
} from "@fluidframework/runtime-utils";
|
|
107
109
|
import { v4 as uuid } from "uuid";
|
|
108
110
|
import { ContainerFluidHandleContext } from "./containerHandleContext";
|
|
@@ -142,7 +144,6 @@ import {
|
|
|
142
144
|
IConnectableRuntime,
|
|
143
145
|
IGeneratedSummaryStats,
|
|
144
146
|
ISubmitSummaryOptions,
|
|
145
|
-
ISummarizer,
|
|
146
147
|
ISummarizerInternalsProvider,
|
|
147
148
|
ISummarizerRuntime,
|
|
148
149
|
IRefreshSummaryAckOptions,
|
|
@@ -155,6 +156,7 @@ import {
|
|
|
155
156
|
EnqueueSummarizeResult,
|
|
156
157
|
ISummarizerEvents,
|
|
157
158
|
IBaseSummarizeResult,
|
|
159
|
+
ISummarizer,
|
|
158
160
|
} from "./summary";
|
|
159
161
|
import { formExponentialFn, Throttler } from "./throttler";
|
|
160
162
|
import {
|
|
@@ -164,7 +166,6 @@ import {
|
|
|
164
166
|
IGarbageCollector,
|
|
165
167
|
IGCRuntimeOptions,
|
|
166
168
|
IGCStats,
|
|
167
|
-
shouldAllowGcTombstoneEnforcement,
|
|
168
169
|
trimLeadingAndTrailingSlashes,
|
|
169
170
|
} from "./gc";
|
|
170
171
|
import { channelToDataStore, IDataStoreAliasMessage, isDataStoreAliasMessage } from "./dataStore";
|
|
@@ -184,92 +185,45 @@ import {
|
|
|
184
185
|
} from "./opLifecycle";
|
|
185
186
|
import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy";
|
|
186
187
|
import { IBatchMetadata } from "./metadata";
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
// Signifies that a blob has been attached and should not be garbage collected by storage
|
|
199
|
-
BlobAttach = "blobAttach",
|
|
200
|
-
|
|
201
|
-
// Ties our new clientId to our old one on reconnect
|
|
202
|
-
Rejoin = "rejoin",
|
|
203
|
-
|
|
204
|
-
// Sets the alias of a root data store
|
|
205
|
-
Alias = "alias",
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* An op containing an IdRange of Ids allocated using the runtime's IdCompressor since
|
|
209
|
-
* the last allocation op was sent.
|
|
210
|
-
* See the [IdCompressor README](./id-compressor/README.md) for more details.
|
|
211
|
-
*/
|
|
212
|
-
IdAllocation = "idAllocation",
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* How should an older client handle an unrecognized remote op type?
|
|
217
|
-
*
|
|
218
|
-
* @internal
|
|
219
|
-
*/
|
|
220
|
-
export type CompatModeBehavior =
|
|
221
|
-
/** Ignore the op. It won't be persisted if this client summarizes */
|
|
222
|
-
| "Ignore"
|
|
223
|
-
/** Fail processing immediately. (The container will close) */
|
|
224
|
-
| "FailToProcess";
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* All the info an older client would need to know how to handle an unrecognized remote op type
|
|
228
|
-
*
|
|
229
|
-
* @internal
|
|
230
|
-
*/
|
|
231
|
-
export interface IContainerRuntimeMessageCompatDetails {
|
|
232
|
-
/** How should an older client handle an unrecognized remote op type? */
|
|
233
|
-
behavior: CompatModeBehavior;
|
|
234
|
-
}
|
|
188
|
+
import {
|
|
189
|
+
ContainerMessageType,
|
|
190
|
+
type InboundSequencedContainerRuntimeMessage,
|
|
191
|
+
type InboundSequencedContainerRuntimeMessageOrSystemMessage,
|
|
192
|
+
type ContainerRuntimeIdAllocationMessage,
|
|
193
|
+
type LocalContainerRuntimeIdAllocationMessage,
|
|
194
|
+
type LocalContainerRuntimeMessage,
|
|
195
|
+
type OutboundContainerRuntimeMessage,
|
|
196
|
+
type UnknownContainerRuntimeMessage,
|
|
197
|
+
} from "./messageTypes";
|
|
235
198
|
|
|
236
199
|
/**
|
|
237
200
|
* Utility to implement compat behaviors given an unknown message type
|
|
238
201
|
* The parameters are typed to support compile-time enforcement of handling all known types/behaviors
|
|
239
202
|
*
|
|
240
|
-
* @param _unknownContainerRuntimeMessageType - Typed as
|
|
203
|
+
* @param _unknownContainerRuntimeMessageType - Typed as something unexpected, to ensure all known types have been
|
|
241
204
|
* handled before calling this function (e.g. in a switch statement).
|
|
242
205
|
* @param compatBehavior - Typed redundantly with CompatModeBehavior to ensure handling is added when updating that type
|
|
243
206
|
*/
|
|
244
207
|
function compatBehaviorAllowsMessageType(
|
|
245
|
-
_unknownContainerRuntimeMessageType:
|
|
208
|
+
_unknownContainerRuntimeMessageType: UnknownContainerRuntimeMessage["type"],
|
|
246
209
|
compatBehavior: "Ignore" | "FailToProcess" | undefined,
|
|
247
210
|
): boolean {
|
|
248
211
|
// undefined defaults to same behavior as "FailToProcess"
|
|
249
212
|
return compatBehavior === "Ignore";
|
|
250
213
|
}
|
|
251
214
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
/** Type of the op, within the ContainerRuntime's domain */
|
|
260
|
-
type: ContainerMessageType;
|
|
261
|
-
/** Domain-specific contents, interpreted according to the type */
|
|
262
|
-
contents: any;
|
|
263
|
-
/** Info describing how to handle this op in case the type is unrecognized (default: fail to process) */
|
|
264
|
-
compatDetails?: IContainerRuntimeMessageCompatDetails;
|
|
215
|
+
function prepareLocalContainerRuntimeIdAllocationMessageForTransit(
|
|
216
|
+
message: LocalContainerRuntimeIdAllocationMessage | ContainerRuntimeIdAllocationMessage,
|
|
217
|
+
): asserts message is ContainerRuntimeIdAllocationMessage {
|
|
218
|
+
// Remove the stashedState from the op if it's a stashed op
|
|
219
|
+
if ("stashedState" in message.contents) {
|
|
220
|
+
delete message.contents.stashedState;
|
|
221
|
+
}
|
|
265
222
|
}
|
|
266
223
|
|
|
267
224
|
/**
|
|
268
|
-
*
|
|
269
|
-
* promoted up to the outer object
|
|
225
|
+
* @public
|
|
270
226
|
*/
|
|
271
|
-
export type SequencedContainerRuntimeMessage = ISequencedDocumentMessage & ContainerRuntimeMessage;
|
|
272
|
-
|
|
273
227
|
export interface ISummaryBaseConfiguration {
|
|
274
228
|
/**
|
|
275
229
|
* Delay before first attempt to spawn summarizing container.
|
|
@@ -289,6 +243,9 @@ export interface ISummaryBaseConfiguration {
|
|
|
289
243
|
maxOpsSinceLastSummary: number;
|
|
290
244
|
}
|
|
291
245
|
|
|
246
|
+
/**
|
|
247
|
+
* @public
|
|
248
|
+
*/
|
|
292
249
|
export interface ISummaryConfigurationHeuristics extends ISummaryBaseConfiguration {
|
|
293
250
|
state: "enabled";
|
|
294
251
|
/**
|
|
@@ -349,19 +306,31 @@ export interface ISummaryConfigurationHeuristics extends ISummaryBaseConfigurati
|
|
|
349
306
|
nonRuntimeHeuristicThreshold?: number;
|
|
350
307
|
}
|
|
351
308
|
|
|
309
|
+
/**
|
|
310
|
+
* @public
|
|
311
|
+
*/
|
|
352
312
|
export interface ISummaryConfigurationDisableSummarizer {
|
|
353
313
|
state: "disabled";
|
|
354
314
|
}
|
|
355
315
|
|
|
316
|
+
/**
|
|
317
|
+
* @public
|
|
318
|
+
*/
|
|
356
319
|
export interface ISummaryConfigurationDisableHeuristics extends ISummaryBaseConfiguration {
|
|
357
320
|
state: "disableHeuristics";
|
|
358
321
|
}
|
|
359
322
|
|
|
323
|
+
/**
|
|
324
|
+
* @public
|
|
325
|
+
*/
|
|
360
326
|
export type ISummaryConfiguration =
|
|
361
327
|
| ISummaryConfigurationDisableSummarizer
|
|
362
328
|
| ISummaryConfigurationDisableHeuristics
|
|
363
329
|
| ISummaryConfigurationHeuristics;
|
|
364
330
|
|
|
331
|
+
/**
|
|
332
|
+
* @public
|
|
333
|
+
*/
|
|
365
334
|
export const DefaultSummaryConfiguration: ISummaryConfiguration = {
|
|
366
335
|
state: "enabled",
|
|
367
336
|
|
|
@@ -388,6 +357,9 @@ export const DefaultSummaryConfiguration: ISummaryConfiguration = {
|
|
|
388
357
|
nonRuntimeHeuristicThreshold: 20,
|
|
389
358
|
};
|
|
390
359
|
|
|
360
|
+
/**
|
|
361
|
+
* @public
|
|
362
|
+
*/
|
|
391
363
|
export interface ISummaryRuntimeOptions {
|
|
392
364
|
/** Override summary configurations set by the server. */
|
|
393
365
|
summaryConfigOverrides?: ISummaryConfiguration;
|
|
@@ -403,22 +375,25 @@ export interface ISummaryRuntimeOptions {
|
|
|
403
375
|
|
|
404
376
|
/**
|
|
405
377
|
* Options for op compression.
|
|
406
|
-
* @
|
|
378
|
+
* @public
|
|
407
379
|
*/
|
|
408
380
|
export interface ICompressionRuntimeOptions {
|
|
409
381
|
/**
|
|
410
|
-
* The
|
|
382
|
+
* The value the batch's content size must exceed for the batch to be compressed.
|
|
383
|
+
* By default the value is 600 * 1024 = 614400 bytes. If the value is set to `Infinity`, compression will be disabled.
|
|
411
384
|
*/
|
|
412
385
|
readonly minimumBatchSizeInBytes: number;
|
|
413
386
|
|
|
414
387
|
/**
|
|
415
388
|
* The compression algorithm that will be used to compress the op.
|
|
389
|
+
* By default the value is `lz4` which is the only compression algorithm currently supported.
|
|
416
390
|
*/
|
|
417
391
|
readonly compressionAlgorithm: CompressionAlgorithms;
|
|
418
392
|
}
|
|
419
393
|
|
|
420
394
|
/**
|
|
421
395
|
* Options for container runtime.
|
|
396
|
+
* @public
|
|
422
397
|
*/
|
|
423
398
|
export interface IContainerRuntimeOptions {
|
|
424
399
|
readonly summaryOptions?: ISummaryRuntimeOptions;
|
|
@@ -440,8 +415,7 @@ export interface IContainerRuntimeOptions {
|
|
|
440
415
|
*/
|
|
441
416
|
readonly flushMode?: FlushMode;
|
|
442
417
|
/**
|
|
443
|
-
* Enables the runtime to compress ops.
|
|
444
|
-
* @experimental Not ready for use.
|
|
418
|
+
* Enables the runtime to compress ops. See {@link ICompressionRuntimeOptions}.
|
|
445
419
|
*/
|
|
446
420
|
readonly compressionOptions?: ICompressionRuntimeOptions;
|
|
447
421
|
/**
|
|
@@ -458,12 +432,15 @@ export interface IContainerRuntimeOptions {
|
|
|
458
432
|
/**
|
|
459
433
|
* If the op payload needs to be chunked in order to work around the maximum size of the batch, this value represents
|
|
460
434
|
* how large the individual chunks will be. This is only supported when compression is enabled. If after compression, the
|
|
461
|
-
* batch size exceeds this value, it will be chunked into smaller ops of this size.
|
|
435
|
+
* batch content size exceeds this value, it will be chunked into smaller ops of this exact size.
|
|
462
436
|
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
437
|
+
* This value is a trade-off between having many small chunks vs fewer larger chunks and by default, the runtime is configured to use
|
|
438
|
+
* 200 * 1024 = 204800 bytes. This default value ensures that no compressed payload's content is able to exceed {@link IContainerRuntimeOptions.maxBatchSizeInBytes}
|
|
439
|
+
* regardless of the overhead of an individual op.
|
|
465
440
|
*
|
|
466
|
-
* @
|
|
441
|
+
* Any value of `chunkSizeInBytes` exceeding {@link IContainerRuntimeOptions.maxBatchSizeInBytes} will disable this feature, therefore if a compressed batch's content
|
|
442
|
+
* size exceeds {@link IContainerRuntimeOptions.maxBatchSizeInBytes} after compression, the container will close with an instance of `GenericError` with
|
|
443
|
+
* the `BatchTooLarge` message.
|
|
467
444
|
*/
|
|
468
445
|
readonly chunkSizeInBytes?: number;
|
|
469
446
|
|
|
@@ -498,6 +475,7 @@ export interface IContainerRuntimeOptions {
|
|
|
498
475
|
|
|
499
476
|
/**
|
|
500
477
|
* Accepted header keys for requests coming to the runtime.
|
|
478
|
+
* @public
|
|
501
479
|
*/
|
|
502
480
|
export enum RuntimeHeaders {
|
|
503
481
|
/** True to wait for a data store to be created and loaded before returning it. */
|
|
@@ -506,14 +484,25 @@ export enum RuntimeHeaders {
|
|
|
506
484
|
viaHandle = "viaHandle",
|
|
507
485
|
}
|
|
508
486
|
|
|
509
|
-
/** True if a tombstoned object should be returned without erroring
|
|
487
|
+
/** True if a tombstoned object should be returned without erroring
|
|
488
|
+
* @public
|
|
489
|
+
*/
|
|
510
490
|
export const AllowTombstoneRequestHeaderKey = "allowTombstone"; // Belongs in the enum above, but avoiding the breaking change
|
|
511
|
-
/**
|
|
491
|
+
/**
|
|
492
|
+
* [IRRELEVANT IF throwOnInactiveLoad OPTION NOT SET] True if an inactive object should be returned without erroring
|
|
493
|
+
* @public
|
|
494
|
+
*/
|
|
512
495
|
export const AllowInactiveRequestHeaderKey = "allowInactive"; // Belongs in the enum above, but avoiding the breaking change
|
|
513
496
|
|
|
514
|
-
/**
|
|
497
|
+
/**
|
|
498
|
+
* Tombstone error responses will have this header set to true
|
|
499
|
+
* @public
|
|
500
|
+
*/
|
|
515
501
|
export const TombstoneResponseHeaderKey = "isTombstoned";
|
|
516
|
-
/**
|
|
502
|
+
/**
|
|
503
|
+
* Inactive error responses will have this header set to true
|
|
504
|
+
* @public
|
|
505
|
+
*/
|
|
517
506
|
export const InactiveResponseHeaderKey = "isInactive";
|
|
518
507
|
|
|
519
508
|
/**
|
|
@@ -534,6 +523,7 @@ export const defaultRuntimeHeaderData: Required<RuntimeHeaderData> = {
|
|
|
534
523
|
|
|
535
524
|
/**
|
|
536
525
|
* Available compression algorithms for op compression.
|
|
526
|
+
* @public
|
|
537
527
|
*/
|
|
538
528
|
export enum CompressionAlgorithms {
|
|
539
529
|
lz4 = "lz4",
|
|
@@ -597,7 +587,8 @@ export const defaultPendingOpsRetryDelayMs = 1000;
|
|
|
597
587
|
const defaultCloseSummarizerDelayMs = 5000; // 5 seconds
|
|
598
588
|
|
|
599
589
|
/**
|
|
600
|
-
* @deprecated
|
|
590
|
+
* @deprecated use ContainerRuntimeMessageType instead
|
|
591
|
+
* @public
|
|
601
592
|
*/
|
|
602
593
|
export enum RuntimeMessage {
|
|
603
594
|
FluidDataStoreOp = "component",
|
|
@@ -610,7 +601,8 @@ export enum RuntimeMessage {
|
|
|
610
601
|
}
|
|
611
602
|
|
|
612
603
|
/**
|
|
613
|
-
* @deprecated
|
|
604
|
+
* @deprecated please use version in driver-utils
|
|
605
|
+
* @public
|
|
614
606
|
*/
|
|
615
607
|
export function isRuntimeMessage(message: ISequencedDocumentMessage): boolean {
|
|
616
608
|
return (Object.values(RuntimeMessage) as string[]).includes(message.type);
|
|
@@ -620,6 +612,7 @@ export function isRuntimeMessage(message: ISequencedDocumentMessage): boolean {
|
|
|
620
612
|
* Legacy ID for the built-in AgentScheduler. To minimize disruption while removing it, retaining this as a
|
|
621
613
|
* special-case for document dirty state. Ultimately we should have no special-cases from the
|
|
622
614
|
* ContainerRuntime's perspective.
|
|
615
|
+
* @public
|
|
623
616
|
*/
|
|
624
617
|
export const agentSchedulerId = "_scheduler";
|
|
625
618
|
|
|
@@ -660,23 +653,94 @@ export const makeLegacySendBatchFn =
|
|
|
660
653
|
deltaManager.flush();
|
|
661
654
|
};
|
|
662
655
|
|
|
656
|
+
/** Helper type for type constraints passed through several functions.
|
|
657
|
+
* message - The unpacked message. Likely a TypedContainerRuntimeMessage, but could also be a system op
|
|
658
|
+
* modernRuntimeMessage - Does this appear like a current TypedContainerRuntimeMessage?
|
|
659
|
+
* local - Did this client send the op?
|
|
660
|
+
*/
|
|
661
|
+
type MessageWithContext =
|
|
662
|
+
| {
|
|
663
|
+
message: InboundSequencedContainerRuntimeMessage;
|
|
664
|
+
modernRuntimeMessage: true;
|
|
665
|
+
local: boolean;
|
|
666
|
+
}
|
|
667
|
+
| {
|
|
668
|
+
message: InboundSequencedContainerRuntimeMessageOrSystemMessage;
|
|
669
|
+
modernRuntimeMessage: false;
|
|
670
|
+
local: boolean;
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
const summarizerRequestUrl = "_summarizer";
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Create and retrieve the summmarizer
|
|
677
|
+
*/
|
|
678
|
+
async function createSummarizer(loader: ILoader, url: string): Promise<ISummarizer> {
|
|
679
|
+
const request: IRequest = {
|
|
680
|
+
headers: {
|
|
681
|
+
[LoaderHeader.cache]: false,
|
|
682
|
+
[LoaderHeader.clientDetails]: {
|
|
683
|
+
capabilities: { interactive: false },
|
|
684
|
+
type: summarizerClientType,
|
|
685
|
+
},
|
|
686
|
+
[DriverHeader.summarizingClient]: true,
|
|
687
|
+
[LoaderHeader.reconnect]: false,
|
|
688
|
+
},
|
|
689
|
+
url,
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
const resolvedContainer = await loader.resolve(request);
|
|
693
|
+
let fluidObject: FluidObject<ISummarizer> | undefined;
|
|
694
|
+
|
|
695
|
+
// Older containers may not have the "getEntryPoint" API
|
|
696
|
+
// ! This check will need to stay until LTS of loader moves past 2.0.0-internal.7.0.0
|
|
697
|
+
if (resolvedContainer.getEntryPoint !== undefined) {
|
|
698
|
+
fluidObject = await resolvedContainer.getEntryPoint();
|
|
699
|
+
} else {
|
|
700
|
+
const response = await resolvedContainer.request({ url: `/${summarizerRequestUrl}` });
|
|
701
|
+
if (response.status !== 200 || response.mimeType !== "fluid/object") {
|
|
702
|
+
throw responseToException(response, request);
|
|
703
|
+
}
|
|
704
|
+
fluidObject = response.value;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
if (fluidObject?.ISummarizer === undefined) {
|
|
708
|
+
throw new UsageError("Fluid object does not implement ISummarizer");
|
|
709
|
+
}
|
|
710
|
+
return fluidObject.ISummarizer;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* This function is not supported publicly and exists for e2e testing
|
|
715
|
+
* @internal
|
|
716
|
+
*/
|
|
717
|
+
export async function TEST_requestSummarizer(loader: ILoader, url: string): Promise<ISummarizer> {
|
|
718
|
+
return createSummarizer(loader, url);
|
|
719
|
+
}
|
|
720
|
+
|
|
663
721
|
/**
|
|
664
722
|
* Represents the runtime of the container. Contains helper functions/state of the container.
|
|
665
723
|
* It will define the store level mappings.
|
|
724
|
+
* @public
|
|
666
725
|
*/
|
|
667
726
|
export class ContainerRuntime
|
|
668
727
|
extends TypedEventEmitter<IContainerRuntimeEvents & ISummarizerEvents>
|
|
669
|
-
implements
|
|
728
|
+
implements
|
|
729
|
+
IContainerRuntime,
|
|
730
|
+
IRuntime,
|
|
731
|
+
ISummarizerRuntime,
|
|
732
|
+
ISummarizerInternalsProvider,
|
|
733
|
+
IProvideFluidHandleContext
|
|
670
734
|
{
|
|
671
735
|
/**
|
|
672
|
-
* @deprecated
|
|
736
|
+
* @deprecated Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
673
737
|
*/
|
|
674
738
|
public get IFluidRouter() {
|
|
675
739
|
return this;
|
|
676
740
|
}
|
|
677
741
|
|
|
678
742
|
/**
|
|
679
|
-
* @deprecated
|
|
743
|
+
* @deprecated use loadRuntime instead.
|
|
680
744
|
* Load the stores from a snapshot and returns the runtime.
|
|
681
745
|
* @param context - Context of the container.
|
|
682
746
|
* @param registryEntries - Mapping to the stores.
|
|
@@ -703,10 +767,15 @@ export class ContainerRuntime
|
|
|
703
767
|
context,
|
|
704
768
|
registryEntries,
|
|
705
769
|
existing: existingFlag,
|
|
706
|
-
requestHandler,
|
|
707
770
|
runtimeOptions,
|
|
708
771
|
containerScope,
|
|
709
772
|
containerRuntimeCtor,
|
|
773
|
+
requestHandler,
|
|
774
|
+
provideEntryPoint: () => {
|
|
775
|
+
throw new UsageError(
|
|
776
|
+
"ContainerRuntime.load is deprecated and should no longer be used",
|
|
777
|
+
);
|
|
778
|
+
},
|
|
710
779
|
});
|
|
711
780
|
}
|
|
712
781
|
|
|
@@ -722,7 +791,7 @@ export class ContainerRuntime
|
|
|
722
791
|
* - containerScope - runtime services provided with context
|
|
723
792
|
* - containerRuntimeCtor - Constructor to use to create the ContainerRuntime instance.
|
|
724
793
|
* This allows mixin classes to leverage this method to define their own async initializer.
|
|
725
|
-
* -
|
|
794
|
+
* - provideEntryPoint - Promise that resolves to an object which will act as entryPoint for the Container.
|
|
726
795
|
* This object should provide all the functionality that the Container is expected to provide to the loader layer.
|
|
727
796
|
*/
|
|
728
797
|
public static async loadRuntime(params: {
|
|
@@ -732,30 +801,21 @@ export class ContainerRuntime
|
|
|
732
801
|
runtimeOptions?: IContainerRuntimeOptions;
|
|
733
802
|
containerScope?: FluidObject;
|
|
734
803
|
containerRuntimeCtor?: typeof ContainerRuntime;
|
|
804
|
+
/** @deprecated Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md */
|
|
735
805
|
requestHandler?: (request: IRequest, runtime: IContainerRuntime) => Promise<IResponse>;
|
|
736
|
-
|
|
806
|
+
provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>;
|
|
737
807
|
}): Promise<ContainerRuntime> {
|
|
738
808
|
const {
|
|
739
809
|
context,
|
|
740
810
|
registryEntries,
|
|
741
811
|
existing,
|
|
742
812
|
requestHandler,
|
|
813
|
+
provideEntryPoint,
|
|
743
814
|
runtimeOptions = {},
|
|
744
815
|
containerScope = {},
|
|
745
816
|
containerRuntimeCtor = ContainerRuntime,
|
|
746
817
|
} = params;
|
|
747
818
|
|
|
748
|
-
const initializeEntryPoint =
|
|
749
|
-
params.initializeEntryPoint ??
|
|
750
|
-
(async (containerRuntime: IContainerRuntime) => ({
|
|
751
|
-
get IFluidRouter() {
|
|
752
|
-
return this;
|
|
753
|
-
},
|
|
754
|
-
async request(req) {
|
|
755
|
-
return containerRuntime.request(req);
|
|
756
|
-
},
|
|
757
|
-
}));
|
|
758
|
-
|
|
759
819
|
// If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
|
|
760
820
|
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
761
821
|
const backCompatContext: IContainerContext | OldContainerContextWithLogger = context;
|
|
@@ -884,15 +944,14 @@ export class ContainerRuntime
|
|
|
884
944
|
blobManagerSnapshot,
|
|
885
945
|
context.storage,
|
|
886
946
|
idCompressor,
|
|
947
|
+
provideEntryPoint,
|
|
887
948
|
requestHandler,
|
|
888
949
|
undefined, // summaryConfiguration
|
|
889
|
-
initializeEntryPoint,
|
|
890
950
|
);
|
|
891
951
|
|
|
892
|
-
|
|
893
|
-
//
|
|
894
|
-
|
|
895
|
-
await runtime.pendingStateManager.applyStashedOpsAt(0);
|
|
952
|
+
// Apply stashed ops with a reference sequence number equal to the sequence number of the snapshot,
|
|
953
|
+
// or zero. This must be done before Container replays saved ops.
|
|
954
|
+
await runtime.pendingStateManager.applyStashedOpsAt(runtimeSequenceNumber ?? 0);
|
|
896
955
|
|
|
897
956
|
// Initialize the base state of the runtime before it's returned.
|
|
898
957
|
await runtime.initializeBaseState();
|
|
@@ -913,17 +972,6 @@ export class ContainerRuntime
|
|
|
913
972
|
return this._storage;
|
|
914
973
|
}
|
|
915
974
|
|
|
916
|
-
/** @deprecated - The functionality is no longer exposed publicly */
|
|
917
|
-
public get reSubmitFn() {
|
|
918
|
-
return (
|
|
919
|
-
type: ContainerMessageType,
|
|
920
|
-
contents: any,
|
|
921
|
-
localOpMetadata: unknown,
|
|
922
|
-
opMetadata: Record<string, unknown> | undefined,
|
|
923
|
-
) => this.reSubmitCore({ type, contents }, localOpMetadata, opMetadata);
|
|
924
|
-
// Note: compatDetails is not included in this deprecated API
|
|
925
|
-
}
|
|
926
|
-
|
|
927
975
|
private readonly submitFn: (
|
|
928
976
|
type: MessageType,
|
|
929
977
|
contents: any,
|
|
@@ -1132,10 +1180,20 @@ export class ContainerRuntime
|
|
|
1132
1180
|
*/
|
|
1133
1181
|
private nextSummaryNumber: number;
|
|
1134
1182
|
|
|
1135
|
-
/**
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1183
|
+
/** If false, loading or using a Tombstoned object should merely log, not fail */
|
|
1184
|
+
public get gcTombstoneEnforcementAllowed(): boolean {
|
|
1185
|
+
return this.garbageCollector.tombstoneEnforcementAllowed;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
/** If true, throw an error when a tombstone data store is retrieved */
|
|
1189
|
+
public get gcThrowOnTombstoneLoad(): boolean {
|
|
1190
|
+
return this.garbageCollector.throwOnTombstoneLoad;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
/** If true, throw an error when a tombstone data store is used. */
|
|
1194
|
+
public get gcThrowOnTombstoneUsage(): boolean {
|
|
1195
|
+
return this.garbageCollector.throwOnTombstoneUsage;
|
|
1196
|
+
}
|
|
1139
1197
|
|
|
1140
1198
|
/**
|
|
1141
1199
|
* GUID to identify a document in telemetry
|
|
@@ -1175,6 +1233,7 @@ export class ContainerRuntime
|
|
|
1175
1233
|
blobManagerSnapshot: IBlobManagerLoadInfo,
|
|
1176
1234
|
private readonly _storage: IDocumentStorageService,
|
|
1177
1235
|
idCompressor: (IIdCompressor & IIdCompressorCore) | undefined,
|
|
1236
|
+
provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>,
|
|
1178
1237
|
private readonly requestHandler?: (
|
|
1179
1238
|
request: IRequest,
|
|
1180
1239
|
runtime: IContainerRuntime,
|
|
@@ -1185,7 +1244,6 @@ export class ContainerRuntime
|
|
|
1185
1244
|
// the runtime configuration overrides
|
|
1186
1245
|
...runtimeOptions.summaryOptions?.summaryConfigOverrides,
|
|
1187
1246
|
},
|
|
1188
|
-
initializeEntryPoint?: (containerRuntime: IContainerRuntime) => Promise<FluidObject>,
|
|
1189
1247
|
) {
|
|
1190
1248
|
super();
|
|
1191
1249
|
|
|
@@ -1282,11 +1340,6 @@ export class ContainerRuntime
|
|
|
1282
1340
|
// Later updates come through calls to setConnectionState.
|
|
1283
1341
|
this._connected = connected;
|
|
1284
1342
|
|
|
1285
|
-
this.gcTombstoneEnforcementAllowed = shouldAllowGcTombstoneEnforcement(
|
|
1286
|
-
metadata?.gcFeatureMatrix?.tombstoneGeneration /* persisted */,
|
|
1287
|
-
this.runtimeOptions.gcOptions[gcTombstoneGenerationOptionName] /* current */,
|
|
1288
|
-
);
|
|
1289
|
-
|
|
1290
1343
|
this.mc.logger.sendTelemetryEvent({
|
|
1291
1344
|
eventName: "GCFeatureMatrix",
|
|
1292
1345
|
metadataValue: JSON.stringify(metadata?.gcFeatureMatrix),
|
|
@@ -1619,7 +1672,7 @@ export class ContainerRuntime
|
|
|
1619
1672
|
this, // IConnectedState
|
|
1620
1673
|
this.summaryCollection,
|
|
1621
1674
|
this.logger,
|
|
1622
|
-
this.
|
|
1675
|
+
this.formCreateSummarizerFn(loader),
|
|
1623
1676
|
new Throttler(
|
|
1624
1677
|
60 * 1000, // 60 sec delay window
|
|
1625
1678
|
30 * 1000, // 30 sec max delay
|
|
@@ -1638,35 +1691,6 @@ export class ContainerRuntime
|
|
|
1638
1691
|
}
|
|
1639
1692
|
}
|
|
1640
1693
|
|
|
1641
|
-
this.deltaManager.on("readonly", (readonly: boolean) => {
|
|
1642
|
-
// we accumulate ops while being in read-only state.
|
|
1643
|
-
// once user gets write permissions and we have active connection, flush all pending ops.
|
|
1644
|
-
// Note that the inner (non-proxy) delta manager is needed here to get the readonly information.
|
|
1645
|
-
assert(
|
|
1646
|
-
readonly === this.innerDeltaManager.readOnlyInfo.readonly,
|
|
1647
|
-
0x124 /* "inconsistent readonly property/event state" */,
|
|
1648
|
-
);
|
|
1649
|
-
|
|
1650
|
-
// We need to be very careful with when we (re)send pending ops, to ensure that we only send ops
|
|
1651
|
-
// when we either never send an op, or attempted to send it but we know for sure it was not
|
|
1652
|
-
// sequenced by server and will never be sequenced (i.e. was lost)
|
|
1653
|
-
// For loss of connection, we wait for our own "join" op and use it a a barrier to know all the
|
|
1654
|
-
// ops that made it from previous connection, before switching clientId and raising "connected" event
|
|
1655
|
-
// But with read-only permissions, if we transition between read-only and r/w states while on same
|
|
1656
|
-
// connection, then we have no good signal to tell us when it's safe to send ops we accumulated while
|
|
1657
|
-
// being in read-only state.
|
|
1658
|
-
// For that reason, we support getting to read-only state only when disconnected. This ensures that we
|
|
1659
|
-
// can rely on same safety mechanism and resend ops only when we establish new connection.
|
|
1660
|
-
// This is applicable for read-only permissions (event is raised before connection is properly registered),
|
|
1661
|
-
// but it's an extra requirement for Container.forceReadonly() API
|
|
1662
|
-
assert(
|
|
1663
|
-
!readonly || !this.connected,
|
|
1664
|
-
0x125 /* "Unsafe to transition to read-only state!" */,
|
|
1665
|
-
);
|
|
1666
|
-
|
|
1667
|
-
this.replayPendingStates();
|
|
1668
|
-
});
|
|
1669
|
-
|
|
1670
1694
|
// logging hardware telemetry
|
|
1671
1695
|
logger.sendTelemetryEvent({
|
|
1672
1696
|
eventName: "DeviceSpec",
|
|
@@ -1706,7 +1730,7 @@ export class ContainerRuntime
|
|
|
1706
1730
|
);
|
|
1707
1731
|
return this._summarizer;
|
|
1708
1732
|
}
|
|
1709
|
-
return
|
|
1733
|
+
return provideEntryPoint(this);
|
|
1710
1734
|
});
|
|
1711
1735
|
}
|
|
1712
1736
|
|
|
@@ -1747,14 +1771,14 @@ export class ContainerRuntime
|
|
|
1747
1771
|
/**
|
|
1748
1772
|
* Notifies this object about the request made to the container.
|
|
1749
1773
|
* @param request - Request made to the handler.
|
|
1750
|
-
* @deprecated
|
|
1774
|
+
* @deprecated Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
1751
1775
|
*/
|
|
1752
1776
|
public async request(request: IRequest): Promise<IResponse> {
|
|
1753
1777
|
try {
|
|
1754
1778
|
const parser = RequestParser.create(request);
|
|
1755
1779
|
const id = parser.pathParts[0];
|
|
1756
1780
|
|
|
1757
|
-
if (id ===
|
|
1781
|
+
if (id === summarizerRequestUrl && parser.pathParts.length === 1) {
|
|
1758
1782
|
if (this._summarizer !== undefined) {
|
|
1759
1783
|
return {
|
|
1760
1784
|
status: 200,
|
|
@@ -1765,6 +1789,7 @@ export class ContainerRuntime
|
|
|
1765
1789
|
return create404Response(request);
|
|
1766
1790
|
}
|
|
1767
1791
|
if (this.requestHandler !== undefined) {
|
|
1792
|
+
// eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
|
|
1768
1793
|
return this.requestHandler(parser, this);
|
|
1769
1794
|
}
|
|
1770
1795
|
|
|
@@ -1784,6 +1809,7 @@ export class ContainerRuntime
|
|
|
1784
1809
|
const id = requestParser.pathParts[0];
|
|
1785
1810
|
|
|
1786
1811
|
if (id === "_channels") {
|
|
1812
|
+
// eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
|
|
1787
1813
|
return this.resolveHandle(requestParser.createSubRequest(1));
|
|
1788
1814
|
}
|
|
1789
1815
|
|
|
@@ -1797,7 +1823,10 @@ export class ContainerRuntime
|
|
|
1797
1823
|
}
|
|
1798
1824
|
: create404Response(request);
|
|
1799
1825
|
} else if (requestParser.pathParts.length > 0) {
|
|
1800
|
-
|
|
1826
|
+
// Differentiate between requesting the dataStore directly, or one of its children
|
|
1827
|
+
const requestForChild = !requestParser.isLeaf(1);
|
|
1828
|
+
const dataStore = await this.getDataStoreFromRequest(id, request, requestForChild);
|
|
1829
|
+
|
|
1801
1830
|
const subRequest = requestParser.createSubRequest(1);
|
|
1802
1831
|
// We always expect createSubRequest to include a leading slash, but asserting here to protect against
|
|
1803
1832
|
// unintentionally modifying the url if that changes.
|
|
@@ -1805,6 +1834,7 @@ export class ContainerRuntime
|
|
|
1805
1834
|
subRequest.url.startsWith("/"),
|
|
1806
1835
|
0x126 /* "Expected createSubRequest url to include a leading slash" */,
|
|
1807
1836
|
);
|
|
1837
|
+
// eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
|
|
1808
1838
|
return dataStore.request(subRequest);
|
|
1809
1839
|
}
|
|
1810
1840
|
|
|
@@ -1817,16 +1847,20 @@ export class ContainerRuntime
|
|
|
1817
1847
|
/**
|
|
1818
1848
|
* {@inheritDoc @fluidframework/container-definitions#IRuntime.getEntryPoint}
|
|
1819
1849
|
*/
|
|
1820
|
-
public async getEntryPoint
|
|
1850
|
+
public async getEntryPoint(): Promise<FluidObject> {
|
|
1821
1851
|
return this.entryPoint;
|
|
1822
1852
|
}
|
|
1823
|
-
private readonly entryPoint: LazyPromise<FluidObject
|
|
1853
|
+
private readonly entryPoint: LazyPromise<FluidObject>;
|
|
1824
1854
|
|
|
1825
1855
|
private internalId(maybeAlias: string): string {
|
|
1826
1856
|
return this.dataStores.aliases.get(maybeAlias) ?? maybeAlias;
|
|
1827
1857
|
}
|
|
1828
1858
|
|
|
1829
|
-
private async getDataStoreFromRequest(
|
|
1859
|
+
private async getDataStoreFromRequest(
|
|
1860
|
+
id: string,
|
|
1861
|
+
request: IRequest,
|
|
1862
|
+
requestForChild: boolean,
|
|
1863
|
+
): Promise<IFluidDataStoreChannel> {
|
|
1830
1864
|
const headerData: RuntimeHeaderData = {};
|
|
1831
1865
|
if (typeof request.headers?.[RuntimeHeaders.wait] === "boolean") {
|
|
1832
1866
|
headerData.wait = request.headers[RuntimeHeaders.wait];
|
|
@@ -1838,6 +1872,11 @@ export class ContainerRuntime
|
|
|
1838
1872
|
headerData.allowTombstone = request.headers[AllowTombstoneRequestHeaderKey];
|
|
1839
1873
|
}
|
|
1840
1874
|
|
|
1875
|
+
// We allow Tombstone requests for sub-DataStore objects
|
|
1876
|
+
if (requestForChild) {
|
|
1877
|
+
headerData.allowTombstone = true;
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1841
1880
|
await this.dataStores.waitIfPendingAlias(id);
|
|
1842
1881
|
const internalId = this.internalId(id);
|
|
1843
1882
|
const dataStoreContext = await this.dataStores.getDataStore(internalId, headerData);
|
|
@@ -2015,28 +2054,28 @@ export class ContainerRuntime
|
|
|
2015
2054
|
* Parse an op's type and actual content from given serialized content
|
|
2016
2055
|
* ! Note: this format needs to be in-line with what is set in the "ContainerRuntime.submit(...)" method
|
|
2017
2056
|
*/
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
assert(type !== undefined, 0x6d6 /* incorrect op content format */);
|
|
2023
|
-
return
|
|
2057
|
+
// TODO: markfields: confirm Local- versus Outbound- ContainerRuntimeMessage typing
|
|
2058
|
+
private parseLocalOpContent(serializedContents?: string): LocalContainerRuntimeMessage {
|
|
2059
|
+
assert(serializedContents !== undefined, 0x6d5 /* content must be defined */);
|
|
2060
|
+
const message: LocalContainerRuntimeMessage = JSON.parse(serializedContents);
|
|
2061
|
+
assert(message.type !== undefined, 0x6d6 /* incorrect op content format */);
|
|
2062
|
+
return message;
|
|
2024
2063
|
}
|
|
2025
2064
|
|
|
2026
|
-
private async applyStashedOp(
|
|
2065
|
+
private async applyStashedOp(serializedOpContent: string): Promise<unknown> {
|
|
2027
2066
|
// Need to parse from string for back-compat
|
|
2028
|
-
const
|
|
2029
|
-
switch (type) {
|
|
2067
|
+
const opContents = this.parseLocalOpContent(serializedOpContent);
|
|
2068
|
+
switch (opContents.type) {
|
|
2030
2069
|
case ContainerMessageType.FluidDataStoreOp:
|
|
2031
|
-
return this.dataStores.applyStashedOp(contents
|
|
2070
|
+
return this.dataStores.applyStashedOp(opContents.contents);
|
|
2032
2071
|
case ContainerMessageType.Attach:
|
|
2033
|
-
return this.dataStores.applyStashedAttachOp(contents
|
|
2072
|
+
return this.dataStores.applyStashedAttachOp(opContents.contents);
|
|
2034
2073
|
case ContainerMessageType.IdAllocation:
|
|
2035
2074
|
assert(
|
|
2036
2075
|
this.idCompressor !== undefined,
|
|
2037
2076
|
0x67b /* IdCompressor should be defined if enabled */,
|
|
2038
2077
|
);
|
|
2039
|
-
return this.applyStashedIdAllocationOp(contents
|
|
2078
|
+
return this.applyStashedIdAllocationOp(opContents.contents);
|
|
2040
2079
|
case ContainerMessageType.Alias:
|
|
2041
2080
|
case ContainerMessageType.BlobAttach:
|
|
2042
2081
|
return;
|
|
@@ -2048,15 +2087,15 @@ export class ContainerRuntime
|
|
|
2048
2087
|
// This should be extremely rare for stashed ops.
|
|
2049
2088
|
// It would require a newer runtime stashing ops and then an older one applying them,
|
|
2050
2089
|
// e.g. if an app rolled back its container version
|
|
2051
|
-
const compatBehavior = compatDetails?.behavior;
|
|
2052
|
-
if (!compatBehaviorAllowsMessageType(type, compatBehavior)) {
|
|
2090
|
+
const compatBehavior = opContents.compatDetails?.behavior;
|
|
2091
|
+
if (!compatBehaviorAllowsMessageType(opContents.type, compatBehavior)) {
|
|
2053
2092
|
const error = DataProcessingError.create(
|
|
2054
2093
|
"Stashed runtime message of unknown type",
|
|
2055
2094
|
"applyStashedOp",
|
|
2056
2095
|
undefined /* sequencedMessage */,
|
|
2057
2096
|
{
|
|
2058
2097
|
messageDetails: JSON.stringify({
|
|
2059
|
-
type,
|
|
2098
|
+
type: opContents.type,
|
|
2060
2099
|
compatBehavior,
|
|
2061
2100
|
}),
|
|
2062
2101
|
},
|
|
@@ -2078,6 +2117,30 @@ export class ContainerRuntime
|
|
|
2078
2117
|
return;
|
|
2079
2118
|
}
|
|
2080
2119
|
|
|
2120
|
+
// If there are stashed blobs in the pending state, we need to delay
|
|
2121
|
+
// propagation of the "connected" event until we have uploaded them to
|
|
2122
|
+
// ensure we don't submit ops referencing a blob that has not been uploaded
|
|
2123
|
+
const connecting = connected && !this._connected;
|
|
2124
|
+
if (connecting && this.blobManager.hasPendingStashedBlobs()) {
|
|
2125
|
+
assert(
|
|
2126
|
+
!this.delayConnectClientId,
|
|
2127
|
+
0x791 /* Connect event delay must be canceled before subsequent connect event */,
|
|
2128
|
+
);
|
|
2129
|
+
assert(!!clientId, 0x792 /* Must have clientId when connecting */);
|
|
2130
|
+
this.delayConnectClientId = clientId;
|
|
2131
|
+
this.blobManager.processStashedChanges().then(
|
|
2132
|
+
() => {
|
|
2133
|
+
// make sure we didn't reconnect before the promise resolved
|
|
2134
|
+
if (this.delayConnectClientId === clientId && !this.disposed) {
|
|
2135
|
+
this.delayConnectClientId = undefined;
|
|
2136
|
+
this.setConnectionStateCore(connected, clientId);
|
|
2137
|
+
}
|
|
2138
|
+
},
|
|
2139
|
+
(error) => this.closeFn(error),
|
|
2140
|
+
);
|
|
2141
|
+
return;
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2081
2144
|
this.setConnectionStateCore(connected, clientId);
|
|
2082
2145
|
}
|
|
2083
2146
|
|
|
@@ -2156,9 +2219,25 @@ export class ContainerRuntime
|
|
|
2156
2219
|
const modernRuntimeMessage = messageArg.type === MessageType.Operation;
|
|
2157
2220
|
|
|
2158
2221
|
// Do shallow copy of message, as the processing flow will modify it.
|
|
2222
|
+
// There might be multiple container instances receiving the same message.
|
|
2223
|
+
// We do not need to make a deep copy. Each layer will just replace message.contents itself,
|
|
2224
|
+
// but will not modify the contents object (likely it will replace it on the message).
|
|
2159
2225
|
const messageCopy = { ...messageArg };
|
|
2160
2226
|
for (const message of this.remoteMessageProcessor.process(messageCopy)) {
|
|
2161
|
-
|
|
2227
|
+
if (modernRuntimeMessage) {
|
|
2228
|
+
this.processCore({
|
|
2229
|
+
// Cast it since we expect it to be this based on modernRuntimeMessage computation above.
|
|
2230
|
+
// There is nothing really ensuring that anytime original message.type is Operation that
|
|
2231
|
+
// the result messages will be so. In the end modern bool being true only directs to
|
|
2232
|
+
// throw error if ultimately unrecognized without compat details saying otherwise.
|
|
2233
|
+
message: message as InboundSequencedContainerRuntimeMessage,
|
|
2234
|
+
local,
|
|
2235
|
+
modernRuntimeMessage,
|
|
2236
|
+
});
|
|
2237
|
+
} else {
|
|
2238
|
+
// Unrecognized message will be ignored.
|
|
2239
|
+
this.processCore({ message, local, modernRuntimeMessage });
|
|
2240
|
+
}
|
|
2162
2241
|
}
|
|
2163
2242
|
}
|
|
2164
2243
|
|
|
@@ -2166,15 +2245,9 @@ export class ContainerRuntime
|
|
|
2166
2245
|
|
|
2167
2246
|
/**
|
|
2168
2247
|
* Direct the message to the correct subsystem for processing, and implement other side effects
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
*/
|
|
2173
|
-
private processCore(
|
|
2174
|
-
message: ISequencedDocumentMessage | SequencedContainerRuntimeMessage,
|
|
2175
|
-
local: boolean,
|
|
2176
|
-
modernRuntimeMessage: boolean,
|
|
2177
|
-
) {
|
|
2248
|
+
*/
|
|
2249
|
+
private processCore(messageWithContext: MessageWithContext) {
|
|
2250
|
+
const { message, local } = messageWithContext;
|
|
2178
2251
|
// Surround the actual processing of the operation with messages to the schedule manager indicating
|
|
2179
2252
|
// the beginning and end. This allows it to emit appropriate events and/or pause the processing of new
|
|
2180
2253
|
// messages once a batch has been fully processed.
|
|
@@ -2184,9 +2257,13 @@ export class ContainerRuntime
|
|
|
2184
2257
|
|
|
2185
2258
|
try {
|
|
2186
2259
|
let localOpMetadata: unknown;
|
|
2187
|
-
if (
|
|
2260
|
+
if (
|
|
2261
|
+
local &&
|
|
2262
|
+
messageWithContext.modernRuntimeMessage &&
|
|
2263
|
+
message.type !== ContainerMessageType.ChunkedOp
|
|
2264
|
+
) {
|
|
2188
2265
|
localOpMetadata = this.pendingStateManager.processPendingLocalMessage(
|
|
2189
|
-
message
|
|
2266
|
+
messageWithContext.message,
|
|
2190
2267
|
);
|
|
2191
2268
|
}
|
|
2192
2269
|
|
|
@@ -2196,14 +2273,9 @@ export class ContainerRuntime
|
|
|
2196
2273
|
this.updateDocumentDirtyState(false);
|
|
2197
2274
|
}
|
|
2198
2275
|
|
|
2199
|
-
this.validateAndProcessRuntimeMessage(
|
|
2200
|
-
message,
|
|
2201
|
-
localOpMetadata,
|
|
2202
|
-
local,
|
|
2203
|
-
modernRuntimeMessage,
|
|
2204
|
-
);
|
|
2276
|
+
this.validateAndProcessRuntimeMessage(messageWithContext, localOpMetadata);
|
|
2205
2277
|
|
|
2206
|
-
this.emit("op", message, modernRuntimeMessage);
|
|
2278
|
+
this.emit("op", message, messageWithContext.modernRuntimeMessage);
|
|
2207
2279
|
|
|
2208
2280
|
this.scheduleManager.afterOpProcessing(undefined, message);
|
|
2209
2281
|
|
|
@@ -2219,39 +2291,43 @@ export class ContainerRuntime
|
|
|
2219
2291
|
}
|
|
2220
2292
|
}
|
|
2221
2293
|
/**
|
|
2222
|
-
* Assuming the given message is also a
|
|
2294
|
+
* Assuming the given message is also a TypedContainerRuntimeMessage,
|
|
2223
2295
|
* checks its type and dispatches the message to the appropriate handler in the runtime.
|
|
2224
|
-
* Throws a DataProcessingError if the message doesn't conform to
|
|
2296
|
+
* Throws a DataProcessingError if the message looks like but doesn't conform to a known TypedContainerRuntimeMessage type.
|
|
2225
2297
|
*/
|
|
2226
2298
|
private validateAndProcessRuntimeMessage(
|
|
2227
|
-
|
|
2299
|
+
messageWithContext: MessageWithContext,
|
|
2228
2300
|
localOpMetadata: unknown,
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
const { type: maybeContainerMessageType, compatDetails } =
|
|
2234
|
-
message as ContainerRuntimeMessage;
|
|
2235
|
-
|
|
2236
|
-
switch (maybeContainerMessageType) {
|
|
2301
|
+
): void {
|
|
2302
|
+
// TODO: destructure message and modernRuntimeMessage once using typescript 5.2.2+
|
|
2303
|
+
const { local } = messageWithContext;
|
|
2304
|
+
switch (messageWithContext.message.type) {
|
|
2237
2305
|
case ContainerMessageType.Attach:
|
|
2238
|
-
this.dataStores.processAttachMessage(message, local);
|
|
2306
|
+
this.dataStores.processAttachMessage(messageWithContext.message, local);
|
|
2239
2307
|
break;
|
|
2240
2308
|
case ContainerMessageType.Alias:
|
|
2241
|
-
this.dataStores.processAliasMessage(
|
|
2309
|
+
this.dataStores.processAliasMessage(
|
|
2310
|
+
messageWithContext.message,
|
|
2311
|
+
localOpMetadata,
|
|
2312
|
+
local,
|
|
2313
|
+
);
|
|
2242
2314
|
break;
|
|
2243
2315
|
case ContainerMessageType.FluidDataStoreOp:
|
|
2244
|
-
this.dataStores.processFluidDataStoreOp(
|
|
2316
|
+
this.dataStores.processFluidDataStoreOp(
|
|
2317
|
+
messageWithContext.message,
|
|
2318
|
+
local,
|
|
2319
|
+
localOpMetadata,
|
|
2320
|
+
);
|
|
2245
2321
|
break;
|
|
2246
2322
|
case ContainerMessageType.BlobAttach:
|
|
2247
|
-
this.blobManager.processBlobAttachOp(message, local);
|
|
2323
|
+
this.blobManager.processBlobAttachOp(messageWithContext.message, local);
|
|
2248
2324
|
break;
|
|
2249
2325
|
case ContainerMessageType.IdAllocation:
|
|
2250
2326
|
assert(
|
|
2251
2327
|
this.idCompressor !== undefined,
|
|
2252
2328
|
0x67c /* IdCompressor should be defined if enabled */,
|
|
2253
2329
|
);
|
|
2254
|
-
this.idCompressor.finalizeCreationRange(message.contents
|
|
2330
|
+
this.idCompressor.finalizeCreationRange(messageWithContext.message.contents);
|
|
2255
2331
|
break;
|
|
2256
2332
|
case ContainerMessageType.ChunkedOp:
|
|
2257
2333
|
case ContainerMessageType.Rejoin:
|
|
@@ -2259,12 +2335,18 @@ export class ContainerRuntime
|
|
|
2259
2335
|
default: {
|
|
2260
2336
|
// If we didn't necessarily expect a runtime message type, then no worries - just return
|
|
2261
2337
|
// e.g. this case applies to system ops, or legacy ops that would have fallen into the above cases anyway.
|
|
2262
|
-
if (!
|
|
2338
|
+
if (!messageWithContext.modernRuntimeMessage) {
|
|
2263
2339
|
return;
|
|
2264
2340
|
}
|
|
2265
2341
|
|
|
2266
|
-
const compatBehavior = compatDetails?.behavior;
|
|
2267
|
-
if (
|
|
2342
|
+
const compatBehavior = messageWithContext.message.compatDetails?.behavior;
|
|
2343
|
+
if (
|
|
2344
|
+
!compatBehaviorAllowsMessageType(
|
|
2345
|
+
messageWithContext.message.type,
|
|
2346
|
+
compatBehavior,
|
|
2347
|
+
)
|
|
2348
|
+
) {
|
|
2349
|
+
const { message } = messageWithContext;
|
|
2268
2350
|
const error = DataProcessingError.create(
|
|
2269
2351
|
// Former assert 0x3ce
|
|
2270
2352
|
"Runtime message of unknown type",
|
|
@@ -2354,8 +2436,9 @@ export class ContainerRuntime
|
|
|
2354
2436
|
* Returns the runtime of the data store.
|
|
2355
2437
|
* @param id - Id supplied during creating the data store.
|
|
2356
2438
|
* @param wait - True if you want to wait for it.
|
|
2357
|
-
* @deprecated
|
|
2439
|
+
* @deprecated Use getAliasedDataStoreEntryPoint instead to get an aliased data store's entry point.
|
|
2358
2440
|
*/
|
|
2441
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2359
2442
|
public async getRootDataStore(id: string, wait = true): Promise<IFluidRouter> {
|
|
2360
2443
|
return this.getRootDataStoreChannel(id, wait);
|
|
2361
2444
|
}
|
|
@@ -2535,7 +2618,7 @@ export class ContainerRuntime
|
|
|
2535
2618
|
return this.dirtyContainer;
|
|
2536
2619
|
}
|
|
2537
2620
|
|
|
2538
|
-
private isContainerMessageDirtyable({ type, contents }:
|
|
2621
|
+
private isContainerMessageDirtyable({ type, contents }: OutboundContainerRuntimeMessage) {
|
|
2539
2622
|
// For legacy purposes, exclude the old built-in AgentScheduler from dirty consideration as a special-case.
|
|
2540
2623
|
// Ultimately we should have no special-cases from the ContainerRuntime's perspective.
|
|
2541
2624
|
if (type === ContainerMessageType.Attach) {
|
|
@@ -2544,7 +2627,7 @@ export class ContainerRuntime
|
|
|
2544
2627
|
return false;
|
|
2545
2628
|
}
|
|
2546
2629
|
} else if (type === ContainerMessageType.FluidDataStoreOp) {
|
|
2547
|
-
const envelope = contents
|
|
2630
|
+
const envelope = contents;
|
|
2548
2631
|
if (envelope.address === agentSchedulerId) {
|
|
2549
2632
|
return false;
|
|
2550
2633
|
}
|
|
@@ -2788,7 +2871,7 @@ export class ContainerRuntime
|
|
|
2788
2871
|
}
|
|
2789
2872
|
|
|
2790
2873
|
/**
|
|
2791
|
-
* @deprecated
|
|
2874
|
+
* @deprecated Replaced by deleteSweepReadyNodes.
|
|
2792
2875
|
*/
|
|
2793
2876
|
public deleteUnusedNodes(unusedRoutes: string[]): string[] {
|
|
2794
2877
|
throw new Error("deleteUnusedRoutes should not be called");
|
|
@@ -2937,19 +3020,15 @@ export class ContainerRuntime
|
|
|
2937
3020
|
|
|
2938
3021
|
assert(this.outbox.isEmpty, 0x3d1 /* Can't trigger summary in the middle of a batch */);
|
|
2939
3022
|
|
|
3023
|
+
// We close the summarizer and download a new snapshot and reload the container
|
|
2940
3024
|
let latestSnapshotVersionId: string | undefined;
|
|
2941
|
-
if (refreshLatestAck) {
|
|
2942
|
-
|
|
3025
|
+
if (refreshLatestAck === true) {
|
|
3026
|
+
return this.prefetchLatestSummaryThenClose(
|
|
2943
3027
|
createChildLogger({
|
|
2944
3028
|
logger: summaryNumberLogger,
|
|
2945
3029
|
properties: { all: { safeSummary: true } },
|
|
2946
3030
|
}),
|
|
2947
3031
|
);
|
|
2948
|
-
const latestSnapshotRefSeq = latestSnapshotInfo.latestSnapshotRefSeq;
|
|
2949
|
-
latestSnapshotVersionId = latestSnapshotInfo.latestSnapshotVersionId;
|
|
2950
|
-
|
|
2951
|
-
// We might need to catch up to the latest summary's reference sequence number before pausing.
|
|
2952
|
-
await this.waitForDeltaManagerToCatchup(latestSnapshotRefSeq, summaryNumberLogger);
|
|
2953
3032
|
}
|
|
2954
3033
|
|
|
2955
3034
|
// If there are pending (unacked ops), the summary will not be eventual consistent and it may even be
|
|
@@ -3397,7 +3476,7 @@ export class ContainerRuntime
|
|
|
3397
3476
|
}
|
|
3398
3477
|
|
|
3399
3478
|
if (idRange !== undefined) {
|
|
3400
|
-
const idAllocationMessage:
|
|
3479
|
+
const idAllocationMessage: ContainerRuntimeIdAllocationMessage = {
|
|
3401
3480
|
type: ContainerMessageType.IdAllocation,
|
|
3402
3481
|
contents: idRange,
|
|
3403
3482
|
};
|
|
@@ -3417,7 +3496,7 @@ export class ContainerRuntime
|
|
|
3417
3496
|
}
|
|
3418
3497
|
|
|
3419
3498
|
private submit(
|
|
3420
|
-
containerRuntimeMessage:
|
|
3499
|
+
containerRuntimeMessage: OutboundContainerRuntimeMessage,
|
|
3421
3500
|
localOpMetadata: unknown = undefined,
|
|
3422
3501
|
metadata: Record<string, unknown> | undefined = undefined,
|
|
3423
3502
|
): void {
|
|
@@ -3613,39 +3692,36 @@ export class ContainerRuntime
|
|
|
3613
3692
|
|
|
3614
3693
|
private reSubmit(message: IPendingBatchMessage) {
|
|
3615
3694
|
// Need to parse from string for back-compat
|
|
3616
|
-
const containerRuntimeMessage = this.
|
|
3695
|
+
const containerRuntimeMessage = this.parseLocalOpContent(message.content);
|
|
3617
3696
|
this.reSubmitCore(containerRuntimeMessage, message.localOpMetadata, message.opMetadata);
|
|
3618
3697
|
}
|
|
3619
3698
|
|
|
3620
3699
|
/**
|
|
3621
3700
|
* Finds the right store and asks it to resubmit the message. This typically happens when we
|
|
3622
3701
|
* reconnect and there are pending messages.
|
|
3623
|
-
* @param message - The original
|
|
3702
|
+
* @param message - The original LocalContainerRuntimeMessage.
|
|
3624
3703
|
* @param localOpMetadata - The local metadata associated with the original message.
|
|
3625
3704
|
*/
|
|
3626
3705
|
private reSubmitCore(
|
|
3627
|
-
message:
|
|
3706
|
+
message: LocalContainerRuntimeMessage,
|
|
3628
3707
|
localOpMetadata: unknown,
|
|
3629
3708
|
opMetadata: Record<string, unknown> | undefined,
|
|
3630
3709
|
) {
|
|
3631
|
-
const contents = message.contents;
|
|
3632
3710
|
switch (message.type) {
|
|
3633
3711
|
case ContainerMessageType.FluidDataStoreOp:
|
|
3634
3712
|
// For Operations, call resubmitDataStoreOp which will find the right store
|
|
3635
3713
|
// and trigger resubmission on it.
|
|
3636
|
-
this.dataStores.resubmitDataStoreOp(contents, localOpMetadata);
|
|
3714
|
+
this.dataStores.resubmitDataStoreOp(message.contents, localOpMetadata);
|
|
3637
3715
|
break;
|
|
3638
3716
|
case ContainerMessageType.Attach:
|
|
3639
3717
|
case ContainerMessageType.Alias:
|
|
3640
3718
|
this.submit(message, localOpMetadata);
|
|
3641
3719
|
break;
|
|
3642
|
-
case ContainerMessageType.IdAllocation:
|
|
3643
|
-
|
|
3644
|
-
if (contents.stashedState !== undefined) {
|
|
3645
|
-
delete contents.stashedState;
|
|
3646
|
-
}
|
|
3720
|
+
case ContainerMessageType.IdAllocation: {
|
|
3721
|
+
prepareLocalContainerRuntimeIdAllocationMessageForTransit(message);
|
|
3647
3722
|
this.submit(message, localOpMetadata);
|
|
3648
3723
|
break;
|
|
3724
|
+
}
|
|
3649
3725
|
case ContainerMessageType.ChunkedOp:
|
|
3650
3726
|
throw new Error(`chunkedOp not expected here`);
|
|
3651
3727
|
case ContainerMessageType.BlobAttach:
|
|
@@ -3684,12 +3760,12 @@ export class ContainerRuntime
|
|
|
3684
3760
|
|
|
3685
3761
|
private rollback(content: string | undefined, localOpMetadata: unknown) {
|
|
3686
3762
|
// Need to parse from string for back-compat
|
|
3687
|
-
const { type, contents } = this.
|
|
3763
|
+
const { type, contents } = this.parseLocalOpContent(content);
|
|
3688
3764
|
switch (type) {
|
|
3689
3765
|
case ContainerMessageType.FluidDataStoreOp:
|
|
3690
3766
|
// For operations, call rollbackDataStoreOp which will find the right store
|
|
3691
3767
|
// and trigger rollback on it.
|
|
3692
|
-
this.dataStores.rollbackDataStoreOp(contents
|
|
3768
|
+
this.dataStores.rollbackDataStoreOp(contents, localOpMetadata);
|
|
3693
3769
|
break;
|
|
3694
3770
|
default:
|
|
3695
3771
|
// Don't check message.compatDetails because this is for rolling back a local op so the type will be known
|
|
@@ -3697,26 +3773,6 @@ export class ContainerRuntime
|
|
|
3697
3773
|
}
|
|
3698
3774
|
}
|
|
3699
3775
|
|
|
3700
|
-
private async waitForDeltaManagerToCatchup(
|
|
3701
|
-
latestSnapshotRefSeq: number,
|
|
3702
|
-
summaryLogger: ITelemetryLoggerExt,
|
|
3703
|
-
): Promise<void> {
|
|
3704
|
-
if (latestSnapshotRefSeq > this.deltaManager.lastSequenceNumber) {
|
|
3705
|
-
// We need to catch up to the latest summary's reference sequence number before proceeding.
|
|
3706
|
-
await PerformanceEvent.timedExecAsync(
|
|
3707
|
-
summaryLogger,
|
|
3708
|
-
{
|
|
3709
|
-
eventName: "WaitingForSeq",
|
|
3710
|
-
lastSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
3711
|
-
targetSequenceNumber: latestSnapshotRefSeq,
|
|
3712
|
-
lastKnownSeqNumber: this.deltaManager.lastKnownSeqNumber,
|
|
3713
|
-
},
|
|
3714
|
-
async () => waitForSeq(this.deltaManager, latestSnapshotRefSeq),
|
|
3715
|
-
{ start: true, end: true, cancel: "error" }, // definitely want start event
|
|
3716
|
-
);
|
|
3717
|
-
}
|
|
3718
|
-
}
|
|
3719
|
-
|
|
3720
3776
|
/** Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck */
|
|
3721
3777
|
public async refreshLatestSummaryAck(options: IRefreshSummaryAckOptions) {
|
|
3722
3778
|
const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options;
|
|
@@ -3735,7 +3791,7 @@ export class ContainerRuntime
|
|
|
3735
3791
|
* and then close as the current main client is likely to be re-elected as the parent summarizer again.
|
|
3736
3792
|
*/
|
|
3737
3793
|
if (!result.isSummaryTracked && result.isSummaryNewer) {
|
|
3738
|
-
const fetchResult = await this.
|
|
3794
|
+
const fetchResult = await this.fetchLatestSnapshotFromStorage(
|
|
3739
3795
|
summaryLogger,
|
|
3740
3796
|
{
|
|
3741
3797
|
eventName: "RefreshLatestSummaryAckFetch",
|
|
@@ -3743,7 +3799,6 @@ export class ContainerRuntime
|
|
|
3743
3799
|
targetSequenceNumber: summaryRefSeq,
|
|
3744
3800
|
},
|
|
3745
3801
|
readAndParseBlob,
|
|
3746
|
-
null,
|
|
3747
3802
|
);
|
|
3748
3803
|
|
|
3749
3804
|
/**
|
|
@@ -3780,40 +3835,37 @@ export class ContainerRuntime
|
|
|
3780
3835
|
}
|
|
3781
3836
|
|
|
3782
3837
|
/**
|
|
3783
|
-
* Fetches the latest snapshot from storage
|
|
3784
|
-
*
|
|
3838
|
+
* Fetches the latest snapshot from storage to refresh the cache as a performance optimization and closes the
|
|
3839
|
+
* summarizer to reload from new state.
|
|
3785
3840
|
* @param summaryLogger - logger to use when fetching snapshot from storage
|
|
3786
|
-
* @returns
|
|
3841
|
+
* @returns a generic summarization error
|
|
3787
3842
|
*/
|
|
3788
|
-
private async
|
|
3843
|
+
private async prefetchLatestSummaryThenClose(
|
|
3789
3844
|
summaryLogger: ITelemetryLoggerExt,
|
|
3790
|
-
): Promise<
|
|
3845
|
+
): Promise<IBaseSummarizeResult> {
|
|
3791
3846
|
const readAndParseBlob = async <T>(id: string) => readAndParse<T>(this.storage, id);
|
|
3792
|
-
|
|
3847
|
+
|
|
3848
|
+
// This is a performance optimization as the same parent is likely to be elected again, and would use its
|
|
3849
|
+
// cache to fetch the snapshot instead of the network.
|
|
3850
|
+
await this.fetchLatestSnapshotFromStorage(
|
|
3793
3851
|
summaryLogger,
|
|
3794
3852
|
{
|
|
3795
3853
|
eventName: "RefreshLatestSummaryFromServerFetch",
|
|
3796
3854
|
},
|
|
3797
3855
|
readAndParseBlob,
|
|
3798
|
-
null,
|
|
3799
3856
|
);
|
|
3800
3857
|
|
|
3801
3858
|
await this.closeStaleSummarizer("RefreshLatestSummaryFromServerFetch");
|
|
3802
3859
|
|
|
3803
|
-
return {
|
|
3860
|
+
return {
|
|
3861
|
+
stage: "base",
|
|
3862
|
+
error: "summary state stale - Unsupported option 'refreshLatestAck'",
|
|
3863
|
+
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
3864
|
+
minimumSequenceNumber: this.deltaManager.minimumSequenceNumber,
|
|
3865
|
+
};
|
|
3804
3866
|
}
|
|
3805
3867
|
|
|
3806
3868
|
private async closeStaleSummarizer(codePath: string): Promise<void> {
|
|
3807
|
-
this.mc.logger.sendTelemetryEvent(
|
|
3808
|
-
{
|
|
3809
|
-
eventName: "ClosingSummarizerOnSummaryStale",
|
|
3810
|
-
codePath,
|
|
3811
|
-
message: "Stopping fetch from storage",
|
|
3812
|
-
closeSummarizerDelayMs: this.closeSummarizerDelayMs,
|
|
3813
|
-
},
|
|
3814
|
-
new GenericError("Restarting summarizer instead of refreshing"),
|
|
3815
|
-
);
|
|
3816
|
-
|
|
3817
3869
|
// Delay before restarting summarizer to prevent the summarizer from restarting too frequently.
|
|
3818
3870
|
await delay(this.closeSummarizerDelayMs);
|
|
3819
3871
|
this._summarizer?.stop("latestSummaryStateStale");
|
|
@@ -3821,15 +3873,14 @@ export class ContainerRuntime
|
|
|
3821
3873
|
}
|
|
3822
3874
|
|
|
3823
3875
|
/**
|
|
3824
|
-
* Downloads
|
|
3876
|
+
* Downloads the latest snapshot from storage.
|
|
3825
3877
|
* By default, it also closes the container after downloading the snapshot. However, this may be
|
|
3826
3878
|
* overridden via options.
|
|
3827
3879
|
*/
|
|
3828
|
-
private async
|
|
3880
|
+
private async fetchLatestSnapshotFromStorage(
|
|
3829
3881
|
logger: ITelemetryLoggerExt,
|
|
3830
3882
|
event: ITelemetryGenericEvent,
|
|
3831
3883
|
readAndParseBlob: ReadAndParseBlob,
|
|
3832
|
-
versionId: string | null,
|
|
3833
3884
|
): Promise<{ snapshotTree: ISnapshotTree; versionId: string; latestSnapshotRefSeq: number }> {
|
|
3834
3885
|
return PerformanceEvent.timedExecAsync(
|
|
3835
3886
|
logger,
|
|
@@ -3851,10 +3902,10 @@ export class ContainerRuntime
|
|
|
3851
3902
|
const trace = Trace.start();
|
|
3852
3903
|
|
|
3853
3904
|
const versions = await this.storage.getVersions(
|
|
3854
|
-
|
|
3905
|
+
null,
|
|
3855
3906
|
1,
|
|
3856
|
-
"
|
|
3857
|
-
|
|
3907
|
+
"prefetchLatestSummaryBeforeClose",
|
|
3908
|
+
FetchSource.noCache,
|
|
3858
3909
|
);
|
|
3859
3910
|
assert(
|
|
3860
3911
|
!!versions && !!versions[0],
|
|
@@ -3896,17 +3947,17 @@ export class ContainerRuntime
|
|
|
3896
3947
|
if (this._orderSequentiallyCalls !== 0) {
|
|
3897
3948
|
throw new UsageError("can't get state during orderSequentially");
|
|
3898
3949
|
}
|
|
3899
|
-
const pendingAttachmentBlobs = await this.blobManager.getPendingBlobs(
|
|
3900
|
-
waitBlobsToAttach,
|
|
3901
|
-
);
|
|
3902
|
-
const pending = this.pendingStateManager.getLocalState();
|
|
3903
|
-
if (!pendingAttachmentBlobs && !this.hasPendingMessages()) {
|
|
3904
|
-
return; // no pending state to save
|
|
3905
|
-
}
|
|
3906
3950
|
// Flush pending batch.
|
|
3907
3951
|
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
3908
3952
|
// to close current batch.
|
|
3909
3953
|
this.flush();
|
|
3954
|
+
const pendingAttachmentBlobs = waitBlobsToAttach
|
|
3955
|
+
? await this.blobManager.attachAndGetPendingBlobs()
|
|
3956
|
+
: undefined;
|
|
3957
|
+
const pending = this.pendingStateManager.getLocalState();
|
|
3958
|
+
if (!pendingAttachmentBlobs && !this.hasPendingMessages()) {
|
|
3959
|
+
return; // no pending state to save
|
|
3960
|
+
}
|
|
3910
3961
|
|
|
3911
3962
|
const pendingState: IPendingRuntimeState = {
|
|
3912
3963
|
pending,
|
|
@@ -3948,35 +3999,11 @@ export class ContainerRuntime
|
|
|
3948
3999
|
}
|
|
3949
4000
|
|
|
3950
4001
|
/**
|
|
3951
|
-
*
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
private formRequestSummarizerFn(loaderRouter: IFluidRouter) {
|
|
4002
|
+
* Forms a function that will create and retrieve a Summarizer.
|
|
4003
|
+
*/
|
|
4004
|
+
private formCreateSummarizerFn(loader: ILoader) {
|
|
3955
4005
|
return async () => {
|
|
3956
|
-
|
|
3957
|
-
headers: {
|
|
3958
|
-
[LoaderHeader.cache]: false,
|
|
3959
|
-
[LoaderHeader.clientDetails]: {
|
|
3960
|
-
capabilities: { interactive: false },
|
|
3961
|
-
type: summarizerClientType,
|
|
3962
|
-
},
|
|
3963
|
-
[DriverHeader.summarizingClient]: true,
|
|
3964
|
-
[LoaderHeader.reconnect]: false,
|
|
3965
|
-
},
|
|
3966
|
-
url: "/_summarizer",
|
|
3967
|
-
};
|
|
3968
|
-
|
|
3969
|
-
const fluidObject = await requestFluidObject<FluidObject<ISummarizer>>(
|
|
3970
|
-
loaderRouter,
|
|
3971
|
-
request,
|
|
3972
|
-
);
|
|
3973
|
-
const summarizer = fluidObject.ISummarizer;
|
|
3974
|
-
|
|
3975
|
-
if (!summarizer) {
|
|
3976
|
-
throw new UsageError("Fluid object does not implement ISummarizer");
|
|
3977
|
-
}
|
|
3978
|
-
|
|
3979
|
-
return summarizer;
|
|
4006
|
+
return createSummarizer(loader, `/${summarizerRequestUrl}`);
|
|
3980
4007
|
};
|
|
3981
4008
|
}
|
|
3982
4009
|
|
|
@@ -4003,30 +4030,3 @@ export class ContainerRuntime
|
|
|
4003
4030
|
return killSwitch !== true && this.runtimeOptions.enableGroupedBatching;
|
|
4004
4031
|
}
|
|
4005
4032
|
}
|
|
4006
|
-
|
|
4007
|
-
/**
|
|
4008
|
-
* Wait for a specific sequence number. Promise should resolve when we reach that number,
|
|
4009
|
-
* or reject if closed.
|
|
4010
|
-
*/
|
|
4011
|
-
const waitForSeq = async (
|
|
4012
|
-
deltaManager: IDeltaManager<Pick<ISequencedDocumentMessage, "sequenceNumber">, unknown>,
|
|
4013
|
-
targetSeq: number,
|
|
4014
|
-
): Promise<void> =>
|
|
4015
|
-
new Promise<void>((resolve, reject) => {
|
|
4016
|
-
// TODO: remove cast to any when actual event is determined
|
|
4017
|
-
deltaManager.on("closed" as any, reject);
|
|
4018
|
-
deltaManager.on("disposed" as any, reject);
|
|
4019
|
-
|
|
4020
|
-
// If we already reached target sequence number, simply resolve the promise.
|
|
4021
|
-
if (deltaManager.lastSequenceNumber >= targetSeq) {
|
|
4022
|
-
resolve();
|
|
4023
|
-
} else {
|
|
4024
|
-
const handleOp = (message: Pick<ISequencedDocumentMessage, "sequenceNumber">) => {
|
|
4025
|
-
if (message.sequenceNumber >= targetSeq) {
|
|
4026
|
-
resolve();
|
|
4027
|
-
deltaManager.off("op", handleOp);
|
|
4028
|
-
}
|
|
4029
|
-
};
|
|
4030
|
-
deltaManager.on("op", handleOp);
|
|
4031
|
-
}
|
|
4032
|
-
});
|