@fluidframework/container-runtime 2.0.0-dev-rc.1.0.0.232845 → 2.0.0-dev-rc.2.0.0.245554
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +5 -5
- package/{.mocharc.js → .mocharc.cjs} +1 -1
- package/CHANGELOG.md +54 -0
- package/README.md +45 -0
- package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
- package/api-extractor-lint.json +1 -1
- package/api-extractor.json +1 -1
- package/api-report/container-runtime.api.md +425 -33
- package/dist/batchTracker.d.ts +1 -2
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +0 -5
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +0 -12
- package/dist/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +225 -0
- package/dist/channelCollection.d.ts.map +1 -0
- package/dist/{dataStores.js → channelCollection.js} +447 -147
- package/dist/channelCollection.js.map +1 -0
- package/dist/connectionTelemetry.d.ts +11 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +42 -4
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/container-runtime-alpha.d.ts +129 -48
- package/dist/container-runtime-beta.d.ts +68 -9
- package/dist/container-runtime-public.d.ts +68 -9
- package/dist/container-runtime-untrimmed.d.ts +692 -49
- package/dist/containerHandleContext.d.ts +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +81 -64
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +503 -368
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +2 -3
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +12 -11
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +118 -41
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +248 -159
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts +2 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +1 -0
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts +29 -4
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js +91 -5
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +12 -6
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +116 -78
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +2 -2
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +30 -23
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +22 -13
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +7 -4
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +2 -2
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +12 -5
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +18 -6
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +6 -7
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +20 -18
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.d.ts +1 -1
- package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +10 -10
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +8 -8
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +40 -39
- package/dist/gc/index.js.map +1 -1
- package/dist/index.d.ts +11 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -42
- package/dist/index.js.map +1 -1
- package/dist/messageTypes.d.ts +3 -3
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +2 -2
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +2 -2
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +8 -8
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +18 -18
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +4 -4
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +3 -3
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +1 -10
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +5 -5
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +7 -7
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +20 -12
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +4 -4
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +2 -2
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/package.json +3 -0
- 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 -1
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +18 -10
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts +1 -2
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +5 -5
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/index.d.ts +12 -12
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js +43 -43
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.js +8 -8
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +5 -4
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +47 -32
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +4 -4
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +6 -6
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +2 -2
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.d.ts +3 -3
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/index.d.ts +3 -3
- package/dist/summary/summarizerNode/index.d.ts.map +1 -1
- package/dist/summary/summarizerNode/index.js +4 -4
- package/dist/summary/summarizerNode/index.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +16 -5
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +40 -10
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +9 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -4
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +12 -12
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +9 -20
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +15 -2
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +6 -5
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +10 -1
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +5 -6
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +4 -5
- package/dist/summary/summaryManager.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/{batchTracker.d.mts → batchTracker.d.ts} +2 -3
- package/lib/batchTracker.d.ts.map +1 -0
- package/lib/{batchTracker.mjs → batchTracker.js} +1 -1
- package/lib/batchTracker.js.map +1 -0
- package/lib/{blobManager.d.mts → blobManager.d.ts} +1 -6
- package/lib/blobManager.d.ts.map +1 -0
- package/lib/{blobManager.mjs → blobManager.js} +1 -13
- package/lib/blobManager.js.map +1 -0
- package/lib/channelCollection.d.ts +225 -0
- package/lib/channelCollection.d.ts.map +1 -0
- package/lib/{dataStores.mjs → channelCollection.js} +434 -137
- package/lib/channelCollection.js.map +1 -0
- package/lib/{connectionTelemetry.d.mts → connectionTelemetry.d.ts} +12 -2
- package/lib/connectionTelemetry.d.ts.map +1 -0
- package/lib/{connectionTelemetry.mjs → connectionTelemetry.js} +43 -5
- package/lib/connectionTelemetry.js.map +1 -0
- package/lib/{container-runtime-alpha.d.mts → container-runtime-alpha.d.ts} +129 -48
- package/lib/{container-runtime-beta.d.mts → container-runtime-beta.d.ts} +68 -9
- package/lib/{container-runtime-public.d.mts → container-runtime-public.d.ts} +68 -9
- package/lib/{container-runtime-untrimmed.d.mts → container-runtime-untrimmed.d.ts} +692 -49
- package/lib/{containerHandleContext.d.mts → containerHandleContext.d.ts} +2 -2
- package/lib/containerHandleContext.d.ts.map +1 -0
- package/lib/{containerHandleContext.mjs → containerHandleContext.js} +1 -1
- package/lib/containerHandleContext.js.map +1 -0
- package/lib/{containerRuntime.d.mts → containerRuntime.d.ts} +86 -65
- package/lib/containerRuntime.d.ts.map +1 -0
- package/lib/{containerRuntime.mjs → containerRuntime.js} +423 -290
- package/lib/containerRuntime.js.map +1 -0
- package/lib/{dataStore.d.mts → dataStore.d.ts} +3 -4
- package/lib/dataStore.d.ts.map +1 -0
- package/lib/{dataStore.mjs → dataStore.js} +13 -12
- package/lib/dataStore.js.map +1 -0
- package/lib/{dataStoreContext.d.mts → dataStoreContext.d.ts} +119 -42
- package/lib/dataStoreContext.d.ts.map +1 -0
- package/lib/{dataStoreContext.mjs → dataStoreContext.js} +240 -151
- package/lib/dataStoreContext.js.map +1 -0
- package/lib/{dataStoreContexts.d.mts → dataStoreContexts.d.ts} +3 -2
- package/lib/dataStoreContexts.d.ts.map +1 -0
- package/lib/{dataStoreContexts.mjs → dataStoreContexts.js} +2 -1
- package/lib/dataStoreContexts.js.map +1 -0
- package/lib/{dataStoreRegistry.d.mts → dataStoreRegistry.d.ts} +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -0
- package/lib/{dataStoreRegistry.mjs → dataStoreRegistry.js} +5 -1
- package/lib/dataStoreRegistry.js.map +1 -0
- package/{dist/deltaManagerProxyBase.d.ts → lib/deltaManagerSummarizerProxy.d.ts} +16 -7
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -0
- package/lib/deltaManagerSummarizerProxy.js +124 -0
- package/lib/deltaManagerSummarizerProxy.js.map +1 -0
- package/lib/{deltaScheduler.d.mts → deltaScheduler.d.ts} +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -0
- package/lib/{deltaScheduler.mjs → deltaScheduler.js} +1 -1
- package/lib/deltaScheduler.js.map +1 -0
- package/lib/{error.d.mts → error.d.ts} +1 -1
- package/lib/error.d.ts.map +1 -0
- package/lib/{error.mjs → error.js} +1 -1
- package/lib/error.js.map +1 -0
- package/lib/gc/{garbageCollection.d.mts → garbageCollection.d.ts} +13 -7
- package/lib/gc/garbageCollection.d.ts.map +1 -0
- package/lib/gc/{garbageCollection.mjs → garbageCollection.js} +79 -41
- package/lib/gc/garbageCollection.js.map +1 -0
- package/lib/gc/{gcConfigs.d.mts → gcConfigs.d.ts} +3 -3
- package/lib/gc/gcConfigs.d.ts.map +1 -0
- package/lib/gc/{gcConfigs.mjs → gcConfigs.js} +14 -7
- package/lib/gc/gcConfigs.js.map +1 -0
- package/lib/gc/{gcDefinitions.d.mts → gcDefinitions.d.ts} +23 -14
- package/lib/gc/gcDefinitions.d.ts.map +1 -0
- package/lib/gc/{gcDefinitions.mjs → gcDefinitions.js} +7 -4
- package/lib/gc/gcDefinitions.js.map +1 -0
- package/lib/gc/{gcHelpers.d.mts → gcHelpers.d.ts} +3 -3
- package/lib/gc/{gcHelpers.d.mts.map → gcHelpers.d.ts.map} +1 -1
- package/lib/gc/{gcHelpers.mjs → gcHelpers.js} +1 -1
- package/lib/gc/gcHelpers.js.map +1 -0
- package/lib/gc/{gcReferenceGraphAlgorithm.d.mts → gcReferenceGraphAlgorithm.d.ts} +2 -2
- package/lib/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -0
- package/lib/gc/{gcReferenceGraphAlgorithm.mjs → gcReferenceGraphAlgorithm.js} +1 -1
- package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -0
- package/lib/gc/{gcSummaryDefinitions.d.mts → gcSummaryDefinitions.d.ts} +1 -1
- package/lib/gc/gcSummaryDefinitions.d.ts.map +1 -0
- package/lib/gc/{gcSummaryDefinitions.mjs → gcSummaryDefinitions.js} +1 -1
- package/lib/gc/gcSummaryDefinitions.js.map +1 -0
- package/lib/gc/{gcSummaryStateTracker.d.mts → gcSummaryStateTracker.d.ts} +13 -6
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -0
- package/lib/gc/{gcSummaryStateTracker.mjs → gcSummaryStateTracker.js} +17 -5
- package/lib/gc/gcSummaryStateTracker.js.map +1 -0
- package/lib/gc/{gcTelemetry.d.mts → gcTelemetry.d.ts} +7 -8
- package/lib/gc/gcTelemetry.d.ts.map +1 -0
- package/lib/gc/{gcTelemetry.mjs → gcTelemetry.js} +5 -3
- package/lib/gc/gcTelemetry.js.map +1 -0
- package/lib/gc/{gcUnreferencedStateTracker.d.mts → gcUnreferencedStateTracker.d.ts} +2 -2
- package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
- package/lib/gc/{gcUnreferencedStateTracker.mjs → gcUnreferencedStateTracker.js} +2 -2
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -0
- package/lib/gc/index.d.ts +13 -0
- package/lib/gc/index.d.ts.map +1 -0
- package/lib/gc/{index.mjs → index.js} +8 -8
- package/lib/gc/index.js.map +1 -0
- package/lib/{index.d.mts → index.d.ts} +12 -22
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +15 -0
- package/lib/index.js.map +1 -0
- package/lib/{messageTypes.d.mts → messageTypes.d.ts} +4 -4
- package/lib/messageTypes.d.ts.map +1 -0
- package/lib/{messageTypes.mjs → messageTypes.js} +1 -1
- package/lib/messageTypes.js.map +1 -0
- package/lib/{metadata.d.mts → metadata.d.ts} +1 -1
- package/lib/metadata.d.ts.map +1 -0
- package/lib/{metadata.mjs → metadata.js} +1 -1
- package/lib/metadata.js.map +1 -0
- package/lib/opLifecycle/{batchManager.d.mts → batchManager.d.ts} +3 -3
- package/lib/opLifecycle/batchManager.d.ts.map +1 -0
- package/lib/opLifecycle/{batchManager.mjs → batchManager.js} +1 -1
- package/lib/opLifecycle/batchManager.js.map +1 -0
- package/lib/opLifecycle/{definitions.d.mts → definitions.d.ts} +3 -3
- package/lib/opLifecycle/definitions.d.ts.map +1 -0
- package/lib/opLifecycle/{definitions.mjs → definitions.js} +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -0
- package/lib/opLifecycle/index.d.ts +13 -0
- package/lib/opLifecycle/index.d.ts.map +1 -0
- package/lib/opLifecycle/index.js +12 -0
- package/lib/opLifecycle/index.js.map +1 -0
- package/lib/opLifecycle/{opCompressor.d.mts → opCompressor.d.ts} +2 -2
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -0
- package/lib/opLifecycle/{opCompressor.mjs → opCompressor.js} +3 -3
- package/lib/opLifecycle/opCompressor.js.map +1 -0
- package/lib/opLifecycle/{opDecompressor.d.mts → opDecompressor.d.ts} +2 -2
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -0
- package/lib/opLifecycle/{opDecompressor.mjs → opDecompressor.js} +2 -2
- package/lib/opLifecycle/opDecompressor.js.map +1 -0
- package/lib/opLifecycle/{opGroupingManager.d.mts → opGroupingManager.d.ts} +2 -2
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -0
- package/lib/opLifecycle/{opGroupingManager.mjs → opGroupingManager.js} +2 -11
- package/lib/opLifecycle/opGroupingManager.js.map +1 -0
- package/lib/opLifecycle/{opSplitter.d.mts → opSplitter.d.ts} +2 -2
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -0
- package/lib/opLifecycle/{opSplitter.mjs → opSplitter.js} +3 -3
- package/lib/opLifecycle/opSplitter.js.map +1 -0
- package/lib/opLifecycle/{outbox.d.mts → outbox.d.ts} +8 -8
- package/lib/opLifecycle/outbox.d.ts.map +1 -0
- package/lib/opLifecycle/{outbox.mjs → outbox.js} +12 -4
- package/lib/opLifecycle/outbox.js.map +1 -0
- package/lib/opLifecycle/{remoteMessageProcessor.d.mts → remoteMessageProcessor.d.ts} +5 -5
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -0
- package/lib/opLifecycle/{remoteMessageProcessor.mjs → remoteMessageProcessor.js} +2 -2
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -0
- package/lib/{opProperties.d.mts → opProperties.d.ts} +1 -1
- package/lib/opProperties.d.ts.map +1 -0
- package/lib/{opProperties.mjs → opProperties.js} +1 -1
- package/lib/opProperties.js.map +1 -0
- package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
- package/lib/packageVersion.d.ts.map +1 -0
- package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
- package/lib/packageVersion.js.map +1 -0
- package/lib/{pendingStateManager.d.mts → pendingStateManager.d.ts} +3 -2
- package/lib/pendingStateManager.d.ts.map +1 -0
- package/lib/{pendingStateManager.mjs → pendingStateManager.js} +18 -10
- package/lib/pendingStateManager.js.map +1 -0
- package/lib/{scheduleManager.d.mts → scheduleManager.d.ts} +6 -3
- package/lib/scheduleManager.d.ts.map +1 -0
- package/lib/{scheduleManager.mjs → scheduleManager.js} +3 -3
- package/lib/scheduleManager.js.map +1 -0
- package/lib/{storageServiceWithAttachBlobs.d.mts → storageServiceWithAttachBlobs.d.ts} +1 -1
- package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -0
- package/lib/{storageServiceWithAttachBlobs.mjs → storageServiceWithAttachBlobs.js} +1 -1
- package/lib/storageServiceWithAttachBlobs.js.map +1 -0
- package/lib/summary/{index.d.mts → index.d.ts} +13 -13
- package/lib/summary/index.d.ts.map +1 -0
- package/lib/summary/{index.mjs → index.js} +12 -12
- package/lib/summary/index.js.map +1 -0
- package/lib/summary/{orderedClientElection.d.mts → orderedClientElection.d.ts} +5 -1
- package/lib/summary/orderedClientElection.d.ts.map +1 -0
- package/lib/summary/{orderedClientElection.mjs → orderedClientElection.js} +2 -2
- package/lib/summary/orderedClientElection.js.map +1 -0
- package/lib/summary/{runWhileConnectedCoordinator.d.mts → runWhileConnectedCoordinator.d.ts} +2 -2
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/lib/summary/{runWhileConnectedCoordinator.mjs → runWhileConnectedCoordinator.js} +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -0
- package/lib/summary/{runningSummarizer.d.mts → runningSummarizer.d.ts} +6 -5
- package/lib/summary/runningSummarizer.d.ts.map +1 -0
- package/lib/summary/{runningSummarizer.mjs → runningSummarizer.js} +41 -26
- package/lib/summary/runningSummarizer.js.map +1 -0
- package/lib/summary/{summarizer.d.mts → summarizer.d.ts} +5 -5
- package/lib/summary/summarizer.d.ts.map +1 -0
- package/lib/summary/{summarizer.mjs → summarizer.js} +4 -4
- package/lib/summary/summarizer.js.map +1 -0
- package/lib/summary/{summarizerClientElection.d.mts → summarizerClientElection.d.ts} +3 -3
- package/lib/summary/summarizerClientElection.d.ts.map +1 -0
- package/lib/summary/{summarizerClientElection.mjs → summarizerClientElection.js} +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -0
- package/lib/summary/{summarizerHeuristics.d.mts → summarizerHeuristics.d.ts} +4 -4
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
- package/lib/summary/{summarizerHeuristics.mjs → summarizerHeuristics.js} +1 -1
- package/lib/summary/summarizerHeuristics.js.map +1 -0
- package/lib/summary/summarizerNode/{index.d.mts → index.d.ts} +4 -4
- package/lib/summary/summarizerNode/index.d.ts.map +1 -0
- package/lib/summary/summarizerNode/index.js +7 -0
- package/lib/summary/summarizerNode/index.js.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNode.d.mts → summarizerNode.d.ts} +17 -6
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNode.mjs → summarizerNode.js} +34 -4
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeUtils.d.mts → summarizerNodeUtils.d.ts} +10 -2
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeUtils.mjs → summarizerNodeUtils.js} +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeWithGc.d.mts → summarizerNodeWithGc.d.ts} +4 -5
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeWithGc.mjs → summarizerNodeWithGc.js} +7 -7
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -0
- package/lib/summary/{summarizerTypes.d.mts → summarizerTypes.d.ts} +10 -21
- package/lib/summary/summarizerTypes.d.ts.map +1 -0
- package/lib/summary/{summarizerTypes.mjs → summarizerTypes.js} +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -0
- package/lib/summary/{summaryCollection.d.mts → summaryCollection.d.ts} +1 -1
- package/lib/summary/summaryCollection.d.ts.map +1 -0
- package/lib/summary/{summaryCollection.mjs → summaryCollection.js} +1 -1
- package/lib/summary/summaryCollection.js.map +1 -0
- package/lib/summary/{summaryFormat.d.mts → summaryFormat.d.ts} +16 -3
- package/lib/summary/summaryFormat.d.ts.map +1 -0
- package/lib/summary/{summaryFormat.mjs → summaryFormat.js} +1 -1
- package/lib/summary/summaryFormat.js.map +1 -0
- package/lib/summary/{summaryGenerator.d.mts → summaryGenerator.d.ts} +7 -6
- package/lib/summary/summaryGenerator.d.ts.map +1 -0
- package/lib/summary/{summaryGenerator.mjs → summaryGenerator.js} +11 -2
- package/lib/summary/summaryGenerator.js.map +1 -0
- package/lib/summary/{summaryManager.d.mts → summaryManager.d.ts} +6 -7
- package/lib/summary/summaryManager.d.ts.map +1 -0
- package/lib/summary/{summaryManager.mjs → summaryManager.js} +4 -5
- package/lib/summary/summaryManager.js.map +1 -0
- package/lib/test/batchTracker.spec.js +88 -0
- package/lib/test/batchTracker.spec.js.map +1 -0
- package/lib/test/blobManager.spec.js +835 -0
- package/lib/test/blobManager.spec.js.map +1 -0
- package/lib/test/channelCollection.spec.js +138 -0
- package/lib/test/channelCollection.spec.js.map +1 -0
- package/lib/test/containerRuntime.spec.js +1748 -0
- package/lib/test/containerRuntime.spec.js.map +1 -0
- package/lib/test/dataStoreContext.spec.js +771 -0
- package/lib/test/dataStoreContext.spec.js.map +1 -0
- package/lib/test/dataStoreCreation.spec.js +303 -0
- package/lib/test/dataStoreCreation.spec.js.map +1 -0
- package/lib/test/dataStoreRegistry.spec.js +26 -0
- package/lib/test/dataStoreRegistry.spec.js.map +1 -0
- package/lib/test/fuzz/fuzzUtils.js +66 -0
- package/lib/test/fuzz/fuzzUtils.js.map +1 -0
- package/lib/test/fuzz/summarizer.fuzz.spec.js +31 -0
- package/lib/test/fuzz/summarizer.fuzz.spec.js.map +1 -0
- package/lib/test/fuzz/summarizerFuzzMocks.js +162 -0
- package/lib/test/fuzz/summarizerFuzzMocks.js.map +1 -0
- package/lib/test/fuzz/summarizerFuzzSuite.js +106 -0
- package/lib/test/fuzz/summarizerFuzzSuite.js.map +1 -0
- package/lib/test/gc/garbageCollection.spec.js +1464 -0
- package/lib/test/gc/garbageCollection.spec.js.map +1 -0
- package/lib/test/gc/gcConfigs.spec.js +689 -0
- package/lib/test/gc/gcConfigs.spec.js.map +1 -0
- package/lib/test/gc/gcHelpers.spec.js +110 -0
- package/lib/test/gc/gcHelpers.spec.js.map +1 -0
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js +68 -0
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js.map +1 -0
- package/lib/test/gc/gcStats.spec.js +390 -0
- package/lib/test/gc/gcStats.spec.js.map +1 -0
- package/lib/test/gc/gcSummaryStateTracker.spec.js +228 -0
- package/lib/test/gc/gcSummaryStateTracker.spec.js.map +1 -0
- package/lib/test/gc/gcTelemetry.spec.js +530 -0
- package/lib/test/gc/gcTelemetry.spec.js.map +1 -0
- package/lib/test/gc/gcUnitTestHelpers.js +29 -0
- package/lib/test/gc/gcUnitTestHelpers.js.map +1 -0
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js +192 -0
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js.map +1 -0
- package/lib/test/getPendingBlobs.spec.js +193 -0
- package/lib/test/getPendingBlobs.spec.js.map +1 -0
- package/lib/test/hardwareStats.spec.js +93 -0
- package/lib/test/hardwareStats.spec.js.map +1 -0
- package/lib/test/index.js +6 -0
- package/lib/test/index.js.map +1 -0
- package/lib/test/opLifecycle/OpGroupingManager.spec.js +225 -0
- package/lib/test/opLifecycle/OpGroupingManager.spec.js.map +1 -0
- package/lib/test/opLifecycle/batchManager.spec.js +189 -0
- package/lib/test/opLifecycle/batchManager.spec.js.map +1 -0
- package/lib/test/opLifecycle/opCompressor.spec.js +74 -0
- package/lib/test/opLifecycle/opCompressor.spec.js.map +1 -0
- package/lib/test/opLifecycle/opDecompressor.spec.js +218 -0
- package/lib/test/opLifecycle/opDecompressor.spec.js.map +1 -0
- package/lib/test/opLifecycle/opSplitter.spec.js +272 -0
- package/lib/test/opLifecycle/opSplitter.spec.js.map +1 -0
- package/lib/test/opLifecycle/outbox.spec.js +675 -0
- package/lib/test/opLifecycle/outbox.spec.js.map +1 -0
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js +196 -0
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js.map +1 -0
- package/lib/test/pendingStateManager.spec.js +329 -0
- package/lib/test/pendingStateManager.spec.js.map +1 -0
- package/lib/test/scheduleManager.spec.js +270 -0
- package/lib/test/scheduleManager.spec.js.map +1 -0
- package/lib/test/summarizerNode.spec.js +326 -0
- package/lib/test/summarizerNode.spec.js.map +1 -0
- package/lib/test/summarizerNodeWithGc.spec.js +318 -0
- package/lib/test/summarizerNodeWithGc.spec.js.map +1 -0
- package/lib/test/summary/orderedClientElection.spec.js +535 -0
- package/lib/test/summary/orderedClientElection.spec.js.map +1 -0
- package/lib/test/summary/runningSummarizer.spec.js +1349 -0
- package/lib/test/summary/runningSummarizer.spec.js.map +1 -0
- package/lib/test/summary/summarizer.spec.js +29 -0
- package/lib/test/summary/summarizer.spec.js.map +1 -0
- package/lib/test/summary/summarizerClientElection.spec.js +436 -0
- package/lib/test/summary/summarizerClientElection.spec.js.map +1 -0
- package/lib/test/summary/summarizerHeuristics.spec.js +289 -0
- package/lib/test/summary/summarizerHeuristics.spec.js.map +1 -0
- package/lib/test/summary/summaryCollection.spec.js +200 -0
- package/lib/test/summary/summaryCollection.spec.js.map +1 -0
- package/lib/test/summary/summaryManager.spec.js +430 -0
- package/lib/test/summary/summaryManager.spec.js.map +1 -0
- package/lib/test/summary/testQuorumClients.js +34 -0
- package/lib/test/summary/testQuorumClients.js.map +1 -0
- package/lib/test/throttler.spec.js +175 -0
- package/lib/test/throttler.spec.js.map +1 -0
- package/lib/test/types/validateContainerRuntimePrevious.generated.js +180 -0
- package/lib/test/types/validateContainerRuntimePrevious.generated.js.map +1 -0
- package/lib/{throttler.d.mts → throttler.d.ts} +1 -1
- package/lib/throttler.d.ts.map +1 -0
- package/lib/{throttler.mjs → throttler.js} +1 -1
- package/lib/throttler.js.map +1 -0
- package/package.json +101 -88
- package/src/batchTracker.ts +1 -1
- package/src/blobManager.ts +1 -15
- package/src/{dataStores.ts → channelCollection.ts} +620 -175
- package/src/connectionTelemetry.ts +42 -3
- package/src/containerHandleContext.ts +1 -1
- package/src/containerRuntime.ts +604 -415
- package/src/dataStore.ts +16 -15
- package/src/dataStoreContext.ts +376 -216
- package/src/dataStoreContexts.ts +2 -1
- package/src/deltaManagerSummarizerProxy.ts +132 -7
- package/src/gc/garbageCollection.ts +84 -44
- package/src/gc/gcConfigs.ts +17 -7
- package/src/gc/gcDefinitions.ts +23 -13
- package/src/gc/gcHelpers.ts +2 -2
- package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
- package/src/gc/gcSummaryStateTracker.ts +19 -7
- package/src/gc/gcTelemetry.ts +9 -7
- package/src/gc/gcUnreferencedStateTracker.ts +1 -1
- package/src/gc/index.ts +10 -9
- package/src/index.ts +28 -27
- package/src/messageTypes.ts +3 -3
- package/src/opLifecycle/README.md +2 -4
- package/src/opLifecycle/batchManager.ts +2 -2
- package/src/opLifecycle/definitions.ts +2 -2
- package/src/opLifecycle/index.ts +8 -8
- package/src/opLifecycle/opCompressor.ts +3 -3
- package/src/opLifecycle/opDecompressor.ts +3 -3
- package/src/opLifecycle/opGroupingManager.ts +3 -12
- package/src/opLifecycle/opSplitter.ts +3 -3
- package/src/opLifecycle/outbox.ts +29 -9
- package/src/opLifecycle/remoteMessageProcessor.ts +4 -4
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +19 -13
- package/src/scheduleManager.ts +4 -4
- package/src/summary/index.ts +13 -12
- package/src/summary/orderedClientElection.ts +1 -1
- package/src/summary/runWhileConnectedCoordinator.ts +1 -1
- package/src/summary/runningSummarizer.ts +52 -32
- package/src/summary/summarizer.ts +7 -7
- package/src/summary/summarizerClientElection.ts +2 -2
- package/src/summary/summarizerHeuristics.ts +3 -3
- package/src/summary/summarizerNode/index.ts +6 -3
- package/src/summary/summarizerNode/summarizerNode.ts +50 -5
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +14 -1
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +11 -11
- package/src/summary/summarizerTypes.ts +11 -23
- package/src/summary/summaryFormat.ts +16 -2
- package/src/summary/summaryGenerator.ts +16 -4
- package/src/summary/summaryManager.ts +6 -7
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.json +2 -5
- package/dist/dataStores.d.ts +0 -151
- package/dist/dataStores.d.ts.map +0 -1
- package/dist/dataStores.js.map +0 -1
- package/dist/deltaManagerProxyBase.d.ts.map +0 -1
- package/dist/deltaManagerProxyBase.js +0 -77
- package/dist/deltaManagerProxyBase.js.map +0 -1
- package/lib/batchTracker.d.mts.map +0 -1
- package/lib/batchTracker.mjs.map +0 -1
- package/lib/blobManager.d.mts.map +0 -1
- package/lib/blobManager.mjs.map +0 -1
- package/lib/connectionTelemetry.d.mts.map +0 -1
- package/lib/connectionTelemetry.mjs.map +0 -1
- package/lib/containerHandleContext.d.mts.map +0 -1
- package/lib/containerHandleContext.mjs.map +0 -1
- package/lib/containerRuntime.d.mts.map +0 -1
- package/lib/containerRuntime.mjs.map +0 -1
- package/lib/dataStore.d.mts.map +0 -1
- package/lib/dataStore.mjs.map +0 -1
- package/lib/dataStoreContext.d.mts.map +0 -1
- package/lib/dataStoreContext.mjs.map +0 -1
- package/lib/dataStoreContexts.d.mts.map +0 -1
- package/lib/dataStoreContexts.mjs.map +0 -1
- package/lib/dataStoreRegistry.d.mts.map +0 -1
- package/lib/dataStoreRegistry.mjs.map +0 -1
- package/lib/dataStores.d.mts +0 -151
- package/lib/dataStores.d.mts.map +0 -1
- package/lib/dataStores.mjs.map +0 -1
- package/lib/deltaManagerProxyBase.d.mts +0 -35
- package/lib/deltaManagerProxyBase.d.mts.map +0 -1
- package/lib/deltaManagerProxyBase.mjs +0 -73
- package/lib/deltaManagerProxyBase.mjs.map +0 -1
- package/lib/deltaManagerSummarizerProxy.d.mts +0 -19
- package/lib/deltaManagerSummarizerProxy.d.mts.map +0 -1
- package/lib/deltaManagerSummarizerProxy.mjs +0 -38
- package/lib/deltaManagerSummarizerProxy.mjs.map +0 -1
- package/lib/deltaScheduler.d.mts.map +0 -1
- package/lib/deltaScheduler.mjs.map +0 -1
- package/lib/error.d.mts.map +0 -1
- package/lib/error.mjs.map +0 -1
- package/lib/gc/garbageCollection.d.mts.map +0 -1
- package/lib/gc/garbageCollection.mjs.map +0 -1
- package/lib/gc/gcConfigs.d.mts.map +0 -1
- package/lib/gc/gcConfigs.mjs.map +0 -1
- package/lib/gc/gcDefinitions.d.mts.map +0 -1
- package/lib/gc/gcDefinitions.mjs.map +0 -1
- package/lib/gc/gcHelpers.mjs.map +0 -1
- package/lib/gc/gcReferenceGraphAlgorithm.d.mts.map +0 -1
- package/lib/gc/gcReferenceGraphAlgorithm.mjs.map +0 -1
- package/lib/gc/gcSummaryDefinitions.d.mts.map +0 -1
- package/lib/gc/gcSummaryDefinitions.mjs.map +0 -1
- package/lib/gc/gcSummaryStateTracker.d.mts.map +0 -1
- package/lib/gc/gcSummaryStateTracker.mjs.map +0 -1
- package/lib/gc/gcTelemetry.d.mts.map +0 -1
- package/lib/gc/gcTelemetry.mjs.map +0 -1
- package/lib/gc/gcUnreferencedStateTracker.d.mts.map +0 -1
- package/lib/gc/gcUnreferencedStateTracker.mjs.map +0 -1
- package/lib/gc/index.d.mts +0 -13
- package/lib/gc/index.d.mts.map +0 -1
- package/lib/gc/index.mjs.map +0 -1
- package/lib/index.d.mts.map +0 -1
- package/lib/index.mjs +0 -25
- package/lib/index.mjs.map +0 -1
- package/lib/messageTypes.d.mts.map +0 -1
- package/lib/messageTypes.mjs.map +0 -1
- package/lib/metadata.d.mts.map +0 -1
- package/lib/metadata.mjs.map +0 -1
- package/lib/opLifecycle/batchManager.d.mts.map +0 -1
- package/lib/opLifecycle/batchManager.mjs.map +0 -1
- package/lib/opLifecycle/definitions.d.mts.map +0 -1
- package/lib/opLifecycle/definitions.mjs.map +0 -1
- package/lib/opLifecycle/index.d.mts +0 -13
- package/lib/opLifecycle/index.d.mts.map +0 -1
- package/lib/opLifecycle/index.mjs +0 -12
- package/lib/opLifecycle/index.mjs.map +0 -1
- package/lib/opLifecycle/opCompressor.d.mts.map +0 -1
- package/lib/opLifecycle/opCompressor.mjs.map +0 -1
- package/lib/opLifecycle/opDecompressor.d.mts.map +0 -1
- package/lib/opLifecycle/opDecompressor.mjs.map +0 -1
- package/lib/opLifecycle/opGroupingManager.d.mts.map +0 -1
- package/lib/opLifecycle/opGroupingManager.mjs.map +0 -1
- package/lib/opLifecycle/opSplitter.d.mts.map +0 -1
- package/lib/opLifecycle/opSplitter.mjs.map +0 -1
- package/lib/opLifecycle/outbox.d.mts.map +0 -1
- package/lib/opLifecycle/outbox.mjs.map +0 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.mts.map +0 -1
- package/lib/opLifecycle/remoteMessageProcessor.mjs.map +0 -1
- package/lib/opProperties.d.mts.map +0 -1
- package/lib/opProperties.mjs.map +0 -1
- package/lib/packageVersion.d.mts.map +0 -1
- package/lib/packageVersion.mjs.map +0 -1
- package/lib/pendingStateManager.d.mts.map +0 -1
- package/lib/pendingStateManager.mjs.map +0 -1
- package/lib/scheduleManager.d.mts.map +0 -1
- package/lib/scheduleManager.mjs.map +0 -1
- package/lib/storageServiceWithAttachBlobs.d.mts.map +0 -1
- package/lib/storageServiceWithAttachBlobs.mjs.map +0 -1
- package/lib/summary/index.d.mts.map +0 -1
- package/lib/summary/index.mjs.map +0 -1
- package/lib/summary/orderedClientElection.d.mts.map +0 -1
- package/lib/summary/orderedClientElection.mjs.map +0 -1
- package/lib/summary/runWhileConnectedCoordinator.d.mts.map +0 -1
- package/lib/summary/runWhileConnectedCoordinator.mjs.map +0 -1
- package/lib/summary/runningSummarizer.d.mts.map +0 -1
- package/lib/summary/runningSummarizer.mjs.map +0 -1
- package/lib/summary/summarizer.d.mts.map +0 -1
- package/lib/summary/summarizer.mjs.map +0 -1
- package/lib/summary/summarizerClientElection.d.mts.map +0 -1
- package/lib/summary/summarizerClientElection.mjs.map +0 -1
- package/lib/summary/summarizerHeuristics.d.mts.map +0 -1
- package/lib/summary/summarizerHeuristics.mjs.map +0 -1
- package/lib/summary/summarizerNode/index.d.mts.map +0 -1
- package/lib/summary/summarizerNode/index.mjs +0 -7
- package/lib/summary/summarizerNode/index.mjs.map +0 -1
- package/lib/summary/summarizerNode/summarizerNode.d.mts.map +0 -1
- package/lib/summary/summarizerNode/summarizerNode.mjs.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.mts.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.mjs.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.mts.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.mjs.map +0 -1
- package/lib/summary/summarizerTypes.d.mts.map +0 -1
- package/lib/summary/summarizerTypes.mjs.map +0 -1
- package/lib/summary/summaryCollection.d.mts.map +0 -1
- package/lib/summary/summaryCollection.mjs.map +0 -1
- package/lib/summary/summaryFormat.d.mts.map +0 -1
- package/lib/summary/summaryFormat.mjs.map +0 -1
- package/lib/summary/summaryGenerator.d.mts.map +0 -1
- package/lib/summary/summaryGenerator.mjs.map +0 -1
- package/lib/summary/summaryManager.d.mts.map +0 -1
- package/lib/summary/summaryManager.mjs.map +0 -1
- package/lib/throttler.d.mts.map +0 -1
- package/lib/throttler.mjs.map +0 -1
- package/src/deltaManagerProxyBase.ts +0 -111
package/src/containerRuntime.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import {
|
|
6
6
|
ITelemetryBaseLogger,
|
|
7
|
-
ITelemetryGenericEvent,
|
|
8
7
|
FluidObject,
|
|
9
8
|
IFluidHandle,
|
|
10
9
|
IFluidHandleContext,
|
|
@@ -21,7 +20,6 @@ import {
|
|
|
21
20
|
IRuntime,
|
|
22
21
|
ICriticalContainerError,
|
|
23
22
|
AttachState,
|
|
24
|
-
ILoaderOptions,
|
|
25
23
|
ILoader,
|
|
26
24
|
LoaderHeader,
|
|
27
25
|
IGetPendingLocalStateProps,
|
|
@@ -30,7 +28,7 @@ import {
|
|
|
30
28
|
IContainerRuntime,
|
|
31
29
|
IContainerRuntimeEvents,
|
|
32
30
|
} from "@fluidframework/container-runtime-definitions";
|
|
33
|
-
import { assert, delay, LazyPromise } from "@fluidframework/core-utils";
|
|
31
|
+
import { assert, Deferred, delay, LazyPromise, PromiseCache } from "@fluidframework/core-utils";
|
|
34
32
|
import { Trace, TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
35
33
|
import {
|
|
36
34
|
createChildLogger,
|
|
@@ -40,7 +38,6 @@ import {
|
|
|
40
38
|
GenericError,
|
|
41
39
|
raiseConnectedEvent,
|
|
42
40
|
PerformanceEvent,
|
|
43
|
-
// eslint-disable-next-line import/no-deprecated
|
|
44
41
|
TaggedLoggerAdapter,
|
|
45
42
|
MonitoringContext,
|
|
46
43
|
wrapError,
|
|
@@ -49,11 +46,14 @@ import {
|
|
|
49
46
|
LoggingError,
|
|
50
47
|
createSampledLogger,
|
|
51
48
|
IEventSampler,
|
|
49
|
+
type ITelemetryGenericEventExt,
|
|
50
|
+
loggerToMonitoringContext,
|
|
52
51
|
} from "@fluidframework/telemetry-utils";
|
|
53
52
|
import {
|
|
54
53
|
DriverHeader,
|
|
55
54
|
FetchSource,
|
|
56
55
|
IDocumentStorageService,
|
|
56
|
+
type ISnapshot,
|
|
57
57
|
} from "@fluidframework/driver-definitions";
|
|
58
58
|
import { readAndParse } from "@fluidframework/driver-utils";
|
|
59
59
|
import {
|
|
@@ -75,9 +75,7 @@ import {
|
|
|
75
75
|
InboundAttachMessage,
|
|
76
76
|
IFluidDataStoreContextDetached,
|
|
77
77
|
IFluidDataStoreRegistry,
|
|
78
|
-
IFluidDataStoreChannel,
|
|
79
78
|
IGarbageCollectionData,
|
|
80
|
-
IEnvelope,
|
|
81
79
|
IInboundSignalMessage,
|
|
82
80
|
NamedFluidDataStoreRegistryEntries,
|
|
83
81
|
ISummaryTreeWithStats,
|
|
@@ -87,18 +85,18 @@ import {
|
|
|
87
85
|
channelsTreeName,
|
|
88
86
|
IDataStore,
|
|
89
87
|
ITelemetryContext,
|
|
88
|
+
IEnvelope,
|
|
90
89
|
} from "@fluidframework/runtime-definitions";
|
|
91
90
|
import type {
|
|
92
91
|
SerializedIdCompressorWithNoSession,
|
|
93
92
|
IIdCompressor,
|
|
94
93
|
IIdCompressorCore,
|
|
95
|
-
IdCreationRange,
|
|
96
94
|
SerializedIdCompressorWithOngoingSession,
|
|
95
|
+
IdCreationRange,
|
|
97
96
|
} from "@fluidframework/id-compressor";
|
|
98
97
|
import {
|
|
99
98
|
addBlobToSummary,
|
|
100
99
|
addSummarizeResultToSummary,
|
|
101
|
-
addTreeToSummary,
|
|
102
100
|
RequestParser,
|
|
103
101
|
create404Response,
|
|
104
102
|
exceptionToResponse,
|
|
@@ -110,17 +108,17 @@ import {
|
|
|
110
108
|
responseToException,
|
|
111
109
|
} from "@fluidframework/runtime-utils";
|
|
112
110
|
import { v4 as uuid } from "uuid";
|
|
113
|
-
import { ContainerFluidHandleContext } from "./containerHandleContext";
|
|
114
|
-
import { FluidDataStoreRegistry } from "./dataStoreRegistry";
|
|
115
|
-
import { ReportOpPerfTelemetry, IPerfSignalReport } from "./connectionTelemetry";
|
|
111
|
+
import { ContainerFluidHandleContext } from "./containerHandleContext.js";
|
|
112
|
+
import { FluidDataStoreRegistry } from "./dataStoreRegistry.js";
|
|
113
|
+
import { ReportOpPerfTelemetry, IPerfSignalReport } from "./connectionTelemetry.js";
|
|
116
114
|
import {
|
|
117
115
|
IPendingBatchMessage,
|
|
118
116
|
IPendingLocalState,
|
|
119
117
|
PendingStateManager,
|
|
120
|
-
} from "./pendingStateManager";
|
|
121
|
-
import { pkgVersion } from "./packageVersion";
|
|
122
|
-
import { BlobManager, IBlobManagerLoadInfo, IPendingBlobs } from "./blobManager";
|
|
123
|
-
import {
|
|
118
|
+
} from "./pendingStateManager.js";
|
|
119
|
+
import { pkgVersion } from "./packageVersion.js";
|
|
120
|
+
import { BlobManager, IBlobManagerLoadInfo, IPendingBlobs } from "./blobManager.js";
|
|
121
|
+
import { ChannelCollection, getSummaryForDatastores, wrapContext } from "./channelCollection.js";
|
|
124
122
|
import {
|
|
125
123
|
aliasBlobName,
|
|
126
124
|
blobsTreeName,
|
|
@@ -160,8 +158,10 @@ import {
|
|
|
160
158
|
ISummarizerEvents,
|
|
161
159
|
IBaseSummarizeResult,
|
|
162
160
|
ISummarizer,
|
|
163
|
-
|
|
164
|
-
|
|
161
|
+
rootHasIsolatedChannels,
|
|
162
|
+
IdCompressorMode,
|
|
163
|
+
} from "./summary/index.js";
|
|
164
|
+
import { formExponentialFn, Throttler } from "./throttler.js";
|
|
165
165
|
import {
|
|
166
166
|
GarbageCollector,
|
|
167
167
|
GCNodeType,
|
|
@@ -169,11 +169,10 @@ import {
|
|
|
169
169
|
IGarbageCollector,
|
|
170
170
|
IGCRuntimeOptions,
|
|
171
171
|
IGCStats,
|
|
172
|
-
|
|
173
|
-
} from "./
|
|
174
|
-
import {
|
|
175
|
-
import {
|
|
176
|
-
import { ScheduleManager } from "./scheduleManager";
|
|
172
|
+
} from "./gc/index.js";
|
|
173
|
+
import { channelToDataStore } from "./dataStore.js";
|
|
174
|
+
import { BindBatchTracker } from "./batchTracker.js";
|
|
175
|
+
import { ScheduleManager } from "./scheduleManager.js";
|
|
177
176
|
import {
|
|
178
177
|
BatchMessage,
|
|
179
178
|
IBatch,
|
|
@@ -185,9 +184,9 @@ import {
|
|
|
185
184
|
RemoteMessageProcessor,
|
|
186
185
|
OpGroupingManager,
|
|
187
186
|
getLongStack,
|
|
188
|
-
} from "./opLifecycle";
|
|
189
|
-
import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy";
|
|
190
|
-
import { IBatchMetadata, IIdAllocationMetadata } from "./metadata";
|
|
187
|
+
} from "./opLifecycle/index.js";
|
|
188
|
+
import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy.js";
|
|
189
|
+
import { IBatchMetadata, IIdAllocationMetadata } from "./metadata.js";
|
|
191
190
|
import {
|
|
192
191
|
ContainerMessageType,
|
|
193
192
|
type InboundSequencedContainerRuntimeMessage,
|
|
@@ -197,7 +196,7 @@ import {
|
|
|
197
196
|
type OutboundContainerRuntimeMessage,
|
|
198
197
|
type UnknownContainerRuntimeMessage,
|
|
199
198
|
ContainerRuntimeGCMessage,
|
|
200
|
-
} from "./messageTypes";
|
|
199
|
+
} from "./messageTypes.js";
|
|
201
200
|
|
|
202
201
|
/**
|
|
203
202
|
* Utility to implement compat behaviors given an unknown message type
|
|
@@ -442,7 +441,7 @@ export interface IContainerRuntimeOptions {
|
|
|
442
441
|
* Enable the IdCompressor in the runtime.
|
|
443
442
|
* @experimental Not ready for use.
|
|
444
443
|
*/
|
|
445
|
-
readonly enableRuntimeIdCompressor?:
|
|
444
|
+
readonly enableRuntimeIdCompressor?: IdCompressorMode;
|
|
446
445
|
|
|
447
446
|
/**
|
|
448
447
|
* If enabled, the runtime will block all attempts to send an op inside the
|
|
@@ -467,27 +466,6 @@ export interface IContainerRuntimeOptions {
|
|
|
467
466
|
readonly enableGroupedBatching?: boolean;
|
|
468
467
|
}
|
|
469
468
|
|
|
470
|
-
/**
|
|
471
|
-
* Accepted header keys for requests coming to the runtime.
|
|
472
|
-
* @internal
|
|
473
|
-
*/
|
|
474
|
-
export enum RuntimeHeaders {
|
|
475
|
-
/** True to wait for a data store to be created and loaded before returning it. */
|
|
476
|
-
wait = "wait",
|
|
477
|
-
/** True if the request is coming from an IFluidHandle. */
|
|
478
|
-
viaHandle = "viaHandle",
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
/** True if a tombstoned object should be returned without erroring
|
|
482
|
-
* @alpha
|
|
483
|
-
*/
|
|
484
|
-
export const AllowTombstoneRequestHeaderKey = "allowTombstone"; // Belongs in the enum above, but avoiding the breaking change
|
|
485
|
-
/**
|
|
486
|
-
* [IRRELEVANT IF throwOnInactiveLoad OPTION NOT SET] True if an inactive object should be returned without erroring
|
|
487
|
-
* @internal
|
|
488
|
-
*/
|
|
489
|
-
export const AllowInactiveRequestHeaderKey = "allowInactive"; // Belongs in the enum above, but avoiding the breaking change
|
|
490
|
-
|
|
491
469
|
/**
|
|
492
470
|
* Tombstone error responses will have this header set to true
|
|
493
471
|
* @alpha
|
|
@@ -501,6 +479,7 @@ export const InactiveResponseHeaderKey = "isInactive";
|
|
|
501
479
|
|
|
502
480
|
/**
|
|
503
481
|
* The full set of parsed header data that may be found on Runtime requests
|
|
482
|
+
* @internal
|
|
504
483
|
*/
|
|
505
484
|
export interface RuntimeHeaderData {
|
|
506
485
|
wait?: boolean;
|
|
@@ -554,6 +533,11 @@ export interface IPendingRuntimeState {
|
|
|
554
533
|
* Pending idCompressor state
|
|
555
534
|
*/
|
|
556
535
|
pendingIdCompressorState?: SerializedIdCompressorWithOngoingSession;
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Time at which session expiry timer started.
|
|
539
|
+
*/
|
|
540
|
+
sessionExpiryTimerStarted?: number | undefined;
|
|
557
541
|
}
|
|
558
542
|
|
|
559
543
|
const maxConsecutiveReconnectsKey = "Fluid.ContainerRuntime.MaxConsecutiveReconnects";
|
|
@@ -768,7 +752,6 @@ export class ContainerRuntime
|
|
|
768
752
|
const backCompatContext: IContainerContext | OldContainerContextWithLogger = context;
|
|
769
753
|
const passLogger =
|
|
770
754
|
backCompatContext.taggedLogger ??
|
|
771
|
-
// eslint-disable-next-line import/no-deprecated
|
|
772
755
|
new TaggedLoggerAdapter((backCompatContext as OldContainerContextWithLogger).logger);
|
|
773
756
|
const logger = createChildLogger({
|
|
774
757
|
logger: passLogger,
|
|
@@ -779,6 +762,8 @@ export class ContainerRuntime
|
|
|
779
762
|
},
|
|
780
763
|
});
|
|
781
764
|
|
|
765
|
+
const mc = loggerToMonitoringContext(logger);
|
|
766
|
+
|
|
782
767
|
const {
|
|
783
768
|
summaryOptions = {},
|
|
784
769
|
gcOptions = {},
|
|
@@ -786,7 +771,7 @@ export class ContainerRuntime
|
|
|
786
771
|
flushMode = defaultFlushMode,
|
|
787
772
|
compressionOptions = defaultCompressionConfig,
|
|
788
773
|
maxBatchSizeInBytes = defaultMaxBatchSizeInBytes,
|
|
789
|
-
enableRuntimeIdCompressor =
|
|
774
|
+
enableRuntimeIdCompressor = "off",
|
|
790
775
|
chunkSizeInBytes = defaultChunkSizeInBytes,
|
|
791
776
|
enableOpReentryCheck = false,
|
|
792
777
|
enableGroupedBatching = false,
|
|
@@ -855,10 +840,37 @@ export class ContainerRuntime
|
|
|
855
840
|
}
|
|
856
841
|
}
|
|
857
842
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
let
|
|
861
|
-
if (
|
|
843
|
+
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
844
|
+
// allow new containers to turn it on
|
|
845
|
+
let idCompressorMode: IdCompressorMode;
|
|
846
|
+
if (existing) {
|
|
847
|
+
// This setting has to be sticky for correctness:
|
|
848
|
+
// 1) if compressior is OFF, it can't be enabled, as already running clients (in given document session) do not know
|
|
849
|
+
// how to process compressor ops
|
|
850
|
+
// 2) if it's ON, then all sessions should load compressor right away
|
|
851
|
+
// 3) Same logic applies for "delayed" mode
|
|
852
|
+
// Maybe in the future we will need to enabled (and figure how to do it safely) "delayed" -> "on" change.
|
|
853
|
+
// We could do "off" -> "on" transtition too, if all clients start loading compressor (but not using it initially) and do so for a while -
|
|
854
|
+
// this will allow clients to eventually to disregard "off" setting (when it's safe so) and start using compressor in future sessions.
|
|
855
|
+
// Everyting is possible, but it needs to be designed and executed carefully, when such need arises.
|
|
856
|
+
idCompressorMode = metadata?.idCompressorMode ?? "off";
|
|
857
|
+
} else {
|
|
858
|
+
// FG overwrite
|
|
859
|
+
const enabled = mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled");
|
|
860
|
+
switch (enabled) {
|
|
861
|
+
case true:
|
|
862
|
+
idCompressorMode = "on";
|
|
863
|
+
break;
|
|
864
|
+
case false:
|
|
865
|
+
idCompressorMode = "off";
|
|
866
|
+
break;
|
|
867
|
+
default:
|
|
868
|
+
idCompressorMode = enableRuntimeIdCompressor;
|
|
869
|
+
break;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
const createIdCompressorFn = async () => {
|
|
862
874
|
const { createIdCompressor, deserializeIdCompressor, createSessionId } = await import(
|
|
863
875
|
"@fluidframework/id-compressor"
|
|
864
876
|
);
|
|
@@ -878,21 +890,22 @@ export class ContainerRuntime
|
|
|
878
890
|
|
|
879
891
|
const compressorLogger = createSampledLogger(logger, idCompressorEventSampler);
|
|
880
892
|
const pendingLocalState = context.pendingLocalState as IPendingRuntimeState;
|
|
893
|
+
|
|
881
894
|
if (pendingLocalState?.pendingIdCompressorState !== undefined) {
|
|
882
|
-
|
|
895
|
+
return deserializeIdCompressor(
|
|
883
896
|
pendingLocalState.pendingIdCompressorState,
|
|
884
897
|
compressorLogger,
|
|
885
898
|
);
|
|
886
899
|
} else if (serializedIdCompressor !== undefined) {
|
|
887
|
-
|
|
900
|
+
return deserializeIdCompressor(
|
|
888
901
|
serializedIdCompressor,
|
|
889
902
|
createSessionId(),
|
|
890
903
|
compressorLogger,
|
|
891
904
|
);
|
|
892
905
|
} else {
|
|
893
|
-
|
|
906
|
+
return createIdCompressor(compressorLogger);
|
|
894
907
|
}
|
|
895
|
-
}
|
|
908
|
+
};
|
|
896
909
|
|
|
897
910
|
const runtime = new containerRuntimeCtor(
|
|
898
911
|
context,
|
|
@@ -918,7 +931,8 @@ export class ContainerRuntime
|
|
|
918
931
|
existing,
|
|
919
932
|
blobManagerSnapshot,
|
|
920
933
|
context.storage,
|
|
921
|
-
|
|
934
|
+
createIdCompressorFn,
|
|
935
|
+
idCompressorMode,
|
|
922
936
|
provideEntryPoint,
|
|
923
937
|
requestHandler,
|
|
924
938
|
undefined, // summaryConfiguration
|
|
@@ -934,7 +948,7 @@ export class ContainerRuntime
|
|
|
934
948
|
return runtime;
|
|
935
949
|
}
|
|
936
950
|
|
|
937
|
-
public readonly options:
|
|
951
|
+
public readonly options: Record<string | number, any>;
|
|
938
952
|
private imminentClosure: boolean = false;
|
|
939
953
|
|
|
940
954
|
private readonly _getClientId: () => string | undefined;
|
|
@@ -948,6 +962,10 @@ export class ContainerRuntime
|
|
|
948
962
|
return this._storage;
|
|
949
963
|
}
|
|
950
964
|
|
|
965
|
+
public get containerRuntime() {
|
|
966
|
+
return this;
|
|
967
|
+
}
|
|
968
|
+
|
|
951
969
|
private readonly submitFn: (
|
|
952
970
|
type: MessageType,
|
|
953
971
|
contents: any,
|
|
@@ -985,7 +1003,47 @@ export class ContainerRuntime
|
|
|
985
1003
|
return this._getAttachState();
|
|
986
1004
|
}
|
|
987
1005
|
|
|
988
|
-
|
|
1006
|
+
private _idCompressor: (IIdCompressor & IIdCompressorCore) | undefined;
|
|
1007
|
+
|
|
1008
|
+
// We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
|
|
1009
|
+
// Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
|
|
1010
|
+
private pendingIdCompressorOps: IdCreationRange[] = [];
|
|
1011
|
+
|
|
1012
|
+
// Id Compressor serializes final state (see getPendingLocalState()). As result, it needs to skip all ops that preceeded that state
|
|
1013
|
+
// (such ops will be marked by Loader layer as savedOp === true)
|
|
1014
|
+
// That said, in "delayed" mode it's possible that Id Compressor was never initialized before getPendingLocalState() is called.
|
|
1015
|
+
// In such case we have to process all ops, including those marked with saveOp === true.
|
|
1016
|
+
private readonly skipSavedCompressorOps: boolean;
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
* See IContainerRuntimeBase.idCompressor() for details.
|
|
1020
|
+
*/
|
|
1021
|
+
public get idCompressor() {
|
|
1022
|
+
// Expose ID Compressor only if it's On from the start.
|
|
1023
|
+
// If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
|
|
1024
|
+
// That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
|
|
1025
|
+
// to reason over such things as session ID space.
|
|
1026
|
+
if (this.idCompressorMode === "on") {
|
|
1027
|
+
assert(
|
|
1028
|
+
this._idCompressor !== undefined,
|
|
1029
|
+
0x8ea /* compressor should have been loaded */,
|
|
1030
|
+
);
|
|
1031
|
+
return this._idCompressor;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
/**
|
|
1036
|
+
* True if we have ID compressor loading in-flight (async operation). Useful only for
|
|
1037
|
+
* this.idCompressorMode === "delayed" mode
|
|
1038
|
+
*/
|
|
1039
|
+
protected compressorLoadInitiated = false;
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* See IContainerRuntimeBase.generateDocumentUniqueId() for details.
|
|
1043
|
+
*/
|
|
1044
|
+
public generateDocumentUniqueId() {
|
|
1045
|
+
return this._idCompressor?.generateDocumentUniqueId() ?? uuid();
|
|
1046
|
+
}
|
|
989
1047
|
|
|
990
1048
|
public get IFluidHandleContext(): IFluidHandleContext {
|
|
991
1049
|
return this.handleContext;
|
|
@@ -1109,7 +1167,7 @@ export class ContainerRuntime
|
|
|
1109
1167
|
private readonly outbox: Outbox;
|
|
1110
1168
|
private readonly garbageCollector: IGarbageCollector;
|
|
1111
1169
|
|
|
1112
|
-
private readonly
|
|
1170
|
+
private readonly channelCollection: ChannelCollection;
|
|
1113
1171
|
private readonly remoteMessageProcessor: RemoteMessageProcessor;
|
|
1114
1172
|
|
|
1115
1173
|
/** The last message processed at the time of the last summary. */
|
|
@@ -1125,11 +1183,6 @@ export class ContainerRuntime
|
|
|
1125
1183
|
return this.summaryConfiguration.state === "disabled";
|
|
1126
1184
|
}
|
|
1127
1185
|
|
|
1128
|
-
private readonly heuristicsDisabled: boolean;
|
|
1129
|
-
private isHeuristicsDisabled(): boolean {
|
|
1130
|
-
return this.summaryConfiguration.state === "disableHeuristics";
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
1186
|
private readonly maxOpsSinceLastSummary: number;
|
|
1134
1187
|
private getMaxOpsSinceLastSummary(): number {
|
|
1135
1188
|
return this.summaryConfiguration.state !== "disabled"
|
|
@@ -1172,11 +1225,6 @@ export class ContainerRuntime
|
|
|
1172
1225
|
*/
|
|
1173
1226
|
private readonly telemetryDocumentId: string;
|
|
1174
1227
|
|
|
1175
|
-
/**
|
|
1176
|
-
* If true, the runtime has access to an IdCompressor
|
|
1177
|
-
*/
|
|
1178
|
-
private readonly idCompressorEnabled: boolean;
|
|
1179
|
-
|
|
1180
1228
|
/**
|
|
1181
1229
|
* Whether this client is the summarizer client itself (type is summarizerClientType)
|
|
1182
1230
|
*/
|
|
@@ -1187,11 +1235,19 @@ export class ContainerRuntime
|
|
|
1187
1235
|
*/
|
|
1188
1236
|
private readonly loadedFromVersionId: string | undefined;
|
|
1189
1237
|
|
|
1238
|
+
/**
|
|
1239
|
+
* It a cache for holding mapping for loading groupIds with its snapshot from the service. Add expiry policy of 1 minute.
|
|
1240
|
+
* Starting with 1 min and based on recorded usage we can tweak it later on.
|
|
1241
|
+
*/
|
|
1242
|
+
private readonly snapshotCacheForLoadingGroupIds = new PromiseCache<string, ISnapshot>({
|
|
1243
|
+
expiry: { policy: "absolute", durationMs: 60000 },
|
|
1244
|
+
});
|
|
1245
|
+
|
|
1190
1246
|
/***/
|
|
1191
1247
|
protected constructor(
|
|
1192
1248
|
context: IContainerContext,
|
|
1193
1249
|
private readonly registry: IFluidDataStoreRegistry,
|
|
1194
|
-
metadata: IContainerRuntimeMetadata | undefined,
|
|
1250
|
+
private readonly metadata: IContainerRuntimeMetadata | undefined,
|
|
1195
1251
|
electedSummarizerData: ISerializedElection | undefined,
|
|
1196
1252
|
chunks: [string, string[]][],
|
|
1197
1253
|
dataStoreAliasMap: [string, string][],
|
|
@@ -1201,7 +1257,8 @@ export class ContainerRuntime
|
|
|
1201
1257
|
existing: boolean,
|
|
1202
1258
|
blobManagerSnapshot: IBlobManagerLoadInfo,
|
|
1203
1259
|
private readonly _storage: IDocumentStorageService,
|
|
1204
|
-
|
|
1260
|
+
private readonly createIdCompressor: () => Promise<IIdCompressor & IIdCompressorCore>,
|
|
1261
|
+
private readonly idCompressorMode: IdCompressorMode,
|
|
1205
1262
|
provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>,
|
|
1206
1263
|
private readonly requestHandler?: (
|
|
1207
1264
|
request: IRequest,
|
|
@@ -1245,7 +1302,9 @@ export class ContainerRuntime
|
|
|
1245
1302
|
this.submitSummaryFn = submitSummaryFn;
|
|
1246
1303
|
this.submitSignalFn = submitSignalFn;
|
|
1247
1304
|
|
|
1248
|
-
|
|
1305
|
+
// TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
|
|
1306
|
+
// Values are generally expected to be set from the runtime side.
|
|
1307
|
+
this.options = options ?? {};
|
|
1249
1308
|
this.clientDetails = clientDetails;
|
|
1250
1309
|
this.isSummarizerClient = this.clientDetails.type === summarizerClientType;
|
|
1251
1310
|
this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
|
|
@@ -1286,20 +1345,12 @@ export class ContainerRuntime
|
|
|
1286
1345
|
// summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
|
|
1287
1346
|
// the count is reset to 0.
|
|
1288
1347
|
loadSummaryNumber = metadata?.summaryNumber ?? 0;
|
|
1289
|
-
|
|
1290
|
-
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
1291
|
-
// allow new containers to turn it on
|
|
1292
|
-
this.idCompressorEnabled = metadata?.idCompressorEnabled ?? false;
|
|
1293
1348
|
} else {
|
|
1294
1349
|
this.createContainerMetadata = {
|
|
1295
1350
|
createContainerRuntimeVersion: pkgVersion,
|
|
1296
1351
|
createContainerTimestamp: Date.now(),
|
|
1297
1352
|
};
|
|
1298
1353
|
loadSummaryNumber = 0;
|
|
1299
|
-
|
|
1300
|
-
this.idCompressorEnabled =
|
|
1301
|
-
this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled") ??
|
|
1302
|
-
idCompressor !== undefined;
|
|
1303
1354
|
}
|
|
1304
1355
|
this.nextSummaryNumber = loadSummaryNumber + 1;
|
|
1305
1356
|
|
|
@@ -1367,14 +1418,9 @@ export class ContainerRuntime
|
|
|
1367
1418
|
disableOpReentryCheck !== true;
|
|
1368
1419
|
|
|
1369
1420
|
this.summariesDisabled = this.isSummariesDisabled();
|
|
1370
|
-
this.heuristicsDisabled = this.isHeuristicsDisabled();
|
|
1371
1421
|
this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
|
|
1372
1422
|
this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
|
|
1373
1423
|
|
|
1374
|
-
if (this.idCompressorEnabled) {
|
|
1375
|
-
this.idCompressor = idCompressor;
|
|
1376
|
-
}
|
|
1377
|
-
|
|
1378
1424
|
this.maxConsecutiveReconnects =
|
|
1379
1425
|
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
|
|
1380
1426
|
this.defaultMaxConsecutiveReconnects;
|
|
@@ -1418,6 +1464,7 @@ export class ContainerRuntime
|
|
|
1418
1464
|
getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
|
|
1419
1465
|
readAndParseBlob: async <T>(id: string) => readAndParse<T>(this.storage, id),
|
|
1420
1466
|
submitMessage: (message: ContainerRuntimeGCMessage) => this.submit(message),
|
|
1467
|
+
sessionExpiryTimerStarted: pendingRuntimeState?.sessionExpiryTimerStarted,
|
|
1421
1468
|
});
|
|
1422
1469
|
|
|
1423
1470
|
const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
|
|
@@ -1447,28 +1494,44 @@ export class ContainerRuntime
|
|
|
1447
1494
|
this.summarizerNode.updateBaseSummaryState(baseSnapshot);
|
|
1448
1495
|
}
|
|
1449
1496
|
|
|
1450
|
-
|
|
1497
|
+
const parentContext = wrapContext(this);
|
|
1498
|
+
|
|
1499
|
+
// Due to a mismatch between different layers in terms of
|
|
1500
|
+
// what is the interface of passing signals, we need the
|
|
1501
|
+
// downstream stores to wrap the signal.
|
|
1502
|
+
parentContext.submitSignal = (type: string, content: any, targetClientId?: string) => {
|
|
1503
|
+
const envelope1 = content as IEnvelope;
|
|
1504
|
+
const envelope2 = this.createNewSignalEnvelope(
|
|
1505
|
+
envelope1.address,
|
|
1506
|
+
type,
|
|
1507
|
+
envelope1.contents,
|
|
1508
|
+
);
|
|
1509
|
+
return this.submitSignalFn(envelope2, targetClientId);
|
|
1510
|
+
};
|
|
1511
|
+
|
|
1512
|
+
this.channelCollection = new ChannelCollection(
|
|
1451
1513
|
getSummaryForDatastores(baseSnapshot, metadata),
|
|
1452
|
-
|
|
1453
|
-
(attachMsg) => this.submit({ type: ContainerMessageType.Attach, contents: attachMsg }),
|
|
1454
|
-
(id: string, createParam: CreateChildSummarizerNodeParam) =>
|
|
1455
|
-
(
|
|
1456
|
-
summarizeInternal: SummarizeInternalFn,
|
|
1457
|
-
getGCDataFn: (fullGC?: boolean) => Promise<IGarbageCollectionData>,
|
|
1458
|
-
) =>
|
|
1459
|
-
this.summarizerNode.createChild(
|
|
1460
|
-
summarizeInternal,
|
|
1461
|
-
id,
|
|
1462
|
-
createParam,
|
|
1463
|
-
undefined,
|
|
1464
|
-
getGCDataFn,
|
|
1465
|
-
),
|
|
1466
|
-
(id: string) => this.summarizerNode.deleteChild(id),
|
|
1514
|
+
parentContext,
|
|
1467
1515
|
this.mc.logger,
|
|
1468
|
-
(
|
|
1469
|
-
|
|
1516
|
+
(
|
|
1517
|
+
path: string,
|
|
1518
|
+
reason: "Loaded" | "Changed",
|
|
1519
|
+
timestampMs?: number,
|
|
1520
|
+
packagePath?: readonly string[],
|
|
1521
|
+
request?: IRequest,
|
|
1522
|
+
headerData?: RuntimeHeaderData,
|
|
1523
|
+
) =>
|
|
1524
|
+
this.garbageCollector.nodeUpdated(
|
|
1525
|
+
path,
|
|
1526
|
+
reason,
|
|
1527
|
+
timestampMs,
|
|
1528
|
+
packagePath,
|
|
1529
|
+
request,
|
|
1530
|
+
headerData,
|
|
1531
|
+
),
|
|
1470
1532
|
(path: string) => this.garbageCollector.isNodeDeleted(path),
|
|
1471
1533
|
new Map<string, string>(dataStoreAliasMap),
|
|
1534
|
+
async (runtime: ChannelCollection) => provideEntryPoint,
|
|
1472
1535
|
);
|
|
1473
1536
|
|
|
1474
1537
|
this.blobManager = new BlobManager(
|
|
@@ -1510,6 +1573,7 @@ export class ContainerRuntime
|
|
|
1510
1573
|
reSubmit: this.reSubmit.bind(this),
|
|
1511
1574
|
reSubmitBatch: this.reSubmitBatch.bind(this),
|
|
1512
1575
|
isActiveConnection: () => this.innerDeltaManager.active,
|
|
1576
|
+
isAttached: () => this.attachState !== AttachState.Detached,
|
|
1513
1577
|
},
|
|
1514
1578
|
pendingRuntimeState?.pending,
|
|
1515
1579
|
this.logger,
|
|
@@ -1656,7 +1720,6 @@ export class ContainerRuntime
|
|
|
1656
1720
|
{
|
|
1657
1721
|
initialDelayMs: this.initialSummarizerDelayMs,
|
|
1658
1722
|
},
|
|
1659
|
-
this.heuristicsDisabled,
|
|
1660
1723
|
);
|
|
1661
1724
|
this.summaryManager.on("summarize", (eventProps) => {
|
|
1662
1725
|
this.emit("summarize", eventProps);
|
|
@@ -1674,26 +1737,27 @@ export class ContainerRuntime
|
|
|
1674
1737
|
this.mc.logger.sendTelemetryEvent({
|
|
1675
1738
|
eventName: "ContainerLoadStats",
|
|
1676
1739
|
...this.createContainerMetadata,
|
|
1677
|
-
...this.
|
|
1740
|
+
...this.channelCollection.containerLoadStats,
|
|
1678
1741
|
summaryNumber: loadSummaryNumber,
|
|
1679
1742
|
summaryFormatVersion: metadata?.summaryFormatVersion,
|
|
1680
1743
|
disableIsolatedChannels: metadata?.disableIsolatedChannels,
|
|
1681
1744
|
gcVersion: metadata?.gcFeature,
|
|
1682
1745
|
options: JSON.stringify(runtimeOptions),
|
|
1746
|
+
idCompressorModeMetadata: metadata?.idCompressorMode,
|
|
1747
|
+
idCompressorMode: this.idCompressorMode,
|
|
1683
1748
|
featureGates: JSON.stringify({
|
|
1684
1749
|
disableCompression,
|
|
1685
1750
|
disableOpReentryCheck,
|
|
1686
1751
|
disableChunking,
|
|
1687
1752
|
disableAttachReorder: this.disableAttachReorder,
|
|
1688
1753
|
disablePartialFlush,
|
|
1689
|
-
idCompressorEnabled: this.idCompressorEnabled,
|
|
1690
1754
|
closeSummarizerDelayOverride,
|
|
1691
1755
|
}),
|
|
1692
1756
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
1693
1757
|
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
1694
1758
|
});
|
|
1695
1759
|
|
|
1696
|
-
ReportOpPerfTelemetry(this.clientId, this.deltaManager, this.logger);
|
|
1760
|
+
ReportOpPerfTelemetry(this.clientId, this.deltaManager, this, this.logger);
|
|
1697
1761
|
BindBatchTracker(this, this.logger);
|
|
1698
1762
|
|
|
1699
1763
|
this.entryPoint = new LazyPromise(async () => {
|
|
@@ -1706,12 +1770,52 @@ export class ContainerRuntime
|
|
|
1706
1770
|
}
|
|
1707
1771
|
return provideEntryPoint(this);
|
|
1708
1772
|
});
|
|
1773
|
+
|
|
1774
|
+
// If we loaded from pending state, then we need to skip any ops that are already accounted in such
|
|
1775
|
+
// saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
|
|
1776
|
+
this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1779
|
+
public getCreateChildSummarizerNodeFn(id: string, createParam: CreateChildSummarizerNodeParam) {
|
|
1780
|
+
return (
|
|
1781
|
+
summarizeInternal: SummarizeInternalFn,
|
|
1782
|
+
getGCDataFn: (fullGC?: boolean) => Promise<IGarbageCollectionData>,
|
|
1783
|
+
) =>
|
|
1784
|
+
this.summarizerNode.createChild(
|
|
1785
|
+
summarizeInternal,
|
|
1786
|
+
id,
|
|
1787
|
+
createParam,
|
|
1788
|
+
undefined,
|
|
1789
|
+
getGCDataFn,
|
|
1790
|
+
);
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
public deleteChildSummarizerNode(id: string) {
|
|
1794
|
+
return this.summarizerNode.deleteChild(id);
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
/* IFluidParentContext APIs that should not be called on Root */
|
|
1798
|
+
public makeLocallyVisible() {
|
|
1799
|
+
assert(false, 0x8eb /* should not be called */);
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
public setChannelDirty(address: string) {
|
|
1803
|
+
assert(false, "should not be called");
|
|
1709
1804
|
}
|
|
1710
1805
|
|
|
1711
1806
|
/**
|
|
1712
1807
|
* Initializes the state from the base snapshot this container runtime loaded from.
|
|
1713
1808
|
*/
|
|
1714
1809
|
private async initializeBaseState(): Promise<void> {
|
|
1810
|
+
if (
|
|
1811
|
+
this.idCompressorMode === "on" ||
|
|
1812
|
+
(this.idCompressorMode === "delayed" && this.connected)
|
|
1813
|
+
) {
|
|
1814
|
+
// This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
|
|
1815
|
+
assert(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
|
|
1816
|
+
this._idCompressor = await this.createIdCompressor();
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1715
1819
|
await this.garbageCollector.initializeBaseState();
|
|
1716
1820
|
}
|
|
1717
1821
|
|
|
@@ -1736,12 +1840,145 @@ export class ContainerRuntime
|
|
|
1736
1840
|
}
|
|
1737
1841
|
this.garbageCollector.dispose();
|
|
1738
1842
|
this._summarizer?.dispose();
|
|
1739
|
-
this.
|
|
1843
|
+
this.channelCollection.dispose();
|
|
1740
1844
|
this.pendingStateManager.dispose();
|
|
1741
1845
|
this.emit("dispose");
|
|
1742
1846
|
this.removeAllListeners();
|
|
1743
1847
|
}
|
|
1744
1848
|
|
|
1849
|
+
/**
|
|
1850
|
+
* Api to fetch the snapshot from the service for a loadingGroupIds.
|
|
1851
|
+
* @param loadingGroupIds - LoadingGroupId for which the snapshot is asked for.
|
|
1852
|
+
* @param pathParts - Parts of the path, which we want to extract from the snapshot tree.
|
|
1853
|
+
* @returns - snapshotTree and the sequence number of the snapshot.
|
|
1854
|
+
*/
|
|
1855
|
+
public async getSnapshotForLoadingGroupId(
|
|
1856
|
+
loadingGroupIds: string[],
|
|
1857
|
+
pathParts: string[],
|
|
1858
|
+
): Promise<{ snapshotTree: ISnapshotTree; sequenceNumber: number }> {
|
|
1859
|
+
const sortedLoadingGroupIds = loadingGroupIds.sort();
|
|
1860
|
+
assert(
|
|
1861
|
+
this.storage.getSnapshot !== undefined,
|
|
1862
|
+
0x8ed /* getSnapshot api should be defined if used */,
|
|
1863
|
+
);
|
|
1864
|
+
let loadedFromCache = true;
|
|
1865
|
+
// Lookup up in the cache, if not present then make the network call as multiple datastores could
|
|
1866
|
+
// be in same loading group. So, once we have fetched the snapshot for that loading group on
|
|
1867
|
+
// any request, then cache that as same group could be requested in future too.
|
|
1868
|
+
const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(
|
|
1869
|
+
sortedLoadingGroupIds.join(),
|
|
1870
|
+
async () => {
|
|
1871
|
+
assert(
|
|
1872
|
+
this.storage.getSnapshot !== undefined,
|
|
1873
|
+
0x8ee /* getSnapshot api should be defined if used */,
|
|
1874
|
+
);
|
|
1875
|
+
loadedFromCache = false;
|
|
1876
|
+
return this.storage.getSnapshot({
|
|
1877
|
+
cacheSnapshot: false,
|
|
1878
|
+
scenarioName: "snapshotForLoadingGroupId",
|
|
1879
|
+
loadingGroupIds: sortedLoadingGroupIds,
|
|
1880
|
+
});
|
|
1881
|
+
},
|
|
1882
|
+
);
|
|
1883
|
+
|
|
1884
|
+
this.logger.sendTelemetryEvent({
|
|
1885
|
+
eventName: "GroupIdSnapshotFetched",
|
|
1886
|
+
details: JSON.stringify({
|
|
1887
|
+
fromCache: loadedFromCache,
|
|
1888
|
+
loadingGroupIds: loadingGroupIds.join(","),
|
|
1889
|
+
}),
|
|
1890
|
+
});
|
|
1891
|
+
// Find the snapshotTree inside the returned snapshot based on the path as given in the request.
|
|
1892
|
+
const hasIsolatedChannels = rootHasIsolatedChannels(this.metadata);
|
|
1893
|
+
const snapshotTreeForPath = this.getSnapshotTreeForPath(
|
|
1894
|
+
snapshot.snapshotTree,
|
|
1895
|
+
pathParts,
|
|
1896
|
+
hasIsolatedChannels,
|
|
1897
|
+
);
|
|
1898
|
+
assert(snapshotTreeForPath !== undefined, 0x8ef /* no snapshotTree for the path */);
|
|
1899
|
+
const snapshotSeqNumber = snapshot.sequenceNumber;
|
|
1900
|
+
assert(snapshotSeqNumber !== undefined, 0x8f0 /* snapshotSeqNumber should be present */);
|
|
1901
|
+
|
|
1902
|
+
// This assert fires if we get a snapshot older than the snapshot we loaded from. This is a service issue.
|
|
1903
|
+
// Snapshots should only move forward. If we observe an older snapshot than the one we loaded from, then likely
|
|
1904
|
+
// the file has been overwritten or service lost data.
|
|
1905
|
+
if (snapshotSeqNumber < this.deltaManager.initialSequenceNumber) {
|
|
1906
|
+
throw DataProcessingError.create(
|
|
1907
|
+
"Downloaded snapshot older than snapshot we loaded from",
|
|
1908
|
+
"getSnapshotForLoadingGroupId",
|
|
1909
|
+
undefined,
|
|
1910
|
+
{
|
|
1911
|
+
loadingGroupIds: sortedLoadingGroupIds.join(","),
|
|
1912
|
+
snapshotSeqNumber,
|
|
1913
|
+
initialSequenceNumber: this.deltaManager.initialSequenceNumber,
|
|
1914
|
+
},
|
|
1915
|
+
);
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
// If the snapshot is ahead of the last seq number of the delta manager, then catch up before
|
|
1919
|
+
// returning the snapshot.
|
|
1920
|
+
if (snapshotSeqNumber > this.deltaManager.lastSequenceNumber) {
|
|
1921
|
+
// If this is a summarizer client, which is trying to load a group and it finds that there is
|
|
1922
|
+
// another snapshot from which the summarizer loaded and it is behind, then just give up as
|
|
1923
|
+
// the summarizer state is not up to date.
|
|
1924
|
+
// This should be a recoverable scenario and shouldn't happen as we should process the ack first.
|
|
1925
|
+
if (this.isSummarizerClient) {
|
|
1926
|
+
throw new Error(
|
|
1927
|
+
"Summarizer client behind, loaded newer snapshot with loadingGroupId",
|
|
1928
|
+
);
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
// We want to catchup from sequenceNumber to targetSequenceNumber
|
|
1932
|
+
const props: ITelemetryGenericEventExt = {
|
|
1933
|
+
eventName: "GroupIdSnapshotCatchup",
|
|
1934
|
+
loadingGroupIds: sortedLoadingGroupIds.join(","),
|
|
1935
|
+
targetSequenceNumber: snapshotSeqNumber, // This is so we reuse some columns in telemetry
|
|
1936
|
+
sequenceNumber: this.deltaManager.lastSequenceNumber, // This is so we reuse some columns in telemetry
|
|
1937
|
+
};
|
|
1938
|
+
|
|
1939
|
+
const event = PerformanceEvent.start(this.mc.logger, {
|
|
1940
|
+
...props,
|
|
1941
|
+
});
|
|
1942
|
+
// If the inbound deltas queue is paused or disconnected, we expect a reconnect and unpause
|
|
1943
|
+
// as long as it's not a summarizer client.
|
|
1944
|
+
if (this.deltaManager.inbound.paused) {
|
|
1945
|
+
props.inboundPaused = this.deltaManager.inbound.paused; // reusing telemetry
|
|
1946
|
+
}
|
|
1947
|
+
const defP = new Deferred<boolean>();
|
|
1948
|
+
this.deltaManager.on("op", (message: ISequencedDocumentMessage) => {
|
|
1949
|
+
if (message.sequenceNumber >= snapshotSeqNumber) {
|
|
1950
|
+
defP.resolve(true);
|
|
1951
|
+
}
|
|
1952
|
+
});
|
|
1953
|
+
await defP.promise;
|
|
1954
|
+
event.end(props);
|
|
1955
|
+
}
|
|
1956
|
+
return { snapshotTree: snapshotTreeForPath, sequenceNumber: snapshotSeqNumber };
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
/**
|
|
1960
|
+
* Api to find a snapshot tree inside a bigger snapshot tree based on the path in the pathParts array.
|
|
1961
|
+
* @param snapshotTree - snapshot tree to look into.
|
|
1962
|
+
* @param pathParts - Part of the path, which we want to extract from the snapshot tree.
|
|
1963
|
+
* @param hasIsolatedChannels - whether the channels are present inside ".channels" subtree. Older
|
|
1964
|
+
* snapshots will not have trees inside ".channels", so check that.
|
|
1965
|
+
* @returns - requested snapshot tree based on the path parts.
|
|
1966
|
+
*/
|
|
1967
|
+
private getSnapshotTreeForPath(
|
|
1968
|
+
snapshotTree: ISnapshotTree,
|
|
1969
|
+
pathParts: string[],
|
|
1970
|
+
hasIsolatedChannels: boolean,
|
|
1971
|
+
): ISnapshotTree | undefined {
|
|
1972
|
+
let childTree = snapshotTree;
|
|
1973
|
+
for (const part of pathParts) {
|
|
1974
|
+
if (hasIsolatedChannels) {
|
|
1975
|
+
childTree = childTree?.trees[channelsTreeName];
|
|
1976
|
+
}
|
|
1977
|
+
childTree = childTree?.trees[part];
|
|
1978
|
+
}
|
|
1979
|
+
return childTree;
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1745
1982
|
/**
|
|
1746
1983
|
* Notifies this object about the request made to the container.
|
|
1747
1984
|
* @param request - Request made to the handler.
|
|
@@ -1798,19 +2035,7 @@ export class ContainerRuntime
|
|
|
1798
2035
|
}
|
|
1799
2036
|
: create404Response(request);
|
|
1800
2037
|
} else if (requestParser.pathParts.length > 0) {
|
|
1801
|
-
|
|
1802
|
-
const requestForChild = !requestParser.isLeaf(1);
|
|
1803
|
-
const dataStore = await this.getDataStoreFromRequest(id, request, requestForChild);
|
|
1804
|
-
|
|
1805
|
-
const subRequest = requestParser.createSubRequest(1);
|
|
1806
|
-
// We always expect createSubRequest to include a leading slash, but asserting here to protect against
|
|
1807
|
-
// unintentionally modifying the url if that changes.
|
|
1808
|
-
assert(
|
|
1809
|
-
subRequest.url.startsWith("/"),
|
|
1810
|
-
0x126 /* "Expected createSubRequest url to include a leading slash" */,
|
|
1811
|
-
);
|
|
1812
|
-
// eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
|
|
1813
|
-
return dataStore.request(subRequest);
|
|
2038
|
+
return await this.channelCollection.request(request);
|
|
1814
2039
|
}
|
|
1815
2040
|
|
|
1816
2041
|
return create404Response(request);
|
|
@@ -1828,54 +2053,7 @@ export class ContainerRuntime
|
|
|
1828
2053
|
private readonly entryPoint: LazyPromise<FluidObject>;
|
|
1829
2054
|
|
|
1830
2055
|
private internalId(maybeAlias: string): string {
|
|
1831
|
-
return this.
|
|
1832
|
-
}
|
|
1833
|
-
|
|
1834
|
-
private async getDataStoreFromRequest(
|
|
1835
|
-
id: string,
|
|
1836
|
-
request: IRequest,
|
|
1837
|
-
requestForChild: boolean,
|
|
1838
|
-
): Promise<IFluidDataStoreChannel> {
|
|
1839
|
-
const headerData: RuntimeHeaderData = {};
|
|
1840
|
-
if (typeof request.headers?.[RuntimeHeaders.wait] === "boolean") {
|
|
1841
|
-
headerData.wait = request.headers[RuntimeHeaders.wait];
|
|
1842
|
-
}
|
|
1843
|
-
if (typeof request.headers?.[RuntimeHeaders.viaHandle] === "boolean") {
|
|
1844
|
-
headerData.viaHandle = request.headers[RuntimeHeaders.viaHandle];
|
|
1845
|
-
}
|
|
1846
|
-
if (typeof request.headers?.[AllowTombstoneRequestHeaderKey] === "boolean") {
|
|
1847
|
-
headerData.allowTombstone = request.headers[AllowTombstoneRequestHeaderKey];
|
|
1848
|
-
}
|
|
1849
|
-
if (typeof request.headers?.[AllowInactiveRequestHeaderKey] === "boolean") {
|
|
1850
|
-
headerData.allowInactive = request.headers[AllowInactiveRequestHeaderKey];
|
|
1851
|
-
}
|
|
1852
|
-
|
|
1853
|
-
// We allow Tombstone requests for sub-DataStore objects
|
|
1854
|
-
if (requestForChild) {
|
|
1855
|
-
headerData.allowTombstone = true;
|
|
1856
|
-
}
|
|
1857
|
-
|
|
1858
|
-
await this.dataStores.waitIfPendingAlias(id);
|
|
1859
|
-
const internalId = this.internalId(id);
|
|
1860
|
-
const dataStoreContext = await this.dataStores.getDataStore(internalId, headerData);
|
|
1861
|
-
|
|
1862
|
-
// Remove query params, leading and trailing slashes from the url. This is done to make sure the format is
|
|
1863
|
-
// the same as GC nodes id.
|
|
1864
|
-
const urlWithoutQuery = trimLeadingAndTrailingSlashes(request.url.split("?")[0]);
|
|
1865
|
-
// Get the initial snapshot details which contain the data store package path.
|
|
1866
|
-
const details = await dataStoreContext.getInitialSnapshotDetails();
|
|
1867
|
-
|
|
1868
|
-
// Note that this will throw if the data store is inactive or tombstoned and throwing on incorrect usage
|
|
1869
|
-
// is configured.
|
|
1870
|
-
this.garbageCollector.nodeUpdated(
|
|
1871
|
-
`/${urlWithoutQuery}`,
|
|
1872
|
-
"Loaded",
|
|
1873
|
-
undefined /* timestampMs */,
|
|
1874
|
-
details.pkg,
|
|
1875
|
-
request,
|
|
1876
|
-
headerData,
|
|
1877
|
-
);
|
|
1878
|
-
return dataStoreContext.realize();
|
|
2056
|
+
return this.channelCollection.internalId(maybeAlias);
|
|
1879
2057
|
}
|
|
1880
2058
|
|
|
1881
2059
|
/** Adds the container's metadata to the given summary tree. */
|
|
@@ -1892,7 +2070,7 @@ export class ContainerRuntime
|
|
|
1892
2070
|
extractSummaryMetadataMessage(this.deltaManager.lastMessage) ??
|
|
1893
2071
|
this.messageAtLastSummary,
|
|
1894
2072
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
1895
|
-
|
|
2073
|
+
idCompressorMode: this.idCompressorMode,
|
|
1896
2074
|
};
|
|
1897
2075
|
addBlobToSummary(summaryTree, metadataBlobName, JSON.stringify(metadata));
|
|
1898
2076
|
}
|
|
@@ -1905,12 +2083,8 @@ export class ContainerRuntime
|
|
|
1905
2083
|
) {
|
|
1906
2084
|
this.addMetadataToSummary(summaryTree);
|
|
1907
2085
|
|
|
1908
|
-
if (this.
|
|
1909
|
-
|
|
1910
|
-
this.idCompressor !== undefined,
|
|
1911
|
-
0x67a /* IdCompressor should be defined if enabled */,
|
|
1912
|
-
);
|
|
1913
|
-
const idCompressorState = JSON.stringify(this.idCompressor.serialize(false));
|
|
2086
|
+
if (this._idCompressor) {
|
|
2087
|
+
const idCompressorState = JSON.stringify(this._idCompressor.serialize(false));
|
|
1914
2088
|
addBlobToSummary(summaryTree, idCompressorBlobName, idCompressorState);
|
|
1915
2089
|
}
|
|
1916
2090
|
|
|
@@ -1919,7 +2093,7 @@ export class ContainerRuntime
|
|
|
1919
2093
|
addBlobToSummary(summaryTree, chunksBlobName, content);
|
|
1920
2094
|
}
|
|
1921
2095
|
|
|
1922
|
-
const dataStoreAliases = this.
|
|
2096
|
+
const dataStoreAliases = this.channelCollection.aliases;
|
|
1923
2097
|
if (dataStoreAliases.size > 0) {
|
|
1924
2098
|
addBlobToSummary(summaryTree, aliasBlobName, JSON.stringify([...dataStoreAliases]));
|
|
1925
2099
|
}
|
|
@@ -1935,7 +2109,7 @@ export class ContainerRuntime
|
|
|
1935
2109
|
// Some storage (like git) doesn't allow empty tree, so we can omit it.
|
|
1936
2110
|
// and the blob manager can handle the tree not existing when loading
|
|
1937
2111
|
if (Object.keys(blobManagerSummary.summary.tree).length > 0) {
|
|
1938
|
-
|
|
2112
|
+
addSummarizeResultToSummary(summaryTree, blobsTreeName, blobManagerSummary);
|
|
1939
2113
|
}
|
|
1940
2114
|
|
|
1941
2115
|
const gcSummary = this.garbageCollector.summarize(fullTree, trackState, telemetryContext);
|
|
@@ -2035,16 +2209,12 @@ export class ContainerRuntime
|
|
|
2035
2209
|
const opContents = this.parseLocalOpContent(serializedOpContent);
|
|
2036
2210
|
switch (opContents.type) {
|
|
2037
2211
|
case ContainerMessageType.FluidDataStoreOp:
|
|
2038
|
-
return this.dataStores.applyStashedOp(opContents.contents);
|
|
2039
2212
|
case ContainerMessageType.Attach:
|
|
2040
|
-
|
|
2213
|
+
case ContainerMessageType.Alias:
|
|
2214
|
+
return this.channelCollection.applyStashedOp(opContents);
|
|
2041
2215
|
case ContainerMessageType.IdAllocation:
|
|
2042
|
-
assert(
|
|
2043
|
-
this.idCompressor !== undefined,
|
|
2044
|
-
0x67b /* IdCompressor should be defined if enabled */,
|
|
2045
|
-
);
|
|
2216
|
+
assert(this.idCompressorMode !== "off", 0x8f1 /* ID compressor should be in use */);
|
|
2046
2217
|
return;
|
|
2047
|
-
case ContainerMessageType.Alias:
|
|
2048
2218
|
case ContainerMessageType.BlobAttach:
|
|
2049
2219
|
return;
|
|
2050
2220
|
case ContainerMessageType.ChunkedOp:
|
|
@@ -2081,6 +2251,20 @@ export class ContainerRuntime
|
|
|
2081
2251
|
}
|
|
2082
2252
|
|
|
2083
2253
|
public setConnectionState(connected: boolean, clientId?: string) {
|
|
2254
|
+
if (connected && this.idCompressorMode === "delayed" && !this.compressorLoadInitiated) {
|
|
2255
|
+
this.compressorLoadInitiated = true;
|
|
2256
|
+
this.createIdCompressor()
|
|
2257
|
+
.then((compressor) => {
|
|
2258
|
+
this._idCompressor = compressor;
|
|
2259
|
+
for (const range of this.pendingIdCompressorOps) {
|
|
2260
|
+
this._idCompressor.finalizeCreationRange(range);
|
|
2261
|
+
}
|
|
2262
|
+
this.pendingIdCompressorOps = [];
|
|
2263
|
+
})
|
|
2264
|
+
.catch((error) => {
|
|
2265
|
+
this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
|
|
2266
|
+
});
|
|
2267
|
+
}
|
|
2084
2268
|
if (connected === false && this.delayConnectClientId !== undefined) {
|
|
2085
2269
|
this.delayConnectClientId = undefined;
|
|
2086
2270
|
this.mc.logger.sendTelemetryEvent({
|
|
@@ -2173,7 +2357,7 @@ export class ContainerRuntime
|
|
|
2173
2357
|
this.replayPendingStates();
|
|
2174
2358
|
}
|
|
2175
2359
|
|
|
2176
|
-
this.
|
|
2360
|
+
this.channelCollection.setConnectionState(connected, clientId);
|
|
2177
2361
|
this.garbageCollector.setConnectionState(connected, clientId);
|
|
2178
2362
|
|
|
2179
2363
|
raiseConnectedEvent(this.mc.logger, this, connected, clientId);
|
|
@@ -2276,17 +2460,9 @@ export class ContainerRuntime
|
|
|
2276
2460
|
const { local } = messageWithContext;
|
|
2277
2461
|
switch (messageWithContext.message.type) {
|
|
2278
2462
|
case ContainerMessageType.Attach:
|
|
2279
|
-
this.dataStores.processAttachMessage(messageWithContext.message, local);
|
|
2280
|
-
break;
|
|
2281
2463
|
case ContainerMessageType.Alias:
|
|
2282
|
-
this.dataStores.processAliasMessage(
|
|
2283
|
-
messageWithContext.message,
|
|
2284
|
-
localOpMetadata,
|
|
2285
|
-
local,
|
|
2286
|
-
);
|
|
2287
|
-
break;
|
|
2288
2464
|
case ContainerMessageType.FluidDataStoreOp:
|
|
2289
|
-
this.
|
|
2465
|
+
this.channelCollection.process(
|
|
2290
2466
|
messageWithContext.message,
|
|
2291
2467
|
local,
|
|
2292
2468
|
localOpMetadata,
|
|
@@ -2297,17 +2473,23 @@ export class ContainerRuntime
|
|
|
2297
2473
|
this.blobManager.processBlobAttachOp(messageWithContext.message, local);
|
|
2298
2474
|
break;
|
|
2299
2475
|
case ContainerMessageType.IdAllocation:
|
|
2300
|
-
assert(
|
|
2301
|
-
this.idCompressor !== undefined,
|
|
2302
|
-
0x67c /* IdCompressor should be defined if enabled */,
|
|
2303
|
-
);
|
|
2304
|
-
|
|
2305
2476
|
// Don't re-finalize the range if we're processing a "savedOp" in
|
|
2306
2477
|
// stashed ops flow. The compressor is stashed with these ops already processed.
|
|
2478
|
+
// That said, in idCompressorMode === "delayed", we might not serialize ID compressor, and
|
|
2479
|
+
// thus we need to process all the ops.
|
|
2307
2480
|
if (
|
|
2308
|
-
(
|
|
2481
|
+
!(
|
|
2482
|
+
this.skipSavedCompressorOps &&
|
|
2483
|
+
(messageWithContext.message.metadata as IIdAllocationMetadata)?.savedOp ===
|
|
2484
|
+
true
|
|
2485
|
+
)
|
|
2309
2486
|
) {
|
|
2310
|
-
|
|
2487
|
+
const range = messageWithContext.message.contents;
|
|
2488
|
+
if (this._idCompressor === undefined) {
|
|
2489
|
+
this.pendingIdCompressorOps.push(range);
|
|
2490
|
+
} else {
|
|
2491
|
+
this._idCompressor.finalizeCreationRange(range);
|
|
2492
|
+
}
|
|
2311
2493
|
}
|
|
2312
2494
|
break;
|
|
2313
2495
|
case ContainerMessageType.GC:
|
|
@@ -2413,7 +2595,16 @@ export class ContainerRuntime
|
|
|
2413
2595
|
return;
|
|
2414
2596
|
}
|
|
2415
2597
|
|
|
2416
|
-
|
|
2598
|
+
// Due to a mismatch between different layers in terms of
|
|
2599
|
+
// what is the interface of passing signals, we need to adjust
|
|
2600
|
+
// the signal envelope before sending it to the datastores to be processed
|
|
2601
|
+
const envelope2: IEnvelope = {
|
|
2602
|
+
address: envelope.address,
|
|
2603
|
+
contents: transformed.content,
|
|
2604
|
+
};
|
|
2605
|
+
transformed.content = envelope2;
|
|
2606
|
+
|
|
2607
|
+
this.channelCollection.processSignal(transformed, local);
|
|
2417
2608
|
}
|
|
2418
2609
|
|
|
2419
2610
|
/**
|
|
@@ -2500,9 +2691,17 @@ export class ContainerRuntime
|
|
|
2500
2691
|
public async getAliasedDataStoreEntryPoint(
|
|
2501
2692
|
alias: string,
|
|
2502
2693
|
): Promise<IFluidHandle<FluidObject> | undefined> {
|
|
2503
|
-
|
|
2694
|
+
// Back-comapatibility:
|
|
2695
|
+
// There are old files that were created without using data store aliasing feature, but
|
|
2696
|
+
// used createRoot*DataStore*() (already removed) API. Such data stores will have isRoot = true,
|
|
2697
|
+
// and internalID provided by user. The expectation is that such files behave as new files, where
|
|
2698
|
+
// same data store instances created using aliasing feature.
|
|
2699
|
+
// Please also see note on name collisions in DataStores.createDataStoreId()
|
|
2700
|
+
await this.channelCollection.waitIfPendingAlias(alias);
|
|
2504
2701
|
const internalId = this.internalId(alias);
|
|
2505
|
-
const context = await this.
|
|
2702
|
+
const context = await this.channelCollection.getDataStoreIfAvailable(internalId, {
|
|
2703
|
+
wait: false,
|
|
2704
|
+
});
|
|
2506
2705
|
// If the data store is not available or not an alias, return undefined.
|
|
2507
2706
|
if (context === undefined || !(await context.isRoot())) {
|
|
2508
2707
|
return undefined;
|
|
@@ -2523,37 +2722,26 @@ export class ContainerRuntime
|
|
|
2523
2722
|
return channel.entryPoint;
|
|
2524
2723
|
}
|
|
2525
2724
|
|
|
2526
|
-
public createDetachedRootDataStore(
|
|
2527
|
-
pkg: Readonly<string[]>,
|
|
2528
|
-
rootDataStoreId: string,
|
|
2529
|
-
): IFluidDataStoreContextDetached {
|
|
2530
|
-
if (rootDataStoreId.includes("/")) {
|
|
2531
|
-
throw new UsageError(`Id cannot contain slashes: '${rootDataStoreId}'`);
|
|
2532
|
-
}
|
|
2533
|
-
return this.dataStores.createDetachedDataStoreCore(pkg, true, rootDataStoreId);
|
|
2534
|
-
}
|
|
2535
|
-
|
|
2536
2725
|
public createDetachedDataStore(
|
|
2537
2726
|
pkg: Readonly<string[]>,
|
|
2538
|
-
|
|
2727
|
+
loadingGroupId?: string,
|
|
2539
2728
|
): IFluidDataStoreContextDetached {
|
|
2540
|
-
return this.
|
|
2729
|
+
return this.channelCollection.createDetachedDataStore(pkg, loadingGroupId);
|
|
2541
2730
|
}
|
|
2542
2731
|
|
|
2543
|
-
public async createDataStore(
|
|
2544
|
-
|
|
2732
|
+
public async createDataStore(
|
|
2733
|
+
pkg: Readonly<string | string[]>,
|
|
2734
|
+
loadingGroupId?: string,
|
|
2735
|
+
): Promise<IDataStore> {
|
|
2736
|
+
const context = this.channelCollection.createDataStoreContext(
|
|
2737
|
+
Array.isArray(pkg) ? pkg : [pkg],
|
|
2738
|
+
undefined, // props
|
|
2739
|
+
loadingGroupId,
|
|
2740
|
+
);
|
|
2545
2741
|
return channelToDataStore(
|
|
2546
|
-
await
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
id,
|
|
2550
|
-
undefined,
|
|
2551
|
-
groupId,
|
|
2552
|
-
)
|
|
2553
|
-
.realize(),
|
|
2554
|
-
id,
|
|
2555
|
-
this,
|
|
2556
|
-
this.dataStores,
|
|
2742
|
+
await context.realize(),
|
|
2743
|
+
context.id,
|
|
2744
|
+
this.channelCollection,
|
|
2557
2745
|
this.mc.logger,
|
|
2558
2746
|
);
|
|
2559
2747
|
}
|
|
@@ -2562,17 +2750,17 @@ export class ContainerRuntime
|
|
|
2562
2750
|
* @deprecated 0.16 Issue #1537, #3631
|
|
2563
2751
|
*/
|
|
2564
2752
|
public async _createDataStoreWithProps(
|
|
2565
|
-
pkg: string | string[]
|
|
2753
|
+
pkg: Readonly<string | string[]>,
|
|
2566
2754
|
props?: any,
|
|
2567
|
-
id = uuid(),
|
|
2568
2755
|
): Promise<IDataStore> {
|
|
2756
|
+
const context = this.channelCollection.createDataStoreContext(
|
|
2757
|
+
Array.isArray(pkg) ? pkg : [pkg],
|
|
2758
|
+
props,
|
|
2759
|
+
);
|
|
2569
2760
|
return channelToDataStore(
|
|
2570
|
-
await
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
id,
|
|
2574
|
-
this,
|
|
2575
|
-
this.dataStores,
|
|
2761
|
+
await context.realize(),
|
|
2762
|
+
context.id,
|
|
2763
|
+
this.channelCollection,
|
|
2576
2764
|
this.mc.logger,
|
|
2577
2765
|
);
|
|
2578
2766
|
}
|
|
@@ -2673,22 +2861,6 @@ export class ContainerRuntime
|
|
|
2673
2861
|
return this.submitSignalFn(envelope, targetClientId);
|
|
2674
2862
|
}
|
|
2675
2863
|
|
|
2676
|
-
/**
|
|
2677
|
-
* Submits the signal to be sent to other clients.
|
|
2678
|
-
* @param type - Type of the signal.
|
|
2679
|
-
* @param content - Content of the signal.
|
|
2680
|
-
* @param targetClientId - When specified, the signal is only sent to the provided client id.
|
|
2681
|
-
*/
|
|
2682
|
-
public submitDataStoreSignal(
|
|
2683
|
-
address: string,
|
|
2684
|
-
type: string,
|
|
2685
|
-
content: any,
|
|
2686
|
-
targetClientId?: string,
|
|
2687
|
-
) {
|
|
2688
|
-
const envelope = this.createNewSignalEnvelope(address, type, content);
|
|
2689
|
-
return this.submitSignalFn(envelope, targetClientId);
|
|
2690
|
-
}
|
|
2691
|
-
|
|
2692
2864
|
public setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void {
|
|
2693
2865
|
if (attachState === AttachState.Attaching) {
|
|
2694
2866
|
assert(
|
|
@@ -2706,7 +2878,7 @@ export class ContainerRuntime
|
|
|
2706
2878
|
if (attachState === AttachState.Attached && !this.hasPendingMessages()) {
|
|
2707
2879
|
this.updateDocumentDirtyState(false);
|
|
2708
2880
|
}
|
|
2709
|
-
this.
|
|
2881
|
+
this.channelCollection.setAttachState(attachState);
|
|
2710
2882
|
}
|
|
2711
2883
|
|
|
2712
2884
|
/**
|
|
@@ -2726,12 +2898,12 @@ export class ContainerRuntime
|
|
|
2726
2898
|
}
|
|
2727
2899
|
|
|
2728
2900
|
// We can finalize any allocated IDs since we're the only client
|
|
2729
|
-
const idRange = this.
|
|
2901
|
+
const idRange = this._idCompressor?.takeNextCreationRange();
|
|
2730
2902
|
if (idRange !== undefined) {
|
|
2731
|
-
this.
|
|
2903
|
+
this._idCompressor?.finalizeCreationRange(idRange);
|
|
2732
2904
|
}
|
|
2733
2905
|
|
|
2734
|
-
const summarizeResult = this.
|
|
2906
|
+
const summarizeResult = this.channelCollection.getAttachSummary(telemetryContext);
|
|
2735
2907
|
// Wrap data store summaries in .channels subtree.
|
|
2736
2908
|
wrapSummaryInChannelsTree(summarizeResult);
|
|
2737
2909
|
|
|
@@ -2751,7 +2923,7 @@ export class ContainerRuntime
|
|
|
2751
2923
|
trackState: boolean,
|
|
2752
2924
|
telemetryContext?: ITelemetryContext,
|
|
2753
2925
|
): Promise<ISummarizeInternalResult> {
|
|
2754
|
-
const summarizeResult = await this.
|
|
2926
|
+
const summarizeResult = await this.channelCollection.summarize(
|
|
2755
2927
|
fullTree,
|
|
2756
2928
|
trackState,
|
|
2757
2929
|
telemetryContext,
|
|
@@ -2842,11 +3014,11 @@ export class ContainerRuntime
|
|
|
2842
3014
|
* @see IGarbageCollectionRuntime.updateStateBeforeGC
|
|
2843
3015
|
*/
|
|
2844
3016
|
public async updateStateBeforeGC() {
|
|
2845
|
-
return this.
|
|
3017
|
+
return this.channelCollection.updateStateBeforeGC();
|
|
2846
3018
|
}
|
|
2847
3019
|
|
|
2848
3020
|
private async getGCDataInternal(fullGC?: boolean): Promise<IGarbageCollectionData> {
|
|
2849
|
-
return this.
|
|
3021
|
+
return this.channelCollection.getGCData(fullGC);
|
|
2850
3022
|
}
|
|
2851
3023
|
|
|
2852
3024
|
/**
|
|
@@ -2876,25 +3048,7 @@ export class ContainerRuntime
|
|
|
2876
3048
|
this.summarizerNode.updateUsedRoutes([""]);
|
|
2877
3049
|
|
|
2878
3050
|
const { dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(usedRoutes);
|
|
2879
|
-
this.
|
|
2880
|
-
}
|
|
2881
|
-
|
|
2882
|
-
/**
|
|
2883
|
-
* This is called to update objects whose routes are unused.
|
|
2884
|
-
* @param unusedRoutes - Data store and attachment blob routes that are unused in this Container.
|
|
2885
|
-
*/
|
|
2886
|
-
public updateUnusedRoutes(unusedRoutes: readonly string[]) {
|
|
2887
|
-
const { blobManagerRoutes, dataStoreRoutes } =
|
|
2888
|
-
this.getDataStoreAndBlobManagerRoutes(unusedRoutes);
|
|
2889
|
-
this.blobManager.updateUnusedRoutes(blobManagerRoutes);
|
|
2890
|
-
this.dataStores.updateUnusedRoutes(dataStoreRoutes);
|
|
2891
|
-
}
|
|
2892
|
-
|
|
2893
|
-
/**
|
|
2894
|
-
* @deprecated Replaced by deleteSweepReadyNodes.
|
|
2895
|
-
*/
|
|
2896
|
-
public deleteUnusedNodes(unusedRoutes: readonly string[]): string[] {
|
|
2897
|
-
throw new Error("deleteUnusedRoutes should not be called");
|
|
3051
|
+
this.channelCollection.updateUsedRoutes(dataStoreRoutes);
|
|
2898
3052
|
}
|
|
2899
3053
|
|
|
2900
3054
|
/**
|
|
@@ -2906,7 +3060,7 @@ export class ContainerRuntime
|
|
|
2906
3060
|
const { dataStoreRoutes, blobManagerRoutes } =
|
|
2907
3061
|
this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
|
|
2908
3062
|
|
|
2909
|
-
const deletedRoutes = this.
|
|
3063
|
+
const deletedRoutes = this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes);
|
|
2910
3064
|
return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
|
|
2911
3065
|
}
|
|
2912
3066
|
|
|
@@ -2922,7 +3076,7 @@ export class ContainerRuntime
|
|
|
2922
3076
|
const { blobManagerRoutes, dataStoreRoutes } =
|
|
2923
3077
|
this.getDataStoreAndBlobManagerRoutes(tombstonedRoutes);
|
|
2924
3078
|
this.blobManager.updateTombstonedRoutes(blobManagerRoutes);
|
|
2925
|
-
this.
|
|
3079
|
+
this.channelCollection.updateTombstonedRoutes(dataStoreRoutes);
|
|
2926
3080
|
}
|
|
2927
3081
|
|
|
2928
3082
|
/**
|
|
@@ -2942,7 +3096,7 @@ export class ContainerRuntime
|
|
|
2942
3096
|
if (this.isBlobPath(nodePath)) {
|
|
2943
3097
|
return GCNodeType.Blob;
|
|
2944
3098
|
}
|
|
2945
|
-
return this.
|
|
3099
|
+
return this.channelCollection.getGCNodeType(nodePath) ?? GCNodeType.Other;
|
|
2946
3100
|
}
|
|
2947
3101
|
|
|
2948
3102
|
/**
|
|
@@ -2953,7 +3107,7 @@ export class ContainerRuntime
|
|
|
2953
3107
|
// GC uses "/" when adding "root" references, e.g. for Aliasing or as part of Tombstone Auto-Recovery.
|
|
2954
3108
|
// These have no package path so return a special value.
|
|
2955
3109
|
if (nodePath === "/") {
|
|
2956
|
-
return ["
|
|
3110
|
+
return ["_gcRoot"];
|
|
2957
3111
|
}
|
|
2958
3112
|
|
|
2959
3113
|
switch (this.getNodeType(nodePath)) {
|
|
@@ -2961,7 +3115,7 @@ export class ContainerRuntime
|
|
|
2961
3115
|
return [BlobManager.basePath];
|
|
2962
3116
|
case GCNodeType.DataStore:
|
|
2963
3117
|
case GCNodeType.SubDataStore:
|
|
2964
|
-
return this.
|
|
3118
|
+
return this.channelCollection.getDataStorePackagePath(nodePath);
|
|
2965
3119
|
default:
|
|
2966
3120
|
assert(false, 0x2de /* "Package path requested for unsupported node type." */);
|
|
2967
3121
|
}
|
|
@@ -3021,7 +3175,10 @@ export class ContainerRuntime
|
|
|
3021
3175
|
* @param srcHandle - The handle of the node that added the reference.
|
|
3022
3176
|
* @param outboundHandle - The handle of the outbound node that is referenced.
|
|
3023
3177
|
*/
|
|
3024
|
-
public addedGCOutboundReference(
|
|
3178
|
+
public addedGCOutboundReference(
|
|
3179
|
+
srcHandle: { absolutePath: string },
|
|
3180
|
+
outboundHandle: { absolutePath: string },
|
|
3181
|
+
) {
|
|
3025
3182
|
this.garbageCollector.addedOutboundReference(
|
|
3026
3183
|
srcHandle.absolutePath,
|
|
3027
3184
|
outboundHandle.absolutePath,
|
|
@@ -3037,7 +3194,13 @@ export class ContainerRuntime
|
|
|
3037
3194
|
* @param options - options controlling how the summary is generated or submitted
|
|
3038
3195
|
*/
|
|
3039
3196
|
public async submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult> {
|
|
3040
|
-
const {
|
|
3197
|
+
const {
|
|
3198
|
+
fullTree = false,
|
|
3199
|
+
finalAttempt = false,
|
|
3200
|
+
refreshLatestAck,
|
|
3201
|
+
summaryLogger,
|
|
3202
|
+
latestSummaryRefSeqNum,
|
|
3203
|
+
} = options;
|
|
3041
3204
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
3042
3205
|
// use it for all events logged during this summary.
|
|
3043
3206
|
const summaryNumber = this.nextSummaryNumber;
|
|
@@ -3108,6 +3271,10 @@ export class ContainerRuntime
|
|
|
3108
3271
|
this.mc.config.getBoolean(
|
|
3109
3272
|
"Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause",
|
|
3110
3273
|
) !== true;
|
|
3274
|
+
const shouldValidatePreSummaryState =
|
|
3275
|
+
this.mc.config.getBoolean(
|
|
3276
|
+
"Fluid.ContainerRuntime.SubmitSummary.shouldValidatePreSummaryState",
|
|
3277
|
+
) === true;
|
|
3111
3278
|
|
|
3112
3279
|
let summaryRefSeqNum: number | undefined;
|
|
3113
3280
|
|
|
@@ -3122,7 +3289,33 @@ export class ContainerRuntime
|
|
|
3122
3289
|
const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
|
|
3123
3290
|
const lastAck = this.summaryCollection.latestAck;
|
|
3124
3291
|
|
|
3125
|
-
this.summarizerNode.startSummary(
|
|
3292
|
+
const startSummaryResult = this.summarizerNode.startSummary(
|
|
3293
|
+
summaryRefSeqNum,
|
|
3294
|
+
summaryNumberLogger,
|
|
3295
|
+
latestSummaryRefSeqNum,
|
|
3296
|
+
);
|
|
3297
|
+
|
|
3298
|
+
if (
|
|
3299
|
+
startSummaryResult.invalidNodes > 0 ||
|
|
3300
|
+
startSummaryResult.mismatchNumbers.size > 0
|
|
3301
|
+
) {
|
|
3302
|
+
summaryLogger.sendErrorEvent({
|
|
3303
|
+
eventName: "LatestSummaryRefSeqNumMismatch",
|
|
3304
|
+
details: {
|
|
3305
|
+
...startSummaryResult,
|
|
3306
|
+
mismatchNumbers: Array.from(startSummaryResult.mismatchNumbers),
|
|
3307
|
+
},
|
|
3308
|
+
});
|
|
3309
|
+
|
|
3310
|
+
if (shouldValidatePreSummaryState && !finalAttempt) {
|
|
3311
|
+
return {
|
|
3312
|
+
stage: "base",
|
|
3313
|
+
referenceSequenceNumber: summaryRefSeqNum,
|
|
3314
|
+
minimumSequenceNumber,
|
|
3315
|
+
error: `Summarizer node state inconsistent with summarizer state.`,
|
|
3316
|
+
};
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3126
3319
|
|
|
3127
3320
|
// Helper function to check whether we should still continue between each async step.
|
|
3128
3321
|
const checkContinue = (): { continue: true } | { continue: false; error: string } => {
|
|
@@ -3244,8 +3437,8 @@ export class ContainerRuntime
|
|
|
3244
3437
|
: undefined;
|
|
3245
3438
|
|
|
3246
3439
|
const summaryStats: IGeneratedSummaryStats = {
|
|
3247
|
-
dataStoreCount: this.
|
|
3248
|
-
summarizedDataStoreCount: this.
|
|
3440
|
+
dataStoreCount: this.channelCollection.size,
|
|
3441
|
+
summarizedDataStoreCount: this.channelCollection.size - handleCount,
|
|
3249
3442
|
gcStateUpdatedDataStoreCount: this.garbageCollector.updatedDSCountSinceLastSummary,
|
|
3250
3443
|
gcBlobNodeCount: gcSummaryTreeStats?.blobNodeCount,
|
|
3251
3444
|
gcTotalBlobsSize: gcSummaryTreeStats?.totalBlobSize,
|
|
@@ -3442,28 +3635,15 @@ export class ContainerRuntime
|
|
|
3442
3635
|
}
|
|
3443
3636
|
}
|
|
3444
3637
|
|
|
3445
|
-
public
|
|
3446
|
-
|
|
3638
|
+
public submitMessage(
|
|
3639
|
+
type:
|
|
3640
|
+
| ContainerMessageType.FluidDataStoreOp
|
|
3641
|
+
| ContainerMessageType.Alias
|
|
3642
|
+
| ContainerMessageType.Attach,
|
|
3447
3643
|
contents: any,
|
|
3448
3644
|
localOpMetadata: unknown = undefined,
|
|
3449
3645
|
): void {
|
|
3450
|
-
|
|
3451
|
-
address: id,
|
|
3452
|
-
contents,
|
|
3453
|
-
};
|
|
3454
|
-
this.submit(
|
|
3455
|
-
{ type: ContainerMessageType.FluidDataStoreOp, contents: envelope },
|
|
3456
|
-
localOpMetadata,
|
|
3457
|
-
);
|
|
3458
|
-
}
|
|
3459
|
-
|
|
3460
|
-
public submitDataStoreAliasOp(contents: any, localOpMetadata: unknown): void {
|
|
3461
|
-
const aliasMessage = contents as IDataStoreAliasMessage;
|
|
3462
|
-
if (!isDataStoreAliasMessage(aliasMessage)) {
|
|
3463
|
-
throw new UsageError("malformedDataStoreAliasMessage");
|
|
3464
|
-
}
|
|
3465
|
-
|
|
3466
|
-
this.submit({ type: ContainerMessageType.Alias, contents }, localOpMetadata);
|
|
3646
|
+
this.submit({ type, contents }, localOpMetadata);
|
|
3467
3647
|
}
|
|
3468
3648
|
|
|
3469
3649
|
public async uploadBlob(
|
|
@@ -3474,35 +3654,22 @@ export class ContainerRuntime
|
|
|
3474
3654
|
return this.blobManager.createBlob(blob, signal);
|
|
3475
3655
|
}
|
|
3476
3656
|
|
|
3477
|
-
private
|
|
3478
|
-
if (
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
if (
|
|
3482
|
-
assert(
|
|
3483
|
-
this.idCompressor !== undefined,
|
|
3484
|
-
0x67d /* IdCompressor should be defined if enabled */,
|
|
3485
|
-
);
|
|
3486
|
-
idRange = this.idCompressor.takeNextCreationRange();
|
|
3487
|
-
// Don't include the idRange if there weren't any Ids allocated
|
|
3488
|
-
idRange = idRange?.ids !== undefined ? idRange : undefined;
|
|
3489
|
-
}
|
|
3490
|
-
|
|
3491
|
-
if (idRange !== undefined) {
|
|
3657
|
+
private submitIdAllocationOpIfNeeded(): void {
|
|
3658
|
+
if (this._idCompressor) {
|
|
3659
|
+
const idRange = this._idCompressor.takeNextCreationRange();
|
|
3660
|
+
// Don't include the idRange if there weren't any Ids allocated
|
|
3661
|
+
if (idRange?.ids !== undefined) {
|
|
3492
3662
|
const idAllocationMessage: ContainerRuntimeIdAllocationMessage = {
|
|
3493
3663
|
type: ContainerMessageType.IdAllocation,
|
|
3494
3664
|
contents: idRange,
|
|
3495
3665
|
};
|
|
3496
|
-
idAllocationBatchMessage = {
|
|
3666
|
+
const idAllocationBatchMessage: BatchMessage = {
|
|
3497
3667
|
contents: JSON.stringify(idAllocationMessage),
|
|
3498
3668
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
3499
3669
|
metadata: undefined,
|
|
3500
3670
|
localOpMetadata: undefined,
|
|
3501
3671
|
type: ContainerMessageType.IdAllocation,
|
|
3502
3672
|
};
|
|
3503
|
-
}
|
|
3504
|
-
|
|
3505
|
-
if (idAllocationBatchMessage !== undefined) {
|
|
3506
3673
|
this.outbox.submitIdAllocation(idAllocationBatchMessage);
|
|
3507
3674
|
}
|
|
3508
3675
|
}
|
|
@@ -3543,43 +3710,47 @@ export class ContainerRuntime
|
|
|
3543
3710
|
};
|
|
3544
3711
|
|
|
3545
3712
|
try {
|
|
3546
|
-
//
|
|
3547
|
-
// the
|
|
3548
|
-
// op
|
|
3549
|
-
//
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
// If this is attach message for new data store, and we are in a batch, send this op out of order
|
|
3553
|
-
// Is it safe:
|
|
3554
|
-
// Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
|
|
3555
|
-
// They become visible only when aliased, or handle to some sub-element of newly created datastore
|
|
3556
|
-
// is stored in some DDS, i.e. only after some other op.
|
|
3557
|
-
// Why:
|
|
3558
|
-
// Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
|
|
3559
|
-
// stores are created, causing issues like relay service throttling (too many ops) and catastrophic
|
|
3560
|
-
// failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
|
|
3561
|
-
// these issues.
|
|
3562
|
-
// Cons:
|
|
3563
|
-
// 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
|
|
3564
|
-
// This change creates new possibility of a lot of newly created data stores never being referenced
|
|
3565
|
-
// because client died before it had a change to submit the rest of the ops. This will create more
|
|
3566
|
-
// garbage that needs to be collected leveraging GC (Garbage Collection) feature.
|
|
3567
|
-
// 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
|
|
3568
|
-
// today as rollback can't undo creation of data store. To some extent not sending them is a bigger
|
|
3569
|
-
// issue than sending.
|
|
3570
|
-
// Please note that this does not change file format, so it can be disabled in the future if this
|
|
3571
|
-
// optimization no longer makes sense (for example, batch compression may make it less appealing).
|
|
3572
|
-
if (
|
|
3573
|
-
this.currentlyBatching() &&
|
|
3574
|
-
type === ContainerMessageType.Attach &&
|
|
3575
|
-
this.disableAttachReorder !== true
|
|
3576
|
-
) {
|
|
3577
|
-
this.outbox.submitAttach(message);
|
|
3578
|
-
} else if (type === ContainerMessageType.BlobAttach) {
|
|
3579
|
-
// BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
|
|
3580
|
-
this.outbox.submitBlobAttach(message);
|
|
3713
|
+
// If `message` is an allocation op, then we are in the resubmit path and we must redirect the allocation
|
|
3714
|
+
// op into the correct batch to avoid ranges being finalized out of order.
|
|
3715
|
+
// Otherwise, submit an IdAllocation op if any IDs have been generated since the last op was submitted, as
|
|
3716
|
+
// any of the other op types may contain those IDs and thus depend on the allocation op being sent first.
|
|
3717
|
+
if (type === ContainerMessageType.IdAllocation) {
|
|
3718
|
+
this.outbox.submitIdAllocation(message);
|
|
3581
3719
|
} else {
|
|
3582
|
-
this.
|
|
3720
|
+
this.submitIdAllocationOpIfNeeded();
|
|
3721
|
+
|
|
3722
|
+
// If this is attach message for new data store, and we are in a batch, send this op out of order
|
|
3723
|
+
// Is it safe:
|
|
3724
|
+
// Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
|
|
3725
|
+
// They become visible only when aliased, or handle to some sub-element of newly created datastore
|
|
3726
|
+
// is stored in some DDS, i.e. only after some other op.
|
|
3727
|
+
// Why:
|
|
3728
|
+
// Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
|
|
3729
|
+
// stores are created, causing issues like relay service throttling (too many ops) and catastrophic
|
|
3730
|
+
// failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
|
|
3731
|
+
// these issues.
|
|
3732
|
+
// Cons:
|
|
3733
|
+
// 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
|
|
3734
|
+
// This change creates new possibility of a lot of newly created data stores never being referenced
|
|
3735
|
+
// because client died before it had a change to submit the rest of the ops. This will create more
|
|
3736
|
+
// garbage that needs to be collected leveraging GC (Garbage Collection) feature.
|
|
3737
|
+
// 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
|
|
3738
|
+
// today as rollback can't undo creation of data store. To some extent not sending them is a bigger
|
|
3739
|
+
// issue than sending.
|
|
3740
|
+
// Please note that this does not change file format, so it can be disabled in the future if this
|
|
3741
|
+
// optimization no longer makes sense (for example, batch compression may make it less appealing).
|
|
3742
|
+
if (
|
|
3743
|
+
this.currentlyBatching() &&
|
|
3744
|
+
type === ContainerMessageType.Attach &&
|
|
3745
|
+
this.disableAttachReorder !== true
|
|
3746
|
+
) {
|
|
3747
|
+
this.outbox.submitAttach(message);
|
|
3748
|
+
} else if (type === ContainerMessageType.BlobAttach) {
|
|
3749
|
+
// BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
|
|
3750
|
+
this.outbox.submitBlobAttach(message);
|
|
3751
|
+
} else {
|
|
3752
|
+
this.outbox.submit(message);
|
|
3753
|
+
}
|
|
3583
3754
|
}
|
|
3584
3755
|
|
|
3585
3756
|
if (!this.currentlyBatching()) {
|
|
@@ -3721,15 +3892,18 @@ export class ContainerRuntime
|
|
|
3721
3892
|
localOpMetadata: unknown,
|
|
3722
3893
|
opMetadata: Record<string, unknown> | undefined,
|
|
3723
3894
|
) {
|
|
3724
|
-
assert(
|
|
3895
|
+
assert(
|
|
3896
|
+
!this.isSummarizerClient,
|
|
3897
|
+
0x8f2 /* Summarizer never reconnects so should never resubmit */,
|
|
3898
|
+
);
|
|
3725
3899
|
switch (message.type) {
|
|
3726
3900
|
case ContainerMessageType.FluidDataStoreOp:
|
|
3901
|
+
case ContainerMessageType.Attach:
|
|
3902
|
+
case ContainerMessageType.Alias:
|
|
3727
3903
|
// For Operations, call resubmitDataStoreOp which will find the right store
|
|
3728
3904
|
// and trigger resubmission on it.
|
|
3729
|
-
this.
|
|
3905
|
+
this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
|
|
3730
3906
|
break;
|
|
3731
|
-
case ContainerMessageType.Attach:
|
|
3732
|
-
case ContainerMessageType.Alias:
|
|
3733
3907
|
case ContainerMessageType.IdAllocation: {
|
|
3734
3908
|
this.submit(message, localOpMetadata);
|
|
3735
3909
|
break;
|
|
@@ -3781,7 +3955,7 @@ export class ContainerRuntime
|
|
|
3781
3955
|
case ContainerMessageType.FluidDataStoreOp:
|
|
3782
3956
|
// For operations, call rollbackDataStoreOp which will find the right store
|
|
3783
3957
|
// and trigger rollback on it.
|
|
3784
|
-
this.
|
|
3958
|
+
this.channelCollection.rollback(type, contents, localOpMetadata);
|
|
3785
3959
|
break;
|
|
3786
3960
|
default:
|
|
3787
3961
|
// Don't check message.compatDetails because this is for rolling back a local op so the type will be known
|
|
@@ -3870,7 +4044,7 @@ export class ContainerRuntime
|
|
|
3870
4044
|
*/
|
|
3871
4045
|
private async fetchLatestSnapshotFromStorage(
|
|
3872
4046
|
logger: ITelemetryLoggerExt,
|
|
3873
|
-
event:
|
|
4047
|
+
event: ITelemetryGenericEventExt,
|
|
3874
4048
|
readAndParseBlob: ReadAndParseBlob,
|
|
3875
4049
|
): Promise<{ snapshotTree: ISnapshotTree; versionId: string; latestSnapshotRefSeq: number }> {
|
|
3876
4050
|
return PerformanceEvent.timedExecAsync(
|
|
@@ -3921,50 +4095,65 @@ export class ContainerRuntime
|
|
|
3921
4095
|
);
|
|
3922
4096
|
}
|
|
3923
4097
|
|
|
3924
|
-
public
|
|
3925
|
-
|
|
3926
|
-
this.mc.logger,
|
|
3927
|
-
{
|
|
3928
|
-
eventName: "getPendingLocalState",
|
|
3929
|
-
notifyImminentClosure: props?.notifyImminentClosure,
|
|
3930
|
-
},
|
|
3931
|
-
async (event) => {
|
|
3932
|
-
this.verifyNotClosed();
|
|
3933
|
-
// in case imminentClosure is set to true by future code, we don't
|
|
3934
|
-
// try to change its value
|
|
3935
|
-
if (!this.imminentClosure) {
|
|
3936
|
-
this.imminentClosure = props?.notifyImminentClosure ?? this.imminentClosure;
|
|
3937
|
-
}
|
|
3938
|
-
const stopBlobAttachingSignal = props?.stopBlobAttachingSignal;
|
|
3939
|
-
if (this._orderSequentiallyCalls !== 0) {
|
|
3940
|
-
throw new UsageError("can't get state during orderSequentially");
|
|
3941
|
-
}
|
|
3942
|
-
// Flush pending batch.
|
|
3943
|
-
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
3944
|
-
// to close current batch.
|
|
3945
|
-
this.flush();
|
|
3946
|
-
const pendingAttachmentBlobs = this.imminentClosure
|
|
3947
|
-
? await this.blobManager.attachAndGetPendingBlobs(stopBlobAttachingSignal)
|
|
3948
|
-
: undefined;
|
|
3949
|
-
const pending = this.pendingStateManager.getLocalState();
|
|
3950
|
-
if (!pendingAttachmentBlobs && !this.hasPendingMessages()) {
|
|
3951
|
-
return; // no pending state to save
|
|
3952
|
-
}
|
|
4098
|
+
public getPendingLocalState(props?: IGetPendingLocalStateProps): unknown {
|
|
4099
|
+
this.verifyNotClosed();
|
|
3953
4100
|
|
|
3954
|
-
|
|
4101
|
+
if (this._orderSequentiallyCalls !== 0) {
|
|
4102
|
+
throw new UsageError("can't get state during orderSequentially");
|
|
4103
|
+
}
|
|
4104
|
+
this.imminentClosure ||= props?.notifyImminentClosure ?? false;
|
|
4105
|
+
|
|
4106
|
+
const getSyncState = (
|
|
4107
|
+
pendingAttachmentBlobs?: IPendingBlobs,
|
|
4108
|
+
): IPendingRuntimeState | undefined => {
|
|
4109
|
+
const pending = this.pendingStateManager.getLocalState();
|
|
4110
|
+
if (pendingAttachmentBlobs === undefined && !this.hasPendingMessages()) {
|
|
4111
|
+
return; // no pending state to save
|
|
4112
|
+
}
|
|
3955
4113
|
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
4114
|
+
const pendingIdCompressorState = this._idCompressor?.serialize(true);
|
|
4115
|
+
|
|
4116
|
+
return {
|
|
4117
|
+
pending,
|
|
4118
|
+
pendingIdCompressorState,
|
|
4119
|
+
pendingAttachmentBlobs,
|
|
4120
|
+
sessionExpiryTimerStarted: this.garbageCollector.sessionExpiryTimerStarted,
|
|
4121
|
+
};
|
|
4122
|
+
};
|
|
4123
|
+
const perfEvent = {
|
|
4124
|
+
eventName: "getPendingLocalState",
|
|
4125
|
+
notifyImminentClosure: props?.notifyImminentClosure,
|
|
4126
|
+
};
|
|
4127
|
+
const logAndReturnPendingState = (
|
|
4128
|
+
event: PerformanceEvent,
|
|
4129
|
+
pendingState?: IPendingRuntimeState,
|
|
4130
|
+
) => {
|
|
4131
|
+
event.end({
|
|
4132
|
+
attachmentBlobsSize: Object.keys(pendingState?.pendingAttachmentBlobs ?? {}).length,
|
|
4133
|
+
pendingOpsSize: pendingState?.pending?.pendingStates.length,
|
|
4134
|
+
});
|
|
4135
|
+
return pendingState;
|
|
4136
|
+
};
|
|
4137
|
+
|
|
4138
|
+
// Flush pending batch.
|
|
4139
|
+
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
4140
|
+
// to close current batch.
|
|
4141
|
+
this.flush();
|
|
4142
|
+
|
|
4143
|
+
return props?.notifyImminentClosure === true
|
|
4144
|
+
? PerformanceEvent.timedExecAsync(this.mc.logger, perfEvent, async (event) =>
|
|
4145
|
+
logAndReturnPendingState(
|
|
4146
|
+
event,
|
|
4147
|
+
getSyncState(
|
|
4148
|
+
await this.blobManager.attachAndGetPendingBlobs(
|
|
4149
|
+
props?.stopBlobAttachingSignal,
|
|
4150
|
+
),
|
|
4151
|
+
),
|
|
4152
|
+
),
|
|
4153
|
+
)
|
|
4154
|
+
: PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) =>
|
|
4155
|
+
logAndReturnPendingState(event, getSyncState()),
|
|
4156
|
+
);
|
|
3968
4157
|
}
|
|
3969
4158
|
|
|
3970
4159
|
public summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults {
|