@fluidframework/container-runtime 2.0.0-dev-rc.1.0.0.232845 → 2.0.0-dev-rc.2.0.0.245554
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +5 -5
- package/{.mocharc.js → .mocharc.cjs} +1 -1
- package/CHANGELOG.md +54 -0
- package/README.md +45 -0
- package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
- package/api-extractor-lint.json +1 -1
- package/api-extractor.json +1 -1
- package/api-report/container-runtime.api.md +425 -33
- package/dist/batchTracker.d.ts +1 -2
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +0 -5
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +0 -12
- package/dist/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +225 -0
- package/dist/channelCollection.d.ts.map +1 -0
- package/dist/{dataStores.js → channelCollection.js} +447 -147
- package/dist/channelCollection.js.map +1 -0
- package/dist/connectionTelemetry.d.ts +11 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +42 -4
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/container-runtime-alpha.d.ts +129 -48
- package/dist/container-runtime-beta.d.ts +68 -9
- package/dist/container-runtime-public.d.ts +68 -9
- package/dist/container-runtime-untrimmed.d.ts +692 -49
- package/dist/containerHandleContext.d.ts +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +81 -64
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +503 -368
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +2 -3
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +12 -11
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +118 -41
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +248 -159
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts +2 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +1 -0
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts +29 -4
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js +91 -5
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +12 -6
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +116 -78
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +2 -2
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +30 -23
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +22 -13
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +7 -4
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +2 -2
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +12 -5
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +18 -6
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +6 -7
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +20 -18
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.d.ts +1 -1
- package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +10 -10
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +8 -8
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +40 -39
- package/dist/gc/index.js.map +1 -1
- package/dist/index.d.ts +11 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -42
- package/dist/index.js.map +1 -1
- package/dist/messageTypes.d.ts +3 -3
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +2 -2
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +2 -2
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +8 -8
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +18 -18
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +4 -4
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +3 -3
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +1 -10
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +5 -5
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +7 -7
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +20 -12
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +4 -4
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +2 -2
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/package.json +3 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +2 -1
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +18 -10
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts +1 -2
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +5 -5
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/index.d.ts +12 -12
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js +43 -43
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.js +8 -8
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +5 -4
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +47 -32
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +4 -4
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +6 -6
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +2 -2
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.d.ts +3 -3
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/index.d.ts +3 -3
- package/dist/summary/summarizerNode/index.d.ts.map +1 -1
- package/dist/summary/summarizerNode/index.js +4 -4
- package/dist/summary/summarizerNode/index.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +16 -5
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +40 -10
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +9 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -4
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +12 -12
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +9 -20
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +15 -2
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +6 -5
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +10 -1
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +5 -6
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +4 -5
- package/dist/summary/summaryManager.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/{batchTracker.d.mts → batchTracker.d.ts} +2 -3
- package/lib/batchTracker.d.ts.map +1 -0
- package/lib/{batchTracker.mjs → batchTracker.js} +1 -1
- package/lib/batchTracker.js.map +1 -0
- package/lib/{blobManager.d.mts → blobManager.d.ts} +1 -6
- package/lib/blobManager.d.ts.map +1 -0
- package/lib/{blobManager.mjs → blobManager.js} +1 -13
- package/lib/blobManager.js.map +1 -0
- package/lib/channelCollection.d.ts +225 -0
- package/lib/channelCollection.d.ts.map +1 -0
- package/lib/{dataStores.mjs → channelCollection.js} +434 -137
- package/lib/channelCollection.js.map +1 -0
- package/lib/{connectionTelemetry.d.mts → connectionTelemetry.d.ts} +12 -2
- package/lib/connectionTelemetry.d.ts.map +1 -0
- package/lib/{connectionTelemetry.mjs → connectionTelemetry.js} +43 -5
- package/lib/connectionTelemetry.js.map +1 -0
- package/lib/{container-runtime-alpha.d.mts → container-runtime-alpha.d.ts} +129 -48
- package/lib/{container-runtime-beta.d.mts → container-runtime-beta.d.ts} +68 -9
- package/lib/{container-runtime-public.d.mts → container-runtime-public.d.ts} +68 -9
- package/lib/{container-runtime-untrimmed.d.mts → container-runtime-untrimmed.d.ts} +692 -49
- package/lib/{containerHandleContext.d.mts → containerHandleContext.d.ts} +2 -2
- package/lib/containerHandleContext.d.ts.map +1 -0
- package/lib/{containerHandleContext.mjs → containerHandleContext.js} +1 -1
- package/lib/containerHandleContext.js.map +1 -0
- package/lib/{containerRuntime.d.mts → containerRuntime.d.ts} +86 -65
- package/lib/containerRuntime.d.ts.map +1 -0
- package/lib/{containerRuntime.mjs → containerRuntime.js} +423 -290
- package/lib/containerRuntime.js.map +1 -0
- package/lib/{dataStore.d.mts → dataStore.d.ts} +3 -4
- package/lib/dataStore.d.ts.map +1 -0
- package/lib/{dataStore.mjs → dataStore.js} +13 -12
- package/lib/dataStore.js.map +1 -0
- package/lib/{dataStoreContext.d.mts → dataStoreContext.d.ts} +119 -42
- package/lib/dataStoreContext.d.ts.map +1 -0
- package/lib/{dataStoreContext.mjs → dataStoreContext.js} +240 -151
- package/lib/dataStoreContext.js.map +1 -0
- package/lib/{dataStoreContexts.d.mts → dataStoreContexts.d.ts} +3 -2
- package/lib/dataStoreContexts.d.ts.map +1 -0
- package/lib/{dataStoreContexts.mjs → dataStoreContexts.js} +2 -1
- package/lib/dataStoreContexts.js.map +1 -0
- package/lib/{dataStoreRegistry.d.mts → dataStoreRegistry.d.ts} +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -0
- package/lib/{dataStoreRegistry.mjs → dataStoreRegistry.js} +5 -1
- package/lib/dataStoreRegistry.js.map +1 -0
- package/{dist/deltaManagerProxyBase.d.ts → lib/deltaManagerSummarizerProxy.d.ts} +16 -7
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -0
- package/lib/deltaManagerSummarizerProxy.js +124 -0
- package/lib/deltaManagerSummarizerProxy.js.map +1 -0
- package/lib/{deltaScheduler.d.mts → deltaScheduler.d.ts} +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -0
- package/lib/{deltaScheduler.mjs → deltaScheduler.js} +1 -1
- package/lib/deltaScheduler.js.map +1 -0
- package/lib/{error.d.mts → error.d.ts} +1 -1
- package/lib/error.d.ts.map +1 -0
- package/lib/{error.mjs → error.js} +1 -1
- package/lib/error.js.map +1 -0
- package/lib/gc/{garbageCollection.d.mts → garbageCollection.d.ts} +13 -7
- package/lib/gc/garbageCollection.d.ts.map +1 -0
- package/lib/gc/{garbageCollection.mjs → garbageCollection.js} +79 -41
- package/lib/gc/garbageCollection.js.map +1 -0
- package/lib/gc/{gcConfigs.d.mts → gcConfigs.d.ts} +3 -3
- package/lib/gc/gcConfigs.d.ts.map +1 -0
- package/lib/gc/{gcConfigs.mjs → gcConfigs.js} +14 -7
- package/lib/gc/gcConfigs.js.map +1 -0
- package/lib/gc/{gcDefinitions.d.mts → gcDefinitions.d.ts} +23 -14
- package/lib/gc/gcDefinitions.d.ts.map +1 -0
- package/lib/gc/{gcDefinitions.mjs → gcDefinitions.js} +7 -4
- package/lib/gc/gcDefinitions.js.map +1 -0
- package/lib/gc/{gcHelpers.d.mts → gcHelpers.d.ts} +3 -3
- package/lib/gc/{gcHelpers.d.mts.map → gcHelpers.d.ts.map} +1 -1
- package/lib/gc/{gcHelpers.mjs → gcHelpers.js} +1 -1
- package/lib/gc/gcHelpers.js.map +1 -0
- package/lib/gc/{gcReferenceGraphAlgorithm.d.mts → gcReferenceGraphAlgorithm.d.ts} +2 -2
- package/lib/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -0
- package/lib/gc/{gcReferenceGraphAlgorithm.mjs → gcReferenceGraphAlgorithm.js} +1 -1
- package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -0
- package/lib/gc/{gcSummaryDefinitions.d.mts → gcSummaryDefinitions.d.ts} +1 -1
- package/lib/gc/gcSummaryDefinitions.d.ts.map +1 -0
- package/lib/gc/{gcSummaryDefinitions.mjs → gcSummaryDefinitions.js} +1 -1
- package/lib/gc/gcSummaryDefinitions.js.map +1 -0
- package/lib/gc/{gcSummaryStateTracker.d.mts → gcSummaryStateTracker.d.ts} +13 -6
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -0
- package/lib/gc/{gcSummaryStateTracker.mjs → gcSummaryStateTracker.js} +17 -5
- package/lib/gc/gcSummaryStateTracker.js.map +1 -0
- package/lib/gc/{gcTelemetry.d.mts → gcTelemetry.d.ts} +7 -8
- package/lib/gc/gcTelemetry.d.ts.map +1 -0
- package/lib/gc/{gcTelemetry.mjs → gcTelemetry.js} +5 -3
- package/lib/gc/gcTelemetry.js.map +1 -0
- package/lib/gc/{gcUnreferencedStateTracker.d.mts → gcUnreferencedStateTracker.d.ts} +2 -2
- package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
- package/lib/gc/{gcUnreferencedStateTracker.mjs → gcUnreferencedStateTracker.js} +2 -2
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -0
- package/lib/gc/index.d.ts +13 -0
- package/lib/gc/index.d.ts.map +1 -0
- package/lib/gc/{index.mjs → index.js} +8 -8
- package/lib/gc/index.js.map +1 -0
- package/lib/{index.d.mts → index.d.ts} +12 -22
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +15 -0
- package/lib/index.js.map +1 -0
- package/lib/{messageTypes.d.mts → messageTypes.d.ts} +4 -4
- package/lib/messageTypes.d.ts.map +1 -0
- package/lib/{messageTypes.mjs → messageTypes.js} +1 -1
- package/lib/messageTypes.js.map +1 -0
- package/lib/{metadata.d.mts → metadata.d.ts} +1 -1
- package/lib/metadata.d.ts.map +1 -0
- package/lib/{metadata.mjs → metadata.js} +1 -1
- package/lib/metadata.js.map +1 -0
- package/lib/opLifecycle/{batchManager.d.mts → batchManager.d.ts} +3 -3
- package/lib/opLifecycle/batchManager.d.ts.map +1 -0
- package/lib/opLifecycle/{batchManager.mjs → batchManager.js} +1 -1
- package/lib/opLifecycle/batchManager.js.map +1 -0
- package/lib/opLifecycle/{definitions.d.mts → definitions.d.ts} +3 -3
- package/lib/opLifecycle/definitions.d.ts.map +1 -0
- package/lib/opLifecycle/{definitions.mjs → definitions.js} +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -0
- package/lib/opLifecycle/index.d.ts +13 -0
- package/lib/opLifecycle/index.d.ts.map +1 -0
- package/lib/opLifecycle/index.js +12 -0
- package/lib/opLifecycle/index.js.map +1 -0
- package/lib/opLifecycle/{opCompressor.d.mts → opCompressor.d.ts} +2 -2
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -0
- package/lib/opLifecycle/{opCompressor.mjs → opCompressor.js} +3 -3
- package/lib/opLifecycle/opCompressor.js.map +1 -0
- package/lib/opLifecycle/{opDecompressor.d.mts → opDecompressor.d.ts} +2 -2
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -0
- package/lib/opLifecycle/{opDecompressor.mjs → opDecompressor.js} +2 -2
- package/lib/opLifecycle/opDecompressor.js.map +1 -0
- package/lib/opLifecycle/{opGroupingManager.d.mts → opGroupingManager.d.ts} +2 -2
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -0
- package/lib/opLifecycle/{opGroupingManager.mjs → opGroupingManager.js} +2 -11
- package/lib/opLifecycle/opGroupingManager.js.map +1 -0
- package/lib/opLifecycle/{opSplitter.d.mts → opSplitter.d.ts} +2 -2
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -0
- package/lib/opLifecycle/{opSplitter.mjs → opSplitter.js} +3 -3
- package/lib/opLifecycle/opSplitter.js.map +1 -0
- package/lib/opLifecycle/{outbox.d.mts → outbox.d.ts} +8 -8
- package/lib/opLifecycle/outbox.d.ts.map +1 -0
- package/lib/opLifecycle/{outbox.mjs → outbox.js} +12 -4
- package/lib/opLifecycle/outbox.js.map +1 -0
- package/lib/opLifecycle/{remoteMessageProcessor.d.mts → remoteMessageProcessor.d.ts} +5 -5
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -0
- package/lib/opLifecycle/{remoteMessageProcessor.mjs → remoteMessageProcessor.js} +2 -2
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -0
- package/lib/{opProperties.d.mts → opProperties.d.ts} +1 -1
- package/lib/opProperties.d.ts.map +1 -0
- package/lib/{opProperties.mjs → opProperties.js} +1 -1
- package/lib/opProperties.js.map +1 -0
- package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
- package/lib/packageVersion.d.ts.map +1 -0
- package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
- package/lib/packageVersion.js.map +1 -0
- package/lib/{pendingStateManager.d.mts → pendingStateManager.d.ts} +3 -2
- package/lib/pendingStateManager.d.ts.map +1 -0
- package/lib/{pendingStateManager.mjs → pendingStateManager.js} +18 -10
- package/lib/pendingStateManager.js.map +1 -0
- package/lib/{scheduleManager.d.mts → scheduleManager.d.ts} +6 -3
- package/lib/scheduleManager.d.ts.map +1 -0
- package/lib/{scheduleManager.mjs → scheduleManager.js} +3 -3
- package/lib/scheduleManager.js.map +1 -0
- package/lib/{storageServiceWithAttachBlobs.d.mts → storageServiceWithAttachBlobs.d.ts} +1 -1
- package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -0
- package/lib/{storageServiceWithAttachBlobs.mjs → storageServiceWithAttachBlobs.js} +1 -1
- package/lib/storageServiceWithAttachBlobs.js.map +1 -0
- package/lib/summary/{index.d.mts → index.d.ts} +13 -13
- package/lib/summary/index.d.ts.map +1 -0
- package/lib/summary/{index.mjs → index.js} +12 -12
- package/lib/summary/index.js.map +1 -0
- package/lib/summary/{orderedClientElection.d.mts → orderedClientElection.d.ts} +5 -1
- package/lib/summary/orderedClientElection.d.ts.map +1 -0
- package/lib/summary/{orderedClientElection.mjs → orderedClientElection.js} +2 -2
- package/lib/summary/orderedClientElection.js.map +1 -0
- package/lib/summary/{runWhileConnectedCoordinator.d.mts → runWhileConnectedCoordinator.d.ts} +2 -2
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/lib/summary/{runWhileConnectedCoordinator.mjs → runWhileConnectedCoordinator.js} +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -0
- package/lib/summary/{runningSummarizer.d.mts → runningSummarizer.d.ts} +6 -5
- package/lib/summary/runningSummarizer.d.ts.map +1 -0
- package/lib/summary/{runningSummarizer.mjs → runningSummarizer.js} +41 -26
- package/lib/summary/runningSummarizer.js.map +1 -0
- package/lib/summary/{summarizer.d.mts → summarizer.d.ts} +5 -5
- package/lib/summary/summarizer.d.ts.map +1 -0
- package/lib/summary/{summarizer.mjs → summarizer.js} +4 -4
- package/lib/summary/summarizer.js.map +1 -0
- package/lib/summary/{summarizerClientElection.d.mts → summarizerClientElection.d.ts} +3 -3
- package/lib/summary/summarizerClientElection.d.ts.map +1 -0
- package/lib/summary/{summarizerClientElection.mjs → summarizerClientElection.js} +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -0
- package/lib/summary/{summarizerHeuristics.d.mts → summarizerHeuristics.d.ts} +4 -4
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
- package/lib/summary/{summarizerHeuristics.mjs → summarizerHeuristics.js} +1 -1
- package/lib/summary/summarizerHeuristics.js.map +1 -0
- package/lib/summary/summarizerNode/{index.d.mts → index.d.ts} +4 -4
- package/lib/summary/summarizerNode/index.d.ts.map +1 -0
- package/lib/summary/summarizerNode/index.js +7 -0
- package/lib/summary/summarizerNode/index.js.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNode.d.mts → summarizerNode.d.ts} +17 -6
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNode.mjs → summarizerNode.js} +34 -4
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeUtils.d.mts → summarizerNodeUtils.d.ts} +10 -2
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeUtils.mjs → summarizerNodeUtils.js} +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeWithGc.d.mts → summarizerNodeWithGc.d.ts} +4 -5
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -0
- package/lib/summary/summarizerNode/{summarizerNodeWithGc.mjs → summarizerNodeWithGc.js} +7 -7
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -0
- package/lib/summary/{summarizerTypes.d.mts → summarizerTypes.d.ts} +10 -21
- package/lib/summary/summarizerTypes.d.ts.map +1 -0
- package/lib/summary/{summarizerTypes.mjs → summarizerTypes.js} +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -0
- package/lib/summary/{summaryCollection.d.mts → summaryCollection.d.ts} +1 -1
- package/lib/summary/summaryCollection.d.ts.map +1 -0
- package/lib/summary/{summaryCollection.mjs → summaryCollection.js} +1 -1
- package/lib/summary/summaryCollection.js.map +1 -0
- package/lib/summary/{summaryFormat.d.mts → summaryFormat.d.ts} +16 -3
- package/lib/summary/summaryFormat.d.ts.map +1 -0
- package/lib/summary/{summaryFormat.mjs → summaryFormat.js} +1 -1
- package/lib/summary/summaryFormat.js.map +1 -0
- package/lib/summary/{summaryGenerator.d.mts → summaryGenerator.d.ts} +7 -6
- package/lib/summary/summaryGenerator.d.ts.map +1 -0
- package/lib/summary/{summaryGenerator.mjs → summaryGenerator.js} +11 -2
- package/lib/summary/summaryGenerator.js.map +1 -0
- package/lib/summary/{summaryManager.d.mts → summaryManager.d.ts} +6 -7
- package/lib/summary/summaryManager.d.ts.map +1 -0
- package/lib/summary/{summaryManager.mjs → summaryManager.js} +4 -5
- package/lib/summary/summaryManager.js.map +1 -0
- package/lib/test/batchTracker.spec.js +88 -0
- package/lib/test/batchTracker.spec.js.map +1 -0
- package/lib/test/blobManager.spec.js +835 -0
- package/lib/test/blobManager.spec.js.map +1 -0
- package/lib/test/channelCollection.spec.js +138 -0
- package/lib/test/channelCollection.spec.js.map +1 -0
- package/lib/test/containerRuntime.spec.js +1748 -0
- package/lib/test/containerRuntime.spec.js.map +1 -0
- package/lib/test/dataStoreContext.spec.js +771 -0
- package/lib/test/dataStoreContext.spec.js.map +1 -0
- package/lib/test/dataStoreCreation.spec.js +303 -0
- package/lib/test/dataStoreCreation.spec.js.map +1 -0
- package/lib/test/dataStoreRegistry.spec.js +26 -0
- package/lib/test/dataStoreRegistry.spec.js.map +1 -0
- package/lib/test/fuzz/fuzzUtils.js +66 -0
- package/lib/test/fuzz/fuzzUtils.js.map +1 -0
- package/lib/test/fuzz/summarizer.fuzz.spec.js +31 -0
- package/lib/test/fuzz/summarizer.fuzz.spec.js.map +1 -0
- package/lib/test/fuzz/summarizerFuzzMocks.js +162 -0
- package/lib/test/fuzz/summarizerFuzzMocks.js.map +1 -0
- package/lib/test/fuzz/summarizerFuzzSuite.js +106 -0
- package/lib/test/fuzz/summarizerFuzzSuite.js.map +1 -0
- package/lib/test/gc/garbageCollection.spec.js +1464 -0
- package/lib/test/gc/garbageCollection.spec.js.map +1 -0
- package/lib/test/gc/gcConfigs.spec.js +689 -0
- package/lib/test/gc/gcConfigs.spec.js.map +1 -0
- package/lib/test/gc/gcHelpers.spec.js +110 -0
- package/lib/test/gc/gcHelpers.spec.js.map +1 -0
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js +68 -0
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js.map +1 -0
- package/lib/test/gc/gcStats.spec.js +390 -0
- package/lib/test/gc/gcStats.spec.js.map +1 -0
- package/lib/test/gc/gcSummaryStateTracker.spec.js +228 -0
- package/lib/test/gc/gcSummaryStateTracker.spec.js.map +1 -0
- package/lib/test/gc/gcTelemetry.spec.js +530 -0
- package/lib/test/gc/gcTelemetry.spec.js.map +1 -0
- package/lib/test/gc/gcUnitTestHelpers.js +29 -0
- package/lib/test/gc/gcUnitTestHelpers.js.map +1 -0
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js +192 -0
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js.map +1 -0
- package/lib/test/getPendingBlobs.spec.js +193 -0
- package/lib/test/getPendingBlobs.spec.js.map +1 -0
- package/lib/test/hardwareStats.spec.js +93 -0
- package/lib/test/hardwareStats.spec.js.map +1 -0
- package/lib/test/index.js +6 -0
- package/lib/test/index.js.map +1 -0
- package/lib/test/opLifecycle/OpGroupingManager.spec.js +225 -0
- package/lib/test/opLifecycle/OpGroupingManager.spec.js.map +1 -0
- package/lib/test/opLifecycle/batchManager.spec.js +189 -0
- package/lib/test/opLifecycle/batchManager.spec.js.map +1 -0
- package/lib/test/opLifecycle/opCompressor.spec.js +74 -0
- package/lib/test/opLifecycle/opCompressor.spec.js.map +1 -0
- package/lib/test/opLifecycle/opDecompressor.spec.js +218 -0
- package/lib/test/opLifecycle/opDecompressor.spec.js.map +1 -0
- package/lib/test/opLifecycle/opSplitter.spec.js +272 -0
- package/lib/test/opLifecycle/opSplitter.spec.js.map +1 -0
- package/lib/test/opLifecycle/outbox.spec.js +675 -0
- package/lib/test/opLifecycle/outbox.spec.js.map +1 -0
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js +196 -0
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js.map +1 -0
- package/lib/test/pendingStateManager.spec.js +329 -0
- package/lib/test/pendingStateManager.spec.js.map +1 -0
- package/lib/test/scheduleManager.spec.js +270 -0
- package/lib/test/scheduleManager.spec.js.map +1 -0
- package/lib/test/summarizerNode.spec.js +326 -0
- package/lib/test/summarizerNode.spec.js.map +1 -0
- package/lib/test/summarizerNodeWithGc.spec.js +318 -0
- package/lib/test/summarizerNodeWithGc.spec.js.map +1 -0
- package/lib/test/summary/orderedClientElection.spec.js +535 -0
- package/lib/test/summary/orderedClientElection.spec.js.map +1 -0
- package/lib/test/summary/runningSummarizer.spec.js +1349 -0
- package/lib/test/summary/runningSummarizer.spec.js.map +1 -0
- package/lib/test/summary/summarizer.spec.js +29 -0
- package/lib/test/summary/summarizer.spec.js.map +1 -0
- package/lib/test/summary/summarizerClientElection.spec.js +436 -0
- package/lib/test/summary/summarizerClientElection.spec.js.map +1 -0
- package/lib/test/summary/summarizerHeuristics.spec.js +289 -0
- package/lib/test/summary/summarizerHeuristics.spec.js.map +1 -0
- package/lib/test/summary/summaryCollection.spec.js +200 -0
- package/lib/test/summary/summaryCollection.spec.js.map +1 -0
- package/lib/test/summary/summaryManager.spec.js +430 -0
- package/lib/test/summary/summaryManager.spec.js.map +1 -0
- package/lib/test/summary/testQuorumClients.js +34 -0
- package/lib/test/summary/testQuorumClients.js.map +1 -0
- package/lib/test/throttler.spec.js +175 -0
- package/lib/test/throttler.spec.js.map +1 -0
- package/lib/test/types/validateContainerRuntimePrevious.generated.js +180 -0
- package/lib/test/types/validateContainerRuntimePrevious.generated.js.map +1 -0
- package/lib/{throttler.d.mts → throttler.d.ts} +1 -1
- package/lib/throttler.d.ts.map +1 -0
- package/lib/{throttler.mjs → throttler.js} +1 -1
- package/lib/throttler.js.map +1 -0
- package/package.json +101 -88
- package/src/batchTracker.ts +1 -1
- package/src/blobManager.ts +1 -15
- package/src/{dataStores.ts → channelCollection.ts} +620 -175
- package/src/connectionTelemetry.ts +42 -3
- package/src/containerHandleContext.ts +1 -1
- package/src/containerRuntime.ts +604 -415
- package/src/dataStore.ts +16 -15
- package/src/dataStoreContext.ts +376 -216
- package/src/dataStoreContexts.ts +2 -1
- package/src/deltaManagerSummarizerProxy.ts +132 -7
- package/src/gc/garbageCollection.ts +84 -44
- package/src/gc/gcConfigs.ts +17 -7
- package/src/gc/gcDefinitions.ts +23 -13
- package/src/gc/gcHelpers.ts +2 -2
- package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
- package/src/gc/gcSummaryStateTracker.ts +19 -7
- package/src/gc/gcTelemetry.ts +9 -7
- package/src/gc/gcUnreferencedStateTracker.ts +1 -1
- package/src/gc/index.ts +10 -9
- package/src/index.ts +28 -27
- package/src/messageTypes.ts +3 -3
- package/src/opLifecycle/README.md +2 -4
- package/src/opLifecycle/batchManager.ts +2 -2
- package/src/opLifecycle/definitions.ts +2 -2
- package/src/opLifecycle/index.ts +8 -8
- package/src/opLifecycle/opCompressor.ts +3 -3
- package/src/opLifecycle/opDecompressor.ts +3 -3
- package/src/opLifecycle/opGroupingManager.ts +3 -12
- package/src/opLifecycle/opSplitter.ts +3 -3
- package/src/opLifecycle/outbox.ts +29 -9
- package/src/opLifecycle/remoteMessageProcessor.ts +4 -4
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +19 -13
- package/src/scheduleManager.ts +4 -4
- package/src/summary/index.ts +13 -12
- package/src/summary/orderedClientElection.ts +1 -1
- package/src/summary/runWhileConnectedCoordinator.ts +1 -1
- package/src/summary/runningSummarizer.ts +52 -32
- package/src/summary/summarizer.ts +7 -7
- package/src/summary/summarizerClientElection.ts +2 -2
- package/src/summary/summarizerHeuristics.ts +3 -3
- package/src/summary/summarizerNode/index.ts +6 -3
- package/src/summary/summarizerNode/summarizerNode.ts +50 -5
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +14 -1
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +11 -11
- package/src/summary/summarizerTypes.ts +11 -23
- package/src/summary/summaryFormat.ts +16 -2
- package/src/summary/summaryGenerator.ts +16 -4
- package/src/summary/summaryManager.ts +6 -7
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.json +2 -5
- package/dist/dataStores.d.ts +0 -151
- package/dist/dataStores.d.ts.map +0 -1
- package/dist/dataStores.js.map +0 -1
- package/dist/deltaManagerProxyBase.d.ts.map +0 -1
- package/dist/deltaManagerProxyBase.js +0 -77
- package/dist/deltaManagerProxyBase.js.map +0 -1
- package/lib/batchTracker.d.mts.map +0 -1
- package/lib/batchTracker.mjs.map +0 -1
- package/lib/blobManager.d.mts.map +0 -1
- package/lib/blobManager.mjs.map +0 -1
- package/lib/connectionTelemetry.d.mts.map +0 -1
- package/lib/connectionTelemetry.mjs.map +0 -1
- package/lib/containerHandleContext.d.mts.map +0 -1
- package/lib/containerHandleContext.mjs.map +0 -1
- package/lib/containerRuntime.d.mts.map +0 -1
- package/lib/containerRuntime.mjs.map +0 -1
- package/lib/dataStore.d.mts.map +0 -1
- package/lib/dataStore.mjs.map +0 -1
- package/lib/dataStoreContext.d.mts.map +0 -1
- package/lib/dataStoreContext.mjs.map +0 -1
- package/lib/dataStoreContexts.d.mts.map +0 -1
- package/lib/dataStoreContexts.mjs.map +0 -1
- package/lib/dataStoreRegistry.d.mts.map +0 -1
- package/lib/dataStoreRegistry.mjs.map +0 -1
- package/lib/dataStores.d.mts +0 -151
- package/lib/dataStores.d.mts.map +0 -1
- package/lib/dataStores.mjs.map +0 -1
- package/lib/deltaManagerProxyBase.d.mts +0 -35
- package/lib/deltaManagerProxyBase.d.mts.map +0 -1
- package/lib/deltaManagerProxyBase.mjs +0 -73
- package/lib/deltaManagerProxyBase.mjs.map +0 -1
- package/lib/deltaManagerSummarizerProxy.d.mts +0 -19
- package/lib/deltaManagerSummarizerProxy.d.mts.map +0 -1
- package/lib/deltaManagerSummarizerProxy.mjs +0 -38
- package/lib/deltaManagerSummarizerProxy.mjs.map +0 -1
- package/lib/deltaScheduler.d.mts.map +0 -1
- package/lib/deltaScheduler.mjs.map +0 -1
- package/lib/error.d.mts.map +0 -1
- package/lib/error.mjs.map +0 -1
- package/lib/gc/garbageCollection.d.mts.map +0 -1
- package/lib/gc/garbageCollection.mjs.map +0 -1
- package/lib/gc/gcConfigs.d.mts.map +0 -1
- package/lib/gc/gcConfigs.mjs.map +0 -1
- package/lib/gc/gcDefinitions.d.mts.map +0 -1
- package/lib/gc/gcDefinitions.mjs.map +0 -1
- package/lib/gc/gcHelpers.mjs.map +0 -1
- package/lib/gc/gcReferenceGraphAlgorithm.d.mts.map +0 -1
- package/lib/gc/gcReferenceGraphAlgorithm.mjs.map +0 -1
- package/lib/gc/gcSummaryDefinitions.d.mts.map +0 -1
- package/lib/gc/gcSummaryDefinitions.mjs.map +0 -1
- package/lib/gc/gcSummaryStateTracker.d.mts.map +0 -1
- package/lib/gc/gcSummaryStateTracker.mjs.map +0 -1
- package/lib/gc/gcTelemetry.d.mts.map +0 -1
- package/lib/gc/gcTelemetry.mjs.map +0 -1
- package/lib/gc/gcUnreferencedStateTracker.d.mts.map +0 -1
- package/lib/gc/gcUnreferencedStateTracker.mjs.map +0 -1
- package/lib/gc/index.d.mts +0 -13
- package/lib/gc/index.d.mts.map +0 -1
- package/lib/gc/index.mjs.map +0 -1
- package/lib/index.d.mts.map +0 -1
- package/lib/index.mjs +0 -25
- package/lib/index.mjs.map +0 -1
- package/lib/messageTypes.d.mts.map +0 -1
- package/lib/messageTypes.mjs.map +0 -1
- package/lib/metadata.d.mts.map +0 -1
- package/lib/metadata.mjs.map +0 -1
- package/lib/opLifecycle/batchManager.d.mts.map +0 -1
- package/lib/opLifecycle/batchManager.mjs.map +0 -1
- package/lib/opLifecycle/definitions.d.mts.map +0 -1
- package/lib/opLifecycle/definitions.mjs.map +0 -1
- package/lib/opLifecycle/index.d.mts +0 -13
- package/lib/opLifecycle/index.d.mts.map +0 -1
- package/lib/opLifecycle/index.mjs +0 -12
- package/lib/opLifecycle/index.mjs.map +0 -1
- package/lib/opLifecycle/opCompressor.d.mts.map +0 -1
- package/lib/opLifecycle/opCompressor.mjs.map +0 -1
- package/lib/opLifecycle/opDecompressor.d.mts.map +0 -1
- package/lib/opLifecycle/opDecompressor.mjs.map +0 -1
- package/lib/opLifecycle/opGroupingManager.d.mts.map +0 -1
- package/lib/opLifecycle/opGroupingManager.mjs.map +0 -1
- package/lib/opLifecycle/opSplitter.d.mts.map +0 -1
- package/lib/opLifecycle/opSplitter.mjs.map +0 -1
- package/lib/opLifecycle/outbox.d.mts.map +0 -1
- package/lib/opLifecycle/outbox.mjs.map +0 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.mts.map +0 -1
- package/lib/opLifecycle/remoteMessageProcessor.mjs.map +0 -1
- package/lib/opProperties.d.mts.map +0 -1
- package/lib/opProperties.mjs.map +0 -1
- package/lib/packageVersion.d.mts.map +0 -1
- package/lib/packageVersion.mjs.map +0 -1
- package/lib/pendingStateManager.d.mts.map +0 -1
- package/lib/pendingStateManager.mjs.map +0 -1
- package/lib/scheduleManager.d.mts.map +0 -1
- package/lib/scheduleManager.mjs.map +0 -1
- package/lib/storageServiceWithAttachBlobs.d.mts.map +0 -1
- package/lib/storageServiceWithAttachBlobs.mjs.map +0 -1
- package/lib/summary/index.d.mts.map +0 -1
- package/lib/summary/index.mjs.map +0 -1
- package/lib/summary/orderedClientElection.d.mts.map +0 -1
- package/lib/summary/orderedClientElection.mjs.map +0 -1
- package/lib/summary/runWhileConnectedCoordinator.d.mts.map +0 -1
- package/lib/summary/runWhileConnectedCoordinator.mjs.map +0 -1
- package/lib/summary/runningSummarizer.d.mts.map +0 -1
- package/lib/summary/runningSummarizer.mjs.map +0 -1
- package/lib/summary/summarizer.d.mts.map +0 -1
- package/lib/summary/summarizer.mjs.map +0 -1
- package/lib/summary/summarizerClientElection.d.mts.map +0 -1
- package/lib/summary/summarizerClientElection.mjs.map +0 -1
- package/lib/summary/summarizerHeuristics.d.mts.map +0 -1
- package/lib/summary/summarizerHeuristics.mjs.map +0 -1
- package/lib/summary/summarizerNode/index.d.mts.map +0 -1
- package/lib/summary/summarizerNode/index.mjs +0 -7
- package/lib/summary/summarizerNode/index.mjs.map +0 -1
- package/lib/summary/summarizerNode/summarizerNode.d.mts.map +0 -1
- package/lib/summary/summarizerNode/summarizerNode.mjs.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.mts.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.mjs.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.mts.map +0 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.mjs.map +0 -1
- package/lib/summary/summarizerTypes.d.mts.map +0 -1
- package/lib/summary/summarizerTypes.mjs.map +0 -1
- package/lib/summary/summaryCollection.d.mts.map +0 -1
- package/lib/summary/summaryCollection.mjs.map +0 -1
- package/lib/summary/summaryFormat.d.mts.map +0 -1
- package/lib/summary/summaryFormat.mjs.map +0 -1
- package/lib/summary/summaryGenerator.d.mts.map +0 -1
- package/lib/summary/summaryGenerator.mjs.map +0 -1
- package/lib/summary/summaryManager.d.mts.map +0 -1
- package/lib/summary/summaryManager.mjs.map +0 -1
- package/lib/throttler.d.mts.map +0 -1
- package/lib/throttler.mjs.map +0 -1
- package/src/deltaManagerProxyBase.ts +0 -111
package/dist/containerRuntime.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ContainerRuntime = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isRuntimeMessage = exports.RuntimeMessage = exports.defaultPendingOpsRetryDelayMs = exports.defaultPendingOpsWaitTimeoutMs = exports.CompressionAlgorithms = exports.defaultRuntimeHeaderData = exports.InactiveResponseHeaderKey = exports.TombstoneResponseHeaderKey = exports.
|
|
3
|
+
exports.ContainerRuntime = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isRuntimeMessage = exports.RuntimeMessage = exports.defaultPendingOpsRetryDelayMs = exports.defaultPendingOpsWaitTimeoutMs = exports.CompressionAlgorithms = exports.defaultRuntimeHeaderData = exports.InactiveResponseHeaderKey = exports.TombstoneResponseHeaderKey = exports.DefaultSummaryConfiguration = void 0;
|
|
4
4
|
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
5
5
|
const core_utils_1 = require("@fluidframework/core-utils");
|
|
6
6
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
@@ -11,22 +11,22 @@ const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
|
11
11
|
const runtime_definitions_1 = require("@fluidframework/runtime-definitions");
|
|
12
12
|
const runtime_utils_1 = require("@fluidframework/runtime-utils");
|
|
13
13
|
const uuid_1 = require("uuid");
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
14
|
+
const containerHandleContext_js_1 = require("./containerHandleContext.js");
|
|
15
|
+
const dataStoreRegistry_js_1 = require("./dataStoreRegistry.js");
|
|
16
|
+
const connectionTelemetry_js_1 = require("./connectionTelemetry.js");
|
|
17
|
+
const pendingStateManager_js_1 = require("./pendingStateManager.js");
|
|
18
|
+
const packageVersion_js_1 = require("./packageVersion.js");
|
|
19
|
+
const blobManager_js_1 = require("./blobManager.js");
|
|
20
|
+
const channelCollection_js_1 = require("./channelCollection.js");
|
|
21
|
+
const index_js_1 = require("./summary/index.js");
|
|
22
|
+
const throttler_js_1 = require("./throttler.js");
|
|
23
|
+
const index_js_2 = require("./gc/index.js");
|
|
24
|
+
const dataStore_js_1 = require("./dataStore.js");
|
|
25
|
+
const batchTracker_js_1 = require("./batchTracker.js");
|
|
26
|
+
const scheduleManager_js_1 = require("./scheduleManager.js");
|
|
27
|
+
const index_js_3 = require("./opLifecycle/index.js");
|
|
28
|
+
const deltaManagerSummarizerProxy_js_1 = require("./deltaManagerSummarizerProxy.js");
|
|
29
|
+
const messageTypes_js_1 = require("./messageTypes.js");
|
|
30
30
|
/**
|
|
31
31
|
* Utility to implement compat behaviors given an unknown message type
|
|
32
32
|
* The parameters are typed to support compile-time enforcement of handling all known types/behaviors
|
|
@@ -56,26 +56,6 @@ exports.DefaultSummaryConfiguration = {
|
|
|
56
56
|
runtimeOpWeight: 1.0,
|
|
57
57
|
nonRuntimeHeuristicThreshold: 20,
|
|
58
58
|
};
|
|
59
|
-
/**
|
|
60
|
-
* Accepted header keys for requests coming to the runtime.
|
|
61
|
-
* @internal
|
|
62
|
-
*/
|
|
63
|
-
var RuntimeHeaders;
|
|
64
|
-
(function (RuntimeHeaders) {
|
|
65
|
-
/** True to wait for a data store to be created and loaded before returning it. */
|
|
66
|
-
RuntimeHeaders["wait"] = "wait";
|
|
67
|
-
/** True if the request is coming from an IFluidHandle. */
|
|
68
|
-
RuntimeHeaders["viaHandle"] = "viaHandle";
|
|
69
|
-
})(RuntimeHeaders || (exports.RuntimeHeaders = RuntimeHeaders = {}));
|
|
70
|
-
/** True if a tombstoned object should be returned without erroring
|
|
71
|
-
* @alpha
|
|
72
|
-
*/
|
|
73
|
-
exports.AllowTombstoneRequestHeaderKey = "allowTombstone"; // Belongs in the enum above, but avoiding the breaking change
|
|
74
|
-
/**
|
|
75
|
-
* [IRRELEVANT IF throwOnInactiveLoad OPTION NOT SET] True if an inactive object should be returned without erroring
|
|
76
|
-
* @internal
|
|
77
|
-
*/
|
|
78
|
-
exports.AllowInactiveRequestHeaderKey = "allowInactive"; // Belongs in the enum above, but avoiding the breaking change
|
|
79
59
|
/**
|
|
80
60
|
* Tombstone error responses will have this header set to true
|
|
81
61
|
* @alpha
|
|
@@ -192,7 +172,7 @@ async function createSummarizer(loader, url) {
|
|
|
192
172
|
[container_definitions_1.LoaderHeader.cache]: false,
|
|
193
173
|
[container_definitions_1.LoaderHeader.clientDetails]: {
|
|
194
174
|
capabilities: { interactive: false },
|
|
195
|
-
type:
|
|
175
|
+
type: index_js_1.summarizerClientType,
|
|
196
176
|
},
|
|
197
177
|
[driver_definitions_1.DriverHeader.summarizingClient]: true,
|
|
198
178
|
[container_definitions_1.LoaderHeader.reconnect]: false,
|
|
@@ -247,18 +227,18 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
247
227
|
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
248
228
|
const backCompatContext = context;
|
|
249
229
|
const passLogger = backCompatContext.taggedLogger ??
|
|
250
|
-
// eslint-disable-next-line import/no-deprecated
|
|
251
230
|
new telemetry_utils_1.TaggedLoggerAdapter(backCompatContext.logger);
|
|
252
231
|
const logger = (0, telemetry_utils_1.createChildLogger)({
|
|
253
232
|
logger: passLogger,
|
|
254
233
|
properties: {
|
|
255
234
|
all: {
|
|
256
|
-
runtimeVersion:
|
|
235
|
+
runtimeVersion: packageVersion_js_1.pkgVersion,
|
|
257
236
|
},
|
|
258
237
|
},
|
|
259
238
|
});
|
|
260
|
-
const
|
|
261
|
-
const
|
|
239
|
+
const mc = (0, telemetry_utils_1.loggerToMonitoringContext)(logger);
|
|
240
|
+
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor = "off", chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, enableGroupedBatching = false, } = runtimeOptions;
|
|
241
|
+
const registry = new dataStoreRegistry_js_1.FluidDataStoreRegistry(registryEntries);
|
|
262
242
|
const tryFetchBlob = async (blobName) => {
|
|
263
243
|
const blobId = context.baseSnapshot?.blobs[blobName];
|
|
264
244
|
if (context.baseSnapshot && blobId) {
|
|
@@ -269,14 +249,14 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
269
249
|
}
|
|
270
250
|
};
|
|
271
251
|
const [chunks, metadata, electedSummarizerData, aliases, serializedIdCompressor] = await Promise.all([
|
|
272
|
-
tryFetchBlob(
|
|
273
|
-
tryFetchBlob(
|
|
274
|
-
tryFetchBlob(
|
|
275
|
-
tryFetchBlob(
|
|
276
|
-
tryFetchBlob(
|
|
252
|
+
tryFetchBlob(index_js_1.chunksBlobName),
|
|
253
|
+
tryFetchBlob(index_js_1.metadataBlobName),
|
|
254
|
+
tryFetchBlob(index_js_1.electedSummarizerBlobName),
|
|
255
|
+
tryFetchBlob(index_js_1.aliasBlobName),
|
|
256
|
+
tryFetchBlob(index_js_1.idCompressorBlobName),
|
|
277
257
|
]);
|
|
278
258
|
// read snapshot blobs needed for BlobManager to load
|
|
279
|
-
const blobManagerSnapshot = await
|
|
259
|
+
const blobManagerSnapshot = await blobManager_js_1.BlobManager.load(context.baseSnapshot?.trees[index_js_1.blobsTreeName], async (id) => {
|
|
280
260
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
281
261
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
282
262
|
(0, core_utils_1.assert)(context.storage !== undefined, 0x256 /* "storage undefined in attached container" */);
|
|
@@ -293,7 +273,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
293
273
|
// "Load from summary, runtime metadata sequenceNumber !== initialSequenceNumber"
|
|
294
274
|
const error = new telemetry_utils_1.DataCorruptionError(
|
|
295
275
|
// pre-0.58 error message: SummaryMetadataMismatch
|
|
296
|
-
"Summary metadata mismatch", { runtimeVersion:
|
|
276
|
+
"Summary metadata mismatch", { runtimeVersion: packageVersion_js_1.pkgVersion, runtimeSequenceNumber, protocolSequenceNumber });
|
|
297
277
|
if (loadSequenceNumberVerification === "log") {
|
|
298
278
|
logger.sendErrorEvent({ eventName: "SequenceNumberMismatch" }, error);
|
|
299
279
|
}
|
|
@@ -302,9 +282,37 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
302
282
|
}
|
|
303
283
|
}
|
|
304
284
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
285
|
+
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
286
|
+
// allow new containers to turn it on
|
|
287
|
+
let idCompressorMode;
|
|
288
|
+
if (existing) {
|
|
289
|
+
// This setting has to be sticky for correctness:
|
|
290
|
+
// 1) if compressior is OFF, it can't be enabled, as already running clients (in given document session) do not know
|
|
291
|
+
// how to process compressor ops
|
|
292
|
+
// 2) if it's ON, then all sessions should load compressor right away
|
|
293
|
+
// 3) Same logic applies for "delayed" mode
|
|
294
|
+
// Maybe in the future we will need to enabled (and figure how to do it safely) "delayed" -> "on" change.
|
|
295
|
+
// We could do "off" -> "on" transtition too, if all clients start loading compressor (but not using it initially) and do so for a while -
|
|
296
|
+
// this will allow clients to eventually to disregard "off" setting (when it's safe so) and start using compressor in future sessions.
|
|
297
|
+
// Everyting is possible, but it needs to be designed and executed carefully, when such need arises.
|
|
298
|
+
idCompressorMode = metadata?.idCompressorMode ?? "off";
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
// FG overwrite
|
|
302
|
+
const enabled = mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled");
|
|
303
|
+
switch (enabled) {
|
|
304
|
+
case true:
|
|
305
|
+
idCompressorMode = "on";
|
|
306
|
+
break;
|
|
307
|
+
case false:
|
|
308
|
+
idCompressorMode = "off";
|
|
309
|
+
break;
|
|
310
|
+
default:
|
|
311
|
+
idCompressorMode = enableRuntimeIdCompressor;
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
const createIdCompressorFn = async () => {
|
|
308
316
|
const { createIdCompressor, deserializeIdCompressor, createSessionId } = await import("@fluidframework/id-compressor");
|
|
309
317
|
/**
|
|
310
318
|
* Because the IdCompressor emits so much telemetry, this function is used to sample
|
|
@@ -321,15 +329,15 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
321
329
|
const compressorLogger = (0, telemetry_utils_1.createSampledLogger)(logger, idCompressorEventSampler);
|
|
322
330
|
const pendingLocalState = context.pendingLocalState;
|
|
323
331
|
if (pendingLocalState?.pendingIdCompressorState !== undefined) {
|
|
324
|
-
|
|
332
|
+
return deserializeIdCompressor(pendingLocalState.pendingIdCompressorState, compressorLogger);
|
|
325
333
|
}
|
|
326
334
|
else if (serializedIdCompressor !== undefined) {
|
|
327
|
-
|
|
335
|
+
return deserializeIdCompressor(serializedIdCompressor, createSessionId(), compressorLogger);
|
|
328
336
|
}
|
|
329
337
|
else {
|
|
330
|
-
|
|
338
|
+
return createIdCompressor(compressorLogger);
|
|
331
339
|
}
|
|
332
|
-
}
|
|
340
|
+
};
|
|
333
341
|
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], {
|
|
334
342
|
summaryOptions,
|
|
335
343
|
gcOptions,
|
|
@@ -341,7 +349,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
341
349
|
enableRuntimeIdCompressor,
|
|
342
350
|
enableOpReentryCheck,
|
|
343
351
|
enableGroupedBatching,
|
|
344
|
-
}, containerScope, logger, existing, blobManagerSnapshot, context.storage,
|
|
352
|
+
}, containerScope, logger, existing, blobManagerSnapshot, context.storage, createIdCompressorFn, idCompressorMode, provideEntryPoint, requestHandler, undefined);
|
|
345
353
|
// Apply stashed ops with a reference sequence number equal to the sequence number of the snapshot,
|
|
346
354
|
// or zero. This must be done before Container replays saved ops.
|
|
347
355
|
await runtime.pendingStateManager.applyStashedOpsAt(runtimeSequenceNumber ?? 0);
|
|
@@ -355,6 +363,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
355
363
|
get storage() {
|
|
356
364
|
return this._storage;
|
|
357
365
|
}
|
|
366
|
+
get containerRuntime() {
|
|
367
|
+
return this;
|
|
368
|
+
}
|
|
358
369
|
get flushMode() {
|
|
359
370
|
return this._flushMode;
|
|
360
371
|
}
|
|
@@ -367,6 +378,25 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
367
378
|
get attachState() {
|
|
368
379
|
return this._getAttachState();
|
|
369
380
|
}
|
|
381
|
+
/**
|
|
382
|
+
* See IContainerRuntimeBase.idCompressor() for details.
|
|
383
|
+
*/
|
|
384
|
+
get idCompressor() {
|
|
385
|
+
// Expose ID Compressor only if it's On from the start.
|
|
386
|
+
// If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
|
|
387
|
+
// That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
|
|
388
|
+
// to reason over such things as session ID space.
|
|
389
|
+
if (this.idCompressorMode === "on") {
|
|
390
|
+
(0, core_utils_1.assert)(this._idCompressor !== undefined, 0x8ea /* compressor should have been loaded */);
|
|
391
|
+
return this._idCompressor;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* See IContainerRuntimeBase.generateDocumentUniqueId() for details.
|
|
396
|
+
*/
|
|
397
|
+
generateDocumentUniqueId() {
|
|
398
|
+
return this._idCompressor?.generateDocumentUniqueId() ?? (0, uuid_1.v4)();
|
|
399
|
+
}
|
|
370
400
|
get IFluidHandleContext() {
|
|
371
401
|
return this.handleContext;
|
|
372
402
|
}
|
|
@@ -404,9 +434,6 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
404
434
|
isSummariesDisabled() {
|
|
405
435
|
return this.summaryConfiguration.state === "disabled";
|
|
406
436
|
}
|
|
407
|
-
isHeuristicsDisabled() {
|
|
408
|
-
return this.summaryConfiguration.state === "disableHeuristics";
|
|
409
|
-
}
|
|
410
437
|
getMaxOpsSinceLastSummary() {
|
|
411
438
|
return this.summaryConfiguration.state !== "disabled"
|
|
412
439
|
? this.summaryConfiguration.maxOpsSinceLastSummary
|
|
@@ -431,7 +458,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
431
458
|
return this.garbageCollector.throwOnTombstoneUsage;
|
|
432
459
|
}
|
|
433
460
|
/***/
|
|
434
|
-
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage,
|
|
461
|
+
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, createIdCompressor, idCompressorMode, provideEntryPoint, requestHandler, summaryConfiguration = {
|
|
435
462
|
// the defaults
|
|
436
463
|
...exports.DefaultSummaryConfiguration,
|
|
437
464
|
// the runtime configuration overrides
|
|
@@ -439,13 +466,24 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
439
466
|
}) {
|
|
440
467
|
super();
|
|
441
468
|
this.registry = registry;
|
|
469
|
+
this.metadata = metadata;
|
|
442
470
|
this.runtimeOptions = runtimeOptions;
|
|
443
471
|
this.containerScope = containerScope;
|
|
444
472
|
this.logger = logger;
|
|
445
473
|
this._storage = _storage;
|
|
474
|
+
this.createIdCompressor = createIdCompressor;
|
|
475
|
+
this.idCompressorMode = idCompressorMode;
|
|
446
476
|
this.requestHandler = requestHandler;
|
|
447
477
|
this.summaryConfiguration = summaryConfiguration;
|
|
448
478
|
this.imminentClosure = false;
|
|
479
|
+
// We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
|
|
480
|
+
// Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
|
|
481
|
+
this.pendingIdCompressorOps = [];
|
|
482
|
+
/**
|
|
483
|
+
* True if we have ID compressor loading in-flight (async operation). Useful only for
|
|
484
|
+
* this.idCompressorMode === "delayed" mode
|
|
485
|
+
*/
|
|
486
|
+
this.compressorLoadInitiated = false;
|
|
449
487
|
this.defaultMaxConsecutiveReconnects = 7;
|
|
450
488
|
this._orderSequentiallyCalls = 0;
|
|
451
489
|
this.flushTaskExists = false;
|
|
@@ -467,18 +505,27 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
467
505
|
signalTimestamp: 0,
|
|
468
506
|
trackingSignalSequenceNumber: undefined,
|
|
469
507
|
};
|
|
508
|
+
/**
|
|
509
|
+
* It a cache for holding mapping for loading groupIds with its snapshot from the service. Add expiry policy of 1 minute.
|
|
510
|
+
* Starting with 1 min and based on recorded usage we can tweak it later on.
|
|
511
|
+
*/
|
|
512
|
+
this.snapshotCacheForLoadingGroupIds = new core_utils_1.PromiseCache({
|
|
513
|
+
expiry: { policy: "absolute", durationMs: 60000 },
|
|
514
|
+
});
|
|
470
515
|
const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, loader, pendingLocalState, supportedFeatures, } = context;
|
|
471
516
|
this.innerDeltaManager = deltaManager;
|
|
472
|
-
this.deltaManager = new
|
|
517
|
+
this.deltaManager = new deltaManagerSummarizerProxy_js_1.DeltaManagerSummarizerProxy(this.innerDeltaManager);
|
|
473
518
|
// Here we could wrap/intercept on these functions to block/modify outgoing messages if needed.
|
|
474
519
|
// This makes ContainerRuntime the final gatekeeper for outgoing messages.
|
|
475
520
|
this.submitFn = submitFn;
|
|
476
521
|
this.submitBatchFn = submitBatchFn;
|
|
477
522
|
this.submitSummaryFn = submitSummaryFn;
|
|
478
523
|
this.submitSignalFn = submitSignalFn;
|
|
479
|
-
|
|
524
|
+
// TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
|
|
525
|
+
// Values are generally expected to be set from the runtime side.
|
|
526
|
+
this.options = options ?? {};
|
|
480
527
|
this.clientDetails = clientDetails;
|
|
481
|
-
this.isSummarizerClient = this.clientDetails.type ===
|
|
528
|
+
this.isSummarizerClient = this.clientDetails.type === index_js_1.summarizerClientType;
|
|
482
529
|
this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
|
|
483
530
|
this._getClientId = () => context.clientId;
|
|
484
531
|
this._getAttachState = () => context.attachState;
|
|
@@ -514,19 +561,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
514
561
|
// summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
|
|
515
562
|
// the count is reset to 0.
|
|
516
563
|
loadSummaryNumber = metadata?.summaryNumber ?? 0;
|
|
517
|
-
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
518
|
-
// allow new containers to turn it on
|
|
519
|
-
this.idCompressorEnabled = metadata?.idCompressorEnabled ?? false;
|
|
520
564
|
}
|
|
521
565
|
else {
|
|
522
566
|
this.createContainerMetadata = {
|
|
523
|
-
createContainerRuntimeVersion:
|
|
567
|
+
createContainerRuntimeVersion: packageVersion_js_1.pkgVersion,
|
|
524
568
|
createContainerTimestamp: Date.now(),
|
|
525
569
|
};
|
|
526
570
|
loadSummaryNumber = 0;
|
|
527
|
-
this.idCompressorEnabled =
|
|
528
|
-
this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled") ??
|
|
529
|
-
idCompressor !== undefined;
|
|
530
571
|
}
|
|
531
572
|
this.nextSummaryNumber = loadSummaryNumber + 1;
|
|
532
573
|
this.messageAtLastSummary = metadata?.message;
|
|
@@ -537,21 +578,21 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
537
578
|
eventName: "GCFeatureMatrix",
|
|
538
579
|
metadataValue: JSON.stringify(metadata?.gcFeatureMatrix),
|
|
539
580
|
inputs: JSON.stringify({
|
|
540
|
-
gcOptions_gcGeneration: this.runtimeOptions.gcOptions[
|
|
581
|
+
gcOptions_gcGeneration: this.runtimeOptions.gcOptions[index_js_2.gcGenerationOptionName],
|
|
541
582
|
}),
|
|
542
583
|
});
|
|
543
584
|
this.telemetryDocumentId = metadata?.telemetryDocumentId ?? (0, uuid_1.v4)();
|
|
544
585
|
this.disableAttachReorder = this.mc.config.getBoolean("Fluid.ContainerRuntime.disableAttachOpReorder");
|
|
545
586
|
const disableChunking = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionChunkingDisabled");
|
|
546
|
-
const opGroupingManager = new
|
|
587
|
+
const opGroupingManager = new index_js_3.OpGroupingManager({
|
|
547
588
|
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
548
589
|
opCountThreshold: this.mc.config.getNumber("Fluid.ContainerRuntime.GroupedBatchingOpCount") ?? 2,
|
|
549
590
|
reentrantBatchGroupingEnabled: this.mc.config.getBoolean("Fluid.ContainerRuntime.GroupedBatchingReentrancy") ??
|
|
550
591
|
true,
|
|
551
592
|
}, this.mc.logger);
|
|
552
|
-
const opSplitter = new
|
|
553
|
-
this.remoteMessageProcessor = new
|
|
554
|
-
this.handleContext = new
|
|
593
|
+
const opSplitter = new index_js_3.OpSplitter(chunks, this.submitBatchFn, disableChunking === true ? Number.POSITIVE_INFINITY : runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
|
|
594
|
+
this.remoteMessageProcessor = new index_js_3.RemoteMessageProcessor(opSplitter, new index_js_3.OpDecompressor(this.mc.logger), opGroupingManager);
|
|
595
|
+
this.handleContext = new containerHandleContext_js_1.ContainerFluidHandleContext("", this);
|
|
555
596
|
if (this.summaryConfiguration.state === "enabled") {
|
|
556
597
|
this.validateSummaryHeuristicConfiguration(this.summaryConfiguration);
|
|
557
598
|
}
|
|
@@ -561,12 +602,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
561
602
|
// Allow for a break-glass config to override the options
|
|
562
603
|
disableOpReentryCheck !== true;
|
|
563
604
|
this.summariesDisabled = this.isSummariesDisabled();
|
|
564
|
-
this.heuristicsDisabled = this.isHeuristicsDisabled();
|
|
565
605
|
this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
|
|
566
606
|
this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
|
|
567
|
-
if (this.idCompressorEnabled) {
|
|
568
|
-
this.idCompressor = idCompressor;
|
|
569
|
-
}
|
|
570
607
|
this.maxConsecutiveReconnects =
|
|
571
608
|
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
|
|
572
609
|
this.defaultMaxConsecutiveReconnects;
|
|
@@ -590,7 +627,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
590
627
|
throw new telemetry_utils_1.UsageError("Driver's maximumCacheDurationMs policy cannot exceed 5 days");
|
|
591
628
|
}
|
|
592
629
|
}
|
|
593
|
-
this.garbageCollector =
|
|
630
|
+
this.garbageCollector = index_js_2.GarbageCollector.create({
|
|
594
631
|
runtime: this,
|
|
595
632
|
gcOptions: this.runtimeOptions.gcOptions,
|
|
596
633
|
baseSnapshot,
|
|
@@ -603,9 +640,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
603
640
|
getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
|
|
604
641
|
readAndParseBlob: async (id) => (0, driver_utils_1.readAndParse)(this.storage, id),
|
|
605
642
|
submitMessage: (message) => this.submit(message),
|
|
643
|
+
sessionExpiryTimerStarted: pendingRuntimeState?.sessionExpiryTimerStarted,
|
|
606
644
|
});
|
|
607
645
|
const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
|
|
608
|
-
this.summarizerNode = (0,
|
|
646
|
+
this.summarizerNode = (0, index_js_1.createRootSummarizerNodeWithGC)((0, telemetry_utils_1.createChildLogger)({ logger: this.logger, namespace: "SummarizerNode" }),
|
|
609
647
|
// Summarize function to call when summarize is called. Summarizer node always tracks summary state.
|
|
610
648
|
async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext),
|
|
611
649
|
// Latest change sequence number, no changes since summary applied yet
|
|
@@ -625,17 +663,26 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
625
663
|
if (baseSnapshot) {
|
|
626
664
|
this.summarizerNode.updateBaseSummaryState(baseSnapshot);
|
|
627
665
|
}
|
|
628
|
-
|
|
629
|
-
|
|
666
|
+
const parentContext = (0, channelCollection_js_1.wrapContext)(this);
|
|
667
|
+
// Due to a mismatch between different layers in terms of
|
|
668
|
+
// what is the interface of passing signals, we need the
|
|
669
|
+
// downstream stores to wrap the signal.
|
|
670
|
+
parentContext.submitSignal = (type, content, targetClientId) => {
|
|
671
|
+
const envelope1 = content;
|
|
672
|
+
const envelope2 = this.createNewSignalEnvelope(envelope1.address, type, envelope1.contents);
|
|
673
|
+
return this.submitSignalFn(envelope2, targetClientId);
|
|
674
|
+
};
|
|
675
|
+
this.channelCollection = new channelCollection_js_1.ChannelCollection((0, channelCollection_js_1.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);
|
|
676
|
+
this.blobManager = new blobManager_js_1.BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (localId, blobId) => {
|
|
630
677
|
if (!this.disposed) {
|
|
631
|
-
this.submit({ type:
|
|
678
|
+
this.submit({ type: messageTypes_js_1.ContainerMessageType.BlobAttach, contents: undefined }, undefined, {
|
|
632
679
|
localId,
|
|
633
680
|
blobId,
|
|
634
681
|
});
|
|
635
682
|
}
|
|
636
683
|
}, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), (blobPath) => this.garbageCollector.isNodeDeleted(blobPath), this, pendingRuntimeState?.pendingAttachmentBlobs, (error) => this.closeFn(error));
|
|
637
|
-
this.scheduleManager = new
|
|
638
|
-
this.pendingStateManager = new
|
|
684
|
+
this.scheduleManager = new scheduleManager_js_1.ScheduleManager(this.innerDeltaManager, this, () => this.clientId, (0, telemetry_utils_1.createChildLogger)({ logger: this.logger, namespace: "ScheduleManager" }));
|
|
685
|
+
this.pendingStateManager = new pendingStateManager_js_1.PendingStateManager({
|
|
639
686
|
applyStashedOp: this.applyStashedOp.bind(this),
|
|
640
687
|
clientId: () => this.clientId,
|
|
641
688
|
close: this.closeFn,
|
|
@@ -643,6 +690,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
643
690
|
reSubmit: this.reSubmit.bind(this),
|
|
644
691
|
reSubmitBatch: this.reSubmitBatch.bind(this),
|
|
645
692
|
isActiveConnection: () => this.innerDeltaManager.active,
|
|
693
|
+
isAttached: () => this.attachState !== container_definitions_1.AttachState.Detached,
|
|
646
694
|
}, pendingRuntimeState?.pending, this.logger);
|
|
647
695
|
const disableCompression = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionDisabled");
|
|
648
696
|
const compressionOptions = disableCompression === true
|
|
@@ -653,12 +701,12 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
653
701
|
: runtimeOptions.compressionOptions;
|
|
654
702
|
const disablePartialFlush = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisablePartialFlush");
|
|
655
703
|
const legacySendBatchFn = (0, exports.makeLegacySendBatchFn)(this.submitFn, this.innerDeltaManager);
|
|
656
|
-
this.outbox = new
|
|
704
|
+
this.outbox = new index_js_3.Outbox({
|
|
657
705
|
shouldSend: () => this.canSendOps(),
|
|
658
706
|
pendingStateManager: this.pendingStateManager,
|
|
659
707
|
submitBatchFn: this.submitBatchFn,
|
|
660
708
|
legacySendBatchFn,
|
|
661
|
-
compressor: new
|
|
709
|
+
compressor: new index_js_3.OpCompressor(this.mc.logger),
|
|
662
710
|
splitter: opSplitter,
|
|
663
711
|
config: {
|
|
664
712
|
compressionOptions,
|
|
@@ -685,7 +733,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
685
733
|
this.closeSummarizerDelayMs = closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
|
|
686
734
|
this.validateSummaryBeforeUpload =
|
|
687
735
|
this.mc.config.getBoolean("Fluid.Summarizer.ValidateSummaryBeforeUpload") ?? false;
|
|
688
|
-
this.summaryCollection = new
|
|
736
|
+
this.summaryCollection = new index_js_1.SummaryCollection(this.deltaManager, this.logger);
|
|
689
737
|
this.dirtyContainer =
|
|
690
738
|
this.attachState !== container_definitions_1.AttachState.Attached || this.hasPendingMessages();
|
|
691
739
|
context.updateDirtyContainerState(this.dirtyContainer);
|
|
@@ -697,16 +745,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
697
745
|
logger: this.logger,
|
|
698
746
|
namespace: "OrderedClientElection",
|
|
699
747
|
});
|
|
700
|
-
const orderedClientCollection = new
|
|
701
|
-
const orderedClientElectionForSummarizer = new
|
|
702
|
-
this.summarizerClientElection = new
|
|
748
|
+
const orderedClientCollection = new index_js_1.OrderedClientCollection(orderedClientLogger, this.innerDeltaManager, this._quorum);
|
|
749
|
+
const orderedClientElectionForSummarizer = new index_js_1.OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData ?? this.innerDeltaManager.lastSequenceNumber, index_js_1.SummarizerClientElection.isClientEligible);
|
|
750
|
+
this.summarizerClientElection = new index_js_1.SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, this.maxOpsSinceLastSummary);
|
|
703
751
|
if (this.isSummarizerClient) {
|
|
704
|
-
this._summarizer = new
|
|
752
|
+
this._summarizer = new index_js_1.Summarizer(this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => index_js_1.RunWhileConnectedCoordinator.create(runtime,
|
|
705
753
|
// Summarization runs in summarizer client and needs access to the real (non-proxy) active
|
|
706
754
|
// information. The proxy delta manager would always return false for summarizer client.
|
|
707
755
|
() => this.innerDeltaManager.active));
|
|
708
756
|
}
|
|
709
|
-
else if (
|
|
757
|
+
else if (index_js_1.SummarizerClientElection.clientDetailsPermitElection(this.clientDetails)) {
|
|
710
758
|
// Only create a SummaryManager and SummarizerClientElection
|
|
711
759
|
// if summaries are enabled and we are not the summarizer client.
|
|
712
760
|
const defaultAction = () => {
|
|
@@ -728,13 +776,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
728
776
|
};
|
|
729
777
|
this.summaryCollection.on("default", defaultAction);
|
|
730
778
|
// Create the SummaryManager and mark the initial state
|
|
731
|
-
this.summaryManager = new
|
|
732
|
-
this.summaryCollection, this.logger, this.formCreateSummarizerFn(loader), new
|
|
779
|
+
this.summaryManager = new index_js_1.SummaryManager(this.summarizerClientElection, this, // IConnectedState
|
|
780
|
+
this.summaryCollection, this.logger, this.formCreateSummarizerFn(loader), new throttler_js_1.Throttler(60 * 1000, // 60 sec delay window
|
|
733
781
|
30 * 1000, // 30 sec max delay
|
|
734
782
|
// throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
|
|
735
|
-
(0,
|
|
783
|
+
(0, throttler_js_1.formExponentialFn)({ coefficient: 20, initialDelay: 0 })), {
|
|
736
784
|
initialDelayMs: this.initialSummarizerDelayMs,
|
|
737
|
-
}
|
|
785
|
+
});
|
|
738
786
|
this.summaryManager.on("summarize", (eventProps) => {
|
|
739
787
|
this.emit("summarize", eventProps);
|
|
740
788
|
});
|
|
@@ -749,26 +797,27 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
749
797
|
this.mc.logger.sendTelemetryEvent({
|
|
750
798
|
eventName: "ContainerLoadStats",
|
|
751
799
|
...this.createContainerMetadata,
|
|
752
|
-
...this.
|
|
800
|
+
...this.channelCollection.containerLoadStats,
|
|
753
801
|
summaryNumber: loadSummaryNumber,
|
|
754
802
|
summaryFormatVersion: metadata?.summaryFormatVersion,
|
|
755
803
|
disableIsolatedChannels: metadata?.disableIsolatedChannels,
|
|
756
804
|
gcVersion: metadata?.gcFeature,
|
|
757
805
|
options: JSON.stringify(runtimeOptions),
|
|
806
|
+
idCompressorModeMetadata: metadata?.idCompressorMode,
|
|
807
|
+
idCompressorMode: this.idCompressorMode,
|
|
758
808
|
featureGates: JSON.stringify({
|
|
759
809
|
disableCompression,
|
|
760
810
|
disableOpReentryCheck,
|
|
761
811
|
disableChunking,
|
|
762
812
|
disableAttachReorder: this.disableAttachReorder,
|
|
763
813
|
disablePartialFlush,
|
|
764
|
-
idCompressorEnabled: this.idCompressorEnabled,
|
|
765
814
|
closeSummarizerDelayOverride,
|
|
766
815
|
}),
|
|
767
816
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
768
817
|
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
769
818
|
});
|
|
770
|
-
(0,
|
|
771
|
-
(0,
|
|
819
|
+
(0, connectionTelemetry_js_1.ReportOpPerfTelemetry)(this.clientId, this.deltaManager, this, this.logger);
|
|
820
|
+
(0, batchTracker_js_1.BindBatchTracker)(this, this.logger);
|
|
772
821
|
this.entryPoint = new core_utils_1.LazyPromise(async () => {
|
|
773
822
|
if (this.isSummarizerClient) {
|
|
774
823
|
(0, core_utils_1.assert)(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
|
|
@@ -776,11 +825,33 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
776
825
|
}
|
|
777
826
|
return provideEntryPoint(this);
|
|
778
827
|
});
|
|
828
|
+
// If we loaded from pending state, then we need to skip any ops that are already accounted in such
|
|
829
|
+
// saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
|
|
830
|
+
this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
|
|
831
|
+
}
|
|
832
|
+
getCreateChildSummarizerNodeFn(id, createParam) {
|
|
833
|
+
return (summarizeInternal, getGCDataFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn);
|
|
834
|
+
}
|
|
835
|
+
deleteChildSummarizerNode(id) {
|
|
836
|
+
return this.summarizerNode.deleteChild(id);
|
|
837
|
+
}
|
|
838
|
+
/* IFluidParentContext APIs that should not be called on Root */
|
|
839
|
+
makeLocallyVisible() {
|
|
840
|
+
(0, core_utils_1.assert)(false, 0x8eb /* should not be called */);
|
|
841
|
+
}
|
|
842
|
+
setChannelDirty(address) {
|
|
843
|
+
(0, core_utils_1.assert)(false, "should not be called");
|
|
779
844
|
}
|
|
780
845
|
/**
|
|
781
846
|
* Initializes the state from the base snapshot this container runtime loaded from.
|
|
782
847
|
*/
|
|
783
848
|
async initializeBaseState() {
|
|
849
|
+
if (this.idCompressorMode === "on" ||
|
|
850
|
+
(this.idCompressorMode === "delayed" && this.connected)) {
|
|
851
|
+
// This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
|
|
852
|
+
(0, core_utils_1.assert)(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
|
|
853
|
+
this._idCompressor = await this.createIdCompressor();
|
|
854
|
+
}
|
|
784
855
|
await this.garbageCollector.initializeBaseState();
|
|
785
856
|
}
|
|
786
857
|
dispose(error) {
|
|
@@ -799,11 +870,110 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
799
870
|
}
|
|
800
871
|
this.garbageCollector.dispose();
|
|
801
872
|
this._summarizer?.dispose();
|
|
802
|
-
this.
|
|
873
|
+
this.channelCollection.dispose();
|
|
803
874
|
this.pendingStateManager.dispose();
|
|
804
875
|
this.emit("dispose");
|
|
805
876
|
this.removeAllListeners();
|
|
806
877
|
}
|
|
878
|
+
/**
|
|
879
|
+
* Api to fetch the snapshot from the service for a loadingGroupIds.
|
|
880
|
+
* @param loadingGroupIds - LoadingGroupId for which the snapshot is asked for.
|
|
881
|
+
* @param pathParts - Parts of the path, which we want to extract from the snapshot tree.
|
|
882
|
+
* @returns - snapshotTree and the sequence number of the snapshot.
|
|
883
|
+
*/
|
|
884
|
+
async getSnapshotForLoadingGroupId(loadingGroupIds, pathParts) {
|
|
885
|
+
const sortedLoadingGroupIds = loadingGroupIds.sort();
|
|
886
|
+
(0, core_utils_1.assert)(this.storage.getSnapshot !== undefined, 0x8ed /* getSnapshot api should be defined if used */);
|
|
887
|
+
let loadedFromCache = true;
|
|
888
|
+
// Lookup up in the cache, if not present then make the network call as multiple datastores could
|
|
889
|
+
// be in same loading group. So, once we have fetched the snapshot for that loading group on
|
|
890
|
+
// any request, then cache that as same group could be requested in future too.
|
|
891
|
+
const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(), async () => {
|
|
892
|
+
(0, core_utils_1.assert)(this.storage.getSnapshot !== undefined, 0x8ee /* getSnapshot api should be defined if used */);
|
|
893
|
+
loadedFromCache = false;
|
|
894
|
+
return this.storage.getSnapshot({
|
|
895
|
+
cacheSnapshot: false,
|
|
896
|
+
scenarioName: "snapshotForLoadingGroupId",
|
|
897
|
+
loadingGroupIds: sortedLoadingGroupIds,
|
|
898
|
+
});
|
|
899
|
+
});
|
|
900
|
+
this.logger.sendTelemetryEvent({
|
|
901
|
+
eventName: "GroupIdSnapshotFetched",
|
|
902
|
+
details: JSON.stringify({
|
|
903
|
+
fromCache: loadedFromCache,
|
|
904
|
+
loadingGroupIds: loadingGroupIds.join(","),
|
|
905
|
+
}),
|
|
906
|
+
});
|
|
907
|
+
// Find the snapshotTree inside the returned snapshot based on the path as given in the request.
|
|
908
|
+
const hasIsolatedChannels = (0, index_js_1.rootHasIsolatedChannels)(this.metadata);
|
|
909
|
+
const snapshotTreeForPath = this.getSnapshotTreeForPath(snapshot.snapshotTree, pathParts, hasIsolatedChannels);
|
|
910
|
+
(0, core_utils_1.assert)(snapshotTreeForPath !== undefined, 0x8ef /* no snapshotTree for the path */);
|
|
911
|
+
const snapshotSeqNumber = snapshot.sequenceNumber;
|
|
912
|
+
(0, core_utils_1.assert)(snapshotSeqNumber !== undefined, 0x8f0 /* snapshotSeqNumber should be present */);
|
|
913
|
+
// This assert fires if we get a snapshot older than the snapshot we loaded from. This is a service issue.
|
|
914
|
+
// Snapshots should only move forward. If we observe an older snapshot than the one we loaded from, then likely
|
|
915
|
+
// the file has been overwritten or service lost data.
|
|
916
|
+
if (snapshotSeqNumber < this.deltaManager.initialSequenceNumber) {
|
|
917
|
+
throw telemetry_utils_1.DataProcessingError.create("Downloaded snapshot older than snapshot we loaded from", "getSnapshotForLoadingGroupId", undefined, {
|
|
918
|
+
loadingGroupIds: sortedLoadingGroupIds.join(","),
|
|
919
|
+
snapshotSeqNumber,
|
|
920
|
+
initialSequenceNumber: this.deltaManager.initialSequenceNumber,
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
// If the snapshot is ahead of the last seq number of the delta manager, then catch up before
|
|
924
|
+
// returning the snapshot.
|
|
925
|
+
if (snapshotSeqNumber > this.deltaManager.lastSequenceNumber) {
|
|
926
|
+
// If this is a summarizer client, which is trying to load a group and it finds that there is
|
|
927
|
+
// another snapshot from which the summarizer loaded and it is behind, then just give up as
|
|
928
|
+
// the summarizer state is not up to date.
|
|
929
|
+
// This should be a recoverable scenario and shouldn't happen as we should process the ack first.
|
|
930
|
+
if (this.isSummarizerClient) {
|
|
931
|
+
throw new Error("Summarizer client behind, loaded newer snapshot with loadingGroupId");
|
|
932
|
+
}
|
|
933
|
+
// We want to catchup from sequenceNumber to targetSequenceNumber
|
|
934
|
+
const props = {
|
|
935
|
+
eventName: "GroupIdSnapshotCatchup",
|
|
936
|
+
loadingGroupIds: sortedLoadingGroupIds.join(","),
|
|
937
|
+
targetSequenceNumber: snapshotSeqNumber,
|
|
938
|
+
sequenceNumber: this.deltaManager.lastSequenceNumber, // This is so we reuse some columns in telemetry
|
|
939
|
+
};
|
|
940
|
+
const event = telemetry_utils_1.PerformanceEvent.start(this.mc.logger, {
|
|
941
|
+
...props,
|
|
942
|
+
});
|
|
943
|
+
// If the inbound deltas queue is paused or disconnected, we expect a reconnect and unpause
|
|
944
|
+
// as long as it's not a summarizer client.
|
|
945
|
+
if (this.deltaManager.inbound.paused) {
|
|
946
|
+
props.inboundPaused = this.deltaManager.inbound.paused; // reusing telemetry
|
|
947
|
+
}
|
|
948
|
+
const defP = new core_utils_1.Deferred();
|
|
949
|
+
this.deltaManager.on("op", (message) => {
|
|
950
|
+
if (message.sequenceNumber >= snapshotSeqNumber) {
|
|
951
|
+
defP.resolve(true);
|
|
952
|
+
}
|
|
953
|
+
});
|
|
954
|
+
await defP.promise;
|
|
955
|
+
event.end(props);
|
|
956
|
+
}
|
|
957
|
+
return { snapshotTree: snapshotTreeForPath, sequenceNumber: snapshotSeqNumber };
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* Api to find a snapshot tree inside a bigger snapshot tree based on the path in the pathParts array.
|
|
961
|
+
* @param snapshotTree - snapshot tree to look into.
|
|
962
|
+
* @param pathParts - Part of the path, which we want to extract from the snapshot tree.
|
|
963
|
+
* @param hasIsolatedChannels - whether the channels are present inside ".channels" subtree. Older
|
|
964
|
+
* snapshots will not have trees inside ".channels", so check that.
|
|
965
|
+
* @returns - requested snapshot tree based on the path parts.
|
|
966
|
+
*/
|
|
967
|
+
getSnapshotTreeForPath(snapshotTree, pathParts, hasIsolatedChannels) {
|
|
968
|
+
let childTree = snapshotTree;
|
|
969
|
+
for (const part of pathParts) {
|
|
970
|
+
if (hasIsolatedChannels) {
|
|
971
|
+
childTree = childTree?.trees[runtime_definitions_1.channelsTreeName];
|
|
972
|
+
}
|
|
973
|
+
childTree = childTree?.trees[part];
|
|
974
|
+
}
|
|
975
|
+
return childTree;
|
|
976
|
+
}
|
|
807
977
|
/**
|
|
808
978
|
* Notifies this object about the request made to the container.
|
|
809
979
|
* @param request - Request made to the handler.
|
|
@@ -846,7 +1016,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
846
1016
|
// eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
|
|
847
1017
|
return this.resolveHandle(requestParser.createSubRequest(1));
|
|
848
1018
|
}
|
|
849
|
-
if (id ===
|
|
1019
|
+
if (id === blobManager_js_1.BlobManager.basePath && requestParser.isLeaf(2)) {
|
|
850
1020
|
const blob = await this.blobManager.getBlob(requestParser.pathParts[1]);
|
|
851
1021
|
return blob
|
|
852
1022
|
? {
|
|
@@ -857,15 +1027,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
857
1027
|
: (0, runtime_utils_1.create404Response)(request);
|
|
858
1028
|
}
|
|
859
1029
|
else if (requestParser.pathParts.length > 0) {
|
|
860
|
-
|
|
861
|
-
const requestForChild = !requestParser.isLeaf(1);
|
|
862
|
-
const dataStore = await this.getDataStoreFromRequest(id, request, requestForChild);
|
|
863
|
-
const subRequest = requestParser.createSubRequest(1);
|
|
864
|
-
// We always expect createSubRequest to include a leading slash, but asserting here to protect against
|
|
865
|
-
// unintentionally modifying the url if that changes.
|
|
866
|
-
(0, core_utils_1.assert)(subRequest.url.startsWith("/"), 0x126 /* "Expected createSubRequest url to include a leading slash" */);
|
|
867
|
-
// eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
|
|
868
|
-
return dataStore.request(subRequest);
|
|
1030
|
+
return await this.channelCollection.request(request);
|
|
869
1031
|
}
|
|
870
1032
|
return (0, runtime_utils_1.create404Response)(request);
|
|
871
1033
|
}
|
|
@@ -880,38 +1042,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
880
1042
|
return this.entryPoint;
|
|
881
1043
|
}
|
|
882
1044
|
internalId(maybeAlias) {
|
|
883
|
-
return this.
|
|
884
|
-
}
|
|
885
|
-
async getDataStoreFromRequest(id, request, requestForChild) {
|
|
886
|
-
const headerData = {};
|
|
887
|
-
if (typeof request.headers?.[RuntimeHeaders.wait] === "boolean") {
|
|
888
|
-
headerData.wait = request.headers[RuntimeHeaders.wait];
|
|
889
|
-
}
|
|
890
|
-
if (typeof request.headers?.[RuntimeHeaders.viaHandle] === "boolean") {
|
|
891
|
-
headerData.viaHandle = request.headers[RuntimeHeaders.viaHandle];
|
|
892
|
-
}
|
|
893
|
-
if (typeof request.headers?.[exports.AllowTombstoneRequestHeaderKey] === "boolean") {
|
|
894
|
-
headerData.allowTombstone = request.headers[exports.AllowTombstoneRequestHeaderKey];
|
|
895
|
-
}
|
|
896
|
-
if (typeof request.headers?.[exports.AllowInactiveRequestHeaderKey] === "boolean") {
|
|
897
|
-
headerData.allowInactive = request.headers[exports.AllowInactiveRequestHeaderKey];
|
|
898
|
-
}
|
|
899
|
-
// We allow Tombstone requests for sub-DataStore objects
|
|
900
|
-
if (requestForChild) {
|
|
901
|
-
headerData.allowTombstone = true;
|
|
902
|
-
}
|
|
903
|
-
await this.dataStores.waitIfPendingAlias(id);
|
|
904
|
-
const internalId = this.internalId(id);
|
|
905
|
-
const dataStoreContext = await this.dataStores.getDataStore(internalId, headerData);
|
|
906
|
-
// Remove query params, leading and trailing slashes from the url. This is done to make sure the format is
|
|
907
|
-
// the same as GC nodes id.
|
|
908
|
-
const urlWithoutQuery = (0, gc_1.trimLeadingAndTrailingSlashes)(request.url.split("?")[0]);
|
|
909
|
-
// Get the initial snapshot details which contain the data store package path.
|
|
910
|
-
const details = await dataStoreContext.getInitialSnapshotDetails();
|
|
911
|
-
// Note that this will throw if the data store is inactive or tombstoned and throwing on incorrect usage
|
|
912
|
-
// is configured.
|
|
913
|
-
this.garbageCollector.nodeUpdated(`/${urlWithoutQuery}`, "Loaded", undefined /* timestampMs */, details.pkg, request, headerData);
|
|
914
|
-
return dataStoreContext.realize();
|
|
1045
|
+
return this.channelCollection.internalId(maybeAlias);
|
|
915
1046
|
}
|
|
916
1047
|
/** Adds the container's metadata to the given summary tree. */
|
|
917
1048
|
addMetadataToSummary(summaryTree) {
|
|
@@ -923,37 +1054,36 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
923
1054
|
...this.garbageCollector.getMetadata(),
|
|
924
1055
|
// The last message processed at the time of summary. If there are no new messages, use the message from the
|
|
925
1056
|
// last summary.
|
|
926
|
-
message: (0,
|
|
1057
|
+
message: (0, index_js_1.extractSummaryMetadataMessage)(this.deltaManager.lastMessage) ??
|
|
927
1058
|
this.messageAtLastSummary,
|
|
928
1059
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
929
|
-
|
|
1060
|
+
idCompressorMode: this.idCompressorMode,
|
|
930
1061
|
};
|
|
931
|
-
(0, runtime_utils_1.addBlobToSummary)(summaryTree,
|
|
1062
|
+
(0, runtime_utils_1.addBlobToSummary)(summaryTree, index_js_1.metadataBlobName, JSON.stringify(metadata));
|
|
932
1063
|
}
|
|
933
1064
|
addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext) {
|
|
934
1065
|
this.addMetadataToSummary(summaryTree);
|
|
935
|
-
if (this.
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
(0, runtime_utils_1.addBlobToSummary)(summaryTree, summary_1.idCompressorBlobName, idCompressorState);
|
|
1066
|
+
if (this._idCompressor) {
|
|
1067
|
+
const idCompressorState = JSON.stringify(this._idCompressor.serialize(false));
|
|
1068
|
+
(0, runtime_utils_1.addBlobToSummary)(summaryTree, index_js_1.idCompressorBlobName, idCompressorState);
|
|
939
1069
|
}
|
|
940
1070
|
if (this.remoteMessageProcessor.partialMessages.size > 0) {
|
|
941
1071
|
const content = JSON.stringify([...this.remoteMessageProcessor.partialMessages]);
|
|
942
|
-
(0, runtime_utils_1.addBlobToSummary)(summaryTree,
|
|
1072
|
+
(0, runtime_utils_1.addBlobToSummary)(summaryTree, index_js_1.chunksBlobName, content);
|
|
943
1073
|
}
|
|
944
|
-
const dataStoreAliases = this.
|
|
1074
|
+
const dataStoreAliases = this.channelCollection.aliases;
|
|
945
1075
|
if (dataStoreAliases.size > 0) {
|
|
946
|
-
(0, runtime_utils_1.addBlobToSummary)(summaryTree,
|
|
1076
|
+
(0, runtime_utils_1.addBlobToSummary)(summaryTree, index_js_1.aliasBlobName, JSON.stringify([...dataStoreAliases]));
|
|
947
1077
|
}
|
|
948
1078
|
if (this.summarizerClientElection) {
|
|
949
1079
|
const electedSummarizerContent = JSON.stringify(this.summarizerClientElection?.serialize());
|
|
950
|
-
(0, runtime_utils_1.addBlobToSummary)(summaryTree,
|
|
1080
|
+
(0, runtime_utils_1.addBlobToSummary)(summaryTree, index_js_1.electedSummarizerBlobName, electedSummarizerContent);
|
|
951
1081
|
}
|
|
952
1082
|
const blobManagerSummary = this.blobManager.summarize();
|
|
953
1083
|
// Some storage (like git) doesn't allow empty tree, so we can omit it.
|
|
954
1084
|
// and the blob manager can handle the tree not existing when loading
|
|
955
1085
|
if (Object.keys(blobManagerSummary.summary.tree).length > 0) {
|
|
956
|
-
(0, runtime_utils_1.
|
|
1086
|
+
(0, runtime_utils_1.addSummarizeResultToSummary)(summaryTree, index_js_1.blobsTreeName, blobManagerSummary);
|
|
957
1087
|
}
|
|
958
1088
|
const gcSummary = this.garbageCollector.summarize(fullTree, trackState, telemetryContext);
|
|
959
1089
|
if (gcSummary !== undefined) {
|
|
@@ -993,7 +1123,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
993
1123
|
// in their own batches before the originating batch is sent.
|
|
994
1124
|
// Therefore, receiving them while attempting to send the originating batch
|
|
995
1125
|
// does not mean that the container is making any progress.
|
|
996
|
-
if (message?.type !==
|
|
1126
|
+
if (message?.type !== messageTypes_js_1.ContainerMessageType.ChunkedOp) {
|
|
997
1127
|
this.consecutiveReconnects = 0;
|
|
998
1128
|
}
|
|
999
1129
|
}
|
|
@@ -1039,21 +1169,20 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1039
1169
|
// Need to parse from string for back-compat
|
|
1040
1170
|
const opContents = this.parseLocalOpContent(serializedOpContent);
|
|
1041
1171
|
switch (opContents.type) {
|
|
1042
|
-
case
|
|
1043
|
-
|
|
1044
|
-
case
|
|
1045
|
-
return this.
|
|
1046
|
-
case
|
|
1047
|
-
(0, core_utils_1.assert)(this.
|
|
1172
|
+
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp:
|
|
1173
|
+
case messageTypes_js_1.ContainerMessageType.Attach:
|
|
1174
|
+
case messageTypes_js_1.ContainerMessageType.Alias:
|
|
1175
|
+
return this.channelCollection.applyStashedOp(opContents);
|
|
1176
|
+
case messageTypes_js_1.ContainerMessageType.IdAllocation:
|
|
1177
|
+
(0, core_utils_1.assert)(this.idCompressorMode !== "off", 0x8f1 /* ID compressor should be in use */);
|
|
1048
1178
|
return;
|
|
1049
|
-
case
|
|
1050
|
-
case messageTypes_1.ContainerMessageType.BlobAttach:
|
|
1179
|
+
case messageTypes_js_1.ContainerMessageType.BlobAttach:
|
|
1051
1180
|
return;
|
|
1052
|
-
case
|
|
1181
|
+
case messageTypes_js_1.ContainerMessageType.ChunkedOp:
|
|
1053
1182
|
throw new Error("chunkedOp not expected here");
|
|
1054
|
-
case
|
|
1183
|
+
case messageTypes_js_1.ContainerMessageType.Rejoin:
|
|
1055
1184
|
throw new Error("rejoin not expected here");
|
|
1056
|
-
case
|
|
1185
|
+
case messageTypes_js_1.ContainerMessageType.GC:
|
|
1057
1186
|
// GC op is only sent in summarizer which should never have stashed ops.
|
|
1058
1187
|
throw new telemetry_utils_1.LoggingError("GC op not expected to be stashed in summarizer");
|
|
1059
1188
|
default: {
|
|
@@ -1077,6 +1206,20 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1077
1206
|
}
|
|
1078
1207
|
}
|
|
1079
1208
|
setConnectionState(connected, clientId) {
|
|
1209
|
+
if (connected && this.idCompressorMode === "delayed" && !this.compressorLoadInitiated) {
|
|
1210
|
+
this.compressorLoadInitiated = true;
|
|
1211
|
+
this.createIdCompressor()
|
|
1212
|
+
.then((compressor) => {
|
|
1213
|
+
this._idCompressor = compressor;
|
|
1214
|
+
for (const range of this.pendingIdCompressorOps) {
|
|
1215
|
+
this._idCompressor.finalizeCreationRange(range);
|
|
1216
|
+
}
|
|
1217
|
+
this.pendingIdCompressorOps = [];
|
|
1218
|
+
})
|
|
1219
|
+
.catch((error) => {
|
|
1220
|
+
this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1080
1223
|
if (connected === false && this.delayConnectClientId !== undefined) {
|
|
1081
1224
|
this.delayConnectClientId = undefined;
|
|
1082
1225
|
this.mc.logger.sendTelemetryEvent({
|
|
@@ -1140,7 +1283,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1140
1283
|
if (changeOfState) {
|
|
1141
1284
|
this.replayPendingStates();
|
|
1142
1285
|
}
|
|
1143
|
-
this.
|
|
1286
|
+
this.channelCollection.setConnectionState(connected, clientId);
|
|
1144
1287
|
this.garbageCollector.setConnectionState(connected, clientId);
|
|
1145
1288
|
(0, telemetry_utils_1.raiseConnectedEvent)(this.mc.logger, this, connected, clientId);
|
|
1146
1289
|
}
|
|
@@ -1190,7 +1333,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1190
1333
|
let localOpMetadata;
|
|
1191
1334
|
if (local &&
|
|
1192
1335
|
messageWithContext.modernRuntimeMessage &&
|
|
1193
|
-
message.type !==
|
|
1336
|
+
message.type !== messageTypes_js_1.ContainerMessageType.ChunkedOp) {
|
|
1194
1337
|
localOpMetadata = this.pendingStateManager.processPendingLocalMessage(messageWithContext.message);
|
|
1195
1338
|
}
|
|
1196
1339
|
// If there are no more pending messages after processing a local message,
|
|
@@ -1222,31 +1365,36 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1222
1365
|
// TODO: destructure message and modernRuntimeMessage once using typescript 5.2.2+
|
|
1223
1366
|
const { local } = messageWithContext;
|
|
1224
1367
|
switch (messageWithContext.message.type) {
|
|
1225
|
-
case
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
this.dataStores.processAliasMessage(messageWithContext.message, localOpMetadata, local);
|
|
1230
|
-
break;
|
|
1231
|
-
case messageTypes_1.ContainerMessageType.FluidDataStoreOp:
|
|
1232
|
-
this.dataStores.processFluidDataStoreOp(messageWithContext.message, local, localOpMetadata, (from, to) => this.garbageCollector.addedOutboundReference(from, to));
|
|
1368
|
+
case messageTypes_js_1.ContainerMessageType.Attach:
|
|
1369
|
+
case messageTypes_js_1.ContainerMessageType.Alias:
|
|
1370
|
+
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp:
|
|
1371
|
+
this.channelCollection.process(messageWithContext.message, local, localOpMetadata, (from, to) => this.garbageCollector.addedOutboundReference(from, to));
|
|
1233
1372
|
break;
|
|
1234
|
-
case
|
|
1373
|
+
case messageTypes_js_1.ContainerMessageType.BlobAttach:
|
|
1235
1374
|
this.blobManager.processBlobAttachOp(messageWithContext.message, local);
|
|
1236
1375
|
break;
|
|
1237
|
-
case
|
|
1238
|
-
(0, core_utils_1.assert)(this.idCompressor !== undefined, 0x67c /* IdCompressor should be defined if enabled */);
|
|
1376
|
+
case messageTypes_js_1.ContainerMessageType.IdAllocation:
|
|
1239
1377
|
// Don't re-finalize the range if we're processing a "savedOp" in
|
|
1240
1378
|
// stashed ops flow. The compressor is stashed with these ops already processed.
|
|
1241
|
-
|
|
1242
|
-
|
|
1379
|
+
// That said, in idCompressorMode === "delayed", we might not serialize ID compressor, and
|
|
1380
|
+
// thus we need to process all the ops.
|
|
1381
|
+
if (!(this.skipSavedCompressorOps &&
|
|
1382
|
+
messageWithContext.message.metadata?.savedOp ===
|
|
1383
|
+
true)) {
|
|
1384
|
+
const range = messageWithContext.message.contents;
|
|
1385
|
+
if (this._idCompressor === undefined) {
|
|
1386
|
+
this.pendingIdCompressorOps.push(range);
|
|
1387
|
+
}
|
|
1388
|
+
else {
|
|
1389
|
+
this._idCompressor.finalizeCreationRange(range);
|
|
1390
|
+
}
|
|
1243
1391
|
}
|
|
1244
1392
|
break;
|
|
1245
|
-
case
|
|
1393
|
+
case messageTypes_js_1.ContainerMessageType.GC:
|
|
1246
1394
|
this.garbageCollector.processMessage(messageWithContext.message, local);
|
|
1247
1395
|
break;
|
|
1248
|
-
case
|
|
1249
|
-
case
|
|
1396
|
+
case messageTypes_js_1.ContainerMessageType.ChunkedOp:
|
|
1397
|
+
case messageTypes_js_1.ContainerMessageType.Rejoin:
|
|
1250
1398
|
break;
|
|
1251
1399
|
default: {
|
|
1252
1400
|
// If we didn't necessarily expect a runtime message type, then no worries - just return
|
|
@@ -1326,7 +1474,15 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1326
1474
|
this.emit("signal", transformed, local);
|
|
1327
1475
|
return;
|
|
1328
1476
|
}
|
|
1329
|
-
|
|
1477
|
+
// Due to a mismatch between different layers in terms of
|
|
1478
|
+
// what is the interface of passing signals, we need to adjust
|
|
1479
|
+
// the signal envelope before sending it to the datastores to be processed
|
|
1480
|
+
const envelope2 = {
|
|
1481
|
+
address: envelope.address,
|
|
1482
|
+
contents: transformed.content,
|
|
1483
|
+
};
|
|
1484
|
+
transformed.content = envelope2;
|
|
1485
|
+
this.channelCollection.processSignal(transformed, local);
|
|
1330
1486
|
}
|
|
1331
1487
|
/**
|
|
1332
1488
|
* Flush the pending ops manually.
|
|
@@ -1390,9 +1546,17 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1390
1546
|
* Returns undefined if no data store has been assigned the given alias.
|
|
1391
1547
|
*/
|
|
1392
1548
|
async getAliasedDataStoreEntryPoint(alias) {
|
|
1393
|
-
|
|
1549
|
+
// Back-comapatibility:
|
|
1550
|
+
// There are old files that were created without using data store aliasing feature, but
|
|
1551
|
+
// used createRoot*DataStore*() (already removed) API. Such data stores will have isRoot = true,
|
|
1552
|
+
// and internalID provided by user. The expectation is that such files behave as new files, where
|
|
1553
|
+
// same data store instances created using aliasing feature.
|
|
1554
|
+
// Please also see note on name collisions in DataStores.createDataStoreId()
|
|
1555
|
+
await this.channelCollection.waitIfPendingAlias(alias);
|
|
1394
1556
|
const internalId = this.internalId(alias);
|
|
1395
|
-
const context = await this.
|
|
1557
|
+
const context = await this.channelCollection.getDataStoreIfAvailable(internalId, {
|
|
1558
|
+
wait: false,
|
|
1559
|
+
});
|
|
1396
1560
|
// If the data store is not available or not an alias, return undefined.
|
|
1397
1561
|
if (context === undefined || !(await context.isRoot())) {
|
|
1398
1562
|
return undefined;
|
|
@@ -1404,28 +1568,20 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1404
1568
|
this.garbageCollector.nodeUpdated(`/${internalId}`, "Loaded", undefined /* timestampMs */, context.packagePath);
|
|
1405
1569
|
return channel.entryPoint;
|
|
1406
1570
|
}
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
throw new telemetry_utils_1.UsageError(`Id cannot contain slashes: '${rootDataStoreId}'`);
|
|
1410
|
-
}
|
|
1411
|
-
return this.dataStores.createDetachedDataStoreCore(pkg, true, rootDataStoreId);
|
|
1412
|
-
}
|
|
1413
|
-
createDetachedDataStore(pkg, groupId) {
|
|
1414
|
-
return this.dataStores.createDetachedDataStoreCore(pkg, false, undefined, groupId);
|
|
1571
|
+
createDetachedDataStore(pkg, loadingGroupId) {
|
|
1572
|
+
return this.channelCollection.createDetachedDataStore(pkg, loadingGroupId);
|
|
1415
1573
|
}
|
|
1416
|
-
async createDataStore(pkg,
|
|
1417
|
-
const
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
.realize(), id, this, this.dataStores, this.mc.logger);
|
|
1574
|
+
async createDataStore(pkg, loadingGroupId) {
|
|
1575
|
+
const context = this.channelCollection.createDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], undefined, // props
|
|
1576
|
+
loadingGroupId);
|
|
1577
|
+
return (0, dataStore_js_1.channelToDataStore)(await context.realize(), context.id, this.channelCollection, this.mc.logger);
|
|
1421
1578
|
}
|
|
1422
1579
|
/**
|
|
1423
1580
|
* @deprecated 0.16 Issue #1537, #3631
|
|
1424
1581
|
*/
|
|
1425
|
-
async _createDataStoreWithProps(pkg, props
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
.realize(), id, this, this.dataStores, this.mc.logger);
|
|
1582
|
+
async _createDataStoreWithProps(pkg, props) {
|
|
1583
|
+
const context = this.channelCollection.createDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], props);
|
|
1584
|
+
return (0, dataStore_js_1.channelToDataStore)(await context.realize(), context.id, this.channelCollection, this.mc.logger);
|
|
1429
1585
|
}
|
|
1430
1586
|
canSendOps() {
|
|
1431
1587
|
// Note that the real (non-proxy) delta manager is needed here to get the readonly info. This is because
|
|
@@ -1455,21 +1611,21 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1455
1611
|
// Certain container runtime messages should not mark the container dirty such as the old built-in
|
|
1456
1612
|
// AgentScheduler and Garbage collector messages.
|
|
1457
1613
|
switch (type) {
|
|
1458
|
-
case
|
|
1614
|
+
case messageTypes_js_1.ContainerMessageType.Attach: {
|
|
1459
1615
|
const attachMessage = contents;
|
|
1460
1616
|
if (attachMessage.id === exports.agentSchedulerId) {
|
|
1461
1617
|
return false;
|
|
1462
1618
|
}
|
|
1463
1619
|
break;
|
|
1464
1620
|
}
|
|
1465
|
-
case
|
|
1621
|
+
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp: {
|
|
1466
1622
|
const envelope = contents;
|
|
1467
1623
|
if (envelope.address === exports.agentSchedulerId) {
|
|
1468
1624
|
return false;
|
|
1469
1625
|
}
|
|
1470
1626
|
break;
|
|
1471
1627
|
}
|
|
1472
|
-
case
|
|
1628
|
+
case messageTypes_js_1.ContainerMessageType.GC: {
|
|
1473
1629
|
return false;
|
|
1474
1630
|
}
|
|
1475
1631
|
default:
|
|
@@ -1503,16 +1659,6 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1503
1659
|
const envelope = this.createNewSignalEnvelope(undefined /* address */, type, content);
|
|
1504
1660
|
return this.submitSignalFn(envelope, targetClientId);
|
|
1505
1661
|
}
|
|
1506
|
-
/**
|
|
1507
|
-
* Submits the signal to be sent to other clients.
|
|
1508
|
-
* @param type - Type of the signal.
|
|
1509
|
-
* @param content - Content of the signal.
|
|
1510
|
-
* @param targetClientId - When specified, the signal is only sent to the provided client id.
|
|
1511
|
-
*/
|
|
1512
|
-
submitDataStoreSignal(address, type, content, targetClientId) {
|
|
1513
|
-
const envelope = this.createNewSignalEnvelope(address, type, content);
|
|
1514
|
-
return this.submitSignalFn(envelope, targetClientId);
|
|
1515
|
-
}
|
|
1516
1662
|
setAttachState(attachState) {
|
|
1517
1663
|
if (attachState === container_definitions_1.AttachState.Attaching) {
|
|
1518
1664
|
(0, core_utils_1.assert)(this.attachState === container_definitions_1.AttachState.Attaching, 0x12d /* "Container Context should already be in attaching state" */);
|
|
@@ -1524,7 +1670,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1524
1670
|
if (attachState === container_definitions_1.AttachState.Attached && !this.hasPendingMessages()) {
|
|
1525
1671
|
this.updateDocumentDirtyState(false);
|
|
1526
1672
|
}
|
|
1527
|
-
this.
|
|
1673
|
+
this.channelCollection.setAttachState(attachState);
|
|
1528
1674
|
}
|
|
1529
1675
|
/**
|
|
1530
1676
|
* Create a summary. Used when attaching or serializing a detached container.
|
|
@@ -1539,20 +1685,20 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1539
1685
|
this.blobManager.setRedirectTable(blobRedirectTable);
|
|
1540
1686
|
}
|
|
1541
1687
|
// We can finalize any allocated IDs since we're the only client
|
|
1542
|
-
const idRange = this.
|
|
1688
|
+
const idRange = this._idCompressor?.takeNextCreationRange();
|
|
1543
1689
|
if (idRange !== undefined) {
|
|
1544
|
-
this.
|
|
1690
|
+
this._idCompressor?.finalizeCreationRange(idRange);
|
|
1545
1691
|
}
|
|
1546
|
-
const summarizeResult = this.
|
|
1692
|
+
const summarizeResult = this.channelCollection.getAttachSummary(telemetryContext);
|
|
1547
1693
|
// Wrap data store summaries in .channels subtree.
|
|
1548
|
-
(0,
|
|
1694
|
+
(0, index_js_1.wrapSummaryInChannelsTree)(summarizeResult);
|
|
1549
1695
|
this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
|
|
1550
1696
|
return summarizeResult.summary;
|
|
1551
1697
|
}
|
|
1552
1698
|
async summarizeInternal(fullTree, trackState, telemetryContext) {
|
|
1553
|
-
const summarizeResult = await this.
|
|
1699
|
+
const summarizeResult = await this.channelCollection.summarize(fullTree, trackState, telemetryContext);
|
|
1554
1700
|
// Wrap data store summaries in .channels subtree.
|
|
1555
|
-
(0,
|
|
1701
|
+
(0, index_js_1.wrapSummaryInChannelsTree)(summarizeResult);
|
|
1556
1702
|
const pathPartsForChildren = [runtime_definitions_1.channelsTreeName];
|
|
1557
1703
|
this.addContainerStateToSummary(summarizeResult, fullTree, trackState, telemetryContext);
|
|
1558
1704
|
return {
|
|
@@ -1598,10 +1744,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1598
1744
|
* @see IGarbageCollectionRuntime.updateStateBeforeGC
|
|
1599
1745
|
*/
|
|
1600
1746
|
async updateStateBeforeGC() {
|
|
1601
|
-
return this.
|
|
1747
|
+
return this.channelCollection.updateStateBeforeGC();
|
|
1602
1748
|
}
|
|
1603
1749
|
async getGCDataInternal(fullGC) {
|
|
1604
|
-
return this.
|
|
1750
|
+
return this.channelCollection.getGCData(fullGC);
|
|
1605
1751
|
}
|
|
1606
1752
|
/**
|
|
1607
1753
|
* Generates and returns the GC data for this container.
|
|
@@ -1627,22 +1773,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1627
1773
|
// always referenced, so the used routes is only self-route (empty string).
|
|
1628
1774
|
this.summarizerNode.updateUsedRoutes([""]);
|
|
1629
1775
|
const { dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(usedRoutes);
|
|
1630
|
-
this.
|
|
1631
|
-
}
|
|
1632
|
-
/**
|
|
1633
|
-
* This is called to update objects whose routes are unused.
|
|
1634
|
-
* @param unusedRoutes - Data store and attachment blob routes that are unused in this Container.
|
|
1635
|
-
*/
|
|
1636
|
-
updateUnusedRoutes(unusedRoutes) {
|
|
1637
|
-
const { blobManagerRoutes, dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(unusedRoutes);
|
|
1638
|
-
this.blobManager.updateUnusedRoutes(blobManagerRoutes);
|
|
1639
|
-
this.dataStores.updateUnusedRoutes(dataStoreRoutes);
|
|
1640
|
-
}
|
|
1641
|
-
/**
|
|
1642
|
-
* @deprecated Replaced by deleteSweepReadyNodes.
|
|
1643
|
-
*/
|
|
1644
|
-
deleteUnusedNodes(unusedRoutes) {
|
|
1645
|
-
throw new Error("deleteUnusedRoutes should not be called");
|
|
1776
|
+
this.channelCollection.updateUsedRoutes(dataStoreRoutes);
|
|
1646
1777
|
}
|
|
1647
1778
|
/**
|
|
1648
1779
|
* After GC has run and identified nodes that are sweep ready, this is called to delete the sweep ready nodes.
|
|
@@ -1651,7 +1782,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1651
1782
|
*/
|
|
1652
1783
|
deleteSweepReadyNodes(sweepReadyRoutes) {
|
|
1653
1784
|
const { dataStoreRoutes, blobManagerRoutes } = this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
|
|
1654
|
-
const deletedRoutes = this.
|
|
1785
|
+
const deletedRoutes = this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes);
|
|
1655
1786
|
return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
|
|
1656
1787
|
}
|
|
1657
1788
|
/**
|
|
@@ -1665,7 +1796,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1665
1796
|
updateTombstonedRoutes(tombstonedRoutes) {
|
|
1666
1797
|
const { blobManagerRoutes, dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(tombstonedRoutes);
|
|
1667
1798
|
this.blobManager.updateTombstonedRoutes(blobManagerRoutes);
|
|
1668
|
-
this.
|
|
1799
|
+
this.channelCollection.updateTombstonedRoutes(dataStoreRoutes);
|
|
1669
1800
|
}
|
|
1670
1801
|
/**
|
|
1671
1802
|
* Returns a server generated referenced timestamp to be used to track unreferenced nodes by GC.
|
|
@@ -1681,9 +1812,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1681
1812
|
*/
|
|
1682
1813
|
getNodeType(nodePath) {
|
|
1683
1814
|
if (this.isBlobPath(nodePath)) {
|
|
1684
|
-
return
|
|
1815
|
+
return index_js_2.GCNodeType.Blob;
|
|
1685
1816
|
}
|
|
1686
|
-
return this.
|
|
1817
|
+
return this.channelCollection.getGCNodeType(nodePath) ?? index_js_2.GCNodeType.Other;
|
|
1687
1818
|
}
|
|
1688
1819
|
/**
|
|
1689
1820
|
* Called by GC to retrieve the package path of the node with the given path. The node should belong to a
|
|
@@ -1693,14 +1824,14 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1693
1824
|
// GC uses "/" when adding "root" references, e.g. for Aliasing or as part of Tombstone Auto-Recovery.
|
|
1694
1825
|
// These have no package path so return a special value.
|
|
1695
1826
|
if (nodePath === "/") {
|
|
1696
|
-
return ["
|
|
1827
|
+
return ["_gcRoot"];
|
|
1697
1828
|
}
|
|
1698
1829
|
switch (this.getNodeType(nodePath)) {
|
|
1699
|
-
case
|
|
1700
|
-
return [
|
|
1701
|
-
case
|
|
1702
|
-
case
|
|
1703
|
-
return this.
|
|
1830
|
+
case index_js_2.GCNodeType.Blob:
|
|
1831
|
+
return [blobManager_js_1.BlobManager.basePath];
|
|
1832
|
+
case index_js_2.GCNodeType.DataStore:
|
|
1833
|
+
case index_js_2.GCNodeType.SubDataStore:
|
|
1834
|
+
return this.channelCollection.getDataStorePackagePath(nodePath);
|
|
1704
1835
|
default:
|
|
1705
1836
|
(0, core_utils_1.assert)(false, 0x2de /* "Package path requested for unsupported node type." */);
|
|
1706
1837
|
}
|
|
@@ -1710,7 +1841,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1710
1841
|
*/
|
|
1711
1842
|
isBlobPath(path) {
|
|
1712
1843
|
const pathParts = path.split("/");
|
|
1713
|
-
if (pathParts.length < 2 || pathParts[1] !==
|
|
1844
|
+
if (pathParts.length < 2 || pathParts[1] !== blobManager_js_1.BlobManager.basePath) {
|
|
1714
1845
|
return false;
|
|
1715
1846
|
}
|
|
1716
1847
|
return true;
|
|
@@ -1759,7 +1890,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1759
1890
|
* @param options - options controlling how the summary is generated or submitted
|
|
1760
1891
|
*/
|
|
1761
1892
|
async submitSummary(options) {
|
|
1762
|
-
const { fullTree = false, finalAttempt = false, refreshLatestAck, summaryLogger } = options;
|
|
1893
|
+
const { fullTree = false, finalAttempt = false, refreshLatestAck, summaryLogger, latestSummaryRefSeqNum, } = options;
|
|
1763
1894
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
1764
1895
|
// use it for all events logged during this summary.
|
|
1765
1896
|
const summaryNumber = this.nextSummaryNumber;
|
|
@@ -1812,6 +1943,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1812
1943
|
}
|
|
1813
1944
|
}
|
|
1814
1945
|
const shouldPauseInboundSignal = this.mc.config.getBoolean("Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause") !== true;
|
|
1946
|
+
const shouldValidatePreSummaryState = this.mc.config.getBoolean("Fluid.ContainerRuntime.SubmitSummary.shouldValidatePreSummaryState") === true;
|
|
1815
1947
|
let summaryRefSeqNum;
|
|
1816
1948
|
try {
|
|
1817
1949
|
await this.deltaManager.inbound.pause();
|
|
@@ -1822,7 +1954,25 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1822
1954
|
const minimumSequenceNumber = this.deltaManager.minimumSequenceNumber;
|
|
1823
1955
|
const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
|
|
1824
1956
|
const lastAck = this.summaryCollection.latestAck;
|
|
1825
|
-
this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger);
|
|
1957
|
+
const startSummaryResult = this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger, latestSummaryRefSeqNum);
|
|
1958
|
+
if (startSummaryResult.invalidNodes > 0 ||
|
|
1959
|
+
startSummaryResult.mismatchNumbers.size > 0) {
|
|
1960
|
+
summaryLogger.sendErrorEvent({
|
|
1961
|
+
eventName: "LatestSummaryRefSeqNumMismatch",
|
|
1962
|
+
details: {
|
|
1963
|
+
...startSummaryResult,
|
|
1964
|
+
mismatchNumbers: Array.from(startSummaryResult.mismatchNumbers),
|
|
1965
|
+
},
|
|
1966
|
+
});
|
|
1967
|
+
if (shouldValidatePreSummaryState && !finalAttempt) {
|
|
1968
|
+
return {
|
|
1969
|
+
stage: "base",
|
|
1970
|
+
referenceSequenceNumber: summaryRefSeqNum,
|
|
1971
|
+
minimumSequenceNumber,
|
|
1972
|
+
error: `Summarizer node state inconsistent with summarizer state.`,
|
|
1973
|
+
};
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1826
1976
|
// Helper function to check whether we should still continue between each async step.
|
|
1827
1977
|
const checkContinue = () => {
|
|
1828
1978
|
// Do not check for loss of connectivity directly! Instead leave it up to
|
|
@@ -1892,7 +2042,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1892
2042
|
const validateResult = this.summarizerNode.validateSummary();
|
|
1893
2043
|
if (!validateResult.success) {
|
|
1894
2044
|
const { success, ...loggingProps } = validateResult;
|
|
1895
|
-
const error = new
|
|
2045
|
+
const error = new index_js_1.RetriableSummaryError(validateResult.reason, validateResult.retryAfterSeconds, { ...loggingProps });
|
|
1896
2046
|
return {
|
|
1897
2047
|
stage: "base",
|
|
1898
2048
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
@@ -1918,8 +2068,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1918
2068
|
? (0, runtime_utils_1.calculateStats)(summaryTree.tree[runtime_definitions_1.gcTreeKey])
|
|
1919
2069
|
: undefined;
|
|
1920
2070
|
const summaryStats = {
|
|
1921
|
-
dataStoreCount: this.
|
|
1922
|
-
summarizedDataStoreCount: this.
|
|
2071
|
+
dataStoreCount: this.channelCollection.size,
|
|
2072
|
+
summarizedDataStoreCount: this.channelCollection.size - handleCount,
|
|
1923
2073
|
gcStateUpdatedDataStoreCount: this.garbageCollector.updatedDSCountSinceLastSummary,
|
|
1924
2074
|
gcBlobNodeCount: gcSummaryTreeStats?.blobNodeCount,
|
|
1925
2075
|
gcTotalBlobsSize: gcSummaryTreeStats?.totalBlobSize,
|
|
@@ -2039,7 +2189,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2039
2189
|
// based on telemetry while we decide on a stable number.
|
|
2040
2190
|
const retryDelayMs = this.mc.config.getNumber("Fluid.Summarizer.PendingOpsRetryDelayMs") ??
|
|
2041
2191
|
exports.defaultPendingOpsRetryDelayMs;
|
|
2042
|
-
const error = new
|
|
2192
|
+
const error = new index_js_1.RetriableSummaryError("PendingOpsWhileSummarizing", retryDelayMs / 1000, {
|
|
2043
2193
|
count: this.pendingMessagesCount,
|
|
2044
2194
|
beforeGenerate: beforeSummaryGeneration,
|
|
2045
2195
|
});
|
|
@@ -2073,48 +2223,29 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2073
2223
|
this.emit(dirty ? "dirty" : "saved");
|
|
2074
2224
|
}
|
|
2075
2225
|
}
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
address: id,
|
|
2079
|
-
contents,
|
|
2080
|
-
};
|
|
2081
|
-
this.submit({ type: messageTypes_1.ContainerMessageType.FluidDataStoreOp, contents: envelope }, localOpMetadata);
|
|
2082
|
-
}
|
|
2083
|
-
submitDataStoreAliasOp(contents, localOpMetadata) {
|
|
2084
|
-
const aliasMessage = contents;
|
|
2085
|
-
if (!(0, dataStore_1.isDataStoreAliasMessage)(aliasMessage)) {
|
|
2086
|
-
throw new telemetry_utils_1.UsageError("malformedDataStoreAliasMessage");
|
|
2087
|
-
}
|
|
2088
|
-
this.submit({ type: messageTypes_1.ContainerMessageType.Alias, contents }, localOpMetadata);
|
|
2226
|
+
submitMessage(type, contents, localOpMetadata = undefined) {
|
|
2227
|
+
this.submit({ type, contents }, localOpMetadata);
|
|
2089
2228
|
}
|
|
2090
2229
|
async uploadBlob(blob, signal) {
|
|
2091
2230
|
this.verifyNotClosed();
|
|
2092
2231
|
return this.blobManager.createBlob(blob, signal);
|
|
2093
2232
|
}
|
|
2094
|
-
|
|
2095
|
-
if (
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
if (
|
|
2099
|
-
(0, core_utils_1.assert)(this.idCompressor !== undefined, 0x67d /* IdCompressor should be defined if enabled */);
|
|
2100
|
-
idRange = this.idCompressor.takeNextCreationRange();
|
|
2101
|
-
// Don't include the idRange if there weren't any Ids allocated
|
|
2102
|
-
idRange = idRange?.ids !== undefined ? idRange : undefined;
|
|
2103
|
-
}
|
|
2104
|
-
if (idRange !== undefined) {
|
|
2233
|
+
submitIdAllocationOpIfNeeded() {
|
|
2234
|
+
if (this._idCompressor) {
|
|
2235
|
+
const idRange = this._idCompressor.takeNextCreationRange();
|
|
2236
|
+
// Don't include the idRange if there weren't any Ids allocated
|
|
2237
|
+
if (idRange?.ids !== undefined) {
|
|
2105
2238
|
const idAllocationMessage = {
|
|
2106
|
-
type:
|
|
2239
|
+
type: messageTypes_js_1.ContainerMessageType.IdAllocation,
|
|
2107
2240
|
contents: idRange,
|
|
2108
2241
|
};
|
|
2109
|
-
idAllocationBatchMessage = {
|
|
2242
|
+
const idAllocationBatchMessage = {
|
|
2110
2243
|
contents: JSON.stringify(idAllocationMessage),
|
|
2111
2244
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2112
2245
|
metadata: undefined,
|
|
2113
2246
|
localOpMetadata: undefined,
|
|
2114
|
-
type:
|
|
2247
|
+
type: messageTypes_js_1.ContainerMessageType.IdAllocation,
|
|
2115
2248
|
};
|
|
2116
|
-
}
|
|
2117
|
-
if (idAllocationBatchMessage !== undefined) {
|
|
2118
2249
|
this.outbox.submitIdAllocation(idAllocationBatchMessage);
|
|
2119
2250
|
}
|
|
2120
2251
|
}
|
|
@@ -2142,42 +2273,47 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2142
2273
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2143
2274
|
};
|
|
2144
2275
|
try {
|
|
2145
|
-
//
|
|
2146
|
-
// the
|
|
2147
|
-
// op
|
|
2148
|
-
//
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
// Is it safe:
|
|
2152
|
-
// Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
|
|
2153
|
-
// They become visible only when aliased, or handle to some sub-element of newly created datastore
|
|
2154
|
-
// is stored in some DDS, i.e. only after some other op.
|
|
2155
|
-
// Why:
|
|
2156
|
-
// Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
|
|
2157
|
-
// stores are created, causing issues like relay service throttling (too many ops) and catastrophic
|
|
2158
|
-
// failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
|
|
2159
|
-
// these issues.
|
|
2160
|
-
// Cons:
|
|
2161
|
-
// 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
|
|
2162
|
-
// This change creates new possibility of a lot of newly created data stores never being referenced
|
|
2163
|
-
// because client died before it had a change to submit the rest of the ops. This will create more
|
|
2164
|
-
// garbage that needs to be collected leveraging GC (Garbage Collection) feature.
|
|
2165
|
-
// 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
|
|
2166
|
-
// today as rollback can't undo creation of data store. To some extent not sending them is a bigger
|
|
2167
|
-
// issue than sending.
|
|
2168
|
-
// Please note that this does not change file format, so it can be disabled in the future if this
|
|
2169
|
-
// optimization no longer makes sense (for example, batch compression may make it less appealing).
|
|
2170
|
-
if (this.currentlyBatching() &&
|
|
2171
|
-
type === messageTypes_1.ContainerMessageType.Attach &&
|
|
2172
|
-
this.disableAttachReorder !== true) {
|
|
2173
|
-
this.outbox.submitAttach(message);
|
|
2174
|
-
}
|
|
2175
|
-
else if (type === messageTypes_1.ContainerMessageType.BlobAttach) {
|
|
2176
|
-
// BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
|
|
2177
|
-
this.outbox.submitBlobAttach(message);
|
|
2276
|
+
// If `message` is an allocation op, then we are in the resubmit path and we must redirect the allocation
|
|
2277
|
+
// op into the correct batch to avoid ranges being finalized out of order.
|
|
2278
|
+
// Otherwise, submit an IdAllocation op if any IDs have been generated since the last op was submitted, as
|
|
2279
|
+
// any of the other op types may contain those IDs and thus depend on the allocation op being sent first.
|
|
2280
|
+
if (type === messageTypes_js_1.ContainerMessageType.IdAllocation) {
|
|
2281
|
+
this.outbox.submitIdAllocation(message);
|
|
2178
2282
|
}
|
|
2179
2283
|
else {
|
|
2180
|
-
this.
|
|
2284
|
+
this.submitIdAllocationOpIfNeeded();
|
|
2285
|
+
// If this is attach message for new data store, and we are in a batch, send this op out of order
|
|
2286
|
+
// Is it safe:
|
|
2287
|
+
// Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
|
|
2288
|
+
// They become visible only when aliased, or handle to some sub-element of newly created datastore
|
|
2289
|
+
// is stored in some DDS, i.e. only after some other op.
|
|
2290
|
+
// Why:
|
|
2291
|
+
// Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
|
|
2292
|
+
// stores are created, causing issues like relay service throttling (too many ops) and catastrophic
|
|
2293
|
+
// failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
|
|
2294
|
+
// these issues.
|
|
2295
|
+
// Cons:
|
|
2296
|
+
// 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
|
|
2297
|
+
// This change creates new possibility of a lot of newly created data stores never being referenced
|
|
2298
|
+
// because client died before it had a change to submit the rest of the ops. This will create more
|
|
2299
|
+
// garbage that needs to be collected leveraging GC (Garbage Collection) feature.
|
|
2300
|
+
// 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
|
|
2301
|
+
// today as rollback can't undo creation of data store. To some extent not sending them is a bigger
|
|
2302
|
+
// issue than sending.
|
|
2303
|
+
// Please note that this does not change file format, so it can be disabled in the future if this
|
|
2304
|
+
// optimization no longer makes sense (for example, batch compression may make it less appealing).
|
|
2305
|
+
if (this.currentlyBatching() &&
|
|
2306
|
+
type === messageTypes_js_1.ContainerMessageType.Attach &&
|
|
2307
|
+
this.disableAttachReorder !== true) {
|
|
2308
|
+
this.outbox.submitAttach(message);
|
|
2309
|
+
}
|
|
2310
|
+
else if (type === messageTypes_js_1.ContainerMessageType.BlobAttach) {
|
|
2311
|
+
// BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
|
|
2312
|
+
this.outbox.submitBlobAttach(message);
|
|
2313
|
+
}
|
|
2314
|
+
else {
|
|
2315
|
+
this.outbox.submit(message);
|
|
2316
|
+
}
|
|
2181
2317
|
}
|
|
2182
2318
|
if (!this.currentlyBatching()) {
|
|
2183
2319
|
this.flush();
|
|
@@ -2252,7 +2388,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2252
2388
|
if (this.opReentryCallsToReport > 0) {
|
|
2253
2389
|
this.mc.logger.sendTelemetryEvent({ eventName: "OpReentry" },
|
|
2254
2390
|
// We need to capture the call stack in order to inspect the source of this usage pattern
|
|
2255
|
-
(0,
|
|
2391
|
+
(0, index_js_3.getLongStack)(() => new telemetry_utils_1.UsageError(errorMessage)));
|
|
2256
2392
|
this.opReentryCallsToReport--;
|
|
2257
2393
|
}
|
|
2258
2394
|
// Creating ops while processing ops can lead
|
|
@@ -2293,28 +2429,28 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2293
2429
|
* @param localOpMetadata - The local metadata associated with the original message.
|
|
2294
2430
|
*/
|
|
2295
2431
|
reSubmitCore(message, localOpMetadata, opMetadata) {
|
|
2296
|
-
(0, core_utils_1.assert)(!this.isSummarizerClient,
|
|
2432
|
+
(0, core_utils_1.assert)(!this.isSummarizerClient, 0x8f2 /* Summarizer never reconnects so should never resubmit */);
|
|
2297
2433
|
switch (message.type) {
|
|
2298
|
-
case
|
|
2434
|
+
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp:
|
|
2435
|
+
case messageTypes_js_1.ContainerMessageType.Attach:
|
|
2436
|
+
case messageTypes_js_1.ContainerMessageType.Alias:
|
|
2299
2437
|
// For Operations, call resubmitDataStoreOp which will find the right store
|
|
2300
2438
|
// and trigger resubmission on it.
|
|
2301
|
-
this.
|
|
2439
|
+
this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
|
|
2302
2440
|
break;
|
|
2303
|
-
case
|
|
2304
|
-
case messageTypes_1.ContainerMessageType.Alias:
|
|
2305
|
-
case messageTypes_1.ContainerMessageType.IdAllocation: {
|
|
2441
|
+
case messageTypes_js_1.ContainerMessageType.IdAllocation: {
|
|
2306
2442
|
this.submit(message, localOpMetadata);
|
|
2307
2443
|
break;
|
|
2308
2444
|
}
|
|
2309
|
-
case
|
|
2445
|
+
case messageTypes_js_1.ContainerMessageType.ChunkedOp:
|
|
2310
2446
|
throw new Error(`chunkedOp not expected here`);
|
|
2311
|
-
case
|
|
2447
|
+
case messageTypes_js_1.ContainerMessageType.BlobAttach:
|
|
2312
2448
|
this.blobManager.reSubmit(opMetadata);
|
|
2313
2449
|
break;
|
|
2314
|
-
case
|
|
2450
|
+
case messageTypes_js_1.ContainerMessageType.Rejoin:
|
|
2315
2451
|
this.submit(message);
|
|
2316
2452
|
break;
|
|
2317
|
-
case
|
|
2453
|
+
case messageTypes_js_1.ContainerMessageType.GC:
|
|
2318
2454
|
this.submit(message);
|
|
2319
2455
|
break;
|
|
2320
2456
|
default: {
|
|
@@ -2345,10 +2481,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2345
2481
|
// Need to parse from string for back-compat
|
|
2346
2482
|
const { type, contents } = this.parseLocalOpContent(content);
|
|
2347
2483
|
switch (type) {
|
|
2348
|
-
case
|
|
2484
|
+
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp:
|
|
2349
2485
|
// For operations, call rollbackDataStoreOp which will find the right store
|
|
2350
2486
|
// and trigger rollback on it.
|
|
2351
|
-
this.
|
|
2487
|
+
this.channelCollection.rollback(type, contents, localOpMetadata);
|
|
2352
2488
|
break;
|
|
2353
2489
|
default:
|
|
2354
2490
|
// Don't check message.compatDetails because this is for rolling back a local op so the type will be known
|
|
@@ -2433,44 +2569,43 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2433
2569
|
};
|
|
2434
2570
|
});
|
|
2435
2571
|
}
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
}
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
// try to change its value
|
|
2444
|
-
if (!this.imminentClosure) {
|
|
2445
|
-
this.imminentClosure = props?.notifyImminentClosure ?? this.imminentClosure;
|
|
2446
|
-
}
|
|
2447
|
-
const stopBlobAttachingSignal = props?.stopBlobAttachingSignal;
|
|
2448
|
-
if (this._orderSequentiallyCalls !== 0) {
|
|
2449
|
-
throw new telemetry_utils_1.UsageError("can't get state during orderSequentially");
|
|
2450
|
-
}
|
|
2451
|
-
// Flush pending batch.
|
|
2452
|
-
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
2453
|
-
// to close current batch.
|
|
2454
|
-
this.flush();
|
|
2455
|
-
const pendingAttachmentBlobs = this.imminentClosure
|
|
2456
|
-
? await this.blobManager.attachAndGetPendingBlobs(stopBlobAttachingSignal)
|
|
2457
|
-
: undefined;
|
|
2572
|
+
getPendingLocalState(props) {
|
|
2573
|
+
this.verifyNotClosed();
|
|
2574
|
+
if (this._orderSequentiallyCalls !== 0) {
|
|
2575
|
+
throw new telemetry_utils_1.UsageError("can't get state during orderSequentially");
|
|
2576
|
+
}
|
|
2577
|
+
this.imminentClosure || (this.imminentClosure = props?.notifyImminentClosure ?? false);
|
|
2578
|
+
const getSyncState = (pendingAttachmentBlobs) => {
|
|
2458
2579
|
const pending = this.pendingStateManager.getLocalState();
|
|
2459
|
-
if (
|
|
2580
|
+
if (pendingAttachmentBlobs === undefined && !this.hasPendingMessages()) {
|
|
2460
2581
|
return; // no pending state to save
|
|
2461
2582
|
}
|
|
2462
|
-
const pendingIdCompressorState = this.
|
|
2463
|
-
|
|
2583
|
+
const pendingIdCompressorState = this._idCompressor?.serialize(true);
|
|
2584
|
+
return {
|
|
2464
2585
|
pending,
|
|
2465
|
-
pendingAttachmentBlobs,
|
|
2466
2586
|
pendingIdCompressorState,
|
|
2587
|
+
pendingAttachmentBlobs,
|
|
2588
|
+
sessionExpiryTimerStarted: this.garbageCollector.sessionExpiryTimerStarted,
|
|
2467
2589
|
};
|
|
2590
|
+
};
|
|
2591
|
+
const perfEvent = {
|
|
2592
|
+
eventName: "getPendingLocalState",
|
|
2593
|
+
notifyImminentClosure: props?.notifyImminentClosure,
|
|
2594
|
+
};
|
|
2595
|
+
const logAndReturnPendingState = (event, pendingState) => {
|
|
2468
2596
|
event.end({
|
|
2469
|
-
attachmentBlobsSize: Object.keys(pendingAttachmentBlobs ?? {}).length,
|
|
2470
|
-
pendingOpsSize: pending?.pendingStates.length,
|
|
2597
|
+
attachmentBlobsSize: Object.keys(pendingState?.pendingAttachmentBlobs ?? {}).length,
|
|
2598
|
+
pendingOpsSize: pendingState?.pending?.pendingStates.length,
|
|
2471
2599
|
});
|
|
2472
2600
|
return pendingState;
|
|
2473
|
-
}
|
|
2601
|
+
};
|
|
2602
|
+
// Flush pending batch.
|
|
2603
|
+
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
2604
|
+
// to close current batch.
|
|
2605
|
+
this.flush();
|
|
2606
|
+
return props?.notifyImminentClosure === true
|
|
2607
|
+
? telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, perfEvent, async (event) => logAndReturnPendingState(event, getSyncState(await this.blobManager.attachAndGetPendingBlobs(props?.stopBlobAttachingSignal))))
|
|
2608
|
+
: telemetry_utils_1.PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) => logAndReturnPendingState(event, getSyncState()));
|
|
2474
2609
|
}
|
|
2475
2610
|
summarizeOnDemand(options) {
|
|
2476
2611
|
if (this.isSummarizerClient) {
|