@fluidframework/container-runtime 2.0.0-dev-rc.1.0.0.232845 → 2.0.0-dev-rc.2.0.0.245554
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +5 -5
- package/{.mocharc.js → .mocharc.cjs} +1 -1
- package/CHANGELOG.md +54 -0
- package/README.md +45 -0
- package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
- package/api-extractor-lint.json +1 -1
- package/api-extractor.json +1 -1
- package/api-report/container-runtime.api.md +425 -33
- package/dist/batchTracker.d.ts +1 -2
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +0 -5
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +0 -12
- package/dist/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +225 -0
- package/dist/channelCollection.d.ts.map +1 -0
- package/dist/{dataStores.js → channelCollection.js} +447 -147
- package/dist/channelCollection.js.map +1 -0
- package/dist/connectionTelemetry.d.ts +11 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +42 -4
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/container-runtime-alpha.d.ts +129 -48
- package/dist/container-runtime-beta.d.ts +68 -9
- package/dist/container-runtime-public.d.ts +68 -9
- package/dist/container-runtime-untrimmed.d.ts +692 -49
- package/dist/containerHandleContext.d.ts +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +81 -64
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +503 -368
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +2 -3
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +12 -11
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +118 -41
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +248 -159
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts +2 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +1 -0
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts +29 -4
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js +91 -5
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +12 -6
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +116 -78
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +2 -2
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +30 -23
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +22 -13
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +7 -4
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +2 -2
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +12 -5
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +18 -6
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +6 -7
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +20 -18
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.d.ts +1 -1
- package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +10 -10
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +8 -8
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +40 -39
- package/dist/gc/index.js.map +1 -1
- package/dist/index.d.ts +11 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -42
- package/dist/index.js.map +1 -1
- package/dist/messageTypes.d.ts +3 -3
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +2 -2
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +2 -2
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +8 -8
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +18 -18
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +4 -4
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +3 -3
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +1 -10
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +5 -5
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +7 -7
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +20 -12
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +4 -4
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +2 -2
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/package.json +3 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +2 -1
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +18 -10
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts +1 -2
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +5 -5
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/index.d.ts +12 -12
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js +43 -43
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.js +8 -8
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +5 -4
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +47 -32
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +4 -4
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +6 -6
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +2 -2
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.d.ts +3 -3
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/index.d.ts +3 -3
- package/dist/summary/summarizerNode/index.d.ts.map +1 -1
- package/dist/summary/summarizerNode/index.js +4 -4
- package/dist/summary/summarizerNode/index.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +16 -5
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +40 -10
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +9 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -4
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +12 -12
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +9 -20
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +15 -2
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +6 -5
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +10 -1
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +5 -6
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +4 -5
- package/dist/summary/summaryManager.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/{batchTracker.d.mts → batchTracker.d.ts} +2 -3
- package/lib/batchTracker.d.ts.map +1 -0
- package/lib/{batchTracker.mjs → batchTracker.js} +1 -1
- package/lib/batchTracker.js.map +1 -0
- package/lib/{blobManager.d.mts → blobManager.d.ts} +1 -6
- package/lib/blobManager.d.ts.map +1 -0
- package/lib/{blobManager.mjs → blobManager.js} +1 -13
- package/lib/blobManager.js.map +1 -0
- package/lib/channelCollection.d.ts +225 -0
- package/lib/channelCollection.d.ts.map +1 -0
- package/lib/{dataStores.mjs → channelCollection.js} +434 -137
- package/lib/channelCollection.js.map +1 -0
- package/lib/{connectionTelemetry.d.mts → connectionTelemetry.d.ts} +12 -2
- package/lib/connectionTelemetry.d.ts.map +1 -0
- package/lib/{connectionTelemetry.mjs → connectionTelemetry.js} +43 -5
- package/lib/connectionTelemetry.js.map +1 -0
- package/lib/{container-runtime-alpha.d.mts → container-runtime-alpha.d.ts} +129 -48
- package/lib/{container-runtime-beta.d.mts → container-runtime-beta.d.ts} +68 -9
- package/lib/{container-runtime-public.d.mts → container-runtime-public.d.ts} +68 -9
- package/lib/{container-runtime-untrimmed.d.mts → container-runtime-untrimmed.d.ts} +692 -49
- package/lib/{containerHandleContext.d.mts → containerHandleContext.d.ts} +2 -2
- package/lib/containerHandleContext.d.ts.map +1 -0
- package/lib/{containerHandleContext.mjs → containerHandleContext.js} +1 -1
- package/lib/containerHandleContext.js.map +1 -0
- package/lib/{containerRuntime.d.mts → containerRuntime.d.ts} +86 -65
- package/lib/containerRuntime.d.ts.map +1 -0
- package/lib/{containerRuntime.mjs → containerRuntime.js} +423 -290
- package/lib/containerRuntime.js.map +1 -0
- package/lib/{dataStore.d.mts → dataStore.d.ts} +3 -4
- package/lib/dataStore.d.ts.map +1 -0
- package/lib/{dataStore.mjs → dataStore.js} +13 -12
- package/lib/dataStore.js.map +1 -0
- package/lib/{dataStoreContext.d.mts → dataStoreContext.d.ts} +119 -42
- package/lib/dataStoreContext.d.ts.map +1 -0
- package/lib/{dataStoreContext.mjs → dataStoreContext.js} +240 -151
- package/lib/dataStoreContext.js.map +1 -0
- package/lib/{dataStoreContexts.d.mts → dataStoreContexts.d.ts} +3 -2
- package/lib/dataStoreContexts.d.ts.map +1 -0
- package/lib/{dataStoreContexts.mjs → dataStoreContexts.js} +2 -1
- package/lib/dataStoreContexts.js.map +1 -0
- package/lib/{dataStoreRegistry.d.mts → dataStoreRegistry.d.ts} +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -0
- package/lib/{dataStoreRegistry.mjs → dataStoreRegistry.js} +5 -1
- package/lib/dataStoreRegistry.js.map +1 -0
- package/{dist/deltaManagerProxyBase.d.ts → lib/deltaManagerSummarizerProxy.d.ts} +16 -7
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -0
- package/lib/deltaManagerSummarizerProxy.js +124 -0
- package/lib/deltaManagerSummarizerProxy.js.map +1 -0
- package/lib/{deltaScheduler.d.mts → deltaScheduler.d.ts} +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -0
- package/lib/{deltaScheduler.mjs → deltaScheduler.js} +1 -1
- package/lib/deltaScheduler.js.map +1 -0
- package/lib/{error.d.mts → error.d.ts} +1 -1
- package/lib/error.d.ts.map +1 -0
- package/lib/{error.mjs → error.js} +1 -1
- package/lib/error.js.map +1 -0
- package/lib/gc/{garbageCollection.d.mts → garbageCollection.d.ts} +13 -7
- package/lib/gc/garbageCollection.d.ts.map +1 -0
- package/lib/gc/{garbageCollection.mjs → garbageCollection.js} +79 -41
- package/lib/gc/garbageCollection.js.map +1 -0
- package/lib/gc/{gcConfigs.d.mts → gcConfigs.d.ts} +3 -3
- package/lib/gc/gcConfigs.d.ts.map +1 -0
- package/lib/gc/{gcConfigs.mjs → gcConfigs.js} +14 -7
- package/lib/gc/gcConfigs.js.map +1 -0
- package/lib/gc/{gcDefinitions.d.mts → gcDefinitions.d.ts} +23 -14
- package/lib/gc/gcDefinitions.d.ts.map +1 -0
- package/lib/gc/{gcDefinitions.mjs → gcDefinitions.js} +7 -4
- package/lib/gc/gcDefinitions.js.map +1 -0
- package/lib/gc/{gcHelpers.d.mts → gcHelpers.d.ts} +3 -3
- package/lib/gc/{gcHelpers.d.mts.map → gcHelpers.d.ts.map} +1 -1
- package/lib/gc/{gcHelpers.mjs → gcHelpers.js} +1 -1
- package/lib/gc/gcHelpers.js.map +1 -0
- package/lib/gc/{gcReferenceGraphAlgorithm.d.mts → gcReferenceGraphAlgorithm.d.ts} +2 -2
- package/lib/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -0
- package/lib/gc/{gcReferenceGraphAlgorithm.mjs → gcReferenceGraphAlgorithm.js} +1 -1
- package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -0
- package/lib/gc/{gcSummaryDefinitions.d.mts → gcSummaryDefinitions.d.ts} +1 -1
- package/lib/gc/gcSummaryDefinitions.d.ts.map +1 -0
- package/lib/gc/{gcSummaryDefinitions.mjs → gcSummaryDefinitions.js} +1 -1
- package/lib/gc/gcSummaryDefinitions.js.map +1 -0
- package/lib/gc/{gcSummaryStateTracker.d.mts → gcSummaryStateTracker.d.ts} +13 -6
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -0
- package/lib/gc/{gcSummaryStateTracker.mjs → gcSummaryStateTracker.js} +17 -5
- package/lib/gc/gcSummaryStateTracker.js.map +1 -0
- package/lib/gc/{gcTelemetry.d.mts → gcTelemetry.d.ts} +7 -8
- package/lib/gc/gcTelemetry.d.ts.map +1 -0
- package/lib/gc/{gcTelemetry.mjs → gcTelemetry.js} +5 -3
- package/lib/gc/gcTelemetry.js.map +1 -0
- package/lib/gc/{gcUnreferencedStateTracker.d.mts → gcUnreferencedStateTracker.d.ts} +2 -2
- package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
- package/lib/gc/{gcUnreferencedStateTracker.mjs → gcUnreferencedStateTracker.js} +2 -2
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -0
- package/lib/gc/index.d.ts +13 -0
- package/lib/gc/index.d.ts.map +1 -0
- package/lib/gc/{index.mjs → index.js} +8 -8
- package/lib/gc/index.js.map +1 -0
- package/lib/{index.d.mts → index.d.ts} +12 -22
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +15 -0
- package/lib/index.js.map +1 -0
- package/lib/{messageTypes.d.mts → messageTypes.d.ts} +4 -4
- package/lib/messageTypes.d.ts.map +1 -0
- package/lib/{messageTypes.mjs → messageTypes.js} +1 -1
- package/lib/messageTypes.js.map +1 -0
- package/lib/{metadata.d.mts → metadata.d.ts} +1 -1
- package/lib/metadata.d.ts.map +1 -0
- package/lib/{metadata.mjs → metadata.js} +1 -1
- package/lib/metadata.js.map +1 -0
- package/lib/opLifecycle/{batchManager.d.mts → batchManager.d.ts} +3 -3
- package/lib/opLifecycle/batchManager.d.ts.map +1 -0
- package/lib/opLifecycle/{batchManager.mjs → batchManager.js} +1 -1
- package/lib/opLifecycle/batchManager.js.map +1 -0
- package/lib/opLifecycle/{definitions.d.mts → definitions.d.ts} +3 -3
- package/lib/opLifecycle/definitions.d.ts.map +1 -0
- package/lib/opLifecycle/{definitions.mjs → definitions.js} +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -0
- package/lib/opLifecycle/index.d.ts +13 -0
- package/lib/opLifecycle/index.d.ts.map +1 -0
- package/lib/opLifecycle/index.js +12 -0
- package/lib/opLifecycle/index.js.map +1 -0
- package/lib/opLifecycle/{opCompressor.d.mts → opCompressor.d.ts} +2 -2
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -0
- package/lib/opLifecycle/{opCompressor.mjs → opCompressor.js} +3 -3
- package/lib/opLifecycle/opCompressor.js.map +1 -0
- package/lib/opLifecycle/{opDecompressor.d.mts → opDecompressor.d.ts} +2 -2
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -0
- package/lib/opLifecycle/{opDecompressor.mjs → opDecompressor.js} +2 -2
- package/lib/opLifecycle/opDecompressor.js.map +1 -0
- package/lib/opLifecycle/{opGroupingManager.d.mts → opGroupingManager.d.ts} +2 -2
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -0
- package/lib/opLifecycle/{opGroupingManager.mjs → opGroupingManager.js} +2 -11
- package/lib/opLifecycle/opGroupingManager.js.map +1 -0
- package/lib/opLifecycle/{opSplitter.d.mts → opSplitter.d.ts} +2 -2
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -0
- package/lib/opLifecycle/{opSplitter.mjs → opSplitter.js} +3 -3
- package/lib/opLifecycle/opSplitter.js.map +1 -0
- package/lib/opLifecycle/{outbox.d.mts → outbox.d.ts} +8 -8
- package/lib/opLifecycle/outbox.d.ts.map +1 -0
- package/lib/opLifecycle/{outbox.mjs → outbox.js} +12 -4
- package/lib/opLifecycle/outbox.js.map +1 -0
- package/lib/opLifecycle/{remoteMessageProcessor.d.mts → remoteMessageProcessor.d.ts} +5 -5
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -0
- package/lib/opLifecycle/{remoteMessageProcessor.mjs → remoteMessageProcessor.js} +2 -2
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -0
- package/lib/{opProperties.d.mts → opProperties.d.ts} +1 -1
- package/lib/opProperties.d.ts.map +1 -0
- package/lib/{opProperties.mjs → opProperties.js} +1 -1
- package/lib/opProperties.js.map +1 -0
- package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
- package/lib/packageVersion.d.ts.map +1 -0
- package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
- package/lib/packageVersion.js.map +1 -0
- package/lib/{pendingStateManager.d.mts → pendingStateManager.d.ts} +3 -2
- package/lib/pendingStateManager.d.ts.map +1 -0
- package/lib/{pendingStateManager.mjs → pendingStateManager.js} +18 -10
- package/lib/pendingStateManager.js.map +1 -0
- package/lib/{scheduleManager.d.mts → scheduleManager.d.ts} +6 -3
- package/lib/scheduleManager.d.ts.map +1 -0
- package/lib/{scheduleManager.mjs → scheduleManager.js} +3 -3
- package/lib/scheduleManager.js.map +1 -0
- package/lib/{storageServiceWithAttachBlobs.d.mts → storageServiceWithAttachBlobs.d.ts} +1 -1
- package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -0
- package/lib/{storageServiceWithAttachBlobs.mjs → storageServiceWithAttachBlobs.js} +1 -1
- package/lib/storageServiceWithAttachBlobs.js.map +1 -0
- package/lib/summary/{index.d.mts → index.d.ts} +13 -13
- package/lib/summary/index.d.ts.map +1 -0
- package/lib/summary/{index.mjs → index.js} +12 -12
- package/lib/summary/index.js.map +1 -0
- package/lib/summary/{orderedClientElection.d.mts → orderedClientElection.d.ts} +5 -1
- package/lib/summary/orderedClientElection.d.ts.map +1 -0
- package/lib/summary/{orderedClientElection.mjs → orderedClientElection.js} +2 -2
- package/lib/summary/orderedClientElection.js.map +1 -0
- package/lib/summary/{runWhileConnectedCoordinator.d.mts → runWhileConnectedCoordinator.d.ts} +2 -2
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/lib/summary/{runWhileConnectedCoordinator.mjs → runWhileConnectedCoordinator.js} +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -0
- package/lib/summary/{runningSummarizer.d.mts → runningSummarizer.d.ts} +6 -5
- package/lib/summary/runningSummarizer.d.ts.map +1 -0
- package/lib/summary/{runningSummarizer.mjs → runningSummarizer.js} +41 -26
- package/lib/summary/runningSummarizer.js.map +1 -0
- package/lib/summary/{summarizer.d.mts → summarizer.d.ts} +5 -5
- package/lib/summary/summarizer.d.ts.map +1 -0
- package/lib/summary/{summarizer.mjs → summarizer.js} +4 -4
- package/lib/summary/summarizer.js.map +1 -0
- package/lib/summary/{summarizerClientElection.d.mts → summarizerClientElection.d.ts} +3 -3
- package/lib/summary/summarizerClientElection.d.ts.map +1 -0
- package/lib/summary/{summarizerClientElection.mjs → summarizerClientElection.js} +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -0
- package/lib/summary/{summarizerHeuristics.d.mts → summarizerHeuristics.d.ts} +4 -4
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
- package/lib/summary/{summarizerHeuristics.mjs → summarizerHeuristics.js} +1 -1
- package/lib/summary/summarizerHeuristics.js.map +1 -0
- package/lib/summary/summarizerNode/{index.d.mts → index.d.ts} +4 -4
- package/lib/summary/summarizerNode/index.d.ts.map +1 -0
- package/lib/summary/summarizerNode/index.js +7 -0
- package/lib/summary/summarizerNode/index.js.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNode.d.mts → summarizerNode.d.ts} +17 -6
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNode.mjs → summarizerNode.js} +34 -4
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeUtils.d.mts → summarizerNodeUtils.d.ts} +10 -2
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeUtils.mjs → summarizerNodeUtils.js} +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeWithGc.d.mts → summarizerNodeWithGc.d.ts} +4 -5
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeWithGc.mjs → summarizerNodeWithGc.js} +7 -7
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -0
- package/lib/summary/{summarizerTypes.d.mts → summarizerTypes.d.ts} +10 -21
- package/lib/summary/summarizerTypes.d.ts.map +1 -0
- package/lib/summary/{summarizerTypes.mjs → summarizerTypes.js} +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -0
- package/lib/summary/{summaryCollection.d.mts → summaryCollection.d.ts} +1 -1
- package/lib/summary/summaryCollection.d.ts.map +1 -0
- package/lib/summary/{summaryCollection.mjs → summaryCollection.js} +1 -1
- package/lib/summary/summaryCollection.js.map +1 -0
- package/lib/summary/{summaryFormat.d.mts → summaryFormat.d.ts} +16 -3
- package/lib/summary/summaryFormat.d.ts.map +1 -0
- package/lib/summary/{summaryFormat.mjs → summaryFormat.js} +1 -1
- package/lib/summary/summaryFormat.js.map +1 -0
- package/lib/summary/{summaryGenerator.d.mts → summaryGenerator.d.ts} +7 -6
- package/lib/summary/summaryGenerator.d.ts.map +1 -0
- package/lib/summary/{summaryGenerator.mjs → summaryGenerator.js} +11 -2
- package/lib/summary/summaryGenerator.js.map +1 -0
- package/lib/summary/{summaryManager.d.mts → summaryManager.d.ts} +6 -7
- package/lib/summary/summaryManager.d.ts.map +1 -0
- package/lib/summary/{summaryManager.mjs → summaryManager.js} +4 -5
- package/lib/summary/summaryManager.js.map +1 -0
- package/lib/test/batchTracker.spec.js +88 -0
- package/lib/test/batchTracker.spec.js.map +1 -0
- package/lib/test/blobManager.spec.js +835 -0
- package/lib/test/blobManager.spec.js.map +1 -0
- package/lib/test/channelCollection.spec.js +138 -0
- package/lib/test/channelCollection.spec.js.map +1 -0
- package/lib/test/containerRuntime.spec.js +1748 -0
- package/lib/test/containerRuntime.spec.js.map +1 -0
- package/lib/test/dataStoreContext.spec.js +771 -0
- package/lib/test/dataStoreContext.spec.js.map +1 -0
- package/lib/test/dataStoreCreation.spec.js +303 -0
- package/lib/test/dataStoreCreation.spec.js.map +1 -0
- package/lib/test/dataStoreRegistry.spec.js +26 -0
- package/lib/test/dataStoreRegistry.spec.js.map +1 -0
- package/lib/test/fuzz/fuzzUtils.js +66 -0
- package/lib/test/fuzz/fuzzUtils.js.map +1 -0
- package/lib/test/fuzz/summarizer.fuzz.spec.js +31 -0
- package/lib/test/fuzz/summarizer.fuzz.spec.js.map +1 -0
- package/lib/test/fuzz/summarizerFuzzMocks.js +162 -0
- package/lib/test/fuzz/summarizerFuzzMocks.js.map +1 -0
- package/lib/test/fuzz/summarizerFuzzSuite.js +106 -0
- package/lib/test/fuzz/summarizerFuzzSuite.js.map +1 -0
- package/lib/test/gc/garbageCollection.spec.js +1464 -0
- package/lib/test/gc/garbageCollection.spec.js.map +1 -0
- package/lib/test/gc/gcConfigs.spec.js +689 -0
- package/lib/test/gc/gcConfigs.spec.js.map +1 -0
- package/lib/test/gc/gcHelpers.spec.js +110 -0
- package/lib/test/gc/gcHelpers.spec.js.map +1 -0
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js +68 -0
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js.map +1 -0
- package/lib/test/gc/gcStats.spec.js +390 -0
- package/lib/test/gc/gcStats.spec.js.map +1 -0
- package/lib/test/gc/gcSummaryStateTracker.spec.js +228 -0
- package/lib/test/gc/gcSummaryStateTracker.spec.js.map +1 -0
- package/lib/test/gc/gcTelemetry.spec.js +530 -0
- package/lib/test/gc/gcTelemetry.spec.js.map +1 -0
- package/lib/test/gc/gcUnitTestHelpers.js +29 -0
- package/lib/test/gc/gcUnitTestHelpers.js.map +1 -0
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js +192 -0
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js.map +1 -0
- package/lib/test/getPendingBlobs.spec.js +193 -0
- package/lib/test/getPendingBlobs.spec.js.map +1 -0
- package/lib/test/hardwareStats.spec.js +93 -0
- package/lib/test/hardwareStats.spec.js.map +1 -0
- package/lib/test/index.js +6 -0
- package/lib/test/index.js.map +1 -0
- package/lib/test/opLifecycle/OpGroupingManager.spec.js +225 -0
- package/lib/test/opLifecycle/OpGroupingManager.spec.js.map +1 -0
- package/lib/test/opLifecycle/batchManager.spec.js +189 -0
- package/lib/test/opLifecycle/batchManager.spec.js.map +1 -0
- package/lib/test/opLifecycle/opCompressor.spec.js +74 -0
- package/lib/test/opLifecycle/opCompressor.spec.js.map +1 -0
- package/lib/test/opLifecycle/opDecompressor.spec.js +218 -0
- package/lib/test/opLifecycle/opDecompressor.spec.js.map +1 -0
- package/lib/test/opLifecycle/opSplitter.spec.js +272 -0
- package/lib/test/opLifecycle/opSplitter.spec.js.map +1 -0
- package/lib/test/opLifecycle/outbox.spec.js +675 -0
- package/lib/test/opLifecycle/outbox.spec.js.map +1 -0
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js +196 -0
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js.map +1 -0
- package/lib/test/pendingStateManager.spec.js +329 -0
- package/lib/test/pendingStateManager.spec.js.map +1 -0
- package/lib/test/scheduleManager.spec.js +270 -0
- package/lib/test/scheduleManager.spec.js.map +1 -0
- package/lib/test/summarizerNode.spec.js +326 -0
- package/lib/test/summarizerNode.spec.js.map +1 -0
- package/lib/test/summarizerNodeWithGc.spec.js +318 -0
- package/lib/test/summarizerNodeWithGc.spec.js.map +1 -0
- package/lib/test/summary/orderedClientElection.spec.js +535 -0
- package/lib/test/summary/orderedClientElection.spec.js.map +1 -0
- package/lib/test/summary/runningSummarizer.spec.js +1349 -0
- package/lib/test/summary/runningSummarizer.spec.js.map +1 -0
- package/lib/test/summary/summarizer.spec.js +29 -0
- package/lib/test/summary/summarizer.spec.js.map +1 -0
- package/lib/test/summary/summarizerClientElection.spec.js +436 -0
- package/lib/test/summary/summarizerClientElection.spec.js.map +1 -0
- package/lib/test/summary/summarizerHeuristics.spec.js +289 -0
- package/lib/test/summary/summarizerHeuristics.spec.js.map +1 -0
- package/lib/test/summary/summaryCollection.spec.js +200 -0
- package/lib/test/summary/summaryCollection.spec.js.map +1 -0
- package/lib/test/summary/summaryManager.spec.js +430 -0
- package/lib/test/summary/summaryManager.spec.js.map +1 -0
- package/lib/test/summary/testQuorumClients.js +34 -0
- package/lib/test/summary/testQuorumClients.js.map +1 -0
- package/lib/test/throttler.spec.js +175 -0
- package/lib/test/throttler.spec.js.map +1 -0
- package/lib/test/types/validateContainerRuntimePrevious.generated.js +180 -0
- package/lib/test/types/validateContainerRuntimePrevious.generated.js.map +1 -0
- package/lib/{throttler.d.mts → throttler.d.ts} +1 -1
- package/lib/throttler.d.ts.map +1 -0
- package/lib/{throttler.mjs → throttler.js} +1 -1
- package/lib/throttler.js.map +1 -0
- package/package.json +101 -88
- package/src/batchTracker.ts +1 -1
- package/src/blobManager.ts +1 -15
- package/src/{dataStores.ts → channelCollection.ts} +620 -175
- package/src/connectionTelemetry.ts +42 -3
- package/src/containerHandleContext.ts +1 -1
- package/src/containerRuntime.ts +604 -415
- package/src/dataStore.ts +16 -15
- package/src/dataStoreContext.ts +376 -216
- package/src/dataStoreContexts.ts +2 -1
- package/src/deltaManagerSummarizerProxy.ts +132 -7
- package/src/gc/garbageCollection.ts +84 -44
- package/src/gc/gcConfigs.ts +17 -7
- package/src/gc/gcDefinitions.ts +23 -13
- package/src/gc/gcHelpers.ts +2 -2
- package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
- package/src/gc/gcSummaryStateTracker.ts +19 -7
- package/src/gc/gcTelemetry.ts +9 -7
- package/src/gc/gcUnreferencedStateTracker.ts +1 -1
- package/src/gc/index.ts +10 -9
- package/src/index.ts +28 -27
- package/src/messageTypes.ts +3 -3
- package/src/opLifecycle/README.md +2 -4
- package/src/opLifecycle/batchManager.ts +2 -2
- package/src/opLifecycle/definitions.ts +2 -2
- package/src/opLifecycle/index.ts +8 -8
- package/src/opLifecycle/opCompressor.ts +3 -3
- package/src/opLifecycle/opDecompressor.ts +3 -3
- package/src/opLifecycle/opGroupingManager.ts +3 -12
- package/src/opLifecycle/opSplitter.ts +3 -3
- package/src/opLifecycle/outbox.ts +29 -9
- package/src/opLifecycle/remoteMessageProcessor.ts +4 -4
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +19 -13
- package/src/scheduleManager.ts +4 -4
- package/src/summary/index.ts +13 -12
- package/src/summary/orderedClientElection.ts +1 -1
- package/src/summary/runWhileConnectedCoordinator.ts +1 -1
- package/src/summary/runningSummarizer.ts +52 -32
- package/src/summary/summarizer.ts +7 -7
- package/src/summary/summarizerClientElection.ts +2 -2
- package/src/summary/summarizerHeuristics.ts +3 -3
- package/src/summary/summarizerNode/index.ts +6 -3
- package/src/summary/summarizerNode/summarizerNode.ts +50 -5
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +14 -1
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +11 -11
- package/src/summary/summarizerTypes.ts +11 -23
- package/src/summary/summaryFormat.ts +16 -2
- package/src/summary/summaryGenerator.ts +16 -4
- package/src/summary/summaryManager.ts +6 -7
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.json +2 -5
- package/dist/dataStores.d.ts +0 -151
- package/dist/dataStores.d.ts.map +0 -1
- package/dist/dataStores.js.map +0 -1
- package/dist/deltaManagerProxyBase.d.ts.map +0 -1
- package/dist/deltaManagerProxyBase.js +0 -77
- package/dist/deltaManagerProxyBase.js.map +0 -1
- package/lib/batchTracker.d.mts.map +0 -1
- package/lib/batchTracker.mjs.map +0 -1
- package/lib/blobManager.d.mts.map +0 -1
- package/lib/blobManager.mjs.map +0 -1
- package/lib/connectionTelemetry.d.mts.map +0 -1
- package/lib/connectionTelemetry.mjs.map +0 -1
- package/lib/containerHandleContext.d.mts.map +0 -1
- package/lib/containerHandleContext.mjs.map +0 -1
- package/lib/containerRuntime.d.mts.map +0 -1
- package/lib/containerRuntime.mjs.map +0 -1
- package/lib/dataStore.d.mts.map +0 -1
- package/lib/dataStore.mjs.map +0 -1
- package/lib/dataStoreContext.d.mts.map +0 -1
- package/lib/dataStoreContext.mjs.map +0 -1
- package/lib/dataStoreContexts.d.mts.map +0 -1
- package/lib/dataStoreContexts.mjs.map +0 -1
- package/lib/dataStoreRegistry.d.mts.map +0 -1
- package/lib/dataStoreRegistry.mjs.map +0 -1
- package/lib/dataStores.d.mts +0 -151
- package/lib/dataStores.d.mts.map +0 -1
- package/lib/dataStores.mjs.map +0 -1
- package/lib/deltaManagerProxyBase.d.mts +0 -35
- package/lib/deltaManagerProxyBase.d.mts.map +0 -1
- package/lib/deltaManagerProxyBase.mjs +0 -73
- package/lib/deltaManagerProxyBase.mjs.map +0 -1
- package/lib/deltaManagerSummarizerProxy.d.mts +0 -19
- package/lib/deltaManagerSummarizerProxy.d.mts.map +0 -1
- package/lib/deltaManagerSummarizerProxy.mjs +0 -38
- package/lib/deltaManagerSummarizerProxy.mjs.map +0 -1
- package/lib/deltaScheduler.d.mts.map +0 -1
- package/lib/deltaScheduler.mjs.map +0 -1
- package/lib/error.d.mts.map +0 -1
- package/lib/error.mjs.map +0 -1
- package/lib/gc/garbageCollection.d.mts.map +0 -1
- package/lib/gc/garbageCollection.mjs.map +0 -1
- package/lib/gc/gcConfigs.d.mts.map +0 -1
- package/lib/gc/gcConfigs.mjs.map +0 -1
- package/lib/gc/gcDefinitions.d.mts.map +0 -1
- package/lib/gc/gcDefinitions.mjs.map +0 -1
- package/lib/gc/gcHelpers.mjs.map +0 -1
- package/lib/gc/gcReferenceGraphAlgorithm.d.mts.map +0 -1
- package/lib/gc/gcReferenceGraphAlgorithm.mjs.map +0 -1
- package/lib/gc/gcSummaryDefinitions.d.mts.map +0 -1
- package/lib/gc/gcSummaryDefinitions.mjs.map +0 -1
- package/lib/gc/gcSummaryStateTracker.d.mts.map +0 -1
- package/lib/gc/gcSummaryStateTracker.mjs.map +0 -1
- package/lib/gc/gcTelemetry.d.mts.map +0 -1
- package/lib/gc/gcTelemetry.mjs.map +0 -1
- package/lib/gc/gcUnreferencedStateTracker.d.mts.map +0 -1
- package/lib/gc/gcUnreferencedStateTracker.mjs.map +0 -1
- package/lib/gc/index.d.mts +0 -13
- package/lib/gc/index.d.mts.map +0 -1
- package/lib/gc/index.mjs.map +0 -1
- package/lib/index.d.mts.map +0 -1
- package/lib/index.mjs +0 -25
- package/lib/index.mjs.map +0 -1
- package/lib/messageTypes.d.mts.map +0 -1
- package/lib/messageTypes.mjs.map +0 -1
- package/lib/metadata.d.mts.map +0 -1
- package/lib/metadata.mjs.map +0 -1
- package/lib/opLifecycle/batchManager.d.mts.map +0 -1
- package/lib/opLifecycle/batchManager.mjs.map +0 -1
- package/lib/opLifecycle/definitions.d.mts.map +0 -1
- package/lib/opLifecycle/definitions.mjs.map +0 -1
- package/lib/opLifecycle/index.d.mts +0 -13
- package/lib/opLifecycle/index.d.mts.map +0 -1
- package/lib/opLifecycle/index.mjs +0 -12
- package/lib/opLifecycle/index.mjs.map +0 -1
- package/lib/opLifecycle/opCompressor.d.mts.map +0 -1
- package/lib/opLifecycle/opCompressor.mjs.map +0 -1
- package/lib/opLifecycle/opDecompressor.d.mts.map +0 -1
- package/lib/opLifecycle/opDecompressor.mjs.map +0 -1
- package/lib/opLifecycle/opGroupingManager.d.mts.map +0 -1
- package/lib/opLifecycle/opGroupingManager.mjs.map +0 -1
- package/lib/opLifecycle/opSplitter.d.mts.map +0 -1
- package/lib/opLifecycle/opSplitter.mjs.map +0 -1
- package/lib/opLifecycle/outbox.d.mts.map +0 -1
- package/lib/opLifecycle/outbox.mjs.map +0 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.mts.map +0 -1
- package/lib/opLifecycle/remoteMessageProcessor.mjs.map +0 -1
- package/lib/opProperties.d.mts.map +0 -1
- package/lib/opProperties.mjs.map +0 -1
- package/lib/packageVersion.d.mts.map +0 -1
- package/lib/packageVersion.mjs.map +0 -1
- package/lib/pendingStateManager.d.mts.map +0 -1
- package/lib/pendingStateManager.mjs.map +0 -1
- package/lib/scheduleManager.d.mts.map +0 -1
- package/lib/scheduleManager.mjs.map +0 -1
- package/lib/storageServiceWithAttachBlobs.d.mts.map +0 -1
- package/lib/storageServiceWithAttachBlobs.mjs.map +0 -1
- package/lib/summary/index.d.mts.map +0 -1
- package/lib/summary/index.mjs.map +0 -1
- package/lib/summary/orderedClientElection.d.mts.map +0 -1
- package/lib/summary/orderedClientElection.mjs.map +0 -1
- package/lib/summary/runWhileConnectedCoordinator.d.mts.map +0 -1
- package/lib/summary/runWhileConnectedCoordinator.mjs.map +0 -1
- package/lib/summary/runningSummarizer.d.mts.map +0 -1
- package/lib/summary/runningSummarizer.mjs.map +0 -1
- package/lib/summary/summarizer.d.mts.map +0 -1
- package/lib/summary/summarizer.mjs.map +0 -1
- package/lib/summary/summarizerClientElection.d.mts.map +0 -1
- package/lib/summary/summarizerClientElection.mjs.map +0 -1
- package/lib/summary/summarizerHeuristics.d.mts.map +0 -1
- package/lib/summary/summarizerHeuristics.mjs.map +0 -1
- package/lib/summary/summarizerNode/index.d.mts.map +0 -1
- package/lib/summary/summarizerNode/index.mjs +0 -7
- package/lib/summary/summarizerNode/index.mjs.map +0 -1
- package/lib/summary/summarizerNode/summarizerNode.d.mts.map +0 -1
- package/lib/summary/summarizerNode/summarizerNode.mjs.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.mts.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.mjs.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.mts.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.mjs.map +0 -1
- package/lib/summary/summarizerTypes.d.mts.map +0 -1
- package/lib/summary/summarizerTypes.mjs.map +0 -1
- package/lib/summary/summaryCollection.d.mts.map +0 -1
- package/lib/summary/summaryCollection.mjs.map +0 -1
- package/lib/summary/summaryFormat.d.mts.map +0 -1
- package/lib/summary/summaryFormat.mjs.map +0 -1
- package/lib/summary/summaryGenerator.d.mts.map +0 -1
- package/lib/summary/summaryGenerator.mjs.map +0 -1
- package/lib/summary/summaryManager.d.mts.map +0 -1
- package/lib/summary/summaryManager.mjs.map +0 -1
- package/lib/throttler.d.mts.map +0 -1
- package/lib/throttler.mjs.map +0 -1
- package/src/deltaManagerProxyBase.ts +0 -111
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
import { AttachState, LoaderHeader, } from "@fluidframework/container-definitions";
|
|
2
|
-
import { assert, delay, LazyPromise } from "@fluidframework/core-utils";
|
|
2
|
+
import { assert, Deferred, delay, LazyPromise, PromiseCache } from "@fluidframework/core-utils";
|
|
3
3
|
import { Trace, TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
4
|
-
import { createChildLogger, createChildMonitoringContext, DataCorruptionError, DataProcessingError, GenericError, raiseConnectedEvent, PerformanceEvent,
|
|
5
|
-
// eslint-disable-next-line import/no-deprecated
|
|
6
|
-
TaggedLoggerAdapter, wrapError, UsageError, LoggingError, createSampledLogger, } from "@fluidframework/telemetry-utils";
|
|
4
|
+
import { createChildLogger, createChildMonitoringContext, DataCorruptionError, DataProcessingError, GenericError, raiseConnectedEvent, PerformanceEvent, TaggedLoggerAdapter, wrapError, UsageError, LoggingError, createSampledLogger, loggerToMonitoringContext, } from "@fluidframework/telemetry-utils";
|
|
7
5
|
import { DriverHeader, FetchSource, } from "@fluidframework/driver-definitions";
|
|
8
6
|
import { readAndParse } from "@fluidframework/driver-utils";
|
|
9
7
|
import { MessageType, SummaryType, } from "@fluidframework/protocol-definitions";
|
|
10
8
|
import { FlushMode, FlushModeExperimental, gcTreeKey, channelsTreeName, } from "@fluidframework/runtime-definitions";
|
|
11
|
-
import { addBlobToSummary, addSummarizeResultToSummary,
|
|
9
|
+
import { addBlobToSummary, addSummarizeResultToSummary, RequestParser, create404Response, exceptionToResponse, GCDataBuilder, seqFromTree, calculateStats, TelemetryContext, responseToException, } from "@fluidframework/runtime-utils";
|
|
12
10
|
import { v4 as uuid } from "uuid";
|
|
13
|
-
import { ContainerFluidHandleContext } from "./containerHandleContext.
|
|
14
|
-
import { FluidDataStoreRegistry } from "./dataStoreRegistry.
|
|
15
|
-
import { ReportOpPerfTelemetry } from "./connectionTelemetry.
|
|
16
|
-
import { PendingStateManager, } from "./pendingStateManager.
|
|
17
|
-
import { pkgVersion } from "./packageVersion.
|
|
18
|
-
import { BlobManager } from "./blobManager.
|
|
19
|
-
import {
|
|
20
|
-
import { aliasBlobName, blobsTreeName, chunksBlobName, createRootSummarizerNodeWithGC, electedSummarizerBlobName, extractSummaryMetadataMessage, idCompressorBlobName, metadataBlobName, Summarizer, SummaryManager, wrapSummaryInChannelsTree, SummaryCollection, OrderedClientCollection, OrderedClientElection, SummarizerClientElection, summarizerClientType, RunWhileConnectedCoordinator, RetriableSummaryError, } from "./summary/index.
|
|
21
|
-
import { formExponentialFn, Throttler } from "./throttler.
|
|
22
|
-
import { GarbageCollector, GCNodeType, gcGenerationOptionName,
|
|
23
|
-
import { channelToDataStore
|
|
24
|
-
import { BindBatchTracker } from "./batchTracker.
|
|
25
|
-
import { ScheduleManager } from "./scheduleManager.
|
|
26
|
-
import { OpCompressor, OpDecompressor, Outbox, OpSplitter, RemoteMessageProcessor, OpGroupingManager, getLongStack, } from "./opLifecycle/index.
|
|
27
|
-
import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy.
|
|
28
|
-
import { ContainerMessageType, } from "./messageTypes.
|
|
11
|
+
import { ContainerFluidHandleContext } from "./containerHandleContext.js";
|
|
12
|
+
import { FluidDataStoreRegistry } from "./dataStoreRegistry.js";
|
|
13
|
+
import { ReportOpPerfTelemetry } from "./connectionTelemetry.js";
|
|
14
|
+
import { PendingStateManager, } from "./pendingStateManager.js";
|
|
15
|
+
import { pkgVersion } from "./packageVersion.js";
|
|
16
|
+
import { BlobManager } from "./blobManager.js";
|
|
17
|
+
import { ChannelCollection, getSummaryForDatastores, wrapContext } from "./channelCollection.js";
|
|
18
|
+
import { aliasBlobName, blobsTreeName, chunksBlobName, createRootSummarizerNodeWithGC, electedSummarizerBlobName, extractSummaryMetadataMessage, idCompressorBlobName, metadataBlobName, Summarizer, SummaryManager, wrapSummaryInChannelsTree, SummaryCollection, OrderedClientCollection, OrderedClientElection, SummarizerClientElection, summarizerClientType, RunWhileConnectedCoordinator, RetriableSummaryError, rootHasIsolatedChannels, } from "./summary/index.js";
|
|
19
|
+
import { formExponentialFn, Throttler } from "./throttler.js";
|
|
20
|
+
import { GarbageCollector, GCNodeType, gcGenerationOptionName, } from "./gc/index.js";
|
|
21
|
+
import { channelToDataStore } from "./dataStore.js";
|
|
22
|
+
import { BindBatchTracker } from "./batchTracker.js";
|
|
23
|
+
import { ScheduleManager } from "./scheduleManager.js";
|
|
24
|
+
import { OpCompressor, OpDecompressor, Outbox, OpSplitter, RemoteMessageProcessor, OpGroupingManager, getLongStack, } from "./opLifecycle/index.js";
|
|
25
|
+
import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy.js";
|
|
26
|
+
import { ContainerMessageType, } from "./messageTypes.js";
|
|
29
27
|
/**
|
|
30
28
|
* Utility to implement compat behaviors given an unknown message type
|
|
31
29
|
* The parameters are typed to support compile-time enforcement of handling all known types/behaviors
|
|
@@ -55,26 +53,6 @@ export const DefaultSummaryConfiguration = {
|
|
|
55
53
|
runtimeOpWeight: 1.0,
|
|
56
54
|
nonRuntimeHeuristicThreshold: 20,
|
|
57
55
|
};
|
|
58
|
-
/**
|
|
59
|
-
* Accepted header keys for requests coming to the runtime.
|
|
60
|
-
* @internal
|
|
61
|
-
*/
|
|
62
|
-
export var RuntimeHeaders;
|
|
63
|
-
(function (RuntimeHeaders) {
|
|
64
|
-
/** True to wait for a data store to be created and loaded before returning it. */
|
|
65
|
-
RuntimeHeaders["wait"] = "wait";
|
|
66
|
-
/** True if the request is coming from an IFluidHandle. */
|
|
67
|
-
RuntimeHeaders["viaHandle"] = "viaHandle";
|
|
68
|
-
})(RuntimeHeaders || (RuntimeHeaders = {}));
|
|
69
|
-
/** True if a tombstoned object should be returned without erroring
|
|
70
|
-
* @alpha
|
|
71
|
-
*/
|
|
72
|
-
export const AllowTombstoneRequestHeaderKey = "allowTombstone"; // Belongs in the enum above, but avoiding the breaking change
|
|
73
|
-
/**
|
|
74
|
-
* [IRRELEVANT IF throwOnInactiveLoad OPTION NOT SET] True if an inactive object should be returned without erroring
|
|
75
|
-
* @internal
|
|
76
|
-
*/
|
|
77
|
-
export const AllowInactiveRequestHeaderKey = "allowInactive"; // Belongs in the enum above, but avoiding the breaking change
|
|
78
56
|
/**
|
|
79
57
|
* Tombstone error responses will have this header set to true
|
|
80
58
|
* @alpha
|
|
@@ -243,7 +221,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
243
221
|
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
244
222
|
const backCompatContext = context;
|
|
245
223
|
const passLogger = backCompatContext.taggedLogger ??
|
|
246
|
-
// eslint-disable-next-line import/no-deprecated
|
|
247
224
|
new TaggedLoggerAdapter(backCompatContext.logger);
|
|
248
225
|
const logger = createChildLogger({
|
|
249
226
|
logger: passLogger,
|
|
@@ -253,7 +230,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
253
230
|
},
|
|
254
231
|
},
|
|
255
232
|
});
|
|
256
|
-
const
|
|
233
|
+
const mc = loggerToMonitoringContext(logger);
|
|
234
|
+
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor = "off", chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, enableGroupedBatching = false, } = runtimeOptions;
|
|
257
235
|
const registry = new FluidDataStoreRegistry(registryEntries);
|
|
258
236
|
const tryFetchBlob = async (blobName) => {
|
|
259
237
|
const blobId = context.baseSnapshot?.blobs[blobName];
|
|
@@ -298,9 +276,37 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
298
276
|
}
|
|
299
277
|
}
|
|
300
278
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
279
|
+
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
280
|
+
// allow new containers to turn it on
|
|
281
|
+
let idCompressorMode;
|
|
282
|
+
if (existing) {
|
|
283
|
+
// This setting has to be sticky for correctness:
|
|
284
|
+
// 1) if compressior is OFF, it can't be enabled, as already running clients (in given document session) do not know
|
|
285
|
+
// how to process compressor ops
|
|
286
|
+
// 2) if it's ON, then all sessions should load compressor right away
|
|
287
|
+
// 3) Same logic applies for "delayed" mode
|
|
288
|
+
// Maybe in the future we will need to enabled (and figure how to do it safely) "delayed" -> "on" change.
|
|
289
|
+
// We could do "off" -> "on" transtition too, if all clients start loading compressor (but not using it initially) and do so for a while -
|
|
290
|
+
// this will allow clients to eventually to disregard "off" setting (when it's safe so) and start using compressor in future sessions.
|
|
291
|
+
// Everyting is possible, but it needs to be designed and executed carefully, when such need arises.
|
|
292
|
+
idCompressorMode = metadata?.idCompressorMode ?? "off";
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
// FG overwrite
|
|
296
|
+
const enabled = mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled");
|
|
297
|
+
switch (enabled) {
|
|
298
|
+
case true:
|
|
299
|
+
idCompressorMode = "on";
|
|
300
|
+
break;
|
|
301
|
+
case false:
|
|
302
|
+
idCompressorMode = "off";
|
|
303
|
+
break;
|
|
304
|
+
default:
|
|
305
|
+
idCompressorMode = enableRuntimeIdCompressor;
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const createIdCompressorFn = async () => {
|
|
304
310
|
const { createIdCompressor, deserializeIdCompressor, createSessionId } = await import("@fluidframework/id-compressor");
|
|
305
311
|
/**
|
|
306
312
|
* Because the IdCompressor emits so much telemetry, this function is used to sample
|
|
@@ -317,15 +323,15 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
317
323
|
const compressorLogger = createSampledLogger(logger, idCompressorEventSampler);
|
|
318
324
|
const pendingLocalState = context.pendingLocalState;
|
|
319
325
|
if (pendingLocalState?.pendingIdCompressorState !== undefined) {
|
|
320
|
-
|
|
326
|
+
return deserializeIdCompressor(pendingLocalState.pendingIdCompressorState, compressorLogger);
|
|
321
327
|
}
|
|
322
328
|
else if (serializedIdCompressor !== undefined) {
|
|
323
|
-
|
|
329
|
+
return deserializeIdCompressor(serializedIdCompressor, createSessionId(), compressorLogger);
|
|
324
330
|
}
|
|
325
331
|
else {
|
|
326
|
-
|
|
332
|
+
return createIdCompressor(compressorLogger);
|
|
327
333
|
}
|
|
328
|
-
}
|
|
334
|
+
};
|
|
329
335
|
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], {
|
|
330
336
|
summaryOptions,
|
|
331
337
|
gcOptions,
|
|
@@ -337,7 +343,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
337
343
|
enableRuntimeIdCompressor,
|
|
338
344
|
enableOpReentryCheck,
|
|
339
345
|
enableGroupedBatching,
|
|
340
|
-
}, containerScope, logger, existing, blobManagerSnapshot, context.storage,
|
|
346
|
+
}, containerScope, logger, existing, blobManagerSnapshot, context.storage, createIdCompressorFn, idCompressorMode, provideEntryPoint, requestHandler, undefined);
|
|
341
347
|
// Apply stashed ops with a reference sequence number equal to the sequence number of the snapshot,
|
|
342
348
|
// or zero. This must be done before Container replays saved ops.
|
|
343
349
|
await runtime.pendingStateManager.applyStashedOpsAt(runtimeSequenceNumber ?? 0);
|
|
@@ -351,6 +357,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
351
357
|
get storage() {
|
|
352
358
|
return this._storage;
|
|
353
359
|
}
|
|
360
|
+
get containerRuntime() {
|
|
361
|
+
return this;
|
|
362
|
+
}
|
|
354
363
|
get flushMode() {
|
|
355
364
|
return this._flushMode;
|
|
356
365
|
}
|
|
@@ -363,6 +372,25 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
363
372
|
get attachState() {
|
|
364
373
|
return this._getAttachState();
|
|
365
374
|
}
|
|
375
|
+
/**
|
|
376
|
+
* See IContainerRuntimeBase.idCompressor() for details.
|
|
377
|
+
*/
|
|
378
|
+
get idCompressor() {
|
|
379
|
+
// Expose ID Compressor only if it's On from the start.
|
|
380
|
+
// If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
|
|
381
|
+
// That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
|
|
382
|
+
// to reason over such things as session ID space.
|
|
383
|
+
if (this.idCompressorMode === "on") {
|
|
384
|
+
assert(this._idCompressor !== undefined, 0x8ea /* compressor should have been loaded */);
|
|
385
|
+
return this._idCompressor;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* See IContainerRuntimeBase.generateDocumentUniqueId() for details.
|
|
390
|
+
*/
|
|
391
|
+
generateDocumentUniqueId() {
|
|
392
|
+
return this._idCompressor?.generateDocumentUniqueId() ?? uuid();
|
|
393
|
+
}
|
|
366
394
|
get IFluidHandleContext() {
|
|
367
395
|
return this.handleContext;
|
|
368
396
|
}
|
|
@@ -400,9 +428,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
400
428
|
isSummariesDisabled() {
|
|
401
429
|
return this.summaryConfiguration.state === "disabled";
|
|
402
430
|
}
|
|
403
|
-
isHeuristicsDisabled() {
|
|
404
|
-
return this.summaryConfiguration.state === "disableHeuristics";
|
|
405
|
-
}
|
|
406
431
|
getMaxOpsSinceLastSummary() {
|
|
407
432
|
return this.summaryConfiguration.state !== "disabled"
|
|
408
433
|
? this.summaryConfiguration.maxOpsSinceLastSummary
|
|
@@ -427,7 +452,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
427
452
|
return this.garbageCollector.throwOnTombstoneUsage;
|
|
428
453
|
}
|
|
429
454
|
/***/
|
|
430
|
-
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage,
|
|
455
|
+
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, createIdCompressor, idCompressorMode, provideEntryPoint, requestHandler, summaryConfiguration = {
|
|
431
456
|
// the defaults
|
|
432
457
|
...DefaultSummaryConfiguration,
|
|
433
458
|
// the runtime configuration overrides
|
|
@@ -435,13 +460,24 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
435
460
|
}) {
|
|
436
461
|
super();
|
|
437
462
|
this.registry = registry;
|
|
463
|
+
this.metadata = metadata;
|
|
438
464
|
this.runtimeOptions = runtimeOptions;
|
|
439
465
|
this.containerScope = containerScope;
|
|
440
466
|
this.logger = logger;
|
|
441
467
|
this._storage = _storage;
|
|
468
|
+
this.createIdCompressor = createIdCompressor;
|
|
469
|
+
this.idCompressorMode = idCompressorMode;
|
|
442
470
|
this.requestHandler = requestHandler;
|
|
443
471
|
this.summaryConfiguration = summaryConfiguration;
|
|
444
472
|
this.imminentClosure = false;
|
|
473
|
+
// We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
|
|
474
|
+
// Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
|
|
475
|
+
this.pendingIdCompressorOps = [];
|
|
476
|
+
/**
|
|
477
|
+
* True if we have ID compressor loading in-flight (async operation). Useful only for
|
|
478
|
+
* this.idCompressorMode === "delayed" mode
|
|
479
|
+
*/
|
|
480
|
+
this.compressorLoadInitiated = false;
|
|
445
481
|
this.defaultMaxConsecutiveReconnects = 7;
|
|
446
482
|
this._orderSequentiallyCalls = 0;
|
|
447
483
|
this.flushTaskExists = false;
|
|
@@ -463,6 +499,13 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
463
499
|
signalTimestamp: 0,
|
|
464
500
|
trackingSignalSequenceNumber: undefined,
|
|
465
501
|
};
|
|
502
|
+
/**
|
|
503
|
+
* It a cache for holding mapping for loading groupIds with its snapshot from the service. Add expiry policy of 1 minute.
|
|
504
|
+
* Starting with 1 min and based on recorded usage we can tweak it later on.
|
|
505
|
+
*/
|
|
506
|
+
this.snapshotCacheForLoadingGroupIds = new PromiseCache({
|
|
507
|
+
expiry: { policy: "absolute", durationMs: 60000 },
|
|
508
|
+
});
|
|
466
509
|
const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, loader, pendingLocalState, supportedFeatures, } = context;
|
|
467
510
|
this.innerDeltaManager = deltaManager;
|
|
468
511
|
this.deltaManager = new DeltaManagerSummarizerProxy(this.innerDeltaManager);
|
|
@@ -472,7 +515,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
472
515
|
this.submitBatchFn = submitBatchFn;
|
|
473
516
|
this.submitSummaryFn = submitSummaryFn;
|
|
474
517
|
this.submitSignalFn = submitSignalFn;
|
|
475
|
-
|
|
518
|
+
// TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
|
|
519
|
+
// Values are generally expected to be set from the runtime side.
|
|
520
|
+
this.options = options ?? {};
|
|
476
521
|
this.clientDetails = clientDetails;
|
|
477
522
|
this.isSummarizerClient = this.clientDetails.type === summarizerClientType;
|
|
478
523
|
this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
|
|
@@ -510,9 +555,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
510
555
|
// summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
|
|
511
556
|
// the count is reset to 0.
|
|
512
557
|
loadSummaryNumber = metadata?.summaryNumber ?? 0;
|
|
513
|
-
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
514
|
-
// allow new containers to turn it on
|
|
515
|
-
this.idCompressorEnabled = metadata?.idCompressorEnabled ?? false;
|
|
516
558
|
}
|
|
517
559
|
else {
|
|
518
560
|
this.createContainerMetadata = {
|
|
@@ -520,9 +562,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
520
562
|
createContainerTimestamp: Date.now(),
|
|
521
563
|
};
|
|
522
564
|
loadSummaryNumber = 0;
|
|
523
|
-
this.idCompressorEnabled =
|
|
524
|
-
this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled") ??
|
|
525
|
-
idCompressor !== undefined;
|
|
526
565
|
}
|
|
527
566
|
this.nextSummaryNumber = loadSummaryNumber + 1;
|
|
528
567
|
this.messageAtLastSummary = metadata?.message;
|
|
@@ -557,12 +596,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
557
596
|
// Allow for a break-glass config to override the options
|
|
558
597
|
disableOpReentryCheck !== true;
|
|
559
598
|
this.summariesDisabled = this.isSummariesDisabled();
|
|
560
|
-
this.heuristicsDisabled = this.isHeuristicsDisabled();
|
|
561
599
|
this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
|
|
562
600
|
this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
|
|
563
|
-
if (this.idCompressorEnabled) {
|
|
564
|
-
this.idCompressor = idCompressor;
|
|
565
|
-
}
|
|
566
601
|
this.maxConsecutiveReconnects =
|
|
567
602
|
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
|
|
568
603
|
this.defaultMaxConsecutiveReconnects;
|
|
@@ -599,6 +634,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
599
634
|
getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
|
|
600
635
|
readAndParseBlob: async (id) => readAndParse(this.storage, id),
|
|
601
636
|
submitMessage: (message) => this.submit(message),
|
|
637
|
+
sessionExpiryTimerStarted: pendingRuntimeState?.sessionExpiryTimerStarted,
|
|
602
638
|
});
|
|
603
639
|
const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
|
|
604
640
|
this.summarizerNode = createRootSummarizerNodeWithGC(createChildLogger({ logger: this.logger, namespace: "SummarizerNode" }),
|
|
@@ -621,7 +657,16 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
621
657
|
if (baseSnapshot) {
|
|
622
658
|
this.summarizerNode.updateBaseSummaryState(baseSnapshot);
|
|
623
659
|
}
|
|
624
|
-
|
|
660
|
+
const parentContext = wrapContext(this);
|
|
661
|
+
// Due to a mismatch between different layers in terms of
|
|
662
|
+
// what is the interface of passing signals, we need the
|
|
663
|
+
// downstream stores to wrap the signal.
|
|
664
|
+
parentContext.submitSignal = (type, content, targetClientId) => {
|
|
665
|
+
const envelope1 = content;
|
|
666
|
+
const envelope2 = this.createNewSignalEnvelope(envelope1.address, type, envelope1.contents);
|
|
667
|
+
return this.submitSignalFn(envelope2, targetClientId);
|
|
668
|
+
};
|
|
669
|
+
this.channelCollection = new ChannelCollection(getSummaryForDatastores(baseSnapshot, metadata), parentContext, this.mc.logger, (path, reason, timestampMs, packagePath, request, headerData) => this.garbageCollector.nodeUpdated(path, reason, timestampMs, packagePath, request, headerData), (path) => this.garbageCollector.isNodeDeleted(path), new Map(dataStoreAliasMap), async (runtime) => provideEntryPoint);
|
|
625
670
|
this.blobManager = new BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (localId, blobId) => {
|
|
626
671
|
if (!this.disposed) {
|
|
627
672
|
this.submit({ type: ContainerMessageType.BlobAttach, contents: undefined }, undefined, {
|
|
@@ -639,6 +684,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
639
684
|
reSubmit: this.reSubmit.bind(this),
|
|
640
685
|
reSubmitBatch: this.reSubmitBatch.bind(this),
|
|
641
686
|
isActiveConnection: () => this.innerDeltaManager.active,
|
|
687
|
+
isAttached: () => this.attachState !== AttachState.Detached,
|
|
642
688
|
}, pendingRuntimeState?.pending, this.logger);
|
|
643
689
|
const disableCompression = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionDisabled");
|
|
644
690
|
const compressionOptions = disableCompression === true
|
|
@@ -730,7 +776,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
730
776
|
// throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
|
|
731
777
|
formExponentialFn({ coefficient: 20, initialDelay: 0 })), {
|
|
732
778
|
initialDelayMs: this.initialSummarizerDelayMs,
|
|
733
|
-
}
|
|
779
|
+
});
|
|
734
780
|
this.summaryManager.on("summarize", (eventProps) => {
|
|
735
781
|
this.emit("summarize", eventProps);
|
|
736
782
|
});
|
|
@@ -745,25 +791,26 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
745
791
|
this.mc.logger.sendTelemetryEvent({
|
|
746
792
|
eventName: "ContainerLoadStats",
|
|
747
793
|
...this.createContainerMetadata,
|
|
748
|
-
...this.
|
|
794
|
+
...this.channelCollection.containerLoadStats,
|
|
749
795
|
summaryNumber: loadSummaryNumber,
|
|
750
796
|
summaryFormatVersion: metadata?.summaryFormatVersion,
|
|
751
797
|
disableIsolatedChannels: metadata?.disableIsolatedChannels,
|
|
752
798
|
gcVersion: metadata?.gcFeature,
|
|
753
799
|
options: JSON.stringify(runtimeOptions),
|
|
800
|
+
idCompressorModeMetadata: metadata?.idCompressorMode,
|
|
801
|
+
idCompressorMode: this.idCompressorMode,
|
|
754
802
|
featureGates: JSON.stringify({
|
|
755
803
|
disableCompression,
|
|
756
804
|
disableOpReentryCheck,
|
|
757
805
|
disableChunking,
|
|
758
806
|
disableAttachReorder: this.disableAttachReorder,
|
|
759
807
|
disablePartialFlush,
|
|
760
|
-
idCompressorEnabled: this.idCompressorEnabled,
|
|
761
808
|
closeSummarizerDelayOverride,
|
|
762
809
|
}),
|
|
763
810
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
764
811
|
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
765
812
|
});
|
|
766
|
-
ReportOpPerfTelemetry(this.clientId, this.deltaManager, this.logger);
|
|
813
|
+
ReportOpPerfTelemetry(this.clientId, this.deltaManager, this, this.logger);
|
|
767
814
|
BindBatchTracker(this, this.logger);
|
|
768
815
|
this.entryPoint = new LazyPromise(async () => {
|
|
769
816
|
if (this.isSummarizerClient) {
|
|
@@ -772,11 +819,33 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
772
819
|
}
|
|
773
820
|
return provideEntryPoint(this);
|
|
774
821
|
});
|
|
822
|
+
// If we loaded from pending state, then we need to skip any ops that are already accounted in such
|
|
823
|
+
// saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
|
|
824
|
+
this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
|
|
825
|
+
}
|
|
826
|
+
getCreateChildSummarizerNodeFn(id, createParam) {
|
|
827
|
+
return (summarizeInternal, getGCDataFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn);
|
|
828
|
+
}
|
|
829
|
+
deleteChildSummarizerNode(id) {
|
|
830
|
+
return this.summarizerNode.deleteChild(id);
|
|
831
|
+
}
|
|
832
|
+
/* IFluidParentContext APIs that should not be called on Root */
|
|
833
|
+
makeLocallyVisible() {
|
|
834
|
+
assert(false, 0x8eb /* should not be called */);
|
|
835
|
+
}
|
|
836
|
+
setChannelDirty(address) {
|
|
837
|
+
assert(false, "should not be called");
|
|
775
838
|
}
|
|
776
839
|
/**
|
|
777
840
|
* Initializes the state from the base snapshot this container runtime loaded from.
|
|
778
841
|
*/
|
|
779
842
|
async initializeBaseState() {
|
|
843
|
+
if (this.idCompressorMode === "on" ||
|
|
844
|
+
(this.idCompressorMode === "delayed" && this.connected)) {
|
|
845
|
+
// This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
|
|
846
|
+
assert(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
|
|
847
|
+
this._idCompressor = await this.createIdCompressor();
|
|
848
|
+
}
|
|
780
849
|
await this.garbageCollector.initializeBaseState();
|
|
781
850
|
}
|
|
782
851
|
dispose(error) {
|
|
@@ -795,11 +864,110 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
795
864
|
}
|
|
796
865
|
this.garbageCollector.dispose();
|
|
797
866
|
this._summarizer?.dispose();
|
|
798
|
-
this.
|
|
867
|
+
this.channelCollection.dispose();
|
|
799
868
|
this.pendingStateManager.dispose();
|
|
800
869
|
this.emit("dispose");
|
|
801
870
|
this.removeAllListeners();
|
|
802
871
|
}
|
|
872
|
+
/**
|
|
873
|
+
* Api to fetch the snapshot from the service for a loadingGroupIds.
|
|
874
|
+
* @param loadingGroupIds - LoadingGroupId for which the snapshot is asked for.
|
|
875
|
+
* @param pathParts - Parts of the path, which we want to extract from the snapshot tree.
|
|
876
|
+
* @returns - snapshotTree and the sequence number of the snapshot.
|
|
877
|
+
*/
|
|
878
|
+
async getSnapshotForLoadingGroupId(loadingGroupIds, pathParts) {
|
|
879
|
+
const sortedLoadingGroupIds = loadingGroupIds.sort();
|
|
880
|
+
assert(this.storage.getSnapshot !== undefined, 0x8ed /* getSnapshot api should be defined if used */);
|
|
881
|
+
let loadedFromCache = true;
|
|
882
|
+
// Lookup up in the cache, if not present then make the network call as multiple datastores could
|
|
883
|
+
// be in same loading group. So, once we have fetched the snapshot for that loading group on
|
|
884
|
+
// any request, then cache that as same group could be requested in future too.
|
|
885
|
+
const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(), async () => {
|
|
886
|
+
assert(this.storage.getSnapshot !== undefined, 0x8ee /* getSnapshot api should be defined if used */);
|
|
887
|
+
loadedFromCache = false;
|
|
888
|
+
return this.storage.getSnapshot({
|
|
889
|
+
cacheSnapshot: false,
|
|
890
|
+
scenarioName: "snapshotForLoadingGroupId",
|
|
891
|
+
loadingGroupIds: sortedLoadingGroupIds,
|
|
892
|
+
});
|
|
893
|
+
});
|
|
894
|
+
this.logger.sendTelemetryEvent({
|
|
895
|
+
eventName: "GroupIdSnapshotFetched",
|
|
896
|
+
details: JSON.stringify({
|
|
897
|
+
fromCache: loadedFromCache,
|
|
898
|
+
loadingGroupIds: loadingGroupIds.join(","),
|
|
899
|
+
}),
|
|
900
|
+
});
|
|
901
|
+
// Find the snapshotTree inside the returned snapshot based on the path as given in the request.
|
|
902
|
+
const hasIsolatedChannels = rootHasIsolatedChannels(this.metadata);
|
|
903
|
+
const snapshotTreeForPath = this.getSnapshotTreeForPath(snapshot.snapshotTree, pathParts, hasIsolatedChannels);
|
|
904
|
+
assert(snapshotTreeForPath !== undefined, 0x8ef /* no snapshotTree for the path */);
|
|
905
|
+
const snapshotSeqNumber = snapshot.sequenceNumber;
|
|
906
|
+
assert(snapshotSeqNumber !== undefined, 0x8f0 /* snapshotSeqNumber should be present */);
|
|
907
|
+
// This assert fires if we get a snapshot older than the snapshot we loaded from. This is a service issue.
|
|
908
|
+
// Snapshots should only move forward. If we observe an older snapshot than the one we loaded from, then likely
|
|
909
|
+
// the file has been overwritten or service lost data.
|
|
910
|
+
if (snapshotSeqNumber < this.deltaManager.initialSequenceNumber) {
|
|
911
|
+
throw DataProcessingError.create("Downloaded snapshot older than snapshot we loaded from", "getSnapshotForLoadingGroupId", undefined, {
|
|
912
|
+
loadingGroupIds: sortedLoadingGroupIds.join(","),
|
|
913
|
+
snapshotSeqNumber,
|
|
914
|
+
initialSequenceNumber: this.deltaManager.initialSequenceNumber,
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
// If the snapshot is ahead of the last seq number of the delta manager, then catch up before
|
|
918
|
+
// returning the snapshot.
|
|
919
|
+
if (snapshotSeqNumber > this.deltaManager.lastSequenceNumber) {
|
|
920
|
+
// If this is a summarizer client, which is trying to load a group and it finds that there is
|
|
921
|
+
// another snapshot from which the summarizer loaded and it is behind, then just give up as
|
|
922
|
+
// the summarizer state is not up to date.
|
|
923
|
+
// This should be a recoverable scenario and shouldn't happen as we should process the ack first.
|
|
924
|
+
if (this.isSummarizerClient) {
|
|
925
|
+
throw new Error("Summarizer client behind, loaded newer snapshot with loadingGroupId");
|
|
926
|
+
}
|
|
927
|
+
// We want to catchup from sequenceNumber to targetSequenceNumber
|
|
928
|
+
const props = {
|
|
929
|
+
eventName: "GroupIdSnapshotCatchup",
|
|
930
|
+
loadingGroupIds: sortedLoadingGroupIds.join(","),
|
|
931
|
+
targetSequenceNumber: snapshotSeqNumber,
|
|
932
|
+
sequenceNumber: this.deltaManager.lastSequenceNumber, // This is so we reuse some columns in telemetry
|
|
933
|
+
};
|
|
934
|
+
const event = PerformanceEvent.start(this.mc.logger, {
|
|
935
|
+
...props,
|
|
936
|
+
});
|
|
937
|
+
// If the inbound deltas queue is paused or disconnected, we expect a reconnect and unpause
|
|
938
|
+
// as long as it's not a summarizer client.
|
|
939
|
+
if (this.deltaManager.inbound.paused) {
|
|
940
|
+
props.inboundPaused = this.deltaManager.inbound.paused; // reusing telemetry
|
|
941
|
+
}
|
|
942
|
+
const defP = new Deferred();
|
|
943
|
+
this.deltaManager.on("op", (message) => {
|
|
944
|
+
if (message.sequenceNumber >= snapshotSeqNumber) {
|
|
945
|
+
defP.resolve(true);
|
|
946
|
+
}
|
|
947
|
+
});
|
|
948
|
+
await defP.promise;
|
|
949
|
+
event.end(props);
|
|
950
|
+
}
|
|
951
|
+
return { snapshotTree: snapshotTreeForPath, sequenceNumber: snapshotSeqNumber };
|
|
952
|
+
}
|
|
953
|
+
/**
|
|
954
|
+
* Api to find a snapshot tree inside a bigger snapshot tree based on the path in the pathParts array.
|
|
955
|
+
* @param snapshotTree - snapshot tree to look into.
|
|
956
|
+
* @param pathParts - Part of the path, which we want to extract from the snapshot tree.
|
|
957
|
+
* @param hasIsolatedChannels - whether the channels are present inside ".channels" subtree. Older
|
|
958
|
+
* snapshots will not have trees inside ".channels", so check that.
|
|
959
|
+
* @returns - requested snapshot tree based on the path parts.
|
|
960
|
+
*/
|
|
961
|
+
getSnapshotTreeForPath(snapshotTree, pathParts, hasIsolatedChannels) {
|
|
962
|
+
let childTree = snapshotTree;
|
|
963
|
+
for (const part of pathParts) {
|
|
964
|
+
if (hasIsolatedChannels) {
|
|
965
|
+
childTree = childTree?.trees[channelsTreeName];
|
|
966
|
+
}
|
|
967
|
+
childTree = childTree?.trees[part];
|
|
968
|
+
}
|
|
969
|
+
return childTree;
|
|
970
|
+
}
|
|
803
971
|
/**
|
|
804
972
|
* Notifies this object about the request made to the container.
|
|
805
973
|
* @param request - Request made to the handler.
|
|
@@ -853,15 +1021,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
853
1021
|
: create404Response(request);
|
|
854
1022
|
}
|
|
855
1023
|
else if (requestParser.pathParts.length > 0) {
|
|
856
|
-
|
|
857
|
-
const requestForChild = !requestParser.isLeaf(1);
|
|
858
|
-
const dataStore = await this.getDataStoreFromRequest(id, request, requestForChild);
|
|
859
|
-
const subRequest = requestParser.createSubRequest(1);
|
|
860
|
-
// We always expect createSubRequest to include a leading slash, but asserting here to protect against
|
|
861
|
-
// unintentionally modifying the url if that changes.
|
|
862
|
-
assert(subRequest.url.startsWith("/"), 0x126 /* "Expected createSubRequest url to include a leading slash" */);
|
|
863
|
-
// eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
|
|
864
|
-
return dataStore.request(subRequest);
|
|
1024
|
+
return await this.channelCollection.request(request);
|
|
865
1025
|
}
|
|
866
1026
|
return create404Response(request);
|
|
867
1027
|
}
|
|
@@ -876,38 +1036,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
876
1036
|
return this.entryPoint;
|
|
877
1037
|
}
|
|
878
1038
|
internalId(maybeAlias) {
|
|
879
|
-
return this.
|
|
880
|
-
}
|
|
881
|
-
async getDataStoreFromRequest(id, request, requestForChild) {
|
|
882
|
-
const headerData = {};
|
|
883
|
-
if (typeof request.headers?.[RuntimeHeaders.wait] === "boolean") {
|
|
884
|
-
headerData.wait = request.headers[RuntimeHeaders.wait];
|
|
885
|
-
}
|
|
886
|
-
if (typeof request.headers?.[RuntimeHeaders.viaHandle] === "boolean") {
|
|
887
|
-
headerData.viaHandle = request.headers[RuntimeHeaders.viaHandle];
|
|
888
|
-
}
|
|
889
|
-
if (typeof request.headers?.[AllowTombstoneRequestHeaderKey] === "boolean") {
|
|
890
|
-
headerData.allowTombstone = request.headers[AllowTombstoneRequestHeaderKey];
|
|
891
|
-
}
|
|
892
|
-
if (typeof request.headers?.[AllowInactiveRequestHeaderKey] === "boolean") {
|
|
893
|
-
headerData.allowInactive = request.headers[AllowInactiveRequestHeaderKey];
|
|
894
|
-
}
|
|
895
|
-
// We allow Tombstone requests for sub-DataStore objects
|
|
896
|
-
if (requestForChild) {
|
|
897
|
-
headerData.allowTombstone = true;
|
|
898
|
-
}
|
|
899
|
-
await this.dataStores.waitIfPendingAlias(id);
|
|
900
|
-
const internalId = this.internalId(id);
|
|
901
|
-
const dataStoreContext = await this.dataStores.getDataStore(internalId, headerData);
|
|
902
|
-
// Remove query params, leading and trailing slashes from the url. This is done to make sure the format is
|
|
903
|
-
// the same as GC nodes id.
|
|
904
|
-
const urlWithoutQuery = trimLeadingAndTrailingSlashes(request.url.split("?")[0]);
|
|
905
|
-
// Get the initial snapshot details which contain the data store package path.
|
|
906
|
-
const details = await dataStoreContext.getInitialSnapshotDetails();
|
|
907
|
-
// Note that this will throw if the data store is inactive or tombstoned and throwing on incorrect usage
|
|
908
|
-
// is configured.
|
|
909
|
-
this.garbageCollector.nodeUpdated(`/${urlWithoutQuery}`, "Loaded", undefined /* timestampMs */, details.pkg, request, headerData);
|
|
910
|
-
return dataStoreContext.realize();
|
|
1039
|
+
return this.channelCollection.internalId(maybeAlias);
|
|
911
1040
|
}
|
|
912
1041
|
/** Adds the container's metadata to the given summary tree. */
|
|
913
1042
|
addMetadataToSummary(summaryTree) {
|
|
@@ -922,22 +1051,21 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
922
1051
|
message: extractSummaryMetadataMessage(this.deltaManager.lastMessage) ??
|
|
923
1052
|
this.messageAtLastSummary,
|
|
924
1053
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
925
|
-
|
|
1054
|
+
idCompressorMode: this.idCompressorMode,
|
|
926
1055
|
};
|
|
927
1056
|
addBlobToSummary(summaryTree, metadataBlobName, JSON.stringify(metadata));
|
|
928
1057
|
}
|
|
929
1058
|
addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext) {
|
|
930
1059
|
this.addMetadataToSummary(summaryTree);
|
|
931
|
-
if (this.
|
|
932
|
-
|
|
933
|
-
const idCompressorState = JSON.stringify(this.idCompressor.serialize(false));
|
|
1060
|
+
if (this._idCompressor) {
|
|
1061
|
+
const idCompressorState = JSON.stringify(this._idCompressor.serialize(false));
|
|
934
1062
|
addBlobToSummary(summaryTree, idCompressorBlobName, idCompressorState);
|
|
935
1063
|
}
|
|
936
1064
|
if (this.remoteMessageProcessor.partialMessages.size > 0) {
|
|
937
1065
|
const content = JSON.stringify([...this.remoteMessageProcessor.partialMessages]);
|
|
938
1066
|
addBlobToSummary(summaryTree, chunksBlobName, content);
|
|
939
1067
|
}
|
|
940
|
-
const dataStoreAliases = this.
|
|
1068
|
+
const dataStoreAliases = this.channelCollection.aliases;
|
|
941
1069
|
if (dataStoreAliases.size > 0) {
|
|
942
1070
|
addBlobToSummary(summaryTree, aliasBlobName, JSON.stringify([...dataStoreAliases]));
|
|
943
1071
|
}
|
|
@@ -949,7 +1077,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
949
1077
|
// Some storage (like git) doesn't allow empty tree, so we can omit it.
|
|
950
1078
|
// and the blob manager can handle the tree not existing when loading
|
|
951
1079
|
if (Object.keys(blobManagerSummary.summary.tree).length > 0) {
|
|
952
|
-
|
|
1080
|
+
addSummarizeResultToSummary(summaryTree, blobsTreeName, blobManagerSummary);
|
|
953
1081
|
}
|
|
954
1082
|
const gcSummary = this.garbageCollector.summarize(fullTree, trackState, telemetryContext);
|
|
955
1083
|
if (gcSummary !== undefined) {
|
|
@@ -1036,13 +1164,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1036
1164
|
const opContents = this.parseLocalOpContent(serializedOpContent);
|
|
1037
1165
|
switch (opContents.type) {
|
|
1038
1166
|
case ContainerMessageType.FluidDataStoreOp:
|
|
1039
|
-
return this.dataStores.applyStashedOp(opContents.contents);
|
|
1040
1167
|
case ContainerMessageType.Attach:
|
|
1041
|
-
|
|
1168
|
+
case ContainerMessageType.Alias:
|
|
1169
|
+
return this.channelCollection.applyStashedOp(opContents);
|
|
1042
1170
|
case ContainerMessageType.IdAllocation:
|
|
1043
|
-
assert(this.
|
|
1171
|
+
assert(this.idCompressorMode !== "off", 0x8f1 /* ID compressor should be in use */);
|
|
1044
1172
|
return;
|
|
1045
|
-
case ContainerMessageType.Alias:
|
|
1046
1173
|
case ContainerMessageType.BlobAttach:
|
|
1047
1174
|
return;
|
|
1048
1175
|
case ContainerMessageType.ChunkedOp:
|
|
@@ -1073,6 +1200,20 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1073
1200
|
}
|
|
1074
1201
|
}
|
|
1075
1202
|
setConnectionState(connected, clientId) {
|
|
1203
|
+
if (connected && this.idCompressorMode === "delayed" && !this.compressorLoadInitiated) {
|
|
1204
|
+
this.compressorLoadInitiated = true;
|
|
1205
|
+
this.createIdCompressor()
|
|
1206
|
+
.then((compressor) => {
|
|
1207
|
+
this._idCompressor = compressor;
|
|
1208
|
+
for (const range of this.pendingIdCompressorOps) {
|
|
1209
|
+
this._idCompressor.finalizeCreationRange(range);
|
|
1210
|
+
}
|
|
1211
|
+
this.pendingIdCompressorOps = [];
|
|
1212
|
+
})
|
|
1213
|
+
.catch((error) => {
|
|
1214
|
+
this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
1076
1217
|
if (connected === false && this.delayConnectClientId !== undefined) {
|
|
1077
1218
|
this.delayConnectClientId = undefined;
|
|
1078
1219
|
this.mc.logger.sendTelemetryEvent({
|
|
@@ -1136,7 +1277,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1136
1277
|
if (changeOfState) {
|
|
1137
1278
|
this.replayPendingStates();
|
|
1138
1279
|
}
|
|
1139
|
-
this.
|
|
1280
|
+
this.channelCollection.setConnectionState(connected, clientId);
|
|
1140
1281
|
this.garbageCollector.setConnectionState(connected, clientId);
|
|
1141
1282
|
raiseConnectedEvent(this.mc.logger, this, connected, clientId);
|
|
1142
1283
|
}
|
|
@@ -1219,23 +1360,28 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1219
1360
|
const { local } = messageWithContext;
|
|
1220
1361
|
switch (messageWithContext.message.type) {
|
|
1221
1362
|
case ContainerMessageType.Attach:
|
|
1222
|
-
this.dataStores.processAttachMessage(messageWithContext.message, local);
|
|
1223
|
-
break;
|
|
1224
1363
|
case ContainerMessageType.Alias:
|
|
1225
|
-
this.dataStores.processAliasMessage(messageWithContext.message, localOpMetadata, local);
|
|
1226
|
-
break;
|
|
1227
1364
|
case ContainerMessageType.FluidDataStoreOp:
|
|
1228
|
-
this.
|
|
1365
|
+
this.channelCollection.process(messageWithContext.message, local, localOpMetadata, (from, to) => this.garbageCollector.addedOutboundReference(from, to));
|
|
1229
1366
|
break;
|
|
1230
1367
|
case ContainerMessageType.BlobAttach:
|
|
1231
1368
|
this.blobManager.processBlobAttachOp(messageWithContext.message, local);
|
|
1232
1369
|
break;
|
|
1233
1370
|
case ContainerMessageType.IdAllocation:
|
|
1234
|
-
assert(this.idCompressor !== undefined, 0x67c /* IdCompressor should be defined if enabled */);
|
|
1235
1371
|
// Don't re-finalize the range if we're processing a "savedOp" in
|
|
1236
1372
|
// stashed ops flow. The compressor is stashed with these ops already processed.
|
|
1237
|
-
|
|
1238
|
-
|
|
1373
|
+
// That said, in idCompressorMode === "delayed", we might not serialize ID compressor, and
|
|
1374
|
+
// thus we need to process all the ops.
|
|
1375
|
+
if (!(this.skipSavedCompressorOps &&
|
|
1376
|
+
messageWithContext.message.metadata?.savedOp ===
|
|
1377
|
+
true)) {
|
|
1378
|
+
const range = messageWithContext.message.contents;
|
|
1379
|
+
if (this._idCompressor === undefined) {
|
|
1380
|
+
this.pendingIdCompressorOps.push(range);
|
|
1381
|
+
}
|
|
1382
|
+
else {
|
|
1383
|
+
this._idCompressor.finalizeCreationRange(range);
|
|
1384
|
+
}
|
|
1239
1385
|
}
|
|
1240
1386
|
break;
|
|
1241
1387
|
case ContainerMessageType.GC:
|
|
@@ -1322,7 +1468,15 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1322
1468
|
this.emit("signal", transformed, local);
|
|
1323
1469
|
return;
|
|
1324
1470
|
}
|
|
1325
|
-
|
|
1471
|
+
// Due to a mismatch between different layers in terms of
|
|
1472
|
+
// what is the interface of passing signals, we need to adjust
|
|
1473
|
+
// the signal envelope before sending it to the datastores to be processed
|
|
1474
|
+
const envelope2 = {
|
|
1475
|
+
address: envelope.address,
|
|
1476
|
+
contents: transformed.content,
|
|
1477
|
+
};
|
|
1478
|
+
transformed.content = envelope2;
|
|
1479
|
+
this.channelCollection.processSignal(transformed, local);
|
|
1326
1480
|
}
|
|
1327
1481
|
/**
|
|
1328
1482
|
* Flush the pending ops manually.
|
|
@@ -1386,9 +1540,17 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1386
1540
|
* Returns undefined if no data store has been assigned the given alias.
|
|
1387
1541
|
*/
|
|
1388
1542
|
async getAliasedDataStoreEntryPoint(alias) {
|
|
1389
|
-
|
|
1543
|
+
// Back-comapatibility:
|
|
1544
|
+
// There are old files that were created without using data store aliasing feature, but
|
|
1545
|
+
// used createRoot*DataStore*() (already removed) API. Such data stores will have isRoot = true,
|
|
1546
|
+
// and internalID provided by user. The expectation is that such files behave as new files, where
|
|
1547
|
+
// same data store instances created using aliasing feature.
|
|
1548
|
+
// Please also see note on name collisions in DataStores.createDataStoreId()
|
|
1549
|
+
await this.channelCollection.waitIfPendingAlias(alias);
|
|
1390
1550
|
const internalId = this.internalId(alias);
|
|
1391
|
-
const context = await this.
|
|
1551
|
+
const context = await this.channelCollection.getDataStoreIfAvailable(internalId, {
|
|
1552
|
+
wait: false,
|
|
1553
|
+
});
|
|
1392
1554
|
// If the data store is not available or not an alias, return undefined.
|
|
1393
1555
|
if (context === undefined || !(await context.isRoot())) {
|
|
1394
1556
|
return undefined;
|
|
@@ -1400,28 +1562,20 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1400
1562
|
this.garbageCollector.nodeUpdated(`/${internalId}`, "Loaded", undefined /* timestampMs */, context.packagePath);
|
|
1401
1563
|
return channel.entryPoint;
|
|
1402
1564
|
}
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
throw new UsageError(`Id cannot contain slashes: '${rootDataStoreId}'`);
|
|
1406
|
-
}
|
|
1407
|
-
return this.dataStores.createDetachedDataStoreCore(pkg, true, rootDataStoreId);
|
|
1565
|
+
createDetachedDataStore(pkg, loadingGroupId) {
|
|
1566
|
+
return this.channelCollection.createDetachedDataStore(pkg, loadingGroupId);
|
|
1408
1567
|
}
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
const id = uuid();
|
|
1414
|
-
return channelToDataStore(await this.dataStores
|
|
1415
|
-
._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, undefined, groupId)
|
|
1416
|
-
.realize(), id, this, this.dataStores, this.mc.logger);
|
|
1568
|
+
async createDataStore(pkg, loadingGroupId) {
|
|
1569
|
+
const context = this.channelCollection.createDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], undefined, // props
|
|
1570
|
+
loadingGroupId);
|
|
1571
|
+
return channelToDataStore(await context.realize(), context.id, this.channelCollection, this.mc.logger);
|
|
1417
1572
|
}
|
|
1418
1573
|
/**
|
|
1419
1574
|
* @deprecated 0.16 Issue #1537, #3631
|
|
1420
1575
|
*/
|
|
1421
|
-
async _createDataStoreWithProps(pkg, props
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
.realize(), id, this, this.dataStores, this.mc.logger);
|
|
1576
|
+
async _createDataStoreWithProps(pkg, props) {
|
|
1577
|
+
const context = this.channelCollection.createDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], props);
|
|
1578
|
+
return channelToDataStore(await context.realize(), context.id, this.channelCollection, this.mc.logger);
|
|
1425
1579
|
}
|
|
1426
1580
|
canSendOps() {
|
|
1427
1581
|
// Note that the real (non-proxy) delta manager is needed here to get the readonly info. This is because
|
|
@@ -1499,16 +1653,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1499
1653
|
const envelope = this.createNewSignalEnvelope(undefined /* address */, type, content);
|
|
1500
1654
|
return this.submitSignalFn(envelope, targetClientId);
|
|
1501
1655
|
}
|
|
1502
|
-
/**
|
|
1503
|
-
* Submits the signal to be sent to other clients.
|
|
1504
|
-
* @param type - Type of the signal.
|
|
1505
|
-
* @param content - Content of the signal.
|
|
1506
|
-
* @param targetClientId - When specified, the signal is only sent to the provided client id.
|
|
1507
|
-
*/
|
|
1508
|
-
submitDataStoreSignal(address, type, content, targetClientId) {
|
|
1509
|
-
const envelope = this.createNewSignalEnvelope(address, type, content);
|
|
1510
|
-
return this.submitSignalFn(envelope, targetClientId);
|
|
1511
|
-
}
|
|
1512
1656
|
setAttachState(attachState) {
|
|
1513
1657
|
if (attachState === AttachState.Attaching) {
|
|
1514
1658
|
assert(this.attachState === AttachState.Attaching, 0x12d /* "Container Context should already be in attaching state" */);
|
|
@@ -1520,7 +1664,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1520
1664
|
if (attachState === AttachState.Attached && !this.hasPendingMessages()) {
|
|
1521
1665
|
this.updateDocumentDirtyState(false);
|
|
1522
1666
|
}
|
|
1523
|
-
this.
|
|
1667
|
+
this.channelCollection.setAttachState(attachState);
|
|
1524
1668
|
}
|
|
1525
1669
|
/**
|
|
1526
1670
|
* Create a summary. Used when attaching or serializing a detached container.
|
|
@@ -1535,18 +1679,18 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1535
1679
|
this.blobManager.setRedirectTable(blobRedirectTable);
|
|
1536
1680
|
}
|
|
1537
1681
|
// We can finalize any allocated IDs since we're the only client
|
|
1538
|
-
const idRange = this.
|
|
1682
|
+
const idRange = this._idCompressor?.takeNextCreationRange();
|
|
1539
1683
|
if (idRange !== undefined) {
|
|
1540
|
-
this.
|
|
1684
|
+
this._idCompressor?.finalizeCreationRange(idRange);
|
|
1541
1685
|
}
|
|
1542
|
-
const summarizeResult = this.
|
|
1686
|
+
const summarizeResult = this.channelCollection.getAttachSummary(telemetryContext);
|
|
1543
1687
|
// Wrap data store summaries in .channels subtree.
|
|
1544
1688
|
wrapSummaryInChannelsTree(summarizeResult);
|
|
1545
1689
|
this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
|
|
1546
1690
|
return summarizeResult.summary;
|
|
1547
1691
|
}
|
|
1548
1692
|
async summarizeInternal(fullTree, trackState, telemetryContext) {
|
|
1549
|
-
const summarizeResult = await this.
|
|
1693
|
+
const summarizeResult = await this.channelCollection.summarize(fullTree, trackState, telemetryContext);
|
|
1550
1694
|
// Wrap data store summaries in .channels subtree.
|
|
1551
1695
|
wrapSummaryInChannelsTree(summarizeResult);
|
|
1552
1696
|
const pathPartsForChildren = [channelsTreeName];
|
|
@@ -1594,10 +1738,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1594
1738
|
* @see IGarbageCollectionRuntime.updateStateBeforeGC
|
|
1595
1739
|
*/
|
|
1596
1740
|
async updateStateBeforeGC() {
|
|
1597
|
-
return this.
|
|
1741
|
+
return this.channelCollection.updateStateBeforeGC();
|
|
1598
1742
|
}
|
|
1599
1743
|
async getGCDataInternal(fullGC) {
|
|
1600
|
-
return this.
|
|
1744
|
+
return this.channelCollection.getGCData(fullGC);
|
|
1601
1745
|
}
|
|
1602
1746
|
/**
|
|
1603
1747
|
* Generates and returns the GC data for this container.
|
|
@@ -1623,22 +1767,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1623
1767
|
// always referenced, so the used routes is only self-route (empty string).
|
|
1624
1768
|
this.summarizerNode.updateUsedRoutes([""]);
|
|
1625
1769
|
const { dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(usedRoutes);
|
|
1626
|
-
this.
|
|
1627
|
-
}
|
|
1628
|
-
/**
|
|
1629
|
-
* This is called to update objects whose routes are unused.
|
|
1630
|
-
* @param unusedRoutes - Data store and attachment blob routes that are unused in this Container.
|
|
1631
|
-
*/
|
|
1632
|
-
updateUnusedRoutes(unusedRoutes) {
|
|
1633
|
-
const { blobManagerRoutes, dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(unusedRoutes);
|
|
1634
|
-
this.blobManager.updateUnusedRoutes(blobManagerRoutes);
|
|
1635
|
-
this.dataStores.updateUnusedRoutes(dataStoreRoutes);
|
|
1636
|
-
}
|
|
1637
|
-
/**
|
|
1638
|
-
* @deprecated Replaced by deleteSweepReadyNodes.
|
|
1639
|
-
*/
|
|
1640
|
-
deleteUnusedNodes(unusedRoutes) {
|
|
1641
|
-
throw new Error("deleteUnusedRoutes should not be called");
|
|
1770
|
+
this.channelCollection.updateUsedRoutes(dataStoreRoutes);
|
|
1642
1771
|
}
|
|
1643
1772
|
/**
|
|
1644
1773
|
* After GC has run and identified nodes that are sweep ready, this is called to delete the sweep ready nodes.
|
|
@@ -1647,7 +1776,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1647
1776
|
*/
|
|
1648
1777
|
deleteSweepReadyNodes(sweepReadyRoutes) {
|
|
1649
1778
|
const { dataStoreRoutes, blobManagerRoutes } = this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
|
|
1650
|
-
const deletedRoutes = this.
|
|
1779
|
+
const deletedRoutes = this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes);
|
|
1651
1780
|
return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
|
|
1652
1781
|
}
|
|
1653
1782
|
/**
|
|
@@ -1661,7 +1790,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1661
1790
|
updateTombstonedRoutes(tombstonedRoutes) {
|
|
1662
1791
|
const { blobManagerRoutes, dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(tombstonedRoutes);
|
|
1663
1792
|
this.blobManager.updateTombstonedRoutes(blobManagerRoutes);
|
|
1664
|
-
this.
|
|
1793
|
+
this.channelCollection.updateTombstonedRoutes(dataStoreRoutes);
|
|
1665
1794
|
}
|
|
1666
1795
|
/**
|
|
1667
1796
|
* Returns a server generated referenced timestamp to be used to track unreferenced nodes by GC.
|
|
@@ -1679,7 +1808,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1679
1808
|
if (this.isBlobPath(nodePath)) {
|
|
1680
1809
|
return GCNodeType.Blob;
|
|
1681
1810
|
}
|
|
1682
|
-
return this.
|
|
1811
|
+
return this.channelCollection.getGCNodeType(nodePath) ?? GCNodeType.Other;
|
|
1683
1812
|
}
|
|
1684
1813
|
/**
|
|
1685
1814
|
* Called by GC to retrieve the package path of the node with the given path. The node should belong to a
|
|
@@ -1689,14 +1818,14 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1689
1818
|
// GC uses "/" when adding "root" references, e.g. for Aliasing or as part of Tombstone Auto-Recovery.
|
|
1690
1819
|
// These have no package path so return a special value.
|
|
1691
1820
|
if (nodePath === "/") {
|
|
1692
|
-
return ["
|
|
1821
|
+
return ["_gcRoot"];
|
|
1693
1822
|
}
|
|
1694
1823
|
switch (this.getNodeType(nodePath)) {
|
|
1695
1824
|
case GCNodeType.Blob:
|
|
1696
1825
|
return [BlobManager.basePath];
|
|
1697
1826
|
case GCNodeType.DataStore:
|
|
1698
1827
|
case GCNodeType.SubDataStore:
|
|
1699
|
-
return this.
|
|
1828
|
+
return this.channelCollection.getDataStorePackagePath(nodePath);
|
|
1700
1829
|
default:
|
|
1701
1830
|
assert(false, 0x2de /* "Package path requested for unsupported node type." */);
|
|
1702
1831
|
}
|
|
@@ -1755,7 +1884,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1755
1884
|
* @param options - options controlling how the summary is generated or submitted
|
|
1756
1885
|
*/
|
|
1757
1886
|
async submitSummary(options) {
|
|
1758
|
-
const { fullTree = false, finalAttempt = false, refreshLatestAck, summaryLogger } = options;
|
|
1887
|
+
const { fullTree = false, finalAttempt = false, refreshLatestAck, summaryLogger, latestSummaryRefSeqNum, } = options;
|
|
1759
1888
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
1760
1889
|
// use it for all events logged during this summary.
|
|
1761
1890
|
const summaryNumber = this.nextSummaryNumber;
|
|
@@ -1808,6 +1937,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1808
1937
|
}
|
|
1809
1938
|
}
|
|
1810
1939
|
const shouldPauseInboundSignal = this.mc.config.getBoolean("Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause") !== true;
|
|
1940
|
+
const shouldValidatePreSummaryState = this.mc.config.getBoolean("Fluid.ContainerRuntime.SubmitSummary.shouldValidatePreSummaryState") === true;
|
|
1811
1941
|
let summaryRefSeqNum;
|
|
1812
1942
|
try {
|
|
1813
1943
|
await this.deltaManager.inbound.pause();
|
|
@@ -1818,7 +1948,25 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1818
1948
|
const minimumSequenceNumber = this.deltaManager.minimumSequenceNumber;
|
|
1819
1949
|
const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
|
|
1820
1950
|
const lastAck = this.summaryCollection.latestAck;
|
|
1821
|
-
this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger);
|
|
1951
|
+
const startSummaryResult = this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger, latestSummaryRefSeqNum);
|
|
1952
|
+
if (startSummaryResult.invalidNodes > 0 ||
|
|
1953
|
+
startSummaryResult.mismatchNumbers.size > 0) {
|
|
1954
|
+
summaryLogger.sendErrorEvent({
|
|
1955
|
+
eventName: "LatestSummaryRefSeqNumMismatch",
|
|
1956
|
+
details: {
|
|
1957
|
+
...startSummaryResult,
|
|
1958
|
+
mismatchNumbers: Array.from(startSummaryResult.mismatchNumbers),
|
|
1959
|
+
},
|
|
1960
|
+
});
|
|
1961
|
+
if (shouldValidatePreSummaryState && !finalAttempt) {
|
|
1962
|
+
return {
|
|
1963
|
+
stage: "base",
|
|
1964
|
+
referenceSequenceNumber: summaryRefSeqNum,
|
|
1965
|
+
minimumSequenceNumber,
|
|
1966
|
+
error: `Summarizer node state inconsistent with summarizer state.`,
|
|
1967
|
+
};
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1822
1970
|
// Helper function to check whether we should still continue between each async step.
|
|
1823
1971
|
const checkContinue = () => {
|
|
1824
1972
|
// Do not check for loss of connectivity directly! Instead leave it up to
|
|
@@ -1914,8 +2062,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1914
2062
|
? calculateStats(summaryTree.tree[gcTreeKey])
|
|
1915
2063
|
: undefined;
|
|
1916
2064
|
const summaryStats = {
|
|
1917
|
-
dataStoreCount: this.
|
|
1918
|
-
summarizedDataStoreCount: this.
|
|
2065
|
+
dataStoreCount: this.channelCollection.size,
|
|
2066
|
+
summarizedDataStoreCount: this.channelCollection.size - handleCount,
|
|
1919
2067
|
gcStateUpdatedDataStoreCount: this.garbageCollector.updatedDSCountSinceLastSummary,
|
|
1920
2068
|
gcBlobNodeCount: gcSummaryTreeStats?.blobNodeCount,
|
|
1921
2069
|
gcTotalBlobsSize: gcSummaryTreeStats?.totalBlobSize,
|
|
@@ -2069,48 +2217,29 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2069
2217
|
this.emit(dirty ? "dirty" : "saved");
|
|
2070
2218
|
}
|
|
2071
2219
|
}
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
address: id,
|
|
2075
|
-
contents,
|
|
2076
|
-
};
|
|
2077
|
-
this.submit({ type: ContainerMessageType.FluidDataStoreOp, contents: envelope }, localOpMetadata);
|
|
2078
|
-
}
|
|
2079
|
-
submitDataStoreAliasOp(contents, localOpMetadata) {
|
|
2080
|
-
const aliasMessage = contents;
|
|
2081
|
-
if (!isDataStoreAliasMessage(aliasMessage)) {
|
|
2082
|
-
throw new UsageError("malformedDataStoreAliasMessage");
|
|
2083
|
-
}
|
|
2084
|
-
this.submit({ type: ContainerMessageType.Alias, contents }, localOpMetadata);
|
|
2220
|
+
submitMessage(type, contents, localOpMetadata = undefined) {
|
|
2221
|
+
this.submit({ type, contents }, localOpMetadata);
|
|
2085
2222
|
}
|
|
2086
2223
|
async uploadBlob(blob, signal) {
|
|
2087
2224
|
this.verifyNotClosed();
|
|
2088
2225
|
return this.blobManager.createBlob(blob, signal);
|
|
2089
2226
|
}
|
|
2090
|
-
|
|
2091
|
-
if (
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
if (
|
|
2095
|
-
assert(this.idCompressor !== undefined, 0x67d /* IdCompressor should be defined if enabled */);
|
|
2096
|
-
idRange = this.idCompressor.takeNextCreationRange();
|
|
2097
|
-
// Don't include the idRange if there weren't any Ids allocated
|
|
2098
|
-
idRange = idRange?.ids !== undefined ? idRange : undefined;
|
|
2099
|
-
}
|
|
2100
|
-
if (idRange !== undefined) {
|
|
2227
|
+
submitIdAllocationOpIfNeeded() {
|
|
2228
|
+
if (this._idCompressor) {
|
|
2229
|
+
const idRange = this._idCompressor.takeNextCreationRange();
|
|
2230
|
+
// Don't include the idRange if there weren't any Ids allocated
|
|
2231
|
+
if (idRange?.ids !== undefined) {
|
|
2101
2232
|
const idAllocationMessage = {
|
|
2102
2233
|
type: ContainerMessageType.IdAllocation,
|
|
2103
2234
|
contents: idRange,
|
|
2104
2235
|
};
|
|
2105
|
-
idAllocationBatchMessage = {
|
|
2236
|
+
const idAllocationBatchMessage = {
|
|
2106
2237
|
contents: JSON.stringify(idAllocationMessage),
|
|
2107
2238
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2108
2239
|
metadata: undefined,
|
|
2109
2240
|
localOpMetadata: undefined,
|
|
2110
2241
|
type: ContainerMessageType.IdAllocation,
|
|
2111
2242
|
};
|
|
2112
|
-
}
|
|
2113
|
-
if (idAllocationBatchMessage !== undefined) {
|
|
2114
2243
|
this.outbox.submitIdAllocation(idAllocationBatchMessage);
|
|
2115
2244
|
}
|
|
2116
2245
|
}
|
|
@@ -2138,42 +2267,47 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2138
2267
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2139
2268
|
};
|
|
2140
2269
|
try {
|
|
2141
|
-
//
|
|
2142
|
-
// the
|
|
2143
|
-
// op
|
|
2144
|
-
//
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
// Is it safe:
|
|
2148
|
-
// Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
|
|
2149
|
-
// They become visible only when aliased, or handle to some sub-element of newly created datastore
|
|
2150
|
-
// is stored in some DDS, i.e. only after some other op.
|
|
2151
|
-
// Why:
|
|
2152
|
-
// Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
|
|
2153
|
-
// stores are created, causing issues like relay service throttling (too many ops) and catastrophic
|
|
2154
|
-
// failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
|
|
2155
|
-
// these issues.
|
|
2156
|
-
// Cons:
|
|
2157
|
-
// 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
|
|
2158
|
-
// This change creates new possibility of a lot of newly created data stores never being referenced
|
|
2159
|
-
// because client died before it had a change to submit the rest of the ops. This will create more
|
|
2160
|
-
// garbage that needs to be collected leveraging GC (Garbage Collection) feature.
|
|
2161
|
-
// 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
|
|
2162
|
-
// today as rollback can't undo creation of data store. To some extent not sending them is a bigger
|
|
2163
|
-
// issue than sending.
|
|
2164
|
-
// Please note that this does not change file format, so it can be disabled in the future if this
|
|
2165
|
-
// optimization no longer makes sense (for example, batch compression may make it less appealing).
|
|
2166
|
-
if (this.currentlyBatching() &&
|
|
2167
|
-
type === ContainerMessageType.Attach &&
|
|
2168
|
-
this.disableAttachReorder !== true) {
|
|
2169
|
-
this.outbox.submitAttach(message);
|
|
2170
|
-
}
|
|
2171
|
-
else if (type === ContainerMessageType.BlobAttach) {
|
|
2172
|
-
// BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
|
|
2173
|
-
this.outbox.submitBlobAttach(message);
|
|
2270
|
+
// If `message` is an allocation op, then we are in the resubmit path and we must redirect the allocation
|
|
2271
|
+
// op into the correct batch to avoid ranges being finalized out of order.
|
|
2272
|
+
// Otherwise, submit an IdAllocation op if any IDs have been generated since the last op was submitted, as
|
|
2273
|
+
// any of the other op types may contain those IDs and thus depend on the allocation op being sent first.
|
|
2274
|
+
if (type === ContainerMessageType.IdAllocation) {
|
|
2275
|
+
this.outbox.submitIdAllocation(message);
|
|
2174
2276
|
}
|
|
2175
2277
|
else {
|
|
2176
|
-
this.
|
|
2278
|
+
this.submitIdAllocationOpIfNeeded();
|
|
2279
|
+
// If this is attach message for new data store, and we are in a batch, send this op out of order
|
|
2280
|
+
// Is it safe:
|
|
2281
|
+
// Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
|
|
2282
|
+
// They become visible only when aliased, or handle to some sub-element of newly created datastore
|
|
2283
|
+
// is stored in some DDS, i.e. only after some other op.
|
|
2284
|
+
// Why:
|
|
2285
|
+
// Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
|
|
2286
|
+
// stores are created, causing issues like relay service throttling (too many ops) and catastrophic
|
|
2287
|
+
// failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
|
|
2288
|
+
// these issues.
|
|
2289
|
+
// Cons:
|
|
2290
|
+
// 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
|
|
2291
|
+
// This change creates new possibility of a lot of newly created data stores never being referenced
|
|
2292
|
+
// because client died before it had a change to submit the rest of the ops. This will create more
|
|
2293
|
+
// garbage that needs to be collected leveraging GC (Garbage Collection) feature.
|
|
2294
|
+
// 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
|
|
2295
|
+
// today as rollback can't undo creation of data store. To some extent not sending them is a bigger
|
|
2296
|
+
// issue than sending.
|
|
2297
|
+
// Please note that this does not change file format, so it can be disabled in the future if this
|
|
2298
|
+
// optimization no longer makes sense (for example, batch compression may make it less appealing).
|
|
2299
|
+
if (this.currentlyBatching() &&
|
|
2300
|
+
type === ContainerMessageType.Attach &&
|
|
2301
|
+
this.disableAttachReorder !== true) {
|
|
2302
|
+
this.outbox.submitAttach(message);
|
|
2303
|
+
}
|
|
2304
|
+
else if (type === ContainerMessageType.BlobAttach) {
|
|
2305
|
+
// BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
|
|
2306
|
+
this.outbox.submitBlobAttach(message);
|
|
2307
|
+
}
|
|
2308
|
+
else {
|
|
2309
|
+
this.outbox.submit(message);
|
|
2310
|
+
}
|
|
2177
2311
|
}
|
|
2178
2312
|
if (!this.currentlyBatching()) {
|
|
2179
2313
|
this.flush();
|
|
@@ -2289,15 +2423,15 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2289
2423
|
* @param localOpMetadata - The local metadata associated with the original message.
|
|
2290
2424
|
*/
|
|
2291
2425
|
reSubmitCore(message, localOpMetadata, opMetadata) {
|
|
2292
|
-
assert(!this.isSummarizerClient,
|
|
2426
|
+
assert(!this.isSummarizerClient, 0x8f2 /* Summarizer never reconnects so should never resubmit */);
|
|
2293
2427
|
switch (message.type) {
|
|
2294
2428
|
case ContainerMessageType.FluidDataStoreOp:
|
|
2429
|
+
case ContainerMessageType.Attach:
|
|
2430
|
+
case ContainerMessageType.Alias:
|
|
2295
2431
|
// For Operations, call resubmitDataStoreOp which will find the right store
|
|
2296
2432
|
// and trigger resubmission on it.
|
|
2297
|
-
this.
|
|
2433
|
+
this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
|
|
2298
2434
|
break;
|
|
2299
|
-
case ContainerMessageType.Attach:
|
|
2300
|
-
case ContainerMessageType.Alias:
|
|
2301
2435
|
case ContainerMessageType.IdAllocation: {
|
|
2302
2436
|
this.submit(message, localOpMetadata);
|
|
2303
2437
|
break;
|
|
@@ -2344,7 +2478,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2344
2478
|
case ContainerMessageType.FluidDataStoreOp:
|
|
2345
2479
|
// For operations, call rollbackDataStoreOp which will find the right store
|
|
2346
2480
|
// and trigger rollback on it.
|
|
2347
|
-
this.
|
|
2481
|
+
this.channelCollection.rollback(type, contents, localOpMetadata);
|
|
2348
2482
|
break;
|
|
2349
2483
|
default:
|
|
2350
2484
|
// Don't check message.compatDetails because this is for rolling back a local op so the type will be known
|
|
@@ -2429,44 +2563,43 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2429
2563
|
};
|
|
2430
2564
|
});
|
|
2431
2565
|
}
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
}
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
// try to change its value
|
|
2440
|
-
if (!this.imminentClosure) {
|
|
2441
|
-
this.imminentClosure = props?.notifyImminentClosure ?? this.imminentClosure;
|
|
2442
|
-
}
|
|
2443
|
-
const stopBlobAttachingSignal = props?.stopBlobAttachingSignal;
|
|
2444
|
-
if (this._orderSequentiallyCalls !== 0) {
|
|
2445
|
-
throw new UsageError("can't get state during orderSequentially");
|
|
2446
|
-
}
|
|
2447
|
-
// Flush pending batch.
|
|
2448
|
-
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
2449
|
-
// to close current batch.
|
|
2450
|
-
this.flush();
|
|
2451
|
-
const pendingAttachmentBlobs = this.imminentClosure
|
|
2452
|
-
? await this.blobManager.attachAndGetPendingBlobs(stopBlobAttachingSignal)
|
|
2453
|
-
: undefined;
|
|
2566
|
+
getPendingLocalState(props) {
|
|
2567
|
+
this.verifyNotClosed();
|
|
2568
|
+
if (this._orderSequentiallyCalls !== 0) {
|
|
2569
|
+
throw new UsageError("can't get state during orderSequentially");
|
|
2570
|
+
}
|
|
2571
|
+
this.imminentClosure || (this.imminentClosure = props?.notifyImminentClosure ?? false);
|
|
2572
|
+
const getSyncState = (pendingAttachmentBlobs) => {
|
|
2454
2573
|
const pending = this.pendingStateManager.getLocalState();
|
|
2455
|
-
if (
|
|
2574
|
+
if (pendingAttachmentBlobs === undefined && !this.hasPendingMessages()) {
|
|
2456
2575
|
return; // no pending state to save
|
|
2457
2576
|
}
|
|
2458
|
-
const pendingIdCompressorState = this.
|
|
2459
|
-
|
|
2577
|
+
const pendingIdCompressorState = this._idCompressor?.serialize(true);
|
|
2578
|
+
return {
|
|
2460
2579
|
pending,
|
|
2461
|
-
pendingAttachmentBlobs,
|
|
2462
2580
|
pendingIdCompressorState,
|
|
2581
|
+
pendingAttachmentBlobs,
|
|
2582
|
+
sessionExpiryTimerStarted: this.garbageCollector.sessionExpiryTimerStarted,
|
|
2463
2583
|
};
|
|
2584
|
+
};
|
|
2585
|
+
const perfEvent = {
|
|
2586
|
+
eventName: "getPendingLocalState",
|
|
2587
|
+
notifyImminentClosure: props?.notifyImminentClosure,
|
|
2588
|
+
};
|
|
2589
|
+
const logAndReturnPendingState = (event, pendingState) => {
|
|
2464
2590
|
event.end({
|
|
2465
|
-
attachmentBlobsSize: Object.keys(pendingAttachmentBlobs ?? {}).length,
|
|
2466
|
-
pendingOpsSize: pending?.pendingStates.length,
|
|
2591
|
+
attachmentBlobsSize: Object.keys(pendingState?.pendingAttachmentBlobs ?? {}).length,
|
|
2592
|
+
pendingOpsSize: pendingState?.pending?.pendingStates.length,
|
|
2467
2593
|
});
|
|
2468
2594
|
return pendingState;
|
|
2469
|
-
}
|
|
2595
|
+
};
|
|
2596
|
+
// Flush pending batch.
|
|
2597
|
+
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
2598
|
+
// to close current batch.
|
|
2599
|
+
this.flush();
|
|
2600
|
+
return props?.notifyImminentClosure === true
|
|
2601
|
+
? PerformanceEvent.timedExecAsync(this.mc.logger, perfEvent, async (event) => logAndReturnPendingState(event, getSyncState(await this.blobManager.attachAndGetPendingBlobs(props?.stopBlobAttachingSignal))))
|
|
2602
|
+
: PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) => logAndReturnPendingState(event, getSyncState()));
|
|
2470
2603
|
}
|
|
2471
2604
|
summarizeOnDemand(options) {
|
|
2472
2605
|
if (this.isSummarizerClient) {
|
|
@@ -2520,4 +2653,4 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2520
2653
|
return killSwitch !== true && this.runtimeOptions.enableGroupedBatching;
|
|
2521
2654
|
}
|
|
2522
2655
|
}
|
|
2523
|
-
//# sourceMappingURL=containerRuntime.
|
|
2656
|
+
//# sourceMappingURL=containerRuntime.js.map
|