@fluidframework/container-runtime 2.0.0-dev-rc.1.0.0.232845 → 2.0.0-dev-rc.2.0.0.246488
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +5 -5
- package/{.mocharc.js → .mocharc.cjs} +1 -1
- package/CHANGELOG.md +54 -0
- package/README.md +45 -0
- package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
- package/api-extractor-lint.json +1 -1
- package/api-extractor.json +1 -1
- package/api-report/container-runtime.api.md +426 -33
- package/dist/batchTracker.d.ts +1 -2
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +0 -5
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +0 -12
- package/dist/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +226 -0
- package/dist/channelCollection.d.ts.map +1 -0
- package/dist/{dataStores.js → channelCollection.js} +455 -150
- package/dist/channelCollection.js.map +1 -0
- package/dist/connectionTelemetry.d.ts +11 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +42 -4
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/container-runtime-alpha.d.ts +128 -48
- package/dist/container-runtime-beta.d.ts +67 -9
- package/dist/container-runtime-public.d.ts +67 -9
- package/dist/container-runtime-untrimmed.d.ts +692 -49
- package/dist/containerHandleContext.d.ts +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +81 -64
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +522 -379
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +2 -3
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +12 -11
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +118 -41
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +248 -159
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts +2 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +1 -0
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts +4 -0
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +2 -2
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts +29 -4
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js +91 -5
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +12 -6
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +116 -78
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +2 -2
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +30 -23
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +22 -13
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +7 -4
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +2 -2
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +12 -5
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +18 -6
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +6 -7
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +20 -18
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.d.ts +1 -1
- package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +10 -10
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +8 -8
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +40 -39
- package/dist/gc/index.js.map +1 -1
- package/dist/index.d.ts +11 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -42
- package/dist/index.js.map +1 -1
- package/dist/messageTypes.d.ts +3 -3
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +2 -2
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +2 -2
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +8 -8
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +18 -18
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +4 -4
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +3 -3
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +1 -10
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +5 -5
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +7 -7
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +32 -18
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +4 -4
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +7 -4
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/package.json +3 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +2 -1
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +18 -10
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts +1 -2
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +9 -5
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/index.d.ts +12 -12
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js +43 -43
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +12 -8
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +5 -4
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +47 -32
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +4 -4
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +6 -6
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +2 -2
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.d.ts +3 -3
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/index.d.ts +3 -3
- package/dist/summary/summarizerNode/index.d.ts.map +1 -1
- package/dist/summary/summarizerNode/index.js +4 -4
- package/dist/summary/summarizerNode/index.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +16 -5
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +40 -10
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +9 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -4
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +12 -12
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +9 -20
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +15 -2
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +6 -5
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +10 -1
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +5 -6
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +4 -5
- package/dist/summary/summaryManager.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/{batchTracker.d.mts → batchTracker.d.ts} +2 -3
- package/lib/batchTracker.d.ts.map +1 -0
- package/lib/{batchTracker.mjs → batchTracker.js} +1 -1
- package/lib/batchTracker.js.map +1 -0
- package/lib/{blobManager.d.mts → blobManager.d.ts} +1 -6
- package/lib/blobManager.d.ts.map +1 -0
- package/lib/{blobManager.mjs → blobManager.js} +1 -13
- package/lib/blobManager.js.map +1 -0
- package/lib/channelCollection.d.ts +226 -0
- package/lib/channelCollection.d.ts.map +1 -0
- package/lib/{dataStores.mjs → channelCollection.js} +442 -140
- package/lib/channelCollection.js.map +1 -0
- package/lib/{connectionTelemetry.d.mts → connectionTelemetry.d.ts} +12 -2
- package/lib/connectionTelemetry.d.ts.map +1 -0
- package/lib/{connectionTelemetry.mjs → connectionTelemetry.js} +43 -5
- package/lib/connectionTelemetry.js.map +1 -0
- package/lib/{container-runtime-alpha.d.mts → container-runtime-alpha.d.ts} +128 -48
- package/lib/{container-runtime-beta.d.mts → container-runtime-beta.d.ts} +67 -9
- package/lib/{container-runtime-public.d.mts → container-runtime-public.d.ts} +67 -9
- package/lib/{container-runtime-untrimmed.d.mts → container-runtime-untrimmed.d.ts} +692 -49
- package/lib/{containerHandleContext.d.mts → containerHandleContext.d.ts} +2 -2
- package/lib/containerHandleContext.d.ts.map +1 -0
- package/lib/{containerHandleContext.mjs → containerHandleContext.js} +1 -1
- package/lib/containerHandleContext.js.map +1 -0
- package/lib/{containerRuntime.d.mts → containerRuntime.d.ts} +86 -65
- package/lib/containerRuntime.d.ts.map +1 -0
- package/lib/{containerRuntime.mjs → containerRuntime.js} +444 -303
- package/lib/containerRuntime.js.map +1 -0
- package/lib/{dataStore.d.mts → dataStore.d.ts} +3 -4
- package/lib/dataStore.d.ts.map +1 -0
- package/lib/{dataStore.mjs → dataStore.js} +13 -12
- package/lib/dataStore.js.map +1 -0
- package/lib/{dataStoreContext.d.mts → dataStoreContext.d.ts} +119 -42
- package/lib/dataStoreContext.d.ts.map +1 -0
- package/lib/{dataStoreContext.mjs → dataStoreContext.js} +240 -151
- package/lib/dataStoreContext.js.map +1 -0
- package/lib/{dataStoreContexts.d.mts → dataStoreContexts.d.ts} +3 -2
- package/lib/dataStoreContexts.d.ts.map +1 -0
- package/lib/{dataStoreContexts.mjs → dataStoreContexts.js} +2 -1
- package/lib/dataStoreContexts.js.map +1 -0
- package/lib/{dataStoreRegistry.d.mts → dataStoreRegistry.d.ts} +5 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -0
- package/lib/{dataStoreRegistry.mjs → dataStoreRegistry.js} +5 -1
- package/lib/dataStoreRegistry.js.map +1 -0
- package/{dist/deltaManagerProxyBase.d.ts → lib/deltaManagerSummarizerProxy.d.ts} +16 -7
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -0
- package/lib/deltaManagerSummarizerProxy.js +124 -0
- package/lib/deltaManagerSummarizerProxy.js.map +1 -0
- package/lib/{deltaScheduler.d.mts → deltaScheduler.d.ts} +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -0
- package/lib/{deltaScheduler.mjs → deltaScheduler.js} +1 -1
- package/lib/deltaScheduler.js.map +1 -0
- package/lib/{error.d.mts → error.d.ts} +1 -1
- package/lib/error.d.ts.map +1 -0
- package/lib/{error.mjs → error.js} +1 -1
- package/lib/error.js.map +1 -0
- package/lib/gc/{garbageCollection.d.mts → garbageCollection.d.ts} +13 -7
- package/lib/gc/garbageCollection.d.ts.map +1 -0
- package/lib/gc/{garbageCollection.mjs → garbageCollection.js} +79 -41
- package/lib/gc/garbageCollection.js.map +1 -0
- package/lib/gc/{gcConfigs.d.mts → gcConfigs.d.ts} +3 -3
- package/lib/gc/gcConfigs.d.ts.map +1 -0
- package/lib/gc/{gcConfigs.mjs → gcConfigs.js} +14 -7
- package/lib/gc/gcConfigs.js.map +1 -0
- package/lib/gc/{gcDefinitions.d.mts → gcDefinitions.d.ts} +23 -14
- package/lib/gc/gcDefinitions.d.ts.map +1 -0
- package/lib/gc/{gcDefinitions.mjs → gcDefinitions.js} +7 -4
- package/lib/gc/gcDefinitions.js.map +1 -0
- package/lib/gc/{gcHelpers.d.mts → gcHelpers.d.ts} +3 -3
- package/lib/gc/{gcHelpers.d.mts.map → gcHelpers.d.ts.map} +1 -1
- package/lib/gc/{gcHelpers.mjs → gcHelpers.js} +1 -1
- package/lib/gc/gcHelpers.js.map +1 -0
- package/lib/gc/{gcReferenceGraphAlgorithm.d.mts → gcReferenceGraphAlgorithm.d.ts} +2 -2
- package/lib/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -0
- package/lib/gc/{gcReferenceGraphAlgorithm.mjs → gcReferenceGraphAlgorithm.js} +1 -1
- package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -0
- package/lib/gc/{gcSummaryDefinitions.d.mts → gcSummaryDefinitions.d.ts} +1 -1
- package/lib/gc/gcSummaryDefinitions.d.ts.map +1 -0
- package/lib/gc/{gcSummaryDefinitions.mjs → gcSummaryDefinitions.js} +1 -1
- package/lib/gc/gcSummaryDefinitions.js.map +1 -0
- package/lib/gc/{gcSummaryStateTracker.d.mts → gcSummaryStateTracker.d.ts} +13 -6
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -0
- package/lib/gc/{gcSummaryStateTracker.mjs → gcSummaryStateTracker.js} +17 -5
- package/lib/gc/gcSummaryStateTracker.js.map +1 -0
- package/lib/gc/{gcTelemetry.d.mts → gcTelemetry.d.ts} +7 -8
- package/lib/gc/gcTelemetry.d.ts.map +1 -0
- package/lib/gc/{gcTelemetry.mjs → gcTelemetry.js} +5 -3
- package/lib/gc/gcTelemetry.js.map +1 -0
- package/lib/gc/{gcUnreferencedStateTracker.d.mts → gcUnreferencedStateTracker.d.ts} +2 -2
- package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
- package/lib/gc/{gcUnreferencedStateTracker.mjs → gcUnreferencedStateTracker.js} +2 -2
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -0
- package/lib/gc/index.d.ts +13 -0
- package/lib/gc/index.d.ts.map +1 -0
- package/lib/gc/{index.mjs → index.js} +8 -8
- package/lib/gc/index.js.map +1 -0
- package/lib/{index.d.mts → index.d.ts} +12 -22
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +15 -0
- package/lib/index.js.map +1 -0
- package/lib/{messageTypes.d.mts → messageTypes.d.ts} +4 -4
- package/lib/messageTypes.d.ts.map +1 -0
- package/lib/{messageTypes.mjs → messageTypes.js} +1 -1
- package/lib/messageTypes.js.map +1 -0
- package/lib/{metadata.d.mts → metadata.d.ts} +1 -1
- package/lib/metadata.d.ts.map +1 -0
- package/lib/{metadata.mjs → metadata.js} +1 -1
- package/lib/metadata.js.map +1 -0
- package/lib/opLifecycle/{batchManager.d.mts → batchManager.d.ts} +3 -3
- package/lib/opLifecycle/batchManager.d.ts.map +1 -0
- package/lib/opLifecycle/{batchManager.mjs → batchManager.js} +1 -1
- package/lib/opLifecycle/batchManager.js.map +1 -0
- package/lib/opLifecycle/{definitions.d.mts → definitions.d.ts} +3 -3
- package/lib/opLifecycle/definitions.d.ts.map +1 -0
- package/lib/opLifecycle/{definitions.mjs → definitions.js} +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -0
- package/lib/opLifecycle/index.d.ts +13 -0
- package/lib/opLifecycle/index.d.ts.map +1 -0
- package/lib/opLifecycle/index.js +12 -0
- package/lib/opLifecycle/index.js.map +1 -0
- package/lib/opLifecycle/{opCompressor.d.mts → opCompressor.d.ts} +2 -2
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -0
- package/lib/opLifecycle/{opCompressor.mjs → opCompressor.js} +3 -3
- package/lib/opLifecycle/opCompressor.js.map +1 -0
- package/lib/opLifecycle/{opDecompressor.d.mts → opDecompressor.d.ts} +2 -2
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -0
- package/lib/opLifecycle/{opDecompressor.mjs → opDecompressor.js} +2 -2
- package/lib/opLifecycle/opDecompressor.js.map +1 -0
- package/lib/opLifecycle/{opGroupingManager.d.mts → opGroupingManager.d.ts} +2 -2
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -0
- package/lib/opLifecycle/{opGroupingManager.mjs → opGroupingManager.js} +2 -11
- package/lib/opLifecycle/opGroupingManager.js.map +1 -0
- package/lib/opLifecycle/{opSplitter.d.mts → opSplitter.d.ts} +2 -2
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -0
- package/lib/opLifecycle/{opSplitter.mjs → opSplitter.js} +3 -3
- package/lib/opLifecycle/opSplitter.js.map +1 -0
- package/lib/opLifecycle/{outbox.d.mts → outbox.d.ts} +8 -8
- package/lib/opLifecycle/outbox.d.ts.map +1 -0
- package/lib/opLifecycle/{outbox.mjs → outbox.js} +24 -10
- package/lib/opLifecycle/outbox.js.map +1 -0
- package/lib/opLifecycle/{remoteMessageProcessor.d.mts → remoteMessageProcessor.d.ts} +5 -5
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -0
- package/lib/opLifecycle/{remoteMessageProcessor.mjs → remoteMessageProcessor.js} +7 -4
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -0
- package/lib/{opProperties.d.mts → opProperties.d.ts} +1 -1
- package/lib/opProperties.d.ts.map +1 -0
- package/lib/{opProperties.mjs → opProperties.js} +1 -1
- package/lib/opProperties.js.map +1 -0
- package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
- package/lib/packageVersion.d.ts.map +1 -0
- package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
- package/lib/packageVersion.js.map +1 -0
- package/lib/{pendingStateManager.d.mts → pendingStateManager.d.ts} +3 -2
- package/lib/pendingStateManager.d.ts.map +1 -0
- package/lib/{pendingStateManager.mjs → pendingStateManager.js} +18 -10
- package/lib/pendingStateManager.js.map +1 -0
- package/lib/{scheduleManager.d.mts → scheduleManager.d.ts} +6 -3
- package/lib/scheduleManager.d.ts.map +1 -0
- package/lib/{scheduleManager.mjs → scheduleManager.js} +7 -3
- package/lib/scheduleManager.js.map +1 -0
- package/lib/{storageServiceWithAttachBlobs.d.mts → storageServiceWithAttachBlobs.d.ts} +1 -1
- package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -0
- package/lib/{storageServiceWithAttachBlobs.mjs → storageServiceWithAttachBlobs.js} +1 -1
- package/lib/storageServiceWithAttachBlobs.js.map +1 -0
- package/lib/summary/{index.d.mts → index.d.ts} +13 -13
- package/lib/summary/index.d.ts.map +1 -0
- package/lib/summary/{index.mjs → index.js} +12 -12
- package/lib/summary/index.js.map +1 -0
- package/lib/summary/{orderedClientElection.d.mts → orderedClientElection.d.ts} +5 -1
- package/lib/summary/orderedClientElection.d.ts.map +1 -0
- package/lib/summary/{orderedClientElection.mjs → orderedClientElection.js} +6 -2
- package/lib/summary/orderedClientElection.js.map +1 -0
- package/lib/summary/{runWhileConnectedCoordinator.d.mts → runWhileConnectedCoordinator.d.ts} +2 -2
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/lib/summary/{runWhileConnectedCoordinator.mjs → runWhileConnectedCoordinator.js} +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -0
- package/lib/summary/{runningSummarizer.d.mts → runningSummarizer.d.ts} +6 -5
- package/lib/summary/runningSummarizer.d.ts.map +1 -0
- package/lib/summary/{runningSummarizer.mjs → runningSummarizer.js} +41 -26
- package/lib/summary/runningSummarizer.js.map +1 -0
- package/lib/summary/{summarizer.d.mts → summarizer.d.ts} +5 -5
- package/lib/summary/summarizer.d.ts.map +1 -0
- package/lib/summary/{summarizer.mjs → summarizer.js} +4 -4
- package/lib/summary/summarizer.js.map +1 -0
- package/lib/summary/{summarizerClientElection.d.mts → summarizerClientElection.d.ts} +3 -3
- package/lib/summary/summarizerClientElection.d.ts.map +1 -0
- package/lib/summary/{summarizerClientElection.mjs → summarizerClientElection.js} +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -0
- package/lib/summary/{summarizerHeuristics.d.mts → summarizerHeuristics.d.ts} +4 -4
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
- package/lib/summary/{summarizerHeuristics.mjs → summarizerHeuristics.js} +1 -1
- package/lib/summary/summarizerHeuristics.js.map +1 -0
- package/lib/summary/summarizerNode/{index.d.mts → index.d.ts} +4 -4
- package/lib/summary/summarizerNode/index.d.ts.map +1 -0
- package/lib/summary/summarizerNode/index.js +7 -0
- package/lib/summary/summarizerNode/index.js.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNode.d.mts → summarizerNode.d.ts} +17 -6
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNode.mjs → summarizerNode.js} +34 -4
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeUtils.d.mts → summarizerNodeUtils.d.ts} +10 -2
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeUtils.mjs → summarizerNodeUtils.js} +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeWithGc.d.mts → summarizerNodeWithGc.d.ts} +4 -5
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeWithGc.mjs → summarizerNodeWithGc.js} +7 -7
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -0
- package/lib/summary/{summarizerTypes.d.mts → summarizerTypes.d.ts} +10 -21
- package/lib/summary/summarizerTypes.d.ts.map +1 -0
- package/lib/summary/{summarizerTypes.mjs → summarizerTypes.js} +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -0
- package/lib/summary/{summaryCollection.d.mts → summaryCollection.d.ts} +1 -1
- package/lib/summary/summaryCollection.d.ts.map +1 -0
- package/lib/summary/{summaryCollection.mjs → summaryCollection.js} +1 -1
- package/lib/summary/summaryCollection.js.map +1 -0
- package/lib/summary/{summaryFormat.d.mts → summaryFormat.d.ts} +16 -3
- package/lib/summary/summaryFormat.d.ts.map +1 -0
- package/lib/summary/{summaryFormat.mjs → summaryFormat.js} +1 -1
- package/lib/summary/summaryFormat.js.map +1 -0
- package/lib/summary/{summaryGenerator.d.mts → summaryGenerator.d.ts} +7 -6
- package/lib/summary/summaryGenerator.d.ts.map +1 -0
- package/lib/summary/{summaryGenerator.mjs → summaryGenerator.js} +11 -2
- package/lib/summary/summaryGenerator.js.map +1 -0
- package/lib/summary/{summaryManager.d.mts → summaryManager.d.ts} +6 -7
- package/lib/summary/summaryManager.d.ts.map +1 -0
- package/lib/summary/{summaryManager.mjs → summaryManager.js} +4 -5
- package/lib/summary/summaryManager.js.map +1 -0
- package/lib/test/batchTracker.spec.js +88 -0
- package/lib/test/batchTracker.spec.js.map +1 -0
- package/lib/test/blobManager.spec.js +835 -0
- package/lib/test/blobManager.spec.js.map +1 -0
- package/lib/test/channelCollection.spec.js +138 -0
- package/lib/test/channelCollection.spec.js.map +1 -0
- package/lib/test/containerRuntime.spec.js +1748 -0
- package/lib/test/containerRuntime.spec.js.map +1 -0
- package/lib/test/dataStoreContext.spec.js +771 -0
- package/lib/test/dataStoreContext.spec.js.map +1 -0
- package/lib/test/dataStoreCreation.spec.js +303 -0
- package/lib/test/dataStoreCreation.spec.js.map +1 -0
- package/lib/test/dataStoreRegistry.spec.js +26 -0
- package/lib/test/dataStoreRegistry.spec.js.map +1 -0
- package/lib/test/fuzz/fuzzUtils.js +66 -0
- package/lib/test/fuzz/fuzzUtils.js.map +1 -0
- package/lib/test/fuzz/summarizer.fuzz.spec.js +31 -0
- package/lib/test/fuzz/summarizer.fuzz.spec.js.map +1 -0
- package/lib/test/fuzz/summarizerFuzzMocks.js +162 -0
- package/lib/test/fuzz/summarizerFuzzMocks.js.map +1 -0
- package/lib/test/fuzz/summarizerFuzzSuite.js +106 -0
- package/lib/test/fuzz/summarizerFuzzSuite.js.map +1 -0
- package/lib/test/gc/garbageCollection.spec.js +1464 -0
- package/lib/test/gc/garbageCollection.spec.js.map +1 -0
- package/lib/test/gc/gcConfigs.spec.js +689 -0
- package/lib/test/gc/gcConfigs.spec.js.map +1 -0
- package/lib/test/gc/gcHelpers.spec.js +110 -0
- package/lib/test/gc/gcHelpers.spec.js.map +1 -0
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js +68 -0
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js.map +1 -0
- package/lib/test/gc/gcStats.spec.js +390 -0
- package/lib/test/gc/gcStats.spec.js.map +1 -0
- package/lib/test/gc/gcSummaryStateTracker.spec.js +228 -0
- package/lib/test/gc/gcSummaryStateTracker.spec.js.map +1 -0
- package/lib/test/gc/gcTelemetry.spec.js +530 -0
- package/lib/test/gc/gcTelemetry.spec.js.map +1 -0
- package/lib/test/gc/gcUnitTestHelpers.js +29 -0
- package/lib/test/gc/gcUnitTestHelpers.js.map +1 -0
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js +192 -0
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js.map +1 -0
- package/lib/test/getPendingBlobs.spec.js +193 -0
- package/lib/test/getPendingBlobs.spec.js.map +1 -0
- package/lib/test/hardwareStats.spec.js +93 -0
- package/lib/test/hardwareStats.spec.js.map +1 -0
- package/lib/test/index.js +6 -0
- package/lib/test/index.js.map +1 -0
- package/lib/test/opLifecycle/OpGroupingManager.spec.js +225 -0
- package/lib/test/opLifecycle/OpGroupingManager.spec.js.map +1 -0
- package/lib/test/opLifecycle/batchManager.spec.js +189 -0
- package/lib/test/opLifecycle/batchManager.spec.js.map +1 -0
- package/lib/test/opLifecycle/opCompressor.spec.js +74 -0
- package/lib/test/opLifecycle/opCompressor.spec.js.map +1 -0
- package/lib/test/opLifecycle/opDecompressor.spec.js +218 -0
- package/lib/test/opLifecycle/opDecompressor.spec.js.map +1 -0
- package/lib/test/opLifecycle/opSplitter.spec.js +272 -0
- package/lib/test/opLifecycle/opSplitter.spec.js.map +1 -0
- package/lib/test/opLifecycle/outbox.spec.js +675 -0
- package/lib/test/opLifecycle/outbox.spec.js.map +1 -0
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js +196 -0
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js.map +1 -0
- package/lib/test/pendingStateManager.spec.js +329 -0
- package/lib/test/pendingStateManager.spec.js.map +1 -0
- package/lib/test/scheduleManager.spec.js +270 -0
- package/lib/test/scheduleManager.spec.js.map +1 -0
- package/lib/test/summarizerNode.spec.js +326 -0
- package/lib/test/summarizerNode.spec.js.map +1 -0
- package/lib/test/summarizerNodeWithGc.spec.js +318 -0
- package/lib/test/summarizerNodeWithGc.spec.js.map +1 -0
- package/lib/test/summary/orderedClientElection.spec.js +535 -0
- package/lib/test/summary/orderedClientElection.spec.js.map +1 -0
- package/lib/test/summary/runningSummarizer.spec.js +1349 -0
- package/lib/test/summary/runningSummarizer.spec.js.map +1 -0
- package/lib/test/summary/summarizer.spec.js +29 -0
- package/lib/test/summary/summarizer.spec.js.map +1 -0
- package/lib/test/summary/summarizerClientElection.spec.js +436 -0
- package/lib/test/summary/summarizerClientElection.spec.js.map +1 -0
- package/lib/test/summary/summarizerHeuristics.spec.js +289 -0
- package/lib/test/summary/summarizerHeuristics.spec.js.map +1 -0
- package/lib/test/summary/summaryCollection.spec.js +200 -0
- package/lib/test/summary/summaryCollection.spec.js.map +1 -0
- package/lib/test/summary/summaryManager.spec.js +430 -0
- package/lib/test/summary/summaryManager.spec.js.map +1 -0
- package/lib/test/summary/testQuorumClients.js +34 -0
- package/lib/test/summary/testQuorumClients.js.map +1 -0
- package/lib/test/throttler.spec.js +175 -0
- package/lib/test/throttler.spec.js.map +1 -0
- package/lib/test/types/validateContainerRuntimePrevious.generated.js +180 -0
- package/lib/test/types/validateContainerRuntimePrevious.generated.js.map +1 -0
- package/lib/{throttler.d.mts → throttler.d.ts} +1 -1
- package/lib/throttler.d.ts.map +1 -0
- package/lib/{throttler.mjs → throttler.js} +1 -1
- package/lib/throttler.js.map +1 -0
- package/package.json +101 -88
- package/src/batchTracker.ts +1 -1
- package/src/blobManager.ts +1 -15
- package/src/{dataStores.ts → channelCollection.ts} +629 -178
- package/src/connectionTelemetry.ts +42 -3
- package/src/containerHandleContext.ts +1 -1
- package/src/containerRuntime.ts +626 -430
- package/src/dataStore.ts +16 -15
- package/src/dataStoreContext.ts +376 -216
- package/src/dataStoreContexts.ts +2 -1
- package/src/dataStoreRegistry.ts +1 -0
- package/src/deltaManagerSummarizerProxy.ts +132 -7
- package/src/gc/garbageCollection.ts +84 -44
- package/src/gc/gcConfigs.ts +17 -7
- package/src/gc/gcDefinitions.ts +23 -13
- package/src/gc/gcHelpers.ts +2 -2
- package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
- package/src/gc/gcSummaryStateTracker.ts +19 -7
- package/src/gc/gcTelemetry.ts +9 -7
- package/src/gc/gcUnreferencedStateTracker.ts +1 -1
- package/src/gc/index.ts +10 -9
- package/src/index.ts +28 -27
- package/src/messageTypes.ts +3 -3
- package/src/opLifecycle/README.md +2 -4
- package/src/opLifecycle/batchManager.ts +2 -2
- package/src/opLifecycle/definitions.ts +2 -2
- package/src/opLifecycle/index.ts +8 -8
- package/src/opLifecycle/opCompressor.ts +3 -3
- package/src/opLifecycle/opDecompressor.ts +3 -3
- package/src/opLifecycle/opGroupingManager.ts +3 -12
- package/src/opLifecycle/opSplitter.ts +3 -3
- package/src/opLifecycle/outbox.ts +43 -16
- package/src/opLifecycle/remoteMessageProcessor.ts +10 -6
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +19 -13
- package/src/scheduleManager.ts +5 -4
- package/src/summary/index.ts +13 -12
- package/src/summary/orderedClientElection.ts +2 -1
- package/src/summary/runWhileConnectedCoordinator.ts +1 -1
- package/src/summary/runningSummarizer.ts +52 -32
- package/src/summary/summarizer.ts +7 -7
- package/src/summary/summarizerClientElection.ts +2 -2
- package/src/summary/summarizerHeuristics.ts +3 -3
- package/src/summary/summarizerNode/index.ts +6 -3
- package/src/summary/summarizerNode/summarizerNode.ts +50 -5
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +14 -1
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +11 -11
- package/src/summary/summarizerTypes.ts +11 -23
- package/src/summary/summaryFormat.ts +16 -2
- package/src/summary/summaryGenerator.ts +16 -4
- package/src/summary/summaryManager.ts +6 -7
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.json +2 -5
- package/dist/dataStores.d.ts +0 -151
- package/dist/dataStores.d.ts.map +0 -1
- package/dist/dataStores.js.map +0 -1
- package/dist/deltaManagerProxyBase.d.ts.map +0 -1
- package/dist/deltaManagerProxyBase.js +0 -77
- package/dist/deltaManagerProxyBase.js.map +0 -1
- package/lib/batchTracker.d.mts.map +0 -1
- package/lib/batchTracker.mjs.map +0 -1
- package/lib/blobManager.d.mts.map +0 -1
- package/lib/blobManager.mjs.map +0 -1
- package/lib/connectionTelemetry.d.mts.map +0 -1
- package/lib/connectionTelemetry.mjs.map +0 -1
- package/lib/containerHandleContext.d.mts.map +0 -1
- package/lib/containerHandleContext.mjs.map +0 -1
- package/lib/containerRuntime.d.mts.map +0 -1
- package/lib/containerRuntime.mjs.map +0 -1
- package/lib/dataStore.d.mts.map +0 -1
- package/lib/dataStore.mjs.map +0 -1
- package/lib/dataStoreContext.d.mts.map +0 -1
- package/lib/dataStoreContext.mjs.map +0 -1
- package/lib/dataStoreContexts.d.mts.map +0 -1
- package/lib/dataStoreContexts.mjs.map +0 -1
- package/lib/dataStoreRegistry.d.mts.map +0 -1
- package/lib/dataStoreRegistry.mjs.map +0 -1
- package/lib/dataStores.d.mts +0 -151
- package/lib/dataStores.d.mts.map +0 -1
- package/lib/dataStores.mjs.map +0 -1
- package/lib/deltaManagerProxyBase.d.mts +0 -35
- package/lib/deltaManagerProxyBase.d.mts.map +0 -1
- package/lib/deltaManagerProxyBase.mjs +0 -73
- package/lib/deltaManagerProxyBase.mjs.map +0 -1
- package/lib/deltaManagerSummarizerProxy.d.mts +0 -19
- package/lib/deltaManagerSummarizerProxy.d.mts.map +0 -1
- package/lib/deltaManagerSummarizerProxy.mjs +0 -38
- package/lib/deltaManagerSummarizerProxy.mjs.map +0 -1
- package/lib/deltaScheduler.d.mts.map +0 -1
- package/lib/deltaScheduler.mjs.map +0 -1
- package/lib/error.d.mts.map +0 -1
- package/lib/error.mjs.map +0 -1
- package/lib/gc/garbageCollection.d.mts.map +0 -1
- package/lib/gc/garbageCollection.mjs.map +0 -1
- package/lib/gc/gcConfigs.d.mts.map +0 -1
- package/lib/gc/gcConfigs.mjs.map +0 -1
- package/lib/gc/gcDefinitions.d.mts.map +0 -1
- package/lib/gc/gcDefinitions.mjs.map +0 -1
- package/lib/gc/gcHelpers.mjs.map +0 -1
- package/lib/gc/gcReferenceGraphAlgorithm.d.mts.map +0 -1
- package/lib/gc/gcReferenceGraphAlgorithm.mjs.map +0 -1
- package/lib/gc/gcSummaryDefinitions.d.mts.map +0 -1
- package/lib/gc/gcSummaryDefinitions.mjs.map +0 -1
- package/lib/gc/gcSummaryStateTracker.d.mts.map +0 -1
- package/lib/gc/gcSummaryStateTracker.mjs.map +0 -1
- package/lib/gc/gcTelemetry.d.mts.map +0 -1
- package/lib/gc/gcTelemetry.mjs.map +0 -1
- package/lib/gc/gcUnreferencedStateTracker.d.mts.map +0 -1
- package/lib/gc/gcUnreferencedStateTracker.mjs.map +0 -1
- package/lib/gc/index.d.mts +0 -13
- package/lib/gc/index.d.mts.map +0 -1
- package/lib/gc/index.mjs.map +0 -1
- package/lib/index.d.mts.map +0 -1
- package/lib/index.mjs +0 -25
- package/lib/index.mjs.map +0 -1
- package/lib/messageTypes.d.mts.map +0 -1
- package/lib/messageTypes.mjs.map +0 -1
- package/lib/metadata.d.mts.map +0 -1
- package/lib/metadata.mjs.map +0 -1
- package/lib/opLifecycle/batchManager.d.mts.map +0 -1
- package/lib/opLifecycle/batchManager.mjs.map +0 -1
- package/lib/opLifecycle/definitions.d.mts.map +0 -1
- package/lib/opLifecycle/definitions.mjs.map +0 -1
- package/lib/opLifecycle/index.d.mts +0 -13
- package/lib/opLifecycle/index.d.mts.map +0 -1
- package/lib/opLifecycle/index.mjs +0 -12
- package/lib/opLifecycle/index.mjs.map +0 -1
- package/lib/opLifecycle/opCompressor.d.mts.map +0 -1
- package/lib/opLifecycle/opCompressor.mjs.map +0 -1
- package/lib/opLifecycle/opDecompressor.d.mts.map +0 -1
- package/lib/opLifecycle/opDecompressor.mjs.map +0 -1
- package/lib/opLifecycle/opGroupingManager.d.mts.map +0 -1
- package/lib/opLifecycle/opGroupingManager.mjs.map +0 -1
- package/lib/opLifecycle/opSplitter.d.mts.map +0 -1
- package/lib/opLifecycle/opSplitter.mjs.map +0 -1
- package/lib/opLifecycle/outbox.d.mts.map +0 -1
- package/lib/opLifecycle/outbox.mjs.map +0 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.mts.map +0 -1
- package/lib/opLifecycle/remoteMessageProcessor.mjs.map +0 -1
- package/lib/opProperties.d.mts.map +0 -1
- package/lib/opProperties.mjs.map +0 -1
- package/lib/packageVersion.d.mts.map +0 -1
- package/lib/packageVersion.mjs.map +0 -1
- package/lib/pendingStateManager.d.mts.map +0 -1
- package/lib/pendingStateManager.mjs.map +0 -1
- package/lib/scheduleManager.d.mts.map +0 -1
- package/lib/scheduleManager.mjs.map +0 -1
- package/lib/storageServiceWithAttachBlobs.d.mts.map +0 -1
- package/lib/storageServiceWithAttachBlobs.mjs.map +0 -1
- package/lib/summary/index.d.mts.map +0 -1
- package/lib/summary/index.mjs.map +0 -1
- package/lib/summary/orderedClientElection.d.mts.map +0 -1
- package/lib/summary/orderedClientElection.mjs.map +0 -1
- package/lib/summary/runWhileConnectedCoordinator.d.mts.map +0 -1
- package/lib/summary/runWhileConnectedCoordinator.mjs.map +0 -1
- package/lib/summary/runningSummarizer.d.mts.map +0 -1
- package/lib/summary/runningSummarizer.mjs.map +0 -1
- package/lib/summary/summarizer.d.mts.map +0 -1
- package/lib/summary/summarizer.mjs.map +0 -1
- package/lib/summary/summarizerClientElection.d.mts.map +0 -1
- package/lib/summary/summarizerClientElection.mjs.map +0 -1
- package/lib/summary/summarizerHeuristics.d.mts.map +0 -1
- package/lib/summary/summarizerHeuristics.mjs.map +0 -1
- package/lib/summary/summarizerNode/index.d.mts.map +0 -1
- package/lib/summary/summarizerNode/index.mjs +0 -7
- package/lib/summary/summarizerNode/index.mjs.map +0 -1
- package/lib/summary/summarizerNode/summarizerNode.d.mts.map +0 -1
- package/lib/summary/summarizerNode/summarizerNode.mjs.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.mts.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.mjs.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.mts.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.mjs.map +0 -1
- package/lib/summary/summarizerTypes.d.mts.map +0 -1
- package/lib/summary/summarizerTypes.mjs.map +0 -1
- package/lib/summary/summaryCollection.d.mts.map +0 -1
- package/lib/summary/summaryCollection.mjs.map +0 -1
- package/lib/summary/summaryFormat.d.mts.map +0 -1
- package/lib/summary/summaryFormat.mjs.map +0 -1
- package/lib/summary/summaryGenerator.d.mts.map +0 -1
- package/lib/summary/summaryGenerator.mjs.map +0 -1
- package/lib/summary/summaryManager.d.mts.map +0 -1
- package/lib/summary/summaryManager.mjs.map +0 -1
- package/lib/throttler.d.mts.map +0 -1
- package/lib/throttler.mjs.map +0 -1
- package/src/deltaManagerProxyBase.ts +0 -111
|
@@ -1,31 +1,33 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
1
5
|
import { AttachState, LoaderHeader, } from "@fluidframework/container-definitions";
|
|
2
|
-
import { assert, delay, LazyPromise } from "@fluidframework/core-utils";
|
|
6
|
+
import { assert, Deferred, delay, LazyPromise, PromiseCache } from "@fluidframework/core-utils";
|
|
3
7
|
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";
|
|
8
|
+
import { createChildLogger, createChildMonitoringContext, DataCorruptionError, DataProcessingError, GenericError, raiseConnectedEvent, PerformanceEvent, TaggedLoggerAdapter, wrapError, UsageError, LoggingError, createSampledLogger, loggerToMonitoringContext, } from "@fluidframework/telemetry-utils";
|
|
7
9
|
import { DriverHeader, FetchSource, } from "@fluidframework/driver-definitions";
|
|
8
10
|
import { readAndParse } from "@fluidframework/driver-utils";
|
|
9
11
|
import { MessageType, SummaryType, } from "@fluidframework/protocol-definitions";
|
|
10
12
|
import { FlushMode, FlushModeExperimental, gcTreeKey, channelsTreeName, } from "@fluidframework/runtime-definitions";
|
|
11
|
-
import { addBlobToSummary, addSummarizeResultToSummary,
|
|
13
|
+
import { addBlobToSummary, addSummarizeResultToSummary, RequestParser, create404Response, exceptionToResponse, GCDataBuilder, seqFromTree, calculateStats, TelemetryContext, responseToException, } from "@fluidframework/runtime-utils";
|
|
12
14
|
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.
|
|
15
|
+
import { ContainerFluidHandleContext } from "./containerHandleContext.js";
|
|
16
|
+
import { FluidDataStoreRegistry } from "./dataStoreRegistry.js";
|
|
17
|
+
import { ReportOpPerfTelemetry } from "./connectionTelemetry.js";
|
|
18
|
+
import { PendingStateManager, } from "./pendingStateManager.js";
|
|
19
|
+
import { pkgVersion } from "./packageVersion.js";
|
|
20
|
+
import { BlobManager } from "./blobManager.js";
|
|
21
|
+
import { ChannelCollection, getSummaryForDatastores, wrapContext } from "./channelCollection.js";
|
|
22
|
+
import { aliasBlobName, blobsTreeName, chunksBlobName, createRootSummarizerNodeWithGC, electedSummarizerBlobName, extractSummaryMetadataMessage, idCompressorBlobName, metadataBlobName, Summarizer, SummaryManager, wrapSummaryInChannelsTree, SummaryCollection, OrderedClientCollection, OrderedClientElection, SummarizerClientElection, summarizerClientType, RunWhileConnectedCoordinator, RetriableSummaryError, rootHasIsolatedChannels, } from "./summary/index.js";
|
|
23
|
+
import { formExponentialFn, Throttler } from "./throttler.js";
|
|
24
|
+
import { GarbageCollector, GCNodeType, gcGenerationOptionName, } from "./gc/index.js";
|
|
25
|
+
import { channelToDataStore } from "./dataStore.js";
|
|
26
|
+
import { BindBatchTracker } from "./batchTracker.js";
|
|
27
|
+
import { ScheduleManager } from "./scheduleManager.js";
|
|
28
|
+
import { OpCompressor, OpDecompressor, Outbox, OpSplitter, RemoteMessageProcessor, OpGroupingManager, getLongStack, } from "./opLifecycle/index.js";
|
|
29
|
+
import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy.js";
|
|
30
|
+
import { ContainerMessageType, } from "./messageTypes.js";
|
|
29
31
|
/**
|
|
30
32
|
* Utility to implement compat behaviors given an unknown message type
|
|
31
33
|
* The parameters are typed to support compile-time enforcement of handling all known types/behaviors
|
|
@@ -55,26 +57,6 @@ export const DefaultSummaryConfiguration = {
|
|
|
55
57
|
runtimeOpWeight: 1.0,
|
|
56
58
|
nonRuntimeHeuristicThreshold: 20,
|
|
57
59
|
};
|
|
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
60
|
/**
|
|
79
61
|
* Tombstone error responses will have this header set to true
|
|
80
62
|
* @alpha
|
|
@@ -243,7 +225,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
243
225
|
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
244
226
|
const backCompatContext = context;
|
|
245
227
|
const passLogger = backCompatContext.taggedLogger ??
|
|
246
|
-
// eslint-disable-next-line import/no-deprecated
|
|
247
228
|
new TaggedLoggerAdapter(backCompatContext.logger);
|
|
248
229
|
const logger = createChildLogger({
|
|
249
230
|
logger: passLogger,
|
|
@@ -253,7 +234,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
253
234
|
},
|
|
254
235
|
},
|
|
255
236
|
});
|
|
256
|
-
const
|
|
237
|
+
const mc = loggerToMonitoringContext(logger);
|
|
238
|
+
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor = "off", chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, enableGroupedBatching = false, } = runtimeOptions;
|
|
257
239
|
const registry = new FluidDataStoreRegistry(registryEntries);
|
|
258
240
|
const tryFetchBlob = async (blobName) => {
|
|
259
241
|
const blobId = context.baseSnapshot?.blobs[blobName];
|
|
@@ -298,9 +280,37 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
298
280
|
}
|
|
299
281
|
}
|
|
300
282
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
283
|
+
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
284
|
+
// allow new containers to turn it on
|
|
285
|
+
let idCompressorMode;
|
|
286
|
+
if (existing) {
|
|
287
|
+
// This setting has to be sticky for correctness:
|
|
288
|
+
// 1) if compressior is OFF, it can't be enabled, as already running clients (in given document session) do not know
|
|
289
|
+
// how to process compressor ops
|
|
290
|
+
// 2) if it's ON, then all sessions should load compressor right away
|
|
291
|
+
// 3) Same logic applies for "delayed" mode
|
|
292
|
+
// Maybe in the future we will need to enabled (and figure how to do it safely) "delayed" -> "on" change.
|
|
293
|
+
// We could do "off" -> "on" transtition too, if all clients start loading compressor (but not using it initially) and do so for a while -
|
|
294
|
+
// this will allow clients to eventually to disregard "off" setting (when it's safe so) and start using compressor in future sessions.
|
|
295
|
+
// Everyting is possible, but it needs to be designed and executed carefully, when such need arises.
|
|
296
|
+
idCompressorMode = metadata?.idCompressorMode ?? "off";
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
// FG overwrite
|
|
300
|
+
const enabled = mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled");
|
|
301
|
+
switch (enabled) {
|
|
302
|
+
case true:
|
|
303
|
+
idCompressorMode = "on";
|
|
304
|
+
break;
|
|
305
|
+
case false:
|
|
306
|
+
idCompressorMode = "off";
|
|
307
|
+
break;
|
|
308
|
+
default:
|
|
309
|
+
idCompressorMode = enableRuntimeIdCompressor;
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
const createIdCompressorFn = async () => {
|
|
304
314
|
const { createIdCompressor, deserializeIdCompressor, createSessionId } = await import("@fluidframework/id-compressor");
|
|
305
315
|
/**
|
|
306
316
|
* Because the IdCompressor emits so much telemetry, this function is used to sample
|
|
@@ -317,15 +327,15 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
317
327
|
const compressorLogger = createSampledLogger(logger, idCompressorEventSampler);
|
|
318
328
|
const pendingLocalState = context.pendingLocalState;
|
|
319
329
|
if (pendingLocalState?.pendingIdCompressorState !== undefined) {
|
|
320
|
-
|
|
330
|
+
return deserializeIdCompressor(pendingLocalState.pendingIdCompressorState, compressorLogger);
|
|
321
331
|
}
|
|
322
332
|
else if (serializedIdCompressor !== undefined) {
|
|
323
|
-
|
|
333
|
+
return deserializeIdCompressor(serializedIdCompressor, createSessionId(), compressorLogger);
|
|
324
334
|
}
|
|
325
335
|
else {
|
|
326
|
-
|
|
336
|
+
return createIdCompressor(compressorLogger);
|
|
327
337
|
}
|
|
328
|
-
}
|
|
338
|
+
};
|
|
329
339
|
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], {
|
|
330
340
|
summaryOptions,
|
|
331
341
|
gcOptions,
|
|
@@ -337,7 +347,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
337
347
|
enableRuntimeIdCompressor,
|
|
338
348
|
enableOpReentryCheck,
|
|
339
349
|
enableGroupedBatching,
|
|
340
|
-
}, containerScope, logger, existing, blobManagerSnapshot, context.storage,
|
|
350
|
+
}, containerScope, logger, existing, blobManagerSnapshot, context.storage, createIdCompressorFn, idCompressorMode, provideEntryPoint, requestHandler, undefined);
|
|
341
351
|
// Apply stashed ops with a reference sequence number equal to the sequence number of the snapshot,
|
|
342
352
|
// or zero. This must be done before Container replays saved ops.
|
|
343
353
|
await runtime.pendingStateManager.applyStashedOpsAt(runtimeSequenceNumber ?? 0);
|
|
@@ -351,6 +361,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
351
361
|
get storage() {
|
|
352
362
|
return this._storage;
|
|
353
363
|
}
|
|
364
|
+
get containerRuntime() {
|
|
365
|
+
return this;
|
|
366
|
+
}
|
|
354
367
|
get flushMode() {
|
|
355
368
|
return this._flushMode;
|
|
356
369
|
}
|
|
@@ -363,6 +376,25 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
363
376
|
get attachState() {
|
|
364
377
|
return this._getAttachState();
|
|
365
378
|
}
|
|
379
|
+
/**
|
|
380
|
+
* See IContainerRuntimeBase.idCompressor() for details.
|
|
381
|
+
*/
|
|
382
|
+
get idCompressor() {
|
|
383
|
+
// Expose ID Compressor only if it's On from the start.
|
|
384
|
+
// If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
|
|
385
|
+
// That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
|
|
386
|
+
// to reason over such things as session ID space.
|
|
387
|
+
if (this.idCompressorMode === "on") {
|
|
388
|
+
assert(this._idCompressor !== undefined, 0x8ea /* compressor should have been loaded */);
|
|
389
|
+
return this._idCompressor;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* See IContainerRuntimeBase.generateDocumentUniqueId() for details.
|
|
394
|
+
*/
|
|
395
|
+
generateDocumentUniqueId() {
|
|
396
|
+
return this._idCompressor?.generateDocumentUniqueId() ?? uuid();
|
|
397
|
+
}
|
|
366
398
|
get IFluidHandleContext() {
|
|
367
399
|
return this.handleContext;
|
|
368
400
|
}
|
|
@@ -400,9 +432,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
400
432
|
isSummariesDisabled() {
|
|
401
433
|
return this.summaryConfiguration.state === "disabled";
|
|
402
434
|
}
|
|
403
|
-
isHeuristicsDisabled() {
|
|
404
|
-
return this.summaryConfiguration.state === "disableHeuristics";
|
|
405
|
-
}
|
|
406
435
|
getMaxOpsSinceLastSummary() {
|
|
407
436
|
return this.summaryConfiguration.state !== "disabled"
|
|
408
437
|
? this.summaryConfiguration.maxOpsSinceLastSummary
|
|
@@ -427,7 +456,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
427
456
|
return this.garbageCollector.throwOnTombstoneUsage;
|
|
428
457
|
}
|
|
429
458
|
/***/
|
|
430
|
-
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage,
|
|
459
|
+
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, createIdCompressor, idCompressorMode, provideEntryPoint, requestHandler, summaryConfiguration = {
|
|
431
460
|
// the defaults
|
|
432
461
|
...DefaultSummaryConfiguration,
|
|
433
462
|
// the runtime configuration overrides
|
|
@@ -435,13 +464,24 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
435
464
|
}) {
|
|
436
465
|
super();
|
|
437
466
|
this.registry = registry;
|
|
467
|
+
this.metadata = metadata;
|
|
438
468
|
this.runtimeOptions = runtimeOptions;
|
|
439
469
|
this.containerScope = containerScope;
|
|
440
470
|
this.logger = logger;
|
|
441
471
|
this._storage = _storage;
|
|
472
|
+
this.createIdCompressor = createIdCompressor;
|
|
473
|
+
this.idCompressorMode = idCompressorMode;
|
|
442
474
|
this.requestHandler = requestHandler;
|
|
443
475
|
this.summaryConfiguration = summaryConfiguration;
|
|
444
476
|
this.imminentClosure = false;
|
|
477
|
+
// We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
|
|
478
|
+
// Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
|
|
479
|
+
this.pendingIdCompressorOps = [];
|
|
480
|
+
/**
|
|
481
|
+
* True if we have ID compressor loading in-flight (async operation). Useful only for
|
|
482
|
+
* this.idCompressorMode === "delayed" mode
|
|
483
|
+
*/
|
|
484
|
+
this.compressorLoadInitiated = false;
|
|
445
485
|
this.defaultMaxConsecutiveReconnects = 7;
|
|
446
486
|
this._orderSequentiallyCalls = 0;
|
|
447
487
|
this.flushTaskExists = false;
|
|
@@ -463,6 +503,13 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
463
503
|
signalTimestamp: 0,
|
|
464
504
|
trackingSignalSequenceNumber: undefined,
|
|
465
505
|
};
|
|
506
|
+
/**
|
|
507
|
+
* It a cache for holding mapping for loading groupIds with its snapshot from the service. Add expiry policy of 1 minute.
|
|
508
|
+
* Starting with 1 min and based on recorded usage we can tweak it later on.
|
|
509
|
+
*/
|
|
510
|
+
this.snapshotCacheForLoadingGroupIds = new PromiseCache({
|
|
511
|
+
expiry: { policy: "absolute", durationMs: 60000 },
|
|
512
|
+
});
|
|
466
513
|
const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, loader, pendingLocalState, supportedFeatures, } = context;
|
|
467
514
|
this.innerDeltaManager = deltaManager;
|
|
468
515
|
this.deltaManager = new DeltaManagerSummarizerProxy(this.innerDeltaManager);
|
|
@@ -472,7 +519,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
472
519
|
this.submitBatchFn = submitBatchFn;
|
|
473
520
|
this.submitSummaryFn = submitSummaryFn;
|
|
474
521
|
this.submitSignalFn = submitSignalFn;
|
|
475
|
-
|
|
522
|
+
// TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
|
|
523
|
+
// Values are generally expected to be set from the runtime side.
|
|
524
|
+
this.options = options ?? {};
|
|
476
525
|
this.clientDetails = clientDetails;
|
|
477
526
|
this.isSummarizerClient = this.clientDetails.type === summarizerClientType;
|
|
478
527
|
this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
|
|
@@ -510,9 +559,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
510
559
|
// summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
|
|
511
560
|
// the count is reset to 0.
|
|
512
561
|
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
562
|
}
|
|
517
563
|
else {
|
|
518
564
|
this.createContainerMetadata = {
|
|
@@ -520,9 +566,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
520
566
|
createContainerTimestamp: Date.now(),
|
|
521
567
|
};
|
|
522
568
|
loadSummaryNumber = 0;
|
|
523
|
-
this.idCompressorEnabled =
|
|
524
|
-
this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled") ??
|
|
525
|
-
idCompressor !== undefined;
|
|
526
569
|
}
|
|
527
570
|
this.nextSummaryNumber = loadSummaryNumber + 1;
|
|
528
571
|
this.messageAtLastSummary = metadata?.message;
|
|
@@ -557,12 +600,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
557
600
|
// Allow for a break-glass config to override the options
|
|
558
601
|
disableOpReentryCheck !== true;
|
|
559
602
|
this.summariesDisabled = this.isSummariesDisabled();
|
|
560
|
-
this.heuristicsDisabled = this.isHeuristicsDisabled();
|
|
561
603
|
this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
|
|
562
604
|
this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
|
|
563
|
-
if (this.idCompressorEnabled) {
|
|
564
|
-
this.idCompressor = idCompressor;
|
|
565
|
-
}
|
|
566
605
|
this.maxConsecutiveReconnects =
|
|
567
606
|
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
|
|
568
607
|
this.defaultMaxConsecutiveReconnects;
|
|
@@ -599,6 +638,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
599
638
|
getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
|
|
600
639
|
readAndParseBlob: async (id) => readAndParse(this.storage, id),
|
|
601
640
|
submitMessage: (message) => this.submit(message),
|
|
641
|
+
sessionExpiryTimerStarted: pendingRuntimeState?.sessionExpiryTimerStarted,
|
|
602
642
|
});
|
|
603
643
|
const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
|
|
604
644
|
this.summarizerNode = createRootSummarizerNodeWithGC(createChildLogger({ logger: this.logger, namespace: "SummarizerNode" }),
|
|
@@ -621,7 +661,16 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
621
661
|
if (baseSnapshot) {
|
|
622
662
|
this.summarizerNode.updateBaseSummaryState(baseSnapshot);
|
|
623
663
|
}
|
|
624
|
-
|
|
664
|
+
const parentContext = wrapContext(this);
|
|
665
|
+
// Due to a mismatch between different layers in terms of
|
|
666
|
+
// what is the interface of passing signals, we need the
|
|
667
|
+
// downstream stores to wrap the signal.
|
|
668
|
+
parentContext.submitSignal = (type, content, targetClientId) => {
|
|
669
|
+
const envelope1 = content;
|
|
670
|
+
const envelope2 = this.createNewSignalEnvelope(envelope1.address, type, envelope1.contents);
|
|
671
|
+
return this.submitSignalFn(envelope2, targetClientId);
|
|
672
|
+
};
|
|
673
|
+
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
674
|
this.blobManager = new BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (localId, blobId) => {
|
|
626
675
|
if (!this.disposed) {
|
|
627
676
|
this.submit({ type: ContainerMessageType.BlobAttach, contents: undefined }, undefined, {
|
|
@@ -636,9 +685,13 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
636
685
|
clientId: () => this.clientId,
|
|
637
686
|
close: this.closeFn,
|
|
638
687
|
connected: () => this.connected,
|
|
639
|
-
reSubmit:
|
|
688
|
+
reSubmit: (message) => {
|
|
689
|
+
this.reSubmit(message);
|
|
690
|
+
this.flush();
|
|
691
|
+
},
|
|
640
692
|
reSubmitBatch: this.reSubmitBatch.bind(this),
|
|
641
693
|
isActiveConnection: () => this.innerDeltaManager.active,
|
|
694
|
+
isAttached: () => this.attachState !== AttachState.Detached,
|
|
642
695
|
}, pendingRuntimeState?.pending, this.logger);
|
|
643
696
|
const disableCompression = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionDisabled");
|
|
644
697
|
const compressionOptions = disableCompression === true
|
|
@@ -730,7 +783,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
730
783
|
// throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
|
|
731
784
|
formExponentialFn({ coefficient: 20, initialDelay: 0 })), {
|
|
732
785
|
initialDelayMs: this.initialSummarizerDelayMs,
|
|
733
|
-
}
|
|
786
|
+
});
|
|
734
787
|
this.summaryManager.on("summarize", (eventProps) => {
|
|
735
788
|
this.emit("summarize", eventProps);
|
|
736
789
|
});
|
|
@@ -745,25 +798,26 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
745
798
|
this.mc.logger.sendTelemetryEvent({
|
|
746
799
|
eventName: "ContainerLoadStats",
|
|
747
800
|
...this.createContainerMetadata,
|
|
748
|
-
...this.
|
|
801
|
+
...this.channelCollection.containerLoadStats,
|
|
749
802
|
summaryNumber: loadSummaryNumber,
|
|
750
803
|
summaryFormatVersion: metadata?.summaryFormatVersion,
|
|
751
804
|
disableIsolatedChannels: metadata?.disableIsolatedChannels,
|
|
752
805
|
gcVersion: metadata?.gcFeature,
|
|
753
806
|
options: JSON.stringify(runtimeOptions),
|
|
807
|
+
idCompressorModeMetadata: metadata?.idCompressorMode,
|
|
808
|
+
idCompressorMode: this.idCompressorMode,
|
|
754
809
|
featureGates: JSON.stringify({
|
|
755
810
|
disableCompression,
|
|
756
811
|
disableOpReentryCheck,
|
|
757
812
|
disableChunking,
|
|
758
813
|
disableAttachReorder: this.disableAttachReorder,
|
|
759
814
|
disablePartialFlush,
|
|
760
|
-
idCompressorEnabled: this.idCompressorEnabled,
|
|
761
815
|
closeSummarizerDelayOverride,
|
|
762
816
|
}),
|
|
763
817
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
764
818
|
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
765
819
|
});
|
|
766
|
-
ReportOpPerfTelemetry(this.clientId, this.deltaManager, this.logger);
|
|
820
|
+
ReportOpPerfTelemetry(this.clientId, this.deltaManager, this, this.logger);
|
|
767
821
|
BindBatchTracker(this, this.logger);
|
|
768
822
|
this.entryPoint = new LazyPromise(async () => {
|
|
769
823
|
if (this.isSummarizerClient) {
|
|
@@ -772,11 +826,33 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
772
826
|
}
|
|
773
827
|
return provideEntryPoint(this);
|
|
774
828
|
});
|
|
829
|
+
// If we loaded from pending state, then we need to skip any ops that are already accounted in such
|
|
830
|
+
// saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
|
|
831
|
+
this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
|
|
832
|
+
}
|
|
833
|
+
getCreateChildSummarizerNodeFn(id, createParam) {
|
|
834
|
+
return (summarizeInternal, getGCDataFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn);
|
|
835
|
+
}
|
|
836
|
+
deleteChildSummarizerNode(id) {
|
|
837
|
+
return this.summarizerNode.deleteChild(id);
|
|
838
|
+
}
|
|
839
|
+
/* IFluidParentContext APIs that should not be called on Root */
|
|
840
|
+
makeLocallyVisible() {
|
|
841
|
+
assert(false, 0x8eb /* should not be called */);
|
|
842
|
+
}
|
|
843
|
+
setChannelDirty(address) {
|
|
844
|
+
assert(false, 0x909 /* should not be called */);
|
|
775
845
|
}
|
|
776
846
|
/**
|
|
777
847
|
* Initializes the state from the base snapshot this container runtime loaded from.
|
|
778
848
|
*/
|
|
779
849
|
async initializeBaseState() {
|
|
850
|
+
if (this.idCompressorMode === "on" ||
|
|
851
|
+
(this.idCompressorMode === "delayed" && this.connected)) {
|
|
852
|
+
// This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
|
|
853
|
+
assert(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
|
|
854
|
+
this._idCompressor = await this.createIdCompressor();
|
|
855
|
+
}
|
|
780
856
|
await this.garbageCollector.initializeBaseState();
|
|
781
857
|
}
|
|
782
858
|
dispose(error) {
|
|
@@ -795,11 +871,110 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
795
871
|
}
|
|
796
872
|
this.garbageCollector.dispose();
|
|
797
873
|
this._summarizer?.dispose();
|
|
798
|
-
this.
|
|
874
|
+
this.channelCollection.dispose();
|
|
799
875
|
this.pendingStateManager.dispose();
|
|
800
876
|
this.emit("dispose");
|
|
801
877
|
this.removeAllListeners();
|
|
802
878
|
}
|
|
879
|
+
/**
|
|
880
|
+
* Api to fetch the snapshot from the service for a loadingGroupIds.
|
|
881
|
+
* @param loadingGroupIds - LoadingGroupId for which the snapshot is asked for.
|
|
882
|
+
* @param pathParts - Parts of the path, which we want to extract from the snapshot tree.
|
|
883
|
+
* @returns - snapshotTree and the sequence number of the snapshot.
|
|
884
|
+
*/
|
|
885
|
+
async getSnapshotForLoadingGroupId(loadingGroupIds, pathParts) {
|
|
886
|
+
const sortedLoadingGroupIds = loadingGroupIds.sort();
|
|
887
|
+
assert(this.storage.getSnapshot !== undefined, 0x8ed /* getSnapshot api should be defined if used */);
|
|
888
|
+
let loadedFromCache = true;
|
|
889
|
+
// Lookup up in the cache, if not present then make the network call as multiple datastores could
|
|
890
|
+
// be in same loading group. So, once we have fetched the snapshot for that loading group on
|
|
891
|
+
// any request, then cache that as same group could be requested in future too.
|
|
892
|
+
const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(), async () => {
|
|
893
|
+
assert(this.storage.getSnapshot !== undefined, 0x8ee /* getSnapshot api should be defined if used */);
|
|
894
|
+
loadedFromCache = false;
|
|
895
|
+
return this.storage.getSnapshot({
|
|
896
|
+
cacheSnapshot: false,
|
|
897
|
+
scenarioName: "snapshotForLoadingGroupId",
|
|
898
|
+
loadingGroupIds: sortedLoadingGroupIds,
|
|
899
|
+
});
|
|
900
|
+
});
|
|
901
|
+
this.logger.sendTelemetryEvent({
|
|
902
|
+
eventName: "GroupIdSnapshotFetched",
|
|
903
|
+
details: JSON.stringify({
|
|
904
|
+
fromCache: loadedFromCache,
|
|
905
|
+
loadingGroupIds: loadingGroupIds.join(","),
|
|
906
|
+
}),
|
|
907
|
+
});
|
|
908
|
+
// Find the snapshotTree inside the returned snapshot based on the path as given in the request.
|
|
909
|
+
const hasIsolatedChannels = rootHasIsolatedChannels(this.metadata);
|
|
910
|
+
const snapshotTreeForPath = this.getSnapshotTreeForPath(snapshot.snapshotTree, pathParts, hasIsolatedChannels);
|
|
911
|
+
assert(snapshotTreeForPath !== undefined, 0x8ef /* no snapshotTree for the path */);
|
|
912
|
+
const snapshotSeqNumber = snapshot.sequenceNumber;
|
|
913
|
+
assert(snapshotSeqNumber !== undefined, 0x8f0 /* snapshotSeqNumber should be present */);
|
|
914
|
+
// This assert fires if we get a snapshot older than the snapshot we loaded from. This is a service issue.
|
|
915
|
+
// Snapshots should only move forward. If we observe an older snapshot than the one we loaded from, then likely
|
|
916
|
+
// the file has been overwritten or service lost data.
|
|
917
|
+
if (snapshotSeqNumber < this.deltaManager.initialSequenceNumber) {
|
|
918
|
+
throw DataProcessingError.create("Downloaded snapshot older than snapshot we loaded from", "getSnapshotForLoadingGroupId", undefined, {
|
|
919
|
+
loadingGroupIds: sortedLoadingGroupIds.join(","),
|
|
920
|
+
snapshotSeqNumber,
|
|
921
|
+
initialSequenceNumber: this.deltaManager.initialSequenceNumber,
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
// If the snapshot is ahead of the last seq number of the delta manager, then catch up before
|
|
925
|
+
// returning the snapshot.
|
|
926
|
+
if (snapshotSeqNumber > this.deltaManager.lastSequenceNumber) {
|
|
927
|
+
// If this is a summarizer client, which is trying to load a group and it finds that there is
|
|
928
|
+
// another snapshot from which the summarizer loaded and it is behind, then just give up as
|
|
929
|
+
// the summarizer state is not up to date.
|
|
930
|
+
// This should be a recoverable scenario and shouldn't happen as we should process the ack first.
|
|
931
|
+
if (this.isSummarizerClient) {
|
|
932
|
+
throw new Error("Summarizer client behind, loaded newer snapshot with loadingGroupId");
|
|
933
|
+
}
|
|
934
|
+
// We want to catchup from sequenceNumber to targetSequenceNumber
|
|
935
|
+
const props = {
|
|
936
|
+
eventName: "GroupIdSnapshotCatchup",
|
|
937
|
+
loadingGroupIds: sortedLoadingGroupIds.join(","),
|
|
938
|
+
targetSequenceNumber: snapshotSeqNumber,
|
|
939
|
+
sequenceNumber: this.deltaManager.lastSequenceNumber, // This is so we reuse some columns in telemetry
|
|
940
|
+
};
|
|
941
|
+
const event = PerformanceEvent.start(this.mc.logger, {
|
|
942
|
+
...props,
|
|
943
|
+
});
|
|
944
|
+
// If the inbound deltas queue is paused or disconnected, we expect a reconnect and unpause
|
|
945
|
+
// as long as it's not a summarizer client.
|
|
946
|
+
if (this.deltaManager.inbound.paused) {
|
|
947
|
+
props.inboundPaused = this.deltaManager.inbound.paused; // reusing telemetry
|
|
948
|
+
}
|
|
949
|
+
const defP = new Deferred();
|
|
950
|
+
this.deltaManager.on("op", (message) => {
|
|
951
|
+
if (message.sequenceNumber >= snapshotSeqNumber) {
|
|
952
|
+
defP.resolve(true);
|
|
953
|
+
}
|
|
954
|
+
});
|
|
955
|
+
await defP.promise;
|
|
956
|
+
event.end(props);
|
|
957
|
+
}
|
|
958
|
+
return { snapshotTree: snapshotTreeForPath, sequenceNumber: snapshotSeqNumber };
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Api to find a snapshot tree inside a bigger snapshot tree based on the path in the pathParts array.
|
|
962
|
+
* @param snapshotTree - snapshot tree to look into.
|
|
963
|
+
* @param pathParts - Part of the path, which we want to extract from the snapshot tree.
|
|
964
|
+
* @param hasIsolatedChannels - whether the channels are present inside ".channels" subtree. Older
|
|
965
|
+
* snapshots will not have trees inside ".channels", so check that.
|
|
966
|
+
* @returns - requested snapshot tree based on the path parts.
|
|
967
|
+
*/
|
|
968
|
+
getSnapshotTreeForPath(snapshotTree, pathParts, hasIsolatedChannels) {
|
|
969
|
+
let childTree = snapshotTree;
|
|
970
|
+
for (const part of pathParts) {
|
|
971
|
+
if (hasIsolatedChannels) {
|
|
972
|
+
childTree = childTree?.trees[channelsTreeName];
|
|
973
|
+
}
|
|
974
|
+
childTree = childTree?.trees[part];
|
|
975
|
+
}
|
|
976
|
+
return childTree;
|
|
977
|
+
}
|
|
803
978
|
/**
|
|
804
979
|
* Notifies this object about the request made to the container.
|
|
805
980
|
* @param request - Request made to the handler.
|
|
@@ -853,15 +1028,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
853
1028
|
: create404Response(request);
|
|
854
1029
|
}
|
|
855
1030
|
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);
|
|
1031
|
+
return await this.channelCollection.request(request);
|
|
865
1032
|
}
|
|
866
1033
|
return create404Response(request);
|
|
867
1034
|
}
|
|
@@ -876,38 +1043,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
876
1043
|
return this.entryPoint;
|
|
877
1044
|
}
|
|
878
1045
|
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();
|
|
1046
|
+
return this.channelCollection.internalId(maybeAlias);
|
|
911
1047
|
}
|
|
912
1048
|
/** Adds the container's metadata to the given summary tree. */
|
|
913
1049
|
addMetadataToSummary(summaryTree) {
|
|
@@ -922,22 +1058,21 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
922
1058
|
message: extractSummaryMetadataMessage(this.deltaManager.lastMessage) ??
|
|
923
1059
|
this.messageAtLastSummary,
|
|
924
1060
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
925
|
-
|
|
1061
|
+
idCompressorMode: this.idCompressorMode,
|
|
926
1062
|
};
|
|
927
1063
|
addBlobToSummary(summaryTree, metadataBlobName, JSON.stringify(metadata));
|
|
928
1064
|
}
|
|
929
1065
|
addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext) {
|
|
930
1066
|
this.addMetadataToSummary(summaryTree);
|
|
931
|
-
if (this.
|
|
932
|
-
|
|
933
|
-
const idCompressorState = JSON.stringify(this.idCompressor.serialize(false));
|
|
1067
|
+
if (this._idCompressor) {
|
|
1068
|
+
const idCompressorState = JSON.stringify(this._idCompressor.serialize(false));
|
|
934
1069
|
addBlobToSummary(summaryTree, idCompressorBlobName, idCompressorState);
|
|
935
1070
|
}
|
|
936
1071
|
if (this.remoteMessageProcessor.partialMessages.size > 0) {
|
|
937
1072
|
const content = JSON.stringify([...this.remoteMessageProcessor.partialMessages]);
|
|
938
1073
|
addBlobToSummary(summaryTree, chunksBlobName, content);
|
|
939
1074
|
}
|
|
940
|
-
const dataStoreAliases = this.
|
|
1075
|
+
const dataStoreAliases = this.channelCollection.aliases;
|
|
941
1076
|
if (dataStoreAliases.size > 0) {
|
|
942
1077
|
addBlobToSummary(summaryTree, aliasBlobName, JSON.stringify([...dataStoreAliases]));
|
|
943
1078
|
}
|
|
@@ -949,7 +1084,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
949
1084
|
// Some storage (like git) doesn't allow empty tree, so we can omit it.
|
|
950
1085
|
// and the blob manager can handle the tree not existing when loading
|
|
951
1086
|
if (Object.keys(blobManagerSummary.summary.tree).length > 0) {
|
|
952
|
-
|
|
1087
|
+
addSummarizeResultToSummary(summaryTree, blobsTreeName, blobManagerSummary);
|
|
953
1088
|
}
|
|
954
1089
|
const gcSummary = this.garbageCollector.summarize(fullTree, trackState, telemetryContext);
|
|
955
1090
|
if (gcSummary !== undefined) {
|
|
@@ -984,14 +1119,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
984
1119
|
}
|
|
985
1120
|
return this.consecutiveReconnects < this.maxConsecutiveReconnects;
|
|
986
1121
|
}
|
|
987
|
-
resetReconnectCount(
|
|
988
|
-
|
|
989
|
-
// in their own batches before the originating batch is sent.
|
|
990
|
-
// Therefore, receiving them while attempting to send the originating batch
|
|
991
|
-
// does not mean that the container is making any progress.
|
|
992
|
-
if (message?.type !== ContainerMessageType.ChunkedOp) {
|
|
993
|
-
this.consecutiveReconnects = 0;
|
|
994
|
-
}
|
|
1122
|
+
resetReconnectCount() {
|
|
1123
|
+
this.consecutiveReconnects = 0;
|
|
995
1124
|
}
|
|
996
1125
|
replayPendingStates() {
|
|
997
1126
|
// We need to be able to send ops to replay states
|
|
@@ -1036,13 +1165,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1036
1165
|
const opContents = this.parseLocalOpContent(serializedOpContent);
|
|
1037
1166
|
switch (opContents.type) {
|
|
1038
1167
|
case ContainerMessageType.FluidDataStoreOp:
|
|
1039
|
-
return this.dataStores.applyStashedOp(opContents.contents);
|
|
1040
1168
|
case ContainerMessageType.Attach:
|
|
1041
|
-
|
|
1169
|
+
case ContainerMessageType.Alias:
|
|
1170
|
+
return this.channelCollection.applyStashedOp(opContents);
|
|
1042
1171
|
case ContainerMessageType.IdAllocation:
|
|
1043
|
-
assert(this.
|
|
1172
|
+
assert(this.idCompressorMode !== "off", 0x8f1 /* ID compressor should be in use */);
|
|
1044
1173
|
return;
|
|
1045
|
-
case ContainerMessageType.Alias:
|
|
1046
1174
|
case ContainerMessageType.BlobAttach:
|
|
1047
1175
|
return;
|
|
1048
1176
|
case ContainerMessageType.ChunkedOp:
|
|
@@ -1073,6 +1201,20 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1073
1201
|
}
|
|
1074
1202
|
}
|
|
1075
1203
|
setConnectionState(connected, clientId) {
|
|
1204
|
+
if (connected && this.idCompressorMode === "delayed" && !this.compressorLoadInitiated) {
|
|
1205
|
+
this.compressorLoadInitiated = true;
|
|
1206
|
+
this.createIdCompressor()
|
|
1207
|
+
.then((compressor) => {
|
|
1208
|
+
this._idCompressor = compressor;
|
|
1209
|
+
for (const range of this.pendingIdCompressorOps) {
|
|
1210
|
+
this._idCompressor.finalizeCreationRange(range);
|
|
1211
|
+
}
|
|
1212
|
+
this.pendingIdCompressorOps = [];
|
|
1213
|
+
})
|
|
1214
|
+
.catch((error) => {
|
|
1215
|
+
this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1076
1218
|
if (connected === false && this.delayConnectClientId !== undefined) {
|
|
1077
1219
|
this.delayConnectClientId = undefined;
|
|
1078
1220
|
this.mc.logger.sendTelemetryEvent({
|
|
@@ -1136,7 +1278,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1136
1278
|
if (changeOfState) {
|
|
1137
1279
|
this.replayPendingStates();
|
|
1138
1280
|
}
|
|
1139
|
-
this.
|
|
1281
|
+
this.channelCollection.setConnectionState(connected, clientId);
|
|
1140
1282
|
this.garbageCollector.setConnectionState(connected, clientId);
|
|
1141
1283
|
raiseConnectedEvent(this.mc.logger, this, connected, clientId);
|
|
1142
1284
|
}
|
|
@@ -1183,10 +1325,13 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1183
1325
|
this.scheduleManager.beforeOpProcessing(message);
|
|
1184
1326
|
this._processedClientSequenceNumber = message.clientSequenceNumber;
|
|
1185
1327
|
try {
|
|
1328
|
+
// See commit that added this assert for more details.
|
|
1329
|
+
// These calls should be made for all but chunked ops:
|
|
1330
|
+
// 1) this.pendingStateManager.processPendingLocalMessage() below
|
|
1331
|
+
// 2) this.resetReconnectCount() below
|
|
1332
|
+
assert(message.type !== ContainerMessageType.ChunkedOp, "we should never get here with chunked ops");
|
|
1186
1333
|
let localOpMetadata;
|
|
1187
|
-
if (local &&
|
|
1188
|
-
messageWithContext.modernRuntimeMessage &&
|
|
1189
|
-
message.type !== ContainerMessageType.ChunkedOp) {
|
|
1334
|
+
if (local && messageWithContext.modernRuntimeMessage) {
|
|
1190
1335
|
localOpMetadata = this.pendingStateManager.processPendingLocalMessage(messageWithContext.message);
|
|
1191
1336
|
}
|
|
1192
1337
|
// If there are no more pending messages after processing a local message,
|
|
@@ -1201,7 +1346,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1201
1346
|
// If we have processed a local op, this means that the container is
|
|
1202
1347
|
// making progress and we can reset the counter for how many times
|
|
1203
1348
|
// we have consecutively replayed the pending states
|
|
1204
|
-
this.resetReconnectCount(
|
|
1349
|
+
this.resetReconnectCount();
|
|
1205
1350
|
}
|
|
1206
1351
|
}
|
|
1207
1352
|
catch (e) {
|
|
@@ -1219,29 +1364,37 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1219
1364
|
const { local } = messageWithContext;
|
|
1220
1365
|
switch (messageWithContext.message.type) {
|
|
1221
1366
|
case ContainerMessageType.Attach:
|
|
1222
|
-
this.dataStores.processAttachMessage(messageWithContext.message, local);
|
|
1223
|
-
break;
|
|
1224
1367
|
case ContainerMessageType.Alias:
|
|
1225
|
-
this.dataStores.processAliasMessage(messageWithContext.message, localOpMetadata, local);
|
|
1226
|
-
break;
|
|
1227
1368
|
case ContainerMessageType.FluidDataStoreOp:
|
|
1228
|
-
this.
|
|
1369
|
+
this.channelCollection.process(messageWithContext.message, local, localOpMetadata, (from, to) => this.garbageCollector.addedOutboundReference(from, to));
|
|
1229
1370
|
break;
|
|
1230
1371
|
case ContainerMessageType.BlobAttach:
|
|
1231
1372
|
this.blobManager.processBlobAttachOp(messageWithContext.message, local);
|
|
1232
1373
|
break;
|
|
1233
1374
|
case ContainerMessageType.IdAllocation:
|
|
1234
|
-
assert(this.idCompressor !== undefined, 0x67c /* IdCompressor should be defined if enabled */);
|
|
1235
1375
|
// Don't re-finalize the range if we're processing a "savedOp" in
|
|
1236
1376
|
// stashed ops flow. The compressor is stashed with these ops already processed.
|
|
1237
|
-
|
|
1238
|
-
|
|
1377
|
+
// That said, in idCompressorMode === "delayed", we might not serialize ID compressor, and
|
|
1378
|
+
// thus we need to process all the ops.
|
|
1379
|
+
if (!(this.skipSavedCompressorOps &&
|
|
1380
|
+
messageWithContext.message.metadata?.savedOp ===
|
|
1381
|
+
true)) {
|
|
1382
|
+
const range = messageWithContext.message.contents;
|
|
1383
|
+
if (this._idCompressor === undefined) {
|
|
1384
|
+
this.pendingIdCompressorOps.push(range);
|
|
1385
|
+
}
|
|
1386
|
+
else {
|
|
1387
|
+
this._idCompressor.finalizeCreationRange(range);
|
|
1388
|
+
}
|
|
1239
1389
|
}
|
|
1240
1390
|
break;
|
|
1241
1391
|
case ContainerMessageType.GC:
|
|
1242
1392
|
this.garbageCollector.processMessage(messageWithContext.message, local);
|
|
1243
1393
|
break;
|
|
1244
1394
|
case ContainerMessageType.ChunkedOp:
|
|
1395
|
+
// From observability POV, we should not exppse the rest of the system (including "op" events on object) to these messages.
|
|
1396
|
+
// Also resetReconnectCount() would be wrong - see comment that was there before this change was made.
|
|
1397
|
+
assert(false, "should not even get here");
|
|
1245
1398
|
case ContainerMessageType.Rejoin:
|
|
1246
1399
|
break;
|
|
1247
1400
|
default: {
|
|
@@ -1322,7 +1475,15 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1322
1475
|
this.emit("signal", transformed, local);
|
|
1323
1476
|
return;
|
|
1324
1477
|
}
|
|
1325
|
-
|
|
1478
|
+
// Due to a mismatch between different layers in terms of
|
|
1479
|
+
// what is the interface of passing signals, we need to adjust
|
|
1480
|
+
// the signal envelope before sending it to the datastores to be processed
|
|
1481
|
+
const envelope2 = {
|
|
1482
|
+
address: envelope.address,
|
|
1483
|
+
contents: transformed.content,
|
|
1484
|
+
};
|
|
1485
|
+
transformed.content = envelope2;
|
|
1486
|
+
this.channelCollection.processSignal(transformed, local);
|
|
1326
1487
|
}
|
|
1327
1488
|
/**
|
|
1328
1489
|
* Flush the pending ops manually.
|
|
@@ -1386,9 +1547,17 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1386
1547
|
* Returns undefined if no data store has been assigned the given alias.
|
|
1387
1548
|
*/
|
|
1388
1549
|
async getAliasedDataStoreEntryPoint(alias) {
|
|
1389
|
-
|
|
1550
|
+
// Back-comapatibility:
|
|
1551
|
+
// There are old files that were created without using data store aliasing feature, but
|
|
1552
|
+
// used createRoot*DataStore*() (already removed) API. Such data stores will have isRoot = true,
|
|
1553
|
+
// and internalID provided by user. The expectation is that such files behave as new files, where
|
|
1554
|
+
// same data store instances created using aliasing feature.
|
|
1555
|
+
// Please also see note on name collisions in DataStores.createDataStoreId()
|
|
1556
|
+
await this.channelCollection.waitIfPendingAlias(alias);
|
|
1390
1557
|
const internalId = this.internalId(alias);
|
|
1391
|
-
const context = await this.
|
|
1558
|
+
const context = await this.channelCollection.getDataStoreIfAvailable(internalId, {
|
|
1559
|
+
wait: false,
|
|
1560
|
+
});
|
|
1392
1561
|
// If the data store is not available or not an alias, return undefined.
|
|
1393
1562
|
if (context === undefined || !(await context.isRoot())) {
|
|
1394
1563
|
return undefined;
|
|
@@ -1400,28 +1569,20 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1400
1569
|
this.garbageCollector.nodeUpdated(`/${internalId}`, "Loaded", undefined /* timestampMs */, context.packagePath);
|
|
1401
1570
|
return channel.entryPoint;
|
|
1402
1571
|
}
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
throw new UsageError(`Id cannot contain slashes: '${rootDataStoreId}'`);
|
|
1406
|
-
}
|
|
1407
|
-
return this.dataStores.createDetachedDataStoreCore(pkg, true, rootDataStoreId);
|
|
1408
|
-
}
|
|
1409
|
-
createDetachedDataStore(pkg, groupId) {
|
|
1410
|
-
return this.dataStores.createDetachedDataStoreCore(pkg, false, undefined, groupId);
|
|
1572
|
+
createDetachedDataStore(pkg, loadingGroupId) {
|
|
1573
|
+
return this.channelCollection.createDetachedDataStore(pkg, loadingGroupId);
|
|
1411
1574
|
}
|
|
1412
|
-
async createDataStore(pkg,
|
|
1413
|
-
const
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
.realize(), id, this, this.dataStores, this.mc.logger);
|
|
1575
|
+
async createDataStore(pkg, loadingGroupId) {
|
|
1576
|
+
const context = this.channelCollection.createDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], undefined, // props
|
|
1577
|
+
loadingGroupId);
|
|
1578
|
+
return channelToDataStore(await context.realize(), context.id, this.channelCollection, this.mc.logger);
|
|
1417
1579
|
}
|
|
1418
1580
|
/**
|
|
1419
1581
|
* @deprecated 0.16 Issue #1537, #3631
|
|
1420
1582
|
*/
|
|
1421
|
-
async _createDataStoreWithProps(pkg, props
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
.realize(), id, this, this.dataStores, this.mc.logger);
|
|
1583
|
+
async _createDataStoreWithProps(pkg, props) {
|
|
1584
|
+
const context = this.channelCollection.createDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], props);
|
|
1585
|
+
return channelToDataStore(await context.realize(), context.id, this.channelCollection, this.mc.logger);
|
|
1425
1586
|
}
|
|
1426
1587
|
canSendOps() {
|
|
1427
1588
|
// Note that the real (non-proxy) delta manager is needed here to get the readonly info. This is because
|
|
@@ -1465,6 +1626,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1465
1626
|
}
|
|
1466
1627
|
break;
|
|
1467
1628
|
}
|
|
1629
|
+
case ContainerMessageType.IdAllocation:
|
|
1468
1630
|
case ContainerMessageType.GC: {
|
|
1469
1631
|
return false;
|
|
1470
1632
|
}
|
|
@@ -1499,16 +1661,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1499
1661
|
const envelope = this.createNewSignalEnvelope(undefined /* address */, type, content);
|
|
1500
1662
|
return this.submitSignalFn(envelope, targetClientId);
|
|
1501
1663
|
}
|
|
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
1664
|
setAttachState(attachState) {
|
|
1513
1665
|
if (attachState === AttachState.Attaching) {
|
|
1514
1666
|
assert(this.attachState === AttachState.Attaching, 0x12d /* "Container Context should already be in attaching state" */);
|
|
@@ -1520,7 +1672,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1520
1672
|
if (attachState === AttachState.Attached && !this.hasPendingMessages()) {
|
|
1521
1673
|
this.updateDocumentDirtyState(false);
|
|
1522
1674
|
}
|
|
1523
|
-
this.
|
|
1675
|
+
this.channelCollection.setAttachState(attachState);
|
|
1524
1676
|
}
|
|
1525
1677
|
/**
|
|
1526
1678
|
* Create a summary. Used when attaching or serializing a detached container.
|
|
@@ -1535,18 +1687,18 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1535
1687
|
this.blobManager.setRedirectTable(blobRedirectTable);
|
|
1536
1688
|
}
|
|
1537
1689
|
// We can finalize any allocated IDs since we're the only client
|
|
1538
|
-
const idRange = this.
|
|
1690
|
+
const idRange = this._idCompressor?.takeNextCreationRange();
|
|
1539
1691
|
if (idRange !== undefined) {
|
|
1540
|
-
this.
|
|
1692
|
+
this._idCompressor?.finalizeCreationRange(idRange);
|
|
1541
1693
|
}
|
|
1542
|
-
const summarizeResult = this.
|
|
1694
|
+
const summarizeResult = this.channelCollection.getAttachSummary(telemetryContext);
|
|
1543
1695
|
// Wrap data store summaries in .channels subtree.
|
|
1544
1696
|
wrapSummaryInChannelsTree(summarizeResult);
|
|
1545
1697
|
this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
|
|
1546
1698
|
return summarizeResult.summary;
|
|
1547
1699
|
}
|
|
1548
1700
|
async summarizeInternal(fullTree, trackState, telemetryContext) {
|
|
1549
|
-
const summarizeResult = await this.
|
|
1701
|
+
const summarizeResult = await this.channelCollection.summarize(fullTree, trackState, telemetryContext);
|
|
1550
1702
|
// Wrap data store summaries in .channels subtree.
|
|
1551
1703
|
wrapSummaryInChannelsTree(summarizeResult);
|
|
1552
1704
|
const pathPartsForChildren = [channelsTreeName];
|
|
@@ -1594,10 +1746,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1594
1746
|
* @see IGarbageCollectionRuntime.updateStateBeforeGC
|
|
1595
1747
|
*/
|
|
1596
1748
|
async updateStateBeforeGC() {
|
|
1597
|
-
return this.
|
|
1749
|
+
return this.channelCollection.updateStateBeforeGC();
|
|
1598
1750
|
}
|
|
1599
1751
|
async getGCDataInternal(fullGC) {
|
|
1600
|
-
return this.
|
|
1752
|
+
return this.channelCollection.getGCData(fullGC);
|
|
1601
1753
|
}
|
|
1602
1754
|
/**
|
|
1603
1755
|
* Generates and returns the GC data for this container.
|
|
@@ -1623,22 +1775,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1623
1775
|
// always referenced, so the used routes is only self-route (empty string).
|
|
1624
1776
|
this.summarizerNode.updateUsedRoutes([""]);
|
|
1625
1777
|
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");
|
|
1778
|
+
this.channelCollection.updateUsedRoutes(dataStoreRoutes);
|
|
1642
1779
|
}
|
|
1643
1780
|
/**
|
|
1644
1781
|
* After GC has run and identified nodes that are sweep ready, this is called to delete the sweep ready nodes.
|
|
@@ -1647,7 +1784,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1647
1784
|
*/
|
|
1648
1785
|
deleteSweepReadyNodes(sweepReadyRoutes) {
|
|
1649
1786
|
const { dataStoreRoutes, blobManagerRoutes } = this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
|
|
1650
|
-
const deletedRoutes = this.
|
|
1787
|
+
const deletedRoutes = this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes);
|
|
1651
1788
|
return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
|
|
1652
1789
|
}
|
|
1653
1790
|
/**
|
|
@@ -1661,7 +1798,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1661
1798
|
updateTombstonedRoutes(tombstonedRoutes) {
|
|
1662
1799
|
const { blobManagerRoutes, dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(tombstonedRoutes);
|
|
1663
1800
|
this.blobManager.updateTombstonedRoutes(blobManagerRoutes);
|
|
1664
|
-
this.
|
|
1801
|
+
this.channelCollection.updateTombstonedRoutes(dataStoreRoutes);
|
|
1665
1802
|
}
|
|
1666
1803
|
/**
|
|
1667
1804
|
* Returns a server generated referenced timestamp to be used to track unreferenced nodes by GC.
|
|
@@ -1679,7 +1816,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1679
1816
|
if (this.isBlobPath(nodePath)) {
|
|
1680
1817
|
return GCNodeType.Blob;
|
|
1681
1818
|
}
|
|
1682
|
-
return this.
|
|
1819
|
+
return this.channelCollection.getGCNodeType(nodePath) ?? GCNodeType.Other;
|
|
1683
1820
|
}
|
|
1684
1821
|
/**
|
|
1685
1822
|
* Called by GC to retrieve the package path of the node with the given path. The node should belong to a
|
|
@@ -1689,14 +1826,14 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1689
1826
|
// GC uses "/" when adding "root" references, e.g. for Aliasing or as part of Tombstone Auto-Recovery.
|
|
1690
1827
|
// These have no package path so return a special value.
|
|
1691
1828
|
if (nodePath === "/") {
|
|
1692
|
-
return ["
|
|
1829
|
+
return ["_gcRoot"];
|
|
1693
1830
|
}
|
|
1694
1831
|
switch (this.getNodeType(nodePath)) {
|
|
1695
1832
|
case GCNodeType.Blob:
|
|
1696
1833
|
return [BlobManager.basePath];
|
|
1697
1834
|
case GCNodeType.DataStore:
|
|
1698
1835
|
case GCNodeType.SubDataStore:
|
|
1699
|
-
return this.
|
|
1836
|
+
return this.channelCollection.getDataStorePackagePath(nodePath);
|
|
1700
1837
|
default:
|
|
1701
1838
|
assert(false, 0x2de /* "Package path requested for unsupported node type." */);
|
|
1702
1839
|
}
|
|
@@ -1755,7 +1892,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1755
1892
|
* @param options - options controlling how the summary is generated or submitted
|
|
1756
1893
|
*/
|
|
1757
1894
|
async submitSummary(options) {
|
|
1758
|
-
const { fullTree = false, finalAttempt = false, refreshLatestAck, summaryLogger } = options;
|
|
1895
|
+
const { fullTree = false, finalAttempt = false, refreshLatestAck, summaryLogger, latestSummaryRefSeqNum, } = options;
|
|
1759
1896
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
1760
1897
|
// use it for all events logged during this summary.
|
|
1761
1898
|
const summaryNumber = this.nextSummaryNumber;
|
|
@@ -1808,6 +1945,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1808
1945
|
}
|
|
1809
1946
|
}
|
|
1810
1947
|
const shouldPauseInboundSignal = this.mc.config.getBoolean("Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause") !== true;
|
|
1948
|
+
const shouldValidatePreSummaryState = this.mc.config.getBoolean("Fluid.ContainerRuntime.SubmitSummary.shouldValidatePreSummaryState") === true;
|
|
1811
1949
|
let summaryRefSeqNum;
|
|
1812
1950
|
try {
|
|
1813
1951
|
await this.deltaManager.inbound.pause();
|
|
@@ -1818,7 +1956,25 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1818
1956
|
const minimumSequenceNumber = this.deltaManager.minimumSequenceNumber;
|
|
1819
1957
|
const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
|
|
1820
1958
|
const lastAck = this.summaryCollection.latestAck;
|
|
1821
|
-
this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger);
|
|
1959
|
+
const startSummaryResult = this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger, latestSummaryRefSeqNum);
|
|
1960
|
+
if (startSummaryResult.invalidNodes > 0 ||
|
|
1961
|
+
startSummaryResult.mismatchNumbers.size > 0) {
|
|
1962
|
+
summaryLogger.sendErrorEvent({
|
|
1963
|
+
eventName: "LatestSummaryRefSeqNumMismatch",
|
|
1964
|
+
details: {
|
|
1965
|
+
...startSummaryResult,
|
|
1966
|
+
mismatchNumbers: Array.from(startSummaryResult.mismatchNumbers),
|
|
1967
|
+
},
|
|
1968
|
+
});
|
|
1969
|
+
if (shouldValidatePreSummaryState && !finalAttempt) {
|
|
1970
|
+
return {
|
|
1971
|
+
stage: "base",
|
|
1972
|
+
referenceSequenceNumber: summaryRefSeqNum,
|
|
1973
|
+
minimumSequenceNumber,
|
|
1974
|
+
error: `Summarizer node state inconsistent with summarizer state.`,
|
|
1975
|
+
};
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1822
1978
|
// Helper function to check whether we should still continue between each async step.
|
|
1823
1979
|
const checkContinue = () => {
|
|
1824
1980
|
// Do not check for loss of connectivity directly! Instead leave it up to
|
|
@@ -1914,8 +2070,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1914
2070
|
? calculateStats(summaryTree.tree[gcTreeKey])
|
|
1915
2071
|
: undefined;
|
|
1916
2072
|
const summaryStats = {
|
|
1917
|
-
dataStoreCount: this.
|
|
1918
|
-
summarizedDataStoreCount: this.
|
|
2073
|
+
dataStoreCount: this.channelCollection.size,
|
|
2074
|
+
summarizedDataStoreCount: this.channelCollection.size - handleCount,
|
|
1919
2075
|
gcStateUpdatedDataStoreCount: this.garbageCollector.updatedDSCountSinceLastSummary,
|
|
1920
2076
|
gcBlobNodeCount: gcSummaryTreeStats?.blobNodeCount,
|
|
1921
2077
|
gcTotalBlobsSize: gcSummaryTreeStats?.totalBlobSize,
|
|
@@ -2069,48 +2225,29 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2069
2225
|
this.emit(dirty ? "dirty" : "saved");
|
|
2070
2226
|
}
|
|
2071
2227
|
}
|
|
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);
|
|
2228
|
+
submitMessage(type, contents, localOpMetadata = undefined) {
|
|
2229
|
+
this.submit({ type, contents }, localOpMetadata);
|
|
2085
2230
|
}
|
|
2086
2231
|
async uploadBlob(blob, signal) {
|
|
2087
2232
|
this.verifyNotClosed();
|
|
2088
2233
|
return this.blobManager.createBlob(blob, signal);
|
|
2089
2234
|
}
|
|
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) {
|
|
2235
|
+
submitIdAllocationOpIfNeeded() {
|
|
2236
|
+
if (this._idCompressor) {
|
|
2237
|
+
const idRange = this._idCompressor.takeNextCreationRange();
|
|
2238
|
+
// Don't include the idRange if there weren't any Ids allocated
|
|
2239
|
+
if (idRange?.ids !== undefined) {
|
|
2101
2240
|
const idAllocationMessage = {
|
|
2102
2241
|
type: ContainerMessageType.IdAllocation,
|
|
2103
2242
|
contents: idRange,
|
|
2104
2243
|
};
|
|
2105
|
-
idAllocationBatchMessage = {
|
|
2244
|
+
const idAllocationBatchMessage = {
|
|
2106
2245
|
contents: JSON.stringify(idAllocationMessage),
|
|
2107
2246
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2108
2247
|
metadata: undefined,
|
|
2109
2248
|
localOpMetadata: undefined,
|
|
2110
2249
|
type: ContainerMessageType.IdAllocation,
|
|
2111
2250
|
};
|
|
2112
|
-
}
|
|
2113
|
-
if (idAllocationBatchMessage !== undefined) {
|
|
2114
2251
|
this.outbox.submitIdAllocation(idAllocationBatchMessage);
|
|
2115
2252
|
}
|
|
2116
2253
|
}
|
|
@@ -2138,42 +2275,47 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2138
2275
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2139
2276
|
};
|
|
2140
2277
|
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);
|
|
2278
|
+
// If `message` is an allocation op, then we are in the resubmit path and we must redirect the allocation
|
|
2279
|
+
// op into the correct batch to avoid ranges being finalized out of order.
|
|
2280
|
+
// Otherwise, submit an IdAllocation op if any IDs have been generated since the last op was submitted, as
|
|
2281
|
+
// any of the other op types may contain those IDs and thus depend on the allocation op being sent first.
|
|
2282
|
+
if (type === ContainerMessageType.IdAllocation) {
|
|
2283
|
+
this.outbox.submitIdAllocation(message);
|
|
2174
2284
|
}
|
|
2175
2285
|
else {
|
|
2176
|
-
this.
|
|
2286
|
+
this.submitIdAllocationOpIfNeeded();
|
|
2287
|
+
// If this is attach message for new data store, and we are in a batch, send this op out of order
|
|
2288
|
+
// Is it safe:
|
|
2289
|
+
// Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
|
|
2290
|
+
// They become visible only when aliased, or handle to some sub-element of newly created datastore
|
|
2291
|
+
// is stored in some DDS, i.e. only after some other op.
|
|
2292
|
+
// Why:
|
|
2293
|
+
// Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
|
|
2294
|
+
// stores are created, causing issues like relay service throttling (too many ops) and catastrophic
|
|
2295
|
+
// failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
|
|
2296
|
+
// these issues.
|
|
2297
|
+
// Cons:
|
|
2298
|
+
// 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
|
|
2299
|
+
// This change creates new possibility of a lot of newly created data stores never being referenced
|
|
2300
|
+
// because client died before it had a change to submit the rest of the ops. This will create more
|
|
2301
|
+
// garbage that needs to be collected leveraging GC (Garbage Collection) feature.
|
|
2302
|
+
// 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
|
|
2303
|
+
// today as rollback can't undo creation of data store. To some extent not sending them is a bigger
|
|
2304
|
+
// issue than sending.
|
|
2305
|
+
// Please note that this does not change file format, so it can be disabled in the future if this
|
|
2306
|
+
// optimization no longer makes sense (for example, batch compression may make it less appealing).
|
|
2307
|
+
if (this.currentlyBatching() &&
|
|
2308
|
+
type === ContainerMessageType.Attach &&
|
|
2309
|
+
this.disableAttachReorder !== true) {
|
|
2310
|
+
this.outbox.submitAttach(message);
|
|
2311
|
+
}
|
|
2312
|
+
else if (type === ContainerMessageType.BlobAttach) {
|
|
2313
|
+
// BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
|
|
2314
|
+
this.outbox.submitBlobAttach(message);
|
|
2315
|
+
}
|
|
2316
|
+
else {
|
|
2317
|
+
this.outbox.submit(message);
|
|
2318
|
+
}
|
|
2177
2319
|
}
|
|
2178
2320
|
if (!this.currentlyBatching()) {
|
|
2179
2321
|
this.flush();
|
|
@@ -2289,15 +2431,15 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2289
2431
|
* @param localOpMetadata - The local metadata associated with the original message.
|
|
2290
2432
|
*/
|
|
2291
2433
|
reSubmitCore(message, localOpMetadata, opMetadata) {
|
|
2292
|
-
assert(!this.isSummarizerClient,
|
|
2434
|
+
assert(!this.isSummarizerClient, 0x8f2 /* Summarizer never reconnects so should never resubmit */);
|
|
2293
2435
|
switch (message.type) {
|
|
2294
2436
|
case ContainerMessageType.FluidDataStoreOp:
|
|
2437
|
+
case ContainerMessageType.Attach:
|
|
2438
|
+
case ContainerMessageType.Alias:
|
|
2295
2439
|
// For Operations, call resubmitDataStoreOp which will find the right store
|
|
2296
2440
|
// and trigger resubmission on it.
|
|
2297
|
-
this.
|
|
2441
|
+
this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
|
|
2298
2442
|
break;
|
|
2299
|
-
case ContainerMessageType.Attach:
|
|
2300
|
-
case ContainerMessageType.Alias:
|
|
2301
2443
|
case ContainerMessageType.IdAllocation: {
|
|
2302
2444
|
this.submit(message, localOpMetadata);
|
|
2303
2445
|
break;
|
|
@@ -2344,7 +2486,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2344
2486
|
case ContainerMessageType.FluidDataStoreOp:
|
|
2345
2487
|
// For operations, call rollbackDataStoreOp which will find the right store
|
|
2346
2488
|
// and trigger rollback on it.
|
|
2347
|
-
this.
|
|
2489
|
+
this.channelCollection.rollback(type, contents, localOpMetadata);
|
|
2348
2490
|
break;
|
|
2349
2491
|
default:
|
|
2350
2492
|
// Don't check message.compatDetails because this is for rolling back a local op so the type will be known
|
|
@@ -2429,44 +2571,43 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2429
2571
|
};
|
|
2430
2572
|
});
|
|
2431
2573
|
}
|
|
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;
|
|
2574
|
+
getPendingLocalState(props) {
|
|
2575
|
+
this.verifyNotClosed();
|
|
2576
|
+
if (this._orderSequentiallyCalls !== 0) {
|
|
2577
|
+
throw new UsageError("can't get state during orderSequentially");
|
|
2578
|
+
}
|
|
2579
|
+
this.imminentClosure || (this.imminentClosure = props?.notifyImminentClosure ?? false);
|
|
2580
|
+
const getSyncState = (pendingAttachmentBlobs) => {
|
|
2454
2581
|
const pending = this.pendingStateManager.getLocalState();
|
|
2455
|
-
if (
|
|
2582
|
+
if (pendingAttachmentBlobs === undefined && !this.hasPendingMessages()) {
|
|
2456
2583
|
return; // no pending state to save
|
|
2457
2584
|
}
|
|
2458
|
-
const pendingIdCompressorState = this.
|
|
2459
|
-
|
|
2585
|
+
const pendingIdCompressorState = this._idCompressor?.serialize(true);
|
|
2586
|
+
return {
|
|
2460
2587
|
pending,
|
|
2461
|
-
pendingAttachmentBlobs,
|
|
2462
2588
|
pendingIdCompressorState,
|
|
2589
|
+
pendingAttachmentBlobs,
|
|
2590
|
+
sessionExpiryTimerStarted: this.garbageCollector.sessionExpiryTimerStarted,
|
|
2463
2591
|
};
|
|
2592
|
+
};
|
|
2593
|
+
const perfEvent = {
|
|
2594
|
+
eventName: "getPendingLocalState",
|
|
2595
|
+
notifyImminentClosure: props?.notifyImminentClosure,
|
|
2596
|
+
};
|
|
2597
|
+
const logAndReturnPendingState = (event, pendingState) => {
|
|
2464
2598
|
event.end({
|
|
2465
|
-
attachmentBlobsSize: Object.keys(pendingAttachmentBlobs ?? {}).length,
|
|
2466
|
-
pendingOpsSize: pending?.pendingStates.length,
|
|
2599
|
+
attachmentBlobsSize: Object.keys(pendingState?.pendingAttachmentBlobs ?? {}).length,
|
|
2600
|
+
pendingOpsSize: pendingState?.pending?.pendingStates.length,
|
|
2467
2601
|
});
|
|
2468
2602
|
return pendingState;
|
|
2469
|
-
}
|
|
2603
|
+
};
|
|
2604
|
+
// Flush pending batch.
|
|
2605
|
+
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
2606
|
+
// to close current batch.
|
|
2607
|
+
this.flush();
|
|
2608
|
+
return props?.notifyImminentClosure === true
|
|
2609
|
+
? PerformanceEvent.timedExecAsync(this.mc.logger, perfEvent, async (event) => logAndReturnPendingState(event, getSyncState(await this.blobManager.attachAndGetPendingBlobs(props?.stopBlobAttachingSignal))))
|
|
2610
|
+
: PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) => logAndReturnPendingState(event, getSyncState()));
|
|
2470
2611
|
}
|
|
2471
2612
|
summarizeOnDemand(options) {
|
|
2472
2613
|
if (this.isSummarizerClient) {
|
|
@@ -2520,4 +2661,4 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
2520
2661
|
return killSwitch !== true && this.runtimeOptions.enableGroupedBatching;
|
|
2521
2662
|
}
|
|
2522
2663
|
}
|
|
2523
|
-
//# sourceMappingURL=containerRuntime.
|
|
2664
|
+
//# sourceMappingURL=containerRuntime.js.map
|