@fluidframework/container-runtime 2.0.0-rc.2.0.2 → 2.0.0-rc.3.0.0
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/CHANGELOG.md +23 -0
- package/api-report/container-runtime.api.md +471 -52
- package/dist/batchTracker.d.ts +1 -1
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +4 -4
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +33 -30
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +82 -107
- package/dist/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +27 -22
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +155 -165
- package/dist/channelCollection.js.map +1 -1
- package/dist/connectionTelemetry.d.ts +3 -3
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +17 -17
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js +2 -2
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +42 -39
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +425 -292
- 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 +8 -8
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +58 -19
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +169 -114
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts +1 -0
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +12 -11
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts +5 -1
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +4 -4
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/deltaScheduler.d.ts +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +6 -6
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/error.d.ts +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +4 -4
- package/dist/error.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +3 -2
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +23 -23
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +2 -2
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +4 -5
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +4 -5
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +5 -1
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +21 -12
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +2 -2
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +11 -11
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +2 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +11 -9
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +6 -6
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +1 -1
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +2 -1
- package/dist/gc/index.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +91 -0
- package/dist/messageTypes.d.ts +11 -5
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js +4 -0
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +2 -20
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +3 -3
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +3 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +5 -6
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +15 -4
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +62 -63
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +2 -1
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +14 -16
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +12 -4
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +63 -53
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +2 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +30 -29
- 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 +18 -18
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/public.d.ts +12 -0
- package/dist/scheduleManager.d.ts +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +28 -24
- package/dist/scheduleManager.js.map +1 -1
- package/dist/storageServiceWithAttachBlobs.d.ts +2 -2
- package/dist/storageServiceWithAttachBlobs.d.ts.map +1 -1
- package/dist/storageServiceWithAttachBlobs.js +2 -2
- package/dist/storageServiceWithAttachBlobs.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +209 -0
- package/dist/summary/documentSchema.d.ts.map +1 -0
- package/dist/summary/documentSchema.js +390 -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 +12 -7
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js +3 -3
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +3 -3
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +16 -16
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +3 -2
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +13 -13
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +2 -2
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.d.ts +1 -1
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summarizerHeuristics.js +2 -2
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +3 -2
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +28 -28
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js +3 -3
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +2 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +14 -14
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +5 -3
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +2 -2
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +7 -7
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +6 -17
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js +8 -8
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +4 -3
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +17 -17
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +1 -1
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +15 -14
- package/dist/summary/summaryManager.js.map +1 -1
- package/internal.d.ts +11 -0
- package/legacy.d.ts +11 -0
- package/lib/batchTracker.d.ts +1 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -2
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +33 -30
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +48 -73
- package/lib/blobManager.js.map +1 -1
- package/lib/channelCollection.d.ts +27 -22
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +96 -106
- package/lib/channelCollection.js.map +1 -1
- package/lib/connectionTelemetry.d.ts +3 -3
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +3 -3
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js +1 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +42 -39
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +276 -141
- 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 +3 -3
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +58 -19
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +107 -52
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts +1 -0
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +3 -2
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts +5 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js +1 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/deltaManagerSummarizerProxy.d.ts +1 -1
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/lib/deltaManagerSummarizerProxy.js.map +1 -1
- package/lib/deltaScheduler.d.ts +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +1 -1
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/error.d.ts +1 -1
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js +2 -2
- package/lib/error.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +3 -2
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +8 -8
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts +2 -2
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +4 -5
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +4 -5
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +5 -1
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +10 -2
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts +2 -2
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +2 -2
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +2 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +4 -2
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.js +2 -2
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/lib/gc/index.d.ts +1 -1
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +1 -1
- package/lib/gc/index.js.map +1 -1
- package/lib/index.d.ts +5 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +5 -2
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +91 -0
- package/lib/messageTypes.d.ts +11 -5
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js +4 -0
- package/lib/messageTypes.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +2 -20
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +3 -3
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js +2 -2
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +2 -3
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts +15 -4
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +61 -62
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +2 -1
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +9 -12
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +12 -4
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +47 -38
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +2 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +19 -18
- 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 +2 -2
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/public.d.ts +12 -0
- package/lib/scheduleManager.d.ts +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +7 -3
- package/lib/scheduleManager.js.map +1 -1
- package/lib/storageServiceWithAttachBlobs.d.ts +2 -2
- package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -1
- package/lib/storageServiceWithAttachBlobs.js +1 -1
- package/lib/storageServiceWithAttachBlobs.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +209 -0
- package/lib/summary/documentSchema.d.ts.map +1 -0
- package/lib/summary/documentSchema.js +386 -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 +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +3 -3
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +3 -3
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +3 -2
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +3 -3
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts +2 -2
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.d.ts +1 -1
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summary/summarizerHeuristics.js +1 -1
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +3 -2
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +5 -5
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +2 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +3 -3
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +5 -3
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +2 -2
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +1 -1
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +6 -17
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js +3 -3
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +4 -3
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +4 -4
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +1 -1
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +9 -8
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +57 -65
- package/src/batchTracker.ts +4 -3
- package/src/blobManager.ts +100 -77
- package/src/channelCollection.ts +180 -165
- package/src/connectionTelemetry.ts +12 -12
- package/src/containerHandleContext.ts +3 -2
- package/src/containerRuntime.ts +481 -277
- package/src/dataStore.ts +9 -4
- package/src/dataStoreContext.ts +195 -93
- package/src/dataStoreContexts.ts +5 -2
- package/src/dataStoreRegistry.ts +3 -2
- package/src/deltaManagerSummarizerProxy.ts +1 -1
- package/src/deltaScheduler.ts +2 -1
- package/src/error.ts +2 -2
- package/src/gc/garbageCollection.ts +21 -20
- package/src/gc/gcConfigs.ts +15 -18
- package/src/gc/gcDefinitions.ts +6 -8
- package/src/gc/gcHelpers.ts +22 -5
- package/src/gc/gcSummaryStateTracker.ts +7 -5
- package/src/gc/gcTelemetry.ts +13 -7
- package/src/gc/gcUnreferencedStateTracker.ts +3 -2
- package/src/gc/index.ts +1 -0
- package/src/index.ts +22 -1
- package/src/messageTypes.ts +20 -6
- package/src/opLifecycle/README.md +89 -0
- package/src/opLifecycle/batchManager.ts +1 -0
- package/src/opLifecycle/definitions.ts +3 -21
- package/src/opLifecycle/index.ts +3 -9
- package/src/opLifecycle/opCompressor.ts +6 -5
- package/src/opLifecycle/opDecompressor.ts +90 -100
- package/src/opLifecycle/opGroupingManager.ts +12 -14
- package/src/opLifecycle/opSplitter.ts +76 -48
- package/src/opLifecycle/outbox.ts +30 -38
- package/src/opLifecycle/remoteMessageProcessor.ts +43 -55
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +6 -6
- package/src/scheduleManager.ts +10 -8
- package/src/storageServiceWithAttachBlobs.ts +2 -2
- package/src/summary/documentSchema.ts +631 -0
- package/src/summary/index.ts +10 -1
- package/src/summary/orderedClientElection.ts +7 -7
- package/src/summary/runWhileConnectedCoordinator.ts +3 -2
- package/src/summary/runningSummarizer.ts +22 -20
- package/src/summary/summarizer.ts +17 -15
- package/src/summary/summarizerClientElection.ts +3 -2
- package/src/summary/summarizerHeuristics.ts +4 -2
- package/src/summary/summarizerNode/summarizerNode.ts +20 -18
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +3 -2
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +16 -8
- package/src/summary/summarizerTypes.ts +7 -3
- package/src/summary/summaryCollection.ts +3 -3
- package/src/summary/summaryFormat.ts +14 -26
- package/src/summary/summaryGenerator.ts +12 -15
- package/src/summary/summaryManager.ts +16 -13
- package/api-extractor-cjs.json +0 -8
- package/dist/container-runtime-alpha.d.ts +0 -1753
- package/dist/container-runtime-beta.d.ts +0 -268
- package/dist/container-runtime-public.d.ts +0 -268
- package/dist/container-runtime-untrimmed.d.ts +0 -1893
- package/lib/container-runtime-alpha.d.ts +0 -1753
- package/lib/container-runtime-beta.d.ts +0 -268
- package/lib/container-runtime-public.d.ts +0 -268
- package/lib/container-runtime-untrimmed.d.ts +0 -1893
- package/lib/test/batchTracker.spec.js +0 -88
- package/lib/test/batchTracker.spec.js.map +0 -1
- package/lib/test/blobManager.spec.js +0 -835
- package/lib/test/blobManager.spec.js.map +0 -1
- package/lib/test/channelCollection.spec.js +0 -141
- package/lib/test/channelCollection.spec.js.map +0 -1
- package/lib/test/containerRuntime.spec.js +0 -1748
- package/lib/test/containerRuntime.spec.js.map +0 -1
- package/lib/test/dataStoreContext.spec.js +0 -801
- package/lib/test/dataStoreContext.spec.js.map +0 -1
- package/lib/test/dataStoreCreation.spec.js +0 -312
- package/lib/test/dataStoreCreation.spec.js.map +0 -1
- package/lib/test/dataStoreRegistry.spec.js +0 -26
- package/lib/test/dataStoreRegistry.spec.js.map +0 -1
- package/lib/test/fuzz/fuzzUtils.js +0 -66
- package/lib/test/fuzz/fuzzUtils.js.map +0 -1
- package/lib/test/fuzz/summarizer.fuzz.spec.js +0 -31
- package/lib/test/fuzz/summarizer.fuzz.spec.js.map +0 -1
- package/lib/test/fuzz/summarizerFuzzMocks.js +0 -162
- package/lib/test/fuzz/summarizerFuzzMocks.js.map +0 -1
- package/lib/test/fuzz/summarizerFuzzSuite.js +0 -106
- package/lib/test/fuzz/summarizerFuzzSuite.js.map +0 -1
- package/lib/test/gc/garbageCollection.spec.js +0 -1465
- package/lib/test/gc/garbageCollection.spec.js.map +0 -1
- package/lib/test/gc/gcConfigs.spec.js +0 -690
- package/lib/test/gc/gcConfigs.spec.js.map +0 -1
- package/lib/test/gc/gcHelpers.spec.js +0 -110
- package/lib/test/gc/gcHelpers.spec.js.map +0 -1
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js +0 -68
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js.map +0 -1
- package/lib/test/gc/gcStats.spec.js +0 -391
- package/lib/test/gc/gcStats.spec.js.map +0 -1
- package/lib/test/gc/gcSummaryStateTracker.spec.js +0 -228
- package/lib/test/gc/gcSummaryStateTracker.spec.js.map +0 -1
- package/lib/test/gc/gcTelemetry.spec.js +0 -530
- package/lib/test/gc/gcTelemetry.spec.js.map +0 -1
- package/lib/test/gc/gcUnitTestHelpers.js +0 -29
- package/lib/test/gc/gcUnitTestHelpers.js.map +0 -1
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js +0 -192
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js.map +0 -1
- package/lib/test/getPendingBlobs.spec.js +0 -193
- package/lib/test/getPendingBlobs.spec.js.map +0 -1
- package/lib/test/hardwareStats.spec.js +0 -93
- package/lib/test/hardwareStats.spec.js.map +0 -1
- package/lib/test/index.js +0 -6
- package/lib/test/index.js.map +0 -1
- package/lib/test/opLifecycle/OpGroupingManager.spec.js +0 -225
- package/lib/test/opLifecycle/OpGroupingManager.spec.js.map +0 -1
- package/lib/test/opLifecycle/batchManager.spec.js +0 -189
- package/lib/test/opLifecycle/batchManager.spec.js.map +0 -1
- package/lib/test/opLifecycle/opCompressor.spec.js +0 -74
- package/lib/test/opLifecycle/opCompressor.spec.js.map +0 -1
- package/lib/test/opLifecycle/opDecompressor.spec.js +0 -218
- package/lib/test/opLifecycle/opDecompressor.spec.js.map +0 -1
- package/lib/test/opLifecycle/opSplitter.spec.js +0 -272
- package/lib/test/opLifecycle/opSplitter.spec.js.map +0 -1
- package/lib/test/opLifecycle/outbox.spec.js +0 -675
- package/lib/test/opLifecycle/outbox.spec.js.map +0 -1
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js +0 -196
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js.map +0 -1
- package/lib/test/pendingStateManager.spec.js +0 -329
- package/lib/test/pendingStateManager.spec.js.map +0 -1
- package/lib/test/scheduleManager.spec.js +0 -270
- package/lib/test/scheduleManager.spec.js.map +0 -1
- package/lib/test/summarizerNode.spec.js +0 -326
- package/lib/test/summarizerNode.spec.js.map +0 -1
- package/lib/test/summarizerNodeWithGc.spec.js +0 -318
- package/lib/test/summarizerNodeWithGc.spec.js.map +0 -1
- package/lib/test/summary/orderedClientElection.spec.js +0 -535
- package/lib/test/summary/orderedClientElection.spec.js.map +0 -1
- package/lib/test/summary/runningSummarizer.spec.js +0 -1349
- package/lib/test/summary/runningSummarizer.spec.js.map +0 -1
- package/lib/test/summary/summarizer.spec.js +0 -29
- package/lib/test/summary/summarizer.spec.js.map +0 -1
- package/lib/test/summary/summarizerClientElection.spec.js +0 -436
- package/lib/test/summary/summarizerClientElection.spec.js.map +0 -1
- package/lib/test/summary/summarizerHeuristics.spec.js +0 -289
- package/lib/test/summary/summarizerHeuristics.spec.js.map +0 -1
- package/lib/test/summary/summaryCollection.spec.js +0 -200
- package/lib/test/summary/summaryCollection.spec.js.map +0 -1
- package/lib/test/summary/summaryManager.spec.js +0 -430
- package/lib/test/summary/summaryManager.spec.js.map +0 -1
- package/lib/test/summary/testQuorumClients.js +0 -34
- package/lib/test/summary/testQuorumClients.js.map +0 -1
- package/lib/test/throttler.spec.js +0 -175
- package/lib/test/throttler.spec.js.map +0 -1
- package/lib/test/types/validateContainerRuntimePrevious.generated.js +0 -180
- package/lib/test/types/validateContainerRuntimePrevious.generated.js.map +0 -1
- /package/{dist → lib}/tsdoc-metadata.json +0 -0
|
@@ -1,530 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
import { strict as assert } from "assert";
|
|
6
|
-
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
|
-
import { BlobManager } from "../../blobManager.js";
|
|
11
|
-
describe("GC Telemetry Tracker", () => {
|
|
12
|
-
const defaultSnapshotCacheExpiryMs = 5 * 24 * 60 * 60 * 1000;
|
|
13
|
-
const tombstoneTimeoutMs = defaultSessionExpiryDurationMs + defaultSnapshotCacheExpiryMs + oneDayMs;
|
|
14
|
-
const inactiveTimeoutMs = 500;
|
|
15
|
-
// Nodes in the reference graph.
|
|
16
|
-
const nodes = ["/node1", "/node2", "/node3", "/node4"];
|
|
17
|
-
const testPkgPath = ["testPkg"];
|
|
18
|
-
// The package data is tagged in the telemetry event.
|
|
19
|
-
const eventPkg = { value: testPkgPath.join("/"), tag: TelemetryDataTag.CodeArtifact };
|
|
20
|
-
let mockLogger;
|
|
21
|
-
let mc;
|
|
22
|
-
let clock;
|
|
23
|
-
let sweepGracePeriodMs = 1000; // Default case for these tests
|
|
24
|
-
let unreferencedNodesState = new Map();
|
|
25
|
-
let telemetryTracker;
|
|
26
|
-
function createTelemetryTracker(enableSweep, isSummarizerClient = true) {
|
|
27
|
-
// Node types are as follows based on the path:
|
|
28
|
-
// Path starting with "/_blobs" - blob.
|
|
29
|
-
// Path with one part such as "/id1" - data stores.
|
|
30
|
-
// Path with two parts such as "/id1/id2" - sub data stores.
|
|
31
|
-
// Everything else - other.
|
|
32
|
-
const getNodeType = (nodePath) => {
|
|
33
|
-
if (nodePath.split("/")[1] === BlobManager.basePath) {
|
|
34
|
-
return GCNodeType.Blob;
|
|
35
|
-
}
|
|
36
|
-
if (nodePath.split("/").length === 2) {
|
|
37
|
-
return GCNodeType.DataStore;
|
|
38
|
-
}
|
|
39
|
-
if (nodePath.split("/").length === 3) {
|
|
40
|
-
return GCNodeType.SubDataStore;
|
|
41
|
-
}
|
|
42
|
-
return GCNodeType.Other;
|
|
43
|
-
};
|
|
44
|
-
const configs = {
|
|
45
|
-
gcEnabled: true,
|
|
46
|
-
sweepEnabled: false,
|
|
47
|
-
shouldRunGC: true,
|
|
48
|
-
shouldRunSweep: "NO",
|
|
49
|
-
runFullGC: false,
|
|
50
|
-
testMode: false,
|
|
51
|
-
tombstoneMode: false,
|
|
52
|
-
inactiveTimeoutMs,
|
|
53
|
-
sessionExpiryTimeoutMs: defaultSessionExpiryDurationMs,
|
|
54
|
-
tombstoneTimeoutMs: enableSweep ? tombstoneTimeoutMs : undefined,
|
|
55
|
-
sweepGracePeriodMs,
|
|
56
|
-
throwOnTombstoneLoad: false,
|
|
57
|
-
throwOnTombstoneUsage: false,
|
|
58
|
-
throwOnInactiveLoad: false,
|
|
59
|
-
persistedGcFeatureMatrix: undefined,
|
|
60
|
-
gcVersionInBaseSnapshot: stableGCVersion,
|
|
61
|
-
gcVersionInEffect: stableGCVersion,
|
|
62
|
-
};
|
|
63
|
-
const tracker = new GCTelemetryTracker(mc, configs, isSummarizerClient, { createContainerRuntimeVersion: pkgVersion }, getNodeType, (nodeId) => unreferencedNodesState.get(nodeId), async (nodeId) => testPkgPath);
|
|
64
|
-
return tracker;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* For each node in nodeIds, add an entry in `unreferencedNodesState` indicating that the node was
|
|
68
|
-
* just unreferenced.
|
|
69
|
-
*/
|
|
70
|
-
function markNodesUnreferenced(nodeIds) {
|
|
71
|
-
nodeIds.forEach((nodeId) => {
|
|
72
|
-
unreferencedNodesState.set(nodeId, new UnreferencedStateTracker(Date.now(), inactiveTimeoutMs, Date.now(), tombstoneTimeoutMs, sweepGracePeriodMs));
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
// Mock node loaded and changed activity for the given nodes.
|
|
76
|
-
function mockNodeChanges(nodeIds) {
|
|
77
|
-
nodeIds.forEach((id) => {
|
|
78
|
-
telemetryTracker.nodeUsed({
|
|
79
|
-
id,
|
|
80
|
-
usageType: "Loaded",
|
|
81
|
-
currentReferenceTimestampMs: Date.now(),
|
|
82
|
-
packagePath: testPkgPath,
|
|
83
|
-
completedGCRuns: 0,
|
|
84
|
-
isTombstoned: false,
|
|
85
|
-
});
|
|
86
|
-
telemetryTracker.nodeUsed({
|
|
87
|
-
id,
|
|
88
|
-
usageType: "Changed",
|
|
89
|
-
currentReferenceTimestampMs: Date.now(),
|
|
90
|
-
packagePath: testPkgPath,
|
|
91
|
-
completedGCRuns: 0,
|
|
92
|
-
isTombstoned: false,
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
// Mock node revived activity for the given nodes.
|
|
97
|
-
function reviveNode(fromId, toId, isTombstoned = false) {
|
|
98
|
-
telemetryTracker.nodeUsed({
|
|
99
|
-
id: toId,
|
|
100
|
-
usageType: "Revived",
|
|
101
|
-
currentReferenceTimestampMs: Date.now(),
|
|
102
|
-
packagePath: testPkgPath,
|
|
103
|
-
completedGCRuns: 0,
|
|
104
|
-
isTombstoned,
|
|
105
|
-
fromId,
|
|
106
|
-
});
|
|
107
|
-
unreferencedNodesState.delete(toId);
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* For summarizer clients, inactive / sweep ready events are not logged when on node usage. They are logged when GC
|
|
111
|
-
* runs next time. This emulates that by calling the functions in the telemetry tracker that are called when GC runs.
|
|
112
|
-
*/
|
|
113
|
-
async function simulateGCToTriggerEvents(isSummarizerClient) {
|
|
114
|
-
if (!isSummarizerClient) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
await telemetryTracker.logPendingEvents(mc.logger);
|
|
118
|
-
}
|
|
119
|
-
before(() => {
|
|
120
|
-
clock = useFakeTimers();
|
|
121
|
-
});
|
|
122
|
-
beforeEach(() => {
|
|
123
|
-
mockLogger = new MockLogger();
|
|
124
|
-
mc = mixinMonitoringContext(createChildLogger({ logger: mockLogger, namespace: "GarbageCollector" }));
|
|
125
|
-
unreferencedNodesState = new Map();
|
|
126
|
-
});
|
|
127
|
-
afterEach(() => {
|
|
128
|
-
clock.reset();
|
|
129
|
-
mockLogger.clear();
|
|
130
|
-
sweepGracePeriodMs = 1000; // Default case for these tests
|
|
131
|
-
});
|
|
132
|
-
after(() => {
|
|
133
|
-
clock.restore();
|
|
134
|
-
});
|
|
135
|
-
// Tests that are run once for summarizer client and once for interactive client.
|
|
136
|
-
const clientTypeTests = (isSummarizerClient) => {
|
|
137
|
-
/**
|
|
138
|
-
* Asserts that the events are as expected based on whether its a summarizer client or not. In non-summarizer
|
|
139
|
-
* clients, only "InactiveObject_Loaded", "TombstoneReadyObject_Loaded" and "SweepReadyObject_Loaded" events are logged.
|
|
140
|
-
* "_Changed" and "_Revived" events are not logged.
|
|
141
|
-
*/
|
|
142
|
-
function assertMatchEvents(events, message) {
|
|
143
|
-
const expectedEvents = [];
|
|
144
|
-
const unexpectedEvents = [];
|
|
145
|
-
// For non-summarizer clients, events that are not "Loaded" are unexpected. Everything else is expected.
|
|
146
|
-
for (const event of events) {
|
|
147
|
-
const eventName = event.eventName;
|
|
148
|
-
if (!isSummarizerClient && !eventName.includes("Loaded")) {
|
|
149
|
-
unexpectedEvents.push(event);
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
expectedEvents.push(event);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
// Note that mock logger clears all events after one of the `match` functions is called. Since we call match
|
|
156
|
-
// functions twice, cache the events and repopulate the mock logger with if after the first match call.
|
|
157
|
-
const cachedEvents = Array.from(mockLogger.events);
|
|
158
|
-
mockLogger.assertMatch(expectedEvents, message, true /* inlineDetailsProp */);
|
|
159
|
-
mockLogger.events = cachedEvents;
|
|
160
|
-
mockLogger.assertMatchNone(unexpectedEvents, message, true /* inlineDetailsProp */);
|
|
161
|
-
}
|
|
162
|
-
it("generates inactive, tombstone ready, and sweep ready events when nodes are used after time out", async () => {
|
|
163
|
-
telemetryTracker = createTelemetryTracker(true /* enable Sweep */, isSummarizerClient);
|
|
164
|
-
// Mark nodes 2 and 3 as unreferenced.
|
|
165
|
-
markNodesUnreferenced([nodes[2], nodes[3]]);
|
|
166
|
-
// Advance the clock to trigger inactive timeout and validate that inactive events are as expected.
|
|
167
|
-
clock.tick(inactiveTimeoutMs + 1);
|
|
168
|
-
mockNodeChanges(nodes);
|
|
169
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
170
|
-
assertMatchEvents([
|
|
171
|
-
{
|
|
172
|
-
eventName: "GarbageCollector:InactiveObject_Loaded",
|
|
173
|
-
timeout: inactiveTimeoutMs,
|
|
174
|
-
...tagCodeArtifacts({ id: nodes[2] }),
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
eventName: "GarbageCollector:InactiveObject_Changed",
|
|
178
|
-
timeout: inactiveTimeoutMs,
|
|
179
|
-
...tagCodeArtifacts({ id: nodes[2] }),
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
eventName: "GarbageCollector:InactiveObject_Loaded",
|
|
183
|
-
timeout: inactiveTimeoutMs,
|
|
184
|
-
...tagCodeArtifacts({ id: nodes[3] }),
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
eventName: "GarbageCollector:InactiveObject_Changed",
|
|
188
|
-
timeout: inactiveTimeoutMs,
|
|
189
|
-
...tagCodeArtifacts({ id: nodes[3] }),
|
|
190
|
-
},
|
|
191
|
-
], "inactive events not as expected");
|
|
192
|
-
// Advance the clock to trigger tombstone timeout and validate that TombstoneReady events are as expected.
|
|
193
|
-
clock.tick(tombstoneTimeoutMs - inactiveTimeoutMs);
|
|
194
|
-
mockNodeChanges(nodes);
|
|
195
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
196
|
-
assertMatchEvents([
|
|
197
|
-
{
|
|
198
|
-
eventName: "GarbageCollector:TombstoneReadyObject_Loaded",
|
|
199
|
-
timeout: tombstoneTimeoutMs,
|
|
200
|
-
...tagCodeArtifacts({ id: nodes[2] }),
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
eventName: "GarbageCollector:TombstoneReadyObject_Changed",
|
|
204
|
-
timeout: tombstoneTimeoutMs,
|
|
205
|
-
...tagCodeArtifacts({ id: nodes[2] }),
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
eventName: "GarbageCollector:TombstoneReadyObject_Loaded",
|
|
209
|
-
timeout: tombstoneTimeoutMs,
|
|
210
|
-
...tagCodeArtifacts({ id: nodes[3] }),
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
eventName: "GarbageCollector:TombstoneReadyObject_Changed",
|
|
214
|
-
timeout: tombstoneTimeoutMs,
|
|
215
|
-
...tagCodeArtifacts({ id: nodes[3] }),
|
|
216
|
-
},
|
|
217
|
-
], "tombstone ready events not as expected");
|
|
218
|
-
// Advance the clock by the delay and validate that SweepReady events are as expected.
|
|
219
|
-
clock.tick(sweepGracePeriodMs);
|
|
220
|
-
mockNodeChanges(nodes);
|
|
221
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
222
|
-
assertMatchEvents([
|
|
223
|
-
{
|
|
224
|
-
eventName: "GarbageCollector:SweepReadyObject_Loaded",
|
|
225
|
-
timeout: tombstoneTimeoutMs + sweepGracePeriodMs,
|
|
226
|
-
...tagCodeArtifacts({ id: nodes[2] }),
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
eventName: "GarbageCollector:SweepReadyObject_Changed",
|
|
230
|
-
timeout: tombstoneTimeoutMs + sweepGracePeriodMs,
|
|
231
|
-
...tagCodeArtifacts({ id: nodes[2] }),
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
eventName: "GarbageCollector:SweepReadyObject_Loaded",
|
|
235
|
-
timeout: tombstoneTimeoutMs + sweepGracePeriodMs,
|
|
236
|
-
...tagCodeArtifacts({ id: nodes[3] }),
|
|
237
|
-
},
|
|
238
|
-
{
|
|
239
|
-
eventName: "GarbageCollector:SweepReadyObject_Changed",
|
|
240
|
-
timeout: tombstoneTimeoutMs + sweepGracePeriodMs,
|
|
241
|
-
...tagCodeArtifacts({ id: nodes[3] }),
|
|
242
|
-
},
|
|
243
|
-
], "sweep ready events not as expected");
|
|
244
|
-
});
|
|
245
|
-
it("generates tombstone revived events when nodes are used after they are tombstoned", async () => {
|
|
246
|
-
telemetryTracker = createTelemetryTracker(true /* enable Sweep */, isSummarizerClient);
|
|
247
|
-
// Mark node 2 as unreferenced.
|
|
248
|
-
markNodesUnreferenced([nodes[2]]);
|
|
249
|
-
// Advance the clock to trigger tombstone timeout and validate that tombstone revived event is as expected.
|
|
250
|
-
clock.tick(tombstoneTimeoutMs + 1);
|
|
251
|
-
reviveNode(nodes[1], nodes[2], true /* isTombstoned */);
|
|
252
|
-
mockLogger.assertMatch([
|
|
253
|
-
{
|
|
254
|
-
eventName: "GarbageCollector:GC_Tombstone_DataStore_Revived",
|
|
255
|
-
pkg: eventPkg,
|
|
256
|
-
...tagCodeArtifacts({ id: nodes[2] }),
|
|
257
|
-
},
|
|
258
|
-
], "inactive events not as expected");
|
|
259
|
-
});
|
|
260
|
-
/** Tests that validate either the relevant events are logged as expected. */
|
|
261
|
-
const unreferencedPhasesEventTests = (timeout, mode, revivedEventName, changedEventName, loadedEventName, sweepGracePeriodMsOverride) => {
|
|
262
|
-
// Validates that no unexpected event has been fired.
|
|
263
|
-
function validateNoEvents() {
|
|
264
|
-
mockLogger.assertMatchNone([
|
|
265
|
-
{ eventName: revivedEventName },
|
|
266
|
-
{ eventName: changedEventName },
|
|
267
|
-
{ eventName: loadedEventName },
|
|
268
|
-
], "unexpected events logged");
|
|
269
|
-
}
|
|
270
|
-
beforeEach(() => {
|
|
271
|
-
if (sweepGracePeriodMsOverride !== undefined) {
|
|
272
|
-
sweepGracePeriodMs = sweepGracePeriodMsOverride;
|
|
273
|
-
}
|
|
274
|
-
telemetryTracker = createTelemetryTracker(mode !== "inactive" /* enableSweep */, isSummarizerClient);
|
|
275
|
-
});
|
|
276
|
-
it("doesn't generate events for referenced nodes", async () => {
|
|
277
|
-
mockNodeChanges(nodes);
|
|
278
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
279
|
-
validateNoEvents();
|
|
280
|
-
// Advance the clock to just before the timeout expires, update nodes and validate no events.
|
|
281
|
-
clock.tick(timeout - 1);
|
|
282
|
-
mockNodeChanges(nodes);
|
|
283
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
284
|
-
validateNoEvents();
|
|
285
|
-
// Advance the clock to expire the timeout, update nodes and validate no events.
|
|
286
|
-
clock.tick(1);
|
|
287
|
-
mockNodeChanges(nodes);
|
|
288
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
289
|
-
validateNoEvents();
|
|
290
|
-
});
|
|
291
|
-
it("generates events for nodes that are used after state changes", async () => {
|
|
292
|
-
// Mark nodes 1 and 2 as unreferenced.
|
|
293
|
-
markNodesUnreferenced([nodes[1], nodes[2]]);
|
|
294
|
-
// Advance the clock just before the timeout and validate no unexpected events are logged.
|
|
295
|
-
clock.tick(timeout - 1);
|
|
296
|
-
mockNodeChanges(nodes);
|
|
297
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
298
|
-
validateNoEvents();
|
|
299
|
-
// Expire the timeout, update nodes and validate that all events for node 1 and node 2 are logged.
|
|
300
|
-
clock.tick(1);
|
|
301
|
-
mockNodeChanges(nodes);
|
|
302
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
303
|
-
const expectedEvents = [];
|
|
304
|
-
expectedEvents.push({
|
|
305
|
-
eventName: loadedEventName,
|
|
306
|
-
timeout,
|
|
307
|
-
...tagCodeArtifacts({ id: nodes[1], pkg: testPkgPath.join("/") }),
|
|
308
|
-
createContainerRuntimeVersion: pkgVersion,
|
|
309
|
-
}, {
|
|
310
|
-
eventName: changedEventName,
|
|
311
|
-
timeout,
|
|
312
|
-
...tagCodeArtifacts({ id: nodes[1], pkg: testPkgPath.join("/") }),
|
|
313
|
-
createContainerRuntimeVersion: pkgVersion,
|
|
314
|
-
}, {
|
|
315
|
-
eventName: loadedEventName,
|
|
316
|
-
timeout,
|
|
317
|
-
...tagCodeArtifacts({ id: nodes[2], pkg: testPkgPath.join("/") }),
|
|
318
|
-
createContainerRuntimeVersion: pkgVersion,
|
|
319
|
-
}, {
|
|
320
|
-
eventName: changedEventName,
|
|
321
|
-
timeout,
|
|
322
|
-
...tagCodeArtifacts({ id: nodes[2], pkg: testPkgPath.join("/") }),
|
|
323
|
-
createContainerRuntimeVersion: pkgVersion,
|
|
324
|
-
});
|
|
325
|
-
assertMatchEvents(expectedEvents, "all events not as expected");
|
|
326
|
-
// Revived node 2 and validate that revived event is as expected.
|
|
327
|
-
reviveNode(nodes[0], nodes[2]);
|
|
328
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
329
|
-
assertMatchEvents([
|
|
330
|
-
{
|
|
331
|
-
eventName: revivedEventName,
|
|
332
|
-
timeout,
|
|
333
|
-
...tagCodeArtifacts({
|
|
334
|
-
id: nodes[2],
|
|
335
|
-
fromId: nodes[0],
|
|
336
|
-
pkg: testPkgPath.join("/"),
|
|
337
|
-
}),
|
|
338
|
-
},
|
|
339
|
-
], "revived event not as expected");
|
|
340
|
-
});
|
|
341
|
-
it("generates events once per node", async () => {
|
|
342
|
-
// Mark node 2 as unreferenced.
|
|
343
|
-
markNodesUnreferenced([nodes[2]]);
|
|
344
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
345
|
-
// Advance the clock just before the timeout and validate no unexpected events are logged.
|
|
346
|
-
clock.tick(timeout - 1);
|
|
347
|
-
mockNodeChanges(nodes);
|
|
348
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
349
|
-
validateNoEvents();
|
|
350
|
-
// Expire the timeout, updated nodes and validate that events are logged as expected.
|
|
351
|
-
clock.tick(1);
|
|
352
|
-
mockNodeChanges(nodes);
|
|
353
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
354
|
-
const expectedEvents = [];
|
|
355
|
-
expectedEvents.push({
|
|
356
|
-
eventName: loadedEventName,
|
|
357
|
-
timeout,
|
|
358
|
-
...tagCodeArtifacts({ id: nodes[2] }),
|
|
359
|
-
pkg: eventPkg,
|
|
360
|
-
}, {
|
|
361
|
-
eventName: changedEventName,
|
|
362
|
-
timeout,
|
|
363
|
-
...tagCodeArtifacts({ id: nodes[2] }),
|
|
364
|
-
pkg: eventPkg,
|
|
365
|
-
});
|
|
366
|
-
assertMatchEvents(expectedEvents, "all events not as expected");
|
|
367
|
-
// Update all nodes again. There shouldn't be any more events since for each node the event is only once.
|
|
368
|
-
mockNodeChanges(nodes);
|
|
369
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
370
|
-
validateNoEvents();
|
|
371
|
-
});
|
|
372
|
-
// This test is only relevant for summarizer client because it does not log changed events if the node is revived.
|
|
373
|
-
if (isSummarizerClient) {
|
|
374
|
-
it("generates only revived event in summarizer when a node is updated and revived", async () => {
|
|
375
|
-
// Mark node 2 as unreferenced.
|
|
376
|
-
markNodesUnreferenced([nodes[2]]);
|
|
377
|
-
// Advance the clock just before the timeout and validate no unexpected events are logged.
|
|
378
|
-
clock.tick(timeout - 1);
|
|
379
|
-
mockNodeChanges(nodes);
|
|
380
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
381
|
-
validateNoEvents();
|
|
382
|
-
// Expire the timeout and validate that only revived event is generated for node 2.
|
|
383
|
-
clock.tick(1);
|
|
384
|
-
mockNodeChanges([nodes[2]]);
|
|
385
|
-
reviveNode(nodes[1], nodes[2]);
|
|
386
|
-
await simulateGCToTriggerEvents(isSummarizerClient);
|
|
387
|
-
for (const event of mockLogger.events) {
|
|
388
|
-
assert.notStrictEqual(event.eventName, loadedEventName, "Unexpected loaded event logged");
|
|
389
|
-
assert.notStrictEqual(event.eventName, changedEventName, "Unexpected changed event logged");
|
|
390
|
-
}
|
|
391
|
-
assertMatchEvents([
|
|
392
|
-
{
|
|
393
|
-
eventName: revivedEventName,
|
|
394
|
-
timeout,
|
|
395
|
-
...tagCodeArtifacts({
|
|
396
|
-
id: nodes[2],
|
|
397
|
-
fromId: nodes[1],
|
|
398
|
-
pkg: testPkgPath.join("/"),
|
|
399
|
-
}),
|
|
400
|
-
},
|
|
401
|
-
], "revived event not as expected");
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
};
|
|
405
|
-
describe("Inactive events", () => {
|
|
406
|
-
unreferencedPhasesEventTests(inactiveTimeoutMs, "inactive", "GarbageCollector:InactiveObject_Revived", "GarbageCollector:InactiveObject_Changed", "GarbageCollector:InactiveObject_Loaded");
|
|
407
|
-
});
|
|
408
|
-
describe("TombstoneReady events", () => {
|
|
409
|
-
unreferencedPhasesEventTests(tombstoneTimeoutMs, "tombstone", "GarbageCollector:TombstoneReadyObject_Revived", "GarbageCollector:TombstoneReadyObject_Changed", "GarbageCollector:TombstoneReadyObject_Loaded");
|
|
410
|
-
});
|
|
411
|
-
describe("SweepReady events (with no delay)", () => {
|
|
412
|
-
unreferencedPhasesEventTests(tombstoneTimeoutMs, "sweep", // Jump straight to SweepReady given 0 delay
|
|
413
|
-
"GarbageCollector:SweepReadyObject_Revived", "GarbageCollector:SweepReadyObject_Changed", "GarbageCollector:SweepReadyObject_Loaded", 0 /* sweepGracePeriodMsOverride */);
|
|
414
|
-
});
|
|
415
|
-
describe("SweepReady events", () => {
|
|
416
|
-
unreferencedPhasesEventTests(tombstoneTimeoutMs + sweepGracePeriodMs, "sweep", "GarbageCollector:SweepReadyObject_Revived", "GarbageCollector:SweepReadyObject_Changed", "GarbageCollector:SweepReadyObject_Loaded");
|
|
417
|
-
});
|
|
418
|
-
};
|
|
419
|
-
describe("Summarizer client", () => {
|
|
420
|
-
clientTypeTests(true /* isSummarizerClient */);
|
|
421
|
-
});
|
|
422
|
-
describe("Interactive client", () => {
|
|
423
|
-
clientTypeTests(false /* isSummarizerClient */);
|
|
424
|
-
});
|
|
425
|
-
describe("gcUnknownOutboundReferences telemetry", () => {
|
|
426
|
-
const unknownReferenceEventName = "GarbageCollector:gcUnknownOutboundReferences";
|
|
427
|
-
const currentGCData = { gcNodes: {} };
|
|
428
|
-
let previousGCData;
|
|
429
|
-
let explicitReferences;
|
|
430
|
-
beforeEach(() => {
|
|
431
|
-
telemetryTracker = createTelemetryTracker(true /* enableSweep */, true /* isSummarizerClient */);
|
|
432
|
-
currentGCData.gcNodes["/"] = [nodes[0]];
|
|
433
|
-
currentGCData.gcNodes[nodes[0]] = [nodes[1]];
|
|
434
|
-
currentGCData.gcNodes[nodes[1]] = [nodes[0], nodes[2]];
|
|
435
|
-
currentGCData.gcNodes[nodes[2]] = [nodes[1], nodes[3]];
|
|
436
|
-
currentGCData.gcNodes[nodes[3]] = [nodes[0]];
|
|
437
|
-
previousGCData = cloneGCData(currentGCData);
|
|
438
|
-
explicitReferences = new Map();
|
|
439
|
-
});
|
|
440
|
-
it("does not log gcUnknownOutboundReferences when there are no new references", async () => {
|
|
441
|
-
telemetryTracker.logIfMissingExplicitReferences(currentGCData, previousGCData, explicitReferences, mc.logger);
|
|
442
|
-
mockLogger.assertMatchNone([
|
|
443
|
-
{
|
|
444
|
-
eventName: unknownReferenceEventName,
|
|
445
|
-
},
|
|
446
|
-
], "There should be no gcUnknownOutboundReferences event");
|
|
447
|
-
});
|
|
448
|
-
it("logs gcUnknownOutboundReferences when there are unknown data store references", async () => {
|
|
449
|
-
const id = nodes[0];
|
|
450
|
-
const routes = [nodes[2], nodes[3]];
|
|
451
|
-
currentGCData.gcNodes[id] = routes;
|
|
452
|
-
telemetryTracker.logIfMissingExplicitReferences(currentGCData, previousGCData, explicitReferences, mc.logger);
|
|
453
|
-
mockLogger.assertMatch([
|
|
454
|
-
{
|
|
455
|
-
eventName: unknownReferenceEventName,
|
|
456
|
-
...tagCodeArtifacts({ id, routes: JSON.stringify(routes) }),
|
|
457
|
-
},
|
|
458
|
-
], "gcUnknownOutboundReferences event not logged as expected");
|
|
459
|
-
});
|
|
460
|
-
it("logs gcUnknownOutboundReferences when there are multiple unknown data store references", async () => {
|
|
461
|
-
const id1 = nodes[0];
|
|
462
|
-
const routes1 = [nodes[2], nodes[3]];
|
|
463
|
-
const id2 = nodes[3];
|
|
464
|
-
const routes2 = [nodes[1], nodes[2]];
|
|
465
|
-
currentGCData.gcNodes[id1] = routes1;
|
|
466
|
-
currentGCData.gcNodes[id2] = routes2;
|
|
467
|
-
telemetryTracker.logIfMissingExplicitReferences(currentGCData, previousGCData, explicitReferences, mc.logger);
|
|
468
|
-
mockLogger.assertMatch([
|
|
469
|
-
{
|
|
470
|
-
eventName: unknownReferenceEventName,
|
|
471
|
-
...tagCodeArtifacts({ id: id1, routes: JSON.stringify(routes1) }),
|
|
472
|
-
},
|
|
473
|
-
{
|
|
474
|
-
eventName: unknownReferenceEventName,
|
|
475
|
-
...tagCodeArtifacts({ id: id2, routes: JSON.stringify(routes2) }),
|
|
476
|
-
},
|
|
477
|
-
], "gcUnknownOutboundReferences event not logged as expected");
|
|
478
|
-
});
|
|
479
|
-
it("logs gcUnknownOutboundReferences when there are unknown blob references", async () => {
|
|
480
|
-
const id = nodes[0];
|
|
481
|
-
// Id of type `/_blobs/id1 is treated as a blob node.
|
|
482
|
-
const routes = ["/_blobs/id1"];
|
|
483
|
-
currentGCData.gcNodes[id] = routes;
|
|
484
|
-
telemetryTracker.logIfMissingExplicitReferences(currentGCData, previousGCData, explicitReferences, mc.logger);
|
|
485
|
-
mockLogger.assertMatch([
|
|
486
|
-
{
|
|
487
|
-
eventName: unknownReferenceEventName,
|
|
488
|
-
...tagCodeArtifacts({ id, routes: JSON.stringify(routes) }),
|
|
489
|
-
},
|
|
490
|
-
], "gcUnknownOutboundReferences event not logged as expected for blob nodes");
|
|
491
|
-
});
|
|
492
|
-
it("does not log gcUnknownOutboundReferences for back-routes (ex: DDS to data store)", async () => {
|
|
493
|
-
// Id of type `/id1/id2 is treated as a sub-data store (DDS) node.
|
|
494
|
-
const id = `${nodes[1]}/dds`;
|
|
495
|
-
const routes = [nodes[1]];
|
|
496
|
-
currentGCData.gcNodes[id] = routes;
|
|
497
|
-
telemetryTracker.logIfMissingExplicitReferences(currentGCData, previousGCData, explicitReferences, mc.logger);
|
|
498
|
-
mockLogger.assertMatchNone([
|
|
499
|
-
{
|
|
500
|
-
eventName: unknownReferenceEventName,
|
|
501
|
-
},
|
|
502
|
-
], "There should be no gcUnknownOutboundReferences event when back-routes are added");
|
|
503
|
-
});
|
|
504
|
-
it("does not log gcUnknownOutboundReferences for sub-dataStore routes (ex: to DDS)", async () => {
|
|
505
|
-
const id = nodes[1];
|
|
506
|
-
// Id of type `/id1/id2 is treated as a sub-data store (DDS) node.
|
|
507
|
-
const routes = [`${nodes[1]}/dds`];
|
|
508
|
-
currentGCData.gcNodes[id] = routes;
|
|
509
|
-
telemetryTracker.logIfMissingExplicitReferences(currentGCData, previousGCData, explicitReferences, mc.logger);
|
|
510
|
-
mockLogger.assertMatchNone([
|
|
511
|
-
{
|
|
512
|
-
eventName: unknownReferenceEventName,
|
|
513
|
-
},
|
|
514
|
-
], "There should be no gcUnknownOutboundReferences event when sub-dataStore routes are added");
|
|
515
|
-
});
|
|
516
|
-
it("does not log gcUnknownOutboundReferences for other routes (ex: unknown routes)", async () => {
|
|
517
|
-
const id = nodes[1];
|
|
518
|
-
// Id of type `/id1/id2/ids31` is treated as a other node type.
|
|
519
|
-
const routes = [`${nodes[1]}/ids2/ids3`];
|
|
520
|
-
currentGCData.gcNodes[id] = routes;
|
|
521
|
-
telemetryTracker.logIfMissingExplicitReferences(currentGCData, previousGCData, explicitReferences, mc.logger);
|
|
522
|
-
mockLogger.assertMatchNone([
|
|
523
|
-
{
|
|
524
|
-
eventName: unknownReferenceEventName,
|
|
525
|
-
},
|
|
526
|
-
], "There should be no gcUnknownOutboundReferences event when other node routes are added");
|
|
527
|
-
});
|
|
528
|
-
});
|
|
529
|
-
});
|
|
530
|
-
//# sourceMappingURL=gcTelemetry.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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"]}
|