@fluidframework/container-runtime 2.0.0-dev-rc.2.0.0.245554 → 2.0.0-dev-rc.3.0.0.250606
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 +81 -27
- package/dist/batchTracker.d.ts +1 -1
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +2 -2
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +3 -3
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +3 -3
- package/dist/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +6 -5
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +57 -19
- package/dist/channelCollection.js.map +1 -1
- package/dist/connectionTelemetry.d.ts +2 -2
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +3 -3
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/container-runtime-alpha.d.ts +205 -12
- package/dist/container-runtime-beta.d.ts +16 -3
- package/dist/container-runtime-public.d.ts +16 -3
- package/dist/container-runtime-untrimmed.d.ts +207 -26
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +32 -26
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +235 -133
- 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 +2 -2
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +4 -4
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +18 -18
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts +4 -0
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +2 -2
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/deltaScheduler.d.ts +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +1 -1
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +1 -1
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +1 -1
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +1 -1
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +1 -1
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +1 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.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/definitions.d.ts +1 -19
- 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 +2 -3
- 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 +60 -61
- 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 +9 -11
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +11 -3
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +48 -38
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +18 -17
- 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 -32
- 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.map +1 -1
- package/dist/scheduleManager.d.ts +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +6 -2
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +178 -0
- package/dist/summary/documentSchema.d.ts.map +1 -0
- package/dist/summary/documentSchema.js +345 -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 +7 -2
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +2 -2
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +2 -2
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +2 -2
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +2 -2
- 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.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +2 -2
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +3 -3
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +3 -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 +1 -1
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +5 -16
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +2 -2
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +2 -2
- 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 +2 -2
- 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 +3 -3
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +5 -5
- package/lib/blobManager.js.map +1 -1
- package/lib/channelCollection.d.ts +6 -5
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +59 -21
- package/lib/channelCollection.js.map +1 -1
- package/lib/connectionTelemetry.d.ts +2 -2
- 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 +205 -12
- package/lib/container-runtime-beta.d.ts +16 -3
- package/lib/container-runtime-public.d.ts +16 -3
- package/lib/container-runtime-untrimmed.d.ts +207 -26
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +32 -26
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +197 -95
- 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 +4 -4
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +3 -3
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts +4 -0
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.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/gc/garbageCollection.d.ts +1 -1
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +3 -3
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts +1 -1
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +1 -1
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +1 -1
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +1 -1
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +1 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +1 -1
- package/lib/gc/gcTelemetry.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/definitions.d.ts +1 -19
- 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 +60 -61
- 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 +7 -10
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +11 -3
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +46 -37
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +18 -17
- 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 -32
- 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.map +1 -1
- package/lib/scheduleManager.d.ts +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +6 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +178 -0
- package/lib/summary/documentSchema.d.ts.map +1 -0
- package/lib/summary/documentSchema.js +341 -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 +7 -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.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +2 -2
- 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 +2 -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.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +2 -2
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +4 -4
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +3 -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 +5 -16
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js +1 -1
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +2 -2
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +3 -3
- 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 +2 -2
- package/lib/summary/summaryManager.js.map +1 -1
- package/lib/test/blobManager.spec.js +3 -3
- package/lib/test/blobManager.spec.js.map +1 -1
- package/lib/test/containerRuntime.spec.js +6 -4
- package/lib/test/containerRuntime.spec.js.map +1 -1
- package/lib/test/dataStoreContext.spec.js +4 -4
- package/lib/test/dataStoreContext.spec.js.map +1 -1
- package/lib/test/dataStoreCreation.spec.js +1 -1
- package/lib/test/dataStoreCreation.spec.js.map +1 -1
- package/lib/test/dataStoreRegistry.spec.js.map +1 -1
- package/lib/test/documentSchema.spec.js +282 -0
- package/lib/test/documentSchema.spec.js.map +1 -0
- package/lib/test/fuzz/fuzzUtils.js +11 -7
- package/lib/test/fuzz/fuzzUtils.js.map +1 -1
- package/lib/test/fuzz/summarizer.fuzz.spec.js +9 -7
- package/lib/test/fuzz/summarizer.fuzz.spec.js.map +1 -1
- package/lib/test/fuzz/summarizerFuzzMocks.js +43 -25
- package/lib/test/fuzz/summarizerFuzzMocks.js.map +1 -1
- package/lib/test/fuzz/summarizerFuzzSuite.js +7 -4
- package/lib/test/fuzz/summarizerFuzzSuite.js.map +1 -1
- package/lib/test/gc/garbageCollection.spec.js +5 -5
- package/lib/test/gc/garbageCollection.spec.js.map +1 -1
- package/lib/test/gc/gcConfigs.spec.js +2 -2
- package/lib/test/gc/gcConfigs.spec.js.map +1 -1
- package/lib/test/gc/gcHelpers.spec.js.map +1 -1
- package/lib/test/gc/gcStats.spec.js +2 -2
- package/lib/test/gc/gcStats.spec.js.map +1 -1
- package/lib/test/gc/gcSummaryStateTracker.spec.js +1 -1
- package/lib/test/gc/gcSummaryStateTracker.spec.js.map +1 -1
- package/lib/test/gc/gcTelemetry.spec.js +3 -3
- package/lib/test/gc/gcTelemetry.spec.js.map +1 -1
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js +1 -1
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js.map +1 -1
- package/lib/test/getPendingBlobs.spec.js +1 -1
- package/lib/test/getPendingBlobs.spec.js.map +1 -1
- package/lib/test/hardwareStats.spec.js +1 -1
- package/lib/test/hardwareStats.spec.js.map +1 -1
- package/lib/test/opLifecycle/OpGroupingManager.spec.js +95 -118
- package/lib/test/opLifecycle/OpGroupingManager.spec.js.map +1 -1
- package/lib/test/opLifecycle/batchManager.spec.js +1 -1
- package/lib/test/opLifecycle/batchManager.spec.js.map +1 -1
- package/lib/test/opLifecycle/opCompressor.spec.js +0 -1
- package/lib/test/opLifecycle/opCompressor.spec.js.map +1 -1
- package/lib/test/opLifecycle/opDecompressor.spec.js +60 -55
- package/lib/test/opLifecycle/opDecompressor.spec.js.map +1 -1
- package/lib/test/opLifecycle/opSplitter.spec.js +56 -41
- package/lib/test/opLifecycle/opSplitter.spec.js.map +1 -1
- package/lib/test/opLifecycle/outbox.spec.js +118 -10
- package/lib/test/opLifecycle/outbox.spec.js.map +1 -1
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js +115 -91
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js.map +1 -1
- package/lib/test/pendingStateManager.spec.js +1 -1
- package/lib/test/pendingStateManager.spec.js.map +1 -1
- package/lib/test/scheduleManager.spec.js +1 -1
- package/lib/test/scheduleManager.spec.js.map +1 -1
- package/lib/test/summarizerNode.spec.js +1 -1
- package/lib/test/summarizerNode.spec.js.map +1 -1
- package/lib/test/summarizerNodeWithGc.spec.js +1 -1
- package/lib/test/summarizerNodeWithGc.spec.js.map +1 -1
- package/lib/test/summary/runningSummarizer.spec.js +4 -4
- package/lib/test/summary/runningSummarizer.spec.js.map +1 -1
- package/lib/test/summary/summarizer.spec.js.map +1 -1
- package/lib/test/summary/summarizerClientElection.spec.js +2 -2
- package/lib/test/summary/summarizerClientElection.spec.js.map +1 -1
- package/lib/test/summary/summarizerHeuristics.spec.js +1 -1
- package/lib/test/summary/summarizerHeuristics.spec.js.map +1 -1
- package/lib/test/summary/summaryCollection.spec.js +1 -1
- package/lib/test/summary/summaryCollection.spec.js.map +1 -1
- package/lib/test/summary/summaryManager.spec.js +3 -3
- package/lib/test/summary/summaryManager.spec.js.map +1 -1
- package/lib/test/throttler.spec.js +1 -1
- package/lib/test/throttler.spec.js.map +1 -1
- package/lib/test/types/validateContainerRuntimePrevious.generated.js +6 -4
- package/lib/test/types/validateContainerRuntimePrevious.generated.js.map +1 -1
- package/package.json +35 -21
- package/src/batchTracker.ts +3 -3
- package/src/blobManager.ts +15 -15
- package/src/channelCollection.ts +90 -44
- package/src/connectionTelemetry.ts +10 -10
- package/src/containerHandleContext.ts +1 -1
- package/src/containerRuntime.ts +375 -213
- package/src/dataStore.ts +2 -2
- package/src/dataStoreContext.ts +19 -19
- package/src/dataStoreContexts.ts +2 -2
- package/src/dataStoreRegistry.ts +2 -1
- package/src/deltaScheduler.ts +1 -1
- package/src/gc/garbageCollection.ts +12 -12
- package/src/gc/gcConfigs.ts +11 -11
- package/src/gc/gcDefinitions.ts +2 -2
- package/src/gc/gcHelpers.ts +2 -2
- package/src/gc/gcSummaryStateTracker.ts +4 -4
- package/src/gc/gcTelemetry.ts +6 -6
- package/src/index.ts +8 -1
- package/src/messageTypes.ts +18 -5
- package/src/opLifecycle/README.md +89 -0
- package/src/opLifecycle/definitions.ts +1 -20
- package/src/opLifecycle/index.ts +3 -9
- package/src/opLifecycle/opCompressor.ts +4 -5
- package/src/opLifecycle/opDecompressor.ts +83 -100
- package/src/opLifecycle/opGroupingManager.ts +9 -12
- package/src/opLifecycle/opSplitter.ts +73 -47
- package/src/opLifecycle/outbox.ts +26 -37
- package/src/opLifecycle/remoteMessageProcessor.ts +41 -55
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +2 -2
- package/src/scheduleManager.ts +8 -7
- package/src/summary/documentSchema.ts +553 -0
- package/src/summary/index.ts +10 -1
- package/src/summary/orderedClientElection.ts +7 -5
- package/src/summary/runWhileConnectedCoordinator.ts +1 -1
- package/src/summary/runningSummarizer.ts +19 -19
- package/src/summary/summarizer.ts +14 -14
- package/src/summary/summarizerClientElection.ts +2 -2
- package/src/summary/summarizerHeuristics.ts +2 -2
- package/src/summary/summarizerNode/summarizerNode.ts +15 -15
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +1 -1
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +4 -4
- package/src/summary/summarizerTypes.ts +3 -3
- package/src/summary/summaryCollection.ts +3 -3
- package/src/summary/summaryFormat.ts +8 -19
- package/src/summary/summaryGenerator.ts +10 -10
- package/src/summary/summaryManager.ts +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gcSummaryStateTracker.spec.js","sourceRoot":"","sources":["../../../src/test/gc/gcSummaryStateTracker.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { gcDeletedBlobKey, gcTombstoneBlobKey } from \"@fluidframework/runtime-definitions\";\nimport {\n\tnextGCVersion,\n\tgcStateBlobKey,\n\tGCSummaryStateTracker,\n\tGCVersion,\n\tIGarbageCollectionState,\n\tIGCStats,\n} from \"../../gc/index.js\";\n\ntype GCSummaryStateTrackerWithPrivates = Omit<GCSummaryStateTracker, \"latestSummaryGCVersion\"> & {\n\tlatestSummaryGCVersion: GCVersion;\n};\n\ndescribe(\"GCSummaryStateTracker tests\", () => {\n\tdescribe(\"Summary state reset\", () => {\n\t\t// In these tests, Persisted = gcVersionInBaseSnapshot. Current = gcVersionInEffect.\n\t\tit(\"Persisted < Current: Do Need Reset\", async () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: true,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 0,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\ttrue /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, false, \"Precondition 1\");\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesSummaryStateNeedReset,\n\t\t\t\ttrue,\n\t\t\t\t\"Should need reset: Persisted GC Version was old\",\n\t\t\t);\n\n\t\t\t// After the first summary succeeds (refreshLatestSummary called), the state should not need reset.\n\t\t\tawait tracker.refreshLatestSummary({ isSummaryTracked: true, isSummaryNewer: true });\n\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesSummaryStateNeedReset,\n\t\t\t\tfalse,\n\t\t\t\t\"Shouldn't need reset after first summary\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"Persisted === Current: Don't Need Reset\", () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: true,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 1,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\ttrue /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, false, \"Precondition 1\");\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesSummaryStateNeedReset,\n\t\t\t\tfalse,\n\t\t\t\t\"Shouldn't need reset: GC Versions match\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"Persisted > Current: Do Need Reset\", async () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: true,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 2,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\ttrue /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, false, \"Precondition 1\");\n\n\t\t\t// This covers the case where we rolled back an upgrade. Containers that successfully \"upgraded\" (reset)\n\t\t\t// shouldn't need to do it again.\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesSummaryStateNeedReset,\n\t\t\t\ttrue,\n\t\t\t\t\"Should need reset: Persisted GC Version is not old\",\n\t\t\t);\n\n\t\t\t// After the first summary succeeds (refreshLatestSummary called), the state should not need reset.\n\t\t\tawait tracker.refreshLatestSummary({ isSummaryTracked: true, isSummaryNewer: true });\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesSummaryStateNeedReset,\n\t\t\t\tfalse,\n\t\t\t\t\"Shouldn't need reset after first summary\",\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe(\"GC state reset\", () => {\n\t\tit(\"wasGCRunInBaseSnapshot = false, shouldRunGC = false: Don't Need Reset\", () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: false,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 1,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\tfalse /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, false, \"Shouldn't need reset\");\n\t\t});\n\n\t\tit(\"wasGCRunInBaseSnapshot = true, shouldRunGC = false: Do Need Reset\", async () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: false,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 1,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\ttrue /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, true, \"Should need reset\");\n\n\t\t\t// After the first summary succeeds (refreshLatestSummary called), the state should not need reset.\n\t\t\tawait tracker.refreshLatestSummary({ isSummaryTracked: true, isSummaryNewer: true });\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesGCStateNeedReset,\n\t\t\t\tfalse,\n\t\t\t\t\"Shouldn't need reset after first summary\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"wasGCRunInBaseSnapshot = false, shouldRunGC = true: Do Need Reset\", async () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: true,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 1,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\tfalse /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, true, \"Should need reset\");\n\n\t\t\t// After the first summary succeeds (refreshLatestSummary called), the state should not need reset.\n\t\t\tawait tracker.refreshLatestSummary({ isSummaryTracked: true, isSummaryNewer: true });\n\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesGCStateNeedReset,\n\t\t\t\tfalse,\n\t\t\t\t\"Shouldn't need reset after first summary\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"wasGCRunInBaseSnapshot = true, shouldRunGC = true: Don't Need Reset\", () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: true,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 1,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\ttrue /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, false, \"Shouldn't need reset\");\n\t\t});\n\t});\n\n\tit(\"Autorecovery: requesting Full GC\", async () => {\n\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t{\n\t\t\t\tshouldRunGC: true,\n\t\t\t\ttombstoneMode: false,\n\t\t\t\tgcVersionInBaseSnapshot: 1,\n\t\t\t\tgcVersionInEffect: 1,\n\t\t\t},\n\t\t\tfalse /* wasGCRunInBaseSnapshot */,\n\t\t) as any;\n\t\tassert.equal(tracker.autoRecovery.fullGCRequested(), false, \"Should be false by default\");\n\n\t\ttracker.autoRecovery.requestFullGCOnNextRun();\n\n\t\tassert.equal(\n\t\t\ttracker.autoRecovery.fullGCRequested(),\n\t\t\ttrue,\n\t\t\t\"Should be true after requesting full GC\",\n\t\t);\n\n\t\t// After the first summary succeeds (refreshLatestSummary called), the state should be reset.\n\t\tawait tracker.refreshLatestSummary({ isSummaryTracked: true, isSummaryNewer: true });\n\n\t\tassert.equal(\n\t\t\ttracker.autoRecovery.fullGCRequested(),\n\t\t\tfalse,\n\t\t\t\"Should be false after Summary Ack\",\n\t\t);\n\t});\n\n\t/**\n\t * These tests validate that the GC data is written in summary incrementally. Basically, only parts of the GC\n\t * data that has changed since the last successful summary is re-written, rest is written as SummaryHandle.\n\t */\n\tdescribe(\"Incremental summary of GC data\", () => {\n\t\tconst nodes = [\"node1\", \"node2\", \"node3\"];\n\t\tconst initialGCState: IGarbageCollectionState = {\n\t\t\tgcNodes: {\n\t\t\t\t\"/\": { outboundRoutes: [] },\n\t\t\t\t[nodes[0]]: { outboundRoutes: [] },\n\t\t\t\t[nodes[1]]: { outboundRoutes: [] },\n\t\t\t},\n\t\t};\n\t\tconst initialTombstones: string[] = [nodes[0], nodes[1]];\n\t\tconst initialDeletedNodes: Set<string> = new Set([nodes[1]]);\n\t\tlet summaryStateTracker: GCSummaryStateTracker;\n\n\t\tbeforeEach(async () => {\n\t\t\t// Creates a summary state tracker and initialize it.\n\t\t\tsummaryStateTracker = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: true,\n\t\t\t\t\ttombstoneMode: true,\n\t\t\t\t\tgcVersionInBaseSnapshot: nextGCVersion,\n\t\t\t\t\tgcVersionInEffect: nextGCVersion,\n\t\t\t\t},\n\t\t\t\tfalse /* wasGCRunInBaseSnapshot */,\n\t\t\t);\n\n\t\t\tsummaryStateTracker.initializeBaseState({\n\t\t\t\tgcState: initialGCState,\n\t\t\t\ttombstones: initialTombstones,\n\t\t\t\tdeletedNodes: Array.from(initialDeletedNodes),\n\t\t\t});\n\t\t});\n\n\t\tit(\"does incremental summary when nothing changes\", async () => {\n\t\t\t// Summarize with the same GC state, tombstone state and deleted nodes as in the initial state.\n\t\t\t// The GC data should be summarized as a summary handle.\n\t\t\tconst summary = summaryStateTracker.summarize(\n\t\t\t\ttrue /* trackState */,\n\t\t\t\tinitialGCState,\n\t\t\t\tinitialDeletedNodes,\n\t\t\t\tinitialTombstones,\n\t\t\t);\n\t\t\tassert(summary?.summary.type === SummaryType.Handle, \"GC summary should be a handle\");\n\t\t});\n\n\t\tit(\"does incremental summary when only GC state changes\", async () => {\n\t\t\t// Summarize with the same tombstone state and deleted nodes but different GC state as in the initial.\n\t\t\t// state. The GC state should be summarized as a summary handle.\n\t\t\tconst newGCState: IGarbageCollectionState = {\n\t\t\t\tgcNodes: {\n\t\t\t\t\t...initialGCState.gcNodes,\n\t\t\t\t\t[nodes[2]]: { outboundRoutes: [] },\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst summary = summaryStateTracker.summarize(\n\t\t\t\ttrue /* trackState */,\n\t\t\t\tnewGCState,\n\t\t\t\tinitialDeletedNodes,\n\t\t\t\tinitialTombstones,\n\t\t\t);\n\t\t\tassert(summary?.summary.type === SummaryType.Tree, \"GC summary should be a tree\");\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcStateBlobKey].type === SummaryType.Blob,\n\t\t\t\t\"GC state should be written as a blob\",\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcTombstoneBlobKey].type === SummaryType.Handle,\n\t\t\t\t\"Tombstone state should be written as handle\",\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcDeletedBlobKey].type === SummaryType.Handle,\n\t\t\t\t\"Deleted nodes should be written as handle\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"does incremental summary when only tombstone state changes\", async () => {\n\t\t\t// Summarize with the same GC state and deleted nodes but different tombstone state as in the initial.\n\t\t\t// state. The tombstone state should be summarized as a summary handle.\n\t\t\tconst newTombstones: string[] = Array.from([...initialTombstones, nodes[2]]);\n\t\t\tconst summary = summaryStateTracker.summarize(\n\t\t\t\ttrue /* trackState */,\n\t\t\t\tinitialGCState,\n\t\t\t\tinitialDeletedNodes,\n\t\t\t\tnewTombstones,\n\t\t\t);\n\t\t\tassert(summary?.summary.type === SummaryType.Tree, \"GC summary should be a tree\");\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcStateBlobKey].type === SummaryType.Handle,\n\t\t\t\t\"GC state should be written as handle\",\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcTombstoneBlobKey].type === SummaryType.Blob,\n\t\t\t\t\"Tombstone state should be written as a blob\",\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcDeletedBlobKey].type === SummaryType.Handle,\n\t\t\t\t\"Deleted nodes should be written as handle\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"does incremental summary when only deleted nodes change\", async () => {\n\t\t\t// Summarize with the same GC state and tombstone state but different deleted nodes as in the initial.\n\t\t\t// state. The deleted nodes should be summarized as a summary handle.\n\t\t\tconst newDeletedNodes: Set<string> = new Set(...initialDeletedNodes, nodes[2]);\n\t\t\tconst summary = summaryStateTracker.summarize(\n\t\t\t\ttrue /* trackState */,\n\t\t\t\tinitialGCState,\n\t\t\t\tnewDeletedNodes,\n\t\t\t\tinitialTombstones,\n\t\t\t);\n\t\t\tassert(summary?.summary.type === SummaryType.Tree, \"GC summary should be a tree\");\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcStateBlobKey].type === SummaryType.Handle,\n\t\t\t\t\"GC state should be written as handle\",\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcTombstoneBlobKey].type === SummaryType.Handle,\n\t\t\t\t\"Tombstone state should be written as handle\",\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcDeletedBlobKey].type === SummaryType.Blob,\n\t\t\t\t\"Deleted nodes should be written as a blob\",\n\t\t\t);\n\t\t});\n\t});\n\n\tit(\"updates state updated data store count correctly\", async () => {\n\t\tconst updatedDataStoreCount = 10;\n\t\tconst gcStats: IGCStats = {\n\t\t\tnodeCount: 0,\n\t\t\tunrefNodeCount: 0,\n\t\t\tupdatedNodeCount: 0,\n\t\t\tdataStoreCount: 0,\n\t\t\tunrefDataStoreCount: 0,\n\t\t\tupdatedDataStoreCount,\n\t\t\tattachmentBlobCount: 0,\n\t\t\tunrefAttachmentBlobCount: 0,\n\t\t\tupdatedAttachmentBlobCount: 0,\n\t\t\tlifetimeNodeCount: 0,\n\t\t\tlifetimeDataStoreCount: 0,\n\t\t\tlifetimeAttachmentBlobCount: 0,\n\t\t\tdeletedNodeCount: 0,\n\t\t\tdeletedDataStoreCount: 0,\n\t\t\tdeletedAttachmentBlobCount: 0,\n\t\t};\n\n\t\tconst summaryStateTracker = new GCSummaryStateTracker(\n\t\t\t{\n\t\t\t\tshouldRunGC: true,\n\t\t\t\ttombstoneMode: true,\n\t\t\t\tgcVersionInBaseSnapshot: nextGCVersion,\n\t\t\t\tgcVersionInEffect: nextGCVersion,\n\t\t\t},\n\t\t\tfalse /* wasGCRunInBaseSnapshot */,\n\t\t);\n\n\t\tlet expectedUpdatedDataStoreCount = updatedDataStoreCount;\n\t\t// Update the state from GC stats and validate it's the same as updatedDataStoreCount.\n\t\tsummaryStateTracker.updateStateFromGCRunStats(gcStats);\n\t\tassert.strictEqual(\n\t\t\tsummaryStateTracker.updatedDSCountSinceLastSummary,\n\t\t\texpectedUpdatedDataStoreCount,\n\t\t\t\"Updated DS count is not correct\",\n\t\t);\n\n\t\t// Call summarize but do not refresh latest summary. This mimics scenarios where summary generation fails\n\t\t// sometime after summarize. This means updatedDSCountSinceLastSummary should be updated incrementally\n\t\t// without resetting it.\n\t\tsummaryStateTracker.summarize(true /* trackState */, { gcNodes: {} }, new Set(), []);\n\n\t\t// Update the stat from GC state again mimicking a GC run after a failed summary.\n\t\texpectedUpdatedDataStoreCount += updatedDataStoreCount;\n\t\tsummaryStateTracker.updateStateFromGCRunStats(gcStats);\n\t\tassert.strictEqual(\n\t\t\tsummaryStateTracker.updatedDSCountSinceLastSummary,\n\t\t\texpectedUpdatedDataStoreCount,\n\t\t\t\"Updated DS count should have been incrementally updated\",\n\t\t);\n\n\t\t// Call summarize and refresh latest summary. This mimics a successful summary after a failed one. After\n\t\t// this, updatedDSCountSinceLastSummary should be reset to 0.\n\t\tsummaryStateTracker.summarize(true /* trackState */, { gcNodes: {} }, new Set(), []);\n\n\t\tawait summaryStateTracker.refreshLatestSummary({\n\t\t\tisSummaryTracked: true,\n\t\t\tisSummaryNewer: true,\n\t\t});\n\t\tassert.strictEqual(\n\t\t\tsummaryStateTracker.updatedDSCountSinceLastSummary,\n\t\t\t0,\n\t\t\t\"Updated DS count should be reset after refresh latest summary\",\n\t\t);\n\t});\n});\n"]}
|
|
1
|
+
{"version":3,"file":"gcSummaryStateTracker.spec.js","sourceRoot":"","sources":["../../../src/test/gc/gcSummaryStateTracker.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { gcDeletedBlobKey, gcTombstoneBlobKey } from \"@fluidframework/runtime-definitions\";\nimport {\n\tGCSummaryStateTracker,\n\tGCVersion,\n\tIGCStats,\n\tIGarbageCollectionState,\n\tgcStateBlobKey,\n\tnextGCVersion,\n} from \"../../gc/index.js\";\n\ntype GCSummaryStateTrackerWithPrivates = Omit<GCSummaryStateTracker, \"latestSummaryGCVersion\"> & {\n\tlatestSummaryGCVersion: GCVersion;\n};\n\ndescribe(\"GCSummaryStateTracker tests\", () => {\n\tdescribe(\"Summary state reset\", () => {\n\t\t// In these tests, Persisted = gcVersionInBaseSnapshot. Current = gcVersionInEffect.\n\t\tit(\"Persisted < Current: Do Need Reset\", async () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: true,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 0,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\ttrue /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, false, \"Precondition 1\");\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesSummaryStateNeedReset,\n\t\t\t\ttrue,\n\t\t\t\t\"Should need reset: Persisted GC Version was old\",\n\t\t\t);\n\n\t\t\t// After the first summary succeeds (refreshLatestSummary called), the state should not need reset.\n\t\t\tawait tracker.refreshLatestSummary({ isSummaryTracked: true, isSummaryNewer: true });\n\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesSummaryStateNeedReset,\n\t\t\t\tfalse,\n\t\t\t\t\"Shouldn't need reset after first summary\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"Persisted === Current: Don't Need Reset\", () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: true,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 1,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\ttrue /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, false, \"Precondition 1\");\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesSummaryStateNeedReset,\n\t\t\t\tfalse,\n\t\t\t\t\"Shouldn't need reset: GC Versions match\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"Persisted > Current: Do Need Reset\", async () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: true,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 2,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\ttrue /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, false, \"Precondition 1\");\n\n\t\t\t// This covers the case where we rolled back an upgrade. Containers that successfully \"upgraded\" (reset)\n\t\t\t// shouldn't need to do it again.\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesSummaryStateNeedReset,\n\t\t\t\ttrue,\n\t\t\t\t\"Should need reset: Persisted GC Version is not old\",\n\t\t\t);\n\n\t\t\t// After the first summary succeeds (refreshLatestSummary called), the state should not need reset.\n\t\t\tawait tracker.refreshLatestSummary({ isSummaryTracked: true, isSummaryNewer: true });\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesSummaryStateNeedReset,\n\t\t\t\tfalse,\n\t\t\t\t\"Shouldn't need reset after first summary\",\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe(\"GC state reset\", () => {\n\t\tit(\"wasGCRunInBaseSnapshot = false, shouldRunGC = false: Don't Need Reset\", () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: false,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 1,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\tfalse /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, false, \"Shouldn't need reset\");\n\t\t});\n\n\t\tit(\"wasGCRunInBaseSnapshot = true, shouldRunGC = false: Do Need Reset\", async () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: false,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 1,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\ttrue /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, true, \"Should need reset\");\n\n\t\t\t// After the first summary succeeds (refreshLatestSummary called), the state should not need reset.\n\t\t\tawait tracker.refreshLatestSummary({ isSummaryTracked: true, isSummaryNewer: true });\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesGCStateNeedReset,\n\t\t\t\tfalse,\n\t\t\t\t\"Shouldn't need reset after first summary\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"wasGCRunInBaseSnapshot = false, shouldRunGC = true: Do Need Reset\", async () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: true,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 1,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\tfalse /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, true, \"Should need reset\");\n\n\t\t\t// After the first summary succeeds (refreshLatestSummary called), the state should not need reset.\n\t\t\tawait tracker.refreshLatestSummary({ isSummaryTracked: true, isSummaryNewer: true });\n\n\t\t\tassert.equal(\n\t\t\t\ttracker.doesGCStateNeedReset,\n\t\t\t\tfalse,\n\t\t\t\t\"Shouldn't need reset after first summary\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"wasGCRunInBaseSnapshot = true, shouldRunGC = true: Don't Need Reset\", () => {\n\t\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: true,\n\t\t\t\t\ttombstoneMode: false,\n\t\t\t\t\tgcVersionInBaseSnapshot: 1,\n\t\t\t\t\tgcVersionInEffect: 1,\n\t\t\t\t},\n\t\t\t\ttrue /* wasGCRunInBaseSnapshot */,\n\t\t\t) as any;\n\t\t\tassert.equal(tracker.doesGCStateNeedReset, false, \"Shouldn't need reset\");\n\t\t});\n\t});\n\n\tit(\"Autorecovery: requesting Full GC\", async () => {\n\t\tconst tracker: GCSummaryStateTrackerWithPrivates = new GCSummaryStateTracker(\n\t\t\t{\n\t\t\t\tshouldRunGC: true,\n\t\t\t\ttombstoneMode: false,\n\t\t\t\tgcVersionInBaseSnapshot: 1,\n\t\t\t\tgcVersionInEffect: 1,\n\t\t\t},\n\t\t\tfalse /* wasGCRunInBaseSnapshot */,\n\t\t) as any;\n\t\tassert.equal(tracker.autoRecovery.fullGCRequested(), false, \"Should be false by default\");\n\n\t\ttracker.autoRecovery.requestFullGCOnNextRun();\n\n\t\tassert.equal(\n\t\t\ttracker.autoRecovery.fullGCRequested(),\n\t\t\ttrue,\n\t\t\t\"Should be true after requesting full GC\",\n\t\t);\n\n\t\t// After the first summary succeeds (refreshLatestSummary called), the state should be reset.\n\t\tawait tracker.refreshLatestSummary({ isSummaryTracked: true, isSummaryNewer: true });\n\n\t\tassert.equal(\n\t\t\ttracker.autoRecovery.fullGCRequested(),\n\t\t\tfalse,\n\t\t\t\"Should be false after Summary Ack\",\n\t\t);\n\t});\n\n\t/**\n\t * These tests validate that the GC data is written in summary incrementally. Basically, only parts of the GC\n\t * data that has changed since the last successful summary is re-written, rest is written as SummaryHandle.\n\t */\n\tdescribe(\"Incremental summary of GC data\", () => {\n\t\tconst nodes = [\"node1\", \"node2\", \"node3\"];\n\t\tconst initialGCState: IGarbageCollectionState = {\n\t\t\tgcNodes: {\n\t\t\t\t\"/\": { outboundRoutes: [] },\n\t\t\t\t[nodes[0]]: { outboundRoutes: [] },\n\t\t\t\t[nodes[1]]: { outboundRoutes: [] },\n\t\t\t},\n\t\t};\n\t\tconst initialTombstones: string[] = [nodes[0], nodes[1]];\n\t\tconst initialDeletedNodes: Set<string> = new Set([nodes[1]]);\n\t\tlet summaryStateTracker: GCSummaryStateTracker;\n\n\t\tbeforeEach(async () => {\n\t\t\t// Creates a summary state tracker and initialize it.\n\t\t\tsummaryStateTracker = new GCSummaryStateTracker(\n\t\t\t\t{\n\t\t\t\t\tshouldRunGC: true,\n\t\t\t\t\ttombstoneMode: true,\n\t\t\t\t\tgcVersionInBaseSnapshot: nextGCVersion,\n\t\t\t\t\tgcVersionInEffect: nextGCVersion,\n\t\t\t\t},\n\t\t\t\tfalse /* wasGCRunInBaseSnapshot */,\n\t\t\t);\n\n\t\t\tsummaryStateTracker.initializeBaseState({\n\t\t\t\tgcState: initialGCState,\n\t\t\t\ttombstones: initialTombstones,\n\t\t\t\tdeletedNodes: Array.from(initialDeletedNodes),\n\t\t\t});\n\t\t});\n\n\t\tit(\"does incremental summary when nothing changes\", async () => {\n\t\t\t// Summarize with the same GC state, tombstone state and deleted nodes as in the initial state.\n\t\t\t// The GC data should be summarized as a summary handle.\n\t\t\tconst summary = summaryStateTracker.summarize(\n\t\t\t\ttrue /* trackState */,\n\t\t\t\tinitialGCState,\n\t\t\t\tinitialDeletedNodes,\n\t\t\t\tinitialTombstones,\n\t\t\t);\n\t\t\tassert(summary?.summary.type === SummaryType.Handle, \"GC summary should be a handle\");\n\t\t});\n\n\t\tit(\"does incremental summary when only GC state changes\", async () => {\n\t\t\t// Summarize with the same tombstone state and deleted nodes but different GC state as in the initial.\n\t\t\t// state. The GC state should be summarized as a summary handle.\n\t\t\tconst newGCState: IGarbageCollectionState = {\n\t\t\t\tgcNodes: {\n\t\t\t\t\t...initialGCState.gcNodes,\n\t\t\t\t\t[nodes[2]]: { outboundRoutes: [] },\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst summary = summaryStateTracker.summarize(\n\t\t\t\ttrue /* trackState */,\n\t\t\t\tnewGCState,\n\t\t\t\tinitialDeletedNodes,\n\t\t\t\tinitialTombstones,\n\t\t\t);\n\t\t\tassert(summary?.summary.type === SummaryType.Tree, \"GC summary should be a tree\");\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcStateBlobKey].type === SummaryType.Blob,\n\t\t\t\t\"GC state should be written as a blob\",\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcTombstoneBlobKey].type === SummaryType.Handle,\n\t\t\t\t\"Tombstone state should be written as handle\",\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcDeletedBlobKey].type === SummaryType.Handle,\n\t\t\t\t\"Deleted nodes should be written as handle\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"does incremental summary when only tombstone state changes\", async () => {\n\t\t\t// Summarize with the same GC state and deleted nodes but different tombstone state as in the initial.\n\t\t\t// state. The tombstone state should be summarized as a summary handle.\n\t\t\tconst newTombstones: string[] = Array.from([...initialTombstones, nodes[2]]);\n\t\t\tconst summary = summaryStateTracker.summarize(\n\t\t\t\ttrue /* trackState */,\n\t\t\t\tinitialGCState,\n\t\t\t\tinitialDeletedNodes,\n\t\t\t\tnewTombstones,\n\t\t\t);\n\t\t\tassert(summary?.summary.type === SummaryType.Tree, \"GC summary should be a tree\");\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcStateBlobKey].type === SummaryType.Handle,\n\t\t\t\t\"GC state should be written as handle\",\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcTombstoneBlobKey].type === SummaryType.Blob,\n\t\t\t\t\"Tombstone state should be written as a blob\",\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcDeletedBlobKey].type === SummaryType.Handle,\n\t\t\t\t\"Deleted nodes should be written as handle\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"does incremental summary when only deleted nodes change\", async () => {\n\t\t\t// Summarize with the same GC state and tombstone state but different deleted nodes as in the initial.\n\t\t\t// state. The deleted nodes should be summarized as a summary handle.\n\t\t\tconst newDeletedNodes: Set<string> = new Set(...initialDeletedNodes, nodes[2]);\n\t\t\tconst summary = summaryStateTracker.summarize(\n\t\t\t\ttrue /* trackState */,\n\t\t\t\tinitialGCState,\n\t\t\t\tnewDeletedNodes,\n\t\t\t\tinitialTombstones,\n\t\t\t);\n\t\t\tassert(summary?.summary.type === SummaryType.Tree, \"GC summary should be a tree\");\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcStateBlobKey].type === SummaryType.Handle,\n\t\t\t\t\"GC state should be written as handle\",\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcTombstoneBlobKey].type === SummaryType.Handle,\n\t\t\t\t\"Tombstone state should be written as handle\",\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tsummary.summary.tree[gcDeletedBlobKey].type === SummaryType.Blob,\n\t\t\t\t\"Deleted nodes should be written as a blob\",\n\t\t\t);\n\t\t});\n\t});\n\n\tit(\"updates state updated data store count correctly\", async () => {\n\t\tconst updatedDataStoreCount = 10;\n\t\tconst gcStats: IGCStats = {\n\t\t\tnodeCount: 0,\n\t\t\tunrefNodeCount: 0,\n\t\t\tupdatedNodeCount: 0,\n\t\t\tdataStoreCount: 0,\n\t\t\tunrefDataStoreCount: 0,\n\t\t\tupdatedDataStoreCount,\n\t\t\tattachmentBlobCount: 0,\n\t\t\tunrefAttachmentBlobCount: 0,\n\t\t\tupdatedAttachmentBlobCount: 0,\n\t\t\tlifetimeNodeCount: 0,\n\t\t\tlifetimeDataStoreCount: 0,\n\t\t\tlifetimeAttachmentBlobCount: 0,\n\t\t\tdeletedNodeCount: 0,\n\t\t\tdeletedDataStoreCount: 0,\n\t\t\tdeletedAttachmentBlobCount: 0,\n\t\t};\n\n\t\tconst summaryStateTracker = new GCSummaryStateTracker(\n\t\t\t{\n\t\t\t\tshouldRunGC: true,\n\t\t\t\ttombstoneMode: true,\n\t\t\t\tgcVersionInBaseSnapshot: nextGCVersion,\n\t\t\t\tgcVersionInEffect: nextGCVersion,\n\t\t\t},\n\t\t\tfalse /* wasGCRunInBaseSnapshot */,\n\t\t);\n\n\t\tlet expectedUpdatedDataStoreCount = updatedDataStoreCount;\n\t\t// Update the state from GC stats and validate it's the same as updatedDataStoreCount.\n\t\tsummaryStateTracker.updateStateFromGCRunStats(gcStats);\n\t\tassert.strictEqual(\n\t\t\tsummaryStateTracker.updatedDSCountSinceLastSummary,\n\t\t\texpectedUpdatedDataStoreCount,\n\t\t\t\"Updated DS count is not correct\",\n\t\t);\n\n\t\t// Call summarize but do not refresh latest summary. This mimics scenarios where summary generation fails\n\t\t// sometime after summarize. This means updatedDSCountSinceLastSummary should be updated incrementally\n\t\t// without resetting it.\n\t\tsummaryStateTracker.summarize(true /* trackState */, { gcNodes: {} }, new Set(), []);\n\n\t\t// Update the stat from GC state again mimicking a GC run after a failed summary.\n\t\texpectedUpdatedDataStoreCount += updatedDataStoreCount;\n\t\tsummaryStateTracker.updateStateFromGCRunStats(gcStats);\n\t\tassert.strictEqual(\n\t\t\tsummaryStateTracker.updatedDSCountSinceLastSummary,\n\t\t\texpectedUpdatedDataStoreCount,\n\t\t\t\"Updated DS count should have been incrementally updated\",\n\t\t);\n\n\t\t// Call summarize and refresh latest summary. This mimics a successful summary after a failed one. After\n\t\t// this, updatedDSCountSinceLastSummary should be reset to 0.\n\t\tsummaryStateTracker.summarize(true /* trackState */, { gcNodes: {} }, new Set(), []);\n\n\t\tawait summaryStateTracker.refreshLatestSummary({\n\t\t\tisSummaryTracked: true,\n\t\t\tisSummaryNewer: true,\n\t\t});\n\t\tassert.strictEqual(\n\t\t\tsummaryStateTracker.updatedDSCountSinceLastSummary,\n\t\t\t0,\n\t\t\t\"Updated DS count should be reset after refresh latest summary\",\n\t\t);\n\t});\n});\n"]}
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { strict as assert } from "assert";
|
|
6
|
+
import { MockLogger, TelemetryDataTag, createChildLogger, mixinMonitoringContext, tagCodeArtifacts, } from "@fluidframework/telemetry-utils";
|
|
6
7
|
import { useFakeTimers } from "sinon";
|
|
7
|
-
import { MockLogger, TelemetryDataTag, mixinMonitoringContext, createChildLogger, tagCodeArtifacts, } from "@fluidframework/telemetry-utils";
|
|
8
|
-
import { GCNodeType, GCTelemetryTracker, defaultSessionExpiryDurationMs, oneDayMs, UnreferencedStateTracker, cloneGCData, stableGCVersion, } from "../../gc/index.js";
|
|
9
|
-
import { pkgVersion } from "../../packageVersion.js";
|
|
10
8
|
import { BlobManager } from "../../blobManager.js";
|
|
9
|
+
import { GCNodeType, GCTelemetryTracker, UnreferencedStateTracker, cloneGCData, defaultSessionExpiryDurationMs, oneDayMs, stableGCVersion, } from "../../gc/index.js";
|
|
10
|
+
import { pkgVersion } from "../../packageVersion.js";
|
|
11
11
|
describe("GC Telemetry Tracker", () => {
|
|
12
12
|
const defaultSnapshotCacheExpiryMs = 5 * 24 * 60 * 60 * 1000;
|
|
13
13
|
const tombstoneTimeoutMs = defaultSessionExpiryDurationMs + defaultSnapshotCacheExpiryMs + oneDayMs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gcTelemetry.spec.js","sourceRoot":"","sources":["../../../src/test/gc/gcTelemetry.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { SinonFakeTimers, useFakeTimers } from \"sinon\";\nimport { ITelemetryBaseEvent } from \"@fluidframework/core-interfaces\";\nimport { IGarbageCollectionData } from \"@fluidframework/runtime-definitions\";\nimport {\n\tMockLogger,\n\tTelemetryDataTag,\n\tmixinMonitoringContext,\n\tMonitoringContext,\n\tcreateChildLogger,\n\ttagCodeArtifacts,\n} from \"@fluidframework/telemetry-utils\";\nimport {\n\tGCNodeType,\n\tGCTelemetryTracker,\n\tdefaultSessionExpiryDurationMs,\n\toneDayMs,\n\tUnreferencedStateTracker,\n\tcloneGCData,\n\tIGarbageCollectorConfigs,\n\tstableGCVersion,\n} from \"../../gc/index.js\";\nimport { pkgVersion } from \"../../packageVersion.js\";\nimport { BlobManager } from \"../../blobManager.js\";\n\ndescribe(\"GC Telemetry Tracker\", () => {\n\tconst defaultSnapshotCacheExpiryMs = 5 * 24 * 60 * 60 * 1000;\n\tconst tombstoneTimeoutMs =\n\t\tdefaultSessionExpiryDurationMs + defaultSnapshotCacheExpiryMs + oneDayMs;\n\tconst inactiveTimeoutMs = 500;\n\n\t// Nodes in the reference graph.\n\tconst nodes: string[] = [\"/node1\", \"/node2\", \"/node3\", \"/node4\"];\n\n\tconst testPkgPath = [\"testPkg\"];\n\t// The package data is tagged in the telemetry event.\n\tconst eventPkg = { value: testPkgPath.join(\"/\"), tag: TelemetryDataTag.CodeArtifact };\n\n\tlet mockLogger: MockLogger;\n\tlet mc: MonitoringContext;\n\tlet clock: SinonFakeTimers;\n\tlet sweepGracePeriodMs = 1000; // Default case for these tests\n\tlet unreferencedNodesState: Map<string, UnreferencedStateTracker> = new Map();\n\tlet telemetryTracker: GCTelemetryTracker;\n\n\tfunction createTelemetryTracker(\n\t\tenableSweep: boolean,\n\t\tisSummarizerClient = true,\n\t): GCTelemetryTracker {\n\t\t// Node types are as follows based on the path:\n\t\t// Path starting with \"/_blobs\" - blob.\n\t\t// Path with one part such as \"/id1\" - data stores.\n\t\t// Path with two parts such as \"/id1/id2\" - sub data stores.\n\t\t// Everything else - other.\n\t\tconst getNodeType = (nodePath: string) => {\n\t\t\tif (nodePath.split(\"/\")[1] === BlobManager.basePath) {\n\t\t\t\treturn GCNodeType.Blob;\n\t\t\t}\n\t\t\tif (nodePath.split(\"/\").length === 2) {\n\t\t\t\treturn GCNodeType.DataStore;\n\t\t\t}\n\t\t\tif (nodePath.split(\"/\").length === 3) {\n\t\t\t\treturn GCNodeType.SubDataStore;\n\t\t\t}\n\t\t\treturn GCNodeType.Other;\n\t\t};\n\t\tconst configs: IGarbageCollectorConfigs = {\n\t\t\tgcEnabled: true,\n\t\t\tsweepEnabled: false,\n\t\t\tshouldRunGC: true,\n\t\t\tshouldRunSweep: \"NO\",\n\t\t\trunFullGC: false,\n\t\t\ttestMode: false,\n\t\t\ttombstoneMode: false,\n\t\t\tinactiveTimeoutMs,\n\t\t\tsessionExpiryTimeoutMs: defaultSessionExpiryDurationMs,\n\t\t\ttombstoneTimeoutMs: enableSweep ? tombstoneTimeoutMs : undefined,\n\t\t\tsweepGracePeriodMs,\n\t\t\tthrowOnTombstoneLoad: false,\n\t\t\tthrowOnTombstoneUsage: false,\n\t\t\tthrowOnInactiveLoad: false,\n\t\t\tpersistedGcFeatureMatrix: undefined,\n\t\t\tgcVersionInBaseSnapshot: stableGCVersion,\n\t\t\tgcVersionInEffect: stableGCVersion,\n\t\t};\n\t\tconst tracker = new GCTelemetryTracker(\n\t\t\tmc,\n\t\t\tconfigs,\n\t\t\tisSummarizerClient,\n\t\t\t{ createContainerRuntimeVersion: pkgVersion },\n\t\t\tgetNodeType,\n\t\t\t(nodeId: string) => unreferencedNodesState.get(nodeId),\n\t\t\tasync (nodeId: string) => testPkgPath,\n\t\t);\n\t\treturn tracker;\n\t}\n\n\t/**\n\t * For each node in nodeIds, add an entry in `unreferencedNodesState` indicating that the node was\n\t * just unreferenced.\n\t */\n\tfunction markNodesUnreferenced(nodeIds: string[]) {\n\t\tnodeIds.forEach((nodeId) => {\n\t\t\tunreferencedNodesState.set(\n\t\t\t\tnodeId,\n\t\t\t\tnew UnreferencedStateTracker(\n\t\t\t\t\tDate.now(),\n\t\t\t\t\tinactiveTimeoutMs,\n\t\t\t\t\tDate.now(),\n\t\t\t\t\ttombstoneTimeoutMs,\n\t\t\t\t\tsweepGracePeriodMs,\n\t\t\t\t),\n\t\t\t);\n\t\t});\n\t}\n\n\t// Mock node loaded and changed activity for the given nodes.\n\tfunction mockNodeChanges(nodeIds: string[]) {\n\t\tnodeIds.forEach((id) => {\n\t\t\ttelemetryTracker.nodeUsed({\n\t\t\t\tid,\n\t\t\t\tusageType: \"Loaded\",\n\t\t\t\tcurrentReferenceTimestampMs: Date.now(),\n\t\t\t\tpackagePath: testPkgPath,\n\t\t\t\tcompletedGCRuns: 0,\n\t\t\t\tisTombstoned: false,\n\t\t\t});\n\t\t\ttelemetryTracker.nodeUsed({\n\t\t\t\tid,\n\t\t\t\tusageType: \"Changed\",\n\t\t\t\tcurrentReferenceTimestampMs: Date.now(),\n\t\t\t\tpackagePath: testPkgPath,\n\t\t\t\tcompletedGCRuns: 0,\n\t\t\t\tisTombstoned: false,\n\t\t\t});\n\t\t});\n\t}\n\n\t// Mock node revived activity for the given nodes.\n\tfunction reviveNode(fromId: string, toId: string, isTombstoned = false) {\n\t\ttelemetryTracker.nodeUsed({\n\t\t\tid: toId,\n\t\t\tusageType: \"Revived\",\n\t\t\tcurrentReferenceTimestampMs: Date.now(),\n\t\t\tpackagePath: testPkgPath,\n\t\t\tcompletedGCRuns: 0,\n\t\t\tisTombstoned,\n\t\t\tfromId,\n\t\t});\n\t\tunreferencedNodesState.delete(toId);\n\t}\n\n\t/**\n\t * For summarizer clients, inactive / sweep ready events are not logged when on node usage. They are logged when GC\n\t * runs next time. This emulates that by calling the functions in the telemetry tracker that are called when GC runs.\n\t */\n\tasync function simulateGCToTriggerEvents(isSummarizerClient: boolean) {\n\t\tif (!isSummarizerClient) {\n\t\t\treturn;\n\t\t}\n\t\tawait telemetryTracker.logPendingEvents(mc.logger);\n\t}\n\n\tbefore(() => {\n\t\tclock = useFakeTimers();\n\t});\n\n\tbeforeEach(() => {\n\t\tmockLogger = new MockLogger();\n\t\tmc = mixinMonitoringContext(\n\t\t\tcreateChildLogger({ logger: mockLogger, namespace: \"GarbageCollector\" }),\n\t\t);\n\t\tunreferencedNodesState = new Map();\n\t});\n\n\tafterEach(() => {\n\t\tclock.reset();\n\t\tmockLogger.clear();\n\t\tsweepGracePeriodMs = 1000; // Default case for these tests\n\t});\n\n\tafter(() => {\n\t\tclock.restore();\n\t});\n\n\t// Tests that are run once for summarizer client and once for interactive client.\n\tconst clientTypeTests = (isSummarizerClient: boolean) => {\n\t\t/**\n\t\t * Asserts that the events are as expected based on whether its a summarizer client or not. In non-summarizer\n\t\t * clients, only \"InactiveObject_Loaded\", \"TombstoneReadyObject_Loaded\" and \"SweepReadyObject_Loaded\" events are logged.\n\t\t * \"_Changed\" and \"_Revived\" events are not logged.\n\t\t */\n\t\tfunction assertMatchEvents(\n\t\t\tevents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\t\tmessage: string,\n\t\t) {\n\t\t\tconst expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[] = [];\n\t\t\tconst unexpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[] = [];\n\t\t\t// For non-summarizer clients, events that are not \"Loaded\" are unexpected. Everything else is expected.\n\t\t\tfor (const event of events) {\n\t\t\t\tconst eventName = event.eventName as string;\n\t\t\t\tif (!isSummarizerClient && !eventName.includes(\"Loaded\")) {\n\t\t\t\t\tunexpectedEvents.push(event);\n\t\t\t\t} else {\n\t\t\t\t\texpectedEvents.push(event);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Note that mock logger clears all events after one of the `match` functions is called. Since we call match\n\t\t\t// functions twice, cache the events and repopulate the mock logger with if after the first match call.\n\t\t\tconst cachedEvents = Array.from(mockLogger.events);\n\t\t\tmockLogger.assertMatch(expectedEvents, message, true /* inlineDetailsProp */);\n\t\t\tmockLogger.events = cachedEvents;\n\t\t\tmockLogger.assertMatchNone(unexpectedEvents, message, true /* inlineDetailsProp */);\n\t\t}\n\n\t\tit(\"generates inactive, tombstone ready, and sweep ready events when nodes are used after time out\", async () => {\n\t\t\ttelemetryTracker = createTelemetryTracker(true /* enable Sweep */, isSummarizerClient);\n\t\t\t// Mark nodes 2 and 3 as unreferenced.\n\t\t\tmarkNodesUnreferenced([nodes[2], nodes[3]]);\n\n\t\t\t// Advance the clock to trigger inactive timeout and validate that inactive events are as expected.\n\t\t\tclock.tick(inactiveTimeoutMs + 1);\n\t\t\tmockNodeChanges(nodes);\n\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\tassertMatchEvents(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:InactiveObject_Loaded\",\n\t\t\t\t\t\ttimeout: inactiveTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:InactiveObject_Changed\",\n\t\t\t\t\t\ttimeout: inactiveTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:InactiveObject_Loaded\",\n\t\t\t\t\t\ttimeout: inactiveTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[3] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:InactiveObject_Changed\",\n\t\t\t\t\t\ttimeout: inactiveTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[3] }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"inactive events not as expected\",\n\t\t\t);\n\n\t\t\t// Advance the clock to trigger tombstone timeout and validate that TombstoneReady events are as expected.\n\t\t\tclock.tick(tombstoneTimeoutMs - inactiveTimeoutMs);\n\t\t\tmockNodeChanges(nodes);\n\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\tassertMatchEvents(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:TombstoneReadyObject_Loaded\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:TombstoneReadyObject_Changed\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:TombstoneReadyObject_Loaded\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[3] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:TombstoneReadyObject_Changed\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[3] }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"tombstone ready events not as expected\",\n\t\t\t);\n\n\t\t\t// Advance the clock by the delay and validate that SweepReady events are as expected.\n\t\t\tclock.tick(sweepGracePeriodMs);\n\t\t\tmockNodeChanges(nodes);\n\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\tassertMatchEvents(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:SweepReadyObject_Loaded\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs + sweepGracePeriodMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:SweepReadyObject_Changed\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs + sweepGracePeriodMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:SweepReadyObject_Loaded\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs + sweepGracePeriodMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[3] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:SweepReadyObject_Changed\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs + sweepGracePeriodMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[3] }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"sweep ready events not as expected\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"generates tombstone revived events when nodes are used after they are tombstoned\", async () => {\n\t\t\ttelemetryTracker = createTelemetryTracker(true /* enable Sweep */, isSummarizerClient);\n\t\t\t// Mark node 2 as unreferenced.\n\t\t\tmarkNodesUnreferenced([nodes[2]]);\n\n\t\t\t// Advance the clock to trigger tombstone timeout and validate that tombstone revived event is as expected.\n\t\t\tclock.tick(tombstoneTimeoutMs + 1);\n\t\t\treviveNode(nodes[1], nodes[2], true /* isTombstoned */);\n\t\t\tmockLogger.assertMatch(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:GC_Tombstone_DataStore_Revived\",\n\t\t\t\t\t\tpkg: eventPkg,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"inactive events not as expected\",\n\t\t\t);\n\t\t});\n\n\t\t/** Tests that validate either the relevant events are logged as expected. */\n\t\tconst unreferencedPhasesEventTests = (\n\t\t\ttimeout: number,\n\t\t\tmode: \"inactive\" | \"tombstone\" | \"sweep\",\n\t\t\trevivedEventName: string,\n\t\t\tchangedEventName: string,\n\t\t\tloadedEventName: string,\n\t\t\tsweepGracePeriodMsOverride?: number,\n\t\t) => {\n\t\t\t// Validates that no unexpected event has been fired.\n\t\t\tfunction validateNoEvents() {\n\t\t\t\tmockLogger.assertMatchNone(\n\t\t\t\t\t[\n\t\t\t\t\t\t{ eventName: revivedEventName },\n\t\t\t\t\t\t{ eventName: changedEventName },\n\t\t\t\t\t\t{ eventName: loadedEventName },\n\t\t\t\t\t],\n\t\t\t\t\t\"unexpected events logged\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tbeforeEach(() => {\n\t\t\t\tif (sweepGracePeriodMsOverride !== undefined) {\n\t\t\t\t\tsweepGracePeriodMs = sweepGracePeriodMsOverride;\n\t\t\t\t}\n\t\t\t\ttelemetryTracker = createTelemetryTracker(\n\t\t\t\t\tmode !== \"inactive\" /* enableSweep */,\n\t\t\t\t\tisSummarizerClient,\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tit(\"doesn't generate events for referenced nodes\", async () => {\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tvalidateNoEvents();\n\n\t\t\t\t// Advance the clock to just before the timeout expires, update nodes and validate no events.\n\t\t\t\tclock.tick(timeout - 1);\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tvalidateNoEvents();\n\n\t\t\t\t// Advance the clock to expire the timeout, update nodes and validate no events.\n\t\t\t\tclock.tick(1);\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tvalidateNoEvents();\n\t\t\t});\n\n\t\t\tit(\"generates events for nodes that are used after state changes\", async () => {\n\t\t\t\t// Mark nodes 1 and 2 as unreferenced.\n\t\t\t\tmarkNodesUnreferenced([nodes[1], nodes[2]]);\n\n\t\t\t\t// Advance the clock just before the timeout and validate no unexpected events are logged.\n\t\t\t\tclock.tick(timeout - 1);\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tvalidateNoEvents();\n\n\t\t\t\t// Expire the timeout, update nodes and validate that all events for node 1 and node 2 are logged.\n\t\t\t\tclock.tick(1);\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tconst expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[] = [];\n\t\t\t\texpectedEvents.push(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: loadedEventName,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[1], pkg: testPkgPath.join(\"/\") }),\n\t\t\t\t\t\tcreateContainerRuntimeVersion: pkgVersion,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: changedEventName,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[1], pkg: testPkgPath.join(\"/\") }),\n\t\t\t\t\t\tcreateContainerRuntimeVersion: pkgVersion,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: loadedEventName,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2], pkg: testPkgPath.join(\"/\") }),\n\t\t\t\t\t\tcreateContainerRuntimeVersion: pkgVersion,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: changedEventName,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2], pkg: testPkgPath.join(\"/\") }),\n\t\t\t\t\t\tcreateContainerRuntimeVersion: pkgVersion,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tassertMatchEvents(expectedEvents, \"all events not as expected\");\n\n\t\t\t\t// Revived node 2 and validate that revived event is as expected.\n\t\t\t\treviveNode(nodes[0], nodes[2]);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tassertMatchEvents(\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: revivedEventName,\n\t\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t\t...tagCodeArtifacts({\n\t\t\t\t\t\t\t\tid: nodes[2],\n\t\t\t\t\t\t\t\tfromId: nodes[0],\n\t\t\t\t\t\t\t\tpkg: testPkgPath.join(\"/\"),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\t\"revived event not as expected\",\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tit(\"generates events once per node\", async () => {\n\t\t\t\t// Mark node 2 as unreferenced.\n\t\t\t\tmarkNodesUnreferenced([nodes[2]]);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\n\t\t\t\t// Advance the clock just before the timeout and validate no unexpected events are logged.\n\t\t\t\tclock.tick(timeout - 1);\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tvalidateNoEvents();\n\n\t\t\t\t// Expire the timeout, updated nodes and validate that events are logged as expected.\n\t\t\t\tclock.tick(1);\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tconst expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[] = [];\n\t\t\t\texpectedEvents.push(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: loadedEventName,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t\tpkg: eventPkg,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: changedEventName,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t\tpkg: eventPkg,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tassertMatchEvents(expectedEvents, \"all events not as expected\");\n\n\t\t\t\t// Update all nodes again. There shouldn't be any more events since for each node the event is only once.\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tvalidateNoEvents();\n\t\t\t});\n\n\t\t\t// This test is only relevant for summarizer client because it does not log changed events if the node is revived.\n\t\t\tif (isSummarizerClient) {\n\t\t\t\tit(\"generates only revived event in summarizer when a node is updated and revived\", async () => {\n\t\t\t\t\t// Mark node 2 as unreferenced.\n\t\t\t\t\tmarkNodesUnreferenced([nodes[2]]);\n\n\t\t\t\t\t// Advance the clock just before the timeout and validate no unexpected events are logged.\n\t\t\t\t\tclock.tick(timeout - 1);\n\t\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\n\t\t\t\t\tvalidateNoEvents();\n\n\t\t\t\t\t// Expire the timeout and validate that only revived event is generated for node 2.\n\t\t\t\t\tclock.tick(1);\n\t\t\t\t\tmockNodeChanges([nodes[2]]);\n\t\t\t\t\treviveNode(nodes[1], nodes[2]);\n\t\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\n\t\t\t\t\tfor (const event of mockLogger.events) {\n\t\t\t\t\t\tassert.notStrictEqual(\n\t\t\t\t\t\t\tevent.eventName,\n\t\t\t\t\t\t\tloadedEventName,\n\t\t\t\t\t\t\t\"Unexpected loaded event logged\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.notStrictEqual(\n\t\t\t\t\t\t\tevent.eventName,\n\t\t\t\t\t\t\tchangedEventName,\n\t\t\t\t\t\t\t\"Unexpected changed event logged\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tassertMatchEvents(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\teventName: revivedEventName,\n\t\t\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t\t\t...tagCodeArtifacts({\n\t\t\t\t\t\t\t\t\tid: nodes[2],\n\t\t\t\t\t\t\t\t\tfromId: nodes[1],\n\t\t\t\t\t\t\t\t\tpkg: testPkgPath.join(\"/\"),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"revived event not as expected\",\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tdescribe(\"Inactive events\", () => {\n\t\t\tunreferencedPhasesEventTests(\n\t\t\t\tinactiveTimeoutMs,\n\t\t\t\t\"inactive\",\n\t\t\t\t\"GarbageCollector:InactiveObject_Revived\",\n\t\t\t\t\"GarbageCollector:InactiveObject_Changed\",\n\t\t\t\t\"GarbageCollector:InactiveObject_Loaded\",\n\t\t\t);\n\t\t});\n\n\t\tdescribe(\"TombstoneReady events\", () => {\n\t\t\tunreferencedPhasesEventTests(\n\t\t\t\ttombstoneTimeoutMs,\n\t\t\t\t\"tombstone\",\n\t\t\t\t\"GarbageCollector:TombstoneReadyObject_Revived\",\n\t\t\t\t\"GarbageCollector:TombstoneReadyObject_Changed\",\n\t\t\t\t\"GarbageCollector:TombstoneReadyObject_Loaded\",\n\t\t\t);\n\t\t});\n\n\t\tdescribe(\"SweepReady events (with no delay)\", () => {\n\t\t\tunreferencedPhasesEventTests(\n\t\t\t\ttombstoneTimeoutMs,\n\t\t\t\t\"sweep\", // Jump straight to SweepReady given 0 delay\n\t\t\t\t\"GarbageCollector:SweepReadyObject_Revived\",\n\t\t\t\t\"GarbageCollector:SweepReadyObject_Changed\",\n\t\t\t\t\"GarbageCollector:SweepReadyObject_Loaded\",\n\t\t\t\t0 /* sweepGracePeriodMsOverride */,\n\t\t\t);\n\t\t});\n\n\t\tdescribe(\"SweepReady events\", () => {\n\t\t\tunreferencedPhasesEventTests(\n\t\t\t\ttombstoneTimeoutMs + sweepGracePeriodMs,\n\t\t\t\t\"sweep\",\n\t\t\t\t\"GarbageCollector:SweepReadyObject_Revived\",\n\t\t\t\t\"GarbageCollector:SweepReadyObject_Changed\",\n\t\t\t\t\"GarbageCollector:SweepReadyObject_Loaded\",\n\t\t\t);\n\t\t});\n\t};\n\n\tdescribe(\"Summarizer client\", () => {\n\t\tclientTypeTests(true /* isSummarizerClient */);\n\t});\n\n\tdescribe(\"Interactive client\", () => {\n\t\tclientTypeTests(false /* isSummarizerClient */);\n\t});\n\n\tdescribe(\"gcUnknownOutboundReferences telemetry\", () => {\n\t\tconst unknownReferenceEventName = \"GarbageCollector:gcUnknownOutboundReferences\";\n\t\tconst currentGCData: IGarbageCollectionData = { gcNodes: {} };\n\t\tlet previousGCData: IGarbageCollectionData;\n\t\tlet explicitReferences: Map<string, string[]>;\n\n\t\tbeforeEach(() => {\n\t\t\ttelemetryTracker = createTelemetryTracker(\n\t\t\t\ttrue /* enableSweep */,\n\t\t\t\ttrue /* isSummarizerClient */,\n\t\t\t);\n\n\t\t\tcurrentGCData.gcNodes[\"/\"] = [nodes[0]];\n\t\t\tcurrentGCData.gcNodes[nodes[0]] = [nodes[1]];\n\t\t\tcurrentGCData.gcNodes[nodes[1]] = [nodes[0], nodes[2]];\n\t\t\tcurrentGCData.gcNodes[nodes[2]] = [nodes[1], nodes[3]];\n\t\t\tcurrentGCData.gcNodes[nodes[3]] = [nodes[0]];\n\n\t\t\tpreviousGCData = cloneGCData(currentGCData);\n\t\t\texplicitReferences = new Map();\n\t\t});\n\n\t\tit(\"does not log gcUnknownOutboundReferences when there are no new references\", async () => {\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatchNone(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"There should be no gcUnknownOutboundReferences event\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"logs gcUnknownOutboundReferences when there are unknown data store references\", async () => {\n\t\t\tconst id = nodes[0];\n\t\t\tconst routes = [nodes[2], nodes[3]];\n\t\t\tcurrentGCData.gcNodes[id] = routes;\n\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatch(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t\t...tagCodeArtifacts({ id, routes: JSON.stringify(routes) }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"gcUnknownOutboundReferences event not logged as expected\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"logs gcUnknownOutboundReferences when there are multiple unknown data store references\", async () => {\n\t\t\tconst id1 = nodes[0];\n\t\t\tconst routes1 = [nodes[2], nodes[3]];\n\t\t\tconst id2 = nodes[3];\n\t\t\tconst routes2 = [nodes[1], nodes[2]];\n\t\t\tcurrentGCData.gcNodes[id1] = routes1;\n\t\t\tcurrentGCData.gcNodes[id2] = routes2;\n\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatch(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: id1, routes: JSON.stringify(routes1) }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: id2, routes: JSON.stringify(routes2) }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"gcUnknownOutboundReferences event not logged as expected\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"logs gcUnknownOutboundReferences when there are unknown blob references\", async () => {\n\t\t\tconst id = nodes[0];\n\t\t\t// Id of type `/_blobs/id1 is treated as a blob node.\n\t\t\tconst routes = [\"/_blobs/id1\"];\n\t\t\tcurrentGCData.gcNodes[id] = routes;\n\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatch(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t\t...tagCodeArtifacts({ id, routes: JSON.stringify(routes) }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"gcUnknownOutboundReferences event not logged as expected for blob nodes\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"does not log gcUnknownOutboundReferences for back-routes (ex: DDS to data store)\", async () => {\n\t\t\t// Id of type `/id1/id2 is treated as a sub-data store (DDS) node.\n\t\t\tconst id = `${nodes[1]}/dds`;\n\t\t\tconst routes = [nodes[1]];\n\t\t\tcurrentGCData.gcNodes[id] = routes;\n\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatchNone(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"There should be no gcUnknownOutboundReferences event when back-routes are added\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"does not log gcUnknownOutboundReferences for sub-dataStore routes (ex: to DDS)\", async () => {\n\t\t\tconst id = nodes[1];\n\t\t\t// Id of type `/id1/id2 is treated as a sub-data store (DDS) node.\n\t\t\tconst routes = [`${nodes[1]}/dds`];\n\t\t\tcurrentGCData.gcNodes[id] = routes;\n\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatchNone(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"There should be no gcUnknownOutboundReferences event when sub-dataStore routes are added\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"does not log gcUnknownOutboundReferences for other routes (ex: unknown routes)\", async () => {\n\t\t\tconst id = nodes[1];\n\t\t\t// Id of type `/id1/id2/ids31` is treated as a other node type.\n\t\t\tconst routes = [`${nodes[1]}/ids2/ids3`];\n\t\t\tcurrentGCData.gcNodes[id] = routes;\n\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatchNone(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"There should be no gcUnknownOutboundReferences event when other node routes are added\",\n\t\t\t);\n\t\t});\n\t});\n});\n"]}
|
|
1
|
+
{"version":3,"file":"gcTelemetry.spec.js","sourceRoot":"","sources":["../../../src/test/gc/gcTelemetry.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { ITelemetryBaseEvent } from \"@fluidframework/core-interfaces\";\nimport { IGarbageCollectionData } from \"@fluidframework/runtime-definitions\";\nimport {\n\tMockLogger,\n\tMonitoringContext,\n\tTelemetryDataTag,\n\tcreateChildLogger,\n\tmixinMonitoringContext,\n\ttagCodeArtifacts,\n} from \"@fluidframework/telemetry-utils\";\nimport { SinonFakeTimers, useFakeTimers } from \"sinon\";\nimport { BlobManager } from \"../../blobManager.js\";\nimport {\n\tGCNodeType,\n\tGCTelemetryTracker,\n\tIGarbageCollectorConfigs,\n\tUnreferencedStateTracker,\n\tcloneGCData,\n\tdefaultSessionExpiryDurationMs,\n\toneDayMs,\n\tstableGCVersion,\n} from \"../../gc/index.js\";\nimport { pkgVersion } from \"../../packageVersion.js\";\n\ndescribe(\"GC Telemetry Tracker\", () => {\n\tconst defaultSnapshotCacheExpiryMs = 5 * 24 * 60 * 60 * 1000;\n\tconst tombstoneTimeoutMs =\n\t\tdefaultSessionExpiryDurationMs + defaultSnapshotCacheExpiryMs + oneDayMs;\n\tconst inactiveTimeoutMs = 500;\n\n\t// Nodes in the reference graph.\n\tconst nodes: string[] = [\"/node1\", \"/node2\", \"/node3\", \"/node4\"];\n\n\tconst testPkgPath = [\"testPkg\"];\n\t// The package data is tagged in the telemetry event.\n\tconst eventPkg = { value: testPkgPath.join(\"/\"), tag: TelemetryDataTag.CodeArtifact };\n\n\tlet mockLogger: MockLogger;\n\tlet mc: MonitoringContext;\n\tlet clock: SinonFakeTimers;\n\tlet sweepGracePeriodMs = 1000; // Default case for these tests\n\tlet unreferencedNodesState: Map<string, UnreferencedStateTracker> = new Map();\n\tlet telemetryTracker: GCTelemetryTracker;\n\n\tfunction createTelemetryTracker(\n\t\tenableSweep: boolean,\n\t\tisSummarizerClient = true,\n\t): GCTelemetryTracker {\n\t\t// Node types are as follows based on the path:\n\t\t// Path starting with \"/_blobs\" - blob.\n\t\t// Path with one part such as \"/id1\" - data stores.\n\t\t// Path with two parts such as \"/id1/id2\" - sub data stores.\n\t\t// Everything else - other.\n\t\tconst getNodeType = (nodePath: string) => {\n\t\t\tif (nodePath.split(\"/\")[1] === BlobManager.basePath) {\n\t\t\t\treturn GCNodeType.Blob;\n\t\t\t}\n\t\t\tif (nodePath.split(\"/\").length === 2) {\n\t\t\t\treturn GCNodeType.DataStore;\n\t\t\t}\n\t\t\tif (nodePath.split(\"/\").length === 3) {\n\t\t\t\treturn GCNodeType.SubDataStore;\n\t\t\t}\n\t\t\treturn GCNodeType.Other;\n\t\t};\n\t\tconst configs: IGarbageCollectorConfigs = {\n\t\t\tgcEnabled: true,\n\t\t\tsweepEnabled: false,\n\t\t\tshouldRunGC: true,\n\t\t\tshouldRunSweep: \"NO\",\n\t\t\trunFullGC: false,\n\t\t\ttestMode: false,\n\t\t\ttombstoneMode: false,\n\t\t\tinactiveTimeoutMs,\n\t\t\tsessionExpiryTimeoutMs: defaultSessionExpiryDurationMs,\n\t\t\ttombstoneTimeoutMs: enableSweep ? tombstoneTimeoutMs : undefined,\n\t\t\tsweepGracePeriodMs,\n\t\t\tthrowOnTombstoneLoad: false,\n\t\t\tthrowOnTombstoneUsage: false,\n\t\t\tthrowOnInactiveLoad: false,\n\t\t\tpersistedGcFeatureMatrix: undefined,\n\t\t\tgcVersionInBaseSnapshot: stableGCVersion,\n\t\t\tgcVersionInEffect: stableGCVersion,\n\t\t};\n\t\tconst tracker = new GCTelemetryTracker(\n\t\t\tmc,\n\t\t\tconfigs,\n\t\t\tisSummarizerClient,\n\t\t\t{ createContainerRuntimeVersion: pkgVersion },\n\t\t\tgetNodeType,\n\t\t\t(nodeId: string) => unreferencedNodesState.get(nodeId),\n\t\t\tasync (nodeId: string) => testPkgPath,\n\t\t);\n\t\treturn tracker;\n\t}\n\n\t/**\n\t * For each node in nodeIds, add an entry in `unreferencedNodesState` indicating that the node was\n\t * just unreferenced.\n\t */\n\tfunction markNodesUnreferenced(nodeIds: string[]) {\n\t\tnodeIds.forEach((nodeId) => {\n\t\t\tunreferencedNodesState.set(\n\t\t\t\tnodeId,\n\t\t\t\tnew UnreferencedStateTracker(\n\t\t\t\t\tDate.now(),\n\t\t\t\t\tinactiveTimeoutMs,\n\t\t\t\t\tDate.now(),\n\t\t\t\t\ttombstoneTimeoutMs,\n\t\t\t\t\tsweepGracePeriodMs,\n\t\t\t\t),\n\t\t\t);\n\t\t});\n\t}\n\n\t// Mock node loaded and changed activity for the given nodes.\n\tfunction mockNodeChanges(nodeIds: string[]) {\n\t\tnodeIds.forEach((id) => {\n\t\t\ttelemetryTracker.nodeUsed({\n\t\t\t\tid,\n\t\t\t\tusageType: \"Loaded\",\n\t\t\t\tcurrentReferenceTimestampMs: Date.now(),\n\t\t\t\tpackagePath: testPkgPath,\n\t\t\t\tcompletedGCRuns: 0,\n\t\t\t\tisTombstoned: false,\n\t\t\t});\n\t\t\ttelemetryTracker.nodeUsed({\n\t\t\t\tid,\n\t\t\t\tusageType: \"Changed\",\n\t\t\t\tcurrentReferenceTimestampMs: Date.now(),\n\t\t\t\tpackagePath: testPkgPath,\n\t\t\t\tcompletedGCRuns: 0,\n\t\t\t\tisTombstoned: false,\n\t\t\t});\n\t\t});\n\t}\n\n\t// Mock node revived activity for the given nodes.\n\tfunction reviveNode(fromId: string, toId: string, isTombstoned = false) {\n\t\ttelemetryTracker.nodeUsed({\n\t\t\tid: toId,\n\t\t\tusageType: \"Revived\",\n\t\t\tcurrentReferenceTimestampMs: Date.now(),\n\t\t\tpackagePath: testPkgPath,\n\t\t\tcompletedGCRuns: 0,\n\t\t\tisTombstoned,\n\t\t\tfromId,\n\t\t});\n\t\tunreferencedNodesState.delete(toId);\n\t}\n\n\t/**\n\t * For summarizer clients, inactive / sweep ready events are not logged when on node usage. They are logged when GC\n\t * runs next time. This emulates that by calling the functions in the telemetry tracker that are called when GC runs.\n\t */\n\tasync function simulateGCToTriggerEvents(isSummarizerClient: boolean) {\n\t\tif (!isSummarizerClient) {\n\t\t\treturn;\n\t\t}\n\t\tawait telemetryTracker.logPendingEvents(mc.logger);\n\t}\n\n\tbefore(() => {\n\t\tclock = useFakeTimers();\n\t});\n\n\tbeforeEach(() => {\n\t\tmockLogger = new MockLogger();\n\t\tmc = mixinMonitoringContext(\n\t\t\tcreateChildLogger({ logger: mockLogger, namespace: \"GarbageCollector\" }),\n\t\t);\n\t\tunreferencedNodesState = new Map();\n\t});\n\n\tafterEach(() => {\n\t\tclock.reset();\n\t\tmockLogger.clear();\n\t\tsweepGracePeriodMs = 1000; // Default case for these tests\n\t});\n\n\tafter(() => {\n\t\tclock.restore();\n\t});\n\n\t// Tests that are run once for summarizer client and once for interactive client.\n\tconst clientTypeTests = (isSummarizerClient: boolean) => {\n\t\t/**\n\t\t * Asserts that the events are as expected based on whether its a summarizer client or not. In non-summarizer\n\t\t * clients, only \"InactiveObject_Loaded\", \"TombstoneReadyObject_Loaded\" and \"SweepReadyObject_Loaded\" events are logged.\n\t\t * \"_Changed\" and \"_Revived\" events are not logged.\n\t\t */\n\t\tfunction assertMatchEvents(\n\t\t\tevents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\t\tmessage: string,\n\t\t) {\n\t\t\tconst expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[] = [];\n\t\t\tconst unexpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[] = [];\n\t\t\t// For non-summarizer clients, events that are not \"Loaded\" are unexpected. Everything else is expected.\n\t\t\tfor (const event of events) {\n\t\t\t\tconst eventName = event.eventName as string;\n\t\t\t\tif (!isSummarizerClient && !eventName.includes(\"Loaded\")) {\n\t\t\t\t\tunexpectedEvents.push(event);\n\t\t\t\t} else {\n\t\t\t\t\texpectedEvents.push(event);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Note that mock logger clears all events after one of the `match` functions is called. Since we call match\n\t\t\t// functions twice, cache the events and repopulate the mock logger with if after the first match call.\n\t\t\tconst cachedEvents = Array.from(mockLogger.events);\n\t\t\tmockLogger.assertMatch(expectedEvents, message, true /* inlineDetailsProp */);\n\t\t\tmockLogger.events = cachedEvents;\n\t\t\tmockLogger.assertMatchNone(unexpectedEvents, message, true /* inlineDetailsProp */);\n\t\t}\n\n\t\tit(\"generates inactive, tombstone ready, and sweep ready events when nodes are used after time out\", async () => {\n\t\t\ttelemetryTracker = createTelemetryTracker(true /* enable Sweep */, isSummarizerClient);\n\t\t\t// Mark nodes 2 and 3 as unreferenced.\n\t\t\tmarkNodesUnreferenced([nodes[2], nodes[3]]);\n\n\t\t\t// Advance the clock to trigger inactive timeout and validate that inactive events are as expected.\n\t\t\tclock.tick(inactiveTimeoutMs + 1);\n\t\t\tmockNodeChanges(nodes);\n\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\tassertMatchEvents(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:InactiveObject_Loaded\",\n\t\t\t\t\t\ttimeout: inactiveTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:InactiveObject_Changed\",\n\t\t\t\t\t\ttimeout: inactiveTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:InactiveObject_Loaded\",\n\t\t\t\t\t\ttimeout: inactiveTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[3] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:InactiveObject_Changed\",\n\t\t\t\t\t\ttimeout: inactiveTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[3] }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"inactive events not as expected\",\n\t\t\t);\n\n\t\t\t// Advance the clock to trigger tombstone timeout and validate that TombstoneReady events are as expected.\n\t\t\tclock.tick(tombstoneTimeoutMs - inactiveTimeoutMs);\n\t\t\tmockNodeChanges(nodes);\n\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\tassertMatchEvents(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:TombstoneReadyObject_Loaded\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:TombstoneReadyObject_Changed\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:TombstoneReadyObject_Loaded\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[3] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:TombstoneReadyObject_Changed\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[3] }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"tombstone ready events not as expected\",\n\t\t\t);\n\n\t\t\t// Advance the clock by the delay and validate that SweepReady events are as expected.\n\t\t\tclock.tick(sweepGracePeriodMs);\n\t\t\tmockNodeChanges(nodes);\n\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\tassertMatchEvents(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:SweepReadyObject_Loaded\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs + sweepGracePeriodMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:SweepReadyObject_Changed\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs + sweepGracePeriodMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:SweepReadyObject_Loaded\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs + sweepGracePeriodMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[3] }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:SweepReadyObject_Changed\",\n\t\t\t\t\t\ttimeout: tombstoneTimeoutMs + sweepGracePeriodMs,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[3] }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"sweep ready events not as expected\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"generates tombstone revived events when nodes are used after they are tombstoned\", async () => {\n\t\t\ttelemetryTracker = createTelemetryTracker(true /* enable Sweep */, isSummarizerClient);\n\t\t\t// Mark node 2 as unreferenced.\n\t\t\tmarkNodesUnreferenced([nodes[2]]);\n\n\t\t\t// Advance the clock to trigger tombstone timeout and validate that tombstone revived event is as expected.\n\t\t\tclock.tick(tombstoneTimeoutMs + 1);\n\t\t\treviveNode(nodes[1], nodes[2], true /* isTombstoned */);\n\t\t\tmockLogger.assertMatch(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"GarbageCollector:GC_Tombstone_DataStore_Revived\",\n\t\t\t\t\t\tpkg: eventPkg,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"inactive events not as expected\",\n\t\t\t);\n\t\t});\n\n\t\t/** Tests that validate either the relevant events are logged as expected. */\n\t\tconst unreferencedPhasesEventTests = (\n\t\t\ttimeout: number,\n\t\t\tmode: \"inactive\" | \"tombstone\" | \"sweep\",\n\t\t\trevivedEventName: string,\n\t\t\tchangedEventName: string,\n\t\t\tloadedEventName: string,\n\t\t\tsweepGracePeriodMsOverride?: number,\n\t\t) => {\n\t\t\t// Validates that no unexpected event has been fired.\n\t\t\tfunction validateNoEvents() {\n\t\t\t\tmockLogger.assertMatchNone(\n\t\t\t\t\t[\n\t\t\t\t\t\t{ eventName: revivedEventName },\n\t\t\t\t\t\t{ eventName: changedEventName },\n\t\t\t\t\t\t{ eventName: loadedEventName },\n\t\t\t\t\t],\n\t\t\t\t\t\"unexpected events logged\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tbeforeEach(() => {\n\t\t\t\tif (sweepGracePeriodMsOverride !== undefined) {\n\t\t\t\t\tsweepGracePeriodMs = sweepGracePeriodMsOverride;\n\t\t\t\t}\n\t\t\t\ttelemetryTracker = createTelemetryTracker(\n\t\t\t\t\tmode !== \"inactive\" /* enableSweep */,\n\t\t\t\t\tisSummarizerClient,\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tit(\"doesn't generate events for referenced nodes\", async () => {\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tvalidateNoEvents();\n\n\t\t\t\t// Advance the clock to just before the timeout expires, update nodes and validate no events.\n\t\t\t\tclock.tick(timeout - 1);\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tvalidateNoEvents();\n\n\t\t\t\t// Advance the clock to expire the timeout, update nodes and validate no events.\n\t\t\t\tclock.tick(1);\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tvalidateNoEvents();\n\t\t\t});\n\n\t\t\tit(\"generates events for nodes that are used after state changes\", async () => {\n\t\t\t\t// Mark nodes 1 and 2 as unreferenced.\n\t\t\t\tmarkNodesUnreferenced([nodes[1], nodes[2]]);\n\n\t\t\t\t// Advance the clock just before the timeout and validate no unexpected events are logged.\n\t\t\t\tclock.tick(timeout - 1);\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tvalidateNoEvents();\n\n\t\t\t\t// Expire the timeout, update nodes and validate that all events for node 1 and node 2 are logged.\n\t\t\t\tclock.tick(1);\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tconst expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[] = [];\n\t\t\t\texpectedEvents.push(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: loadedEventName,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[1], pkg: testPkgPath.join(\"/\") }),\n\t\t\t\t\t\tcreateContainerRuntimeVersion: pkgVersion,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: changedEventName,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[1], pkg: testPkgPath.join(\"/\") }),\n\t\t\t\t\t\tcreateContainerRuntimeVersion: pkgVersion,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: loadedEventName,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2], pkg: testPkgPath.join(\"/\") }),\n\t\t\t\t\t\tcreateContainerRuntimeVersion: pkgVersion,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: changedEventName,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2], pkg: testPkgPath.join(\"/\") }),\n\t\t\t\t\t\tcreateContainerRuntimeVersion: pkgVersion,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tassertMatchEvents(expectedEvents, \"all events not as expected\");\n\n\t\t\t\t// Revived node 2 and validate that revived event is as expected.\n\t\t\t\treviveNode(nodes[0], nodes[2]);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tassertMatchEvents(\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: revivedEventName,\n\t\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t\t...tagCodeArtifacts({\n\t\t\t\t\t\t\t\tid: nodes[2],\n\t\t\t\t\t\t\t\tfromId: nodes[0],\n\t\t\t\t\t\t\t\tpkg: testPkgPath.join(\"/\"),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\t\"revived event not as expected\",\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tit(\"generates events once per node\", async () => {\n\t\t\t\t// Mark node 2 as unreferenced.\n\t\t\t\tmarkNodesUnreferenced([nodes[2]]);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\n\t\t\t\t// Advance the clock just before the timeout and validate no unexpected events are logged.\n\t\t\t\tclock.tick(timeout - 1);\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tvalidateNoEvents();\n\n\t\t\t\t// Expire the timeout, updated nodes and validate that events are logged as expected.\n\t\t\t\tclock.tick(1);\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tconst expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[] = [];\n\t\t\t\texpectedEvents.push(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: loadedEventName,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t\tpkg: eventPkg,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: changedEventName,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: nodes[2] }),\n\t\t\t\t\t\tpkg: eventPkg,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tassertMatchEvents(expectedEvents, \"all events not as expected\");\n\n\t\t\t\t// Update all nodes again. There shouldn't be any more events since for each node the event is only once.\n\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\t\t\t\tvalidateNoEvents();\n\t\t\t});\n\n\t\t\t// This test is only relevant for summarizer client because it does not log changed events if the node is revived.\n\t\t\tif (isSummarizerClient) {\n\t\t\t\tit(\"generates only revived event in summarizer when a node is updated and revived\", async () => {\n\t\t\t\t\t// Mark node 2 as unreferenced.\n\t\t\t\t\tmarkNodesUnreferenced([nodes[2]]);\n\n\t\t\t\t\t// Advance the clock just before the timeout and validate no unexpected events are logged.\n\t\t\t\t\tclock.tick(timeout - 1);\n\t\t\t\t\tmockNodeChanges(nodes);\n\t\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\n\t\t\t\t\tvalidateNoEvents();\n\n\t\t\t\t\t// Expire the timeout and validate that only revived event is generated for node 2.\n\t\t\t\t\tclock.tick(1);\n\t\t\t\t\tmockNodeChanges([nodes[2]]);\n\t\t\t\t\treviveNode(nodes[1], nodes[2]);\n\t\t\t\t\tawait simulateGCToTriggerEvents(isSummarizerClient);\n\n\t\t\t\t\tfor (const event of mockLogger.events) {\n\t\t\t\t\t\tassert.notStrictEqual(\n\t\t\t\t\t\t\tevent.eventName,\n\t\t\t\t\t\t\tloadedEventName,\n\t\t\t\t\t\t\t\"Unexpected loaded event logged\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.notStrictEqual(\n\t\t\t\t\t\t\tevent.eventName,\n\t\t\t\t\t\t\tchangedEventName,\n\t\t\t\t\t\t\t\"Unexpected changed event logged\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tassertMatchEvents(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\teventName: revivedEventName,\n\t\t\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\t\t\t...tagCodeArtifacts({\n\t\t\t\t\t\t\t\t\tid: nodes[2],\n\t\t\t\t\t\t\t\t\tfromId: nodes[1],\n\t\t\t\t\t\t\t\t\tpkg: testPkgPath.join(\"/\"),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"revived event not as expected\",\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tdescribe(\"Inactive events\", () => {\n\t\t\tunreferencedPhasesEventTests(\n\t\t\t\tinactiveTimeoutMs,\n\t\t\t\t\"inactive\",\n\t\t\t\t\"GarbageCollector:InactiveObject_Revived\",\n\t\t\t\t\"GarbageCollector:InactiveObject_Changed\",\n\t\t\t\t\"GarbageCollector:InactiveObject_Loaded\",\n\t\t\t);\n\t\t});\n\n\t\tdescribe(\"TombstoneReady events\", () => {\n\t\t\tunreferencedPhasesEventTests(\n\t\t\t\ttombstoneTimeoutMs,\n\t\t\t\t\"tombstone\",\n\t\t\t\t\"GarbageCollector:TombstoneReadyObject_Revived\",\n\t\t\t\t\"GarbageCollector:TombstoneReadyObject_Changed\",\n\t\t\t\t\"GarbageCollector:TombstoneReadyObject_Loaded\",\n\t\t\t);\n\t\t});\n\n\t\tdescribe(\"SweepReady events (with no delay)\", () => {\n\t\t\tunreferencedPhasesEventTests(\n\t\t\t\ttombstoneTimeoutMs,\n\t\t\t\t\"sweep\", // Jump straight to SweepReady given 0 delay\n\t\t\t\t\"GarbageCollector:SweepReadyObject_Revived\",\n\t\t\t\t\"GarbageCollector:SweepReadyObject_Changed\",\n\t\t\t\t\"GarbageCollector:SweepReadyObject_Loaded\",\n\t\t\t\t0 /* sweepGracePeriodMsOverride */,\n\t\t\t);\n\t\t});\n\n\t\tdescribe(\"SweepReady events\", () => {\n\t\t\tunreferencedPhasesEventTests(\n\t\t\t\ttombstoneTimeoutMs + sweepGracePeriodMs,\n\t\t\t\t\"sweep\",\n\t\t\t\t\"GarbageCollector:SweepReadyObject_Revived\",\n\t\t\t\t\"GarbageCollector:SweepReadyObject_Changed\",\n\t\t\t\t\"GarbageCollector:SweepReadyObject_Loaded\",\n\t\t\t);\n\t\t});\n\t};\n\n\tdescribe(\"Summarizer client\", () => {\n\t\tclientTypeTests(true /* isSummarizerClient */);\n\t});\n\n\tdescribe(\"Interactive client\", () => {\n\t\tclientTypeTests(false /* isSummarizerClient */);\n\t});\n\n\tdescribe(\"gcUnknownOutboundReferences telemetry\", () => {\n\t\tconst unknownReferenceEventName = \"GarbageCollector:gcUnknownOutboundReferences\";\n\t\tconst currentGCData: IGarbageCollectionData = { gcNodes: {} };\n\t\tlet previousGCData: IGarbageCollectionData;\n\t\tlet explicitReferences: Map<string, string[]>;\n\n\t\tbeforeEach(() => {\n\t\t\ttelemetryTracker = createTelemetryTracker(\n\t\t\t\ttrue /* enableSweep */,\n\t\t\t\ttrue /* isSummarizerClient */,\n\t\t\t);\n\n\t\t\tcurrentGCData.gcNodes[\"/\"] = [nodes[0]];\n\t\t\tcurrentGCData.gcNodes[nodes[0]] = [nodes[1]];\n\t\t\tcurrentGCData.gcNodes[nodes[1]] = [nodes[0], nodes[2]];\n\t\t\tcurrentGCData.gcNodes[nodes[2]] = [nodes[1], nodes[3]];\n\t\t\tcurrentGCData.gcNodes[nodes[3]] = [nodes[0]];\n\n\t\t\tpreviousGCData = cloneGCData(currentGCData);\n\t\t\texplicitReferences = new Map();\n\t\t});\n\n\t\tit(\"does not log gcUnknownOutboundReferences when there are no new references\", async () => {\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatchNone(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"There should be no gcUnknownOutboundReferences event\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"logs gcUnknownOutboundReferences when there are unknown data store references\", async () => {\n\t\t\tconst id = nodes[0];\n\t\t\tconst routes = [nodes[2], nodes[3]];\n\t\t\tcurrentGCData.gcNodes[id] = routes;\n\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatch(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t\t...tagCodeArtifacts({ id, routes: JSON.stringify(routes) }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"gcUnknownOutboundReferences event not logged as expected\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"logs gcUnknownOutboundReferences when there are multiple unknown data store references\", async () => {\n\t\t\tconst id1 = nodes[0];\n\t\t\tconst routes1 = [nodes[2], nodes[3]];\n\t\t\tconst id2 = nodes[3];\n\t\t\tconst routes2 = [nodes[1], nodes[2]];\n\t\t\tcurrentGCData.gcNodes[id1] = routes1;\n\t\t\tcurrentGCData.gcNodes[id2] = routes2;\n\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatch(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: id1, routes: JSON.stringify(routes1) }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t\t...tagCodeArtifacts({ id: id2, routes: JSON.stringify(routes2) }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"gcUnknownOutboundReferences event not logged as expected\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"logs gcUnknownOutboundReferences when there are unknown blob references\", async () => {\n\t\t\tconst id = nodes[0];\n\t\t\t// Id of type `/_blobs/id1 is treated as a blob node.\n\t\t\tconst routes = [\"/_blobs/id1\"];\n\t\t\tcurrentGCData.gcNodes[id] = routes;\n\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatch(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t\t...tagCodeArtifacts({ id, routes: JSON.stringify(routes) }),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"gcUnknownOutboundReferences event not logged as expected for blob nodes\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"does not log gcUnknownOutboundReferences for back-routes (ex: DDS to data store)\", async () => {\n\t\t\t// Id of type `/id1/id2 is treated as a sub-data store (DDS) node.\n\t\t\tconst id = `${nodes[1]}/dds`;\n\t\t\tconst routes = [nodes[1]];\n\t\t\tcurrentGCData.gcNodes[id] = routes;\n\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatchNone(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"There should be no gcUnknownOutboundReferences event when back-routes are added\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"does not log gcUnknownOutboundReferences for sub-dataStore routes (ex: to DDS)\", async () => {\n\t\t\tconst id = nodes[1];\n\t\t\t// Id of type `/id1/id2 is treated as a sub-data store (DDS) node.\n\t\t\tconst routes = [`${nodes[1]}/dds`];\n\t\t\tcurrentGCData.gcNodes[id] = routes;\n\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatchNone(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"There should be no gcUnknownOutboundReferences event when sub-dataStore routes are added\",\n\t\t\t);\n\t\t});\n\n\t\tit(\"does not log gcUnknownOutboundReferences for other routes (ex: unknown routes)\", async () => {\n\t\t\tconst id = nodes[1];\n\t\t\t// Id of type `/id1/id2/ids31` is treated as a other node type.\n\t\t\tconst routes = [`${nodes[1]}/ids2/ids3`];\n\t\t\tcurrentGCData.gcNodes[id] = routes;\n\n\t\t\ttelemetryTracker.logIfMissingExplicitReferences(\n\t\t\t\tcurrentGCData,\n\t\t\t\tpreviousGCData,\n\t\t\t\texplicitReferences,\n\t\t\t\tmc.logger,\n\t\t\t);\n\n\t\t\tmockLogger.assertMatchNone(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: unknownReferenceEventName,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t\"There should be no gcUnknownOutboundReferences event when other node routes are added\",\n\t\t\t);\n\t\t});\n\t});\n});\n"]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { strict as assert } from "assert";
|
|
6
|
-
import {
|
|
6
|
+
import { spy, useFakeTimers } from "sinon";
|
|
7
7
|
import { UnreferencedState, UnreferencedStateTracker } from "../../gc/index.js";
|
|
8
8
|
describe("Garbage Collection Tests", () => {
|
|
9
9
|
let clock;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gcUnreferencedStateTracker.spec.js","sourceRoot":"","sources":["../../../src/test/gc/gcUnreferencedStateTracker.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { SinonFakeTimers, SinonSpy, useFakeTimers, spy } from \"sinon\";\nimport { UnreferencedState, UnreferencedStateTracker } from \"../../gc/index.js\";\n\n/** Schema for steps taken to test unreferenced state progression / tracking */\ntype Steps = [\n\t{\n\t\t/** Start time (used as both local time and currentReferenceTimestampMs) */\n\t\ttime: number;\n\t\t/** Expected initial state */\n\t\tstate: UnreferencedState;\n\t\t/** Configured sweepGracePeriodMs - defaults to 10ms for these tests */\n\t\tsweepGracePeriodMs?: number;\n\t},\n\t...{\n\t\t/** Local time of the next step */\n\t\ttime: number;\n\t\t/** If defined, call updateTracking with this as currentReferenceTimestampMs */\n\t\tupdateWith?: number;\n\t\t/** Expected new state (after calling updateTracking if applicable) */\n\t\tstate: UnreferencedState;\n\t}[],\n];\n\ndescribe(\"Garbage Collection Tests\", () => {\n\tlet clock: SinonFakeTimers;\n\n\tbefore(() => {\n\t\tclock = useFakeTimers();\n\t});\n\n\tafterEach(() => {\n\t\tclock.reset();\n\t});\n\n\tafter(() => {\n\t\tclock.restore();\n\t});\n\n\tdescribe(\"UnreferencedStateTracker\", () => {\n\t\tlet tracker: UnreferencedStateTracker;\n\n\t\tafterEach(() => {\n\t\t\ttracker.stopTracking();\n\t\t});\n\n\t\t/**\n\t\t * During the lifetime of an unreferenced object, its state is tracked and updated in two ways.\n\t\t * Timers are set to trigger transitioning to the next state, and updateTracking is also called\n\t\t * whenever GC runs.\n\t\t * These tests specify how to advance the clock (to hit the timers) and also when to call updateTracking,\n\t\t * checking that the expected state transitions occur as specified\n\t\t */\n\t\tfunction runTestCase(allSteps: Steps) {\n\t\t\tconst [start, ...steps] = allSteps;\n\t\t\tclock.tick(start.time);\n\n\t\t\ttracker = new UnreferencedStateTracker(\n\t\t\t\t0 /* unreferencedTimestampMs */,\n\t\t\t\t10 /* inactiveTimeoutMs */,\n\t\t\t\tstart.time /* currentReferenceTimestampMs */,\n\t\t\t\t20 /* tombstoneTimeoutMs */,\n\t\t\t\tstart.sweepGracePeriodMs ?? 10 /* sweepGracePeriodMs */,\n\t\t\t);\n\t\t\tassert.equal(tracker.state, start.state, `Wrong starting state`);\n\t\t\tsteps.forEach(({ time: advanceClockTo, updateWith, state: expectedState }, index) => {\n\t\t\t\tassert(\n\t\t\t\t\tadvanceClockTo > clock.now,\n\t\t\t\t\t\"INVALID TEST CASE: steps must move forward in time, following start\",\n\t\t\t\t);\n\t\t\t\tclock.tick(advanceClockTo - clock.now);\n\n\t\t\t\tif (updateWith !== undefined) {\n\t\t\t\t\ttracker.updateTracking(updateWith);\n\t\t\t\t}\n\n\t\t\t\tassert.equal(tracker.state, expectedState, `Wrong state at step ${index + 1}`); // 0-indexed including start\n\t\t\t});\n\t\t}\n\n\t\t/**\n\t\t * Test cases to run through above function runTestCase\n\t\t *\n\t\t * In all cases:\n\t\t * - unreferencedTimestampMs = 0\n\t\t * - inactiveTimeoutMs = 10\n\t\t * - tombstoneTimeoutMs = 20\n\t\t * - sweepGracePeriodMs defaults to 10 (so sweep at 30)\n\t\t */\n\t\tconst testCases: {\n\t\t\tname: string;\n\t\t\tsteps: Steps;\n\t\t}[] = [\n\t\t\t{\n\t\t\t\tname: \"No calls to updateTracking\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\" },\n\t\t\t\t\t{ time: 3, state: \"Active\" },\n\t\t\t\t\t{ time: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 12, state: \"Inactive\" },\n\t\t\t\t\t{ time: 15, state: \"Inactive\" },\n\t\t\t\t\t{ time: 25, state: \"TombstoneReady\" },\n\t\t\t\t\t{ time: 35, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"No calls to updateTracking - sweepGracePeriodMs 0 (no Tombstone phase)\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\", sweepGracePeriodMs: 0 },\n\t\t\t\t\t{ time: 3, state: \"Active\" },\n\t\t\t\t\t{ time: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 12, state: \"Inactive\" },\n\t\t\t\t\t{ time: 19, state: \"Inactive\" },\n\t\t\t\t\t{ time: 20, state: \"SweepReady\" },\n\t\t\t\t\t{ time: 21, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Skip to SweepReady\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\" },\n\t\t\t\t\t{ time: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 35, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Skip to SweepReady - sweepGracePeriodMs 0 (no Tombstone phase)\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\", sweepGracePeriodMs: 0 },\n\t\t\t\t\t{ time: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 20, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Skip to SweepReady (via updateTracking) - sweepGracePeriodMs 0 (no Tombstone phase)\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\", sweepGracePeriodMs: 0 },\n\t\t\t\t\t{ time: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 20, updateWith: 20, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Call update, but triggered via timers\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\" },\n\t\t\t\t\t{ time: 3, updateWith: 2, state: \"Active\" },\n\t\t\t\t\t{ time: 5, updateWith: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 12, updateWith: 9, state: \"Inactive\" }, // Timer will have fired even though server time hasn't passed threshold\n\t\t\t\t\t{ time: 17, updateWith: 15, state: \"Inactive\" }, // No-op, timer already fired\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"currentReferenceTimestampMs jumps ahead\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\" },\n\t\t\t\t\t{ time: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 10, state: \"Inactive\" },\n\t\t\t\t\t{ time: 11, updateWith: 20, state: \"TombstoneReady\" }, // Shouldn't be physically possible, but supported in API\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Start Inactive\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 12, state: \"Inactive\" },\n\t\t\t\t\t{ time: 15, state: \"Inactive\" },\n\t\t\t\t\t{ time: 20, state: \"TombstoneReady\" },\n\t\t\t\t\t{ time: 35, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Start TombstoneReady\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 22, state: \"TombstoneReady\" },\n\t\t\t\t\t{ time: 25, state: \"TombstoneReady\" },\n\t\t\t\t\t{ time: 35, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Start SweepReady\",\n\t\t\t\tsteps: [{ time: 32, state: \"SweepReady\" }],\n\t\t\t},\n\t\t];\n\n\t\ttestCases.forEach((testCase) => {\n\t\t\tit(testCase.name, () => {\n\t\t\t\trunTestCase(testCase.steps);\n\t\t\t});\n\t\t});\n\n\t\tit(\"Non-zero unreferencedTimestampMs properly offsets\", () => {\n\t\t\ttracker = new UnreferencedStateTracker(\n\t\t\t\t10 /* unreferencedTimestampMs */,\n\t\t\t\t3 /* inactiveTimeoutMs */,\n\t\t\t\t11 /* currentReferenceTimestampMs */,\n\t\t\t\t7 /* tombstoneTimeoutMs */,\n\t\t\t\t15 /* sweepGracePeriodMs */,\n\t\t\t);\n\t\t\tassert.equal(tracker.state, UnreferencedState.Active, \"Should start as Active\");\n\t\t\tclock.tick(2);\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.Inactive,\n\t\t\t\t\"Should be Inactive 2ms later (at 13)\",\n\t\t\t);\n\t\t\ttracker.updateTracking(17);\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.TombstoneReady,\n\t\t\t\t\"Should be TombstoneReady after currentReferenceTimestampMs=17\",\n\t\t\t);\n\t\t\tclock.tick(15);\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.SweepReady,\n\t\t\t\t\"Should be SweepReady 15ms later\",\n\t\t\t);\n\t\t});\n\t\tit(\"Timers can't be crossed\", () => {\n\t\t\ttracker = new UnreferencedStateTracker(\n\t\t\t\t0 /* unreferencedTimestampMs */,\n\t\t\t\t10 /* inactiveTimeoutMs */,\n\t\t\t\t0 /* currentReferenceTimestampMs */,\n\t\t\t\t12 /* tombstoneTimeoutMs */,\n\t\t\t\t0 /* sweepGracePeriodMs */,\n\t\t\t);\n\t\t\tassert.equal(tracker.state, UnreferencedState.Active, \"Should start as Active\");\n\t\t\ttracker.updateTracking(10);\n\t\t\t// Would be 10ms left on Inactive timer, but it was just cleared. 2ms left on Sweep timer\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.Inactive,\n\t\t\t\t\"Should be Inactive after currentReferenceTimestampMs=10\",\n\t\t\t);\n\t\t\tclock.tick(2);\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.SweepReady,\n\t\t\t\t\"Should be SweepReady 2ms later\",\n\t\t\t);\n\t\t});\n\t\tit(\"Timers can tighten up over time\", () => {\n\t\t\tclock.tick(10);\n\t\t\ttracker = new UnreferencedStateTracker(\n\t\t\t\t0 /* unreferencedTimestampMs */,\n\t\t\t\t20 /* inactiveTimeoutMs */,\n\t\t\t\t5 /* currentReferenceTimestampMs */,\n\t\t\t\tundefined /* tombstoneTimeoutMs */,\n\t\t\t\t0 /* sweepGracePeriodMs */,\n\t\t\t);\n\t\t\tassert.equal(tracker.state, UnreferencedState.Active, \"Should start as Active\");\n\t\t\tconst timerClearSpy: SinonSpy = spy((tracker as any).inactiveTimer, \"clear\");\n\t\t\t// At T10 we had 15 to go based on server timestamps, so Timer is set to 25\n\t\t\tclock.tick(6); // at T16 (9 to go)\n\t\t\ttracker.updateTracking(15); // Simulate processing a more-recent Summary (reference time 15 at T16). Pulls in timer to 21 (5 to go)\n\t\t\tassert(\n\t\t\t\ttimerClearSpy.callCount > 0,\n\t\t\t\t\"Expected underlying Timer to clear and reset to support shorter timeout\",\n\t\t\t);\n\t\t\tclock.tick(5);\n\t\t\tassert.equal(tracker.state, UnreferencedState.Inactive, \"Should be Inactive at T21\");\n\t\t});\n\t\tit(\"Timers can loosen up over time\", () => {\n\t\t\ttracker = new UnreferencedStateTracker(\n\t\t\t\t0 /* unreferencedTimestampMs */,\n\t\t\t\t10 /* inactiveTimeoutMs */,\n\t\t\t\t0 /* currentReferenceTimestampMs */,\n\t\t\t\tundefined /* tombstoneTimeoutMs */,\n\t\t\t\t0 /* sweepGracePeriodMs */,\n\t\t\t);\n\t\t\tassert.equal(tracker.state, UnreferencedState.Active, \"Should start as Active\");\n\t\t\tclock.tick(5); // at T5, 5 to go\n\t\t\ttracker.updateTracking(1); // Simulate processing an older Summary (reference time 1 at T5). Pushes out timer to 14 (9 to go)\n\t\t\tclock.tick(5);\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.Active,\n\t\t\t\t\"Should still be Active since timer was pushed out\",\n\t\t\t);\n\t\t\tclock.tick(4);\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.Inactive,\n\t\t\t\t\"Should be Inactive finally at T14\",\n\t\t\t);\n\t\t});\n\t});\n});\n"]}
|
|
1
|
+
{"version":3,"file":"gcUnreferencedStateTracker.spec.js","sourceRoot":"","sources":["../../../src/test/gc/gcUnreferencedStateTracker.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { SinonFakeTimers, SinonSpy, spy, useFakeTimers } from \"sinon\";\nimport { UnreferencedState, UnreferencedStateTracker } from \"../../gc/index.js\";\n\n/** Schema for steps taken to test unreferenced state progression / tracking */\ntype Steps = [\n\t{\n\t\t/** Start time (used as both local time and currentReferenceTimestampMs) */\n\t\ttime: number;\n\t\t/** Expected initial state */\n\t\tstate: UnreferencedState;\n\t\t/** Configured sweepGracePeriodMs - defaults to 10ms for these tests */\n\t\tsweepGracePeriodMs?: number;\n\t},\n\t...{\n\t\t/** Local time of the next step */\n\t\ttime: number;\n\t\t/** If defined, call updateTracking with this as currentReferenceTimestampMs */\n\t\tupdateWith?: number;\n\t\t/** Expected new state (after calling updateTracking if applicable) */\n\t\tstate: UnreferencedState;\n\t}[],\n];\n\ndescribe(\"Garbage Collection Tests\", () => {\n\tlet clock: SinonFakeTimers;\n\n\tbefore(() => {\n\t\tclock = useFakeTimers();\n\t});\n\n\tafterEach(() => {\n\t\tclock.reset();\n\t});\n\n\tafter(() => {\n\t\tclock.restore();\n\t});\n\n\tdescribe(\"UnreferencedStateTracker\", () => {\n\t\tlet tracker: UnreferencedStateTracker;\n\n\t\tafterEach(() => {\n\t\t\ttracker.stopTracking();\n\t\t});\n\n\t\t/**\n\t\t * During the lifetime of an unreferenced object, its state is tracked and updated in two ways.\n\t\t * Timers are set to trigger transitioning to the next state, and updateTracking is also called\n\t\t * whenever GC runs.\n\t\t * These tests specify how to advance the clock (to hit the timers) and also when to call updateTracking,\n\t\t * checking that the expected state transitions occur as specified\n\t\t */\n\t\tfunction runTestCase(allSteps: Steps) {\n\t\t\tconst [start, ...steps] = allSteps;\n\t\t\tclock.tick(start.time);\n\n\t\t\ttracker = new UnreferencedStateTracker(\n\t\t\t\t0 /* unreferencedTimestampMs */,\n\t\t\t\t10 /* inactiveTimeoutMs */,\n\t\t\t\tstart.time /* currentReferenceTimestampMs */,\n\t\t\t\t20 /* tombstoneTimeoutMs */,\n\t\t\t\tstart.sweepGracePeriodMs ?? 10 /* sweepGracePeriodMs */,\n\t\t\t);\n\t\t\tassert.equal(tracker.state, start.state, `Wrong starting state`);\n\t\t\tsteps.forEach(({ time: advanceClockTo, updateWith, state: expectedState }, index) => {\n\t\t\t\tassert(\n\t\t\t\t\tadvanceClockTo > clock.now,\n\t\t\t\t\t\"INVALID TEST CASE: steps must move forward in time, following start\",\n\t\t\t\t);\n\t\t\t\tclock.tick(advanceClockTo - clock.now);\n\n\t\t\t\tif (updateWith !== undefined) {\n\t\t\t\t\ttracker.updateTracking(updateWith);\n\t\t\t\t}\n\n\t\t\t\tassert.equal(tracker.state, expectedState, `Wrong state at step ${index + 1}`); // 0-indexed including start\n\t\t\t});\n\t\t}\n\n\t\t/**\n\t\t * Test cases to run through above function runTestCase\n\t\t *\n\t\t * In all cases:\n\t\t * - unreferencedTimestampMs = 0\n\t\t * - inactiveTimeoutMs = 10\n\t\t * - tombstoneTimeoutMs = 20\n\t\t * - sweepGracePeriodMs defaults to 10 (so sweep at 30)\n\t\t */\n\t\tconst testCases: {\n\t\t\tname: string;\n\t\t\tsteps: Steps;\n\t\t}[] = [\n\t\t\t{\n\t\t\t\tname: \"No calls to updateTracking\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\" },\n\t\t\t\t\t{ time: 3, state: \"Active\" },\n\t\t\t\t\t{ time: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 12, state: \"Inactive\" },\n\t\t\t\t\t{ time: 15, state: \"Inactive\" },\n\t\t\t\t\t{ time: 25, state: \"TombstoneReady\" },\n\t\t\t\t\t{ time: 35, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"No calls to updateTracking - sweepGracePeriodMs 0 (no Tombstone phase)\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\", sweepGracePeriodMs: 0 },\n\t\t\t\t\t{ time: 3, state: \"Active\" },\n\t\t\t\t\t{ time: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 12, state: \"Inactive\" },\n\t\t\t\t\t{ time: 19, state: \"Inactive\" },\n\t\t\t\t\t{ time: 20, state: \"SweepReady\" },\n\t\t\t\t\t{ time: 21, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Skip to SweepReady\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\" },\n\t\t\t\t\t{ time: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 35, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Skip to SweepReady - sweepGracePeriodMs 0 (no Tombstone phase)\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\", sweepGracePeriodMs: 0 },\n\t\t\t\t\t{ time: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 20, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Skip to SweepReady (via updateTracking) - sweepGracePeriodMs 0 (no Tombstone phase)\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\", sweepGracePeriodMs: 0 },\n\t\t\t\t\t{ time: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 20, updateWith: 20, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Call update, but triggered via timers\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\" },\n\t\t\t\t\t{ time: 3, updateWith: 2, state: \"Active\" },\n\t\t\t\t\t{ time: 5, updateWith: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 12, updateWith: 9, state: \"Inactive\" }, // Timer will have fired even though server time hasn't passed threshold\n\t\t\t\t\t{ time: 17, updateWith: 15, state: \"Inactive\" }, // No-op, timer already fired\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"currentReferenceTimestampMs jumps ahead\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 0, state: \"Active\" },\n\t\t\t\t\t{ time: 5, state: \"Active\" },\n\t\t\t\t\t{ time: 10, state: \"Inactive\" },\n\t\t\t\t\t{ time: 11, updateWith: 20, state: \"TombstoneReady\" }, // Shouldn't be physically possible, but supported in API\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Start Inactive\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 12, state: \"Inactive\" },\n\t\t\t\t\t{ time: 15, state: \"Inactive\" },\n\t\t\t\t\t{ time: 20, state: \"TombstoneReady\" },\n\t\t\t\t\t{ time: 35, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Start TombstoneReady\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{ time: 22, state: \"TombstoneReady\" },\n\t\t\t\t\t{ time: 25, state: \"TombstoneReady\" },\n\t\t\t\t\t{ time: 35, state: \"SweepReady\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"Start SweepReady\",\n\t\t\t\tsteps: [{ time: 32, state: \"SweepReady\" }],\n\t\t\t},\n\t\t];\n\n\t\ttestCases.forEach((testCase) => {\n\t\t\tit(testCase.name, () => {\n\t\t\t\trunTestCase(testCase.steps);\n\t\t\t});\n\t\t});\n\n\t\tit(\"Non-zero unreferencedTimestampMs properly offsets\", () => {\n\t\t\ttracker = new UnreferencedStateTracker(\n\t\t\t\t10 /* unreferencedTimestampMs */,\n\t\t\t\t3 /* inactiveTimeoutMs */,\n\t\t\t\t11 /* currentReferenceTimestampMs */,\n\t\t\t\t7 /* tombstoneTimeoutMs */,\n\t\t\t\t15 /* sweepGracePeriodMs */,\n\t\t\t);\n\t\t\tassert.equal(tracker.state, UnreferencedState.Active, \"Should start as Active\");\n\t\t\tclock.tick(2);\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.Inactive,\n\t\t\t\t\"Should be Inactive 2ms later (at 13)\",\n\t\t\t);\n\t\t\ttracker.updateTracking(17);\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.TombstoneReady,\n\t\t\t\t\"Should be TombstoneReady after currentReferenceTimestampMs=17\",\n\t\t\t);\n\t\t\tclock.tick(15);\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.SweepReady,\n\t\t\t\t\"Should be SweepReady 15ms later\",\n\t\t\t);\n\t\t});\n\t\tit(\"Timers can't be crossed\", () => {\n\t\t\ttracker = new UnreferencedStateTracker(\n\t\t\t\t0 /* unreferencedTimestampMs */,\n\t\t\t\t10 /* inactiveTimeoutMs */,\n\t\t\t\t0 /* currentReferenceTimestampMs */,\n\t\t\t\t12 /* tombstoneTimeoutMs */,\n\t\t\t\t0 /* sweepGracePeriodMs */,\n\t\t\t);\n\t\t\tassert.equal(tracker.state, UnreferencedState.Active, \"Should start as Active\");\n\t\t\ttracker.updateTracking(10);\n\t\t\t// Would be 10ms left on Inactive timer, but it was just cleared. 2ms left on Sweep timer\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.Inactive,\n\t\t\t\t\"Should be Inactive after currentReferenceTimestampMs=10\",\n\t\t\t);\n\t\t\tclock.tick(2);\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.SweepReady,\n\t\t\t\t\"Should be SweepReady 2ms later\",\n\t\t\t);\n\t\t});\n\t\tit(\"Timers can tighten up over time\", () => {\n\t\t\tclock.tick(10);\n\t\t\ttracker = new UnreferencedStateTracker(\n\t\t\t\t0 /* unreferencedTimestampMs */,\n\t\t\t\t20 /* inactiveTimeoutMs */,\n\t\t\t\t5 /* currentReferenceTimestampMs */,\n\t\t\t\tundefined /* tombstoneTimeoutMs */,\n\t\t\t\t0 /* sweepGracePeriodMs */,\n\t\t\t);\n\t\t\tassert.equal(tracker.state, UnreferencedState.Active, \"Should start as Active\");\n\t\t\tconst timerClearSpy: SinonSpy = spy((tracker as any).inactiveTimer, \"clear\");\n\t\t\t// At T10 we had 15 to go based on server timestamps, so Timer is set to 25\n\t\t\tclock.tick(6); // at T16 (9 to go)\n\t\t\ttracker.updateTracking(15); // Simulate processing a more-recent Summary (reference time 15 at T16). Pulls in timer to 21 (5 to go)\n\t\t\tassert(\n\t\t\t\ttimerClearSpy.callCount > 0,\n\t\t\t\t\"Expected underlying Timer to clear and reset to support shorter timeout\",\n\t\t\t);\n\t\t\tclock.tick(5);\n\t\t\tassert.equal(tracker.state, UnreferencedState.Inactive, \"Should be Inactive at T21\");\n\t\t});\n\t\tit(\"Timers can loosen up over time\", () => {\n\t\t\ttracker = new UnreferencedStateTracker(\n\t\t\t\t0 /* unreferencedTimestampMs */,\n\t\t\t\t10 /* inactiveTimeoutMs */,\n\t\t\t\t0 /* currentReferenceTimestampMs */,\n\t\t\t\tundefined /* tombstoneTimeoutMs */,\n\t\t\t\t0 /* sweepGracePeriodMs */,\n\t\t\t);\n\t\t\tassert.equal(tracker.state, UnreferencedState.Active, \"Should start as Active\");\n\t\t\tclock.tick(5); // at T5, 5 to go\n\t\t\ttracker.updateTracking(1); // Simulate processing an older Summary (reference time 1 at T5). Pushes out timer to 14 (9 to go)\n\t\t\tclock.tick(5);\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.Active,\n\t\t\t\t\"Should still be Active since timer was pushed out\",\n\t\t\t);\n\t\t\tclock.tick(4);\n\t\t\tassert.equal(\n\t\t\t\ttracker.state,\n\t\t\t\tUnreferencedState.Inactive,\n\t\t\t\t\"Should be Inactive finally at T14\",\n\t\t\t);\n\t\t});\n\t});\n});\n"]}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { strict as assert } from "assert";
|
|
6
|
-
import { createChildLogger, mixinMonitoringContext, } from "@fluidframework/telemetry-utils";
|
|
7
6
|
import { IsoBuffer } from "@fluid-internal/client-utils";
|
|
7
|
+
import { createChildLogger, mixinMonitoringContext, } from "@fluidframework/telemetry-utils";
|
|
8
8
|
import { MockRuntime, validateSummary } from "./blobManager.spec.js";
|
|
9
9
|
describe("getPendingLocalState", () => {
|
|
10
10
|
let runtime;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getPendingBlobs.spec.js","sourceRoot":"","sources":["../../src/test/getPendingBlobs.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport {\n\tMonitoringContext,\n\tcreateChildLogger,\n\tmixinMonitoringContext,\n} from \"@fluidframework/telemetry-utils\";\nimport { IsoBuffer } from \"@fluid-internal/client-utils\";\nimport { MockRuntime, validateSummary } from \"./blobManager.spec.js\";\n\ndescribe(\"getPendingLocalState\", () => {\n\tlet runtime: MockRuntime;\n\tlet mc: MonitoringContext;\n\n\tbeforeEach(() => {\n\t\tmc = mixinMonitoringContext(createChildLogger(), undefined);\n\t\truntime = new MockRuntime(mc);\n\t});\n\n\tit(\"get blobs while uploading\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.strictEqual(Object.keys(pendingBlobs).length, 1);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].acked, false);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].attached, true);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].uploadTime, undefined);\n\n\t\tconst summaryData = validateSummary(runtime);\n\t\tassert.strictEqual(summaryData.ids.length, 0);\n\t\tassert.strictEqual(summaryData.redirectTable, undefined);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tawait runtime2.connect();\n\t\tawait runtime2.processAll();\n\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 1);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 1);\n\t});\n\n\tit(\"get blobs and wait for blob attach while waiting for op\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tawait runtime.processBlobs(true);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.strictEqual(Object.keys(pendingBlobs).length, 1);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].acked, false);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].attached, true);\n\t\tassert.ok(Object.values<any>(pendingBlobs)[0].uploadTime);\n\n\t\tconst summaryData = validateSummary(runtime);\n\t\tassert.strictEqual(summaryData.ids.length, 0);\n\t\tassert.strictEqual(summaryData.redirectTable, undefined);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tawait runtime2.connect();\n\t\tawait runtime2.processAll();\n\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 1);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 1);\n\t});\n\n\tit(\"shutdown multiple blobs\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tawait runtime.processBlobs(true);\n\t\tconst blob2 = IsoBuffer.from(\"blob2\", \"utf8\");\n\t\tconst handleP2 = runtime.createBlob(blob2);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tawait assert.doesNotReject(handleP2);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.strictEqual(Object.keys(pendingBlobs).length, 2);\n\n\t\tconst summaryData = validateSummary(runtime);\n\t\tassert.strictEqual(summaryData.ids.length, 0);\n\t\tassert.strictEqual(summaryData.redirectTable, undefined);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tawait runtime2.connect();\n\t\tawait runtime2.processAll();\n\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 2);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 2);\n\t});\n\n\tit(\"upload blob while getting pending state\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tawait runtime.processBlobs(true);\n\t\tconst blob2 = IsoBuffer.from(\"blob2\", \"utf8\");\n\t\tconst handleP2 = runtime.createBlob(blob2);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tconst handleP3 = runtime.createBlob(IsoBuffer.from(\"blob3\", \"utf8\"));\n\t\tawait runtime.processBlobs(true);\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tawait assert.doesNotReject(handleP2);\n\t\tawait assert.doesNotReject(handleP3);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.strictEqual(Object.keys(pendingBlobs).length, 3);\n\n\t\tconst summaryData = validateSummary(runtime);\n\t\tassert.strictEqual(summaryData.ids.length, 0);\n\t\tassert.strictEqual(summaryData.redirectTable, undefined);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tawait runtime2.connect();\n\t\tawait runtime2.processAll();\n\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 3);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 3);\n\t});\n\n\tit(\"retries blob after being rejected if it was stashed\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.strictEqual(Object.keys(pendingBlobs).length, 1);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].acked, false);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].attached, true);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].uploadTime, undefined);\n\n\t\tconst summaryData = validateSummary(runtime);\n\t\tassert.strictEqual(summaryData.ids.length, 0);\n\t\tassert.strictEqual(summaryData.redirectTable, undefined);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tawait runtime2.connect(0, true);\n\t\tawait runtime2.processAll();\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 1);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 1);\n\t});\n\n\tit(\"does not restart upload after applying stashed ops if not expired\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tawait runtime.processBlobs(true);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.ok(pendingBlobs[Object.keys(pendingBlobs)[0]].storageId);\n\t\tconst summaryData = validateSummary(runtime);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tassert.strictEqual(runtime2.unprocessedBlobs.size, 0);\n\t\tawait runtime2.connect();\n\t\tawait runtime2.processAll();\n\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 1);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 1);\n\t});\n\n\tit(\"does restart upload after applying stashed ops if expired\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\truntime.attachedStorage.minTTL = 0.001;\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tawait runtime.processBlobs(true);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.ok(pendingBlobs[Object.keys(pendingBlobs)[0]].storageId);\n\t\tconst summaryData = validateSummary(runtime);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tawait runtime2.connect();\n\t\tawait runtime2.processAll();\n\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 1);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 1);\n\t});\n});\n"]}
|
|
1
|
+
{"version":3,"file":"getPendingBlobs.spec.js","sourceRoot":"","sources":["../../src/test/getPendingBlobs.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"assert\";\nimport { IsoBuffer } from \"@fluid-internal/client-utils\";\nimport {\n\tMonitoringContext,\n\tcreateChildLogger,\n\tmixinMonitoringContext,\n} from \"@fluidframework/telemetry-utils\";\nimport { MockRuntime, validateSummary } from \"./blobManager.spec.js\";\n\ndescribe(\"getPendingLocalState\", () => {\n\tlet runtime: MockRuntime;\n\tlet mc: MonitoringContext;\n\n\tbeforeEach(() => {\n\t\tmc = mixinMonitoringContext(createChildLogger(), undefined);\n\t\truntime = new MockRuntime(mc);\n\t});\n\n\tit(\"get blobs while uploading\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.strictEqual(Object.keys(pendingBlobs).length, 1);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].acked, false);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].attached, true);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].uploadTime, undefined);\n\n\t\tconst summaryData = validateSummary(runtime);\n\t\tassert.strictEqual(summaryData.ids.length, 0);\n\t\tassert.strictEqual(summaryData.redirectTable, undefined);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tawait runtime2.connect();\n\t\tawait runtime2.processAll();\n\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 1);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 1);\n\t});\n\n\tit(\"get blobs and wait for blob attach while waiting for op\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tawait runtime.processBlobs(true);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.strictEqual(Object.keys(pendingBlobs).length, 1);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].acked, false);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].attached, true);\n\t\tassert.ok(Object.values<any>(pendingBlobs)[0].uploadTime);\n\n\t\tconst summaryData = validateSummary(runtime);\n\t\tassert.strictEqual(summaryData.ids.length, 0);\n\t\tassert.strictEqual(summaryData.redirectTable, undefined);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tawait runtime2.connect();\n\t\tawait runtime2.processAll();\n\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 1);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 1);\n\t});\n\n\tit(\"shutdown multiple blobs\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tawait runtime.processBlobs(true);\n\t\tconst blob2 = IsoBuffer.from(\"blob2\", \"utf8\");\n\t\tconst handleP2 = runtime.createBlob(blob2);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tawait assert.doesNotReject(handleP2);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.strictEqual(Object.keys(pendingBlobs).length, 2);\n\n\t\tconst summaryData = validateSummary(runtime);\n\t\tassert.strictEqual(summaryData.ids.length, 0);\n\t\tassert.strictEqual(summaryData.redirectTable, undefined);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tawait runtime2.connect();\n\t\tawait runtime2.processAll();\n\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 2);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 2);\n\t});\n\n\tit(\"upload blob while getting pending state\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tawait runtime.processBlobs(true);\n\t\tconst blob2 = IsoBuffer.from(\"blob2\", \"utf8\");\n\t\tconst handleP2 = runtime.createBlob(blob2);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tconst handleP3 = runtime.createBlob(IsoBuffer.from(\"blob3\", \"utf8\"));\n\t\tawait runtime.processBlobs(true);\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tawait assert.doesNotReject(handleP2);\n\t\tawait assert.doesNotReject(handleP3);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.strictEqual(Object.keys(pendingBlobs).length, 3);\n\n\t\tconst summaryData = validateSummary(runtime);\n\t\tassert.strictEqual(summaryData.ids.length, 0);\n\t\tassert.strictEqual(summaryData.redirectTable, undefined);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tawait runtime2.connect();\n\t\tawait runtime2.processAll();\n\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 3);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 3);\n\t});\n\n\tit(\"retries blob after being rejected if it was stashed\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.strictEqual(Object.keys(pendingBlobs).length, 1);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].acked, false);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].attached, true);\n\t\tassert.strictEqual(Object.values<any>(pendingBlobs)[0].uploadTime, undefined);\n\n\t\tconst summaryData = validateSummary(runtime);\n\t\tassert.strictEqual(summaryData.ids.length, 0);\n\t\tassert.strictEqual(summaryData.redirectTable, undefined);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tawait runtime2.connect(0, true);\n\t\tawait runtime2.processAll();\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 1);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 1);\n\t});\n\n\tit(\"does not restart upload after applying stashed ops if not expired\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tawait runtime.processBlobs(true);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.ok(pendingBlobs[Object.keys(pendingBlobs)[0]].storageId);\n\t\tconst summaryData = validateSummary(runtime);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tassert.strictEqual(runtime2.unprocessedBlobs.size, 0);\n\t\tawait runtime2.connect();\n\t\tawait runtime2.processAll();\n\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 1);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 1);\n\t});\n\n\tit(\"does restart upload after applying stashed ops if expired\", async () => {\n\t\tawait runtime.attach();\n\t\tawait runtime.connect();\n\t\truntime.attachedStorage.minTTL = 0.001;\n\t\tconst blob = IsoBuffer.from(\"blob\", \"utf8\");\n\t\tconst handleP = runtime.createBlob(blob);\n\t\tawait runtime.processBlobs(true);\n\t\tconst pendingStateP = runtime.getPendingLocalState();\n\t\tawait runtime.processHandles();\n\t\tawait assert.doesNotReject(handleP);\n\t\tconst pendingState = await pendingStateP;\n\t\tconst pendingBlobs = pendingState[1] ?? {};\n\t\tassert.ok(pendingBlobs[Object.keys(pendingBlobs)[0]].storageId);\n\t\tconst summaryData = validateSummary(runtime);\n\n\t\tconst runtime2 = new MockRuntime(mc, summaryData, false, pendingState);\n\t\tawait runtime2.attach();\n\t\tawait runtime2.connect();\n\t\tawait runtime2.processAll();\n\n\t\tconst summaryData2 = validateSummary(runtime2);\n\t\tassert.strictEqual(summaryData2.ids.length, 1);\n\t\tassert.strictEqual(summaryData2.redirectTable.size, 1);\n\t});\n});\n"]}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import assert from "assert";
|
|
6
|
-
import { MockDeltaManager, MockQuorumClients } from "@fluidframework/test-runtime-utils";
|
|
7
6
|
import { MockLogger } from "@fluidframework/telemetry-utils";
|
|
7
|
+
import { MockDeltaManager, MockQuorumClients } from "@fluidframework/test-runtime-utils";
|
|
8
8
|
import { ContainerRuntime, getDeviceSpec } from "../containerRuntime.js";
|
|
9
9
|
function setNavigator(navigator) {
|
|
10
10
|
global.navigator = navigator;
|