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