@fluidframework/container-runtime 2.0.0-internal.3.0.2 → 2.0.0-internal.3.2.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/.eslintrc.js +19 -19
- package/.mocharc.js +2 -2
- package/api-extractor.json +2 -2
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +2 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +15 -2
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +109 -37
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +11 -9
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js +3 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +23 -11
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +225 -132
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +11 -9
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +27 -13
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +95 -56
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +7 -3
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +3 -1
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts +28 -4
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +122 -44
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +8 -3
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/{garbageCollection.d.ts → gc/garbageCollection.d.ts} +27 -203
- package/dist/gc/garbageCollection.d.ts.map +1 -0
- package/dist/{garbageCollection.js → gc/garbageCollection.js} +210 -400
- package/dist/gc/garbageCollection.js.map +1 -0
- package/dist/gc/gcDefinitions.d.ts +189 -0
- package/dist/gc/gcDefinitions.d.ts.map +1 -0
- package/dist/{garbageCollectionConstants.js → gc/gcDefinitions.js} +27 -2
- package/dist/gc/gcDefinitions.js.map +1 -0
- package/dist/gc/gcHelpers.d.ts +30 -0
- package/dist/gc/gcHelpers.d.ts.map +1 -0
- package/dist/gc/gcHelpers.js +65 -0
- package/dist/gc/gcHelpers.js.map +1 -0
- package/dist/gc/gcSummaryStateTracker.d.ts +86 -0
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -0
- package/dist/gc/gcSummaryStateTracker.js +246 -0
- package/dist/gc/gcSummaryStateTracker.js.map +1 -0
- package/{lib → dist/gc}/gcSweepReadyUsageDetection.d.ts +5 -5
- package/dist/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
- package/dist/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +15 -11
- package/dist/gc/gcSweepReadyUsageDetection.js.map +1 -0
- package/dist/gc/gcUnreferencedStateTracker.d.ts +34 -0
- package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
- package/dist/gc/gcUnreferencedStateTracker.js +94 -0
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -0
- package/dist/gc/index.d.ts +11 -0
- package/dist/gc/index.d.ts.map +1 -0
- package/dist/gc/index.js +40 -0
- package/dist/gc/index.js.map +1 -0
- package/dist/index.d.ts +2 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -9
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +2 -13
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +19 -41
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +4 -0
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +1 -0
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +5 -2
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +24 -13
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +19 -3
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +78 -45
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/opProperties.d.ts.map +1 -1
- package/dist/opProperties.js +1 -3
- package/dist/opProperties.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 +8 -2
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +21 -13
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +3 -2
- package/dist/scheduleManager.js.map +1 -1
- package/dist/serializedSnapshotStorage.d.ts +2 -2
- package/dist/serializedSnapshotStorage.d.ts.map +1 -1
- package/dist/serializedSnapshotStorage.js +5 -3
- package/dist/serializedSnapshotStorage.js.map +1 -1
- package/dist/summary/index.d.ts +17 -0
- package/dist/summary/index.d.ts.map +1 -0
- package/dist/summary/index.js +47 -0
- package/dist/summary/index.js.map +1 -0
- package/dist/summary/orderedClientElection.d.ts.map +1 -0
- package/dist/{orderedClientElection.js → summary/orderedClientElection.js} +10 -4
- package/dist/summary/orderedClientElection.js.map +1 -0
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -0
- package/{lib → dist/summary}/runningSummarizer.d.ts +19 -18
- package/dist/summary/runningSummarizer.d.ts.map +1 -0
- package/dist/{runningSummarizer.js → summary/runningSummarizer.js} +191 -76
- package/dist/summary/runningSummarizer.js.map +1 -0
- package/dist/{summarizer.d.ts → summary/summarizer.d.ts} +4 -6
- package/dist/summary/summarizer.d.ts.map +1 -0
- package/dist/{summarizer.js → summary/summarizer.js} +31 -71
- package/dist/summary/summarizer.js.map +1 -0
- package/dist/summary/summarizerClientElection.d.ts.map +1 -0
- package/dist/summary/summarizerClientElection.js.map +1 -0
- package/dist/summary/summarizerHandle.d.ts.map +1 -0
- package/dist/summary/summarizerHandle.js.map +1 -0
- package/{lib → dist/summary}/summarizerHeuristics.d.ts +1 -1
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -0
- package/dist/{summarizerHeuristics.js → summary/summarizerHeuristics.js} +6 -9
- package/dist/summary/summarizerHeuristics.js.map +1 -0
- package/{lib → dist/summary}/summarizerTypes.d.ts +22 -22
- package/dist/summary/summarizerTypes.d.ts.map +1 -0
- package/dist/summary/summarizerTypes.js.map +1 -0
- package/dist/summary/summaryCollection.d.ts.map +1 -0
- package/dist/{summaryCollection.js → summary/summaryCollection.js} +18 -8
- package/dist/summary/summaryCollection.js.map +1 -0
- package/{lib → dist/summary}/summaryFormat.d.ts +1 -40
- package/dist/summary/summaryFormat.d.ts.map +1 -0
- package/dist/{summaryFormat.js → summary/summaryFormat.js} +19 -20
- package/dist/summary/summaryFormat.js.map +1 -0
- package/dist/summary/summaryGenerator.d.ts.map +1 -0
- package/dist/{summaryGenerator.js → summary/summaryGenerator.js} +33 -15
- package/dist/summary/summaryGenerator.js.map +1 -0
- package/dist/{summaryManager.d.ts → summary/summaryManager.d.ts} +1 -1
- package/dist/summary/summaryManager.d.ts.map +1 -0
- package/dist/{summaryManager.js → summary/summaryManager.js} +21 -9
- package/dist/summary/summaryManager.js.map +1 -0
- package/dist/throttler.d.ts +2 -2
- package/dist/throttler.d.ts.map +1 -1
- package/dist/throttler.js +4 -4
- package/dist/throttler.js.map +1 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +15 -2
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +109 -37
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +11 -9
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js +3 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +23 -11
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +201 -108
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +11 -9
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +27 -13
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +84 -45
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +7 -3
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js +3 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts +28 -4
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +120 -42
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +9 -4
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/{garbageCollection.d.ts → gc/garbageCollection.d.ts} +27 -203
- package/lib/gc/garbageCollection.d.ts.map +1 -0
- package/lib/{garbageCollection.js → gc/garbageCollection.js} +190 -379
- package/lib/gc/garbageCollection.js.map +1 -0
- package/lib/gc/gcDefinitions.d.ts +189 -0
- package/lib/gc/gcDefinitions.d.ts.map +1 -0
- package/lib/{garbageCollectionConstants.js → gc/gcDefinitions.js} +26 -1
- package/lib/gc/gcDefinitions.js.map +1 -0
- package/lib/gc/gcHelpers.d.ts +30 -0
- package/lib/gc/gcHelpers.d.ts.map +1 -0
- package/lib/gc/gcHelpers.js +58 -0
- package/lib/gc/gcHelpers.js.map +1 -0
- package/lib/gc/gcSummaryStateTracker.d.ts +86 -0
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -0
- package/lib/gc/gcSummaryStateTracker.js +242 -0
- package/lib/gc/gcSummaryStateTracker.js.map +1 -0
- package/{dist → lib/gc}/gcSweepReadyUsageDetection.d.ts +5 -5
- package/lib/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
- package/lib/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +15 -11
- package/lib/gc/gcSweepReadyUsageDetection.js.map +1 -0
- package/lib/gc/gcUnreferencedStateTracker.d.ts +34 -0
- package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
- package/lib/gc/gcUnreferencedStateTracker.js +90 -0
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -0
- package/lib/gc/index.d.ts +11 -0
- package/lib/gc/index.d.ts.map +1 -0
- package/lib/gc/index.js +11 -0
- package/lib/gc/index.js.map +1 -0
- package/lib/index.d.ts +2 -5
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -4
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +2 -13
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +19 -41
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +4 -0
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +1 -0
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +5 -2
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +1 -1
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +25 -14
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +19 -3
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +79 -46
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/opProperties.d.ts.map +1 -1
- package/lib/opProperties.js +1 -3
- package/lib/opProperties.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 +8 -2
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +21 -13
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +3 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/serializedSnapshotStorage.d.ts +2 -2
- package/lib/serializedSnapshotStorage.d.ts.map +1 -1
- package/lib/serializedSnapshotStorage.js +5 -3
- package/lib/serializedSnapshotStorage.js.map +1 -1
- package/lib/summary/index.d.ts +17 -0
- package/lib/summary/index.d.ts.map +1 -0
- package/lib/summary/index.js +16 -0
- package/lib/summary/index.js.map +1 -0
- package/lib/summary/orderedClientElection.d.ts.map +1 -0
- package/lib/{orderedClientElection.js → summary/orderedClientElection.js} +10 -4
- package/lib/summary/orderedClientElection.js.map +1 -0
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -0
- package/{dist → lib/summary}/runningSummarizer.d.ts +19 -18
- package/lib/summary/runningSummarizer.d.ts.map +1 -0
- package/lib/{runningSummarizer.js → summary/runningSummarizer.js} +193 -78
- package/lib/summary/runningSummarizer.js.map +1 -0
- package/lib/{summarizer.d.ts → summary/summarizer.d.ts} +4 -6
- package/lib/summary/summarizer.d.ts.map +1 -0
- package/lib/{summarizer.js → summary/summarizer.js} +33 -73
- package/lib/summary/summarizer.js.map +1 -0
- package/lib/summary/summarizerClientElection.d.ts.map +1 -0
- package/lib/summary/summarizerClientElection.js.map +1 -0
- package/lib/summary/summarizerHandle.d.ts.map +1 -0
- package/lib/summary/summarizerHandle.js.map +1 -0
- package/{dist → lib/summary}/summarizerHeuristics.d.ts +1 -1
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
- package/lib/{summarizerHeuristics.js → summary/summarizerHeuristics.js} +6 -9
- package/lib/summary/summarizerHeuristics.js.map +1 -0
- package/{dist → lib/summary}/summarizerTypes.d.ts +22 -22
- package/lib/summary/summarizerTypes.d.ts.map +1 -0
- package/lib/summary/summarizerTypes.js.map +1 -0
- package/lib/summary/summaryCollection.d.ts.map +1 -0
- package/lib/{summaryCollection.js → summary/summaryCollection.js} +18 -8
- package/lib/summary/summaryCollection.js.map +1 -0
- package/{dist → lib/summary}/summaryFormat.d.ts +1 -40
- package/lib/summary/summaryFormat.d.ts.map +1 -0
- package/lib/{summaryFormat.js → summary/summaryFormat.js} +20 -20
- package/lib/summary/summaryFormat.js.map +1 -0
- package/lib/summary/summaryGenerator.d.ts.map +1 -0
- package/lib/{summaryGenerator.js → summary/summaryGenerator.js} +33 -15
- package/lib/summary/summaryGenerator.js.map +1 -0
- package/lib/{summaryManager.d.ts → summary/summaryManager.d.ts} +1 -1
- package/lib/summary/summaryManager.d.ts.map +1 -0
- package/lib/{summaryManager.js → summary/summaryManager.js} +21 -9
- package/lib/summary/summaryManager.js.map +1 -0
- package/lib/throttler.d.ts +2 -2
- package/lib/throttler.d.ts.map +1 -1
- package/lib/throttler.js +4 -4
- package/lib/throttler.js.map +1 -1
- package/package.json +60 -51
- package/prettier.config.cjs +1 -1
- package/src/batchTracker.ts +54 -49
- package/src/blobManager.ts +825 -674
- package/src/connectionTelemetry.ts +280 -249
- package/src/containerHandleContext.ts +27 -29
- package/src/containerRuntime.ts +3249 -2978
- package/src/dataStore.ts +172 -159
- package/src/dataStoreContext.ts +1141 -1057
- package/src/dataStoreContexts.ts +178 -161
- package/src/dataStoreRegistry.ts +25 -20
- package/src/dataStores.ts +880 -731
- package/src/deltaScheduler.ts +158 -150
- package/{garbageCollection.md → src/gc/garbageCollection.md} +16 -3
- package/src/gc/garbageCollection.ts +1506 -0
- package/src/gc/gcDefinitions.ts +244 -0
- package/src/gc/gcHelpers.ts +86 -0
- package/src/gc/gcSummaryStateTracker.ts +339 -0
- package/src/gc/gcSweepReadyUsageDetection.ts +145 -0
- package/src/gc/gcUnreferencedStateTracker.ts +114 -0
- package/src/gc/index.ts +40 -0
- package/src/index.ts +67 -70
- package/src/opLifecycle/README.md +152 -0
- package/src/opLifecycle/batchManager.ts +101 -144
- package/src/opLifecycle/definitions.ts +33 -29
- package/src/opLifecycle/index.ts +5 -5
- package/src/opLifecycle/opCompressor.ts +55 -53
- package/src/opLifecycle/opDecompressor.ts +100 -81
- package/src/opLifecycle/opSplitter.ts +233 -188
- package/src/opLifecycle/outbox.ts +251 -195
- package/src/opLifecycle/remoteMessageProcessor.ts +62 -62
- package/src/opProperties.ts +11 -9
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +396 -338
- package/src/scheduleManager.ts +299 -269
- package/src/serializedSnapshotStorage.ts +126 -112
- package/src/summary/index.ts +99 -0
- package/src/summary/orderedClientElection.ts +564 -0
- package/src/summary/runWhileConnectedCoordinator.ts +113 -0
- package/src/summary/runningSummarizer.ts +788 -0
- package/src/summary/summarizer.ts +386 -0
- package/src/summary/summarizerClientElection.ts +139 -0
- package/src/{summarizerHandle.ts → summary/summarizerHandle.ts} +11 -9
- package/src/summary/summarizerHeuristics.ts +219 -0
- package/src/summary/summarizerTypes.ts +521 -0
- package/src/summary/summaryCollection.ts +450 -0
- package/src/summary/summaryFormat.ts +226 -0
- package/src/summary/summaryGenerator.ts +505 -0
- package/src/summary/summaryManager.ts +423 -0
- package/src/throttler.ts +131 -122
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +9 -13
- package/dist/garbageCollection.d.ts.map +0 -1
- package/dist/garbageCollection.js.map +0 -1
- package/dist/garbageCollectionConstants.d.ts +0 -25
- package/dist/garbageCollectionConstants.d.ts.map +0 -1
- package/dist/garbageCollectionConstants.js.map +0 -1
- package/dist/garbageCollectionTombstoneUtils.d.ts +0 -14
- package/dist/garbageCollectionTombstoneUtils.d.ts.map +0 -1
- package/dist/garbageCollectionTombstoneUtils.js +0 -23
- package/dist/garbageCollectionTombstoneUtils.js.map +0 -1
- package/dist/gcSweepReadyUsageDetection.d.ts.map +0 -1
- package/dist/gcSweepReadyUsageDetection.js.map +0 -1
- package/dist/orderedClientElection.d.ts.map +0 -1
- package/dist/orderedClientElection.js.map +0 -1
- package/dist/runWhileConnectedCoordinator.d.ts.map +0 -1
- package/dist/runWhileConnectedCoordinator.js.map +0 -1
- package/dist/runningSummarizer.d.ts.map +0 -1
- package/dist/runningSummarizer.js.map +0 -1
- package/dist/summarizer.d.ts.map +0 -1
- package/dist/summarizer.js.map +0 -1
- package/dist/summarizerClientElection.d.ts.map +0 -1
- package/dist/summarizerClientElection.js.map +0 -1
- package/dist/summarizerHandle.d.ts.map +0 -1
- package/dist/summarizerHandle.js.map +0 -1
- package/dist/summarizerHeuristics.d.ts.map +0 -1
- package/dist/summarizerHeuristics.js.map +0 -1
- package/dist/summarizerTypes.d.ts.map +0 -1
- package/dist/summarizerTypes.js.map +0 -1
- package/dist/summaryCollection.d.ts.map +0 -1
- package/dist/summaryCollection.js.map +0 -1
- package/dist/summaryFormat.d.ts.map +0 -1
- package/dist/summaryFormat.js.map +0 -1
- package/dist/summaryGenerator.d.ts.map +0 -1
- package/dist/summaryGenerator.js.map +0 -1
- package/dist/summaryManager.d.ts.map +0 -1
- package/dist/summaryManager.js.map +0 -1
- package/lib/garbageCollection.d.ts.map +0 -1
- package/lib/garbageCollection.js.map +0 -1
- package/lib/garbageCollectionConstants.d.ts +0 -25
- package/lib/garbageCollectionConstants.d.ts.map +0 -1
- package/lib/garbageCollectionConstants.js.map +0 -1
- package/lib/garbageCollectionTombstoneUtils.d.ts +0 -14
- package/lib/garbageCollectionTombstoneUtils.d.ts.map +0 -1
- package/lib/garbageCollectionTombstoneUtils.js +0 -19
- package/lib/garbageCollectionTombstoneUtils.js.map +0 -1
- package/lib/gcSweepReadyUsageDetection.d.ts.map +0 -1
- package/lib/gcSweepReadyUsageDetection.js.map +0 -1
- package/lib/orderedClientElection.d.ts.map +0 -1
- package/lib/orderedClientElection.js.map +0 -1
- package/lib/runWhileConnectedCoordinator.d.ts.map +0 -1
- package/lib/runWhileConnectedCoordinator.js.map +0 -1
- package/lib/runningSummarizer.d.ts.map +0 -1
- package/lib/runningSummarizer.js.map +0 -1
- package/lib/summarizer.d.ts.map +0 -1
- package/lib/summarizer.js.map +0 -1
- package/lib/summarizerClientElection.d.ts.map +0 -1
- package/lib/summarizerClientElection.js.map +0 -1
- package/lib/summarizerHandle.d.ts.map +0 -1
- package/lib/summarizerHandle.js.map +0 -1
- package/lib/summarizerHeuristics.d.ts.map +0 -1
- package/lib/summarizerHeuristics.js.map +0 -1
- package/lib/summarizerTypes.d.ts.map +0 -1
- package/lib/summarizerTypes.js.map +0 -1
- package/lib/summaryCollection.d.ts.map +0 -1
- package/lib/summaryCollection.js.map +0 -1
- package/lib/summaryFormat.d.ts.map +0 -1
- package/lib/summaryFormat.js.map +0 -1
- package/lib/summaryGenerator.d.ts.map +0 -1
- package/lib/summaryGenerator.js.map +0 -1
- package/lib/summaryManager.d.ts.map +0 -1
- package/lib/summaryManager.js.map +0 -1
- package/src/garbageCollection.ts +0 -1800
- package/src/garbageCollectionConstants.ts +0 -41
- package/src/garbageCollectionTombstoneUtils.ts +0 -28
- package/src/gcSweepReadyUsageDetection.ts +0 -139
- package/src/orderedClientElection.ts +0 -532
- package/src/runWhileConnectedCoordinator.ts +0 -106
- package/src/runningSummarizer.ts +0 -610
- package/src/summarizer.ts +0 -421
- package/src/summarizerClientElection.ts +0 -132
- package/src/summarizerHeuristics.ts +0 -222
- package/src/summarizerTypes.ts +0 -507
- package/src/summaryCollection.ts +0 -421
- package/src/summaryFormat.ts +0 -256
- package/src/summaryGenerator.ts +0 -450
- package/src/summaryManager.ts +0 -394
- /package/dist/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
- /package/dist/{runWhileConnectedCoordinator.d.ts → summary/runWhileConnectedCoordinator.d.ts} +0 -0
- /package/dist/{runWhileConnectedCoordinator.js → summary/runWhileConnectedCoordinator.js} +0 -0
- /package/dist/{summarizerClientElection.d.ts → summary/summarizerClientElection.d.ts} +0 -0
- /package/dist/{summarizerClientElection.js → summary/summarizerClientElection.js} +0 -0
- /package/dist/{summarizerHandle.d.ts → summary/summarizerHandle.d.ts} +0 -0
- /package/dist/{summarizerHandle.js → summary/summarizerHandle.js} +0 -0
- /package/dist/{summarizerTypes.js → summary/summarizerTypes.js} +0 -0
- /package/dist/{summaryCollection.d.ts → summary/summaryCollection.d.ts} +0 -0
- /package/dist/{summaryGenerator.d.ts → summary/summaryGenerator.d.ts} +0 -0
- /package/lib/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
- /package/lib/{runWhileConnectedCoordinator.d.ts → summary/runWhileConnectedCoordinator.d.ts} +0 -0
- /package/lib/{runWhileConnectedCoordinator.js → summary/runWhileConnectedCoordinator.js} +0 -0
- /package/lib/{summarizerClientElection.d.ts → summary/summarizerClientElection.d.ts} +0 -0
- /package/lib/{summarizerClientElection.js → summary/summarizerClientElection.js} +0 -0
- /package/lib/{summarizerHandle.d.ts → summary/summarizerHandle.d.ts} +0 -0
- /package/lib/{summarizerHandle.js → summary/summarizerHandle.js} +0 -0
- /package/lib/{summarizerTypes.js → summary/summarizerTypes.js} +0 -0
- /package/lib/{summaryCollection.d.ts → summary/summaryCollection.d.ts} +0 -0
- /package/lib/{summaryGenerator.d.ts → summary/summaryGenerator.d.ts} +0 -0
|
@@ -15,108 +15,21 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
15
15
|
return t;
|
|
16
16
|
};
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.GarbageCollector =
|
|
18
|
+
exports.GarbageCollector = void 0;
|
|
19
19
|
const common_utils_1 = require("@fluidframework/common-utils");
|
|
20
20
|
const container_utils_1 = require("@fluidframework/container-utils");
|
|
21
21
|
const garbage_collector_1 = require("@fluidframework/garbage-collector");
|
|
22
|
-
const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
23
22
|
const runtime_definitions_1 = require("@fluidframework/runtime-definitions");
|
|
24
23
|
const runtime_utils_1 = require("@fluidframework/runtime-utils");
|
|
25
24
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
26
|
-
const containerRuntime_1 = require("
|
|
27
|
-
const dataStores_1 = require("
|
|
28
|
-
const
|
|
29
|
-
const
|
|
25
|
+
const containerRuntime_1 = require("../containerRuntime");
|
|
26
|
+
const dataStores_1 = require("../dataStores");
|
|
27
|
+
const summary_1 = require("../summary");
|
|
28
|
+
const gcDefinitions_1 = require("./gcDefinitions");
|
|
29
|
+
const gcHelpers_1 = require("./gcHelpers");
|
|
30
|
+
const gcSummaryStateTracker_1 = require("./gcSummaryStateTracker");
|
|
30
31
|
const gcSweepReadyUsageDetection_1 = require("./gcSweepReadyUsageDetection");
|
|
31
|
-
const
|
|
32
|
-
/** The types of GC nodes in the GC reference graph. */
|
|
33
|
-
exports.GCNodeType = {
|
|
34
|
-
// Nodes that are for data stores.
|
|
35
|
-
DataStore: "DataStore",
|
|
36
|
-
// Nodes that are within a data store. For example, DDS nodes.
|
|
37
|
-
SubDataStore: "SubDataStore",
|
|
38
|
-
// Nodes that are for attachment blobs, i.e., blobs uploaded via BlobManager.
|
|
39
|
-
Blob: "Blob",
|
|
40
|
-
// Nodes that are neither of the above. For example, root node.
|
|
41
|
-
Other: "Other",
|
|
42
|
-
};
|
|
43
|
-
/** The state of node that is unreferenced. */
|
|
44
|
-
exports.UnreferencedState = {
|
|
45
|
-
/** The node is active, i.e., it can become referenced again. */
|
|
46
|
-
Active: "Active",
|
|
47
|
-
/** The node is inactive, i.e., it should not become referenced. */
|
|
48
|
-
Inactive: "Inactive",
|
|
49
|
-
/** The node is ready to be deleted by the sweep phase. */
|
|
50
|
-
SweepReady: "SweepReady",
|
|
51
|
-
};
|
|
52
|
-
/**
|
|
53
|
-
* Helper class that tracks the state of an unreferenced node such as the time it was unreferenced and if it can
|
|
54
|
-
* be deleted by the sweep phase.
|
|
55
|
-
*/
|
|
56
|
-
class UnreferencedStateTracker {
|
|
57
|
-
constructor(unreferencedTimestampMs,
|
|
58
|
-
/** The time after which node transitions to Inactive state. */
|
|
59
|
-
inactiveTimeoutMs,
|
|
60
|
-
/** The current reference timestamp used to track how long this node has been unreferenced for. */
|
|
61
|
-
currentReferenceTimestampMs,
|
|
62
|
-
/** The time after which node transitions to SweepReady state; undefined if session expiry is disabled. */
|
|
63
|
-
sweepTimeoutMs) {
|
|
64
|
-
this.unreferencedTimestampMs = unreferencedTimestampMs;
|
|
65
|
-
this.inactiveTimeoutMs = inactiveTimeoutMs;
|
|
66
|
-
this.sweepTimeoutMs = sweepTimeoutMs;
|
|
67
|
-
this._state = exports.UnreferencedState.Active;
|
|
68
|
-
if (this.sweepTimeoutMs !== undefined) {
|
|
69
|
-
(0, common_utils_1.assert)(this.inactiveTimeoutMs <= this.sweepTimeoutMs, 0x3b0 /* inactive timeout must not be greater than the sweep timeout */);
|
|
70
|
-
}
|
|
71
|
-
this.sweepTimer = new TimerWithNoDefaultTimeout(() => {
|
|
72
|
-
this._state = exports.UnreferencedState.SweepReady;
|
|
73
|
-
(0, common_utils_1.assert)(!this.inactiveTimer.hasTimer, 0x3b1 /* inactiveTimer still running after sweepTimer fired! */);
|
|
74
|
-
});
|
|
75
|
-
this.inactiveTimer = new TimerWithNoDefaultTimeout(() => {
|
|
76
|
-
this._state = exports.UnreferencedState.Inactive;
|
|
77
|
-
// After the node becomes inactive, start the sweep timer after which the node will be ready for sweep.
|
|
78
|
-
if (this.sweepTimeoutMs !== undefined) {
|
|
79
|
-
this.sweepTimer.restart(this.sweepTimeoutMs - this.inactiveTimeoutMs);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
this.updateTracking(currentReferenceTimestampMs);
|
|
83
|
-
}
|
|
84
|
-
get state() {
|
|
85
|
-
return this._state;
|
|
86
|
-
}
|
|
87
|
-
/* Updates the unreferenced state based on the provided timestamp. */
|
|
88
|
-
updateTracking(currentReferenceTimestampMs) {
|
|
89
|
-
const unreferencedDurationMs = currentReferenceTimestampMs - this.unreferencedTimestampMs;
|
|
90
|
-
// If the node has been unreferenced for sweep timeout amount of time, update the state to SweepReady.
|
|
91
|
-
if (this.sweepTimeoutMs !== undefined && unreferencedDurationMs >= this.sweepTimeoutMs) {
|
|
92
|
-
this._state = exports.UnreferencedState.SweepReady;
|
|
93
|
-
this.clearTimers();
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
// If the node has been unreferenced for inactive timeoutMs amount of time, update the state to inactive.
|
|
97
|
-
// Also, start a timer for the sweep timeout.
|
|
98
|
-
if (unreferencedDurationMs >= this.inactiveTimeoutMs) {
|
|
99
|
-
this._state = exports.UnreferencedState.Inactive;
|
|
100
|
-
this.inactiveTimer.clear();
|
|
101
|
-
if (this.sweepTimeoutMs !== undefined) {
|
|
102
|
-
this.sweepTimer.restart(this.sweepTimeoutMs - unreferencedDurationMs);
|
|
103
|
-
}
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
// The node is still active. Ensure the inactive timer is running with the proper remaining duration.
|
|
107
|
-
this.inactiveTimer.restart(this.inactiveTimeoutMs - unreferencedDurationMs);
|
|
108
|
-
}
|
|
109
|
-
clearTimers() {
|
|
110
|
-
this.inactiveTimer.clear();
|
|
111
|
-
this.sweepTimer.clear();
|
|
112
|
-
}
|
|
113
|
-
/** Stop tracking this node. Reset the unreferenced timers and state, if any. */
|
|
114
|
-
stopTracking() {
|
|
115
|
-
this.clearTimers();
|
|
116
|
-
this._state = exports.UnreferencedState.Active;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
exports.UnreferencedStateTracker = UnreferencedStateTracker;
|
|
32
|
+
const gcUnreferencedStateTracker_1 = require("./gcUnreferencedStateTracker");
|
|
120
33
|
/**
|
|
121
34
|
* The garbage collector for the container runtime. It consolidates the garbage collection functionality and maintains
|
|
122
35
|
* its state across summaries.
|
|
@@ -128,15 +41,15 @@ exports.UnreferencedStateTracker = UnreferencedStateTracker;
|
|
|
128
41
|
* Graph - all nodes with their respective routes
|
|
129
42
|
*
|
|
130
43
|
* ```
|
|
131
|
-
*
|
|
44
|
+
* GC Graph
|
|
132
45
|
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* NodeId = "dds1"
|
|
46
|
+
* Node
|
|
47
|
+
* NodeId = "datastore1"
|
|
48
|
+
* / \\
|
|
49
|
+
* OutboundRoute OutboundRoute
|
|
50
|
+
* / \\
|
|
51
|
+
* Node Node
|
|
52
|
+
* NodeId = "dds1" NodeId = "dds2"
|
|
140
53
|
* ```
|
|
141
54
|
*/
|
|
142
55
|
class GarbageCollector {
|
|
@@ -168,12 +81,11 @@ class GarbageCollector {
|
|
|
168
81
|
const baseSnapshot = createParams.baseSnapshot;
|
|
169
82
|
const metadata = createParams.metadata;
|
|
170
83
|
const readAndParseBlob = createParams.readAndParseBlob;
|
|
171
|
-
this.mc = (0, telemetry_utils_1.loggerToMonitoringContext)(telemetry_utils_1.ChildLogger.create(createParams.baseLogger, "GarbageCollector", {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
this.mc.config.getBoolean(garbageCollectionConstants_1.gcVersionUpgradeToV2Key) === true ? garbageCollectionConstants_1.currentGCVersion : garbageCollectionConstants_1.stableGCVersion;
|
|
84
|
+
this.mc = (0, telemetry_utils_1.loggerToMonitoringContext)(telemetry_utils_1.ChildLogger.create(createParams.baseLogger, "GarbageCollector", {
|
|
85
|
+
all: { completedGCRuns: () => this.completedRuns },
|
|
86
|
+
}));
|
|
175
87
|
this.sweepReadyUsageHandler = new gcSweepReadyUsageDetection_1.SweepReadyUsageDetectionHandler(createParams.getContainerDiagnosticId(), this.mc, this.runtime.closeFn);
|
|
176
|
-
let
|
|
88
|
+
let gcVersionInBaseSnapshot;
|
|
177
89
|
/**
|
|
178
90
|
* Sweep timeout is the time after which unreferenced content can be swept.
|
|
179
91
|
* Sweep timeout = session expiry timeout + snapshot cache expiry timeout + one day buffer.
|
|
@@ -183,10 +95,10 @@ class GarbageCollector {
|
|
|
183
95
|
* We use server timestamps throughout so the skew should be minimal but make it 1 day to be safe.
|
|
184
96
|
*/
|
|
185
97
|
function computeSweepTimeout(sessionExpiryTimeoutMs) {
|
|
186
|
-
const maxSnapshotCacheExpiryMs = 5 *
|
|
187
|
-
const bufferMs =
|
|
188
|
-
return sessionExpiryTimeoutMs &&
|
|
189
|
-
|
|
98
|
+
const maxSnapshotCacheExpiryMs = 5 * gcDefinitions_1.oneDayMs;
|
|
99
|
+
const bufferMs = gcDefinitions_1.oneDayMs;
|
|
100
|
+
return (sessionExpiryTimeoutMs &&
|
|
101
|
+
sessionExpiryTimeoutMs + maxSnapshotCacheExpiryMs + bufferMs);
|
|
190
102
|
}
|
|
191
103
|
/**
|
|
192
104
|
* The following GC state is enabled during container creation and cannot be changed throughout its lifetime:
|
|
@@ -196,10 +108,10 @@ class GarbageCollector {
|
|
|
196
108
|
* For existing containers, we get this information from the metadata blob of its summary.
|
|
197
109
|
*/
|
|
198
110
|
if (createParams.existing) {
|
|
199
|
-
|
|
111
|
+
gcVersionInBaseSnapshot = (0, gcHelpers_1.getGCVersion)(metadata);
|
|
200
112
|
// Existing documents which did not have metadata blob or had GC disabled have version as 0. For all
|
|
201
113
|
// other existing documents, GC is enabled.
|
|
202
|
-
this.gcEnabled =
|
|
114
|
+
this.gcEnabled = gcVersionInBaseSnapshot > 0;
|
|
203
115
|
this.sweepEnabled = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.sweepEnabled) !== null && _a !== void 0 ? _a : false;
|
|
204
116
|
this.sessionExpiryTimeoutMs = metadata === null || metadata === void 0 ? void 0 : metadata.sessionExpiryTimeoutMs;
|
|
205
117
|
this.sweepTimeoutMs =
|
|
@@ -220,14 +132,15 @@ class GarbageCollector {
|
|
|
220
132
|
// The sweep phase has to be explicitly enabled by setting the sweepAllowed flag in GC options to true.
|
|
221
133
|
this.sweepEnabled = this.gcOptions.sweepAllowed === true;
|
|
222
134
|
// Set the Session Expiry only if the flag is enabled and GC is enabled.
|
|
223
|
-
if (this.mc.config.getBoolean(
|
|
224
|
-
this.sessionExpiryTimeoutMs =
|
|
135
|
+
if (this.mc.config.getBoolean(gcDefinitions_1.runSessionExpiryKey) && this.gcEnabled) {
|
|
136
|
+
this.sessionExpiryTimeoutMs =
|
|
137
|
+
(_c = this.gcOptions.sessionExpiryTimeoutMs) !== null && _c !== void 0 ? _c : gcDefinitions_1.defaultSessionExpiryDurationMs;
|
|
225
138
|
}
|
|
226
139
|
this.sweepTimeoutMs =
|
|
227
140
|
testOverrideSweepTimeoutMs !== null && testOverrideSweepTimeoutMs !== void 0 ? testOverrideSweepTimeoutMs : computeSweepTimeout(this.sessionExpiryTimeoutMs);
|
|
228
|
-
if (this.gcOptions[
|
|
141
|
+
if (this.gcOptions[gcDefinitions_1.gcTombstoneGenerationOptionName] !== undefined) {
|
|
229
142
|
this.persistedGcFeatureMatrix = {
|
|
230
|
-
tombstoneGeneration: this.gcOptions[
|
|
143
|
+
tombstoneGeneration: this.gcOptions[gcDefinitions_1.gcTombstoneGenerationOptionName],
|
|
231
144
|
};
|
|
232
145
|
}
|
|
233
146
|
}
|
|
@@ -236,12 +149,11 @@ class GarbageCollector {
|
|
|
236
149
|
// If Test Override config is set, override Session Expiry timeout.
|
|
237
150
|
const overrideSessionExpiryTimeoutMs = this.mc.config.getNumber("Fluid.GarbageCollection.TestOverride.SessionExpiryMs");
|
|
238
151
|
const timeoutMs = overrideSessionExpiryTimeoutMs !== null && overrideSessionExpiryTimeoutMs !== void 0 ? overrideSessionExpiryTimeoutMs : this.sessionExpiryTimeoutMs;
|
|
239
|
-
this.sessionExpiryTimer = new common_utils_1.Timer(timeoutMs, () => {
|
|
152
|
+
this.sessionExpiryTimer = new common_utils_1.Timer(timeoutMs, () => {
|
|
153
|
+
this.runtime.closeFn(new container_utils_1.ClientSessionExpiredError(`Client session expired.`, timeoutMs));
|
|
154
|
+
});
|
|
240
155
|
this.sessionExpiryTimer.start();
|
|
241
156
|
}
|
|
242
|
-
// For existing document, the latest summary is the one that we loaded from. So, use its GC version as the
|
|
243
|
-
// latest tracked GC version. For new documents, we will be writing the first summary with the current version.
|
|
244
|
-
this.latestSummaryGCVersion = prevSummaryGCVersion !== null && prevSummaryGCVersion !== void 0 ? prevSummaryGCVersion : this.currentGCVersion;
|
|
245
157
|
/**
|
|
246
158
|
* Whether GC should run or not. The following conditions have to be met to run sweep:
|
|
247
159
|
*
|
|
@@ -251,11 +163,12 @@ class GarbageCollector {
|
|
|
251
163
|
*
|
|
252
164
|
* These conditions can be overridden via runGCKey feature flag.
|
|
253
165
|
*/
|
|
254
|
-
this.shouldRunGC =
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
166
|
+
this.shouldRunGC =
|
|
167
|
+
(_d = this.mc.config.getBoolean(gcDefinitions_1.runGCKey)) !== null && _d !== void 0 ? _d :
|
|
168
|
+
// GC must be enabled for the document.
|
|
169
|
+
(this.gcEnabled &&
|
|
170
|
+
// GC must not be disabled via GC options.
|
|
171
|
+
!this.gcOptions.disableGC);
|
|
259
172
|
/**
|
|
260
173
|
* Whether sweep should run or not. The following conditions have to be met to run sweep:
|
|
261
174
|
*
|
|
@@ -267,23 +180,25 @@ class GarbageCollector {
|
|
|
267
180
|
* feature flag.
|
|
268
181
|
*/
|
|
269
182
|
this.shouldRunSweep =
|
|
270
|
-
this.shouldRunGC
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
this.trackGCState = this.mc.config.getBoolean(
|
|
183
|
+
this.shouldRunGC &&
|
|
184
|
+
this.sweepTimeoutMs !== undefined &&
|
|
185
|
+
((_e = this.mc.config.getBoolean(gcDefinitions_1.runSweepKey)) !== null && _e !== void 0 ? _e : this.sweepEnabled);
|
|
186
|
+
this.trackGCState = this.mc.config.getBoolean(gcDefinitions_1.trackGCStateKey) === true;
|
|
274
187
|
// Override inactive timeout if test config or gc options to override it is set.
|
|
275
|
-
this.inactiveTimeoutMs =
|
|
188
|
+
this.inactiveTimeoutMs =
|
|
189
|
+
(_g = (_f = this.mc.config.getNumber("Fluid.GarbageCollection.TestOverride.InactiveTimeoutMs")) !== null && _f !== void 0 ? _f : this.gcOptions.inactiveTimeoutMs) !== null && _g !== void 0 ? _g : gcDefinitions_1.defaultInactiveTimeoutMs;
|
|
276
190
|
// Inactive timeout must be greater than sweep timeout since a node goes from active -> inactive -> sweep ready.
|
|
277
191
|
if (this.sweepTimeoutMs !== undefined && this.inactiveTimeoutMs > this.sweepTimeoutMs) {
|
|
278
192
|
throw new container_utils_1.UsageError("inactive timeout should not be greater than the sweep timeout");
|
|
279
193
|
}
|
|
280
194
|
// Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.
|
|
281
|
-
this.testMode =
|
|
195
|
+
this.testMode =
|
|
196
|
+
(_h = this.mc.config.getBoolean(gcDefinitions_1.gcTestModeKey)) !== null && _h !== void 0 ? _h : this.gcOptions.runGCInTestMode === true;
|
|
282
197
|
// Whether we are running in tombstone mode. This is enabled by default if sweep won't run. It can be disabled
|
|
283
198
|
// via feature flags.
|
|
284
|
-
this.tombstoneMode =
|
|
285
|
-
|
|
286
|
-
this.
|
|
199
|
+
this.tombstoneMode =
|
|
200
|
+
!this.shouldRunSweep && this.mc.config.getBoolean(gcDefinitions_1.disableTombstoneKey) !== true;
|
|
201
|
+
this.summaryStateTracker = new gcSummaryStateTracker_1.GCSummaryStateTracker(this.shouldRunGC, this.trackGCState, this.tombstoneMode, this.mc, (baseSnapshot === null || baseSnapshot === void 0 ? void 0 : baseSnapshot.trees[runtime_definitions_1.gcTreeKey]) !== undefined /* wasGCRunInBaseSnapshot */, gcVersionInBaseSnapshot);
|
|
287
202
|
// Get the GC data from the base snapshot. Use LazyPromise because we only want to do this once since it
|
|
288
203
|
// it involves fetching blobs from storage which is expensive.
|
|
289
204
|
this.baseSnapshotDataP = new common_utils_1.LazyPromise(async () => {
|
|
@@ -300,7 +215,9 @@ class GarbageCollector {
|
|
|
300
215
|
// back-compat - Older documents will have the GC blobs in each data store's summary tree. Get them and
|
|
301
216
|
// consolidate into IGarbageCollectionState format.
|
|
302
217
|
// Add a node for the root node that is not present in older snapshot format.
|
|
303
|
-
const gcState = {
|
|
218
|
+
const gcState = {
|
|
219
|
+
gcNodes: { "/": { outboundRoutes: [] } },
|
|
220
|
+
};
|
|
304
221
|
const dataStoreSnapshotTree = (0, dataStores_1.getSummaryForDatastores)(baseSnapshot, metadata);
|
|
305
222
|
(0, common_utils_1.assert)(dataStoreSnapshotTree !== undefined, 0x2a8 /* "Expected data store snapshot tree in base snapshot" */);
|
|
306
223
|
for (const [dsId, dsSnapshotTree] of Object.entries(dataStoreSnapshotTree.trees)) {
|
|
@@ -316,7 +233,7 @@ class GarbageCollector {
|
|
|
316
233
|
const dsRootId = `/${dsId}`;
|
|
317
234
|
// Since we used to write GC data at data store level, we won't have an entry for the root ("/").
|
|
318
235
|
// Construct that entry by adding root data store ids to its outbound routes.
|
|
319
|
-
const initialSnapshotDetails = await readAndParseBlob(dsSnapshotTree.blobs[
|
|
236
|
+
const initialSnapshotDetails = await readAndParseBlob(dsSnapshotTree.blobs[summary_1.dataStoreAttributesBlobName]);
|
|
320
237
|
if (initialSnapshotDetails.isRootDataStore) {
|
|
321
238
|
gcState.gcNodes["/"].outboundRoutes.push(dsRootId);
|
|
322
239
|
}
|
|
@@ -324,10 +241,13 @@ class GarbageCollector {
|
|
|
324
241
|
// Prefix the data store id to the GC node ids to make them relative to the root from being
|
|
325
242
|
// relative to the data store. Similar to how its done in DataStore::getGCData.
|
|
326
243
|
const rootId = id === "/" ? dsRootId : `${dsRootId}${id}`;
|
|
327
|
-
gcState.gcNodes[rootId] = {
|
|
244
|
+
gcState.gcNodes[rootId] = {
|
|
245
|
+
outboundRoutes: Array.from(outboundRoutes),
|
|
246
|
+
};
|
|
328
247
|
}
|
|
329
248
|
(0, common_utils_1.assert)(gcState.gcNodes[dsRootId] !== undefined, 0x2a9 /* GC nodes for data store not in GC blob */);
|
|
330
|
-
gcState.gcNodes[dsRootId].unreferencedTimestampMs =
|
|
249
|
+
gcState.gcNodes[dsRootId].unreferencedTimestampMs =
|
|
250
|
+
gcSummaryDetails.unrefTimestamp;
|
|
331
251
|
}
|
|
332
252
|
// If there is only one node (root node just added above), either GC is disabled or we are loading from
|
|
333
253
|
// the first summary generated by detached container. In both cases, GC was not run - return undefined.
|
|
@@ -405,46 +325,13 @@ class GarbageCollector {
|
|
|
405
325
|
static create(createParams) {
|
|
406
326
|
return new GarbageCollector(createParams);
|
|
407
327
|
}
|
|
408
|
-
/**
|
|
409
|
-
* Tells whether the GC state needs to be reset in the next summary. We need to do this if:
|
|
410
|
-
*
|
|
411
|
-
* 1. GC was enabled and is now disabled. The GC state needs to be removed and everything becomes referenced.
|
|
412
|
-
*
|
|
413
|
-
* 2. GC was disabled and is now enabled. The GC state needs to be regenerated and added to summary.
|
|
414
|
-
*
|
|
415
|
-
* 3. GC is enabled and the latest summary state is refreshed from a snapshot that had GC disabled and vice-versa.
|
|
416
|
-
*
|
|
417
|
-
* 4. The GC version in the latest summary is different from the current GC version. This can happen if:
|
|
418
|
-
*
|
|
419
|
-
* 4.1. The summary this client loaded with has data from a different GC version.
|
|
420
|
-
*
|
|
421
|
-
* 4.2. This client's latest summary was updated from a snapshot that has a different GC version.
|
|
422
|
-
*/
|
|
423
|
-
get summaryStateNeedsReset() {
|
|
424
|
-
return this.gcStateNeedsReset ||
|
|
425
|
-
(this.shouldRunGC && this.latestSummaryGCVersion !== this.currentGCVersion);
|
|
426
|
-
}
|
|
427
|
-
/**
|
|
428
|
-
* Tells whether the GC state needs to be reset. This can happen under 3 conditions:
|
|
429
|
-
*
|
|
430
|
-
* 1. The base snapshot contains GC state but GC is disabled. This will happen the first time GC is disabled after
|
|
431
|
-
* it was enabled before. GC state needs to be removed from summary and all nodes should be marked referenced.
|
|
432
|
-
*
|
|
433
|
-
* 2. The base snapshot does not have GC state but GC is enabled. This will happen the very first time GC runs on
|
|
434
|
-
* a document and the first time GC is enabled after is was disabled before.
|
|
435
|
-
*
|
|
436
|
-
* 3. GC is enabled and the latest summary state is refreshed from a snapshot that had GC disabled and vice-versa.
|
|
437
|
-
*
|
|
438
|
-
* Note that the state will be reset only once for the first summary generated after this returns true. After that,
|
|
439
|
-
* this will return false.
|
|
440
|
-
*/
|
|
441
|
-
get gcStateNeedsReset() {
|
|
442
|
-
return this.wasGCRunInLatestSummary !== this.shouldRunGC;
|
|
443
|
-
}
|
|
444
328
|
/** Returns a list of all the configurations for garbage collection. */
|
|
445
329
|
get configs() {
|
|
446
330
|
return Object.assign({ gcEnabled: this.gcEnabled, sweepEnabled: this.sweepEnabled, runGC: this.shouldRunGC, runSweep: this.shouldRunSweep, testMode: this.testMode, tombstoneMode: this.tombstoneMode, sessionExpiry: this.sessionExpiryTimeoutMs, sweepTimeout: this.sweepTimeoutMs, inactiveTimeout: this.inactiveTimeoutMs, trackGCState: this.trackGCState }, this.gcOptions);
|
|
447
331
|
}
|
|
332
|
+
get summaryStateNeedsReset() {
|
|
333
|
+
return this.summaryStateTracker.doesSummaryStateNeedReset();
|
|
334
|
+
}
|
|
448
335
|
/**
|
|
449
336
|
* Called during container initialization. Initialize from the tombstone state in the base snapshot. This is done
|
|
450
337
|
* during initialization so that deleted or tombstoned objects are marked as such before they are loaded or used.
|
|
@@ -468,6 +355,7 @@ class GarbageCollector {
|
|
|
468
355
|
// If running in tombstone mode, initialize the tombstone state from the snapshot. Also, notify the runtime of
|
|
469
356
|
// tombstone routes.
|
|
470
357
|
if (this.tombstoneMode && baseSnapshotData.tombstones !== undefined) {
|
|
358
|
+
// Create a copy since we are writing from a source we don't control
|
|
471
359
|
this.tombstones = Array.from(baseSnapshotData.tombstones);
|
|
472
360
|
this.runtime.updateTombstonedRoutes(this.tombstones);
|
|
473
361
|
}
|
|
@@ -495,7 +383,6 @@ class GarbageCollector {
|
|
|
495
383
|
for (const [, nodeStateTracker] of this.unreferencedNodesState) {
|
|
496
384
|
nodeStateTracker.stopTracking();
|
|
497
385
|
}
|
|
498
|
-
;
|
|
499
386
|
this.unreferencedNodesState.clear();
|
|
500
387
|
// If running sweep, the tombstone state represents the list of nodes that have been deleted during sweep.
|
|
501
388
|
// If running in tombstone mode, the tombstone state represents the list of nodes that have been marked as
|
|
@@ -503,7 +390,9 @@ class GarbageCollector {
|
|
|
503
390
|
// If this call is because we are refreshing from a snapshot due to an ack, it is likely that the GC state
|
|
504
391
|
// in the snapshot is newer than this client's. And so, the deleted / tombstone nodes need to be updated.
|
|
505
392
|
if (this.shouldRunSweep) {
|
|
506
|
-
const snapshotDeletedNodes = (snapshotData === null || snapshotData === void 0 ? void 0 : snapshotData.
|
|
393
|
+
const snapshotDeletedNodes = (snapshotData === null || snapshotData === void 0 ? void 0 : snapshotData.deletedNodes)
|
|
394
|
+
? new Set(snapshotData.deletedNodes)
|
|
395
|
+
: undefined;
|
|
507
396
|
// If the snapshot contains deleted nodes that are not yet deleted by this client, ask the runtime to
|
|
508
397
|
// delete them.
|
|
509
398
|
if (snapshotDeletedNodes !== undefined) {
|
|
@@ -524,10 +413,11 @@ class GarbageCollector {
|
|
|
524
413
|
this.tombstones = (snapshotData === null || snapshotData === void 0 ? void 0 : snapshotData.tombstones) ? Array.from(snapshotData.tombstones) : [];
|
|
525
414
|
this.runtime.updateTombstonedRoutes(this.tombstones);
|
|
526
415
|
}
|
|
416
|
+
// Update the summary state tracker's state from this snapshot.
|
|
417
|
+
this.summaryStateTracker.updateStateFromSnapshotData(snapshotData);
|
|
527
418
|
// If there is no snapshot data, it means this snapshot was generated with GC disabled. Unset all GC state.
|
|
528
419
|
if (snapshotData === undefined) {
|
|
529
420
|
this.gcDataFromLastRun = undefined;
|
|
530
|
-
this.latestSummaryData = undefined;
|
|
531
421
|
return;
|
|
532
422
|
}
|
|
533
423
|
// Update unreferenced state tracking as per the GC state in the snapshot data and update gcDataFromLastRun
|
|
@@ -535,19 +425,11 @@ class GarbageCollector {
|
|
|
535
425
|
const gcNodes = {};
|
|
536
426
|
for (const [nodeId, nodeData] of Object.entries(snapshotData.gcState.gcNodes)) {
|
|
537
427
|
if (nodeData.unreferencedTimestampMs !== undefined) {
|
|
538
|
-
this.unreferencedNodesState.set(nodeId, new UnreferencedStateTracker(nodeData.unreferencedTimestampMs, this.inactiveTimeoutMs, currentReferenceTimestampMs, this.sweepTimeoutMs));
|
|
428
|
+
this.unreferencedNodesState.set(nodeId, new gcUnreferencedStateTracker_1.UnreferencedStateTracker(nodeData.unreferencedTimestampMs, this.inactiveTimeoutMs, currentReferenceTimestampMs, this.sweepTimeoutMs));
|
|
539
429
|
}
|
|
540
430
|
gcNodes[nodeId] = Array.from(nodeData.outboundRoutes);
|
|
541
431
|
}
|
|
542
432
|
this.gcDataFromLastRun = { gcNodes };
|
|
543
|
-
// If tracking state across summaries, update latest summary data from the snapshot's GC data.
|
|
544
|
-
if (this.trackGCState) {
|
|
545
|
-
this.latestSummaryData = {
|
|
546
|
-
serializedGCState: JSON.stringify(generateSortedGCState(snapshotData.gcState)),
|
|
547
|
-
serializedTombstones: JSON.stringify(snapshotData.tombstones),
|
|
548
|
-
serializedDeletedNodes: JSON.stringify(snapshotData.deletedNodes),
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
433
|
}
|
|
552
434
|
/**
|
|
553
435
|
* Called when the connection state of the runtime changes, i.e., it connects or disconnects. GC subscribes to this
|
|
@@ -579,9 +461,12 @@ class GarbageCollector {
|
|
|
579
461
|
*/
|
|
580
462
|
async collectGarbage(options, telemetryContext) {
|
|
581
463
|
var _a;
|
|
582
|
-
const fullGC = (_a = options.fullGC) !== null && _a !== void 0 ? _a : (this.gcOptions.runFullGC === true ||
|
|
464
|
+
const fullGC = (_a = options.fullGC) !== null && _a !== void 0 ? _a : (this.gcOptions.runFullGC === true ||
|
|
465
|
+
this.summaryStateTracker.doesSummaryStateNeedReset());
|
|
583
466
|
const logger = options.logger
|
|
584
|
-
? telemetry_utils_1.ChildLogger.create(options.logger, undefined, {
|
|
467
|
+
? telemetry_utils_1.ChildLogger.create(options.logger, undefined, {
|
|
468
|
+
all: { completedGCRuns: () => this.completedRuns },
|
|
469
|
+
})
|
|
585
470
|
: this.mc.logger;
|
|
586
471
|
/**
|
|
587
472
|
* If there is no current reference timestamp, skip running GC. We need the current timestamp to track
|
|
@@ -601,7 +486,10 @@ class GarbageCollector {
|
|
|
601
486
|
return undefined;
|
|
602
487
|
}
|
|
603
488
|
// Add the options that are used to run GC to the telemetry context.
|
|
604
|
-
telemetryContext === null || telemetryContext === void 0 ? void 0 : telemetryContext.
|
|
489
|
+
telemetryContext === null || telemetryContext === void 0 ? void 0 : telemetryContext.setMultiple("fluid_GC", "Options", {
|
|
490
|
+
fullGC,
|
|
491
|
+
runSweep: options.runSweep,
|
|
492
|
+
});
|
|
605
493
|
return telemetry_utils_1.PerformanceEvent.timedExecAsync(logger, { eventName: "GarbageCollection" }, async (event) => {
|
|
606
494
|
await this.runPreGCSteps();
|
|
607
495
|
// Get the runtime's GC data and run GC on the reference graph in it.
|
|
@@ -623,26 +511,29 @@ class GarbageCollector {
|
|
|
623
511
|
// Generate statistics from the current run. This is done before updating the current state because it
|
|
624
512
|
// generates some of its data based on previous state of the system.
|
|
625
513
|
const gcStats = this.generateStats(gcResult);
|
|
626
|
-
// Update the state
|
|
627
|
-
|
|
628
|
-
this.updateStateSinceLastRun(gcData, logger);
|
|
629
|
-
// Update the current state and update the runtime of all routes or ids that used as per the GC run.
|
|
630
|
-
this.updateCurrentState(gcData, gcResult, currentReferenceTimestampMs);
|
|
514
|
+
// Update the current mark state and update the runtime of all used routes or ids that used as per the GC run.
|
|
515
|
+
const sweepReadyNodes = this.updateMarkPhase(gcData, gcResult, currentReferenceTimestampMs, logger);
|
|
631
516
|
this.runtime.updateUsedRoutes(gcResult.referencedNodeIds);
|
|
632
517
|
// Log events for objects that are ready to be deleted by sweep. When we have sweep enabled, we will
|
|
633
518
|
// delete these objects here instead.
|
|
634
519
|
this.logSweepEvents(logger, currentReferenceTimestampMs);
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
520
|
+
let updatedGCData = gcData;
|
|
521
|
+
if (this.shouldRunSweep) {
|
|
522
|
+
updatedGCData = this.runSweepPhase(sweepReadyNodes, gcData);
|
|
523
|
+
}
|
|
524
|
+
else if (this.testMode) {
|
|
525
|
+
// If we are running in GC test mode, delete objects for unused routes. This enables testing scenarios
|
|
526
|
+
// involving access to deleted data.
|
|
638
527
|
this.runtime.updateUnusedRoutes(gcResult.deletedNodeIds);
|
|
639
528
|
}
|
|
640
529
|
else if (this.tombstoneMode) {
|
|
530
|
+
this.tombstones = sweepReadyNodes;
|
|
641
531
|
// If we are running in GC tombstone mode, update tombstoned routes. This enables testing scenarios
|
|
642
532
|
// involving access to "deleted" data without actually deleting the data from summaries.
|
|
643
533
|
// Note: we will not tombstone in test mode.
|
|
644
534
|
this.runtime.updateTombstonedRoutes(this.tombstones);
|
|
645
535
|
}
|
|
536
|
+
this.gcDataFromLastRun = (0, garbage_collector_1.cloneGCData)(updatedGCData);
|
|
646
537
|
// Log pending unreferenced events such as a node being used after inactive. This is done after GC runs and
|
|
647
538
|
// updates its state so that we don't send false positives based on intermediate state. For example, we may get
|
|
648
539
|
// reference to an unreferenced node from another unreferenced node which means the node wasn't revived.
|
|
@@ -666,89 +557,7 @@ class GarbageCollector {
|
|
|
666
557
|
unreferencedTimestampMs: (_a = this.unreferencedNodesState.get(nodeId)) === null || _a === void 0 ? void 0 : _a.unreferencedTimestampMs,
|
|
667
558
|
};
|
|
668
559
|
}
|
|
669
|
-
|
|
670
|
-
// Serialize and write deleted nodes, if any. This is done irrespective of whether sweep is enabled or not so
|
|
671
|
-
// to identify deleted nodes' usage.
|
|
672
|
-
const serializedDeletedNodes = this.deletedNodes.size > 0
|
|
673
|
-
? JSON.stringify(Array.from(this.deletedNodes).sort())
|
|
674
|
-
: undefined;
|
|
675
|
-
// If running in tombstone mode, serialize and write tombstones, if any.
|
|
676
|
-
const serializedTombstones = this.tombstoneMode
|
|
677
|
-
? (this.tombstones.length > 0 ? JSON.stringify(this.tombstones.sort()) : undefined)
|
|
678
|
-
: undefined;
|
|
679
|
-
/**
|
|
680
|
-
* Incremental summary of GC data - If none of GC state, deleted nodes or tombstones changed since last summary,
|
|
681
|
-
* write summary handle instead of summary tree for GC.
|
|
682
|
-
* Otherwise, write the GC summary tree. In the tree, for each of these that changed, write a summary blob and
|
|
683
|
-
* for each of these that did not change, write a summary handle.
|
|
684
|
-
*/
|
|
685
|
-
if (this.trackGCState) {
|
|
686
|
-
this.pendingSummaryData = { serializedGCState, serializedTombstones, serializedDeletedNodes };
|
|
687
|
-
if (trackState && !fullTree && this.latestSummaryData !== undefined) {
|
|
688
|
-
// If nothing changed since last summary, send a summary handle for the entire GC data.
|
|
689
|
-
if (this.latestSummaryData.serializedGCState === serializedGCState
|
|
690
|
-
&& this.latestSummaryData.serializedTombstones === serializedTombstones) {
|
|
691
|
-
const stats = (0, runtime_utils_1.mergeStats)();
|
|
692
|
-
stats.handleNodeCount++;
|
|
693
|
-
return {
|
|
694
|
-
summary: {
|
|
695
|
-
type: protocol_definitions_1.SummaryType.Handle,
|
|
696
|
-
handle: `/${runtime_definitions_1.gcTreeKey}`,
|
|
697
|
-
handleType: protocol_definitions_1.SummaryType.Tree,
|
|
698
|
-
},
|
|
699
|
-
stats,
|
|
700
|
-
};
|
|
701
|
-
}
|
|
702
|
-
// If some state changed, build a GC summary tree.
|
|
703
|
-
return this.buildGCSummaryTree(serializedGCState, serializedTombstones, serializedDeletedNodes, true /* trackState */);
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
// If not tracking GC state, build a GC summary tree without any summary handles.
|
|
707
|
-
return this.buildGCSummaryTree(serializedGCState, serializedTombstones, serializedDeletedNodes, false /* trackState */);
|
|
708
|
-
}
|
|
709
|
-
/**
|
|
710
|
-
* Builds the GC summary tree which contains GC state, deleted nodes and tombstones.
|
|
711
|
-
* If trackState is false, all of GC state, deleted nodes and tombstones are written as summary blobs.
|
|
712
|
-
* If trackState is true, only states that changed are written. Rest are written as handles.
|
|
713
|
-
* @param serializedGCState - The GC state serialized as string.
|
|
714
|
-
* @param serializedTombstones - The tombstone state serialized as string.
|
|
715
|
-
* @param serializedDeletedNodes - Deleted nodes serialized as string.
|
|
716
|
-
* @param trackState - Whether we are tracking GC state across summaries.
|
|
717
|
-
* @returns the GC summary tree.
|
|
718
|
-
*/
|
|
719
|
-
buildGCSummaryTree(serializedGCState, serializedTombstones, serializedDeletedNodes, trackState) {
|
|
720
|
-
var _a, _b, _c;
|
|
721
|
-
const gcStateBlobKey = `${runtime_definitions_1.gcBlobPrefix}_root`;
|
|
722
|
-
const builder = new runtime_utils_1.SummaryTreeBuilder();
|
|
723
|
-
// If the GC state hasn't changed, write a summary handle, else write a summary blob for it.
|
|
724
|
-
if (((_a = this.latestSummaryData) === null || _a === void 0 ? void 0 : _a.serializedGCState) === serializedGCState && trackState) {
|
|
725
|
-
builder.addHandle(gcStateBlobKey, protocol_definitions_1.SummaryType.Blob, `/${runtime_definitions_1.gcTreeKey}/${gcStateBlobKey}`);
|
|
726
|
-
}
|
|
727
|
-
else {
|
|
728
|
-
builder.addBlob(gcStateBlobKey, serializedGCState);
|
|
729
|
-
}
|
|
730
|
-
// If tombstones exist, write a summary handle if it hasn't changed. If it has changed, write a
|
|
731
|
-
// summary blob.
|
|
732
|
-
if (serializedTombstones !== undefined) {
|
|
733
|
-
if (((_b = this.latestSummaryData) === null || _b === void 0 ? void 0 : _b.serializedTombstones) === serializedTombstones && trackState) {
|
|
734
|
-
builder.addHandle(runtime_definitions_1.gcTombstoneBlobKey, protocol_definitions_1.SummaryType.Blob, `/${runtime_definitions_1.gcTreeKey}/${runtime_definitions_1.gcTombstoneBlobKey}`);
|
|
735
|
-
}
|
|
736
|
-
else {
|
|
737
|
-
builder.addBlob(runtime_definitions_1.gcTombstoneBlobKey, serializedTombstones);
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
// If there are no deleted nodes, return the summary tree.
|
|
741
|
-
if (serializedDeletedNodes === undefined) {
|
|
742
|
-
return builder.getSummaryTree();
|
|
743
|
-
}
|
|
744
|
-
// If the deleted nodes hasn't changed, write a summary handle, else write a summary blob for it.
|
|
745
|
-
if (((_c = this.latestSummaryData) === null || _c === void 0 ? void 0 : _c.serializedDeletedNodes) === serializedDeletedNodes && trackState) {
|
|
746
|
-
builder.addHandle(runtime_definitions_1.gcDeletedBlobKey, protocol_definitions_1.SummaryType.Blob, `/${runtime_definitions_1.gcTreeKey}/${runtime_definitions_1.gcDeletedBlobKey}`);
|
|
747
|
-
}
|
|
748
|
-
else {
|
|
749
|
-
builder.addBlob(runtime_definitions_1.gcDeletedBlobKey, serializedDeletedNodes);
|
|
750
|
-
}
|
|
751
|
-
return builder.getSummaryTree();
|
|
560
|
+
return this.summaryStateTracker.summarize(fullTree, trackState, gcState, this.deletedNodes, this.tombstones);
|
|
752
561
|
}
|
|
753
562
|
getMetadata() {
|
|
754
563
|
return {
|
|
@@ -756,7 +565,7 @@ class GarbageCollector {
|
|
|
756
565
|
* If GC is enabled, the GC data is written using the current GC version and that is the gcFeature that goes
|
|
757
566
|
* into the metadata blob. If GC is disabled, the gcFeature is 0.
|
|
758
567
|
*/
|
|
759
|
-
gcFeature: this.gcEnabled ? this.currentGCVersion : 0,
|
|
568
|
+
gcFeature: this.gcEnabled ? this.summaryStateTracker.currentGCVersion : 0,
|
|
760
569
|
gcFeatureMatrix: this.persistedGcFeatureMatrix,
|
|
761
570
|
sessionExpiryTimeoutMs: this.sessionExpiryTimeoutMs,
|
|
762
571
|
sweepEnabled: this.sweepEnabled,
|
|
@@ -775,48 +584,22 @@ class GarbageCollector {
|
|
|
775
584
|
* is downloaded and should be used to update the state.
|
|
776
585
|
*/
|
|
777
586
|
async refreshLatestSummary(proposalHandle, result, readAndParseBlob) {
|
|
778
|
-
|
|
779
|
-
// summary
|
|
780
|
-
//
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
this.latestSummaryGCVersion = this.currentGCVersion;
|
|
792
|
-
if (this.trackGCState) {
|
|
793
|
-
this.latestSummaryData = this.pendingSummaryData;
|
|
794
|
-
this.pendingSummaryData = undefined;
|
|
587
|
+
const latestSnapshotData = await this.summaryStateTracker.refreshLatestSummary(proposalHandle, result, readAndParseBlob);
|
|
588
|
+
// If the latest summary was updated but it was not tracked by this client, our state needs to be updated from
|
|
589
|
+
// this snapshot data.
|
|
590
|
+
if (this.shouldRunGC && result.latestSummaryUpdated && !result.wasSummaryTracked) {
|
|
591
|
+
// The current reference timestamp should be available if we are refreshing state from a snapshot. There has
|
|
592
|
+
// to be at least one op (summary op / ack, if nothing else) if a snapshot was taken.
|
|
593
|
+
const currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();
|
|
594
|
+
if (currentReferenceTimestampMs === undefined) {
|
|
595
|
+
throw container_utils_1.DataProcessingError.create("No reference timestamp when updating GC state from snapshot", "refreshLatestSummary", undefined, {
|
|
596
|
+
proposalHandle,
|
|
597
|
+
summaryRefSeq: result.summaryRefSeq,
|
|
598
|
+
details: JSON.stringify(this.configs),
|
|
599
|
+
});
|
|
795
600
|
}
|
|
796
|
-
|
|
797
|
-
}
|
|
798
|
-
// If the summary was not tracked by this client, the state should be updated from the downloaded snapshot.
|
|
799
|
-
const snapshotTree = result.snapshotTree;
|
|
800
|
-
const metadataBlobId = snapshotTree.blobs[summaryFormat_1.metadataBlobName];
|
|
801
|
-
if (metadataBlobId) {
|
|
802
|
-
const metadata = await readAndParseBlob(metadataBlobId);
|
|
803
|
-
this.latestSummaryGCVersion = (0, summaryFormat_1.getGCVersion)(metadata);
|
|
804
|
-
}
|
|
805
|
-
// The current reference timestamp should be available if we are refreshing state from a snapshot. There has
|
|
806
|
-
// to be at least one op (summary op / ack, if nothing else) if a snapshot was taken.
|
|
807
|
-
const currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();
|
|
808
|
-
if (currentReferenceTimestampMs === undefined) {
|
|
809
|
-
throw container_utils_1.DataProcessingError.create("No reference timestamp when updating GC state from snapshot", "refreshLatestSummary", undefined, { proposalHandle, summaryRefSeq: result.summaryRefSeq, details: JSON.stringify(this.configs) });
|
|
601
|
+
this.updateStateFromSnapshotData(latestSnapshotData, currentReferenceTimestampMs);
|
|
810
602
|
}
|
|
811
|
-
const gcSnapshotTree = snapshotTree.trees[runtime_definitions_1.gcTreeKey];
|
|
812
|
-
// If GC ran in the container that generated this snapshot, it will have a GC tree.
|
|
813
|
-
this.wasGCRunInLatestSummary = gcSnapshotTree !== undefined;
|
|
814
|
-
let latestGCData;
|
|
815
|
-
if (gcSnapshotTree !== undefined) {
|
|
816
|
-
latestGCData = await (0, garbage_collector_1.getGCDataFromSnapshot)(gcSnapshotTree, readAndParseBlob);
|
|
817
|
-
}
|
|
818
|
-
this.updateStateFromSnapshotData(latestGCData, currentReferenceTimestampMs);
|
|
819
|
-
this.pendingSummaryData = undefined;
|
|
820
603
|
}
|
|
821
604
|
/**
|
|
822
605
|
* Called when a node with the given id is updated. If the node is inactive, log an error.
|
|
@@ -831,7 +614,7 @@ class GarbageCollector {
|
|
|
831
614
|
return;
|
|
832
615
|
}
|
|
833
616
|
const nodeStateTracker = this.unreferencedNodesState.get(nodePath);
|
|
834
|
-
if (nodeStateTracker && nodeStateTracker.state !==
|
|
617
|
+
if (nodeStateTracker && nodeStateTracker.state !== gcDefinitions_1.UnreferencedState.Active) {
|
|
835
618
|
this.inactiveNodeUsed(reason, nodePath, nodeStateTracker, undefined /* fromNodeId */, packagePath, timestampMs, requestHeaders);
|
|
836
619
|
}
|
|
837
620
|
}
|
|
@@ -851,24 +634,24 @@ class GarbageCollector {
|
|
|
851
634
|
outboundRoutes.push(toNodePath);
|
|
852
635
|
this.newReferencesSinceLastRun.set(fromNodePath, outboundRoutes);
|
|
853
636
|
const nodeStateTracker = this.unreferencedNodesState.get(toNodePath);
|
|
854
|
-
if (nodeStateTracker && nodeStateTracker.state !==
|
|
637
|
+
if (nodeStateTracker && nodeStateTracker.state !== gcDefinitions_1.UnreferencedState.Active) {
|
|
855
638
|
this.inactiveNodeUsed("Revived", toNodePath, nodeStateTracker, fromNodePath);
|
|
856
639
|
}
|
|
857
640
|
if (this.tombstones.includes(toNodePath)) {
|
|
858
641
|
const nodeType = this.runtime.getNodeType(toNodePath);
|
|
859
642
|
let eventName = "GC_Tombstone_SubDatastore_Revived";
|
|
860
|
-
if (nodeType ===
|
|
643
|
+
if (nodeType === gcDefinitions_1.GCNodeType.DataStore) {
|
|
861
644
|
eventName = "GC_Tombstone_Datastore_Revived";
|
|
862
645
|
}
|
|
863
|
-
else if (nodeType ===
|
|
646
|
+
else if (nodeType === gcDefinitions_1.GCNodeType.Blob) {
|
|
864
647
|
eventName = "GC_Tombstone_Blob_Revived";
|
|
865
648
|
}
|
|
866
|
-
(0,
|
|
649
|
+
(0, gcHelpers_1.sendGCUnexpectedUsageEvent)(this.mc, {
|
|
867
650
|
eventName,
|
|
868
651
|
category: "generic",
|
|
869
|
-
isSummarizerClient: this.isSummarizerClient,
|
|
870
652
|
url: (0, garbage_collector_1.trimLeadingSlashes)(toNodePath),
|
|
871
653
|
nodeType,
|
|
654
|
+
gcTombstoneEnforcementAllowed: this.runtime.gcTombstoneEnforcementAllowed,
|
|
872
655
|
}, undefined /* packagePath */);
|
|
873
656
|
}
|
|
874
657
|
}
|
|
@@ -892,13 +675,16 @@ class GarbageCollector {
|
|
|
892
675
|
* @param gcData - The data representing the reference graph on which GC is run.
|
|
893
676
|
* @param gcResult - The result of the GC run on the gcData.
|
|
894
677
|
* @param currentReferenceTimestampMs - The timestamp to be used for unreferenced nodes' timestamp.
|
|
678
|
+
* @returns - A list of sweep ready nodes. (Nodes ready to be deleted)
|
|
895
679
|
*/
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
680
|
+
updateMarkPhase(gcData, gcResult, currentReferenceTimestampMs, logger) {
|
|
681
|
+
var _a;
|
|
682
|
+
// Get references from the current GC run + references between previous and current run and then update each
|
|
683
|
+
// node's state
|
|
684
|
+
const allNodesReferencedBetweenGCs = (_a = this.findAllNodesReferencedBetweenGCs(gcData, this.gcDataFromLastRun, logger)) !== null && _a !== void 0 ? _a : gcResult.referencedNodeIds;
|
|
899
685
|
this.newReferencesSinceLastRun.clear();
|
|
900
686
|
// Iterate through the referenced nodes and stop tracking if they were unreferenced before.
|
|
901
|
-
for (const nodeId of
|
|
687
|
+
for (const nodeId of allNodesReferencedBetweenGCs) {
|
|
902
688
|
const nodeStateTracker = this.unreferencedNodesState.get(nodeId);
|
|
903
689
|
if (nodeStateTracker !== undefined) {
|
|
904
690
|
// Stop tracking so as to clear out any running timers.
|
|
@@ -911,22 +697,62 @@ class GarbageCollector {
|
|
|
911
697
|
* If a node became unreferenced in this run, start tracking it.
|
|
912
698
|
* If a node was already unreferenced, update its tracking information. Since the current reference time is
|
|
913
699
|
* from the ops seen, this will ensure that we keep updating the unreferenced state as time moves forward.
|
|
700
|
+
*
|
|
701
|
+
* If a node is sweep ready, store and then return it.
|
|
914
702
|
*/
|
|
703
|
+
const sweepReadyNodes = [];
|
|
915
704
|
for (const nodeId of gcResult.deletedNodeIds) {
|
|
916
705
|
const nodeStateTracker = this.unreferencedNodesState.get(nodeId);
|
|
917
706
|
if (nodeStateTracker === undefined) {
|
|
918
|
-
this.unreferencedNodesState.set(nodeId, new UnreferencedStateTracker(currentReferenceTimestampMs, this.inactiveTimeoutMs, currentReferenceTimestampMs, this.sweepTimeoutMs));
|
|
707
|
+
this.unreferencedNodesState.set(nodeId, new gcUnreferencedStateTracker_1.UnreferencedStateTracker(currentReferenceTimestampMs, this.inactiveTimeoutMs, currentReferenceTimestampMs, this.sweepTimeoutMs));
|
|
919
708
|
}
|
|
920
709
|
else {
|
|
921
710
|
nodeStateTracker.updateTracking(currentReferenceTimestampMs);
|
|
922
|
-
if (
|
|
923
|
-
|
|
924
|
-
if (nodeType === exports.GCNodeType.DataStore || nodeType === exports.GCNodeType.Blob) {
|
|
925
|
-
this.tombstones.push(nodeId);
|
|
926
|
-
}
|
|
711
|
+
if (nodeStateTracker.state === gcDefinitions_1.UnreferencedState.SweepReady) {
|
|
712
|
+
sweepReadyNodes.push(nodeId);
|
|
927
713
|
}
|
|
928
714
|
}
|
|
929
715
|
}
|
|
716
|
+
return sweepReadyNodes;
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Deletes nodes from both the runtime and garbage collection
|
|
720
|
+
* @param sweepReadyNodes - nodes that are ready to be deleted
|
|
721
|
+
*/
|
|
722
|
+
runSweepPhase(sweepReadyNodes, gcData) {
|
|
723
|
+
// TODO: GC:Validation - validate that removed routes are not double deleted
|
|
724
|
+
// TODO: GC:Validation - validate that the child routes of removed routes are deleted as well
|
|
725
|
+
const sweptRoutes = this.runtime.deleteSweepReadyNodes(sweepReadyNodes);
|
|
726
|
+
const updatedGCData = this.deleteSweptRoutes(sweptRoutes, gcData);
|
|
727
|
+
for (const nodeId of sweptRoutes) {
|
|
728
|
+
const nodeStateTracker = this.unreferencedNodesState.get(nodeId);
|
|
729
|
+
// TODO: GC:Validation - assert that the nodeStateTracker is defined
|
|
730
|
+
if (nodeStateTracker !== undefined) {
|
|
731
|
+
// Stop tracking so as to clear out any running timers.
|
|
732
|
+
nodeStateTracker.stopTracking();
|
|
733
|
+
// Delete the node as we don't need to track it any more.
|
|
734
|
+
this.unreferencedNodesState.delete(nodeId);
|
|
735
|
+
}
|
|
736
|
+
// TODO: GC:Validation - assert that the deleted node is not a duplicate
|
|
737
|
+
this.deletedNodes.add(nodeId);
|
|
738
|
+
}
|
|
739
|
+
return updatedGCData;
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* @returns IGarbageCollectionData after deleting the sweptRoutes from the gcData
|
|
743
|
+
*/
|
|
744
|
+
deleteSweptRoutes(sweptRoutes, gcData) {
|
|
745
|
+
const sweptRoutesSet = new Set(sweptRoutes);
|
|
746
|
+
const gcNodes = {};
|
|
747
|
+
for (const [id, outboundRoutes] of Object.entries(gcData.gcNodes)) {
|
|
748
|
+
if (!sweptRoutesSet.has(id)) {
|
|
749
|
+
gcNodes[id] = Array.from(outboundRoutes);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
// TODO: GC:Validation - assert that the nodeId is in gcData
|
|
753
|
+
return {
|
|
754
|
+
gcNodes,
|
|
755
|
+
};
|
|
930
756
|
}
|
|
931
757
|
/**
|
|
932
758
|
* Since GC runs periodically, the GC data that is generated only tells us the state of the world at that point in
|
|
@@ -938,16 +764,19 @@ class GarbageCollector {
|
|
|
938
764
|
* 2. A reference is added from one unreferenced node to one or more unreferenced nodes. Even though the node[s] were
|
|
939
765
|
* unreferenced, they could have been accessed and in-memory reference to them added.
|
|
940
766
|
*
|
|
941
|
-
* This function identifies nodes that were referenced since last run
|
|
767
|
+
* This function identifies nodes that were referenced since the last run.
|
|
942
768
|
* If these nodes are currently unreferenced, they will be assigned new unreferenced state by the current run.
|
|
769
|
+
*
|
|
770
|
+
* @returns - a list of all nodes referenced from the last local summary until now.
|
|
943
771
|
*/
|
|
944
|
-
|
|
772
|
+
findAllNodesReferencedBetweenGCs(currentGCData, previousGCData, logger) {
|
|
945
773
|
// If we haven't run GC before there is nothing to do.
|
|
946
|
-
|
|
947
|
-
|
|
774
|
+
// No previousGCData, means nothing is unreferenced, and there are no reference state trackers to clear
|
|
775
|
+
if (previousGCData === undefined) {
|
|
776
|
+
return undefined;
|
|
948
777
|
}
|
|
949
778
|
// Find any references that haven't been identified correctly.
|
|
950
|
-
const missingExplicitReferences = this.findMissingExplicitReferences(currentGCData,
|
|
779
|
+
const missingExplicitReferences = this.findMissingExplicitReferences(currentGCData, previousGCData, this.newReferencesSinceLastRun);
|
|
951
780
|
if (missingExplicitReferences.length > 0) {
|
|
952
781
|
missingExplicitReferences.forEach((missingExplicitReference) => {
|
|
953
782
|
logger.sendErrorEvent({
|
|
@@ -958,9 +787,9 @@ class GarbageCollector {
|
|
|
958
787
|
});
|
|
959
788
|
}
|
|
960
789
|
// No references were added since the last run so we don't have to update reference states of any unreferenced
|
|
961
|
-
// nodes
|
|
790
|
+
// nodes. There is no in between state at this point.
|
|
962
791
|
if (this.newReferencesSinceLastRun.size === 0) {
|
|
963
|
-
return;
|
|
792
|
+
return undefined;
|
|
964
793
|
}
|
|
965
794
|
/**
|
|
966
795
|
* Generate a super set of the GC data that contains the nodes and edges from last run, plus any new node and
|
|
@@ -978,7 +807,7 @@ class GarbageCollector {
|
|
|
978
807
|
* - We don't require DDSes handles to be stored in a referenced DDS.
|
|
979
808
|
* - A new data store may have "root" DDSes already created and we don't detect them today.
|
|
980
809
|
*/
|
|
981
|
-
const gcDataSuperSet = (0, garbage_collector_1.concatGarbageCollectionData)(
|
|
810
|
+
const gcDataSuperSet = (0, garbage_collector_1.concatGarbageCollectionData)(previousGCData, currentGCData);
|
|
982
811
|
const newOutboundRoutesSinceLastRun = [];
|
|
983
812
|
this.newReferencesSinceLastRun.forEach((outboundRoutes, sourceNodeId) => {
|
|
984
813
|
if (gcDataSuperSet.gcNodes[sourceNodeId] === undefined) {
|
|
@@ -996,16 +825,11 @@ class GarbageCollector {
|
|
|
996
825
|
* Note that some of these nodes may be unreferenced now and if so, the current run will mark them as
|
|
997
826
|
* unreferenced and add unreferenced state.
|
|
998
827
|
*/
|
|
999
|
-
const gcResult = (0, garbage_collector_1.runGarbageCollection)(gcDataSuperSet.gcNodes, [
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
nodeStateTracker.stopTracking();
|
|
1005
|
-
// Delete the unreferenced state as we don't need to track it any more.
|
|
1006
|
-
this.unreferencedNodesState.delete(nodeId);
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
828
|
+
const gcResult = (0, garbage_collector_1.runGarbageCollection)(gcDataSuperSet.gcNodes, [
|
|
829
|
+
"/",
|
|
830
|
+
...newOutboundRoutesSinceLastRun,
|
|
831
|
+
]);
|
|
832
|
+
return gcResult.referencedNodeIds;
|
|
1009
833
|
}
|
|
1010
834
|
/**
|
|
1011
835
|
* Finds all new references or outbound routes in the current graph that haven't been explicitly notified to GC.
|
|
@@ -1021,7 +845,7 @@ class GarbageCollector {
|
|
|
1021
845
|
* @returns - a list of missing explicit references
|
|
1022
846
|
*/
|
|
1023
847
|
findMissingExplicitReferences(currentGCData, previousGCData, explicitReferences) {
|
|
1024
|
-
(0, common_utils_1.assert)(previousGCData !== undefined, 0x2b7);
|
|
848
|
+
(0, common_utils_1.assert)(previousGCData !== undefined, 0x2b7 /* "Can't validate correctness without GC data from last run" */);
|
|
1025
849
|
const currentGraph = Object.entries(currentGCData.gcNodes);
|
|
1026
850
|
const missingExplicitReferences = [];
|
|
1027
851
|
currentGraph.forEach(([nodeId, currentOutboundRoutes]) => {
|
|
@@ -1039,9 +863,10 @@ class GarbageCollector {
|
|
|
1039
863
|
*/
|
|
1040
864
|
currentOutboundRoutes.forEach((route) => {
|
|
1041
865
|
const nodeType = this.runtime.getNodeType(route);
|
|
1042
|
-
if ((nodeType ===
|
|
1043
|
-
|
|
1044
|
-
|
|
866
|
+
if ((nodeType === gcDefinitions_1.GCNodeType.DataStore || nodeType === gcDefinitions_1.GCNodeType.Blob) &&
|
|
867
|
+
!nodeId.startsWith(route) &&
|
|
868
|
+
!previousRoutes.includes(route) &&
|
|
869
|
+
!explicitRoutes.includes(route)) {
|
|
1045
870
|
missingExplicitRoutes.push(route);
|
|
1046
871
|
}
|
|
1047
872
|
});
|
|
@@ -1081,7 +906,7 @@ class GarbageCollector {
|
|
|
1081
906
|
if (!referenced) {
|
|
1082
907
|
gcStats.unrefNodeCount++;
|
|
1083
908
|
}
|
|
1084
|
-
if (this.runtime.getNodeType(nodeId) ===
|
|
909
|
+
if (this.runtime.getNodeType(nodeId) === gcDefinitions_1.GCNodeType.DataStore) {
|
|
1085
910
|
gcStats.dataStoreCount++;
|
|
1086
911
|
if (stateUpdated) {
|
|
1087
912
|
gcStats.updatedDataStoreCount++;
|
|
@@ -1090,7 +915,7 @@ class GarbageCollector {
|
|
|
1090
915
|
gcStats.unrefDataStoreCount++;
|
|
1091
916
|
}
|
|
1092
917
|
}
|
|
1093
|
-
if (this.runtime.getNodeType(nodeId) ===
|
|
918
|
+
if (this.runtime.getNodeType(nodeId) === gcDefinitions_1.GCNodeType.Blob) {
|
|
1094
919
|
gcStats.attachmentBlobCount++;
|
|
1095
920
|
if (stateUpdated) {
|
|
1096
921
|
gcStats.updatedAttachmentBlobCount++;
|
|
@@ -1113,15 +938,16 @@ class GarbageCollector {
|
|
|
1113
938
|
* this will give us a view into how much deleted content a container has.
|
|
1114
939
|
*/
|
|
1115
940
|
logSweepEvents(logger, currentReferenceTimestampMs) {
|
|
1116
|
-
if (this.mc.config.getBoolean(
|
|
941
|
+
if (this.mc.config.getBoolean(gcDefinitions_1.disableSweepLogKey) === true ||
|
|
942
|
+
this.sweepTimeoutMs === undefined) {
|
|
1117
943
|
return;
|
|
1118
944
|
}
|
|
1119
945
|
this.unreferencedNodesState.forEach((nodeStateTracker, nodeId) => {
|
|
1120
|
-
if (nodeStateTracker.state !==
|
|
946
|
+
if (nodeStateTracker.state !== gcDefinitions_1.UnreferencedState.SweepReady) {
|
|
1121
947
|
return;
|
|
1122
948
|
}
|
|
1123
949
|
const nodeType = this.runtime.getNodeType(nodeId);
|
|
1124
|
-
if (nodeType !==
|
|
950
|
+
if (nodeType !== gcDefinitions_1.GCNodeType.DataStore && nodeType !== gcDefinitions_1.GCNodeType.Blob) {
|
|
1125
951
|
return;
|
|
1126
952
|
}
|
|
1127
953
|
// Log deleted event for each node only once to reduce noise in telemetry.
|
|
@@ -1148,13 +974,14 @@ class GarbageCollector {
|
|
|
1148
974
|
// If there is no reference timestamp to work with, no ops have been processed after creation. If so, skip
|
|
1149
975
|
// logging as nothing interesting would have happened worth logging.
|
|
1150
976
|
// If the node is active, skip logging.
|
|
1151
|
-
if (currentReferenceTimestampMs === undefined ||
|
|
977
|
+
if (currentReferenceTimestampMs === undefined ||
|
|
978
|
+
nodeStateTracker.state === gcDefinitions_1.UnreferencedState.Active) {
|
|
1152
979
|
return;
|
|
1153
980
|
}
|
|
1154
981
|
// We only care about data stores and attachment blobs for this telemetry since GC only marks these objects
|
|
1155
982
|
// as unreferenced. Also, if an inactive DDS is used, the corresponding data store store will also be used.
|
|
1156
983
|
const nodeType = this.runtime.getNodeType(nodeId);
|
|
1157
|
-
if (nodeType !==
|
|
984
|
+
if (nodeType !== gcDefinitions_1.GCNodeType.DataStore && nodeType !== gcDefinitions_1.GCNodeType.Blob) {
|
|
1158
985
|
return;
|
|
1159
986
|
}
|
|
1160
987
|
const state = nodeStateTracker.state;
|
|
@@ -1163,9 +990,9 @@ class GarbageCollector {
|
|
|
1163
990
|
return;
|
|
1164
991
|
}
|
|
1165
992
|
this.loggedUnreferencedEvents.add(uniqueEventId);
|
|
1166
|
-
const propsToLog = Object.assign(Object.assign({ id: nodeId, type: nodeType, unrefTime: nodeStateTracker.unreferencedTimestampMs, age: currentReferenceTimestampMs - nodeStateTracker.unreferencedTimestampMs, timeout: nodeStateTracker.state ===
|
|
993
|
+
const propsToLog = Object.assign(Object.assign({ id: nodeId, type: nodeType, unrefTime: nodeStateTracker.unreferencedTimestampMs, age: currentReferenceTimestampMs - nodeStateTracker.unreferencedTimestampMs, timeout: nodeStateTracker.state === gcDefinitions_1.UnreferencedState.Inactive
|
|
1167
994
|
? this.inactiveTimeoutMs
|
|
1168
|
-
: this.sweepTimeoutMs, completedGCRuns: this.completedRuns, lastSummaryTime: this.getLastSummaryTimestampMs() }, this.createContainerMetadata), {
|
|
995
|
+
: this.sweepTimeoutMs, completedGCRuns: this.completedRuns, lastSummaryTime: this.getLastSummaryTimestampMs() }, this.createContainerMetadata), { viaHandle: requestHeaders === null || requestHeaders === void 0 ? void 0 : requestHeaders[containerRuntime_1.RuntimeHeaders.viaHandle], fromId: fromNodeId });
|
|
1169
996
|
// For summarizer client, queue the event so it is logged the next time GC runs if the event is still valid.
|
|
1170
997
|
// For non-summarizer client, log the event now since GC won't run on it. This may result in false positives
|
|
1171
998
|
// but it's a good signal nonetheless and we can consume it with a grain of salt.
|
|
@@ -1183,7 +1010,7 @@ class GarbageCollector {
|
|
|
1183
1010
|
const event = Object.assign(Object.assign({}, propsToLog), { eventName: `${state}Object_${usageType}`, pkg: (0, runtime_utils_1.packagePathToTelemetryProperty)(packagePath), stack: (0, telemetry_utils_1.generateStack)() });
|
|
1184
1011
|
// Do not log the inactive object x events as error events as they are not the best signal for
|
|
1185
1012
|
// detecting something wrong with GC either from the partner or from the runtime itself.
|
|
1186
|
-
if (state ===
|
|
1013
|
+
if (state === gcDefinitions_1.UnreferencedState.Inactive) {
|
|
1187
1014
|
this.mc.logger.sendTelemetryEvent(event);
|
|
1188
1015
|
}
|
|
1189
1016
|
else {
|
|
@@ -1193,7 +1020,7 @@ class GarbageCollector {
|
|
|
1193
1020
|
// If SweepReady Usage Detection is enabled, the handler may close the interactive container.
|
|
1194
1021
|
// Once Sweep is fully implemented, this will be removed since the objects will be gone
|
|
1195
1022
|
// and errors will arise elsewhere in the runtime
|
|
1196
|
-
if (state ===
|
|
1023
|
+
if (state === gcDefinitions_1.UnreferencedState.SweepReady) {
|
|
1197
1024
|
this.sweepReadyUsageHandler.usageDetectedInInteractiveClient(Object.assign(Object.assign({}, propsToLog), { usageType }));
|
|
1198
1025
|
}
|
|
1199
1026
|
}
|
|
@@ -1213,12 +1040,19 @@ class GarbageCollector {
|
|
|
1213
1040
|
* revived and a Revived event will be logged for it.
|
|
1214
1041
|
*/
|
|
1215
1042
|
const nodeStateTracker = this.unreferencedNodesState.get(eventProps.id);
|
|
1216
|
-
const active = nodeStateTracker === undefined ||
|
|
1043
|
+
const active = nodeStateTracker === undefined ||
|
|
1044
|
+
nodeStateTracker.state === gcDefinitions_1.UnreferencedState.Active;
|
|
1217
1045
|
if ((usageType === "Revived") === active) {
|
|
1218
1046
|
const pkg = await this.getNodePackagePath(eventProps.id);
|
|
1219
|
-
const fromPkg = eventProps.fromId
|
|
1220
|
-
|
|
1221
|
-
|
|
1047
|
+
const fromPkg = eventProps.fromId
|
|
1048
|
+
? await this.getNodePackagePath(eventProps.fromId)
|
|
1049
|
+
: undefined;
|
|
1050
|
+
const event = Object.assign(Object.assign({}, propsToLog), { eventName: `${state}Object_${usageType}`, pkg: pkg
|
|
1051
|
+
? { value: pkg.join("/"), tag: telemetry_utils_1.TelemetryDataTag.CodeArtifact }
|
|
1052
|
+
: undefined, fromPkg: fromPkg
|
|
1053
|
+
? { value: fromPkg.join("/"), tag: telemetry_utils_1.TelemetryDataTag.CodeArtifact }
|
|
1054
|
+
: undefined });
|
|
1055
|
+
if (state === gcDefinitions_1.UnreferencedState.Inactive) {
|
|
1222
1056
|
logger.sendTelemetryEvent(event);
|
|
1223
1057
|
}
|
|
1224
1058
|
else {
|
|
@@ -1230,28 +1064,4 @@ class GarbageCollector {
|
|
|
1230
1064
|
}
|
|
1231
1065
|
}
|
|
1232
1066
|
exports.GarbageCollector = GarbageCollector;
|
|
1233
|
-
function generateSortedGCState(gcState) {
|
|
1234
|
-
const sortableArray = Object.entries(gcState.gcNodes);
|
|
1235
|
-
sortableArray.sort(([a], [b]) => a.localeCompare(b));
|
|
1236
|
-
const sortedGCState = { gcNodes: {} };
|
|
1237
|
-
for (const [nodeId, nodeData] of sortableArray) {
|
|
1238
|
-
nodeData.outboundRoutes.sort();
|
|
1239
|
-
sortedGCState.gcNodes[nodeId] = nodeData;
|
|
1240
|
-
}
|
|
1241
|
-
return sortedGCState;
|
|
1242
|
-
}
|
|
1243
|
-
/** A wrapper around common-utils Timer that requires the timeout when calling start/restart */
|
|
1244
|
-
class TimerWithNoDefaultTimeout extends common_utils_1.Timer {
|
|
1245
|
-
constructor(callback) {
|
|
1246
|
-
// The default timeout/handlers will never be used since start/restart pass overrides below
|
|
1247
|
-
super(0, () => { throw new Error("DefaultHandler should not be used"); });
|
|
1248
|
-
this.callback = callback;
|
|
1249
|
-
}
|
|
1250
|
-
start(timeoutMs) {
|
|
1251
|
-
super.start(timeoutMs, this.callback);
|
|
1252
|
-
}
|
|
1253
|
-
restart(timeoutMs) {
|
|
1254
|
-
super.restart(timeoutMs, this.callback);
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1257
1067
|
//# sourceMappingURL=garbageCollection.js.map
|