@fluidframework/container-runtime 2.0.0-dev-rc.2.0.0.246488 → 2.0.0-dev-rc.3.0.0.253463
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/api-report/container-runtime.api.md +109 -55
- package/dist/batchTracker.d.ts +1 -1
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +4 -4
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +33 -25
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +82 -100
- package/dist/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +7 -6
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +110 -77
- package/dist/channelCollection.js.map +1 -1
- package/dist/connectionTelemetry.d.ts +3 -3
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +17 -17
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/container-runtime-alpha.d.ts +263 -41
- package/dist/container-runtime-beta.d.ts +44 -30
- package/dist/container-runtime-public.d.ts +44 -30
- package/dist/container-runtime-untrimmed.d.ts +265 -56
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js +2 -2
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +40 -30
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +376 -255
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +7 -7
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +9 -9
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +74 -74
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +11 -11
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts +1 -1
- 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 +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/deltaScheduler.d.ts +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +6 -6
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/error.d.ts +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +4 -4
- package/dist/error.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +3 -2
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +21 -21
- 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 +4 -5
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +4 -3
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +5 -1
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +21 -12
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +2 -2
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +11 -11
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +2 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +11 -9
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +6 -6
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +1 -1
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +2 -1
- package/dist/gc/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/messageTypes.d.ts +11 -5
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js +4 -0
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +2 -20
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +3 -3
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +3 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +5 -6
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +15 -4
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +62 -63
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +2 -1
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +14 -16
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +12 -4
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +63 -53
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +2 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +19 -24
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +8 -0
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +36 -35
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- 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 +1 -1
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +18 -18
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +24 -24
- package/dist/scheduleManager.js.map +1 -1
- package/dist/storageServiceWithAttachBlobs.d.ts +2 -2
- package/dist/storageServiceWithAttachBlobs.d.ts.map +1 -1
- package/dist/storageServiceWithAttachBlobs.js +2 -2
- package/dist/storageServiceWithAttachBlobs.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +209 -0
- package/dist/summary/documentSchema.d.ts.map +1 -0
- package/dist/summary/documentSchema.js +382 -0
- package/dist/summary/documentSchema.js.map +1 -0
- package/dist/summary/index.d.ts +2 -1
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js +4 -1
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +2 -2
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +8 -7
- 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 +3 -3
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +3 -3
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +16 -16
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +3 -2
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +13 -13
- 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 +1 -1
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summarizerHeuristics.js +2 -2
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +3 -2
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +28 -28
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js +3 -3
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +2 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +14 -14
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +5 -3
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +2 -2
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +7 -7
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +6 -17
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js +8 -8
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +4 -3
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +17 -17
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +1 -1
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +15 -14
- package/dist/summary/summaryManager.js.map +1 -1
- package/lib/batchTracker.d.ts +1 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -2
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +33 -25
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +48 -66
- package/lib/blobManager.js.map +1 -1
- package/lib/channelCollection.d.ts +7 -6
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +47 -14
- package/lib/channelCollection.js.map +1 -1
- package/lib/connectionTelemetry.d.ts +3 -3
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +3 -3
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/container-runtime-alpha.d.ts +263 -41
- package/lib/container-runtime-beta.d.ts +44 -30
- package/lib/container-runtime-public.d.ts +44 -30
- package/lib/container-runtime-untrimmed.d.ts +265 -56
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js +1 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +40 -30
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +224 -101
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +2 -2
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +9 -9
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +8 -8
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +2 -2
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js +1 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/deltaManagerSummarizerProxy.d.ts +1 -1
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/lib/deltaManagerSummarizerProxy.js.map +1 -1
- package/lib/deltaScheduler.d.ts +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +1 -1
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/error.d.ts +1 -1
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js +2 -2
- package/lib/error.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +3 -2
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +6 -6
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts +2 -2
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +4 -5
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +4 -3
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +5 -1
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +10 -2
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts +2 -2
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +2 -2
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +2 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +4 -2
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.js +2 -2
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/lib/gc/index.d.ts +1 -1
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +1 -1
- package/lib/gc/index.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/messageTypes.d.ts +11 -5
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js +4 -0
- package/lib/messageTypes.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +2 -20
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +3 -3
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js +2 -2
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +2 -3
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts +15 -4
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +61 -62
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +2 -1
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +9 -12
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +12 -4
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +47 -38
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +2 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +8 -13
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +8 -0
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +36 -35
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +1 -1
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +2 -2
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.d.ts +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +3 -3
- package/lib/scheduleManager.js.map +1 -1
- package/lib/storageServiceWithAttachBlobs.d.ts +2 -2
- package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -1
- package/lib/storageServiceWithAttachBlobs.js +1 -1
- package/lib/storageServiceWithAttachBlobs.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +209 -0
- package/lib/summary/documentSchema.d.ts.map +1 -0
- package/lib/summary/documentSchema.js +378 -0
- package/lib/summary/documentSchema.js.map +1 -0
- package/lib/summary/index.d.ts +2 -1
- package/lib/summary/index.d.ts.map +1 -1
- package/lib/summary/index.js +1 -0
- package/lib/summary/index.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +2 -2
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +3 -2
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.d.ts +1 -1
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +3 -3
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +3 -3
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +3 -2
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +3 -3
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts +2 -2
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.d.ts +1 -1
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summary/summarizerHeuristics.js +1 -1
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +3 -2
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +5 -5
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +2 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +3 -3
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +5 -3
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +2 -2
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +1 -1
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +6 -17
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js +3 -3
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +4 -3
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +4 -4
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +1 -1
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +9 -8
- package/lib/summary/summaryManager.js.map +1 -1
- package/lib/tsdoc-metadata.json +11 -0
- package/package.json +34 -32
- package/src/batchTracker.ts +4 -3
- package/src/blobManager.ts +100 -69
- package/src/channelCollection.ts +86 -43
- package/src/connectionTelemetry.ts +12 -12
- package/src/containerHandleContext.ts +3 -2
- package/src/containerRuntime.ts +419 -232
- package/src/dataStore.ts +5 -3
- package/src/dataStoreContext.ts +32 -29
- package/src/dataStoreContexts.ts +4 -2
- package/src/dataStoreRegistry.ts +2 -2
- package/src/deltaManagerSummarizerProxy.ts +1 -1
- package/src/deltaScheduler.ts +2 -1
- package/src/error.ts +2 -2
- package/src/gc/garbageCollection.ts +19 -18
- package/src/gc/gcConfigs.ts +15 -18
- package/src/gc/gcDefinitions.ts +6 -6
- package/src/gc/gcHelpers.ts +22 -5
- package/src/gc/gcSummaryStateTracker.ts +7 -5
- package/src/gc/gcTelemetry.ts +13 -7
- package/src/gc/gcUnreferencedStateTracker.ts +3 -2
- package/src/gc/index.ts +1 -0
- package/src/index.ts +8 -1
- package/src/messageTypes.ts +20 -6
- package/src/opLifecycle/README.md +89 -0
- package/src/opLifecycle/batchManager.ts +1 -0
- package/src/opLifecycle/definitions.ts +3 -21
- package/src/opLifecycle/index.ts +3 -9
- package/src/opLifecycle/opCompressor.ts +6 -5
- package/src/opLifecycle/opDecompressor.ts +84 -100
- package/src/opLifecycle/opGroupingManager.ts +12 -14
- package/src/opLifecycle/opSplitter.ts +76 -48
- package/src/opLifecycle/outbox.ts +17 -32
- package/src/opLifecycle/remoteMessageProcessor.ts +43 -59
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +6 -6
- package/src/scheduleManager.ts +9 -8
- package/src/storageServiceWithAttachBlobs.ts +2 -2
- package/src/summary/documentSchema.ts +612 -0
- package/src/summary/index.ts +10 -1
- package/src/summary/orderedClientElection.ts +6 -7
- package/src/summary/runWhileConnectedCoordinator.ts +3 -2
- package/src/summary/runningSummarizer.ts +22 -20
- package/src/summary/summarizer.ts +17 -15
- package/src/summary/summarizerClientElection.ts +3 -2
- package/src/summary/summarizerHeuristics.ts +4 -2
- package/src/summary/summarizerNode/summarizerNode.ts +20 -18
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +3 -2
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +16 -8
- package/src/summary/summarizerTypes.ts +7 -3
- package/src/summary/summaryCollection.ts +3 -3
- package/src/summary/summaryFormat.ts +14 -26
- package/src/summary/summaryGenerator.ts +12 -15
- package/src/summary/summaryManager.ts +16 -13
- package/lib/test/batchTracker.spec.js +0 -88
- package/lib/test/batchTracker.spec.js.map +0 -1
- package/lib/test/blobManager.spec.js +0 -835
- package/lib/test/blobManager.spec.js.map +0 -1
- package/lib/test/channelCollection.spec.js +0 -138
- package/lib/test/channelCollection.spec.js.map +0 -1
- package/lib/test/containerRuntime.spec.js +0 -1748
- package/lib/test/containerRuntime.spec.js.map +0 -1
- package/lib/test/dataStoreContext.spec.js +0 -771
- package/lib/test/dataStoreContext.spec.js.map +0 -1
- package/lib/test/dataStoreCreation.spec.js +0 -303
- package/lib/test/dataStoreCreation.spec.js.map +0 -1
- package/lib/test/dataStoreRegistry.spec.js +0 -26
- package/lib/test/dataStoreRegistry.spec.js.map +0 -1
- package/lib/test/fuzz/fuzzUtils.js +0 -66
- package/lib/test/fuzz/fuzzUtils.js.map +0 -1
- package/lib/test/fuzz/summarizer.fuzz.spec.js +0 -31
- package/lib/test/fuzz/summarizer.fuzz.spec.js.map +0 -1
- package/lib/test/fuzz/summarizerFuzzMocks.js +0 -162
- package/lib/test/fuzz/summarizerFuzzMocks.js.map +0 -1
- package/lib/test/fuzz/summarizerFuzzSuite.js +0 -106
- package/lib/test/fuzz/summarizerFuzzSuite.js.map +0 -1
- package/lib/test/gc/garbageCollection.spec.js +0 -1464
- package/lib/test/gc/garbageCollection.spec.js.map +0 -1
- package/lib/test/gc/gcConfigs.spec.js +0 -689
- package/lib/test/gc/gcConfigs.spec.js.map +0 -1
- package/lib/test/gc/gcHelpers.spec.js +0 -110
- package/lib/test/gc/gcHelpers.spec.js.map +0 -1
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js +0 -68
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js.map +0 -1
- package/lib/test/gc/gcStats.spec.js +0 -390
- package/lib/test/gc/gcStats.spec.js.map +0 -1
- package/lib/test/gc/gcSummaryStateTracker.spec.js +0 -228
- package/lib/test/gc/gcSummaryStateTracker.spec.js.map +0 -1
- package/lib/test/gc/gcTelemetry.spec.js +0 -530
- package/lib/test/gc/gcTelemetry.spec.js.map +0 -1
- package/lib/test/gc/gcUnitTestHelpers.js +0 -29
- package/lib/test/gc/gcUnitTestHelpers.js.map +0 -1
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js +0 -192
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js.map +0 -1
- package/lib/test/getPendingBlobs.spec.js +0 -193
- package/lib/test/getPendingBlobs.spec.js.map +0 -1
- package/lib/test/hardwareStats.spec.js +0 -93
- package/lib/test/hardwareStats.spec.js.map +0 -1
- package/lib/test/index.js +0 -6
- package/lib/test/index.js.map +0 -1
- package/lib/test/opLifecycle/OpGroupingManager.spec.js +0 -225
- package/lib/test/opLifecycle/OpGroupingManager.spec.js.map +0 -1
- package/lib/test/opLifecycle/batchManager.spec.js +0 -189
- package/lib/test/opLifecycle/batchManager.spec.js.map +0 -1
- package/lib/test/opLifecycle/opCompressor.spec.js +0 -74
- package/lib/test/opLifecycle/opCompressor.spec.js.map +0 -1
- package/lib/test/opLifecycle/opDecompressor.spec.js +0 -218
- package/lib/test/opLifecycle/opDecompressor.spec.js.map +0 -1
- package/lib/test/opLifecycle/opSplitter.spec.js +0 -272
- package/lib/test/opLifecycle/opSplitter.spec.js.map +0 -1
- package/lib/test/opLifecycle/outbox.spec.js +0 -675
- package/lib/test/opLifecycle/outbox.spec.js.map +0 -1
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js +0 -196
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js.map +0 -1
- package/lib/test/pendingStateManager.spec.js +0 -329
- package/lib/test/pendingStateManager.spec.js.map +0 -1
- package/lib/test/scheduleManager.spec.js +0 -270
- package/lib/test/scheduleManager.spec.js.map +0 -1
- package/lib/test/summarizerNode.spec.js +0 -326
- package/lib/test/summarizerNode.spec.js.map +0 -1
- package/lib/test/summarizerNodeWithGc.spec.js +0 -318
- package/lib/test/summarizerNodeWithGc.spec.js.map +0 -1
- package/lib/test/summary/orderedClientElection.spec.js +0 -535
- package/lib/test/summary/orderedClientElection.spec.js.map +0 -1
- package/lib/test/summary/runningSummarizer.spec.js +0 -1349
- package/lib/test/summary/runningSummarizer.spec.js.map +0 -1
- package/lib/test/summary/summarizer.spec.js +0 -29
- package/lib/test/summary/summarizer.spec.js.map +0 -1
- package/lib/test/summary/summarizerClientElection.spec.js +0 -436
- package/lib/test/summary/summarizerClientElection.spec.js.map +0 -1
- package/lib/test/summary/summarizerHeuristics.spec.js +0 -289
- package/lib/test/summary/summarizerHeuristics.spec.js.map +0 -1
- package/lib/test/summary/summaryCollection.spec.js +0 -200
- package/lib/test/summary/summaryCollection.spec.js.map +0 -1
- package/lib/test/summary/summaryManager.spec.js +0 -430
- package/lib/test/summary/summaryManager.spec.js.map +0 -1
- package/lib/test/summary/testQuorumClients.js +0 -34
- package/lib/test/summary/testQuorumClients.js.map +0 -1
- package/lib/test/throttler.spec.js +0 -175
- package/lib/test/throttler.spec.js.map +0 -1
- package/lib/test/types/validateContainerRuntimePrevious.generated.js +0 -180
- package/lib/test/types/validateContainerRuntimePrevious.generated.js.map +0 -1
package/dist/containerRuntime.js
CHANGED
|
@@ -4,33 +4,34 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.ContainerRuntime = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isRuntimeMessage = exports.
|
|
8
|
-
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
9
|
-
const core_utils_1 = require("@fluidframework/core-utils");
|
|
7
|
+
exports.ContainerRuntime = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isRuntimeMessage = exports.defaultPendingOpsRetryDelayMs = exports.defaultPendingOpsWaitTimeoutMs = exports.disabledCompressionConfig = exports.CompressionAlgorithms = exports.defaultRuntimeHeaderData = exports.InactiveResponseHeaderKey = exports.TombstoneResponseHeaderKey = exports.DefaultSummaryConfiguration = void 0;
|
|
10
8
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
9
|
+
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
10
|
+
const internal_1 = require("@fluidframework/container-definitions/internal");
|
|
11
|
+
const internal_2 = require("@fluidframework/core-utils/internal");
|
|
12
|
+
const internal_3 = require("@fluidframework/driver-definitions/internal");
|
|
13
|
+
const internal_4 = require("@fluidframework/driver-utils/internal");
|
|
14
14
|
const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
15
|
-
const
|
|
16
|
-
const
|
|
15
|
+
const internal_5 = require("@fluidframework/runtime-definitions/internal");
|
|
16
|
+
const internal_6 = require("@fluidframework/runtime-utils/internal");
|
|
17
|
+
const internal_7 = require("@fluidframework/telemetry-utils/internal");
|
|
17
18
|
const uuid_1 = require("uuid");
|
|
18
|
-
const
|
|
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");
|
|
19
|
+
const batchTracker_js_1 = require("./batchTracker.js");
|
|
23
20
|
const blobManager_js_1 = require("./blobManager.js");
|
|
24
21
|
const channelCollection_js_1 = require("./channelCollection.js");
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const index_js_2 = require("./gc/index.js");
|
|
22
|
+
const connectionTelemetry_js_1 = require("./connectionTelemetry.js");
|
|
23
|
+
const containerHandleContext_js_1 = require("./containerHandleContext.js");
|
|
28
24
|
const dataStore_js_1 = require("./dataStore.js");
|
|
29
|
-
const
|
|
30
|
-
const scheduleManager_js_1 = require("./scheduleManager.js");
|
|
31
|
-
const index_js_3 = require("./opLifecycle/index.js");
|
|
25
|
+
const dataStoreRegistry_js_1 = require("./dataStoreRegistry.js");
|
|
32
26
|
const deltaManagerSummarizerProxy_js_1 = require("./deltaManagerSummarizerProxy.js");
|
|
27
|
+
const index_js_1 = require("./gc/index.js");
|
|
33
28
|
const messageTypes_js_1 = require("./messageTypes.js");
|
|
29
|
+
const index_js_2 = require("./opLifecycle/index.js");
|
|
30
|
+
const packageVersion_js_1 = require("./packageVersion.js");
|
|
31
|
+
const pendingStateManager_js_1 = require("./pendingStateManager.js");
|
|
32
|
+
const scheduleManager_js_1 = require("./scheduleManager.js");
|
|
33
|
+
const index_js_3 = require("./summary/index.js");
|
|
34
|
+
const throttler_js_1 = require("./throttler.js");
|
|
34
35
|
/**
|
|
35
36
|
* Utility to implement compat behaviors given an unknown message type
|
|
36
37
|
* The parameters are typed to support compile-time enforcement of handling all known types/behaviors
|
|
@@ -85,8 +86,13 @@ var CompressionAlgorithms;
|
|
|
85
86
|
(function (CompressionAlgorithms) {
|
|
86
87
|
CompressionAlgorithms["lz4"] = "lz4";
|
|
87
88
|
})(CompressionAlgorithms || (exports.CompressionAlgorithms = CompressionAlgorithms = {}));
|
|
89
|
+
/** @alpha */
|
|
90
|
+
exports.disabledCompressionConfig = {
|
|
91
|
+
minimumBatchSizeInBytes: Infinity,
|
|
92
|
+
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
93
|
+
};
|
|
88
94
|
const maxConsecutiveReconnectsKey = "Fluid.ContainerRuntime.MaxConsecutiveReconnects";
|
|
89
|
-
const defaultFlushMode =
|
|
95
|
+
const defaultFlushMode = internal_5.FlushMode.TurnBased;
|
|
90
96
|
// The actual limit is 1Mb (socket.io and Kafka limits)
|
|
91
97
|
// We can't estimate it fully, as we
|
|
92
98
|
// - do not know what properties relay service will add
|
|
@@ -108,26 +114,12 @@ exports.defaultPendingOpsRetryDelayMs = 1000;
|
|
|
108
114
|
* This delay's goal is to prevent tight restart loops
|
|
109
115
|
*/
|
|
110
116
|
const defaultCloseSummarizerDelayMs = 5000; // 5 seconds
|
|
111
|
-
/**
|
|
112
|
-
* @deprecated use ContainerRuntimeMessageType instead
|
|
113
|
-
* @internal
|
|
114
|
-
*/
|
|
115
|
-
var RuntimeMessage;
|
|
116
|
-
(function (RuntimeMessage) {
|
|
117
|
-
RuntimeMessage["FluidDataStoreOp"] = "component";
|
|
118
|
-
RuntimeMessage["Attach"] = "attach";
|
|
119
|
-
RuntimeMessage["ChunkedOp"] = "chunkedOp";
|
|
120
|
-
RuntimeMessage["BlobAttach"] = "blobAttach";
|
|
121
|
-
RuntimeMessage["Rejoin"] = "rejoin";
|
|
122
|
-
RuntimeMessage["Alias"] = "alias";
|
|
123
|
-
RuntimeMessage["Operation"] = "op";
|
|
124
|
-
})(RuntimeMessage || (exports.RuntimeMessage = RuntimeMessage = {}));
|
|
125
117
|
/**
|
|
126
118
|
* @deprecated please use version in driver-utils
|
|
127
119
|
* @internal
|
|
128
120
|
*/
|
|
129
121
|
function isRuntimeMessage(message) {
|
|
130
|
-
return Object.values(
|
|
122
|
+
return Object.values(messageTypes_js_1.ContainerMessageType).includes(message.type);
|
|
131
123
|
}
|
|
132
124
|
exports.isRuntimeMessage = isRuntimeMessage;
|
|
133
125
|
/**
|
|
@@ -173,13 +165,13 @@ const summarizerRequestUrl = "_summarizer";
|
|
|
173
165
|
async function createSummarizer(loader, url) {
|
|
174
166
|
const request = {
|
|
175
167
|
headers: {
|
|
176
|
-
[
|
|
177
|
-
[
|
|
168
|
+
[internal_1.LoaderHeader.cache]: false,
|
|
169
|
+
[internal_1.LoaderHeader.clientDetails]: {
|
|
178
170
|
capabilities: { interactive: false },
|
|
179
|
-
type:
|
|
171
|
+
type: index_js_3.summarizerClientType,
|
|
180
172
|
},
|
|
181
|
-
[
|
|
182
|
-
[
|
|
173
|
+
[internal_3.DriverHeader.summarizingClient]: true,
|
|
174
|
+
[internal_1.LoaderHeader.reconnect]: false,
|
|
183
175
|
},
|
|
184
176
|
url,
|
|
185
177
|
};
|
|
@@ -195,15 +187,26 @@ async function createSummarizer(loader, url) {
|
|
|
195
187
|
url: `/${summarizerRequestUrl}`,
|
|
196
188
|
});
|
|
197
189
|
if (response.status !== 200 || response.mimeType !== "fluid/object") {
|
|
198
|
-
throw (0,
|
|
190
|
+
throw (0, internal_6.responseToException)(response, request);
|
|
199
191
|
}
|
|
200
192
|
fluidObject = response.value;
|
|
201
193
|
}
|
|
202
194
|
if (fluidObject?.ISummarizer === undefined) {
|
|
203
|
-
throw new
|
|
195
|
+
throw new internal_7.UsageError("Fluid object does not implement ISummarizer");
|
|
204
196
|
}
|
|
205
197
|
return fluidObject.ISummarizer;
|
|
206
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Extract last message from the snapshot metadata.
|
|
201
|
+
* Uses legacy property if not using explicit schema control, otherwise uses the new property.
|
|
202
|
+
* This allows new runtime to make documents not openable for old runtimes, one explicit document schema control is enabled.
|
|
203
|
+
* Please see addMetadataToSummary() as well
|
|
204
|
+
*/
|
|
205
|
+
function lastMessageFromMetadata(metadata) {
|
|
206
|
+
return metadata?.documentSchema?.runtime?.explicitSchemaControl
|
|
207
|
+
? metadata?.lastMessage
|
|
208
|
+
: metadata?.message;
|
|
209
|
+
}
|
|
207
210
|
/**
|
|
208
211
|
* Represents the runtime of the container. Contains helper functions/state of the container.
|
|
209
212
|
* It will define the store level mappings.
|
|
@@ -231,8 +234,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
231
234
|
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
232
235
|
const backCompatContext = context;
|
|
233
236
|
const passLogger = backCompatContext.taggedLogger ??
|
|
234
|
-
|
|
235
|
-
|
|
237
|
+
// eslint-disable-next-line import/no-deprecated
|
|
238
|
+
new internal_7.TaggedLoggerAdapter(backCompatContext.logger);
|
|
239
|
+
const logger = (0, internal_7.createChildLogger)({
|
|
236
240
|
logger: passLogger,
|
|
237
241
|
properties: {
|
|
238
242
|
all: {
|
|
@@ -240,42 +244,49 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
240
244
|
},
|
|
241
245
|
},
|
|
242
246
|
});
|
|
243
|
-
const mc = (0,
|
|
244
|
-
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor
|
|
247
|
+
const mc = (0, internal_7.loggerToMonitoringContext)(logger);
|
|
248
|
+
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor, chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, enableGroupedBatching = false, explicitSchemaControl = false, } = runtimeOptions;
|
|
245
249
|
const registry = new dataStoreRegistry_js_1.FluidDataStoreRegistry(registryEntries);
|
|
246
250
|
const tryFetchBlob = async (blobName) => {
|
|
247
251
|
const blobId = context.baseSnapshot?.blobs[blobName];
|
|
248
252
|
if (context.baseSnapshot && blobId) {
|
|
249
253
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
250
254
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
251
|
-
(0,
|
|
252
|
-
return (0,
|
|
255
|
+
(0, internal_2.assert)(context.storage !== undefined, 0x1f5 /* "Attached state should have storage" */);
|
|
256
|
+
return (0, internal_4.readAndParse)(context.storage, blobId);
|
|
253
257
|
}
|
|
254
258
|
};
|
|
255
259
|
const [chunks, metadata, electedSummarizerData, aliases, serializedIdCompressor] = await Promise.all([
|
|
256
|
-
tryFetchBlob(
|
|
257
|
-
tryFetchBlob(
|
|
258
|
-
tryFetchBlob(
|
|
259
|
-
tryFetchBlob(
|
|
260
|
-
tryFetchBlob(
|
|
260
|
+
tryFetchBlob(index_js_3.chunksBlobName),
|
|
261
|
+
tryFetchBlob(index_js_3.metadataBlobName),
|
|
262
|
+
tryFetchBlob(index_js_3.electedSummarizerBlobName),
|
|
263
|
+
tryFetchBlob(index_js_3.aliasBlobName),
|
|
264
|
+
tryFetchBlob(index_js_3.idCompressorBlobName),
|
|
261
265
|
]);
|
|
262
266
|
// read snapshot blobs needed for BlobManager to load
|
|
263
|
-
const blobManagerSnapshot = await blobManager_js_1.BlobManager.load(context.baseSnapshot?.trees[
|
|
267
|
+
const blobManagerSnapshot = await blobManager_js_1.BlobManager.load(context.baseSnapshot?.trees[index_js_3.blobsTreeName], async (id) => {
|
|
264
268
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
265
269
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
266
|
-
(0,
|
|
267
|
-
return (0,
|
|
270
|
+
(0, internal_2.assert)(context.storage !== undefined, 0x256 /* "storage undefined in attached container" */);
|
|
271
|
+
return (0, internal_4.readAndParse)(context.storage, id);
|
|
268
272
|
});
|
|
273
|
+
const messageAtLastSummary = lastMessageFromMetadata(metadata);
|
|
269
274
|
// Verify summary runtime sequence number matches protocol sequence number.
|
|
270
|
-
const runtimeSequenceNumber =
|
|
275
|
+
const runtimeSequenceNumber = messageAtLastSummary?.sequenceNumber;
|
|
271
276
|
// When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
|
|
272
277
|
if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
|
|
273
278
|
const protocolSequenceNumber = context.deltaManager.initialSequenceNumber;
|
|
274
279
|
// Unless bypass is explicitly set, then take action when sequence numbers mismatch.
|
|
275
280
|
if (loadSequenceNumberVerification !== "bypass" &&
|
|
276
281
|
runtimeSequenceNumber !== protocolSequenceNumber) {
|
|
282
|
+
// Message to OCEs:
|
|
283
|
+
// You can hit this error with runtimeSequenceNumber === -1 in < 2.0 RC3 builds.
|
|
284
|
+
// This would indicate that explicit schema control is enabled in current (2.0 RC3+) builds and it
|
|
285
|
+
// results in addMetadataToSummary() creating a poison pill for older runtimes in the form of a -1 sequence number.
|
|
286
|
+
// Older runtimes do not understand new schema, and thus could corrupt document if they proceed, thus we are using
|
|
287
|
+
// this poison pill to prevent them from proceeding.
|
|
277
288
|
// "Load from summary, runtime metadata sequenceNumber !== initialSequenceNumber"
|
|
278
|
-
const error = new
|
|
289
|
+
const error = new internal_7.DataCorruptionError(
|
|
279
290
|
// pre-0.58 error message: SummaryMetadataMismatch
|
|
280
291
|
"Summary metadata mismatch", { runtimeVersion: packageVersion_js_1.pkgVersion, runtimeSequenceNumber, protocolSequenceNumber });
|
|
281
292
|
if (loadSequenceNumberVerification === "log") {
|
|
@@ -287,7 +298,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
287
298
|
}
|
|
288
299
|
}
|
|
289
300
|
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
290
|
-
// allow new containers to turn it on
|
|
301
|
+
// allow new containers to turn it on.
|
|
291
302
|
let idCompressorMode;
|
|
292
303
|
if (existing) {
|
|
293
304
|
// This setting has to be sticky for correctness:
|
|
@@ -296,20 +307,20 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
296
307
|
// 2) if it's ON, then all sessions should load compressor right away
|
|
297
308
|
// 3) Same logic applies for "delayed" mode
|
|
298
309
|
// 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"
|
|
300
|
-
// this will allow clients to eventually to disregard "off" setting (when it's safe so) and start
|
|
310
|
+
// We could do "off" -> "on" transition too, if all clients start loading compressor (but not using it initially) and
|
|
311
|
+
// do so for a while - this will allow clients to eventually to disregard "off" setting (when it's safe so) and start
|
|
312
|
+
// using compressor in future sessions.
|
|
301
313
|
// Everyting is possible, but it needs to be designed and executed carefully, when such need arises.
|
|
302
|
-
idCompressorMode = metadata?.
|
|
314
|
+
idCompressorMode = metadata?.documentSchema?.runtime
|
|
315
|
+
?.idCompressorMode;
|
|
303
316
|
}
|
|
304
317
|
else {
|
|
305
|
-
|
|
306
|
-
const enabled = mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled");
|
|
307
|
-
switch (enabled) {
|
|
318
|
+
switch (mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled")) {
|
|
308
319
|
case true:
|
|
309
320
|
idCompressorMode = "on";
|
|
310
321
|
break;
|
|
311
322
|
case false:
|
|
312
|
-
idCompressorMode =
|
|
323
|
+
idCompressorMode = undefined;
|
|
313
324
|
break;
|
|
314
325
|
default:
|
|
315
326
|
idCompressorMode = enableRuntimeIdCompressor;
|
|
@@ -317,7 +328,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
317
328
|
}
|
|
318
329
|
}
|
|
319
330
|
const createIdCompressorFn = async () => {
|
|
320
|
-
const { createIdCompressor, deserializeIdCompressor, createSessionId } = await import("@fluidframework/id-compressor");
|
|
331
|
+
const { createIdCompressor, deserializeIdCompressor, createSessionId } = await import("@fluidframework/id-compressor/internal");
|
|
321
332
|
/**
|
|
322
333
|
* Because the IdCompressor emits so much telemetry, this function is used to sample
|
|
323
334
|
* approximately 5% of all clients. Only the given percentage of sessions will emit telemetry.
|
|
@@ -330,7 +341,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
330
341
|
},
|
|
331
342
|
};
|
|
332
343
|
})();
|
|
333
|
-
const compressorLogger = (0,
|
|
344
|
+
const compressorLogger = (0, internal_7.createSampledLogger)(logger, idCompressorEventSampler);
|
|
334
345
|
const pendingLocalState = context.pendingLocalState;
|
|
335
346
|
if (pendingLocalState?.pendingIdCompressorState !== undefined) {
|
|
336
347
|
return deserializeIdCompressor(pendingLocalState.pendingIdCompressorState, compressorLogger);
|
|
@@ -342,6 +353,25 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
342
353
|
return createIdCompressor(compressorLogger);
|
|
343
354
|
}
|
|
344
355
|
};
|
|
356
|
+
const disableGroupedBatching = mc.config.getBoolean("Fluid.ContainerRuntime.DisableGroupedBatching");
|
|
357
|
+
const disableCompression = mc.config.getBoolean("Fluid.ContainerRuntime.CompressionDisabled");
|
|
358
|
+
const compressionLz4 = disableCompression !== true &&
|
|
359
|
+
compressionOptions.minimumBatchSizeInBytes !== Infinity &&
|
|
360
|
+
compressionOptions.compressionAlgorithm === "lz4";
|
|
361
|
+
const opGroupingEnabled = disableGroupedBatching !== true && enableGroupedBatching;
|
|
362
|
+
const documentSchemaController = new index_js_3.DocumentsSchemaController(existing, metadata?.documentSchema, {
|
|
363
|
+
explicitSchemaControl,
|
|
364
|
+
compressionLz4,
|
|
365
|
+
idCompressorMode,
|
|
366
|
+
opGroupingEnabled,
|
|
367
|
+
disallowedVersions: [],
|
|
368
|
+
}, (schema) => {
|
|
369
|
+
runtime.onSchemaChange(schema);
|
|
370
|
+
});
|
|
371
|
+
const featureGatesForTelemetry = {
|
|
372
|
+
disableGroupedBatching,
|
|
373
|
+
disableCompression,
|
|
374
|
+
};
|
|
345
375
|
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], {
|
|
346
376
|
summaryOptions,
|
|
347
377
|
gcOptions,
|
|
@@ -350,10 +380,19 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
350
380
|
compressionOptions,
|
|
351
381
|
maxBatchSizeInBytes,
|
|
352
382
|
chunkSizeInBytes,
|
|
353
|
-
|
|
383
|
+
// Requires<> drops undefined from IdCompressorType
|
|
384
|
+
enableRuntimeIdCompressor: enableRuntimeIdCompressor,
|
|
354
385
|
enableOpReentryCheck,
|
|
355
386
|
enableGroupedBatching,
|
|
356
|
-
|
|
387
|
+
explicitSchemaControl,
|
|
388
|
+
}, containerScope, logger, existing, blobManagerSnapshot, context.storage, createIdCompressorFn, documentSchemaController, featureGatesForTelemetry, provideEntryPoint, requestHandler, undefined);
|
|
389
|
+
runtime.blobManager.trackPendingStashedUploads().then(() => {
|
|
390
|
+
// make sure we didn't reconnect before the promise resolved
|
|
391
|
+
if (runtime.delayConnectClientId !== undefined && !runtime.disposed) {
|
|
392
|
+
runtime.delayConnectClientId = undefined;
|
|
393
|
+
runtime.setConnectionStateCore(true, runtime.delayConnectClientId);
|
|
394
|
+
}
|
|
395
|
+
}, (error) => runtime.closeFn(error));
|
|
357
396
|
// Apply stashed ops with a reference sequence number equal to the sequence number of the snapshot,
|
|
358
397
|
// or zero. This must be done before Container replays saved ops.
|
|
359
398
|
await runtime.pendingStateManager.applyStashedOpsAt(runtimeSequenceNumber ?? 0);
|
|
@@ -382,6 +421,12 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
382
421
|
get attachState() {
|
|
383
422
|
return this._getAttachState();
|
|
384
423
|
}
|
|
424
|
+
get documentSchema() {
|
|
425
|
+
return this.documentsSchemaController.sessionSchema.runtime;
|
|
426
|
+
}
|
|
427
|
+
get idCompressorMode() {
|
|
428
|
+
return this.documentSchema.idCompressorMode;
|
|
429
|
+
}
|
|
385
430
|
/**
|
|
386
431
|
* See IContainerRuntimeBase.idCompressor() for details.
|
|
387
432
|
*/
|
|
@@ -391,7 +436,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
391
436
|
// That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
|
|
392
437
|
// to reason over such things as session ID space.
|
|
393
438
|
if (this.idCompressorMode === "on") {
|
|
394
|
-
(0,
|
|
439
|
+
(0, internal_2.assert)(this._idCompressor !== undefined, 0x8ea /* compressor should have been loaded */);
|
|
395
440
|
return this._idCompressor;
|
|
396
441
|
}
|
|
397
442
|
}
|
|
@@ -432,7 +477,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
432
477
|
return this._disposed;
|
|
433
478
|
}
|
|
434
479
|
get summarizer() {
|
|
435
|
-
(0,
|
|
480
|
+
(0, internal_2.assert)(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
|
|
436
481
|
return this._summarizer;
|
|
437
482
|
}
|
|
438
483
|
isSummariesDisabled() {
|
|
@@ -462,7 +507,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
462
507
|
return this.garbageCollector.throwOnTombstoneUsage;
|
|
463
508
|
}
|
|
464
509
|
/***/
|
|
465
|
-
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, createIdCompressor,
|
|
510
|
+
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, createIdCompressor, documentsSchemaController, featureGatesForTelemetry, provideEntryPoint, requestHandler, summaryConfiguration = {
|
|
466
511
|
// the defaults
|
|
467
512
|
...exports.DefaultSummaryConfiguration,
|
|
468
513
|
// the runtime configuration overrides
|
|
@@ -476,18 +521,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
476
521
|
this.logger = logger;
|
|
477
522
|
this._storage = _storage;
|
|
478
523
|
this.createIdCompressor = createIdCompressor;
|
|
479
|
-
this.
|
|
524
|
+
this.documentsSchemaController = documentsSchemaController;
|
|
480
525
|
this.requestHandler = requestHandler;
|
|
481
526
|
this.summaryConfiguration = summaryConfiguration;
|
|
482
527
|
this.imminentClosure = false;
|
|
483
528
|
// We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
|
|
484
529
|
// 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
530
|
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;
|
|
491
531
|
this.defaultMaxConsecutiveReconnects = 7;
|
|
492
532
|
this._orderSequentiallyCalls = 0;
|
|
493
533
|
this.flushTaskExists = false;
|
|
@@ -513,10 +553,24 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
513
553
|
* It a cache for holding mapping for loading groupIds with its snapshot from the service. Add expiry policy of 1 minute.
|
|
514
554
|
* Starting with 1 min and based on recorded usage we can tweak it later on.
|
|
515
555
|
*/
|
|
516
|
-
this.snapshotCacheForLoadingGroupIds = new
|
|
556
|
+
this.snapshotCacheForLoadingGroupIds = new internal_2.PromiseCache({
|
|
517
557
|
expiry: { policy: "absolute", durationMs: 60000 },
|
|
518
558
|
});
|
|
519
559
|
const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, loader, pendingLocalState, supportedFeatures, } = context;
|
|
560
|
+
this.mc = (0, internal_7.createChildMonitoringContext)({
|
|
561
|
+
logger: this.logger,
|
|
562
|
+
namespace: "ContainerRuntime",
|
|
563
|
+
});
|
|
564
|
+
// If we support multiple algorithms in the future, then we would need to manage it here carefully.
|
|
565
|
+
// We can use runtimeOptions.compressionOptions.compressionAlgorithm, but only if it's in the schema list!
|
|
566
|
+
// If it's not in the list, then we will need to either use no compression, or fallback to some other (supported by format)
|
|
567
|
+
// compression.
|
|
568
|
+
const compressionOptions = {
|
|
569
|
+
minimumBatchSizeInBytes: this.documentSchema.compressionLz4
|
|
570
|
+
? runtimeOptions.compressionOptions.minimumBatchSizeInBytes
|
|
571
|
+
: Number.POSITIVE_INFINITY,
|
|
572
|
+
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
573
|
+
};
|
|
520
574
|
this.innerDeltaManager = deltaManager;
|
|
521
575
|
this.deltaManager = new deltaManagerSummarizerProxy_js_1.DeltaManagerSummarizerProxy(this.innerDeltaManager);
|
|
522
576
|
// Here we could wrap/intercept on these functions to block/modify outgoing messages if needed.
|
|
@@ -529,7 +583,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
529
583
|
// Values are generally expected to be set from the runtime side.
|
|
530
584
|
this.options = options ?? {};
|
|
531
585
|
this.clientDetails = clientDetails;
|
|
532
|
-
this.isSummarizerClient = this.clientDetails.type ===
|
|
586
|
+
this.isSummarizerClient = this.clientDetails.type === index_js_3.summarizerClientType;
|
|
533
587
|
this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
|
|
534
588
|
this._getClientId = () => context.clientId;
|
|
535
589
|
this._getAttachState = () => context.attachState;
|
|
@@ -550,10 +604,6 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
550
604
|
this.disposeFn = disposeFn ?? closeFn;
|
|
551
605
|
// In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
|
|
552
606
|
this.closeFn = this.isSummarizerClient ? this.disposeFn : closeFn;
|
|
553
|
-
this.mc = (0, telemetry_utils_1.createChildMonitoringContext)({
|
|
554
|
-
logger: this.logger,
|
|
555
|
-
namespace: "ContainerRuntime",
|
|
556
|
-
});
|
|
557
607
|
let loadSummaryNumber;
|
|
558
608
|
// Get the container creation metadata. For new container, we initialize these. For existing containers,
|
|
559
609
|
// get the values from the metadata blob.
|
|
@@ -574,7 +624,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
574
624
|
loadSummaryNumber = 0;
|
|
575
625
|
}
|
|
576
626
|
this.nextSummaryNumber = loadSummaryNumber + 1;
|
|
577
|
-
this.messageAtLastSummary = metadata
|
|
627
|
+
this.messageAtLastSummary = lastMessageFromMetadata(metadata);
|
|
578
628
|
// Note that we only need to pull the *initial* connected state from the context.
|
|
579
629
|
// Later updates come through calls to setConnectionState.
|
|
580
630
|
this._connected = connected;
|
|
@@ -582,20 +632,20 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
582
632
|
eventName: "GCFeatureMatrix",
|
|
583
633
|
metadataValue: JSON.stringify(metadata?.gcFeatureMatrix),
|
|
584
634
|
inputs: JSON.stringify({
|
|
585
|
-
gcOptions_gcGeneration: this.runtimeOptions.gcOptions[
|
|
635
|
+
gcOptions_gcGeneration: this.runtimeOptions.gcOptions[index_js_1.gcGenerationOptionName],
|
|
586
636
|
}),
|
|
587
637
|
});
|
|
588
638
|
this.telemetryDocumentId = metadata?.telemetryDocumentId ?? (0, uuid_1.v4)();
|
|
589
639
|
this.disableAttachReorder = this.mc.config.getBoolean("Fluid.ContainerRuntime.disableAttachOpReorder");
|
|
590
640
|
const disableChunking = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionChunkingDisabled");
|
|
591
|
-
const opGroupingManager = new
|
|
641
|
+
const opGroupingManager = new index_js_2.OpGroupingManager({
|
|
592
642
|
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
593
643
|
opCountThreshold: this.mc.config.getNumber("Fluid.ContainerRuntime.GroupedBatchingOpCount") ?? 2,
|
|
594
644
|
reentrantBatchGroupingEnabled: this.mc.config.getBoolean("Fluid.ContainerRuntime.GroupedBatchingReentrancy") ??
|
|
595
645
|
true,
|
|
596
646
|
}, this.mc.logger);
|
|
597
|
-
const opSplitter = new
|
|
598
|
-
this.remoteMessageProcessor = new
|
|
647
|
+
const opSplitter = new index_js_2.OpSplitter(chunks, this.submitBatchFn, disableChunking === true ? Number.POSITIVE_INFINITY : runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
|
|
648
|
+
this.remoteMessageProcessor = new index_js_2.RemoteMessageProcessor(opSplitter, new index_js_2.OpDecompressor(this.mc.logger), opGroupingManager);
|
|
599
649
|
this.handleContext = new containerHandleContext_js_1.ContainerFluidHandleContext("", this);
|
|
600
650
|
if (this.summaryConfiguration.state === "enabled") {
|
|
601
651
|
this.validateSummaryHeuristicConfiguration(this.summaryConfiguration);
|
|
@@ -611,11 +661,11 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
611
661
|
this.maxConsecutiveReconnects =
|
|
612
662
|
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
|
|
613
663
|
this.defaultMaxConsecutiveReconnects;
|
|
614
|
-
if (runtimeOptions.flushMode ===
|
|
664
|
+
if (runtimeOptions.flushMode === internal_5.FlushModeExperimental.Async &&
|
|
615
665
|
supportedFeatures?.get("referenceSequenceNumbers") !== true) {
|
|
616
666
|
// The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
|
|
617
667
|
this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
|
|
618
|
-
this._flushMode =
|
|
668
|
+
this._flushMode = internal_5.FlushMode.TurnBased;
|
|
619
669
|
}
|
|
620
670
|
else {
|
|
621
671
|
this._flushMode = runtimeOptions.flushMode;
|
|
@@ -628,10 +678,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
628
678
|
// This is a runtime enforcement of what's already explicit in the policy's type itself,
|
|
629
679
|
// which dictates the value is either undefined or exactly 5 days in ms.
|
|
630
680
|
// As long as the actual value is less than 5 days, the assumptions GC makes here are valid.
|
|
631
|
-
throw new
|
|
681
|
+
throw new internal_7.UsageError("Driver's maximumCacheDurationMs policy cannot exceed 5 days");
|
|
632
682
|
}
|
|
633
683
|
}
|
|
634
|
-
this.garbageCollector =
|
|
684
|
+
this.garbageCollector = index_js_1.GarbageCollector.create({
|
|
635
685
|
runtime: this,
|
|
636
686
|
gcOptions: this.runtimeOptions.gcOptions,
|
|
637
687
|
baseSnapshot,
|
|
@@ -642,12 +692,12 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
642
692
|
isSummarizerClient: this.isSummarizerClient,
|
|
643
693
|
getNodePackagePath: async (nodePath) => this.getGCNodePackagePath(nodePath),
|
|
644
694
|
getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
|
|
645
|
-
readAndParseBlob: async (id) => (0,
|
|
695
|
+
readAndParseBlob: async (id) => (0, internal_4.readAndParse)(this.storage, id),
|
|
646
696
|
submitMessage: (message) => this.submit(message),
|
|
647
697
|
sessionExpiryTimerStarted: pendingRuntimeState?.sessionExpiryTimerStarted,
|
|
648
698
|
});
|
|
649
699
|
const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
|
|
650
|
-
this.summarizerNode = (0,
|
|
700
|
+
this.summarizerNode = (0, index_js_3.createRootSummarizerNodeWithGC)((0, internal_7.createChildLogger)({ logger: this.logger, namespace: "SummarizerNode" }),
|
|
651
701
|
// Summarize function to call when summarize is called. Summarizer node always tracks summary state.
|
|
652
702
|
async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext),
|
|
653
703
|
// Latest change sequence number, no changes since summary applied yet
|
|
@@ -677,15 +727,25 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
677
727
|
return this.submitSignalFn(envelope2, targetClientId);
|
|
678
728
|
};
|
|
679
729
|
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(
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
730
|
+
this.blobManager = new blobManager_js_1.BlobManager({
|
|
731
|
+
routeContext: this.handleContext,
|
|
732
|
+
snapshot: blobManagerSnapshot,
|
|
733
|
+
getStorage: () => this.storage,
|
|
734
|
+
sendBlobAttachOp: (localId, blobId) => {
|
|
735
|
+
if (!this.disposed) {
|
|
736
|
+
this.submit({ type: messageTypes_js_1.ContainerMessageType.BlobAttach, contents: undefined }, undefined, {
|
|
737
|
+
localId,
|
|
738
|
+
blobId,
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
},
|
|
742
|
+
blobRequested: (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"),
|
|
743
|
+
isBlobDeleted: (blobPath) => this.garbageCollector.isNodeDeleted(blobPath),
|
|
744
|
+
runtime: this,
|
|
745
|
+
stashedBlobs: pendingRuntimeState?.pendingAttachmentBlobs,
|
|
746
|
+
closeContainer: (error) => this.closeFn(error),
|
|
747
|
+
});
|
|
748
|
+
this.scheduleManager = new scheduleManager_js_1.ScheduleManager(this.innerDeltaManager, this, () => this.clientId, (0, internal_7.createChildLogger)({ logger: this.logger, namespace: "ScheduleManager" }));
|
|
689
749
|
this.pendingStateManager = new pendingStateManager_js_1.PendingStateManager({
|
|
690
750
|
applyStashedOp: this.applyStashedOp.bind(this),
|
|
691
751
|
clientId: () => this.clientId,
|
|
@@ -699,21 +759,14 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
699
759
|
isActiveConnection: () => this.innerDeltaManager.active,
|
|
700
760
|
isAttached: () => this.attachState !== container_definitions_1.AttachState.Detached,
|
|
701
761
|
}, pendingRuntimeState?.pending, this.logger);
|
|
702
|
-
const disableCompression = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionDisabled");
|
|
703
|
-
const compressionOptions = disableCompression === true
|
|
704
|
-
? {
|
|
705
|
-
minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
|
|
706
|
-
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
707
|
-
}
|
|
708
|
-
: runtimeOptions.compressionOptions;
|
|
709
762
|
const disablePartialFlush = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisablePartialFlush");
|
|
710
763
|
const legacySendBatchFn = (0, exports.makeLegacySendBatchFn)(this.submitFn, this.innerDeltaManager);
|
|
711
|
-
this.outbox = new
|
|
764
|
+
this.outbox = new index_js_2.Outbox({
|
|
712
765
|
shouldSend: () => this.canSendOps(),
|
|
713
766
|
pendingStateManager: this.pendingStateManager,
|
|
714
767
|
submitBatchFn: this.submitBatchFn,
|
|
715
768
|
legacySendBatchFn,
|
|
716
|
-
compressor: new
|
|
769
|
+
compressor: new index_js_2.OpCompressor(this.mc.logger),
|
|
717
770
|
splitter: opSplitter,
|
|
718
771
|
config: {
|
|
719
772
|
compressionOptions,
|
|
@@ -740,7 +793,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
740
793
|
this.closeSummarizerDelayMs = closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
|
|
741
794
|
this.validateSummaryBeforeUpload =
|
|
742
795
|
this.mc.config.getBoolean("Fluid.Summarizer.ValidateSummaryBeforeUpload") ?? false;
|
|
743
|
-
this.summaryCollection = new
|
|
796
|
+
this.summaryCollection = new index_js_3.SummaryCollection(this.deltaManager, this.logger);
|
|
744
797
|
this.dirtyContainer =
|
|
745
798
|
this.attachState !== container_definitions_1.AttachState.Attached || this.hasPendingMessages();
|
|
746
799
|
context.updateDirtyContainerState(this.dirtyContainer);
|
|
@@ -748,20 +801,20 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
748
801
|
this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
|
|
749
802
|
}
|
|
750
803
|
else {
|
|
751
|
-
const orderedClientLogger = (0,
|
|
804
|
+
const orderedClientLogger = (0, internal_7.createChildLogger)({
|
|
752
805
|
logger: this.logger,
|
|
753
806
|
namespace: "OrderedClientElection",
|
|
754
807
|
});
|
|
755
|
-
const orderedClientCollection = new
|
|
756
|
-
const orderedClientElectionForSummarizer = new
|
|
757
|
-
this.summarizerClientElection = new
|
|
808
|
+
const orderedClientCollection = new index_js_3.OrderedClientCollection(orderedClientLogger, this.innerDeltaManager, this._quorum);
|
|
809
|
+
const orderedClientElectionForSummarizer = new index_js_3.OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData ?? this.innerDeltaManager.lastSequenceNumber, index_js_3.SummarizerClientElection.isClientEligible);
|
|
810
|
+
this.summarizerClientElection = new index_js_3.SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, this.maxOpsSinceLastSummary);
|
|
758
811
|
if (this.isSummarizerClient) {
|
|
759
|
-
this._summarizer = new
|
|
812
|
+
this._summarizer = new index_js_3.Summarizer(this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => index_js_3.RunWhileConnectedCoordinator.create(runtime,
|
|
760
813
|
// Summarization runs in summarizer client and needs access to the real (non-proxy) active
|
|
761
814
|
// information. The proxy delta manager would always return false for summarizer client.
|
|
762
815
|
() => this.innerDeltaManager.active));
|
|
763
816
|
}
|
|
764
|
-
else if (
|
|
817
|
+
else if (index_js_3.SummarizerClientElection.clientDetailsPermitElection(this.clientDetails)) {
|
|
765
818
|
// Only create a SummaryManager and SummarizerClientElection
|
|
766
819
|
// if summaries are enabled and we are not the summarizer client.
|
|
767
820
|
const defaultAction = () => {
|
|
@@ -783,7 +836,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
783
836
|
};
|
|
784
837
|
this.summaryCollection.on("default", defaultAction);
|
|
785
838
|
// Create the SummaryManager and mark the initial state
|
|
786
|
-
this.summaryManager = new
|
|
839
|
+
this.summaryManager = new index_js_3.SummaryManager(this.summarizerClientElection, this, // IConnectedState
|
|
787
840
|
this.summaryCollection, this.logger, this.formCreateSummarizerFn(loader), new throttler_js_1.Throttler(60 * 1000, // 60 sec delay window
|
|
788
841
|
30 * 1000, // 30 sec max delay
|
|
789
842
|
// throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
|
|
@@ -810,10 +863,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
810
863
|
disableIsolatedChannels: metadata?.disableIsolatedChannels,
|
|
811
864
|
gcVersion: metadata?.gcFeature,
|
|
812
865
|
options: JSON.stringify(runtimeOptions),
|
|
813
|
-
idCompressorModeMetadata: metadata?.idCompressorMode,
|
|
866
|
+
idCompressorModeMetadata: metadata?.documentSchema?.runtime?.idCompressorMode,
|
|
814
867
|
idCompressorMode: this.idCompressorMode,
|
|
815
868
|
featureGates: JSON.stringify({
|
|
816
|
-
|
|
869
|
+
...featureGatesForTelemetry,
|
|
817
870
|
disableOpReentryCheck,
|
|
818
871
|
disableChunking,
|
|
819
872
|
disableAttachReorder: this.disableAttachReorder,
|
|
@@ -825,9 +878,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
825
878
|
});
|
|
826
879
|
(0, connectionTelemetry_js_1.ReportOpPerfTelemetry)(this.clientId, this.deltaManager, this, this.logger);
|
|
827
880
|
(0, batchTracker_js_1.BindBatchTracker)(this, this.logger);
|
|
828
|
-
this.entryPoint = new
|
|
881
|
+
this.entryPoint = new internal_2.LazyPromise(async () => {
|
|
829
882
|
if (this.isSummarizerClient) {
|
|
830
|
-
(0,
|
|
883
|
+
(0, internal_2.assert)(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
|
|
831
884
|
return this._summarizer;
|
|
832
885
|
}
|
|
833
886
|
return provideEntryPoint(this);
|
|
@@ -836,6 +889,20 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
836
889
|
// saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
|
|
837
890
|
this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
|
|
838
891
|
}
|
|
892
|
+
onSchemaChange(schema) {
|
|
893
|
+
// Most of the settings will be picked up only by new sessions (i.e. after reload).
|
|
894
|
+
// We can make it better in the future (i.e. start to use op compression right away), but for simplicity
|
|
895
|
+
// this is not done.
|
|
896
|
+
// But ID compressor is special. It's possible, that in future, we will remove "stickiness" of ID compressor setting
|
|
897
|
+
// and will allow to start using it. If that were to happen, we want to ensure that we do not break eventual consistency
|
|
898
|
+
// promises. To do so, we need to initialize id compressor right away.
|
|
899
|
+
// As it's implemented right now (with async initialization), this will only work for "off" -> "delayed" transitions.
|
|
900
|
+
// Anything else is too risky, and requires ability to initialize ID compressor synchronously!
|
|
901
|
+
if (schema.runtime.idCompressorMode !== undefined) {
|
|
902
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
903
|
+
this.loadIdCompressor();
|
|
904
|
+
}
|
|
905
|
+
}
|
|
839
906
|
getCreateChildSummarizerNodeFn(id, createParam) {
|
|
840
907
|
return (summarizeInternal, getGCDataFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn);
|
|
841
908
|
}
|
|
@@ -844,10 +911,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
844
911
|
}
|
|
845
912
|
/* IFluidParentContext APIs that should not be called on Root */
|
|
846
913
|
makeLocallyVisible() {
|
|
847
|
-
(0,
|
|
914
|
+
(0, internal_2.assert)(false, 0x8eb /* should not be called */);
|
|
848
915
|
}
|
|
849
916
|
setChannelDirty(address) {
|
|
850
|
-
(0,
|
|
917
|
+
(0, internal_2.assert)(false, 0x909 /* should not be called */);
|
|
851
918
|
}
|
|
852
919
|
/**
|
|
853
920
|
* Initializes the state from the base snapshot this container runtime loaded from.
|
|
@@ -856,7 +923,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
856
923
|
if (this.idCompressorMode === "on" ||
|
|
857
924
|
(this.idCompressorMode === "delayed" && this.connected)) {
|
|
858
925
|
// This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
|
|
859
|
-
(0,
|
|
926
|
+
(0, internal_2.assert)(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
|
|
860
927
|
this._idCompressor = await this.createIdCompressor();
|
|
861
928
|
}
|
|
862
929
|
await this.garbageCollector.initializeBaseState();
|
|
@@ -890,13 +957,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
890
957
|
*/
|
|
891
958
|
async getSnapshotForLoadingGroupId(loadingGroupIds, pathParts) {
|
|
892
959
|
const sortedLoadingGroupIds = loadingGroupIds.sort();
|
|
893
|
-
(0,
|
|
960
|
+
(0, internal_2.assert)(this.storage.getSnapshot !== undefined, 0x8ed /* getSnapshot api should be defined if used */);
|
|
894
961
|
let loadedFromCache = true;
|
|
895
962
|
// Lookup up in the cache, if not present then make the network call as multiple datastores could
|
|
896
963
|
// be in same loading group. So, once we have fetched the snapshot for that loading group on
|
|
897
964
|
// any request, then cache that as same group could be requested in future too.
|
|
898
965
|
const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(), async () => {
|
|
899
|
-
(0,
|
|
966
|
+
(0, internal_2.assert)(this.storage.getSnapshot !== undefined, 0x8ee /* getSnapshot api should be defined if used */);
|
|
900
967
|
loadedFromCache = false;
|
|
901
968
|
return this.storage.getSnapshot({
|
|
902
969
|
cacheSnapshot: false,
|
|
@@ -912,16 +979,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
912
979
|
}),
|
|
913
980
|
});
|
|
914
981
|
// Find the snapshotTree inside the returned snapshot based on the path as given in the request.
|
|
915
|
-
const hasIsolatedChannels = (0,
|
|
982
|
+
const hasIsolatedChannels = (0, index_js_3.rootHasIsolatedChannels)(this.metadata);
|
|
916
983
|
const snapshotTreeForPath = this.getSnapshotTreeForPath(snapshot.snapshotTree, pathParts, hasIsolatedChannels);
|
|
917
|
-
(0,
|
|
984
|
+
(0, internal_2.assert)(snapshotTreeForPath !== undefined, 0x8ef /* no snapshotTree for the path */);
|
|
918
985
|
const snapshotSeqNumber = snapshot.sequenceNumber;
|
|
919
|
-
(0,
|
|
986
|
+
(0, internal_2.assert)(snapshotSeqNumber !== undefined, 0x8f0 /* snapshotSeqNumber should be present */);
|
|
920
987
|
// This assert fires if we get a snapshot older than the snapshot we loaded from. This is a service issue.
|
|
921
988
|
// Snapshots should only move forward. If we observe an older snapshot than the one we loaded from, then likely
|
|
922
989
|
// the file has been overwritten or service lost data.
|
|
923
990
|
if (snapshotSeqNumber < this.deltaManager.initialSequenceNumber) {
|
|
924
|
-
throw
|
|
991
|
+
throw internal_7.DataProcessingError.create("Downloaded snapshot older than snapshot we loaded from", "getSnapshotForLoadingGroupId", undefined, {
|
|
925
992
|
loadingGroupIds: sortedLoadingGroupIds.join(","),
|
|
926
993
|
snapshotSeqNumber,
|
|
927
994
|
initialSequenceNumber: this.deltaManager.initialSequenceNumber,
|
|
@@ -944,7 +1011,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
944
1011
|
targetSequenceNumber: snapshotSeqNumber,
|
|
945
1012
|
sequenceNumber: this.deltaManager.lastSequenceNumber, // This is so we reuse some columns in telemetry
|
|
946
1013
|
};
|
|
947
|
-
const event =
|
|
1014
|
+
const event = internal_7.PerformanceEvent.start(this.mc.logger, {
|
|
948
1015
|
...props,
|
|
949
1016
|
});
|
|
950
1017
|
// If the inbound deltas queue is paused or disconnected, we expect a reconnect and unpause
|
|
@@ -952,7 +1019,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
952
1019
|
if (this.deltaManager.inbound.paused) {
|
|
953
1020
|
props.inboundPaused = this.deltaManager.inbound.paused; // reusing telemetry
|
|
954
1021
|
}
|
|
955
|
-
const defP = new
|
|
1022
|
+
const defP = new internal_2.Deferred();
|
|
956
1023
|
this.deltaManager.on("op", (message) => {
|
|
957
1024
|
if (message.sequenceNumber >= snapshotSeqNumber) {
|
|
958
1025
|
defP.resolve(true);
|
|
@@ -975,7 +1042,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
975
1042
|
let childTree = snapshotTree;
|
|
976
1043
|
for (const part of pathParts) {
|
|
977
1044
|
if (hasIsolatedChannels) {
|
|
978
|
-
childTree = childTree?.trees[
|
|
1045
|
+
childTree = childTree?.trees[internal_5.channelsTreeName];
|
|
979
1046
|
}
|
|
980
1047
|
childTree = childTree?.trees[part];
|
|
981
1048
|
}
|
|
@@ -989,7 +1056,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
989
1056
|
// @ts-expect-error expected to be used by LTS Loaders and Containers
|
|
990
1057
|
async request(request) {
|
|
991
1058
|
try {
|
|
992
|
-
const parser =
|
|
1059
|
+
const parser = internal_6.RequestParser.create(request);
|
|
993
1060
|
const id = parser.pathParts[0];
|
|
994
1061
|
if (id === summarizerRequestUrl && parser.pathParts.length === 1) {
|
|
995
1062
|
if (this._summarizer !== undefined) {
|
|
@@ -999,16 +1066,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
999
1066
|
value: this.summarizer,
|
|
1000
1067
|
};
|
|
1001
1068
|
}
|
|
1002
|
-
return (0,
|
|
1069
|
+
return (0, internal_6.create404Response)(request);
|
|
1003
1070
|
}
|
|
1004
1071
|
if (this.requestHandler !== undefined) {
|
|
1005
1072
|
// eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
|
|
1006
1073
|
return this.requestHandler(parser, this);
|
|
1007
1074
|
}
|
|
1008
|
-
return (0,
|
|
1075
|
+
return (0, internal_6.create404Response)(request);
|
|
1009
1076
|
}
|
|
1010
1077
|
catch (error) {
|
|
1011
|
-
return (0,
|
|
1078
|
+
return (0, internal_6.exceptionToResponse)(error);
|
|
1012
1079
|
}
|
|
1013
1080
|
}
|
|
1014
1081
|
/**
|
|
@@ -1017,7 +1084,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1017
1084
|
*/
|
|
1018
1085
|
async resolveHandle(request) {
|
|
1019
1086
|
try {
|
|
1020
|
-
const requestParser =
|
|
1087
|
+
const requestParser = internal_6.RequestParser.create(request);
|
|
1021
1088
|
const id = requestParser.pathParts[0];
|
|
1022
1089
|
if (id === "_channels") {
|
|
1023
1090
|
// eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
|
|
@@ -1031,15 +1098,15 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1031
1098
|
mimeType: "fluid/object",
|
|
1032
1099
|
value: blob,
|
|
1033
1100
|
}
|
|
1034
|
-
: (0,
|
|
1101
|
+
: (0, internal_6.create404Response)(request);
|
|
1035
1102
|
}
|
|
1036
1103
|
else if (requestParser.pathParts.length > 0) {
|
|
1037
1104
|
return await this.channelCollection.request(request);
|
|
1038
1105
|
}
|
|
1039
|
-
return (0,
|
|
1106
|
+
return (0, internal_6.create404Response)(request);
|
|
1040
1107
|
}
|
|
1041
1108
|
catch (error) {
|
|
1042
|
-
return (0,
|
|
1109
|
+
return (0, internal_6.exceptionToResponse)(error);
|
|
1043
1110
|
}
|
|
1044
1111
|
}
|
|
1045
1112
|
/**
|
|
@@ -1053,48 +1120,60 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1053
1120
|
}
|
|
1054
1121
|
/** Adds the container's metadata to the given summary tree. */
|
|
1055
1122
|
addMetadataToSummary(summaryTree) {
|
|
1123
|
+
// The last message processed at the time of summary. If there are no new messages, use the message from the
|
|
1124
|
+
// last summary.
|
|
1125
|
+
const message = (0, index_js_3.extractSummaryMetadataMessage)(this.deltaManager.lastMessage) ??
|
|
1126
|
+
this.messageAtLastSummary;
|
|
1127
|
+
const documentSchema = this.documentsSchemaController.summarizeDocumentSchema(this.deltaManager.lastSequenceNumber);
|
|
1128
|
+
// Is document schema explicit control on?
|
|
1129
|
+
const explitiSchemaControl = documentSchema?.runtime.explicitSchemaControl;
|
|
1056
1130
|
const metadata = {
|
|
1057
1131
|
...this.createContainerMetadata,
|
|
1058
1132
|
// Increment the summary number for the next summary that will be generated.
|
|
1059
1133
|
summaryNumber: this.nextSummaryNumber++,
|
|
1060
1134
|
summaryFormatVersion: 1,
|
|
1061
1135
|
...this.garbageCollector.getMetadata(),
|
|
1062
|
-
// The last message processed at the time of summary. If there are no new messages, use the message from the
|
|
1063
|
-
// last summary.
|
|
1064
|
-
message: (0, index_js_1.extractSummaryMetadataMessage)(this.deltaManager.lastMessage) ??
|
|
1065
|
-
this.messageAtLastSummary,
|
|
1066
1136
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
1067
|
-
|
|
1137
|
+
// If explicit document schema control is not on, use legacy way to supply last message (using 'message' property).
|
|
1138
|
+
// Otherwise use new 'lastMessage' property, but also put content into the 'message' property that cases old
|
|
1139
|
+
// runtimes (that preceed document schema control capabilities) to close container on load due to mismatch in
|
|
1140
|
+
// last message's sequence number.
|
|
1141
|
+
// See also lastMessageFromMetadata()
|
|
1142
|
+
message: explitiSchemaControl
|
|
1143
|
+
? { sequenceNumber: -1 }
|
|
1144
|
+
: message,
|
|
1145
|
+
lastMessage: explitiSchemaControl ? message : undefined,
|
|
1146
|
+
documentSchema,
|
|
1068
1147
|
};
|
|
1069
|
-
(0,
|
|
1148
|
+
(0, internal_6.addBlobToSummary)(summaryTree, index_js_3.metadataBlobName, JSON.stringify(metadata));
|
|
1070
1149
|
}
|
|
1071
1150
|
addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext) {
|
|
1072
1151
|
this.addMetadataToSummary(summaryTree);
|
|
1073
1152
|
if (this._idCompressor) {
|
|
1074
1153
|
const idCompressorState = JSON.stringify(this._idCompressor.serialize(false));
|
|
1075
|
-
(0,
|
|
1154
|
+
(0, internal_6.addBlobToSummary)(summaryTree, index_js_3.idCompressorBlobName, idCompressorState);
|
|
1076
1155
|
}
|
|
1077
1156
|
if (this.remoteMessageProcessor.partialMessages.size > 0) {
|
|
1078
1157
|
const content = JSON.stringify([...this.remoteMessageProcessor.partialMessages]);
|
|
1079
|
-
(0,
|
|
1158
|
+
(0, internal_6.addBlobToSummary)(summaryTree, index_js_3.chunksBlobName, content);
|
|
1080
1159
|
}
|
|
1081
1160
|
const dataStoreAliases = this.channelCollection.aliases;
|
|
1082
1161
|
if (dataStoreAliases.size > 0) {
|
|
1083
|
-
(0,
|
|
1162
|
+
(0, internal_6.addBlobToSummary)(summaryTree, index_js_3.aliasBlobName, JSON.stringify([...dataStoreAliases]));
|
|
1084
1163
|
}
|
|
1085
1164
|
if (this.summarizerClientElection) {
|
|
1086
1165
|
const electedSummarizerContent = JSON.stringify(this.summarizerClientElection?.serialize());
|
|
1087
|
-
(0,
|
|
1166
|
+
(0, internal_6.addBlobToSummary)(summaryTree, index_js_3.electedSummarizerBlobName, electedSummarizerContent);
|
|
1088
1167
|
}
|
|
1089
1168
|
const blobManagerSummary = this.blobManager.summarize();
|
|
1090
1169
|
// Some storage (like git) doesn't allow empty tree, so we can omit it.
|
|
1091
1170
|
// and the blob manager can handle the tree not existing when loading
|
|
1092
1171
|
if (Object.keys(blobManagerSummary.summary.tree).length > 0) {
|
|
1093
|
-
(0,
|
|
1172
|
+
(0, internal_6.addSummarizeResultToSummary)(summaryTree, index_js_3.blobsTreeName, blobManagerSummary);
|
|
1094
1173
|
}
|
|
1095
1174
|
const gcSummary = this.garbageCollector.summarize(fullTree, trackState, telemetryContext);
|
|
1096
1175
|
if (gcSummary !== undefined) {
|
|
1097
|
-
(0,
|
|
1176
|
+
(0, internal_6.addSummarizeResultToSummary)(summaryTree, internal_5.gcTreeKey, gcSummary);
|
|
1098
1177
|
}
|
|
1099
1178
|
}
|
|
1100
1179
|
// Track how many times the container tries to reconnect with pending messages.
|
|
@@ -1139,7 +1218,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1139
1218
|
// Save the old state, reset to false, disable event emit
|
|
1140
1219
|
const oldState = this.dirtyContainer;
|
|
1141
1220
|
this.dirtyContainer = false;
|
|
1142
|
-
(0,
|
|
1221
|
+
(0, internal_2.assert)(this.emitDirtyDocumentEvent, 0x127 /* "dirty document event not set on replay" */);
|
|
1143
1222
|
this.emitDirtyDocumentEvent = false;
|
|
1144
1223
|
let newState;
|
|
1145
1224
|
try {
|
|
@@ -1161,9 +1240,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1161
1240
|
*/
|
|
1162
1241
|
// TODO: markfields: confirm Local- versus Outbound- ContainerRuntimeMessage typing
|
|
1163
1242
|
parseLocalOpContent(serializedContents) {
|
|
1164
|
-
(0,
|
|
1243
|
+
(0, internal_2.assert)(serializedContents !== undefined, 0x6d5 /* content must be defined */);
|
|
1165
1244
|
const message = JSON.parse(serializedContents);
|
|
1166
|
-
(0,
|
|
1245
|
+
(0, internal_2.assert)(message.type !== undefined, 0x6d6 /* incorrect op content format */);
|
|
1167
1246
|
return message;
|
|
1168
1247
|
}
|
|
1169
1248
|
async applyStashedOp(serializedOpContent) {
|
|
@@ -1175,7 +1254,18 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1175
1254
|
case messageTypes_js_1.ContainerMessageType.Alias:
|
|
1176
1255
|
return this.channelCollection.applyStashedOp(opContents);
|
|
1177
1256
|
case messageTypes_js_1.ContainerMessageType.IdAllocation:
|
|
1178
|
-
|
|
1257
|
+
// IDs allocation ops in stashed state are ignored because the tip state of the compressor
|
|
1258
|
+
// is serialized into the pending state. This is done because generation of new IDs during
|
|
1259
|
+
// stashed op application (or, later, resubmit) must generate new IDs and if the compressor
|
|
1260
|
+
// was loaded from a state serialized at the same time as the summary tree in the stashed state
|
|
1261
|
+
// then it would generate IDs that collide with any in later stashed ops.
|
|
1262
|
+
// In the future, IdCompressor could be extended to have an "applyStashedOp" or similar method
|
|
1263
|
+
// and the runtime could filter out all ID allocation ops from the stashed state and apply them
|
|
1264
|
+
// before applying the rest of the stashed ops. This would accomplish the same thing but with
|
|
1265
|
+
// better performance in future incremental stashed state creation.
|
|
1266
|
+
(0, internal_2.assert)(this.idCompressorMode !== undefined, 0x8f1 /* ID compressor should be in use */);
|
|
1267
|
+
return;
|
|
1268
|
+
case messageTypes_js_1.ContainerMessageType.DocumentSchemaChange:
|
|
1179
1269
|
return;
|
|
1180
1270
|
case messageTypes_js_1.ContainerMessageType.BlobAttach:
|
|
1181
1271
|
return;
|
|
@@ -1185,14 +1275,14 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1185
1275
|
throw new Error("rejoin not expected here");
|
|
1186
1276
|
case messageTypes_js_1.ContainerMessageType.GC:
|
|
1187
1277
|
// GC op is only sent in summarizer which should never have stashed ops.
|
|
1188
|
-
throw new
|
|
1278
|
+
throw new internal_7.LoggingError("GC op not expected to be stashed in summarizer");
|
|
1189
1279
|
default: {
|
|
1190
1280
|
// This should be extremely rare for stashed ops.
|
|
1191
1281
|
// It would require a newer runtime stashing ops and then an older one applying them,
|
|
1192
1282
|
// e.g. if an app rolled back its container version
|
|
1193
1283
|
const compatBehavior = opContents.compatDetails?.behavior;
|
|
1194
1284
|
if (!compatBehaviorAllowsMessageType(opContents.type, compatBehavior)) {
|
|
1195
|
-
const error =
|
|
1285
|
+
const error = internal_7.DataProcessingError.create("Stashed runtime message of unknown type", "applyStashedOp", undefined /* sequencedMessage */, {
|
|
1196
1286
|
messageDetails: JSON.stringify({
|
|
1197
1287
|
type: opContents.type,
|
|
1198
1288
|
compatBehavior,
|
|
@@ -1206,12 +1296,14 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1206
1296
|
}
|
|
1207
1297
|
}
|
|
1208
1298
|
}
|
|
1209
|
-
|
|
1210
|
-
if (
|
|
1211
|
-
this.
|
|
1212
|
-
this.
|
|
1299
|
+
async loadIdCompressor() {
|
|
1300
|
+
if (this._idCompressor === undefined &&
|
|
1301
|
+
this.idCompressorMode !== undefined &&
|
|
1302
|
+
this._loadIdCompressor === undefined) {
|
|
1303
|
+
this._loadIdCompressor = this.createIdCompressor()
|
|
1213
1304
|
.then((compressor) => {
|
|
1214
1305
|
this._idCompressor = compressor;
|
|
1306
|
+
// Finalize any ranges we received while the compressor was turned off.
|
|
1215
1307
|
for (const range of this.pendingIdCompressorOps) {
|
|
1216
1308
|
this._idCompressor.finalizeCreationRange(range);
|
|
1217
1309
|
}
|
|
@@ -1219,8 +1311,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1219
1311
|
})
|
|
1220
1312
|
.catch((error) => {
|
|
1221
1313
|
this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
|
|
1314
|
+
throw error;
|
|
1222
1315
|
});
|
|
1223
1316
|
}
|
|
1317
|
+
return this._loadIdCompressor;
|
|
1318
|
+
}
|
|
1319
|
+
setConnectionState(connected, clientId) {
|
|
1320
|
+
if (connected && this.idCompressorMode === "delayed") {
|
|
1321
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1322
|
+
this.loadIdCompressor();
|
|
1323
|
+
}
|
|
1224
1324
|
if (connected === false && this.delayConnectClientId !== undefined) {
|
|
1225
1325
|
this.delayConnectClientId = undefined;
|
|
1226
1326
|
this.mc.logger.sendTelemetryEvent({
|
|
@@ -1229,27 +1329,23 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1229
1329
|
// Don't propagate "disconnected" event because we didn't propagate the previous "connected" event
|
|
1230
1330
|
return;
|
|
1231
1331
|
}
|
|
1332
|
+
if (!connected) {
|
|
1333
|
+
this.documentsSchemaController.onDisconnect();
|
|
1334
|
+
}
|
|
1232
1335
|
// If there are stashed blobs in the pending state, we need to delay
|
|
1233
1336
|
// propagation of the "connected" event until we have uploaded them to
|
|
1234
1337
|
// ensure we don't submit ops referencing a blob that has not been uploaded
|
|
1235
1338
|
const connecting = connected && !this._connected;
|
|
1236
|
-
if (connecting && this.blobManager.
|
|
1237
|
-
(0,
|
|
1238
|
-
(0,
|
|
1339
|
+
if (connecting && this.blobManager.hasPendingStashedUploads()) {
|
|
1340
|
+
(0, internal_2.assert)(!this.delayConnectClientId, 0x791 /* Connect event delay must be canceled before subsequent connect event */);
|
|
1341
|
+
(0, internal_2.assert)(!!clientId, 0x792 /* Must have clientId when connecting */);
|
|
1239
1342
|
this.delayConnectClientId = clientId;
|
|
1240
|
-
this.blobManager.processStashedChanges().then(() => {
|
|
1241
|
-
// make sure we didn't reconnect before the promise resolved
|
|
1242
|
-
if (this.delayConnectClientId === clientId && !this.disposed) {
|
|
1243
|
-
this.delayConnectClientId = undefined;
|
|
1244
|
-
this.setConnectionStateCore(connected, clientId);
|
|
1245
|
-
}
|
|
1246
|
-
}, (error) => this.closeFn(error));
|
|
1247
1343
|
return;
|
|
1248
1344
|
}
|
|
1249
1345
|
this.setConnectionStateCore(connected, clientId);
|
|
1250
1346
|
}
|
|
1251
1347
|
setConnectionStateCore(connected, clientId) {
|
|
1252
|
-
(0,
|
|
1348
|
+
(0, internal_2.assert)(!this.delayConnectClientId, 0x394 /* connect event delay must be cleared before propagating connect event */);
|
|
1253
1349
|
this.verifyNotClosed();
|
|
1254
1350
|
// There might be no change of state due to Container calling this API after loading runtime.
|
|
1255
1351
|
const changeOfState = this._connected !== connected;
|
|
@@ -1267,13 +1363,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1267
1363
|
this._perfSignalData.trackingSignalSequenceNumber = undefined;
|
|
1268
1364
|
}
|
|
1269
1365
|
else {
|
|
1270
|
-
(0,
|
|
1366
|
+
(0, internal_2.assert)(this.attachState === container_definitions_1.AttachState.Attached, 0x3cd /* Connection is possible only if container exists in storage */);
|
|
1271
1367
|
}
|
|
1272
1368
|
// Fail while disconnected
|
|
1273
1369
|
if (reconnection) {
|
|
1274
1370
|
this.consecutiveReconnects++;
|
|
1275
1371
|
if (!this.shouldContinueReconnecting()) {
|
|
1276
|
-
this.closeFn(
|
|
1372
|
+
this.closeFn(internal_7.DataProcessingError.create("Runtime detected too many reconnects with no progress syncing local ops.", "setConnectionState", undefined, {
|
|
1277
1373
|
dataLoss: 1,
|
|
1278
1374
|
attempts: this.consecutiveReconnects,
|
|
1279
1375
|
pendingMessages: this.pendingMessagesCount,
|
|
@@ -1286,7 +1382,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1286
1382
|
}
|
|
1287
1383
|
this.channelCollection.setConnectionState(connected, clientId);
|
|
1288
1384
|
this.garbageCollector.setConnectionState(connected, clientId);
|
|
1289
|
-
(0,
|
|
1385
|
+
(0, internal_7.raiseConnectedEvent)(this.mc.logger, this, connected, clientId);
|
|
1290
1386
|
}
|
|
1291
1387
|
async notifyOpReplay(message) {
|
|
1292
1388
|
await this.pendingStateManager.applyStashedOpsAt(message.sequenceNumber);
|
|
@@ -1335,7 +1431,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1335
1431
|
// These calls should be made for all but chunked ops:
|
|
1336
1432
|
// 1) this.pendingStateManager.processPendingLocalMessage() below
|
|
1337
1433
|
// 2) this.resetReconnectCount() below
|
|
1338
|
-
(0,
|
|
1434
|
+
(0, internal_2.assert)(message.type !== messageTypes_js_1.ContainerMessageType.ChunkedOp, "we should never get here with chunked ops");
|
|
1339
1435
|
let localOpMetadata;
|
|
1340
1436
|
if (local && messageWithContext.modernRuntimeMessage) {
|
|
1341
1437
|
localOpMetadata = this.pendingStateManager.processPendingLocalMessage(messageWithContext.message);
|
|
@@ -1386,6 +1482,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1386
1482
|
messageWithContext.message.metadata?.savedOp ===
|
|
1387
1483
|
true)) {
|
|
1388
1484
|
const range = messageWithContext.message.contents;
|
|
1485
|
+
// Some other client turned on the id compressor. If we have not turned it on,
|
|
1486
|
+
// put it in a pending queue and delay finalization.
|
|
1389
1487
|
if (this._idCompressor === undefined) {
|
|
1390
1488
|
this.pendingIdCompressorOps.push(range);
|
|
1391
1489
|
}
|
|
@@ -1400,9 +1498,12 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1400
1498
|
case messageTypes_js_1.ContainerMessageType.ChunkedOp:
|
|
1401
1499
|
// From observability POV, we should not exppse the rest of the system (including "op" events on object) to these messages.
|
|
1402
1500
|
// Also resetReconnectCount() would be wrong - see comment that was there before this change was made.
|
|
1403
|
-
(0,
|
|
1501
|
+
(0, internal_2.assert)(false, "should not even get here");
|
|
1404
1502
|
case messageTypes_js_1.ContainerMessageType.Rejoin:
|
|
1405
1503
|
break;
|
|
1504
|
+
case messageTypes_js_1.ContainerMessageType.DocumentSchemaChange:
|
|
1505
|
+
this.documentsSchemaController.processDocumentSchemaOp(messageWithContext.message.contents, messageWithContext.local, messageWithContext.message.sequenceNumber);
|
|
1506
|
+
break;
|
|
1406
1507
|
default: {
|
|
1407
1508
|
// If we didn't necessarily expect a runtime message type, then no worries - just return
|
|
1408
1509
|
// e.g. this case applies to system ops, or legacy ops that would have fallen into the above cases anyway.
|
|
@@ -1412,7 +1513,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1412
1513
|
const compatBehavior = messageWithContext.message.compatDetails?.behavior;
|
|
1413
1514
|
if (!compatBehaviorAllowsMessageType(messageWithContext.message.type, compatBehavior)) {
|
|
1414
1515
|
const { message } = messageWithContext;
|
|
1415
|
-
const error =
|
|
1516
|
+
const error = internal_7.DataProcessingError.create(
|
|
1416
1517
|
// Former assert 0x3ce
|
|
1417
1518
|
"Runtime message of unknown type", "OpProcessing", message, {
|
|
1418
1519
|
local,
|
|
@@ -1496,9 +1597,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1496
1597
|
* This method is expected to be called at the end of a batch.
|
|
1497
1598
|
*/
|
|
1498
1599
|
flush() {
|
|
1499
|
-
(0,
|
|
1600
|
+
(0, internal_2.assert)(this._orderSequentiallyCalls === 0, 0x24c /* "Cannot call `flush()` from `orderSequentially`'s callback" */);
|
|
1500
1601
|
this.outbox.flush();
|
|
1501
|
-
(0,
|
|
1602
|
+
(0, internal_2.assert)(this.outbox.isEmpty, 0x3cf /* reentrancy */);
|
|
1502
1603
|
}
|
|
1503
1604
|
/**
|
|
1504
1605
|
* {@inheritDoc @fluidframework/runtime-definitions#IContainerRuntimeBase.orderSequentially}
|
|
@@ -1523,15 +1624,15 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1523
1624
|
checkpoint.rollback((message) => this.rollback(message.contents, message.localOpMetadata));
|
|
1524
1625
|
}
|
|
1525
1626
|
catch (err) {
|
|
1526
|
-
const error2 = (0,
|
|
1527
|
-
return
|
|
1627
|
+
const error2 = (0, internal_7.wrapError)(err, (message) => {
|
|
1628
|
+
return internal_7.DataProcessingError.create(`RollbackError: ${message}`, "checkpointRollback", undefined);
|
|
1528
1629
|
});
|
|
1529
1630
|
this.closeFn(error2);
|
|
1530
1631
|
throw error2;
|
|
1531
1632
|
}
|
|
1532
1633
|
}
|
|
1533
1634
|
else {
|
|
1534
|
-
this.closeFn((0,
|
|
1635
|
+
this.closeFn((0, internal_7.wrapError)(error, (errorMessage) => new internal_7.GenericError(`orderSequentially callback exception: ${errorMessage}`, error, {
|
|
1535
1636
|
orderSequentiallyCalls: this._orderSequentiallyCalls,
|
|
1536
1637
|
})));
|
|
1537
1638
|
}
|
|
@@ -1541,7 +1642,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1541
1642
|
this._orderSequentiallyCalls--;
|
|
1542
1643
|
}
|
|
1543
1644
|
// We don't flush on TurnBased since we expect all messages in the same JS turn to be part of the same batch
|
|
1544
|
-
if (this.flushMode !==
|
|
1645
|
+
if (this.flushMode !== internal_5.FlushMode.TurnBased && this._orderSequentiallyCalls === 0) {
|
|
1545
1646
|
this.flush();
|
|
1546
1647
|
}
|
|
1547
1648
|
return result;
|
|
@@ -1570,7 +1671,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1570
1671
|
}
|
|
1571
1672
|
const channel = await context.realize();
|
|
1572
1673
|
if (channel.entryPoint === undefined) {
|
|
1573
|
-
throw new
|
|
1674
|
+
throw new internal_7.UsageError("entryPoint must be defined on data store runtime for using getAliasedDataStoreEntryPoint");
|
|
1574
1675
|
}
|
|
1575
1676
|
this.garbageCollector.nodeUpdated(`/${internalId}`, "Loaded", undefined /* timestampMs */, context.packagePath);
|
|
1576
1677
|
return channel.entryPoint;
|
|
@@ -1599,7 +1700,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1599
1700
|
* Are we in the middle of batching ops together?
|
|
1600
1701
|
*/
|
|
1601
1702
|
currentlyBatching() {
|
|
1602
|
-
return this.flushMode !==
|
|
1703
|
+
return this.flushMode !== internal_5.FlushMode.Immediate || this._orderSequentiallyCalls !== 0;
|
|
1603
1704
|
}
|
|
1604
1705
|
getQuorum() {
|
|
1605
1706
|
return this._quorum;
|
|
@@ -1633,6 +1734,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1633
1734
|
break;
|
|
1634
1735
|
}
|
|
1635
1736
|
case messageTypes_js_1.ContainerMessageType.IdAllocation:
|
|
1737
|
+
case messageTypes_js_1.ContainerMessageType.DocumentSchemaChange:
|
|
1636
1738
|
case messageTypes_js_1.ContainerMessageType.GC: {
|
|
1637
1739
|
return false;
|
|
1638
1740
|
}
|
|
@@ -1659,7 +1761,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1659
1761
|
/**
|
|
1660
1762
|
* Submits the signal to be sent to other clients.
|
|
1661
1763
|
* @param type - Type of the signal.
|
|
1662
|
-
* @param content - Content of the signal.
|
|
1764
|
+
* @param content - Content of the signal. Should be a JSON serializable object or primitive.
|
|
1663
1765
|
* @param targetClientId - When specified, the signal is only sent to the provided client id.
|
|
1664
1766
|
*/
|
|
1665
1767
|
submitSignal(type, content, targetClientId) {
|
|
@@ -1669,10 +1771,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1669
1771
|
}
|
|
1670
1772
|
setAttachState(attachState) {
|
|
1671
1773
|
if (attachState === container_definitions_1.AttachState.Attaching) {
|
|
1672
|
-
(0,
|
|
1774
|
+
(0, internal_2.assert)(this.attachState === container_definitions_1.AttachState.Attaching, 0x12d /* "Container Context should already be in attaching state" */);
|
|
1673
1775
|
}
|
|
1674
1776
|
else {
|
|
1675
|
-
(0,
|
|
1777
|
+
(0, internal_2.assert)(this.attachState === container_definitions_1.AttachState.Attached, 0x12e /* "Container Context should already be in attached state" */);
|
|
1676
1778
|
this.emit("attached");
|
|
1677
1779
|
}
|
|
1678
1780
|
if (attachState === container_definitions_1.AttachState.Attached && !this.hasPendingMessages()) {
|
|
@@ -1695,19 +1797,22 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1695
1797
|
// We can finalize any allocated IDs since we're the only client
|
|
1696
1798
|
const idRange = this._idCompressor?.takeNextCreationRange();
|
|
1697
1799
|
if (idRange !== undefined) {
|
|
1800
|
+
(0, internal_2.assert)(idRange.ids === undefined || idRange.ids.firstGenCount === 1, "No other ranges should be taken while container is detached.");
|
|
1698
1801
|
this._idCompressor?.finalizeCreationRange(idRange);
|
|
1699
1802
|
}
|
|
1700
1803
|
const summarizeResult = this.channelCollection.getAttachSummary(telemetryContext);
|
|
1701
1804
|
// Wrap data store summaries in .channels subtree.
|
|
1702
|
-
(0,
|
|
1805
|
+
(0, index_js_3.wrapSummaryInChannelsTree)(summarizeResult);
|
|
1703
1806
|
this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
|
|
1704
1807
|
return summarizeResult.summary;
|
|
1705
1808
|
}
|
|
1706
1809
|
async summarizeInternal(fullTree, trackState, telemetryContext) {
|
|
1707
1810
|
const summarizeResult = await this.channelCollection.summarize(fullTree, trackState, telemetryContext);
|
|
1708
1811
|
// Wrap data store summaries in .channels subtree.
|
|
1709
|
-
(0,
|
|
1710
|
-
const pathPartsForChildren = [
|
|
1812
|
+
(0, index_js_3.wrapSummaryInChannelsTree)(summarizeResult);
|
|
1813
|
+
const pathPartsForChildren = [internal_5.channelsTreeName];
|
|
1814
|
+
// Ensure that ID compressor had a chance to load, if we are using delayed mode.
|
|
1815
|
+
await this.loadIdCompressor();
|
|
1711
1816
|
this.addContainerStateToSummary(summarizeResult, fullTree, trackState, telemetryContext);
|
|
1712
1817
|
return {
|
|
1713
1818
|
...summarizeResult,
|
|
@@ -1721,7 +1826,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1721
1826
|
async summarize(options) {
|
|
1722
1827
|
this.verifyNotClosed();
|
|
1723
1828
|
const { fullTree = false, trackState = true, summaryLogger = this.mc.logger, runGC = this.garbageCollector.shouldRunGC, runSweep, fullGC, } = options;
|
|
1724
|
-
const telemetryContext = new
|
|
1829
|
+
const telemetryContext = new internal_6.TelemetryContext();
|
|
1725
1830
|
// Add the options that are used to generate this summary to the telemetry context.
|
|
1726
1831
|
telemetryContext.setMultiple("fluid_Summarize", "Options", {
|
|
1727
1832
|
fullTree,
|
|
@@ -1735,7 +1840,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1735
1840
|
await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC }, telemetryContext);
|
|
1736
1841
|
}
|
|
1737
1842
|
const { stats, summary } = await this.summarizerNode.summarize(fullTree, trackState, telemetryContext);
|
|
1738
|
-
(0,
|
|
1843
|
+
(0, internal_2.assert)(summary.type === protocol_definitions_1.SummaryType.Tree, 0x12f /* "Container Runtime's summarize should always return a tree" */);
|
|
1739
1844
|
return { stats, summary };
|
|
1740
1845
|
}
|
|
1741
1846
|
finally {
|
|
@@ -1763,7 +1868,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1763
1868
|
* @see IGarbageCollectionRuntime.getGCData
|
|
1764
1869
|
*/
|
|
1765
1870
|
async getGCData(fullGC) {
|
|
1766
|
-
const builder = new
|
|
1871
|
+
const builder = new internal_6.GCDataBuilder();
|
|
1767
1872
|
const dsGCData = await this.summarizerNode.getGCData(fullGC);
|
|
1768
1873
|
builder.addNodes(dsGCData.gcNodes);
|
|
1769
1874
|
const blobsGCData = this.blobManager.getGCData(fullGC);
|
|
@@ -1820,9 +1925,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1820
1925
|
*/
|
|
1821
1926
|
getNodeType(nodePath) {
|
|
1822
1927
|
if (this.isBlobPath(nodePath)) {
|
|
1823
|
-
return
|
|
1928
|
+
return index_js_1.GCNodeType.Blob;
|
|
1824
1929
|
}
|
|
1825
|
-
return this.channelCollection.getGCNodeType(nodePath) ??
|
|
1930
|
+
return this.channelCollection.getGCNodeType(nodePath) ?? index_js_1.GCNodeType.Other;
|
|
1826
1931
|
}
|
|
1827
1932
|
/**
|
|
1828
1933
|
* Called by GC to retrieve the package path of the node with the given path. The node should belong to a
|
|
@@ -1835,13 +1940,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1835
1940
|
return ["_gcRoot"];
|
|
1836
1941
|
}
|
|
1837
1942
|
switch (this.getNodeType(nodePath)) {
|
|
1838
|
-
case
|
|
1943
|
+
case index_js_1.GCNodeType.Blob:
|
|
1839
1944
|
return [blobManager_js_1.BlobManager.basePath];
|
|
1840
|
-
case
|
|
1841
|
-
case
|
|
1945
|
+
case index_js_1.GCNodeType.DataStore:
|
|
1946
|
+
case index_js_1.GCNodeType.SubDataStore:
|
|
1842
1947
|
return this.channelCollection.getDataStorePackagePath(nodePath);
|
|
1843
1948
|
default:
|
|
1844
|
-
(0,
|
|
1949
|
+
(0, internal_2.assert)(false, 0x2de /* "Package path requested for unsupported node type." */);
|
|
1845
1950
|
}
|
|
1846
1951
|
}
|
|
1847
1952
|
/**
|
|
@@ -1902,16 +2007,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1902
2007
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
1903
2008
|
// use it for all events logged during this summary.
|
|
1904
2009
|
const summaryNumber = this.nextSummaryNumber;
|
|
1905
|
-
const summaryNumberLogger = (0,
|
|
2010
|
+
const summaryNumberLogger = (0, internal_7.createChildLogger)({
|
|
1906
2011
|
logger: summaryLogger,
|
|
1907
2012
|
properties: {
|
|
1908
2013
|
all: { summaryNumber },
|
|
1909
2014
|
},
|
|
1910
2015
|
});
|
|
1911
|
-
(0,
|
|
2016
|
+
(0, internal_2.assert)(this.outbox.isEmpty, 0x3d1 /* Can't trigger summary in the middle of a batch */);
|
|
1912
2017
|
// We close the summarizer and download a new snapshot and reload the container
|
|
1913
2018
|
if (refreshLatestAck === true) {
|
|
1914
|
-
return this.prefetchLatestSummaryThenClose((0,
|
|
2019
|
+
return this.prefetchLatestSummaryThenClose((0, internal_7.createChildLogger)({
|
|
1915
2020
|
logger: summaryNumberLogger,
|
|
1916
2021
|
properties: { all: { safeSummary: true } },
|
|
1917
2022
|
}));
|
|
@@ -1995,7 +2100,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1995
2100
|
// That said, we rely on submitSystemMessage() that today only works in connected state.
|
|
1996
2101
|
// So if we fail here, it either means that RunWhileConnectedCoordinator does not work correctly,
|
|
1997
2102
|
// OR that design changed and we need to remove this check and fix submitSystemMessage.
|
|
1998
|
-
(0,
|
|
2103
|
+
(0, internal_2.assert)(this.connected, 0x258 /* "connected" */);
|
|
1999
2104
|
// Ensure that lastSequenceNumber has not changed after pausing.
|
|
2000
2105
|
// We need the summary op's reference sequence number to match our summary sequence number,
|
|
2001
2106
|
// otherwise we'll get the wrong sequence number stamped on the summary's .protocol attributes.
|
|
@@ -2005,7 +2110,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2005
2110
|
error: `lastSequenceNumber changed before uploading to storage. ${this.deltaManager.lastSequenceNumber} !== ${summaryRefSeqNum}`,
|
|
2006
2111
|
};
|
|
2007
2112
|
}
|
|
2008
|
-
(0,
|
|
2113
|
+
(0, internal_2.assert)(summaryRefSeqNum === this.deltaManager.lastMessage?.sequenceNumber, 0x395 /* it's one and the same thing */);
|
|
2009
2114
|
if (lastAck !== this.summaryCollection.latestAck) {
|
|
2010
2115
|
return {
|
|
2011
2116
|
continue: false,
|
|
@@ -2050,7 +2155,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2050
2155
|
const validateResult = this.summarizerNode.validateSummary();
|
|
2051
2156
|
if (!validateResult.success) {
|
|
2052
2157
|
const { success, ...loggingProps } = validateResult;
|
|
2053
|
-
const error = new
|
|
2158
|
+
const error = new index_js_3.RetriableSummaryError(validateResult.reason, validateResult.retryAfterSeconds, { ...loggingProps });
|
|
2054
2159
|
return {
|
|
2055
2160
|
stage: "base",
|
|
2056
2161
|
referenceSequenceNumber: summaryRefSeqNum,
|
|
@@ -2069,11 +2174,11 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2069
2174
|
// Counting dataStores and handles
|
|
2070
2175
|
// Because handles are unchanged dataStores in the current logic,
|
|
2071
2176
|
// summarized dataStore count is total dataStore count minus handle count
|
|
2072
|
-
const dataStoreTree = summaryTree.tree[
|
|
2073
|
-
(0,
|
|
2177
|
+
const dataStoreTree = summaryTree.tree[internal_5.channelsTreeName];
|
|
2178
|
+
(0, internal_2.assert)(dataStoreTree.type === protocol_definitions_1.SummaryType.Tree, 0x1fc /* "summary is not a tree" */);
|
|
2074
2179
|
const handleCount = Object.values(dataStoreTree.tree).filter((value) => value.type === protocol_definitions_1.SummaryType.Handle).length;
|
|
2075
|
-
const gcSummaryTreeStats = summaryTree.tree[
|
|
2076
|
-
? (0,
|
|
2180
|
+
const gcSummaryTreeStats = summaryTree.tree[internal_5.gcTreeKey]
|
|
2181
|
+
? (0, internal_6.calculateStats)(summaryTree.tree[internal_5.gcTreeKey])
|
|
2077
2182
|
: undefined;
|
|
2078
2183
|
const summaryStats = {
|
|
2079
2184
|
dataStoreCount: this.channelCollection.size,
|
|
@@ -2184,7 +2289,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2184
2289
|
// the summarizer.
|
|
2185
2290
|
if (finalAttempt &&
|
|
2186
2291
|
this.mc.config.getBoolean("Fluid.Summarizer.SkipFailingIncorrectSummary")) {
|
|
2187
|
-
const error =
|
|
2292
|
+
const error = internal_7.DataProcessingError.create("Pending ops during summarization", "submitSummary", undefined, { pendingMessages: this.pendingMessagesCount });
|
|
2188
2293
|
logger.sendErrorEvent({
|
|
2189
2294
|
eventName: "SkipFailingIncorrectSummary",
|
|
2190
2295
|
referenceSequenceNumber,
|
|
@@ -2197,7 +2302,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2197
2302
|
// based on telemetry while we decide on a stable number.
|
|
2198
2303
|
const retryDelayMs = this.mc.config.getNumber("Fluid.Summarizer.PendingOpsRetryDelayMs") ??
|
|
2199
2304
|
exports.defaultPendingOpsRetryDelayMs;
|
|
2200
|
-
const error = new
|
|
2305
|
+
const error = new index_js_3.RetriableSummaryError("PendingOpsWhileSummarizing", retryDelayMs / 1000, {
|
|
2201
2306
|
count: this.pendingMessagesCount,
|
|
2202
2307
|
beforeGenerate: beforeSummaryGeneration,
|
|
2203
2308
|
});
|
|
@@ -2217,11 +2322,11 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2217
2322
|
}
|
|
2218
2323
|
updateDocumentDirtyState(dirty) {
|
|
2219
2324
|
if (this.attachState !== container_definitions_1.AttachState.Attached) {
|
|
2220
|
-
(0,
|
|
2325
|
+
(0, internal_2.assert)(dirty, 0x3d2 /* Non-attached container is dirty */);
|
|
2221
2326
|
}
|
|
2222
2327
|
else {
|
|
2223
2328
|
// Other way is not true = see this.isContainerMessageDirtyable()
|
|
2224
|
-
(0,
|
|
2329
|
+
(0, internal_2.assert)(!dirty || this.hasPendingMessages(), 0x3d3 /* if doc is dirty, there has to be pending ops */);
|
|
2225
2330
|
}
|
|
2226
2331
|
if (this.dirtyContainer === dirty) {
|
|
2227
2332
|
return;
|
|
@@ -2250,19 +2355,18 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2250
2355
|
const idAllocationBatchMessage = {
|
|
2251
2356
|
contents: JSON.stringify(idAllocationMessage),
|
|
2252
2357
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2253
|
-
metadata: undefined,
|
|
2254
|
-
localOpMetadata: undefined,
|
|
2255
|
-
type: messageTypes_js_1.ContainerMessageType.IdAllocation,
|
|
2256
2358
|
};
|
|
2257
2359
|
this.outbox.submitIdAllocation(idAllocationBatchMessage);
|
|
2258
2360
|
}
|
|
2259
2361
|
}
|
|
2260
2362
|
}
|
|
2261
|
-
submit(containerRuntimeMessage, localOpMetadata = undefined, metadata
|
|
2363
|
+
submit(containerRuntimeMessage, localOpMetadata = undefined, metadata) {
|
|
2262
2364
|
this.verifyNotClosed();
|
|
2263
2365
|
this.verifyCanSubmitOps();
|
|
2264
2366
|
// There should be no ops in detached container state!
|
|
2265
|
-
(0,
|
|
2367
|
+
(0, internal_2.assert)(this.attachState !== container_definitions_1.AttachState.Detached, 0x132 /* "sending ops in detached container" */);
|
|
2368
|
+
(0, internal_2.assert)(metadata === undefined ||
|
|
2369
|
+
containerRuntimeMessage.type === messageTypes_js_1.ContainerMessageType.BlobAttach, "metadata");
|
|
2266
2370
|
const serializedContent = JSON.stringify(containerRuntimeMessage);
|
|
2267
2371
|
// Note that the real (non-proxy) delta manager is used here to get the readonly info. This is because
|
|
2268
2372
|
// container runtime's ability to submit ops depend on the actual readonly state of the delta manager.
|
|
@@ -2275,7 +2379,6 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2275
2379
|
const type = containerRuntimeMessage.type;
|
|
2276
2380
|
const message = {
|
|
2277
2381
|
contents: serializedContent,
|
|
2278
|
-
type,
|
|
2279
2382
|
metadata,
|
|
2280
2383
|
localOpMetadata,
|
|
2281
2384
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
@@ -2290,6 +2393,20 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2290
2393
|
}
|
|
2291
2394
|
else {
|
|
2292
2395
|
this.submitIdAllocationOpIfNeeded();
|
|
2396
|
+
// Allow document schema controller to send a message if it needs to propose change in document schema.
|
|
2397
|
+
// If it needs to send a message, it will call provided callback with payload of such message and rely
|
|
2398
|
+
// on this callback to do actual sending.
|
|
2399
|
+
const contents = this.documentsSchemaController.maybeSendSchemaMessage();
|
|
2400
|
+
if (contents) {
|
|
2401
|
+
const msg = {
|
|
2402
|
+
type: messageTypes_js_1.ContainerMessageType.DocumentSchemaChange,
|
|
2403
|
+
contents,
|
|
2404
|
+
};
|
|
2405
|
+
this.outbox.submit({
|
|
2406
|
+
contents: JSON.stringify(msg),
|
|
2407
|
+
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2408
|
+
});
|
|
2409
|
+
}
|
|
2293
2410
|
// If this is attach message for new data store, and we are in a batch, send this op out of order
|
|
2294
2411
|
// Is it safe:
|
|
2295
2412
|
// Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
|
|
@@ -2353,29 +2470,29 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2353
2470
|
}
|
|
2354
2471
|
};
|
|
2355
2472
|
switch (this.flushMode) {
|
|
2356
|
-
case
|
|
2473
|
+
case internal_5.FlushMode.TurnBased:
|
|
2357
2474
|
// When in TurnBased flush mode the runtime will buffer operations in the current turn and send them as a single
|
|
2358
2475
|
// batch at the end of the turn
|
|
2359
2476
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
2360
2477
|
Promise.resolve().then(flush);
|
|
2361
2478
|
break;
|
|
2362
2479
|
// FlushModeExperimental is experimental and not exposed directly in the runtime APIs
|
|
2363
|
-
case
|
|
2480
|
+
case internal_5.FlushModeExperimental.Async:
|
|
2364
2481
|
// When in Async flush mode, the runtime will accumulate all operations across JS turns and send them as a single
|
|
2365
2482
|
// batch when all micro-tasks are complete.
|
|
2366
2483
|
// Compared to TurnBased, this flush mode will capture more ops into the same batch.
|
|
2367
2484
|
setTimeout(flush, 0);
|
|
2368
2485
|
break;
|
|
2369
2486
|
default:
|
|
2370
|
-
(0,
|
|
2487
|
+
(0, internal_2.assert)(this._orderSequentiallyCalls > 0, 0x587 /* Unreachable unless running under orderSequentially */);
|
|
2371
2488
|
break;
|
|
2372
2489
|
}
|
|
2373
2490
|
}
|
|
2374
2491
|
submitSummaryMessage(contents, referenceSequenceNumber) {
|
|
2375
2492
|
this.verifyNotClosed();
|
|
2376
|
-
(0,
|
|
2493
|
+
(0, internal_2.assert)(this.connected, 0x133 /* "Container disconnected when trying to submit system message" */);
|
|
2377
2494
|
// System message should not be sent in the middle of the batch.
|
|
2378
|
-
(0,
|
|
2495
|
+
(0, internal_2.assert)(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
|
|
2379
2496
|
// back-compat: ADO #1385: Make this call unconditional in the future
|
|
2380
2497
|
return this.submitSummaryFn !== undefined
|
|
2381
2498
|
? this.submitSummaryFn(contents, referenceSequenceNumber)
|
|
@@ -2396,7 +2513,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2396
2513
|
if (this.opReentryCallsToReport > 0) {
|
|
2397
2514
|
this.mc.logger.sendTelemetryEvent({ eventName: "OpReentry" },
|
|
2398
2515
|
// We need to capture the call stack in order to inspect the source of this usage pattern
|
|
2399
|
-
(0,
|
|
2516
|
+
(0, index_js_2.getLongStack)(() => new internal_7.UsageError(errorMessage)));
|
|
2400
2517
|
this.opReentryCallsToReport--;
|
|
2401
2518
|
}
|
|
2402
2519
|
// Creating ops while processing ops can lead
|
|
@@ -2412,7 +2529,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2412
2529
|
// The runtime must enforce op coherence by not allowing ops to be submitted
|
|
2413
2530
|
// while ops are being processed.
|
|
2414
2531
|
if (this.enableOpReentryCheck) {
|
|
2415
|
-
throw new
|
|
2532
|
+
throw new internal_7.UsageError(errorMessage);
|
|
2416
2533
|
}
|
|
2417
2534
|
}
|
|
2418
2535
|
}
|
|
@@ -2437,7 +2554,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2437
2554
|
* @param localOpMetadata - The local metadata associated with the original message.
|
|
2438
2555
|
*/
|
|
2439
2556
|
reSubmitCore(message, localOpMetadata, opMetadata) {
|
|
2440
|
-
(0,
|
|
2557
|
+
(0, internal_2.assert)(!this.isSummarizerClient, 0x8f2 /* Summarizer never reconnects so should never resubmit */);
|
|
2441
2558
|
switch (message.type) {
|
|
2442
2559
|
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp:
|
|
2443
2560
|
case messageTypes_js_1.ContainerMessageType.Attach:
|
|
@@ -2461,6 +2578,11 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2461
2578
|
case messageTypes_js_1.ContainerMessageType.GC:
|
|
2462
2579
|
this.submit(message);
|
|
2463
2580
|
break;
|
|
2581
|
+
case messageTypes_js_1.ContainerMessageType.DocumentSchemaChange:
|
|
2582
|
+
// There is no need to resend this message. Document schema controller will properly resend it again (if needed)
|
|
2583
|
+
// on a first occasion (any ops sent after reconnect). There is a good chance, though, that it will not want to
|
|
2584
|
+
// send any ops, as some other client already changed schema.
|
|
2585
|
+
break;
|
|
2464
2586
|
default: {
|
|
2465
2587
|
// This case should be very rare - it would imply an op was stashed from a
|
|
2466
2588
|
// future version of runtime code and now is being applied on an older version.
|
|
@@ -2473,7 +2595,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2473
2595
|
});
|
|
2474
2596
|
}
|
|
2475
2597
|
else {
|
|
2476
|
-
const error =
|
|
2598
|
+
const error = internal_7.DataProcessingError.create("Resubmitting runtime message of unknown type", "reSubmitCore", undefined /* sequencedMessage */, {
|
|
2477
2599
|
messageDetails: JSON.stringify({
|
|
2478
2600
|
type: message.type,
|
|
2479
2601
|
compatBehavior,
|
|
@@ -2503,8 +2625,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2503
2625
|
async refreshLatestSummaryAck(options) {
|
|
2504
2626
|
const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options;
|
|
2505
2627
|
// proposalHandle is always passed from RunningSummarizer.
|
|
2506
|
-
(0,
|
|
2507
|
-
const readAndParseBlob = async (id) => (0,
|
|
2628
|
+
(0, internal_2.assert)(proposalHandle !== undefined, 0x766 /* proposalHandle should be available */);
|
|
2629
|
+
const readAndParseBlob = async (id) => (0, internal_4.readAndParse)(this.storage, id);
|
|
2508
2630
|
const result = await this.summarizerNode.refreshLatestSummary(proposalHandle, summaryRefSeq);
|
|
2509
2631
|
/**
|
|
2510
2632
|
* When refreshing a summary ack, this check indicates a new ack of a summary that is newer than the
|
|
@@ -2531,7 +2653,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2531
2653
|
* @returns a generic summarization error
|
|
2532
2654
|
*/
|
|
2533
2655
|
async prefetchLatestSummaryThenClose(summaryLogger) {
|
|
2534
|
-
const readAndParseBlob = async (id) => (0,
|
|
2656
|
+
const readAndParseBlob = async (id) => (0, internal_4.readAndParse)(this.storage, id);
|
|
2535
2657
|
// This is a performance optimization as the same parent is likely to be elected again, and would use its
|
|
2536
2658
|
// cache to fetch the snapshot instead of the network.
|
|
2537
2659
|
await this.fetchLatestSnapshotFromStorage(summaryLogger, {
|
|
@@ -2547,7 +2669,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2547
2669
|
}
|
|
2548
2670
|
async closeStaleSummarizer() {
|
|
2549
2671
|
// Delay before restarting summarizer to prevent the summarizer from restarting too frequently.
|
|
2550
|
-
await (0,
|
|
2672
|
+
await (0, internal_2.delay)(this.closeSummarizerDelayMs);
|
|
2551
2673
|
this._summarizer?.stop("latestSummaryStateStale");
|
|
2552
2674
|
this.disposeFn();
|
|
2553
2675
|
}
|
|
@@ -2557,16 +2679,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2557
2679
|
* overridden via options.
|
|
2558
2680
|
*/
|
|
2559
2681
|
async fetchLatestSnapshotFromStorage(logger, event, readAndParseBlob) {
|
|
2560
|
-
return
|
|
2682
|
+
return internal_7.PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
|
|
2561
2683
|
const stats = {};
|
|
2562
2684
|
const trace = client_utils_1.Trace.start();
|
|
2563
|
-
const versions = await this.storage.getVersions(null, 1, "prefetchLatestSummaryBeforeClose",
|
|
2564
|
-
(0,
|
|
2685
|
+
const versions = await this.storage.getVersions(null, 1, "prefetchLatestSummaryBeforeClose", internal_3.FetchSource.noCache);
|
|
2686
|
+
(0, internal_2.assert)(!!versions && !!versions[0], 0x137 /* "Failed to get version from storage" */);
|
|
2565
2687
|
stats.getVersionDuration = trace.trace().duration;
|
|
2566
2688
|
const maybeSnapshot = await this.storage.getSnapshotTree(versions[0]);
|
|
2567
|
-
(0,
|
|
2689
|
+
(0, internal_2.assert)(!!maybeSnapshot, 0x138 /* "Failed to get snapshot from storage" */);
|
|
2568
2690
|
stats.getSnapshotDuration = trace.trace().duration;
|
|
2569
|
-
const latestSnapshotRefSeq = await (0,
|
|
2691
|
+
const latestSnapshotRefSeq = await (0, internal_6.seqFromTree)(maybeSnapshot, readAndParseBlob);
|
|
2570
2692
|
stats.snapshotRefSeq = latestSnapshotRefSeq;
|
|
2571
2693
|
stats.snapshotVersion = versions[0].id;
|
|
2572
2694
|
perfEvent.end(stats);
|
|
@@ -2580,7 +2702,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2580
2702
|
getPendingLocalState(props) {
|
|
2581
2703
|
this.verifyNotClosed();
|
|
2582
2704
|
if (this._orderSequentiallyCalls !== 0) {
|
|
2583
|
-
throw new
|
|
2705
|
+
throw new internal_7.UsageError("can't get state during orderSequentially");
|
|
2584
2706
|
}
|
|
2585
2707
|
this.imminentClosure || (this.imminentClosure = props?.notifyImminentClosure ?? false);
|
|
2586
2708
|
const getSyncState = (pendingAttachmentBlobs) => {
|
|
@@ -2612,8 +2734,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2612
2734
|
// to close current batch.
|
|
2613
2735
|
this.flush();
|
|
2614
2736
|
return props?.notifyImminentClosure === true
|
|
2615
|
-
?
|
|
2616
|
-
:
|
|
2737
|
+
? internal_7.PerformanceEvent.timedExecAsync(this.mc.logger, perfEvent, async (event) => logAndReturnPendingState(event, getSyncState(await this.blobManager.attachAndGetPendingBlobs(props?.stopBlobAttachingSignal))))
|
|
2738
|
+
: internal_7.PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) => logAndReturnPendingState(event, getSyncState()));
|
|
2617
2739
|
}
|
|
2618
2740
|
summarizeOnDemand(options) {
|
|
2619
2741
|
if (this.isSummarizerClient) {
|
|
@@ -2626,7 +2748,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2626
2748
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
2627
2749
|
// disableSummaries is turned on. We are throwing instead of returning a failure here,
|
|
2628
2750
|
// because it is a misuse of the API rather than an expected failure.
|
|
2629
|
-
throw new
|
|
2751
|
+
throw new internal_7.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
2630
2752
|
}
|
|
2631
2753
|
}
|
|
2632
2754
|
enqueueSummarize(options) {
|
|
@@ -2640,7 +2762,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2640
2762
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
2641
2763
|
// generateSummaries is turned off. We are throwing instead of returning a failure here,
|
|
2642
2764
|
// because it is a misuse of the API rather than an expected failure.
|
|
2643
|
-
throw new
|
|
2765
|
+
throw new internal_7.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
2644
2766
|
}
|
|
2645
2767
|
}
|
|
2646
2768
|
/**
|
|
@@ -2655,16 +2777,15 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2655
2777
|
// eslint-disable-next-line no-restricted-syntax
|
|
2656
2778
|
for (const prop in configuration) {
|
|
2657
2779
|
if (typeof configuration[prop] === "number" && configuration[prop] < 0) {
|
|
2658
|
-
throw new
|
|
2780
|
+
throw new internal_7.UsageError(`Summary heuristic configuration property "${prop}" cannot be less than 0`);
|
|
2659
2781
|
}
|
|
2660
2782
|
}
|
|
2661
2783
|
if (configuration.minIdleTime > configuration.maxIdleTime) {
|
|
2662
|
-
throw new
|
|
2784
|
+
throw new internal_7.UsageError(`"minIdleTime" [${configuration.minIdleTime}] cannot be greater than "maxIdleTime" [${configuration.maxIdleTime}]`);
|
|
2663
2785
|
}
|
|
2664
2786
|
}
|
|
2665
2787
|
get groupedBatchingEnabled() {
|
|
2666
|
-
|
|
2667
|
-
return killSwitch !== true && this.runtimeOptions.enableGroupedBatching;
|
|
2788
|
+
return this.documentSchema.opGroupingEnabled === true;
|
|
2668
2789
|
}
|
|
2669
2790
|
}
|
|
2670
2791
|
exports.ContainerRuntime = ContainerRuntime;
|