@fluidframework/container-runtime 2.0.0-dev-rc.1.0.0.232845 → 2.0.0-dev-rc.2.0.0.246488
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 +426 -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 +226 -0
- package/dist/channelCollection.d.ts.map +1 -0
- package/dist/{dataStores.js → channelCollection.js} +455 -150
- 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 +128 -48
- package/dist/container-runtime-beta.d.ts +67 -9
- package/dist/container-runtime-public.d.ts +67 -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 +522 -379
- 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/dataStoreRegistry.d.ts +4 -0
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +2 -2
- package/dist/dataStoreRegistry.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 +32 -18
- 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 +7 -4
- 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 +9 -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.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +12 -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 +226 -0
- package/lib/channelCollection.d.ts.map +1 -0
- package/lib/{dataStores.mjs → channelCollection.js} +442 -140
- 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} +128 -48
- package/lib/{container-runtime-beta.d.mts → container-runtime-beta.d.ts} +67 -9
- package/lib/{container-runtime-public.d.mts → container-runtime-public.d.ts} +67 -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} +444 -303
- 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} +5 -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} +24 -10
- 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} +7 -4
- 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} +7 -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} +6 -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} +629 -178
- package/src/connectionTelemetry.ts +42 -3
- package/src/containerHandleContext.ts +1 -1
- package/src/containerRuntime.ts +626 -430
- package/src/dataStore.ts +16 -15
- package/src/dataStoreContext.ts +376 -216
- package/src/dataStoreContexts.ts +2 -1
- package/src/dataStoreRegistry.ts +1 -0
- 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 +43 -16
- package/src/opLifecycle/remoteMessageProcessor.ts +10 -6
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +19 -13
- package/src/scheduleManager.ts +5 -4
- package/src/summary/index.ts +13 -12
- package/src/summary/orderedClientElection.ts +2 -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
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
+
|
|
5
6
|
import {
|
|
6
7
|
ITelemetryBaseLogger,
|
|
7
|
-
ITelemetryGenericEvent,
|
|
8
8
|
FluidObject,
|
|
9
9
|
IFluidHandle,
|
|
10
10
|
IFluidHandleContext,
|
|
@@ -21,7 +21,6 @@ import {
|
|
|
21
21
|
IRuntime,
|
|
22
22
|
ICriticalContainerError,
|
|
23
23
|
AttachState,
|
|
24
|
-
ILoaderOptions,
|
|
25
24
|
ILoader,
|
|
26
25
|
LoaderHeader,
|
|
27
26
|
IGetPendingLocalStateProps,
|
|
@@ -30,7 +29,7 @@ import {
|
|
|
30
29
|
IContainerRuntime,
|
|
31
30
|
IContainerRuntimeEvents,
|
|
32
31
|
} from "@fluidframework/container-runtime-definitions";
|
|
33
|
-
import { assert, delay, LazyPromise } from "@fluidframework/core-utils";
|
|
32
|
+
import { assert, Deferred, delay, LazyPromise, PromiseCache } from "@fluidframework/core-utils";
|
|
34
33
|
import { Trace, TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
35
34
|
import {
|
|
36
35
|
createChildLogger,
|
|
@@ -40,7 +39,6 @@ import {
|
|
|
40
39
|
GenericError,
|
|
41
40
|
raiseConnectedEvent,
|
|
42
41
|
PerformanceEvent,
|
|
43
|
-
// eslint-disable-next-line import/no-deprecated
|
|
44
42
|
TaggedLoggerAdapter,
|
|
45
43
|
MonitoringContext,
|
|
46
44
|
wrapError,
|
|
@@ -49,11 +47,14 @@ import {
|
|
|
49
47
|
LoggingError,
|
|
50
48
|
createSampledLogger,
|
|
51
49
|
IEventSampler,
|
|
50
|
+
type ITelemetryGenericEventExt,
|
|
51
|
+
loggerToMonitoringContext,
|
|
52
52
|
} from "@fluidframework/telemetry-utils";
|
|
53
53
|
import {
|
|
54
54
|
DriverHeader,
|
|
55
55
|
FetchSource,
|
|
56
56
|
IDocumentStorageService,
|
|
57
|
+
type ISnapshot,
|
|
57
58
|
} from "@fluidframework/driver-definitions";
|
|
58
59
|
import { readAndParse } from "@fluidframework/driver-utils";
|
|
59
60
|
import {
|
|
@@ -75,9 +76,7 @@ import {
|
|
|
75
76
|
InboundAttachMessage,
|
|
76
77
|
IFluidDataStoreContextDetached,
|
|
77
78
|
IFluidDataStoreRegistry,
|
|
78
|
-
IFluidDataStoreChannel,
|
|
79
79
|
IGarbageCollectionData,
|
|
80
|
-
IEnvelope,
|
|
81
80
|
IInboundSignalMessage,
|
|
82
81
|
NamedFluidDataStoreRegistryEntries,
|
|
83
82
|
ISummaryTreeWithStats,
|
|
@@ -87,18 +86,18 @@ import {
|
|
|
87
86
|
channelsTreeName,
|
|
88
87
|
IDataStore,
|
|
89
88
|
ITelemetryContext,
|
|
89
|
+
IEnvelope,
|
|
90
90
|
} from "@fluidframework/runtime-definitions";
|
|
91
91
|
import type {
|
|
92
92
|
SerializedIdCompressorWithNoSession,
|
|
93
93
|
IIdCompressor,
|
|
94
94
|
IIdCompressorCore,
|
|
95
|
-
IdCreationRange,
|
|
96
95
|
SerializedIdCompressorWithOngoingSession,
|
|
96
|
+
IdCreationRange,
|
|
97
97
|
} from "@fluidframework/id-compressor";
|
|
98
98
|
import {
|
|
99
99
|
addBlobToSummary,
|
|
100
100
|
addSummarizeResultToSummary,
|
|
101
|
-
addTreeToSummary,
|
|
102
101
|
RequestParser,
|
|
103
102
|
create404Response,
|
|
104
103
|
exceptionToResponse,
|
|
@@ -110,17 +109,17 @@ import {
|
|
|
110
109
|
responseToException,
|
|
111
110
|
} from "@fluidframework/runtime-utils";
|
|
112
111
|
import { v4 as uuid } from "uuid";
|
|
113
|
-
import { ContainerFluidHandleContext } from "./containerHandleContext";
|
|
114
|
-
import { FluidDataStoreRegistry } from "./dataStoreRegistry";
|
|
115
|
-
import { ReportOpPerfTelemetry, IPerfSignalReport } from "./connectionTelemetry";
|
|
112
|
+
import { ContainerFluidHandleContext } from "./containerHandleContext.js";
|
|
113
|
+
import { FluidDataStoreRegistry } from "./dataStoreRegistry.js";
|
|
114
|
+
import { ReportOpPerfTelemetry, IPerfSignalReport } from "./connectionTelemetry.js";
|
|
116
115
|
import {
|
|
117
116
|
IPendingBatchMessage,
|
|
118
117
|
IPendingLocalState,
|
|
119
118
|
PendingStateManager,
|
|
120
|
-
} from "./pendingStateManager";
|
|
121
|
-
import { pkgVersion } from "./packageVersion";
|
|
122
|
-
import { BlobManager, IBlobManagerLoadInfo, IPendingBlobs } from "./blobManager";
|
|
123
|
-
import {
|
|
119
|
+
} from "./pendingStateManager.js";
|
|
120
|
+
import { pkgVersion } from "./packageVersion.js";
|
|
121
|
+
import { BlobManager, IBlobManagerLoadInfo, IPendingBlobs } from "./blobManager.js";
|
|
122
|
+
import { ChannelCollection, getSummaryForDatastores, wrapContext } from "./channelCollection.js";
|
|
124
123
|
import {
|
|
125
124
|
aliasBlobName,
|
|
126
125
|
blobsTreeName,
|
|
@@ -160,8 +159,10 @@ import {
|
|
|
160
159
|
ISummarizerEvents,
|
|
161
160
|
IBaseSummarizeResult,
|
|
162
161
|
ISummarizer,
|
|
163
|
-
|
|
164
|
-
|
|
162
|
+
rootHasIsolatedChannels,
|
|
163
|
+
IdCompressorMode,
|
|
164
|
+
} from "./summary/index.js";
|
|
165
|
+
import { formExponentialFn, Throttler } from "./throttler.js";
|
|
165
166
|
import {
|
|
166
167
|
GarbageCollector,
|
|
167
168
|
GCNodeType,
|
|
@@ -169,11 +170,10 @@ import {
|
|
|
169
170
|
IGarbageCollector,
|
|
170
171
|
IGCRuntimeOptions,
|
|
171
172
|
IGCStats,
|
|
172
|
-
|
|
173
|
-
} from "./
|
|
174
|
-
import {
|
|
175
|
-
import {
|
|
176
|
-
import { ScheduleManager } from "./scheduleManager";
|
|
173
|
+
} from "./gc/index.js";
|
|
174
|
+
import { channelToDataStore } from "./dataStore.js";
|
|
175
|
+
import { BindBatchTracker } from "./batchTracker.js";
|
|
176
|
+
import { ScheduleManager } from "./scheduleManager.js";
|
|
177
177
|
import {
|
|
178
178
|
BatchMessage,
|
|
179
179
|
IBatch,
|
|
@@ -185,9 +185,9 @@ import {
|
|
|
185
185
|
RemoteMessageProcessor,
|
|
186
186
|
OpGroupingManager,
|
|
187
187
|
getLongStack,
|
|
188
|
-
} from "./opLifecycle";
|
|
189
|
-
import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy";
|
|
190
|
-
import { IBatchMetadata, IIdAllocationMetadata } from "./metadata";
|
|
188
|
+
} from "./opLifecycle/index.js";
|
|
189
|
+
import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy.js";
|
|
190
|
+
import { IBatchMetadata, IIdAllocationMetadata } from "./metadata.js";
|
|
191
191
|
import {
|
|
192
192
|
ContainerMessageType,
|
|
193
193
|
type InboundSequencedContainerRuntimeMessage,
|
|
@@ -197,7 +197,7 @@ import {
|
|
|
197
197
|
type OutboundContainerRuntimeMessage,
|
|
198
198
|
type UnknownContainerRuntimeMessage,
|
|
199
199
|
ContainerRuntimeGCMessage,
|
|
200
|
-
} from "./messageTypes";
|
|
200
|
+
} from "./messageTypes.js";
|
|
201
201
|
|
|
202
202
|
/**
|
|
203
203
|
* Utility to implement compat behaviors given an unknown message type
|
|
@@ -442,7 +442,7 @@ export interface IContainerRuntimeOptions {
|
|
|
442
442
|
* Enable the IdCompressor in the runtime.
|
|
443
443
|
* @experimental Not ready for use.
|
|
444
444
|
*/
|
|
445
|
-
readonly enableRuntimeIdCompressor?:
|
|
445
|
+
readonly enableRuntimeIdCompressor?: IdCompressorMode;
|
|
446
446
|
|
|
447
447
|
/**
|
|
448
448
|
* If enabled, the runtime will block all attempts to send an op inside the
|
|
@@ -467,27 +467,6 @@ export interface IContainerRuntimeOptions {
|
|
|
467
467
|
readonly enableGroupedBatching?: boolean;
|
|
468
468
|
}
|
|
469
469
|
|
|
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
470
|
/**
|
|
492
471
|
* Tombstone error responses will have this header set to true
|
|
493
472
|
* @alpha
|
|
@@ -501,6 +480,7 @@ export const InactiveResponseHeaderKey = "isInactive";
|
|
|
501
480
|
|
|
502
481
|
/**
|
|
503
482
|
* The full set of parsed header data that may be found on Runtime requests
|
|
483
|
+
* @internal
|
|
504
484
|
*/
|
|
505
485
|
export interface RuntimeHeaderData {
|
|
506
486
|
wait?: boolean;
|
|
@@ -554,6 +534,11 @@ export interface IPendingRuntimeState {
|
|
|
554
534
|
* Pending idCompressor state
|
|
555
535
|
*/
|
|
556
536
|
pendingIdCompressorState?: SerializedIdCompressorWithOngoingSession;
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Time at which session expiry timer started.
|
|
540
|
+
*/
|
|
541
|
+
sessionExpiryTimerStarted?: number | undefined;
|
|
557
542
|
}
|
|
558
543
|
|
|
559
544
|
const maxConsecutiveReconnectsKey = "Fluid.ContainerRuntime.MaxConsecutiveReconnects";
|
|
@@ -768,7 +753,6 @@ export class ContainerRuntime
|
|
|
768
753
|
const backCompatContext: IContainerContext | OldContainerContextWithLogger = context;
|
|
769
754
|
const passLogger =
|
|
770
755
|
backCompatContext.taggedLogger ??
|
|
771
|
-
// eslint-disable-next-line import/no-deprecated
|
|
772
756
|
new TaggedLoggerAdapter((backCompatContext as OldContainerContextWithLogger).logger);
|
|
773
757
|
const logger = createChildLogger({
|
|
774
758
|
logger: passLogger,
|
|
@@ -779,6 +763,8 @@ export class ContainerRuntime
|
|
|
779
763
|
},
|
|
780
764
|
});
|
|
781
765
|
|
|
766
|
+
const mc = loggerToMonitoringContext(logger);
|
|
767
|
+
|
|
782
768
|
const {
|
|
783
769
|
summaryOptions = {},
|
|
784
770
|
gcOptions = {},
|
|
@@ -786,7 +772,7 @@ export class ContainerRuntime
|
|
|
786
772
|
flushMode = defaultFlushMode,
|
|
787
773
|
compressionOptions = defaultCompressionConfig,
|
|
788
774
|
maxBatchSizeInBytes = defaultMaxBatchSizeInBytes,
|
|
789
|
-
enableRuntimeIdCompressor =
|
|
775
|
+
enableRuntimeIdCompressor = "off",
|
|
790
776
|
chunkSizeInBytes = defaultChunkSizeInBytes,
|
|
791
777
|
enableOpReentryCheck = false,
|
|
792
778
|
enableGroupedBatching = false,
|
|
@@ -855,10 +841,37 @@ export class ContainerRuntime
|
|
|
855
841
|
}
|
|
856
842
|
}
|
|
857
843
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
let
|
|
861
|
-
if (
|
|
844
|
+
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
845
|
+
// allow new containers to turn it on
|
|
846
|
+
let idCompressorMode: IdCompressorMode;
|
|
847
|
+
if (existing) {
|
|
848
|
+
// This setting has to be sticky for correctness:
|
|
849
|
+
// 1) if compressior is OFF, it can't be enabled, as already running clients (in given document session) do not know
|
|
850
|
+
// how to process compressor ops
|
|
851
|
+
// 2) if it's ON, then all sessions should load compressor right away
|
|
852
|
+
// 3) Same logic applies for "delayed" mode
|
|
853
|
+
// Maybe in the future we will need to enabled (and figure how to do it safely) "delayed" -> "on" change.
|
|
854
|
+
// We could do "off" -> "on" transtition too, if all clients start loading compressor (but not using it initially) and do so for a while -
|
|
855
|
+
// this will allow clients to eventually to disregard "off" setting (when it's safe so) and start using compressor in future sessions.
|
|
856
|
+
// Everyting is possible, but it needs to be designed and executed carefully, when such need arises.
|
|
857
|
+
idCompressorMode = metadata?.idCompressorMode ?? "off";
|
|
858
|
+
} else {
|
|
859
|
+
// FG overwrite
|
|
860
|
+
const enabled = mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled");
|
|
861
|
+
switch (enabled) {
|
|
862
|
+
case true:
|
|
863
|
+
idCompressorMode = "on";
|
|
864
|
+
break;
|
|
865
|
+
case false:
|
|
866
|
+
idCompressorMode = "off";
|
|
867
|
+
break;
|
|
868
|
+
default:
|
|
869
|
+
idCompressorMode = enableRuntimeIdCompressor;
|
|
870
|
+
break;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
const createIdCompressorFn = async () => {
|
|
862
875
|
const { createIdCompressor, deserializeIdCompressor, createSessionId } = await import(
|
|
863
876
|
"@fluidframework/id-compressor"
|
|
864
877
|
);
|
|
@@ -878,21 +891,22 @@ export class ContainerRuntime
|
|
|
878
891
|
|
|
879
892
|
const compressorLogger = createSampledLogger(logger, idCompressorEventSampler);
|
|
880
893
|
const pendingLocalState = context.pendingLocalState as IPendingRuntimeState;
|
|
894
|
+
|
|
881
895
|
if (pendingLocalState?.pendingIdCompressorState !== undefined) {
|
|
882
|
-
|
|
896
|
+
return deserializeIdCompressor(
|
|
883
897
|
pendingLocalState.pendingIdCompressorState,
|
|
884
898
|
compressorLogger,
|
|
885
899
|
);
|
|
886
900
|
} else if (serializedIdCompressor !== undefined) {
|
|
887
|
-
|
|
901
|
+
return deserializeIdCompressor(
|
|
888
902
|
serializedIdCompressor,
|
|
889
903
|
createSessionId(),
|
|
890
904
|
compressorLogger,
|
|
891
905
|
);
|
|
892
906
|
} else {
|
|
893
|
-
|
|
907
|
+
return createIdCompressor(compressorLogger);
|
|
894
908
|
}
|
|
895
|
-
}
|
|
909
|
+
};
|
|
896
910
|
|
|
897
911
|
const runtime = new containerRuntimeCtor(
|
|
898
912
|
context,
|
|
@@ -918,7 +932,8 @@ export class ContainerRuntime
|
|
|
918
932
|
existing,
|
|
919
933
|
blobManagerSnapshot,
|
|
920
934
|
context.storage,
|
|
921
|
-
|
|
935
|
+
createIdCompressorFn,
|
|
936
|
+
idCompressorMode,
|
|
922
937
|
provideEntryPoint,
|
|
923
938
|
requestHandler,
|
|
924
939
|
undefined, // summaryConfiguration
|
|
@@ -934,7 +949,7 @@ export class ContainerRuntime
|
|
|
934
949
|
return runtime;
|
|
935
950
|
}
|
|
936
951
|
|
|
937
|
-
public readonly options:
|
|
952
|
+
public readonly options: Record<string | number, any>;
|
|
938
953
|
private imminentClosure: boolean = false;
|
|
939
954
|
|
|
940
955
|
private readonly _getClientId: () => string | undefined;
|
|
@@ -948,6 +963,10 @@ export class ContainerRuntime
|
|
|
948
963
|
return this._storage;
|
|
949
964
|
}
|
|
950
965
|
|
|
966
|
+
public get containerRuntime() {
|
|
967
|
+
return this;
|
|
968
|
+
}
|
|
969
|
+
|
|
951
970
|
private readonly submitFn: (
|
|
952
971
|
type: MessageType,
|
|
953
972
|
contents: any,
|
|
@@ -985,7 +1004,47 @@ export class ContainerRuntime
|
|
|
985
1004
|
return this._getAttachState();
|
|
986
1005
|
}
|
|
987
1006
|
|
|
988
|
-
|
|
1007
|
+
private _idCompressor: (IIdCompressor & IIdCompressorCore) | undefined;
|
|
1008
|
+
|
|
1009
|
+
// We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
|
|
1010
|
+
// Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
|
|
1011
|
+
private pendingIdCompressorOps: IdCreationRange[] = [];
|
|
1012
|
+
|
|
1013
|
+
// Id Compressor serializes final state (see getPendingLocalState()). As result, it needs to skip all ops that preceeded that state
|
|
1014
|
+
// (such ops will be marked by Loader layer as savedOp === true)
|
|
1015
|
+
// That said, in "delayed" mode it's possible that Id Compressor was never initialized before getPendingLocalState() is called.
|
|
1016
|
+
// In such case we have to process all ops, including those marked with saveOp === true.
|
|
1017
|
+
private readonly skipSavedCompressorOps: boolean;
|
|
1018
|
+
|
|
1019
|
+
/**
|
|
1020
|
+
* See IContainerRuntimeBase.idCompressor() for details.
|
|
1021
|
+
*/
|
|
1022
|
+
public get idCompressor() {
|
|
1023
|
+
// Expose ID Compressor only if it's On from the start.
|
|
1024
|
+
// If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
|
|
1025
|
+
// That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
|
|
1026
|
+
// to reason over such things as session ID space.
|
|
1027
|
+
if (this.idCompressorMode === "on") {
|
|
1028
|
+
assert(
|
|
1029
|
+
this._idCompressor !== undefined,
|
|
1030
|
+
0x8ea /* compressor should have been loaded */,
|
|
1031
|
+
);
|
|
1032
|
+
return this._idCompressor;
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
/**
|
|
1037
|
+
* True if we have ID compressor loading in-flight (async operation). Useful only for
|
|
1038
|
+
* this.idCompressorMode === "delayed" mode
|
|
1039
|
+
*/
|
|
1040
|
+
protected compressorLoadInitiated = false;
|
|
1041
|
+
|
|
1042
|
+
/**
|
|
1043
|
+
* See IContainerRuntimeBase.generateDocumentUniqueId() for details.
|
|
1044
|
+
*/
|
|
1045
|
+
public generateDocumentUniqueId() {
|
|
1046
|
+
return this._idCompressor?.generateDocumentUniqueId() ?? uuid();
|
|
1047
|
+
}
|
|
989
1048
|
|
|
990
1049
|
public get IFluidHandleContext(): IFluidHandleContext {
|
|
991
1050
|
return this.handleContext;
|
|
@@ -1109,7 +1168,7 @@ export class ContainerRuntime
|
|
|
1109
1168
|
private readonly outbox: Outbox;
|
|
1110
1169
|
private readonly garbageCollector: IGarbageCollector;
|
|
1111
1170
|
|
|
1112
|
-
private readonly
|
|
1171
|
+
private readonly channelCollection: ChannelCollection;
|
|
1113
1172
|
private readonly remoteMessageProcessor: RemoteMessageProcessor;
|
|
1114
1173
|
|
|
1115
1174
|
/** The last message processed at the time of the last summary. */
|
|
@@ -1125,11 +1184,6 @@ export class ContainerRuntime
|
|
|
1125
1184
|
return this.summaryConfiguration.state === "disabled";
|
|
1126
1185
|
}
|
|
1127
1186
|
|
|
1128
|
-
private readonly heuristicsDisabled: boolean;
|
|
1129
|
-
private isHeuristicsDisabled(): boolean {
|
|
1130
|
-
return this.summaryConfiguration.state === "disableHeuristics";
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
1187
|
private readonly maxOpsSinceLastSummary: number;
|
|
1134
1188
|
private getMaxOpsSinceLastSummary(): number {
|
|
1135
1189
|
return this.summaryConfiguration.state !== "disabled"
|
|
@@ -1172,11 +1226,6 @@ export class ContainerRuntime
|
|
|
1172
1226
|
*/
|
|
1173
1227
|
private readonly telemetryDocumentId: string;
|
|
1174
1228
|
|
|
1175
|
-
/**
|
|
1176
|
-
* If true, the runtime has access to an IdCompressor
|
|
1177
|
-
*/
|
|
1178
|
-
private readonly idCompressorEnabled: boolean;
|
|
1179
|
-
|
|
1180
1229
|
/**
|
|
1181
1230
|
* Whether this client is the summarizer client itself (type is summarizerClientType)
|
|
1182
1231
|
*/
|
|
@@ -1187,11 +1236,19 @@ export class ContainerRuntime
|
|
|
1187
1236
|
*/
|
|
1188
1237
|
private readonly loadedFromVersionId: string | undefined;
|
|
1189
1238
|
|
|
1239
|
+
/**
|
|
1240
|
+
* It a cache for holding mapping for loading groupIds with its snapshot from the service. Add expiry policy of 1 minute.
|
|
1241
|
+
* Starting with 1 min and based on recorded usage we can tweak it later on.
|
|
1242
|
+
*/
|
|
1243
|
+
private readonly snapshotCacheForLoadingGroupIds = new PromiseCache<string, ISnapshot>({
|
|
1244
|
+
expiry: { policy: "absolute", durationMs: 60000 },
|
|
1245
|
+
});
|
|
1246
|
+
|
|
1190
1247
|
/***/
|
|
1191
1248
|
protected constructor(
|
|
1192
1249
|
context: IContainerContext,
|
|
1193
1250
|
private readonly registry: IFluidDataStoreRegistry,
|
|
1194
|
-
metadata: IContainerRuntimeMetadata | undefined,
|
|
1251
|
+
private readonly metadata: IContainerRuntimeMetadata | undefined,
|
|
1195
1252
|
electedSummarizerData: ISerializedElection | undefined,
|
|
1196
1253
|
chunks: [string, string[]][],
|
|
1197
1254
|
dataStoreAliasMap: [string, string][],
|
|
@@ -1201,7 +1258,8 @@ export class ContainerRuntime
|
|
|
1201
1258
|
existing: boolean,
|
|
1202
1259
|
blobManagerSnapshot: IBlobManagerLoadInfo,
|
|
1203
1260
|
private readonly _storage: IDocumentStorageService,
|
|
1204
|
-
|
|
1261
|
+
private readonly createIdCompressor: () => Promise<IIdCompressor & IIdCompressorCore>,
|
|
1262
|
+
private readonly idCompressorMode: IdCompressorMode,
|
|
1205
1263
|
provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>,
|
|
1206
1264
|
private readonly requestHandler?: (
|
|
1207
1265
|
request: IRequest,
|
|
@@ -1245,7 +1303,9 @@ export class ContainerRuntime
|
|
|
1245
1303
|
this.submitSummaryFn = submitSummaryFn;
|
|
1246
1304
|
this.submitSignalFn = submitSignalFn;
|
|
1247
1305
|
|
|
1248
|
-
|
|
1306
|
+
// TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
|
|
1307
|
+
// Values are generally expected to be set from the runtime side.
|
|
1308
|
+
this.options = options ?? {};
|
|
1249
1309
|
this.clientDetails = clientDetails;
|
|
1250
1310
|
this.isSummarizerClient = this.clientDetails.type === summarizerClientType;
|
|
1251
1311
|
this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
|
|
@@ -1286,20 +1346,12 @@ export class ContainerRuntime
|
|
|
1286
1346
|
// summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
|
|
1287
1347
|
// the count is reset to 0.
|
|
1288
1348
|
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
1349
|
} else {
|
|
1294
1350
|
this.createContainerMetadata = {
|
|
1295
1351
|
createContainerRuntimeVersion: pkgVersion,
|
|
1296
1352
|
createContainerTimestamp: Date.now(),
|
|
1297
1353
|
};
|
|
1298
1354
|
loadSummaryNumber = 0;
|
|
1299
|
-
|
|
1300
|
-
this.idCompressorEnabled =
|
|
1301
|
-
this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled") ??
|
|
1302
|
-
idCompressor !== undefined;
|
|
1303
1355
|
}
|
|
1304
1356
|
this.nextSummaryNumber = loadSummaryNumber + 1;
|
|
1305
1357
|
|
|
@@ -1367,14 +1419,9 @@ export class ContainerRuntime
|
|
|
1367
1419
|
disableOpReentryCheck !== true;
|
|
1368
1420
|
|
|
1369
1421
|
this.summariesDisabled = this.isSummariesDisabled();
|
|
1370
|
-
this.heuristicsDisabled = this.isHeuristicsDisabled();
|
|
1371
1422
|
this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
|
|
1372
1423
|
this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
|
|
1373
1424
|
|
|
1374
|
-
if (this.idCompressorEnabled) {
|
|
1375
|
-
this.idCompressor = idCompressor;
|
|
1376
|
-
}
|
|
1377
|
-
|
|
1378
1425
|
this.maxConsecutiveReconnects =
|
|
1379
1426
|
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
|
|
1380
1427
|
this.defaultMaxConsecutiveReconnects;
|
|
@@ -1418,6 +1465,7 @@ export class ContainerRuntime
|
|
|
1418
1465
|
getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
|
|
1419
1466
|
readAndParseBlob: async <T>(id: string) => readAndParse<T>(this.storage, id),
|
|
1420
1467
|
submitMessage: (message: ContainerRuntimeGCMessage) => this.submit(message),
|
|
1468
|
+
sessionExpiryTimerStarted: pendingRuntimeState?.sessionExpiryTimerStarted,
|
|
1421
1469
|
});
|
|
1422
1470
|
|
|
1423
1471
|
const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
|
|
@@ -1447,28 +1495,44 @@ export class ContainerRuntime
|
|
|
1447
1495
|
this.summarizerNode.updateBaseSummaryState(baseSnapshot);
|
|
1448
1496
|
}
|
|
1449
1497
|
|
|
1450
|
-
|
|
1498
|
+
const parentContext = wrapContext(this);
|
|
1499
|
+
|
|
1500
|
+
// Due to a mismatch between different layers in terms of
|
|
1501
|
+
// what is the interface of passing signals, we need the
|
|
1502
|
+
// downstream stores to wrap the signal.
|
|
1503
|
+
parentContext.submitSignal = (type: string, content: any, targetClientId?: string) => {
|
|
1504
|
+
const envelope1 = content as IEnvelope;
|
|
1505
|
+
const envelope2 = this.createNewSignalEnvelope(
|
|
1506
|
+
envelope1.address,
|
|
1507
|
+
type,
|
|
1508
|
+
envelope1.contents,
|
|
1509
|
+
);
|
|
1510
|
+
return this.submitSignalFn(envelope2, targetClientId);
|
|
1511
|
+
};
|
|
1512
|
+
|
|
1513
|
+
this.channelCollection = new ChannelCollection(
|
|
1451
1514
|
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),
|
|
1515
|
+
parentContext,
|
|
1467
1516
|
this.mc.logger,
|
|
1468
|
-
(
|
|
1469
|
-
|
|
1517
|
+
(
|
|
1518
|
+
path: string,
|
|
1519
|
+
reason: "Loaded" | "Changed",
|
|
1520
|
+
timestampMs?: number,
|
|
1521
|
+
packagePath?: readonly string[],
|
|
1522
|
+
request?: IRequest,
|
|
1523
|
+
headerData?: RuntimeHeaderData,
|
|
1524
|
+
) =>
|
|
1525
|
+
this.garbageCollector.nodeUpdated(
|
|
1526
|
+
path,
|
|
1527
|
+
reason,
|
|
1528
|
+
timestampMs,
|
|
1529
|
+
packagePath,
|
|
1530
|
+
request,
|
|
1531
|
+
headerData,
|
|
1532
|
+
),
|
|
1470
1533
|
(path: string) => this.garbageCollector.isNodeDeleted(path),
|
|
1471
1534
|
new Map<string, string>(dataStoreAliasMap),
|
|
1535
|
+
async (runtime: ChannelCollection) => provideEntryPoint,
|
|
1472
1536
|
);
|
|
1473
1537
|
|
|
1474
1538
|
this.blobManager = new BlobManager(
|
|
@@ -1507,9 +1571,13 @@ export class ContainerRuntime
|
|
|
1507
1571
|
clientId: () => this.clientId,
|
|
1508
1572
|
close: this.closeFn,
|
|
1509
1573
|
connected: () => this.connected,
|
|
1510
|
-
reSubmit:
|
|
1574
|
+
reSubmit: (message: IPendingBatchMessage) => {
|
|
1575
|
+
this.reSubmit(message);
|
|
1576
|
+
this.flush();
|
|
1577
|
+
},
|
|
1511
1578
|
reSubmitBatch: this.reSubmitBatch.bind(this),
|
|
1512
1579
|
isActiveConnection: () => this.innerDeltaManager.active,
|
|
1580
|
+
isAttached: () => this.attachState !== AttachState.Detached,
|
|
1513
1581
|
},
|
|
1514
1582
|
pendingRuntimeState?.pending,
|
|
1515
1583
|
this.logger,
|
|
@@ -1656,7 +1724,6 @@ export class ContainerRuntime
|
|
|
1656
1724
|
{
|
|
1657
1725
|
initialDelayMs: this.initialSummarizerDelayMs,
|
|
1658
1726
|
},
|
|
1659
|
-
this.heuristicsDisabled,
|
|
1660
1727
|
);
|
|
1661
1728
|
this.summaryManager.on("summarize", (eventProps) => {
|
|
1662
1729
|
this.emit("summarize", eventProps);
|
|
@@ -1674,26 +1741,27 @@ export class ContainerRuntime
|
|
|
1674
1741
|
this.mc.logger.sendTelemetryEvent({
|
|
1675
1742
|
eventName: "ContainerLoadStats",
|
|
1676
1743
|
...this.createContainerMetadata,
|
|
1677
|
-
...this.
|
|
1744
|
+
...this.channelCollection.containerLoadStats,
|
|
1678
1745
|
summaryNumber: loadSummaryNumber,
|
|
1679
1746
|
summaryFormatVersion: metadata?.summaryFormatVersion,
|
|
1680
1747
|
disableIsolatedChannels: metadata?.disableIsolatedChannels,
|
|
1681
1748
|
gcVersion: metadata?.gcFeature,
|
|
1682
1749
|
options: JSON.stringify(runtimeOptions),
|
|
1750
|
+
idCompressorModeMetadata: metadata?.idCompressorMode,
|
|
1751
|
+
idCompressorMode: this.idCompressorMode,
|
|
1683
1752
|
featureGates: JSON.stringify({
|
|
1684
1753
|
disableCompression,
|
|
1685
1754
|
disableOpReentryCheck,
|
|
1686
1755
|
disableChunking,
|
|
1687
1756
|
disableAttachReorder: this.disableAttachReorder,
|
|
1688
1757
|
disablePartialFlush,
|
|
1689
|
-
idCompressorEnabled: this.idCompressorEnabled,
|
|
1690
1758
|
closeSummarizerDelayOverride,
|
|
1691
1759
|
}),
|
|
1692
1760
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
1693
1761
|
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
1694
1762
|
});
|
|
1695
1763
|
|
|
1696
|
-
ReportOpPerfTelemetry(this.clientId, this.deltaManager, this.logger);
|
|
1764
|
+
ReportOpPerfTelemetry(this.clientId, this.deltaManager, this, this.logger);
|
|
1697
1765
|
BindBatchTracker(this, this.logger);
|
|
1698
1766
|
|
|
1699
1767
|
this.entryPoint = new LazyPromise(async () => {
|
|
@@ -1706,12 +1774,52 @@ export class ContainerRuntime
|
|
|
1706
1774
|
}
|
|
1707
1775
|
return provideEntryPoint(this);
|
|
1708
1776
|
});
|
|
1777
|
+
|
|
1778
|
+
// If we loaded from pending state, then we need to skip any ops that are already accounted in such
|
|
1779
|
+
// saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
|
|
1780
|
+
this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
public getCreateChildSummarizerNodeFn(id: string, createParam: CreateChildSummarizerNodeParam) {
|
|
1784
|
+
return (
|
|
1785
|
+
summarizeInternal: SummarizeInternalFn,
|
|
1786
|
+
getGCDataFn: (fullGC?: boolean) => Promise<IGarbageCollectionData>,
|
|
1787
|
+
) =>
|
|
1788
|
+
this.summarizerNode.createChild(
|
|
1789
|
+
summarizeInternal,
|
|
1790
|
+
id,
|
|
1791
|
+
createParam,
|
|
1792
|
+
undefined,
|
|
1793
|
+
getGCDataFn,
|
|
1794
|
+
);
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
public deleteChildSummarizerNode(id: string) {
|
|
1798
|
+
return this.summarizerNode.deleteChild(id);
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
/* IFluidParentContext APIs that should not be called on Root */
|
|
1802
|
+
public makeLocallyVisible() {
|
|
1803
|
+
assert(false, 0x8eb /* should not be called */);
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
public setChannelDirty(address: string) {
|
|
1807
|
+
assert(false, 0x909 /* should not be called */);
|
|
1709
1808
|
}
|
|
1710
1809
|
|
|
1711
1810
|
/**
|
|
1712
1811
|
* Initializes the state from the base snapshot this container runtime loaded from.
|
|
1713
1812
|
*/
|
|
1714
1813
|
private async initializeBaseState(): Promise<void> {
|
|
1814
|
+
if (
|
|
1815
|
+
this.idCompressorMode === "on" ||
|
|
1816
|
+
(this.idCompressorMode === "delayed" && this.connected)
|
|
1817
|
+
) {
|
|
1818
|
+
// This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
|
|
1819
|
+
assert(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
|
|
1820
|
+
this._idCompressor = await this.createIdCompressor();
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1715
1823
|
await this.garbageCollector.initializeBaseState();
|
|
1716
1824
|
}
|
|
1717
1825
|
|
|
@@ -1736,12 +1844,145 @@ export class ContainerRuntime
|
|
|
1736
1844
|
}
|
|
1737
1845
|
this.garbageCollector.dispose();
|
|
1738
1846
|
this._summarizer?.dispose();
|
|
1739
|
-
this.
|
|
1847
|
+
this.channelCollection.dispose();
|
|
1740
1848
|
this.pendingStateManager.dispose();
|
|
1741
1849
|
this.emit("dispose");
|
|
1742
1850
|
this.removeAllListeners();
|
|
1743
1851
|
}
|
|
1744
1852
|
|
|
1853
|
+
/**
|
|
1854
|
+
* Api to fetch the snapshot from the service for a loadingGroupIds.
|
|
1855
|
+
* @param loadingGroupIds - LoadingGroupId for which the snapshot is asked for.
|
|
1856
|
+
* @param pathParts - Parts of the path, which we want to extract from the snapshot tree.
|
|
1857
|
+
* @returns - snapshotTree and the sequence number of the snapshot.
|
|
1858
|
+
*/
|
|
1859
|
+
public async getSnapshotForLoadingGroupId(
|
|
1860
|
+
loadingGroupIds: string[],
|
|
1861
|
+
pathParts: string[],
|
|
1862
|
+
): Promise<{ snapshotTree: ISnapshotTree; sequenceNumber: number }> {
|
|
1863
|
+
const sortedLoadingGroupIds = loadingGroupIds.sort();
|
|
1864
|
+
assert(
|
|
1865
|
+
this.storage.getSnapshot !== undefined,
|
|
1866
|
+
0x8ed /* getSnapshot api should be defined if used */,
|
|
1867
|
+
);
|
|
1868
|
+
let loadedFromCache = true;
|
|
1869
|
+
// Lookup up in the cache, if not present then make the network call as multiple datastores could
|
|
1870
|
+
// be in same loading group. So, once we have fetched the snapshot for that loading group on
|
|
1871
|
+
// any request, then cache that as same group could be requested in future too.
|
|
1872
|
+
const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(
|
|
1873
|
+
sortedLoadingGroupIds.join(),
|
|
1874
|
+
async () => {
|
|
1875
|
+
assert(
|
|
1876
|
+
this.storage.getSnapshot !== undefined,
|
|
1877
|
+
0x8ee /* getSnapshot api should be defined if used */,
|
|
1878
|
+
);
|
|
1879
|
+
loadedFromCache = false;
|
|
1880
|
+
return this.storage.getSnapshot({
|
|
1881
|
+
cacheSnapshot: false,
|
|
1882
|
+
scenarioName: "snapshotForLoadingGroupId",
|
|
1883
|
+
loadingGroupIds: sortedLoadingGroupIds,
|
|
1884
|
+
});
|
|
1885
|
+
},
|
|
1886
|
+
);
|
|
1887
|
+
|
|
1888
|
+
this.logger.sendTelemetryEvent({
|
|
1889
|
+
eventName: "GroupIdSnapshotFetched",
|
|
1890
|
+
details: JSON.stringify({
|
|
1891
|
+
fromCache: loadedFromCache,
|
|
1892
|
+
loadingGroupIds: loadingGroupIds.join(","),
|
|
1893
|
+
}),
|
|
1894
|
+
});
|
|
1895
|
+
// Find the snapshotTree inside the returned snapshot based on the path as given in the request.
|
|
1896
|
+
const hasIsolatedChannels = rootHasIsolatedChannels(this.metadata);
|
|
1897
|
+
const snapshotTreeForPath = this.getSnapshotTreeForPath(
|
|
1898
|
+
snapshot.snapshotTree,
|
|
1899
|
+
pathParts,
|
|
1900
|
+
hasIsolatedChannels,
|
|
1901
|
+
);
|
|
1902
|
+
assert(snapshotTreeForPath !== undefined, 0x8ef /* no snapshotTree for the path */);
|
|
1903
|
+
const snapshotSeqNumber = snapshot.sequenceNumber;
|
|
1904
|
+
assert(snapshotSeqNumber !== undefined, 0x8f0 /* snapshotSeqNumber should be present */);
|
|
1905
|
+
|
|
1906
|
+
// This assert fires if we get a snapshot older than the snapshot we loaded from. This is a service issue.
|
|
1907
|
+
// Snapshots should only move forward. If we observe an older snapshot than the one we loaded from, then likely
|
|
1908
|
+
// the file has been overwritten or service lost data.
|
|
1909
|
+
if (snapshotSeqNumber < this.deltaManager.initialSequenceNumber) {
|
|
1910
|
+
throw DataProcessingError.create(
|
|
1911
|
+
"Downloaded snapshot older than snapshot we loaded from",
|
|
1912
|
+
"getSnapshotForLoadingGroupId",
|
|
1913
|
+
undefined,
|
|
1914
|
+
{
|
|
1915
|
+
loadingGroupIds: sortedLoadingGroupIds.join(","),
|
|
1916
|
+
snapshotSeqNumber,
|
|
1917
|
+
initialSequenceNumber: this.deltaManager.initialSequenceNumber,
|
|
1918
|
+
},
|
|
1919
|
+
);
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
// If the snapshot is ahead of the last seq number of the delta manager, then catch up before
|
|
1923
|
+
// returning the snapshot.
|
|
1924
|
+
if (snapshotSeqNumber > this.deltaManager.lastSequenceNumber) {
|
|
1925
|
+
// If this is a summarizer client, which is trying to load a group and it finds that there is
|
|
1926
|
+
// another snapshot from which the summarizer loaded and it is behind, then just give up as
|
|
1927
|
+
// the summarizer state is not up to date.
|
|
1928
|
+
// This should be a recoverable scenario and shouldn't happen as we should process the ack first.
|
|
1929
|
+
if (this.isSummarizerClient) {
|
|
1930
|
+
throw new Error(
|
|
1931
|
+
"Summarizer client behind, loaded newer snapshot with loadingGroupId",
|
|
1932
|
+
);
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
// We want to catchup from sequenceNumber to targetSequenceNumber
|
|
1936
|
+
const props: ITelemetryGenericEventExt = {
|
|
1937
|
+
eventName: "GroupIdSnapshotCatchup",
|
|
1938
|
+
loadingGroupIds: sortedLoadingGroupIds.join(","),
|
|
1939
|
+
targetSequenceNumber: snapshotSeqNumber, // This is so we reuse some columns in telemetry
|
|
1940
|
+
sequenceNumber: this.deltaManager.lastSequenceNumber, // This is so we reuse some columns in telemetry
|
|
1941
|
+
};
|
|
1942
|
+
|
|
1943
|
+
const event = PerformanceEvent.start(this.mc.logger, {
|
|
1944
|
+
...props,
|
|
1945
|
+
});
|
|
1946
|
+
// If the inbound deltas queue is paused or disconnected, we expect a reconnect and unpause
|
|
1947
|
+
// as long as it's not a summarizer client.
|
|
1948
|
+
if (this.deltaManager.inbound.paused) {
|
|
1949
|
+
props.inboundPaused = this.deltaManager.inbound.paused; // reusing telemetry
|
|
1950
|
+
}
|
|
1951
|
+
const defP = new Deferred<boolean>();
|
|
1952
|
+
this.deltaManager.on("op", (message: ISequencedDocumentMessage) => {
|
|
1953
|
+
if (message.sequenceNumber >= snapshotSeqNumber) {
|
|
1954
|
+
defP.resolve(true);
|
|
1955
|
+
}
|
|
1956
|
+
});
|
|
1957
|
+
await defP.promise;
|
|
1958
|
+
event.end(props);
|
|
1959
|
+
}
|
|
1960
|
+
return { snapshotTree: snapshotTreeForPath, sequenceNumber: snapshotSeqNumber };
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
/**
|
|
1964
|
+
* Api to find a snapshot tree inside a bigger snapshot tree based on the path in the pathParts array.
|
|
1965
|
+
* @param snapshotTree - snapshot tree to look into.
|
|
1966
|
+
* @param pathParts - Part of the path, which we want to extract from the snapshot tree.
|
|
1967
|
+
* @param hasIsolatedChannels - whether the channels are present inside ".channels" subtree. Older
|
|
1968
|
+
* snapshots will not have trees inside ".channels", so check that.
|
|
1969
|
+
* @returns - requested snapshot tree based on the path parts.
|
|
1970
|
+
*/
|
|
1971
|
+
private getSnapshotTreeForPath(
|
|
1972
|
+
snapshotTree: ISnapshotTree,
|
|
1973
|
+
pathParts: string[],
|
|
1974
|
+
hasIsolatedChannels: boolean,
|
|
1975
|
+
): ISnapshotTree | undefined {
|
|
1976
|
+
let childTree = snapshotTree;
|
|
1977
|
+
for (const part of pathParts) {
|
|
1978
|
+
if (hasIsolatedChannels) {
|
|
1979
|
+
childTree = childTree?.trees[channelsTreeName];
|
|
1980
|
+
}
|
|
1981
|
+
childTree = childTree?.trees[part];
|
|
1982
|
+
}
|
|
1983
|
+
return childTree;
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1745
1986
|
/**
|
|
1746
1987
|
* Notifies this object about the request made to the container.
|
|
1747
1988
|
* @param request - Request made to the handler.
|
|
@@ -1798,19 +2039,7 @@ export class ContainerRuntime
|
|
|
1798
2039
|
}
|
|
1799
2040
|
: create404Response(request);
|
|
1800
2041
|
} 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);
|
|
2042
|
+
return await this.channelCollection.request(request);
|
|
1814
2043
|
}
|
|
1815
2044
|
|
|
1816
2045
|
return create404Response(request);
|
|
@@ -1828,54 +2057,7 @@ export class ContainerRuntime
|
|
|
1828
2057
|
private readonly entryPoint: LazyPromise<FluidObject>;
|
|
1829
2058
|
|
|
1830
2059
|
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();
|
|
2060
|
+
return this.channelCollection.internalId(maybeAlias);
|
|
1879
2061
|
}
|
|
1880
2062
|
|
|
1881
2063
|
/** Adds the container's metadata to the given summary tree. */
|
|
@@ -1892,7 +2074,7 @@ export class ContainerRuntime
|
|
|
1892
2074
|
extractSummaryMetadataMessage(this.deltaManager.lastMessage) ??
|
|
1893
2075
|
this.messageAtLastSummary,
|
|
1894
2076
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
1895
|
-
|
|
2077
|
+
idCompressorMode: this.idCompressorMode,
|
|
1896
2078
|
};
|
|
1897
2079
|
addBlobToSummary(summaryTree, metadataBlobName, JSON.stringify(metadata));
|
|
1898
2080
|
}
|
|
@@ -1905,12 +2087,8 @@ export class ContainerRuntime
|
|
|
1905
2087
|
) {
|
|
1906
2088
|
this.addMetadataToSummary(summaryTree);
|
|
1907
2089
|
|
|
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));
|
|
2090
|
+
if (this._idCompressor) {
|
|
2091
|
+
const idCompressorState = JSON.stringify(this._idCompressor.serialize(false));
|
|
1914
2092
|
addBlobToSummary(summaryTree, idCompressorBlobName, idCompressorState);
|
|
1915
2093
|
}
|
|
1916
2094
|
|
|
@@ -1919,7 +2097,7 @@ export class ContainerRuntime
|
|
|
1919
2097
|
addBlobToSummary(summaryTree, chunksBlobName, content);
|
|
1920
2098
|
}
|
|
1921
2099
|
|
|
1922
|
-
const dataStoreAliases = this.
|
|
2100
|
+
const dataStoreAliases = this.channelCollection.aliases;
|
|
1923
2101
|
if (dataStoreAliases.size > 0) {
|
|
1924
2102
|
addBlobToSummary(summaryTree, aliasBlobName, JSON.stringify([...dataStoreAliases]));
|
|
1925
2103
|
}
|
|
@@ -1935,7 +2113,7 @@ export class ContainerRuntime
|
|
|
1935
2113
|
// Some storage (like git) doesn't allow empty tree, so we can omit it.
|
|
1936
2114
|
// and the blob manager can handle the tree not existing when loading
|
|
1937
2115
|
if (Object.keys(blobManagerSummary.summary.tree).length > 0) {
|
|
1938
|
-
|
|
2116
|
+
addSummarizeResultToSummary(summaryTree, blobsTreeName, blobManagerSummary);
|
|
1939
2117
|
}
|
|
1940
2118
|
|
|
1941
2119
|
const gcSummary = this.garbageCollector.summarize(fullTree, trackState, telemetryContext);
|
|
@@ -1976,14 +2154,8 @@ export class ContainerRuntime
|
|
|
1976
2154
|
return this.consecutiveReconnects < this.maxConsecutiveReconnects;
|
|
1977
2155
|
}
|
|
1978
2156
|
|
|
1979
|
-
private resetReconnectCount(
|
|
1980
|
-
|
|
1981
|
-
// in their own batches before the originating batch is sent.
|
|
1982
|
-
// Therefore, receiving them while attempting to send the originating batch
|
|
1983
|
-
// does not mean that the container is making any progress.
|
|
1984
|
-
if (message?.type !== ContainerMessageType.ChunkedOp) {
|
|
1985
|
-
this.consecutiveReconnects = 0;
|
|
1986
|
-
}
|
|
2157
|
+
private resetReconnectCount() {
|
|
2158
|
+
this.consecutiveReconnects = 0;
|
|
1987
2159
|
}
|
|
1988
2160
|
|
|
1989
2161
|
private replayPendingStates() {
|
|
@@ -2035,16 +2207,12 @@ export class ContainerRuntime
|
|
|
2035
2207
|
const opContents = this.parseLocalOpContent(serializedOpContent);
|
|
2036
2208
|
switch (opContents.type) {
|
|
2037
2209
|
case ContainerMessageType.FluidDataStoreOp:
|
|
2038
|
-
return this.dataStores.applyStashedOp(opContents.contents);
|
|
2039
2210
|
case ContainerMessageType.Attach:
|
|
2040
|
-
|
|
2211
|
+
case ContainerMessageType.Alias:
|
|
2212
|
+
return this.channelCollection.applyStashedOp(opContents);
|
|
2041
2213
|
case ContainerMessageType.IdAllocation:
|
|
2042
|
-
assert(
|
|
2043
|
-
this.idCompressor !== undefined,
|
|
2044
|
-
0x67b /* IdCompressor should be defined if enabled */,
|
|
2045
|
-
);
|
|
2214
|
+
assert(this.idCompressorMode !== "off", 0x8f1 /* ID compressor should be in use */);
|
|
2046
2215
|
return;
|
|
2047
|
-
case ContainerMessageType.Alias:
|
|
2048
2216
|
case ContainerMessageType.BlobAttach:
|
|
2049
2217
|
return;
|
|
2050
2218
|
case ContainerMessageType.ChunkedOp:
|
|
@@ -2081,6 +2249,20 @@ export class ContainerRuntime
|
|
|
2081
2249
|
}
|
|
2082
2250
|
|
|
2083
2251
|
public setConnectionState(connected: boolean, clientId?: string) {
|
|
2252
|
+
if (connected && this.idCompressorMode === "delayed" && !this.compressorLoadInitiated) {
|
|
2253
|
+
this.compressorLoadInitiated = true;
|
|
2254
|
+
this.createIdCompressor()
|
|
2255
|
+
.then((compressor) => {
|
|
2256
|
+
this._idCompressor = compressor;
|
|
2257
|
+
for (const range of this.pendingIdCompressorOps) {
|
|
2258
|
+
this._idCompressor.finalizeCreationRange(range);
|
|
2259
|
+
}
|
|
2260
|
+
this.pendingIdCompressorOps = [];
|
|
2261
|
+
})
|
|
2262
|
+
.catch((error) => {
|
|
2263
|
+
this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
|
|
2264
|
+
});
|
|
2265
|
+
}
|
|
2084
2266
|
if (connected === false && this.delayConnectClientId !== undefined) {
|
|
2085
2267
|
this.delayConnectClientId = undefined;
|
|
2086
2268
|
this.mc.logger.sendTelemetryEvent({
|
|
@@ -2173,7 +2355,7 @@ export class ContainerRuntime
|
|
|
2173
2355
|
this.replayPendingStates();
|
|
2174
2356
|
}
|
|
2175
2357
|
|
|
2176
|
-
this.
|
|
2358
|
+
this.channelCollection.setConnectionState(connected, clientId);
|
|
2177
2359
|
this.garbageCollector.setConnectionState(connected, clientId);
|
|
2178
2360
|
|
|
2179
2361
|
raiseConnectedEvent(this.mc.logger, this, connected, clientId);
|
|
@@ -2229,12 +2411,17 @@ export class ContainerRuntime
|
|
|
2229
2411
|
this._processedClientSequenceNumber = message.clientSequenceNumber;
|
|
2230
2412
|
|
|
2231
2413
|
try {
|
|
2414
|
+
// See commit that added this assert for more details.
|
|
2415
|
+
// These calls should be made for all but chunked ops:
|
|
2416
|
+
// 1) this.pendingStateManager.processPendingLocalMessage() below
|
|
2417
|
+
// 2) this.resetReconnectCount() below
|
|
2418
|
+
assert(
|
|
2419
|
+
message.type !== ContainerMessageType.ChunkedOp,
|
|
2420
|
+
"we should never get here with chunked ops",
|
|
2421
|
+
);
|
|
2422
|
+
|
|
2232
2423
|
let localOpMetadata: unknown;
|
|
2233
|
-
if (
|
|
2234
|
-
local &&
|
|
2235
|
-
messageWithContext.modernRuntimeMessage &&
|
|
2236
|
-
message.type !== ContainerMessageType.ChunkedOp
|
|
2237
|
-
) {
|
|
2424
|
+
if (local && messageWithContext.modernRuntimeMessage) {
|
|
2238
2425
|
localOpMetadata = this.pendingStateManager.processPendingLocalMessage(
|
|
2239
2426
|
messageWithContext.message,
|
|
2240
2427
|
);
|
|
@@ -2256,7 +2443,7 @@ export class ContainerRuntime
|
|
|
2256
2443
|
// If we have processed a local op, this means that the container is
|
|
2257
2444
|
// making progress and we can reset the counter for how many times
|
|
2258
2445
|
// we have consecutively replayed the pending states
|
|
2259
|
-
this.resetReconnectCount(
|
|
2446
|
+
this.resetReconnectCount();
|
|
2260
2447
|
}
|
|
2261
2448
|
} catch (e) {
|
|
2262
2449
|
this.scheduleManager.afterOpProcessing(e, message);
|
|
@@ -2276,17 +2463,9 @@ export class ContainerRuntime
|
|
|
2276
2463
|
const { local } = messageWithContext;
|
|
2277
2464
|
switch (messageWithContext.message.type) {
|
|
2278
2465
|
case ContainerMessageType.Attach:
|
|
2279
|
-
this.dataStores.processAttachMessage(messageWithContext.message, local);
|
|
2280
|
-
break;
|
|
2281
2466
|
case ContainerMessageType.Alias:
|
|
2282
|
-
this.dataStores.processAliasMessage(
|
|
2283
|
-
messageWithContext.message,
|
|
2284
|
-
localOpMetadata,
|
|
2285
|
-
local,
|
|
2286
|
-
);
|
|
2287
|
-
break;
|
|
2288
2467
|
case ContainerMessageType.FluidDataStoreOp:
|
|
2289
|
-
this.
|
|
2468
|
+
this.channelCollection.process(
|
|
2290
2469
|
messageWithContext.message,
|
|
2291
2470
|
local,
|
|
2292
2471
|
localOpMetadata,
|
|
@@ -2297,23 +2476,32 @@ export class ContainerRuntime
|
|
|
2297
2476
|
this.blobManager.processBlobAttachOp(messageWithContext.message, local);
|
|
2298
2477
|
break;
|
|
2299
2478
|
case ContainerMessageType.IdAllocation:
|
|
2300
|
-
assert(
|
|
2301
|
-
this.idCompressor !== undefined,
|
|
2302
|
-
0x67c /* IdCompressor should be defined if enabled */,
|
|
2303
|
-
);
|
|
2304
|
-
|
|
2305
2479
|
// Don't re-finalize the range if we're processing a "savedOp" in
|
|
2306
2480
|
// stashed ops flow. The compressor is stashed with these ops already processed.
|
|
2481
|
+
// That said, in idCompressorMode === "delayed", we might not serialize ID compressor, and
|
|
2482
|
+
// thus we need to process all the ops.
|
|
2307
2483
|
if (
|
|
2308
|
-
(
|
|
2484
|
+
!(
|
|
2485
|
+
this.skipSavedCompressorOps &&
|
|
2486
|
+
(messageWithContext.message.metadata as IIdAllocationMetadata)?.savedOp ===
|
|
2487
|
+
true
|
|
2488
|
+
)
|
|
2309
2489
|
) {
|
|
2310
|
-
|
|
2490
|
+
const range = messageWithContext.message.contents;
|
|
2491
|
+
if (this._idCompressor === undefined) {
|
|
2492
|
+
this.pendingIdCompressorOps.push(range);
|
|
2493
|
+
} else {
|
|
2494
|
+
this._idCompressor.finalizeCreationRange(range);
|
|
2495
|
+
}
|
|
2311
2496
|
}
|
|
2312
2497
|
break;
|
|
2313
2498
|
case ContainerMessageType.GC:
|
|
2314
2499
|
this.garbageCollector.processMessage(messageWithContext.message, local);
|
|
2315
2500
|
break;
|
|
2316
2501
|
case ContainerMessageType.ChunkedOp:
|
|
2502
|
+
// From observability POV, we should not exppse the rest of the system (including "op" events on object) to these messages.
|
|
2503
|
+
// Also resetReconnectCount() would be wrong - see comment that was there before this change was made.
|
|
2504
|
+
assert(false, "should not even get here");
|
|
2317
2505
|
case ContainerMessageType.Rejoin:
|
|
2318
2506
|
break;
|
|
2319
2507
|
default: {
|
|
@@ -2413,7 +2601,16 @@ export class ContainerRuntime
|
|
|
2413
2601
|
return;
|
|
2414
2602
|
}
|
|
2415
2603
|
|
|
2416
|
-
|
|
2604
|
+
// Due to a mismatch between different layers in terms of
|
|
2605
|
+
// what is the interface of passing signals, we need to adjust
|
|
2606
|
+
// the signal envelope before sending it to the datastores to be processed
|
|
2607
|
+
const envelope2: IEnvelope = {
|
|
2608
|
+
address: envelope.address,
|
|
2609
|
+
contents: transformed.content,
|
|
2610
|
+
};
|
|
2611
|
+
transformed.content = envelope2;
|
|
2612
|
+
|
|
2613
|
+
this.channelCollection.processSignal(transformed, local);
|
|
2417
2614
|
}
|
|
2418
2615
|
|
|
2419
2616
|
/**
|
|
@@ -2500,9 +2697,17 @@ export class ContainerRuntime
|
|
|
2500
2697
|
public async getAliasedDataStoreEntryPoint(
|
|
2501
2698
|
alias: string,
|
|
2502
2699
|
): Promise<IFluidHandle<FluidObject> | undefined> {
|
|
2503
|
-
|
|
2700
|
+
// Back-comapatibility:
|
|
2701
|
+
// There are old files that were created without using data store aliasing feature, but
|
|
2702
|
+
// used createRoot*DataStore*() (already removed) API. Such data stores will have isRoot = true,
|
|
2703
|
+
// and internalID provided by user. The expectation is that such files behave as new files, where
|
|
2704
|
+
// same data store instances created using aliasing feature.
|
|
2705
|
+
// Please also see note on name collisions in DataStores.createDataStoreId()
|
|
2706
|
+
await this.channelCollection.waitIfPendingAlias(alias);
|
|
2504
2707
|
const internalId = this.internalId(alias);
|
|
2505
|
-
const context = await this.
|
|
2708
|
+
const context = await this.channelCollection.getDataStoreIfAvailable(internalId, {
|
|
2709
|
+
wait: false,
|
|
2710
|
+
});
|
|
2506
2711
|
// If the data store is not available or not an alias, return undefined.
|
|
2507
2712
|
if (context === undefined || !(await context.isRoot())) {
|
|
2508
2713
|
return undefined;
|
|
@@ -2523,37 +2728,26 @@ export class ContainerRuntime
|
|
|
2523
2728
|
return channel.entryPoint;
|
|
2524
2729
|
}
|
|
2525
2730
|
|
|
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
2731
|
public createDetachedDataStore(
|
|
2537
2732
|
pkg: Readonly<string[]>,
|
|
2538
|
-
|
|
2733
|
+
loadingGroupId?: string,
|
|
2539
2734
|
): IFluidDataStoreContextDetached {
|
|
2540
|
-
return this.
|
|
2735
|
+
return this.channelCollection.createDetachedDataStore(pkg, loadingGroupId);
|
|
2541
2736
|
}
|
|
2542
2737
|
|
|
2543
|
-
public async createDataStore(
|
|
2544
|
-
|
|
2738
|
+
public async createDataStore(
|
|
2739
|
+
pkg: Readonly<string | string[]>,
|
|
2740
|
+
loadingGroupId?: string,
|
|
2741
|
+
): Promise<IDataStore> {
|
|
2742
|
+
const context = this.channelCollection.createDataStoreContext(
|
|
2743
|
+
Array.isArray(pkg) ? pkg : [pkg],
|
|
2744
|
+
undefined, // props
|
|
2745
|
+
loadingGroupId,
|
|
2746
|
+
);
|
|
2545
2747
|
return channelToDataStore(
|
|
2546
|
-
await
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
id,
|
|
2550
|
-
undefined,
|
|
2551
|
-
groupId,
|
|
2552
|
-
)
|
|
2553
|
-
.realize(),
|
|
2554
|
-
id,
|
|
2555
|
-
this,
|
|
2556
|
-
this.dataStores,
|
|
2748
|
+
await context.realize(),
|
|
2749
|
+
context.id,
|
|
2750
|
+
this.channelCollection,
|
|
2557
2751
|
this.mc.logger,
|
|
2558
2752
|
);
|
|
2559
2753
|
}
|
|
@@ -2562,17 +2756,17 @@ export class ContainerRuntime
|
|
|
2562
2756
|
* @deprecated 0.16 Issue #1537, #3631
|
|
2563
2757
|
*/
|
|
2564
2758
|
public async _createDataStoreWithProps(
|
|
2565
|
-
pkg: string | string[]
|
|
2759
|
+
pkg: Readonly<string | string[]>,
|
|
2566
2760
|
props?: any,
|
|
2567
|
-
id = uuid(),
|
|
2568
2761
|
): Promise<IDataStore> {
|
|
2762
|
+
const context = this.channelCollection.createDataStoreContext(
|
|
2763
|
+
Array.isArray(pkg) ? pkg : [pkg],
|
|
2764
|
+
props,
|
|
2765
|
+
);
|
|
2569
2766
|
return channelToDataStore(
|
|
2570
|
-
await
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
id,
|
|
2574
|
-
this,
|
|
2575
|
-
this.dataStores,
|
|
2767
|
+
await context.realize(),
|
|
2768
|
+
context.id,
|
|
2769
|
+
this.channelCollection,
|
|
2576
2770
|
this.mc.logger,
|
|
2577
2771
|
);
|
|
2578
2772
|
}
|
|
@@ -2628,6 +2822,7 @@ export class ContainerRuntime
|
|
|
2628
2822
|
}
|
|
2629
2823
|
break;
|
|
2630
2824
|
}
|
|
2825
|
+
case ContainerMessageType.IdAllocation:
|
|
2631
2826
|
case ContainerMessageType.GC: {
|
|
2632
2827
|
return false;
|
|
2633
2828
|
}
|
|
@@ -2673,22 +2868,6 @@ export class ContainerRuntime
|
|
|
2673
2868
|
return this.submitSignalFn(envelope, targetClientId);
|
|
2674
2869
|
}
|
|
2675
2870
|
|
|
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
2871
|
public setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void {
|
|
2693
2872
|
if (attachState === AttachState.Attaching) {
|
|
2694
2873
|
assert(
|
|
@@ -2706,7 +2885,7 @@ export class ContainerRuntime
|
|
|
2706
2885
|
if (attachState === AttachState.Attached && !this.hasPendingMessages()) {
|
|
2707
2886
|
this.updateDocumentDirtyState(false);
|
|
2708
2887
|
}
|
|
2709
|
-
this.
|
|
2888
|
+
this.channelCollection.setAttachState(attachState);
|
|
2710
2889
|
}
|
|
2711
2890
|
|
|
2712
2891
|
/**
|
|
@@ -2726,12 +2905,12 @@ export class ContainerRuntime
|
|
|
2726
2905
|
}
|
|
2727
2906
|
|
|
2728
2907
|
// We can finalize any allocated IDs since we're the only client
|
|
2729
|
-
const idRange = this.
|
|
2908
|
+
const idRange = this._idCompressor?.takeNextCreationRange();
|
|
2730
2909
|
if (idRange !== undefined) {
|
|
2731
|
-
this.
|
|
2910
|
+
this._idCompressor?.finalizeCreationRange(idRange);
|
|
2732
2911
|
}
|
|
2733
2912
|
|
|
2734
|
-
const summarizeResult = this.
|
|
2913
|
+
const summarizeResult = this.channelCollection.getAttachSummary(telemetryContext);
|
|
2735
2914
|
// Wrap data store summaries in .channels subtree.
|
|
2736
2915
|
wrapSummaryInChannelsTree(summarizeResult);
|
|
2737
2916
|
|
|
@@ -2751,7 +2930,7 @@ export class ContainerRuntime
|
|
|
2751
2930
|
trackState: boolean,
|
|
2752
2931
|
telemetryContext?: ITelemetryContext,
|
|
2753
2932
|
): Promise<ISummarizeInternalResult> {
|
|
2754
|
-
const summarizeResult = await this.
|
|
2933
|
+
const summarizeResult = await this.channelCollection.summarize(
|
|
2755
2934
|
fullTree,
|
|
2756
2935
|
trackState,
|
|
2757
2936
|
telemetryContext,
|
|
@@ -2842,11 +3021,11 @@ export class ContainerRuntime
|
|
|
2842
3021
|
* @see IGarbageCollectionRuntime.updateStateBeforeGC
|
|
2843
3022
|
*/
|
|
2844
3023
|
public async updateStateBeforeGC() {
|
|
2845
|
-
return this.
|
|
3024
|
+
return this.channelCollection.updateStateBeforeGC();
|
|
2846
3025
|
}
|
|
2847
3026
|
|
|
2848
3027
|
private async getGCDataInternal(fullGC?: boolean): Promise<IGarbageCollectionData> {
|
|
2849
|
-
return this.
|
|
3028
|
+
return this.channelCollection.getGCData(fullGC);
|
|
2850
3029
|
}
|
|
2851
3030
|
|
|
2852
3031
|
/**
|
|
@@ -2876,25 +3055,7 @@ export class ContainerRuntime
|
|
|
2876
3055
|
this.summarizerNode.updateUsedRoutes([""]);
|
|
2877
3056
|
|
|
2878
3057
|
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");
|
|
3058
|
+
this.channelCollection.updateUsedRoutes(dataStoreRoutes);
|
|
2898
3059
|
}
|
|
2899
3060
|
|
|
2900
3061
|
/**
|
|
@@ -2906,7 +3067,7 @@ export class ContainerRuntime
|
|
|
2906
3067
|
const { dataStoreRoutes, blobManagerRoutes } =
|
|
2907
3068
|
this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
|
|
2908
3069
|
|
|
2909
|
-
const deletedRoutes = this.
|
|
3070
|
+
const deletedRoutes = this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes);
|
|
2910
3071
|
return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
|
|
2911
3072
|
}
|
|
2912
3073
|
|
|
@@ -2922,7 +3083,7 @@ export class ContainerRuntime
|
|
|
2922
3083
|
const { blobManagerRoutes, dataStoreRoutes } =
|
|
2923
3084
|
this.getDataStoreAndBlobManagerRoutes(tombstonedRoutes);
|
|
2924
3085
|
this.blobManager.updateTombstonedRoutes(blobManagerRoutes);
|
|
2925
|
-
this.
|
|
3086
|
+
this.channelCollection.updateTombstonedRoutes(dataStoreRoutes);
|
|
2926
3087
|
}
|
|
2927
3088
|
|
|
2928
3089
|
/**
|
|
@@ -2942,7 +3103,7 @@ export class ContainerRuntime
|
|
|
2942
3103
|
if (this.isBlobPath(nodePath)) {
|
|
2943
3104
|
return GCNodeType.Blob;
|
|
2944
3105
|
}
|
|
2945
|
-
return this.
|
|
3106
|
+
return this.channelCollection.getGCNodeType(nodePath) ?? GCNodeType.Other;
|
|
2946
3107
|
}
|
|
2947
3108
|
|
|
2948
3109
|
/**
|
|
@@ -2953,7 +3114,7 @@ export class ContainerRuntime
|
|
|
2953
3114
|
// GC uses "/" when adding "root" references, e.g. for Aliasing or as part of Tombstone Auto-Recovery.
|
|
2954
3115
|
// These have no package path so return a special value.
|
|
2955
3116
|
if (nodePath === "/") {
|
|
2956
|
-
return ["
|
|
3117
|
+
return ["_gcRoot"];
|
|
2957
3118
|
}
|
|
2958
3119
|
|
|
2959
3120
|
switch (this.getNodeType(nodePath)) {
|
|
@@ -2961,7 +3122,7 @@ export class ContainerRuntime
|
|
|
2961
3122
|
return [BlobManager.basePath];
|
|
2962
3123
|
case GCNodeType.DataStore:
|
|
2963
3124
|
case GCNodeType.SubDataStore:
|
|
2964
|
-
return this.
|
|
3125
|
+
return this.channelCollection.getDataStorePackagePath(nodePath);
|
|
2965
3126
|
default:
|
|
2966
3127
|
assert(false, 0x2de /* "Package path requested for unsupported node type." */);
|
|
2967
3128
|
}
|
|
@@ -3021,7 +3182,10 @@ export class ContainerRuntime
|
|
|
3021
3182
|
* @param srcHandle - The handle of the node that added the reference.
|
|
3022
3183
|
* @param outboundHandle - The handle of the outbound node that is referenced.
|
|
3023
3184
|
*/
|
|
3024
|
-
public addedGCOutboundReference(
|
|
3185
|
+
public addedGCOutboundReference(
|
|
3186
|
+
srcHandle: { absolutePath: string },
|
|
3187
|
+
outboundHandle: { absolutePath: string },
|
|
3188
|
+
) {
|
|
3025
3189
|
this.garbageCollector.addedOutboundReference(
|
|
3026
3190
|
srcHandle.absolutePath,
|
|
3027
3191
|
outboundHandle.absolutePath,
|
|
@@ -3037,7 +3201,13 @@ export class ContainerRuntime
|
|
|
3037
3201
|
* @param options - options controlling how the summary is generated or submitted
|
|
3038
3202
|
*/
|
|
3039
3203
|
public async submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult> {
|
|
3040
|
-
const {
|
|
3204
|
+
const {
|
|
3205
|
+
fullTree = false,
|
|
3206
|
+
finalAttempt = false,
|
|
3207
|
+
refreshLatestAck,
|
|
3208
|
+
summaryLogger,
|
|
3209
|
+
latestSummaryRefSeqNum,
|
|
3210
|
+
} = options;
|
|
3041
3211
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
3042
3212
|
// use it for all events logged during this summary.
|
|
3043
3213
|
const summaryNumber = this.nextSummaryNumber;
|
|
@@ -3108,6 +3278,10 @@ export class ContainerRuntime
|
|
|
3108
3278
|
this.mc.config.getBoolean(
|
|
3109
3279
|
"Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause",
|
|
3110
3280
|
) !== true;
|
|
3281
|
+
const shouldValidatePreSummaryState =
|
|
3282
|
+
this.mc.config.getBoolean(
|
|
3283
|
+
"Fluid.ContainerRuntime.SubmitSummary.shouldValidatePreSummaryState",
|
|
3284
|
+
) === true;
|
|
3111
3285
|
|
|
3112
3286
|
let summaryRefSeqNum: number | undefined;
|
|
3113
3287
|
|
|
@@ -3122,7 +3296,33 @@ export class ContainerRuntime
|
|
|
3122
3296
|
const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
|
|
3123
3297
|
const lastAck = this.summaryCollection.latestAck;
|
|
3124
3298
|
|
|
3125
|
-
this.summarizerNode.startSummary(
|
|
3299
|
+
const startSummaryResult = this.summarizerNode.startSummary(
|
|
3300
|
+
summaryRefSeqNum,
|
|
3301
|
+
summaryNumberLogger,
|
|
3302
|
+
latestSummaryRefSeqNum,
|
|
3303
|
+
);
|
|
3304
|
+
|
|
3305
|
+
if (
|
|
3306
|
+
startSummaryResult.invalidNodes > 0 ||
|
|
3307
|
+
startSummaryResult.mismatchNumbers.size > 0
|
|
3308
|
+
) {
|
|
3309
|
+
summaryLogger.sendErrorEvent({
|
|
3310
|
+
eventName: "LatestSummaryRefSeqNumMismatch",
|
|
3311
|
+
details: {
|
|
3312
|
+
...startSummaryResult,
|
|
3313
|
+
mismatchNumbers: Array.from(startSummaryResult.mismatchNumbers),
|
|
3314
|
+
},
|
|
3315
|
+
});
|
|
3316
|
+
|
|
3317
|
+
if (shouldValidatePreSummaryState && !finalAttempt) {
|
|
3318
|
+
return {
|
|
3319
|
+
stage: "base",
|
|
3320
|
+
referenceSequenceNumber: summaryRefSeqNum,
|
|
3321
|
+
minimumSequenceNumber,
|
|
3322
|
+
error: `Summarizer node state inconsistent with summarizer state.`,
|
|
3323
|
+
};
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
3126
3326
|
|
|
3127
3327
|
// Helper function to check whether we should still continue between each async step.
|
|
3128
3328
|
const checkContinue = (): { continue: true } | { continue: false; error: string } => {
|
|
@@ -3244,8 +3444,8 @@ export class ContainerRuntime
|
|
|
3244
3444
|
: undefined;
|
|
3245
3445
|
|
|
3246
3446
|
const summaryStats: IGeneratedSummaryStats = {
|
|
3247
|
-
dataStoreCount: this.
|
|
3248
|
-
summarizedDataStoreCount: this.
|
|
3447
|
+
dataStoreCount: this.channelCollection.size,
|
|
3448
|
+
summarizedDataStoreCount: this.channelCollection.size - handleCount,
|
|
3249
3449
|
gcStateUpdatedDataStoreCount: this.garbageCollector.updatedDSCountSinceLastSummary,
|
|
3250
3450
|
gcBlobNodeCount: gcSummaryTreeStats?.blobNodeCount,
|
|
3251
3451
|
gcTotalBlobsSize: gcSummaryTreeStats?.totalBlobSize,
|
|
@@ -3442,28 +3642,15 @@ export class ContainerRuntime
|
|
|
3442
3642
|
}
|
|
3443
3643
|
}
|
|
3444
3644
|
|
|
3445
|
-
public
|
|
3446
|
-
|
|
3645
|
+
public submitMessage(
|
|
3646
|
+
type:
|
|
3647
|
+
| ContainerMessageType.FluidDataStoreOp
|
|
3648
|
+
| ContainerMessageType.Alias
|
|
3649
|
+
| ContainerMessageType.Attach,
|
|
3447
3650
|
contents: any,
|
|
3448
3651
|
localOpMetadata: unknown = undefined,
|
|
3449
3652
|
): 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);
|
|
3653
|
+
this.submit({ type, contents }, localOpMetadata);
|
|
3467
3654
|
}
|
|
3468
3655
|
|
|
3469
3656
|
public async uploadBlob(
|
|
@@ -3474,35 +3661,22 @@ export class ContainerRuntime
|
|
|
3474
3661
|
return this.blobManager.createBlob(blob, signal);
|
|
3475
3662
|
}
|
|
3476
3663
|
|
|
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) {
|
|
3664
|
+
private submitIdAllocationOpIfNeeded(): void {
|
|
3665
|
+
if (this._idCompressor) {
|
|
3666
|
+
const idRange = this._idCompressor.takeNextCreationRange();
|
|
3667
|
+
// Don't include the idRange if there weren't any Ids allocated
|
|
3668
|
+
if (idRange?.ids !== undefined) {
|
|
3492
3669
|
const idAllocationMessage: ContainerRuntimeIdAllocationMessage = {
|
|
3493
3670
|
type: ContainerMessageType.IdAllocation,
|
|
3494
3671
|
contents: idRange,
|
|
3495
3672
|
};
|
|
3496
|
-
idAllocationBatchMessage = {
|
|
3673
|
+
const idAllocationBatchMessage: BatchMessage = {
|
|
3497
3674
|
contents: JSON.stringify(idAllocationMessage),
|
|
3498
3675
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
3499
3676
|
metadata: undefined,
|
|
3500
3677
|
localOpMetadata: undefined,
|
|
3501
3678
|
type: ContainerMessageType.IdAllocation,
|
|
3502
3679
|
};
|
|
3503
|
-
}
|
|
3504
|
-
|
|
3505
|
-
if (idAllocationBatchMessage !== undefined) {
|
|
3506
3680
|
this.outbox.submitIdAllocation(idAllocationBatchMessage);
|
|
3507
3681
|
}
|
|
3508
3682
|
}
|
|
@@ -3543,43 +3717,47 @@ export class ContainerRuntime
|
|
|
3543
3717
|
};
|
|
3544
3718
|
|
|
3545
3719
|
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);
|
|
3720
|
+
// If `message` is an allocation op, then we are in the resubmit path and we must redirect the allocation
|
|
3721
|
+
// op into the correct batch to avoid ranges being finalized out of order.
|
|
3722
|
+
// Otherwise, submit an IdAllocation op if any IDs have been generated since the last op was submitted, as
|
|
3723
|
+
// any of the other op types may contain those IDs and thus depend on the allocation op being sent first.
|
|
3724
|
+
if (type === ContainerMessageType.IdAllocation) {
|
|
3725
|
+
this.outbox.submitIdAllocation(message);
|
|
3581
3726
|
} else {
|
|
3582
|
-
this.
|
|
3727
|
+
this.submitIdAllocationOpIfNeeded();
|
|
3728
|
+
|
|
3729
|
+
// If this is attach message for new data store, and we are in a batch, send this op out of order
|
|
3730
|
+
// Is it safe:
|
|
3731
|
+
// Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
|
|
3732
|
+
// They become visible only when aliased, or handle to some sub-element of newly created datastore
|
|
3733
|
+
// is stored in some DDS, i.e. only after some other op.
|
|
3734
|
+
// Why:
|
|
3735
|
+
// Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
|
|
3736
|
+
// stores are created, causing issues like relay service throttling (too many ops) and catastrophic
|
|
3737
|
+
// failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
|
|
3738
|
+
// these issues.
|
|
3739
|
+
// Cons:
|
|
3740
|
+
// 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
|
|
3741
|
+
// This change creates new possibility of a lot of newly created data stores never being referenced
|
|
3742
|
+
// because client died before it had a change to submit the rest of the ops. This will create more
|
|
3743
|
+
// garbage that needs to be collected leveraging GC (Garbage Collection) feature.
|
|
3744
|
+
// 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
|
|
3745
|
+
// today as rollback can't undo creation of data store. To some extent not sending them is a bigger
|
|
3746
|
+
// issue than sending.
|
|
3747
|
+
// Please note that this does not change file format, so it can be disabled in the future if this
|
|
3748
|
+
// optimization no longer makes sense (for example, batch compression may make it less appealing).
|
|
3749
|
+
if (
|
|
3750
|
+
this.currentlyBatching() &&
|
|
3751
|
+
type === ContainerMessageType.Attach &&
|
|
3752
|
+
this.disableAttachReorder !== true
|
|
3753
|
+
) {
|
|
3754
|
+
this.outbox.submitAttach(message);
|
|
3755
|
+
} else if (type === ContainerMessageType.BlobAttach) {
|
|
3756
|
+
// BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
|
|
3757
|
+
this.outbox.submitBlobAttach(message);
|
|
3758
|
+
} else {
|
|
3759
|
+
this.outbox.submit(message);
|
|
3760
|
+
}
|
|
3583
3761
|
}
|
|
3584
3762
|
|
|
3585
3763
|
if (!this.currentlyBatching()) {
|
|
@@ -3721,15 +3899,18 @@ export class ContainerRuntime
|
|
|
3721
3899
|
localOpMetadata: unknown,
|
|
3722
3900
|
opMetadata: Record<string, unknown> | undefined,
|
|
3723
3901
|
) {
|
|
3724
|
-
assert(
|
|
3902
|
+
assert(
|
|
3903
|
+
!this.isSummarizerClient,
|
|
3904
|
+
0x8f2 /* Summarizer never reconnects so should never resubmit */,
|
|
3905
|
+
);
|
|
3725
3906
|
switch (message.type) {
|
|
3726
3907
|
case ContainerMessageType.FluidDataStoreOp:
|
|
3908
|
+
case ContainerMessageType.Attach:
|
|
3909
|
+
case ContainerMessageType.Alias:
|
|
3727
3910
|
// For Operations, call resubmitDataStoreOp which will find the right store
|
|
3728
3911
|
// and trigger resubmission on it.
|
|
3729
|
-
this.
|
|
3912
|
+
this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
|
|
3730
3913
|
break;
|
|
3731
|
-
case ContainerMessageType.Attach:
|
|
3732
|
-
case ContainerMessageType.Alias:
|
|
3733
3914
|
case ContainerMessageType.IdAllocation: {
|
|
3734
3915
|
this.submit(message, localOpMetadata);
|
|
3735
3916
|
break;
|
|
@@ -3781,7 +3962,7 @@ export class ContainerRuntime
|
|
|
3781
3962
|
case ContainerMessageType.FluidDataStoreOp:
|
|
3782
3963
|
// For operations, call rollbackDataStoreOp which will find the right store
|
|
3783
3964
|
// and trigger rollback on it.
|
|
3784
|
-
this.
|
|
3965
|
+
this.channelCollection.rollback(type, contents, localOpMetadata);
|
|
3785
3966
|
break;
|
|
3786
3967
|
default:
|
|
3787
3968
|
// Don't check message.compatDetails because this is for rolling back a local op so the type will be known
|
|
@@ -3870,7 +4051,7 @@ export class ContainerRuntime
|
|
|
3870
4051
|
*/
|
|
3871
4052
|
private async fetchLatestSnapshotFromStorage(
|
|
3872
4053
|
logger: ITelemetryLoggerExt,
|
|
3873
|
-
event:
|
|
4054
|
+
event: ITelemetryGenericEventExt,
|
|
3874
4055
|
readAndParseBlob: ReadAndParseBlob,
|
|
3875
4056
|
): Promise<{ snapshotTree: ISnapshotTree; versionId: string; latestSnapshotRefSeq: number }> {
|
|
3876
4057
|
return PerformanceEvent.timedExecAsync(
|
|
@@ -3921,50 +4102,65 @@ export class ContainerRuntime
|
|
|
3921
4102
|
);
|
|
3922
4103
|
}
|
|
3923
4104
|
|
|
3924
|
-
public
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
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
|
-
}
|
|
4105
|
+
public getPendingLocalState(props?: IGetPendingLocalStateProps): unknown {
|
|
4106
|
+
this.verifyNotClosed();
|
|
4107
|
+
|
|
4108
|
+
if (this._orderSequentiallyCalls !== 0) {
|
|
4109
|
+
throw new UsageError("can't get state during orderSequentially");
|
|
4110
|
+
}
|
|
4111
|
+
this.imminentClosure ||= props?.notifyImminentClosure ?? false;
|
|
4112
|
+
|
|
4113
|
+
const getSyncState = (
|
|
4114
|
+
pendingAttachmentBlobs?: IPendingBlobs,
|
|
4115
|
+
): IPendingRuntimeState | undefined => {
|
|
4116
|
+
const pending = this.pendingStateManager.getLocalState();
|
|
4117
|
+
if (pendingAttachmentBlobs === undefined && !this.hasPendingMessages()) {
|
|
4118
|
+
return; // no pending state to save
|
|
4119
|
+
}
|
|
3953
4120
|
|
|
3954
|
-
|
|
4121
|
+
const pendingIdCompressorState = this._idCompressor?.serialize(true);
|
|
3955
4122
|
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
4123
|
+
return {
|
|
4124
|
+
pending,
|
|
4125
|
+
pendingIdCompressorState,
|
|
4126
|
+
pendingAttachmentBlobs,
|
|
4127
|
+
sessionExpiryTimerStarted: this.garbageCollector.sessionExpiryTimerStarted,
|
|
4128
|
+
};
|
|
4129
|
+
};
|
|
4130
|
+
const perfEvent = {
|
|
4131
|
+
eventName: "getPendingLocalState",
|
|
4132
|
+
notifyImminentClosure: props?.notifyImminentClosure,
|
|
4133
|
+
};
|
|
4134
|
+
const logAndReturnPendingState = (
|
|
4135
|
+
event: PerformanceEvent,
|
|
4136
|
+
pendingState?: IPendingRuntimeState,
|
|
4137
|
+
) => {
|
|
4138
|
+
event.end({
|
|
4139
|
+
attachmentBlobsSize: Object.keys(pendingState?.pendingAttachmentBlobs ?? {}).length,
|
|
4140
|
+
pendingOpsSize: pendingState?.pending?.pendingStates.length,
|
|
4141
|
+
});
|
|
4142
|
+
return pendingState;
|
|
4143
|
+
};
|
|
4144
|
+
|
|
4145
|
+
// Flush pending batch.
|
|
4146
|
+
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
4147
|
+
// to close current batch.
|
|
4148
|
+
this.flush();
|
|
4149
|
+
|
|
4150
|
+
return props?.notifyImminentClosure === true
|
|
4151
|
+
? PerformanceEvent.timedExecAsync(this.mc.logger, perfEvent, async (event) =>
|
|
4152
|
+
logAndReturnPendingState(
|
|
4153
|
+
event,
|
|
4154
|
+
getSyncState(
|
|
4155
|
+
await this.blobManager.attachAndGetPendingBlobs(
|
|
4156
|
+
props?.stopBlobAttachingSignal,
|
|
4157
|
+
),
|
|
4158
|
+
),
|
|
4159
|
+
),
|
|
4160
|
+
)
|
|
4161
|
+
: PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) =>
|
|
4162
|
+
logAndReturnPendingState(event, getSyncState()),
|
|
4163
|
+
);
|
|
3968
4164
|
}
|
|
3969
4165
|
|
|
3970
4166
|
public summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults {
|