@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,1349 +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 sinon from "sinon";
|
|
7
|
-
import { Deferred } from "@fluidframework/core-utils";
|
|
8
|
-
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
9
|
-
import { MessageType, SummaryType, } from "@fluidframework/protocol-definitions";
|
|
10
|
-
import { MockLogger, mixinMonitoringContext } from "@fluidframework/telemetry-utils";
|
|
11
|
-
import { MockDeltaManager } from "@fluidframework/test-runtime-utils";
|
|
12
|
-
import { isRuntimeMessage } from "@fluidframework/driver-utils";
|
|
13
|
-
import { getFailMessage, neverCancelledSummaryToken, RunningSummarizer, SummaryCollection, SummarizeHeuristicData, RetriableSummaryError, } from "../../summary/index.js";
|
|
14
|
-
import { defaultMaxAttempts, defaultMaxAttemptsForSubmitFailures,
|
|
15
|
-
// eslint-disable-next-line import/no-internal-modules
|
|
16
|
-
} from "../../summary/runningSummarizer.js";
|
|
17
|
-
class MockRuntime extends TypedEventEmitter {
|
|
18
|
-
constructor(deltaManager) {
|
|
19
|
-
super();
|
|
20
|
-
this.deltaManager = deltaManager;
|
|
21
|
-
this.disposed = false;
|
|
22
|
-
}
|
|
23
|
-
closeFn() {
|
|
24
|
-
this.disposed = true;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
const configProvider = (settings) => ({
|
|
28
|
-
getRawConfig: (name) => settings[name],
|
|
29
|
-
});
|
|
30
|
-
describe("Runtime", () => {
|
|
31
|
-
describe("Summarization", () => {
|
|
32
|
-
describe("RunningSummarizer", () => {
|
|
33
|
-
let stopCall;
|
|
34
|
-
let runCount;
|
|
35
|
-
let fullTreeRunCount;
|
|
36
|
-
let refreshLatestAckRunCount;
|
|
37
|
-
let clock;
|
|
38
|
-
let mockLogger;
|
|
39
|
-
let settings = {};
|
|
40
|
-
let mockDeltaManager;
|
|
41
|
-
let summaryCollection;
|
|
42
|
-
let summarizer;
|
|
43
|
-
const summarizerClientId = "test";
|
|
44
|
-
let lastRefSeq = 0;
|
|
45
|
-
let lastClientSeq;
|
|
46
|
-
let lastSummarySeq;
|
|
47
|
-
let mockRuntime;
|
|
48
|
-
let heuristicData;
|
|
49
|
-
const summaryCommon = {
|
|
50
|
-
maxAckWaitTime: 120000,
|
|
51
|
-
maxOpsSinceLastSummary: 7000,
|
|
52
|
-
initialSummarizerDelayMs: 0,
|
|
53
|
-
};
|
|
54
|
-
const summaryConfig = {
|
|
55
|
-
state: "enabled",
|
|
56
|
-
maxTime: 5000 * 12,
|
|
57
|
-
maxOps: 1000,
|
|
58
|
-
minOpsForLastSummaryAttempt: 50,
|
|
59
|
-
minIdleTime: 5000,
|
|
60
|
-
maxIdleTime: 5000,
|
|
61
|
-
nonRuntimeOpWeight: 0.1,
|
|
62
|
-
runtimeOpWeight: 1.0,
|
|
63
|
-
nonRuntimeHeuristicThreshold: 20,
|
|
64
|
-
...summaryCommon,
|
|
65
|
-
};
|
|
66
|
-
const summaryConfigDisableHeuristics = {
|
|
67
|
-
state: "disableHeuristics",
|
|
68
|
-
...summaryCommon,
|
|
69
|
-
};
|
|
70
|
-
const emptySummaryStats = {
|
|
71
|
-
treeNodeCount: 0,
|
|
72
|
-
blobNodeCount: 0,
|
|
73
|
-
handleNodeCount: 0,
|
|
74
|
-
totalBlobSize: 0,
|
|
75
|
-
dataStoreCount: 0,
|
|
76
|
-
summarizedDataStoreCount: 0,
|
|
77
|
-
unreferencedBlobSize: 0,
|
|
78
|
-
summaryNumber: 0,
|
|
79
|
-
};
|
|
80
|
-
let shouldDeferGenerateSummary = false;
|
|
81
|
-
let deferGenerateSummary;
|
|
82
|
-
const flushPromises = async () => new Promise((resolve) => process.nextTick(resolve));
|
|
83
|
-
async function emitNextOp(increment = 1, timestamp = Date.now(), type = MessageType.Operation) {
|
|
84
|
-
heuristicData.numRuntimeOps += increment - 1; // -1 because we emit an op below
|
|
85
|
-
lastRefSeq += increment;
|
|
86
|
-
const op = {
|
|
87
|
-
sequenceNumber: lastRefSeq,
|
|
88
|
-
timestamp,
|
|
89
|
-
type,
|
|
90
|
-
};
|
|
91
|
-
mockDeltaManager.emit("op", op);
|
|
92
|
-
mockRuntime.emit("op", op, isRuntimeMessage({ type }));
|
|
93
|
-
await flushPromises();
|
|
94
|
-
}
|
|
95
|
-
async function emitNoOp(increment = 1) {
|
|
96
|
-
heuristicData.numNonRuntimeOps += increment - 1; // -1 because we emit an op below
|
|
97
|
-
lastRefSeq += increment;
|
|
98
|
-
const op = {
|
|
99
|
-
sequenceNumber: lastRefSeq,
|
|
100
|
-
timestamp: Date.now(),
|
|
101
|
-
type: MessageType.NoOp,
|
|
102
|
-
};
|
|
103
|
-
mockDeltaManager.emit("op", op);
|
|
104
|
-
mockRuntime.emit("op", op, isRuntimeMessage({ type: MessageType.NoOp }));
|
|
105
|
-
await flushPromises();
|
|
106
|
-
}
|
|
107
|
-
function emitBroadcast(timestamp = Date.now()) {
|
|
108
|
-
const referenceSequenceNumber = lastRefSeq;
|
|
109
|
-
lastSummarySeq = ++lastRefSeq;
|
|
110
|
-
const op = {
|
|
111
|
-
type: MessageType.Summarize,
|
|
112
|
-
clientId: summarizerClientId,
|
|
113
|
-
referenceSequenceNumber,
|
|
114
|
-
clientSequenceNumber: ++lastClientSeq,
|
|
115
|
-
sequenceNumber: lastSummarySeq,
|
|
116
|
-
contents: {
|
|
117
|
-
handle: "test-broadcast-handle",
|
|
118
|
-
},
|
|
119
|
-
timestamp,
|
|
120
|
-
};
|
|
121
|
-
mockDeltaManager.emit("op", op);
|
|
122
|
-
mockRuntime.emit("op", op, isRuntimeMessage(op));
|
|
123
|
-
}
|
|
124
|
-
async function emitAck() {
|
|
125
|
-
const summaryProposal = {
|
|
126
|
-
summarySequenceNumber: lastSummarySeq,
|
|
127
|
-
};
|
|
128
|
-
const contents = {
|
|
129
|
-
handle: "test-ack-handle",
|
|
130
|
-
summaryProposal,
|
|
131
|
-
};
|
|
132
|
-
const op = {
|
|
133
|
-
data: JSON.stringify(contents),
|
|
134
|
-
type: MessageType.SummaryAck,
|
|
135
|
-
sequenceNumber: ++lastRefSeq,
|
|
136
|
-
};
|
|
137
|
-
mockDeltaManager.emit("op", op);
|
|
138
|
-
mockRuntime.emit("op", op, isRuntimeMessage(op));
|
|
139
|
-
await flushPromises(); // let summarize run
|
|
140
|
-
}
|
|
141
|
-
async function emitNack(retryAfterSeconds) {
|
|
142
|
-
const summaryProposal = {
|
|
143
|
-
summarySequenceNumber: lastSummarySeq,
|
|
144
|
-
};
|
|
145
|
-
const contents = {
|
|
146
|
-
summaryProposal,
|
|
147
|
-
retryAfter: retryAfterSeconds,
|
|
148
|
-
message: "test-nack",
|
|
149
|
-
};
|
|
150
|
-
const op = {
|
|
151
|
-
data: JSON.stringify(contents),
|
|
152
|
-
type: MessageType.SummaryNack,
|
|
153
|
-
sequenceNumber: ++lastRefSeq,
|
|
154
|
-
};
|
|
155
|
-
mockDeltaManager.emit("op", op);
|
|
156
|
-
mockRuntime.emit("op", op, isRuntimeMessage(op));
|
|
157
|
-
await flushPromises();
|
|
158
|
-
}
|
|
159
|
-
async function tickAndFlushPromises(ms) {
|
|
160
|
-
clock.tick(ms);
|
|
161
|
-
await flushPromises();
|
|
162
|
-
}
|
|
163
|
-
function assertRunCounts(expectedTotalRunCount, expectedFullTreeRunCount, expectedRefreshLatestAckRunCount, errorMessage, expectedStopCount = 0) {
|
|
164
|
-
const errorPrefix = errorMessage ? `${errorMessage}: ` : "";
|
|
165
|
-
assert.strictEqual(runCount, expectedTotalRunCount, `${errorPrefix}unexpected total run count`);
|
|
166
|
-
assert.strictEqual(fullTreeRunCount, expectedFullTreeRunCount, `${errorPrefix}unexpected fullTree count`);
|
|
167
|
-
assert.strictEqual(refreshLatestAckRunCount, expectedRefreshLatestAckRunCount, `${errorPrefix}unexpected refreshLatestAck count`);
|
|
168
|
-
assert.strictEqual(stopCall, expectedStopCount, `${errorPrefix}summarizer should${expectedStopCount === 1 ? "" : " not"} have stopped`);
|
|
169
|
-
}
|
|
170
|
-
async function successfulSubmitSummary() {
|
|
171
|
-
// emitBroadcast will increment this number
|
|
172
|
-
const lastRefSeqBefore = lastRefSeq;
|
|
173
|
-
// immediate broadcast
|
|
174
|
-
emitBroadcast();
|
|
175
|
-
if (shouldDeferGenerateSummary) {
|
|
176
|
-
deferGenerateSummary = new Deferred();
|
|
177
|
-
await deferGenerateSummary.promise;
|
|
178
|
-
deferGenerateSummary = undefined;
|
|
179
|
-
}
|
|
180
|
-
return {
|
|
181
|
-
stage: "submit",
|
|
182
|
-
referenceSequenceNumber: lastRefSeqBefore,
|
|
183
|
-
minimumSequenceNumber: 0,
|
|
184
|
-
generateDuration: 0,
|
|
185
|
-
uploadDuration: 0,
|
|
186
|
-
submitOpDuration: 0,
|
|
187
|
-
summaryTree: { type: SummaryType.Tree, tree: {} },
|
|
188
|
-
summaryStats: emptySummaryStats,
|
|
189
|
-
handle: "test-handle",
|
|
190
|
-
clientSequenceNumber: lastClientSeq,
|
|
191
|
-
forcedFullTree: false,
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
const startRunningSummarizer = async (disableHeuristics, submitSummaryCallback = successfulSubmitSummary, cancellationToken = neverCancelledSummaryToken) => {
|
|
195
|
-
heuristicData = new SummarizeHeuristicData(0, {
|
|
196
|
-
refSequenceNumber: 0,
|
|
197
|
-
summaryTime: Date.now(),
|
|
198
|
-
});
|
|
199
|
-
summarizer = await RunningSummarizer.start(mockLogger, summaryCollection.createWatcher(summarizerClientId), disableHeuristics ? summaryConfigDisableHeuristics : summaryConfig, async (options) => {
|
|
200
|
-
runCount++;
|
|
201
|
-
heuristicData.recordAttempt(lastRefSeq);
|
|
202
|
-
const { fullTree = false, refreshLatestAck = false } = options;
|
|
203
|
-
if (fullTree) {
|
|
204
|
-
fullTreeRunCount++;
|
|
205
|
-
}
|
|
206
|
-
if (refreshLatestAck) {
|
|
207
|
-
refreshLatestAckRunCount++;
|
|
208
|
-
}
|
|
209
|
-
return submitSummaryCallback();
|
|
210
|
-
}, async (options) => { }, heuristicData, summaryCollection, cancellationToken,
|
|
211
|
-
// stopSummarizerCallback
|
|
212
|
-
(reason) => {
|
|
213
|
-
stopCall++;
|
|
214
|
-
}, mockRuntime);
|
|
215
|
-
};
|
|
216
|
-
before(() => {
|
|
217
|
-
// eslint-disable-next-line import/no-named-as-default-member
|
|
218
|
-
clock = sinon.useFakeTimers();
|
|
219
|
-
});
|
|
220
|
-
after(() => {
|
|
221
|
-
clock.restore();
|
|
222
|
-
});
|
|
223
|
-
beforeEach(async () => {
|
|
224
|
-
shouldDeferGenerateSummary = false;
|
|
225
|
-
deferGenerateSummary = undefined;
|
|
226
|
-
clock.reset();
|
|
227
|
-
runCount = 0;
|
|
228
|
-
stopCall = 0;
|
|
229
|
-
fullTreeRunCount = 0;
|
|
230
|
-
refreshLatestAckRunCount = 0;
|
|
231
|
-
lastRefSeq = 0;
|
|
232
|
-
lastClientSeq = -1000; // negative/decrement for test
|
|
233
|
-
lastSummarySeq = 0; // negative/decrement for test
|
|
234
|
-
settings = {};
|
|
235
|
-
mockLogger = mixinMonitoringContext(new MockLogger(), configProvider(settings)).logger;
|
|
236
|
-
mockDeltaManager = new MockDeltaManager();
|
|
237
|
-
mockRuntime = new MockRuntime(mockDeltaManager);
|
|
238
|
-
summaryCollection = new SummaryCollection(mockDeltaManager, mockLogger.toTelemetryLogger());
|
|
239
|
-
});
|
|
240
|
-
describe("Summary Schedule", () => {
|
|
241
|
-
beforeEach(async () => {
|
|
242
|
-
await startRunningSummarizer();
|
|
243
|
-
});
|
|
244
|
-
it("Should summarize after configured number of ops when not pending", async () => {
|
|
245
|
-
// too early, should not run yet
|
|
246
|
-
await emitNextOp(summaryConfig.maxOps);
|
|
247
|
-
assertRunCounts(0, 0, 0);
|
|
248
|
-
// now should run
|
|
249
|
-
await emitNextOp(1);
|
|
250
|
-
assertRunCounts(1, 0, 0);
|
|
251
|
-
assert(mockLogger.matchEvents([
|
|
252
|
-
{ eventName: "Running:Summarize_generate", summarizeCount: runCount },
|
|
253
|
-
{ eventName: "Running:Summarize_Op", summarizeCount: runCount },
|
|
254
|
-
]), "unexpected log sequence");
|
|
255
|
-
// should not run, because our summary hasnt been acked/nacked yet
|
|
256
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
257
|
-
assertRunCounts(1, 0, 0);
|
|
258
|
-
// should run, because another op has come in, and our summary has been acked
|
|
259
|
-
await emitAck();
|
|
260
|
-
assertRunCounts(2, 0, 0);
|
|
261
|
-
assert(mockLogger.matchEvents([
|
|
262
|
-
{ eventName: "Running:Summarize_end", summarizeCount: runCount - 1 },
|
|
263
|
-
{ eventName: "Running:Summarize_generate", summarizeCount: runCount },
|
|
264
|
-
{ eventName: "Running:Summarize_Op", summarizeCount: runCount },
|
|
265
|
-
]), "unexpected log sequence");
|
|
266
|
-
await emitNextOp();
|
|
267
|
-
assertRunCounts(2, 0, 0);
|
|
268
|
-
assert(!mockLogger.matchEvents([{ eventName: "Running:Summarize_end" }]), "No ack expected yet");
|
|
269
|
-
});
|
|
270
|
-
it("Should summarize after configured idle time when not pending", async () => {
|
|
271
|
-
await emitNextOp();
|
|
272
|
-
// too early, should not run yet
|
|
273
|
-
await tickAndFlushPromises(summaryConfig.minIdleTime - 1);
|
|
274
|
-
assertRunCounts(0, 0, 0);
|
|
275
|
-
// now should run
|
|
276
|
-
await tickAndFlushPromises(1);
|
|
277
|
-
assertRunCounts(1, 0, 0);
|
|
278
|
-
// should not run, because our summary hasnt been acked/nacked yet
|
|
279
|
-
await emitNextOp();
|
|
280
|
-
await tickAndFlushPromises(summaryConfig.minIdleTime);
|
|
281
|
-
assertRunCounts(1, 0, 0);
|
|
282
|
-
// should run, because another op has come in, and our summary has been acked
|
|
283
|
-
await emitAck();
|
|
284
|
-
await emitNextOp();
|
|
285
|
-
await tickAndFlushPromises(summaryConfig.minIdleTime);
|
|
286
|
-
assertRunCounts(2, 0, 0);
|
|
287
|
-
});
|
|
288
|
-
it("Should summarize after configured active time when not pending", async () => {
|
|
289
|
-
const idlesPerActive = Math.floor((summaryConfig.maxTime + 1) / (summaryConfig.minIdleTime - 1));
|
|
290
|
-
const remainingTime = (summaryConfig.maxTime + 1) % (summaryConfig.minIdleTime - 1);
|
|
291
|
-
await emitNextOp();
|
|
292
|
-
// too early should not run yet
|
|
293
|
-
for (let i = 0; i < idlesPerActive; i++) {
|
|
294
|
-
// prevent idle from triggering with periodic ops
|
|
295
|
-
await tickAndFlushPromises(summaryConfig.minIdleTime - 1);
|
|
296
|
-
await emitNextOp();
|
|
297
|
-
}
|
|
298
|
-
await tickAndFlushPromises(remainingTime - 1);
|
|
299
|
-
await emitNextOp();
|
|
300
|
-
assertRunCounts(0, 0, 0);
|
|
301
|
-
// now should run
|
|
302
|
-
await tickAndFlushPromises(1);
|
|
303
|
-
await emitNextOp();
|
|
304
|
-
assertRunCounts(1, 0, 0);
|
|
305
|
-
// should not run because our summary hasnt been acked/nacked yet
|
|
306
|
-
for (let i = 0; i < idlesPerActive; i++) {
|
|
307
|
-
// prevent idle from triggering with periodic ops
|
|
308
|
-
await tickAndFlushPromises(summaryConfig.minIdleTime - 1);
|
|
309
|
-
await emitNextOp();
|
|
310
|
-
}
|
|
311
|
-
await tickAndFlushPromises(remainingTime);
|
|
312
|
-
await emitNextOp();
|
|
313
|
-
assertRunCounts(1, 0, 0);
|
|
314
|
-
// should run, because another op has come in, and our summary has been acked
|
|
315
|
-
await emitAck();
|
|
316
|
-
await emitNextOp();
|
|
317
|
-
assertRunCounts(2, 0, 0);
|
|
318
|
-
});
|
|
319
|
-
it("Should summarize after pending timeout", async () => {
|
|
320
|
-
// first run to start pending
|
|
321
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
322
|
-
assertRunCounts(1, 0, 0);
|
|
323
|
-
// should not run because still pending
|
|
324
|
-
await tickAndFlushPromises(summaryConfig.maxAckWaitTime - 1);
|
|
325
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
326
|
-
assertRunCounts(1, 0, 0);
|
|
327
|
-
// should run because pending timeout
|
|
328
|
-
await tickAndFlushPromises(1);
|
|
329
|
-
await emitNextOp();
|
|
330
|
-
assertRunCounts(2, 0, 1);
|
|
331
|
-
// verify subsequent ack works
|
|
332
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
333
|
-
assertRunCounts(2, 0, 1);
|
|
334
|
-
await emitAck();
|
|
335
|
-
await emitNextOp();
|
|
336
|
-
assertRunCounts(3, 0, 1);
|
|
337
|
-
});
|
|
338
|
-
it("Should not cause pending ack timeouts using older summary time", async () => {
|
|
339
|
-
shouldDeferGenerateSummary = true;
|
|
340
|
-
await emitNextOp();
|
|
341
|
-
// should do first summary fine
|
|
342
|
-
await emitNextOp(summaryConfig.maxOps);
|
|
343
|
-
assertRunCounts(1, 0, 0);
|
|
344
|
-
assert(deferGenerateSummary !== undefined, "submitSummary was not called");
|
|
345
|
-
deferGenerateSummary.resolve();
|
|
346
|
-
await emitAck();
|
|
347
|
-
// pass time that should not count towards the next max ack wait time
|
|
348
|
-
await tickAndFlushPromises(summaryConfig.maxAckWaitTime);
|
|
349
|
-
// subsequent summary should not cancel pending!
|
|
350
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
351
|
-
assertRunCounts(2, 0, 0);
|
|
352
|
-
await emitNextOp(); // fine
|
|
353
|
-
await tickAndFlushPromises(1); // next op will exceed maxAckWaitTime from first summary
|
|
354
|
-
await emitNextOp(); // not fine, nay cancel pending too soon
|
|
355
|
-
assert(deferGenerateSummary !== undefined, "submitSummary was not called");
|
|
356
|
-
deferGenerateSummary.resolve();
|
|
357
|
-
// we should not generate another summary without previous ack
|
|
358
|
-
await emitNextOp(); // flush finish summarizing
|
|
359
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
360
|
-
assertRunCounts(2, 0, 0);
|
|
361
|
-
});
|
|
362
|
-
it("Should summarize one last time before closing >=min ops", async () => {
|
|
363
|
-
await emitNextOp(summaryConfig.minOpsForLastSummaryAttempt);
|
|
364
|
-
const stopP = summarizer.waitStop(true);
|
|
365
|
-
await flushPromises();
|
|
366
|
-
await emitAck();
|
|
367
|
-
await stopP;
|
|
368
|
-
assertRunCounts(1, 0, 0, "should perform lastSummary");
|
|
369
|
-
});
|
|
370
|
-
it("Should not summarize one last time before closing <min ops", async () => {
|
|
371
|
-
await emitNextOp(summaryConfig.minOpsForLastSummaryAttempt - 1);
|
|
372
|
-
const stopP = summarizer.waitStop(true);
|
|
373
|
-
await flushPromises();
|
|
374
|
-
await emitAck();
|
|
375
|
-
await stopP;
|
|
376
|
-
assertRunCounts(0, 0, 0, "should not perform lastSummary");
|
|
377
|
-
});
|
|
378
|
-
it("Should not summarize when processing summary ack op", async () => {
|
|
379
|
-
await emitNextOp(summaryConfig.maxOps);
|
|
380
|
-
assertRunCounts(0, 0, 0, "should not perform summary");
|
|
381
|
-
await emitAck();
|
|
382
|
-
assertRunCounts(0, 0, 0, "should not perform summary");
|
|
383
|
-
});
|
|
384
|
-
it("Should not summarize when processing summary nack op", async () => {
|
|
385
|
-
await emitNextOp(summaryConfig.maxOps);
|
|
386
|
-
assertRunCounts(0, 0, 0, "should not perform summary");
|
|
387
|
-
await emitNack();
|
|
388
|
-
assertRunCounts(0, 0, 0, "should not perform summary");
|
|
389
|
-
});
|
|
390
|
-
it("Should not summarize when processing summarize op", async () => {
|
|
391
|
-
await emitNextOp(summaryConfig.maxOps);
|
|
392
|
-
assertRunCounts(0, 0, 0, "should not perform summary");
|
|
393
|
-
await emitNextOp(1, Date.now(), MessageType.Summarize);
|
|
394
|
-
assertRunCounts(0, 0, 0, "should not perform summary");
|
|
395
|
-
});
|
|
396
|
-
it("Should not include Summarize ops with runtime count", async () => {
|
|
397
|
-
assert.strictEqual(heuristicData.numRuntimeOps, 0);
|
|
398
|
-
assert.strictEqual(heuristicData.numNonRuntimeOps, 0);
|
|
399
|
-
await emitNextOp(1, Date.now(), MessageType.Summarize);
|
|
400
|
-
assert.strictEqual(heuristicData.numRuntimeOps, 0);
|
|
401
|
-
assert.strictEqual(heuristicData.numNonRuntimeOps, 1);
|
|
402
|
-
});
|
|
403
|
-
it("Should not summarize on non-runtime op before threshold is reached", async () => {
|
|
404
|
-
// Creating RunningSummarizer starts heuristics automatically
|
|
405
|
-
await emitNoOp(1);
|
|
406
|
-
await tickAndFlushPromises(summaryConfig.minIdleTime);
|
|
407
|
-
assertRunCounts(1, 0, 0, "should perform summary");
|
|
408
|
-
await emitAck();
|
|
409
|
-
assert(summaryConfig.nonRuntimeHeuristicThreshold !== undefined, "Expect nonRuntimeHeuristicThreshold to be provided");
|
|
410
|
-
await emitNoOp(summaryConfig.nonRuntimeHeuristicThreshold - 3); // Summarize and SummaryAck are included
|
|
411
|
-
await tickAndFlushPromises(summaryConfig.minIdleTime);
|
|
412
|
-
assertRunCounts(1, 0, 0, "should not perform summary");
|
|
413
|
-
assert.strictEqual(heuristicData.numRuntimeOps, 0);
|
|
414
|
-
assert.strictEqual(heuristicData.numNonRuntimeOps, summaryConfig.nonRuntimeHeuristicThreshold - 1);
|
|
415
|
-
await emitNoOp(1);
|
|
416
|
-
await tickAndFlushPromises(summaryConfig.minIdleTime);
|
|
417
|
-
assertRunCounts(2, 0, 0, "should perform summary");
|
|
418
|
-
});
|
|
419
|
-
});
|
|
420
|
-
describe("Safe Retries", () => {
|
|
421
|
-
beforeEach(async () => {
|
|
422
|
-
shouldDeferGenerateSummary = false;
|
|
423
|
-
deferGenerateSummary = undefined;
|
|
424
|
-
await startRunningSummarizer();
|
|
425
|
-
});
|
|
426
|
-
it("Should retry on failures", async () => {
|
|
427
|
-
await emitNextOp();
|
|
428
|
-
// too early, should not run yet
|
|
429
|
-
await emitNextOp(summaryConfig.maxOps - 1);
|
|
430
|
-
assertRunCounts(0, 0, 0);
|
|
431
|
-
// now should run a normal run
|
|
432
|
-
await emitNextOp(1);
|
|
433
|
-
assertRunCounts(1, 0, 0);
|
|
434
|
-
const retryProps1 = {
|
|
435
|
-
summarizeCount: 1,
|
|
436
|
-
summaryAttemptsPerPhase: 1,
|
|
437
|
-
summaryAttempts: 1,
|
|
438
|
-
summaryAttemptPhase: 1,
|
|
439
|
-
};
|
|
440
|
-
assert(mockLogger.matchEvents([
|
|
441
|
-
{ eventName: "Running:Summarize_generate", ...retryProps1 },
|
|
442
|
-
{ eventName: "Running:Summarize_Op", ...retryProps1 },
|
|
443
|
-
]), "unexpected log sequence");
|
|
444
|
-
// should not run, because our summary hasn't been acked/nacked yet
|
|
445
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
446
|
-
assertRunCounts(1, 0, 0);
|
|
447
|
-
// should run with refresh after first nack
|
|
448
|
-
await emitNack();
|
|
449
|
-
assertRunCounts(2, 0, 1, "retry1 should be refreshLatestAck");
|
|
450
|
-
const retryProps2 = {
|
|
451
|
-
summarizeCount: 1,
|
|
452
|
-
summaryAttemptsPerPhase: 1,
|
|
453
|
-
summaryAttempts: 2,
|
|
454
|
-
summaryAttemptPhase: 2,
|
|
455
|
-
};
|
|
456
|
-
assert(mockLogger.matchEvents([
|
|
457
|
-
{
|
|
458
|
-
eventName: "Running:Summarize_cancel",
|
|
459
|
-
...retryProps1,
|
|
460
|
-
reason: getFailMessage("summaryNack"),
|
|
461
|
-
},
|
|
462
|
-
{ eventName: "Running:Summarize_generate", ...retryProps2 },
|
|
463
|
-
{ eventName: "Running:Summarize_Op", ...retryProps2 },
|
|
464
|
-
]), "unexpected log sequence");
|
|
465
|
-
// Should stop after final nack
|
|
466
|
-
assert.strictEqual(stopCall, 0);
|
|
467
|
-
await emitNack();
|
|
468
|
-
assert.strictEqual(stopCall, 1);
|
|
469
|
-
});
|
|
470
|
-
it("Should retry after delay on failures with retryAfter", async () => {
|
|
471
|
-
await emitNextOp();
|
|
472
|
-
// too early, should not run yet
|
|
473
|
-
await emitNextOp(summaryConfig.maxOps - 1);
|
|
474
|
-
assertRunCounts(0, 0, 0, "too early");
|
|
475
|
-
// now should run a normal run
|
|
476
|
-
await emitNextOp(1);
|
|
477
|
-
assertRunCounts(1, 0, 0, "normal run");
|
|
478
|
-
const retryProps1 = {
|
|
479
|
-
summarizeCount: 1,
|
|
480
|
-
summaryAttemptsPerPhase: 1,
|
|
481
|
-
summaryAttempts: 1,
|
|
482
|
-
summaryAttemptPhase: 1,
|
|
483
|
-
};
|
|
484
|
-
assert(mockLogger.matchEvents([
|
|
485
|
-
{ eventName: "Running:Summarize_generate", ...retryProps1 },
|
|
486
|
-
{ eventName: "Running:Summarize_Op", ...retryProps1 },
|
|
487
|
-
]), "unexpected log sequence");
|
|
488
|
-
// should not run, because our summary hasn't been acked/nacked yet
|
|
489
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
490
|
-
assertRunCounts(1, 0, 0, "waiting for ack/nack");
|
|
491
|
-
// should not run, because of specified 30 sec delay
|
|
492
|
-
await emitNack(30);
|
|
493
|
-
await tickAndFlushPromises(30 * 1000 - 1);
|
|
494
|
-
assertRunCounts(1, 0, 0, "waiting for retryAfter delay");
|
|
495
|
-
// should rerun the normal try after the delay
|
|
496
|
-
await tickAndFlushPromises(1);
|
|
497
|
-
assertRunCounts(2, 0, 0, "rerun after retryAfter delay");
|
|
498
|
-
const retryProps2 = {
|
|
499
|
-
summarizeCount: 1,
|
|
500
|
-
summaryAttemptsPerPhase: 2,
|
|
501
|
-
summaryAttempts: 2,
|
|
502
|
-
summaryAttemptPhase: 1,
|
|
503
|
-
};
|
|
504
|
-
assert(mockLogger.matchEvents([
|
|
505
|
-
{
|
|
506
|
-
eventName: "Running:Summarize_cancel",
|
|
507
|
-
summarizeCount: 1,
|
|
508
|
-
reason: getFailMessage("summaryNack"),
|
|
509
|
-
},
|
|
510
|
-
{
|
|
511
|
-
eventName: "Running:SummarizeAttemptDelay",
|
|
512
|
-
...{
|
|
513
|
-
summarizeCount: 1,
|
|
514
|
-
summaryAttemptsPerPhase: 1,
|
|
515
|
-
summaryAttempts: 1,
|
|
516
|
-
summaryAttemptPhase: 1,
|
|
517
|
-
},
|
|
518
|
-
},
|
|
519
|
-
{
|
|
520
|
-
eventName: "Running:Summarize_generate",
|
|
521
|
-
...retryProps2,
|
|
522
|
-
},
|
|
523
|
-
{
|
|
524
|
-
eventName: "Running:Summarize_Op",
|
|
525
|
-
...retryProps2,
|
|
526
|
-
},
|
|
527
|
-
]), "unexpected log sequence");
|
|
528
|
-
});
|
|
529
|
-
it("Should wait on 429 from uploadSummaryWithContext", async () => {
|
|
530
|
-
shouldDeferGenerateSummary = true;
|
|
531
|
-
await emitNextOp();
|
|
532
|
-
// too early, should not run yet
|
|
533
|
-
await emitNextOp(summaryConfig.maxOps);
|
|
534
|
-
assert(deferGenerateSummary !== undefined, "submitSummary was not called");
|
|
535
|
-
deferGenerateSummary.reject({ message: "error", retryAfterSeconds: 30 });
|
|
536
|
-
await flushPromises();
|
|
537
|
-
await tickAndFlushPromises(30 * 1000 - 1);
|
|
538
|
-
assertRunCounts(1, 0, 0, "failed upload");
|
|
539
|
-
const retryProps1 = {
|
|
540
|
-
summarizeCount: 1,
|
|
541
|
-
summaryAttemptsPerPhase: 1,
|
|
542
|
-
summaryAttempts: 1,
|
|
543
|
-
summaryAttemptPhase: 1,
|
|
544
|
-
};
|
|
545
|
-
assert(mockLogger.matchEvents([
|
|
546
|
-
{ eventName: "Running:Summarize_cancel", ...retryProps1 },
|
|
547
|
-
{ eventName: "Running:SummarizeAttemptDelay", ...retryProps1 },
|
|
548
|
-
]), "unexpected log sequence");
|
|
549
|
-
shouldDeferGenerateSummary = false;
|
|
550
|
-
await tickAndFlushPromises(1);
|
|
551
|
-
assertRunCounts(2, 0, 0, "normal run");
|
|
552
|
-
const retryProps2 = {
|
|
553
|
-
summarizeCount: 1,
|
|
554
|
-
summaryAttemptsPerPhase: 2,
|
|
555
|
-
summaryAttempts: 2,
|
|
556
|
-
summaryAttemptPhase: 1,
|
|
557
|
-
};
|
|
558
|
-
assert(mockLogger.matchEvents([
|
|
559
|
-
{ eventName: "Running:Summarize_generate", ...retryProps2 },
|
|
560
|
-
{ eventName: "Running:Summarize_Op", ...retryProps2 },
|
|
561
|
-
]), "unexpected log sequence");
|
|
562
|
-
});
|
|
563
|
-
});
|
|
564
|
-
describe("Summarization attempts with retry", () => {
|
|
565
|
-
beforeEach(async () => {
|
|
566
|
-
settings["Fluid.Summarizer.UseDynamicRetries"] = true;
|
|
567
|
-
shouldDeferGenerateSummary = false;
|
|
568
|
-
deferGenerateSummary = undefined;
|
|
569
|
-
});
|
|
570
|
-
/**
|
|
571
|
-
* Validate that a summary attempt fails as expected, correct events are received and summarization
|
|
572
|
-
* stops (or doesn't) as per the given params.
|
|
573
|
-
* @param attemptNumber - The current attempt number.
|
|
574
|
-
* @param totalAttempts - The total number of attempts. After the last attempt, summarizer should close.
|
|
575
|
-
* @param lastSuccessfulStage - The stage after which summarization failed.
|
|
576
|
-
* @param retryAfterSeconds - The number of seconds after which the next attempt should be tried.
|
|
577
|
-
*/
|
|
578
|
-
const validateSummaryAttemptFails = async (attemptNumber, totalAttempts, lastSuccessfulStage, retryAfterSeconds) => {
|
|
579
|
-
const finalAttempt = attemptNumber >= totalAttempts;
|
|
580
|
-
// Nack the summary with "retryAfterSeconds" specified.
|
|
581
|
-
await emitNack(retryAfterSeconds);
|
|
582
|
-
assertRunCounts(attemptNumber, 0, 0, `Total run count should be ${attemptNumber}`, finalAttempt ? 1 : 0 /* expectedStopCount */);
|
|
583
|
-
const retryProps1 = {
|
|
584
|
-
summarizeCount: 1,
|
|
585
|
-
summaryAttempts: attemptNumber,
|
|
586
|
-
stage: lastSuccessfulStage,
|
|
587
|
-
};
|
|
588
|
-
const expectedEvents = [
|
|
589
|
-
{
|
|
590
|
-
eventName: "Running:Summarize_cancel",
|
|
591
|
-
...retryProps1,
|
|
592
|
-
retryAfterSeconds,
|
|
593
|
-
reason: getFailMessage(lastSuccessfulStage === "submit"
|
|
594
|
-
? "summaryNack" // if last stage is submit, summarization fails due to summary nack
|
|
595
|
-
: "submitSummaryFailure"),
|
|
596
|
-
},
|
|
597
|
-
];
|
|
598
|
-
// After the final attempt, there shouldn't be any delay.
|
|
599
|
-
if (!finalAttempt) {
|
|
600
|
-
expectedEvents.push({
|
|
601
|
-
eventName: "Running:SummarizeAttemptDelay",
|
|
602
|
-
...retryProps1,
|
|
603
|
-
duration: retryAfterSeconds,
|
|
604
|
-
dynamicRetries: true,
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
mockLogger.assertMatch(expectedEvents, `Summarizer attempt ${attemptNumber} did not fail as expected`);
|
|
608
|
-
// After the final attempt, summarizer should stop.
|
|
609
|
-
assert.strictEqual(stopCall, finalAttempt ? 1 : 0, `Summarizer should${finalAttempt ? "" : " not"} have stopped after ${totalAttempts} attempts`);
|
|
610
|
-
};
|
|
611
|
-
// Callback that fails the summary for all stages expect submit. For submit, the summarization
|
|
612
|
-
// will fail because of summary ack not received withing timeout.
|
|
613
|
-
const submitSummaryCallback = async (stage, retryAfterSeconds) => {
|
|
614
|
-
if (stage === "submit") {
|
|
615
|
-
return successfulSubmitSummary();
|
|
616
|
-
}
|
|
617
|
-
else {
|
|
618
|
-
const error = new RetriableSummaryError(`Fail summarization at ${stage}`, retryAfterSeconds);
|
|
619
|
-
const failedResult = {
|
|
620
|
-
stage,
|
|
621
|
-
referenceSequenceNumber: lastRefSeq,
|
|
622
|
-
minimumSequenceNumber: 0,
|
|
623
|
-
error,
|
|
624
|
-
};
|
|
625
|
-
return failedResult;
|
|
626
|
-
}
|
|
627
|
-
};
|
|
628
|
-
it(`should not retry when summary attempt succeeds`, async () => {
|
|
629
|
-
await startRunningSummarizer();
|
|
630
|
-
await emitNextOp();
|
|
631
|
-
// This should run a summarization because max ops has reached.
|
|
632
|
-
await emitNextOp(summaryConfig.maxOps);
|
|
633
|
-
assertRunCounts(1, 0, 0, `Total run count should be 1`);
|
|
634
|
-
await emitAck();
|
|
635
|
-
assertRunCounts(1, 0, 0, `The run count should still be 1`);
|
|
636
|
-
assert.strictEqual(stopCall, 0, "Summarizer should not have stopped");
|
|
637
|
-
});
|
|
638
|
-
const failedStages = ["base", "generate", "upload", "submit"];
|
|
639
|
-
for (const [stageIndex, stage] of failedStages.entries()) {
|
|
640
|
-
// When stage is "submit", the submit stage was successful and default max attempts is used
|
|
641
|
-
// for any other failures.
|
|
642
|
-
const maxAttempts = stage === "submit"
|
|
643
|
-
? defaultMaxAttempts
|
|
644
|
-
: defaultMaxAttemptsForSubmitFailures;
|
|
645
|
-
const titleStage = stage === "submit" ? "nack" : stage;
|
|
646
|
-
it(`should attempt 1 time only on failure without retry specified at ${titleStage} stage`, async () => {
|
|
647
|
-
await startRunningSummarizer(undefined /* disableHeuristics */, async () => submitSummaryCallback(stage, undefined /* retryAfterSeconds */));
|
|
648
|
-
await emitNextOp();
|
|
649
|
-
// This should run a summarization because max ops has reached.
|
|
650
|
-
await emitNextOp(summaryConfig.maxOps);
|
|
651
|
-
await validateSummaryAttemptFails(1 /* attemptNumber */, 1 /* totalAttempts */, stage, undefined /* retryAfterSeconds */);
|
|
652
|
-
});
|
|
653
|
-
it(`should attempt ${maxAttempts} times on failure with retryAfterSeconds at ${titleStage} stage`, async () => {
|
|
654
|
-
const retryAfterSeconds = 5;
|
|
655
|
-
await startRunningSummarizer(undefined /* disableHeuristics */, async () => submitSummaryCallback(stage, retryAfterSeconds));
|
|
656
|
-
await emitNextOp();
|
|
657
|
-
// This should run a summarization because max ops has reached.
|
|
658
|
-
await emitNextOp(summaryConfig.maxOps);
|
|
659
|
-
for (let attemptNumber = 1; attemptNumber <= maxAttempts; attemptNumber++) {
|
|
660
|
-
await validateSummaryAttemptFails(attemptNumber, maxAttempts, stage, retryAfterSeconds);
|
|
661
|
-
// Wait for "retryAfterSeconds". The next attempt should start after this.
|
|
662
|
-
await tickAndFlushPromises(retryAfterSeconds * 1000 + 1);
|
|
663
|
-
}
|
|
664
|
-
// validate that summarization is not run again.
|
|
665
|
-
assertRunCounts(maxAttempts, 0, 0, `Summarization should not have been attempted more than ${maxAttempts} times`, 1 /** expectedStopCount */);
|
|
666
|
-
});
|
|
667
|
-
it(`should attempt ${maxAttempts} times on failure when stage changes from ${titleStage}`, async () => {
|
|
668
|
-
// Helper to get a different stage from the current one.
|
|
669
|
-
const getNewStage = () => {
|
|
670
|
-
let index = stageIndex + 1;
|
|
671
|
-
// If the new stage is "submit", get another stage instead. This is because the logic is
|
|
672
|
-
// different when failure happens after "submit" stage. This is validated in a separate test.
|
|
673
|
-
if (index > failedStages.length - 2) {
|
|
674
|
-
index = 0;
|
|
675
|
-
}
|
|
676
|
-
return failedStages[index];
|
|
677
|
-
};
|
|
678
|
-
const retryAfterSeconds = 5;
|
|
679
|
-
let currentStage = stage;
|
|
680
|
-
await startRunningSummarizer(undefined /* disableHeuristics */, async () => {
|
|
681
|
-
if (currentStage === "submit") {
|
|
682
|
-
return successfulSubmitSummary();
|
|
683
|
-
}
|
|
684
|
-
else {
|
|
685
|
-
const error = new RetriableSummaryError(`Fail summarization at ${currentStage}`, retryAfterSeconds);
|
|
686
|
-
const failedResult = {
|
|
687
|
-
stage: currentStage,
|
|
688
|
-
referenceSequenceNumber: lastRefSeq,
|
|
689
|
-
minimumSequenceNumber: 0,
|
|
690
|
-
error,
|
|
691
|
-
};
|
|
692
|
-
return failedResult;
|
|
693
|
-
}
|
|
694
|
-
});
|
|
695
|
-
await emitNextOp();
|
|
696
|
-
// This should run a summarization because max ops has reached.
|
|
697
|
-
await emitNextOp(summaryConfig.maxOps);
|
|
698
|
-
for (let attemptNumber = 1; attemptNumber <= maxAttempts; attemptNumber++) {
|
|
699
|
-
await validateSummaryAttemptFails(attemptNumber, maxAttempts, currentStage, retryAfterSeconds);
|
|
700
|
-
// Change the failure stage after 2 attempts.
|
|
701
|
-
if (attemptNumber === 2) {
|
|
702
|
-
currentStage = getNewStage();
|
|
703
|
-
}
|
|
704
|
-
// Wait for "retryAfterSeconds". The next attempt should start after this.
|
|
705
|
-
await tickAndFlushPromises(retryAfterSeconds * 1000 + 1);
|
|
706
|
-
}
|
|
707
|
-
// Validate summarization is not run again.
|
|
708
|
-
assertRunCounts(maxAttempts, 0, 0, `Summarization should not have been attempted more than ${maxAttempts} times`, 1 /** expectedStopCount */);
|
|
709
|
-
});
|
|
710
|
-
it(`should update max attempts on failure at ${titleStage} stage as per AttemptsForSubmitFailures`, async () => {
|
|
711
|
-
const retryAfterSeconds = 5;
|
|
712
|
-
const maxAttemptsOverride = stage === "submit"
|
|
713
|
-
? defaultMaxAttempts
|
|
714
|
-
: defaultMaxAttemptsForSubmitFailures - 1;
|
|
715
|
-
settings["Fluid.Summarizer.AttemptsForSubmitFailures"] =
|
|
716
|
-
maxAttemptsOverride;
|
|
717
|
-
await startRunningSummarizer(undefined /* disableHeuristics */, async () => submitSummaryCallback(stage, retryAfterSeconds));
|
|
718
|
-
await emitNextOp();
|
|
719
|
-
// This should run a summarization because max ops has reached.
|
|
720
|
-
await emitNextOp(summaryConfig.maxOps);
|
|
721
|
-
for (let attemptNumber = 1; attemptNumber <= maxAttemptsOverride; attemptNumber++) {
|
|
722
|
-
await validateSummaryAttemptFails(attemptNumber, maxAttemptsOverride, stage, retryAfterSeconds);
|
|
723
|
-
// Wait for "retryAfterSeconds". The next attempt should start after this.
|
|
724
|
-
await tickAndFlushPromises(retryAfterSeconds * 1000 + 1);
|
|
725
|
-
}
|
|
726
|
-
// validate that summarization is not run again.
|
|
727
|
-
assertRunCounts(maxAttemptsOverride, 0, 0, `Summarization should not have been attempted more than ${maxAttemptsOverride} times`, 1 /** expectedStopCount */);
|
|
728
|
-
});
|
|
729
|
-
}
|
|
730
|
-
/**
|
|
731
|
-
* This test validates a special case where summarize failures switch from on of the submit stages to
|
|
732
|
-
* a nack failure. Submit stage failures are retried more times than nack failures and so when the
|
|
733
|
-
* failure switches from submit to nack, only one more retry happens irrespective of what the
|
|
734
|
-
* defaultMaxAttempts value is.
|
|
735
|
-
*/
|
|
736
|
-
for (let maxAttempts = 1; maxAttempts < defaultMaxAttemptsForSubmitFailures; maxAttempts++) {
|
|
737
|
-
it(`should attempt one more time when stage changes to nack after ${maxAttempts} failed attempts`, async () => {
|
|
738
|
-
const retryAfterSeconds = 5;
|
|
739
|
-
let currentStage = maxAttempts === 1 ? "submit" : "generate";
|
|
740
|
-
await startRunningSummarizer(undefined /* disableHeuristics */, async () => {
|
|
741
|
-
if (currentStage === "submit") {
|
|
742
|
-
return successfulSubmitSummary();
|
|
743
|
-
}
|
|
744
|
-
else {
|
|
745
|
-
const error = new RetriableSummaryError(`Fail summarization at ${currentStage}`, retryAfterSeconds);
|
|
746
|
-
const failedResult = {
|
|
747
|
-
stage: currentStage,
|
|
748
|
-
referenceSequenceNumber: lastRefSeq,
|
|
749
|
-
minimumSequenceNumber: 0,
|
|
750
|
-
error,
|
|
751
|
-
};
|
|
752
|
-
return failedResult;
|
|
753
|
-
}
|
|
754
|
-
});
|
|
755
|
-
// Fail at the "generate" stage 2 times.
|
|
756
|
-
await emitNextOp();
|
|
757
|
-
// This should run a summarization because max ops has reached.
|
|
758
|
-
await emitNextOp(summaryConfig.maxOps);
|
|
759
|
-
let attemptNumber = 1;
|
|
760
|
-
for (; attemptNumber <= maxAttempts; attemptNumber++) {
|
|
761
|
-
await validateSummaryAttemptFails(attemptNumber, maxAttempts + 1, currentStage, retryAfterSeconds);
|
|
762
|
-
// In the third attempt, fail at "submit" stage. This will trigger a nack failure. It should
|
|
763
|
-
// not retry attempts anymore because "defaultMaxAttempts" attempts have already been done.
|
|
764
|
-
if (attemptNumber === maxAttempts - 1) {
|
|
765
|
-
currentStage = "submit";
|
|
766
|
-
}
|
|
767
|
-
// Wait for "retryAfterSeconds". The next attempt should start after this.
|
|
768
|
-
await tickAndFlushPromises(retryAfterSeconds * 1000 + 1);
|
|
769
|
-
}
|
|
770
|
-
// Wait for "retryAfterSeconds". The next attempt should start after this.
|
|
771
|
-
await tickAndFlushPromises(retryAfterSeconds * 1000 + 1);
|
|
772
|
-
await validateSummaryAttemptFails(attemptNumber++, maxAttempts + 1, currentStage, retryAfterSeconds);
|
|
773
|
-
// Wait for "retryAfterSeconds". There shouldn't be any more attempts.
|
|
774
|
-
await tickAndFlushPromises(retryAfterSeconds * 1000 + 1);
|
|
775
|
-
// Validate summarization is not run again.
|
|
776
|
-
assertRunCounts(maxAttempts + 1, 0, 0, `Summarization should not have been attempted more than ${maxAttempts + 1} times`, 1 /** expectedStopCount */);
|
|
777
|
-
});
|
|
778
|
-
}
|
|
779
|
-
it("Should not retry last summary", async () => {
|
|
780
|
-
const stage = "base";
|
|
781
|
-
const retryAfterSeconds = 10;
|
|
782
|
-
await startRunningSummarizer(undefined /* disableHeuristics */, async () => submitSummaryCallback(stage, retryAfterSeconds));
|
|
783
|
-
// This should trigger last summary when summarizer stops.
|
|
784
|
-
await emitNextOp(summaryConfig.minOpsForLastSummaryAttempt);
|
|
785
|
-
const stopP = summarizer.waitStop(true /* allowLastSummary */);
|
|
786
|
-
await flushPromises();
|
|
787
|
-
await stopP;
|
|
788
|
-
summarizer.dispose();
|
|
789
|
-
assertRunCounts(1, 0, 0, "should perform lastSummary");
|
|
790
|
-
const expectedEvents = [
|
|
791
|
-
{
|
|
792
|
-
eventName: "Running:Summarize_cancel",
|
|
793
|
-
retryAfterSeconds,
|
|
794
|
-
summarizeCount: 1,
|
|
795
|
-
stage,
|
|
796
|
-
},
|
|
797
|
-
];
|
|
798
|
-
mockLogger.assertMatch(expectedEvents, `last summary attempt did not fail as expected`);
|
|
799
|
-
// Wait for "retryAfterSeconds". There shouldn't be any more attempts.
|
|
800
|
-
await tickAndFlushPromises(retryAfterSeconds * 1000 + 1);
|
|
801
|
-
assertRunCounts(1, 0, 0, "should not retry lastSummary");
|
|
802
|
-
});
|
|
803
|
-
});
|
|
804
|
-
describe("On-demand Summaries", () => {
|
|
805
|
-
const reason = "test";
|
|
806
|
-
// This is used to validate the summarizeReason property in telemetry.
|
|
807
|
-
const summarizeReason = `onDemand/${reason}`;
|
|
808
|
-
beforeEach(async () => {
|
|
809
|
-
await startRunningSummarizer();
|
|
810
|
-
});
|
|
811
|
-
it("Should create an on-demand summary", async () => {
|
|
812
|
-
await emitNextOp(2); // set ref seq to 2
|
|
813
|
-
const result = summarizer.summarizeOnDemand({ reason });
|
|
814
|
-
const submitResult = await result.summarySubmitted;
|
|
815
|
-
assertRunCounts(1, 0, 0, "on-demand should run");
|
|
816
|
-
assert(submitResult.success, "on-demand summary should submit");
|
|
817
|
-
assert(submitResult.data.stage === "submit", "on-demand summary submitted data stage should be submit");
|
|
818
|
-
assert.strictEqual(submitResult.data.referenceSequenceNumber, 2, "ref seq num");
|
|
819
|
-
assert(submitResult.data.summaryTree !== undefined, "summary tree should exist");
|
|
820
|
-
const broadcastResult = await result.summaryOpBroadcasted;
|
|
821
|
-
assert(broadcastResult.success, "summary op should be broadcast");
|
|
822
|
-
assert.strictEqual(broadcastResult.data.summarizeOp.referenceSequenceNumber, 2, "summarize op ref seq num should be same as summary seq");
|
|
823
|
-
assert.strictEqual(broadcastResult.data.summarizeOp.sequenceNumber, 3, "unexpected summary sequence number");
|
|
824
|
-
assert.strictEqual(broadcastResult.data.summarizeOp.contents.handle, "test-broadcast-handle", "summarize op handle should be test-broadcast-handle");
|
|
825
|
-
assert(mockLogger.matchEvents([
|
|
826
|
-
{
|
|
827
|
-
eventName: "Running:Summarize_generate",
|
|
828
|
-
summarizeCount: runCount,
|
|
829
|
-
summarizeReason,
|
|
830
|
-
},
|
|
831
|
-
{
|
|
832
|
-
eventName: "Running:Summarize_Op",
|
|
833
|
-
summarizeCount: runCount,
|
|
834
|
-
summarizeReason,
|
|
835
|
-
},
|
|
836
|
-
]), "unexpected log sequence");
|
|
837
|
-
// Verify that heuristics are blocked while waiting for ack
|
|
838
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
839
|
-
assertRunCounts(1, 0, 0);
|
|
840
|
-
await emitAck();
|
|
841
|
-
const ackNackResult = await result.receivedSummaryAckOrNack;
|
|
842
|
-
assert(ackNackResult.success, "on-demand summary should succeed");
|
|
843
|
-
assert(ackNackResult.data.summaryAckOp.type === MessageType.SummaryAck, "should be ack");
|
|
844
|
-
assert(ackNackResult.data.summaryAckOp.contents.handle === "test-ack-handle", "summary ack handle should be test-ack-handle");
|
|
845
|
-
});
|
|
846
|
-
it("Should return already running for on-demand summary", async () => {
|
|
847
|
-
// Should start running by heuristics
|
|
848
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
849
|
-
assertRunCounts(1, 0, 0);
|
|
850
|
-
let resolved = false;
|
|
851
|
-
try {
|
|
852
|
-
summarizer.summarizeOnDemand({ reason });
|
|
853
|
-
resolved = true;
|
|
854
|
-
}
|
|
855
|
-
catch { }
|
|
856
|
-
await flushPromises();
|
|
857
|
-
assert(resolved === false, "already running promise should not resolve yet");
|
|
858
|
-
});
|
|
859
|
-
it("On-demand summary should fail on nack", async () => {
|
|
860
|
-
await emitNextOp(2); // set ref seq to 2
|
|
861
|
-
const result = summarizer.summarizeOnDemand({ reason });
|
|
862
|
-
const submitResult = await result.summarySubmitted;
|
|
863
|
-
assertRunCounts(1, 0, 0, "on-demand should run");
|
|
864
|
-
assert(submitResult.success, "on-demand summary should submit");
|
|
865
|
-
assert(submitResult.data.stage === "submit", "on-demand summary submitted data stage should be submit");
|
|
866
|
-
assert.strictEqual(submitResult.data.referenceSequenceNumber, 2, "ref seq num");
|
|
867
|
-
assert(submitResult.data.summaryTree !== undefined, "summary tree should exist");
|
|
868
|
-
const broadcastResult = await result.summaryOpBroadcasted;
|
|
869
|
-
assert(broadcastResult.success, "summary op should be broadcast");
|
|
870
|
-
assert.strictEqual(broadcastResult.data.summarizeOp.referenceSequenceNumber, 2, "summarize op ref seq num should be same as summary seq");
|
|
871
|
-
assert.strictEqual(broadcastResult.data.summarizeOp.sequenceNumber, 3, "unexpected summary sequence number");
|
|
872
|
-
assert.strictEqual(broadcastResult.data.summarizeOp.contents.handle, "test-broadcast-handle", "summarize op handle should be test-broadcast-handle");
|
|
873
|
-
assert(mockLogger.matchEvents([
|
|
874
|
-
{
|
|
875
|
-
eventName: "Running:Summarize_generate",
|
|
876
|
-
summarizeCount: runCount,
|
|
877
|
-
summarizeReason,
|
|
878
|
-
},
|
|
879
|
-
{
|
|
880
|
-
eventName: "Running:Summarize_Op",
|
|
881
|
-
summarizeCount: runCount,
|
|
882
|
-
summarizeReason,
|
|
883
|
-
},
|
|
884
|
-
]), "unexpected log sequence");
|
|
885
|
-
// Verify that heuristics are blocked while waiting for ack
|
|
886
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
887
|
-
assertRunCounts(1, 0, 0);
|
|
888
|
-
await emitNack();
|
|
889
|
-
const ackNackResult = await result.receivedSummaryAckOrNack;
|
|
890
|
-
assert(!ackNackResult.success, "on-demand summary should fail");
|
|
891
|
-
assert(ackNackResult.data?.summaryNackOp.type === MessageType.SummaryNack, "should be nack");
|
|
892
|
-
assert(JSON.parse(ackNackResult.data.summaryNackOp.data).message ===
|
|
893
|
-
"test-nack", "summary nack error should be test-nack");
|
|
894
|
-
});
|
|
895
|
-
it("Should fail an on-demand summary if stopping", async () => {
|
|
896
|
-
summarizer.waitStop(true).catch(() => { });
|
|
897
|
-
const [refreshLatestAck, fullTree] = [true, true];
|
|
898
|
-
const result1 = summarizer.summarizeOnDemand({ reason: "test1" });
|
|
899
|
-
const result2 = summarizer.summarizeOnDemand({
|
|
900
|
-
reason: "test2",
|
|
901
|
-
refreshLatestAck,
|
|
902
|
-
});
|
|
903
|
-
const result3 = summarizer.summarizeOnDemand({
|
|
904
|
-
reason: "test3",
|
|
905
|
-
fullTree,
|
|
906
|
-
});
|
|
907
|
-
const result4 = summarizer.summarizeOnDemand({
|
|
908
|
-
reason: "test4",
|
|
909
|
-
refreshLatestAck,
|
|
910
|
-
fullTree,
|
|
911
|
-
});
|
|
912
|
-
const allResults = (await Promise.all([
|
|
913
|
-
result1.summarySubmitted,
|
|
914
|
-
result1.summaryOpBroadcasted,
|
|
915
|
-
result1.receivedSummaryAckOrNack,
|
|
916
|
-
result2.summarySubmitted,
|
|
917
|
-
result2.summaryOpBroadcasted,
|
|
918
|
-
result2.receivedSummaryAckOrNack,
|
|
919
|
-
])).concat(await Promise.all([
|
|
920
|
-
result3.summarySubmitted,
|
|
921
|
-
result3.summaryOpBroadcasted,
|
|
922
|
-
result3.receivedSummaryAckOrNack,
|
|
923
|
-
result4.summarySubmitted,
|
|
924
|
-
result4.summaryOpBroadcasted,
|
|
925
|
-
result4.receivedSummaryAckOrNack,
|
|
926
|
-
]));
|
|
927
|
-
for (const result of allResults) {
|
|
928
|
-
assert(!result.success, "all results should fail");
|
|
929
|
-
}
|
|
930
|
-
});
|
|
931
|
-
it("Should fail an on-demand summary if disposed", async () => {
|
|
932
|
-
summarizer.dispose();
|
|
933
|
-
const [refreshLatestAck, fullTree] = [true, true];
|
|
934
|
-
const result1 = summarizer.summarizeOnDemand({ reason: "test1" });
|
|
935
|
-
const result2 = summarizer.summarizeOnDemand({
|
|
936
|
-
reason: "test2",
|
|
937
|
-
refreshLatestAck,
|
|
938
|
-
});
|
|
939
|
-
const result3 = summarizer.summarizeOnDemand({
|
|
940
|
-
reason: "test3",
|
|
941
|
-
fullTree,
|
|
942
|
-
});
|
|
943
|
-
const result4 = summarizer.summarizeOnDemand({
|
|
944
|
-
reason: "test4",
|
|
945
|
-
refreshLatestAck,
|
|
946
|
-
fullTree,
|
|
947
|
-
});
|
|
948
|
-
const allResults = (await Promise.all([
|
|
949
|
-
result1.summarySubmitted,
|
|
950
|
-
result1.summaryOpBroadcasted,
|
|
951
|
-
result1.receivedSummaryAckOrNack,
|
|
952
|
-
result2.summarySubmitted,
|
|
953
|
-
result2.summaryOpBroadcasted,
|
|
954
|
-
result2.receivedSummaryAckOrNack,
|
|
955
|
-
])).concat(await Promise.all([
|
|
956
|
-
result3.summarySubmitted,
|
|
957
|
-
result3.summaryOpBroadcasted,
|
|
958
|
-
result3.receivedSummaryAckOrNack,
|
|
959
|
-
result4.summarySubmitted,
|
|
960
|
-
result4.summaryOpBroadcasted,
|
|
961
|
-
result4.receivedSummaryAckOrNack,
|
|
962
|
-
]));
|
|
963
|
-
for (const result of allResults) {
|
|
964
|
-
assert(!result.success, "all results should fail");
|
|
965
|
-
}
|
|
966
|
-
});
|
|
967
|
-
});
|
|
968
|
-
describe("Enqueue Summaries", () => {
|
|
969
|
-
const reason = "test";
|
|
970
|
-
// This is used to validate the summarizeReason property in telemetry.
|
|
971
|
-
const summarizeReason = `enqueuedSummary/enqueue;${reason}`;
|
|
972
|
-
beforeEach(async () => {
|
|
973
|
-
await startRunningSummarizer();
|
|
974
|
-
});
|
|
975
|
-
it("Should summarize after specified sequence number", async () => {
|
|
976
|
-
await emitNextOp(2); // set ref seq to 2
|
|
977
|
-
const afterSequenceNumber = 9;
|
|
978
|
-
const result = summarizer.enqueueSummarize({
|
|
979
|
-
reason,
|
|
980
|
-
afterSequenceNumber,
|
|
981
|
-
});
|
|
982
|
-
assert(result.alreadyEnqueued === undefined, "should not be already enqueued");
|
|
983
|
-
await emitNextOp(6);
|
|
984
|
-
assertRunCounts(0, 0, 0, "enqueued should not run yet, still 1 op short");
|
|
985
|
-
await emitNextOp(1);
|
|
986
|
-
assertRunCounts(1, 0, 0, "enqueued should run");
|
|
987
|
-
const submitResult = await result.summarySubmitted;
|
|
988
|
-
assert(submitResult.success, "enqueued summary should submit");
|
|
989
|
-
assert(submitResult.data.stage === "submit", "enqueued summary submitted data stage should be submit");
|
|
990
|
-
assert.strictEqual(submitResult.data.referenceSequenceNumber, 9, "ref seq num");
|
|
991
|
-
assert(submitResult.data.summaryTree !== undefined, "summary tree should exist");
|
|
992
|
-
const broadcastResult = await result.summaryOpBroadcasted;
|
|
993
|
-
assert(broadcastResult.success, "summary op should be broadcast");
|
|
994
|
-
assert.strictEqual(broadcastResult.data.summarizeOp.referenceSequenceNumber, 9, "summarize op ref seq num should be same as summary seq");
|
|
995
|
-
assert.strictEqual(broadcastResult.data.summarizeOp.sequenceNumber, 10, "unexpected summary sequence number");
|
|
996
|
-
assert.strictEqual(broadcastResult.data.summarizeOp.contents.handle, "test-broadcast-handle", "summarize op handle should be test-broadcast-handle");
|
|
997
|
-
assert(mockLogger.matchEvents([
|
|
998
|
-
{
|
|
999
|
-
eventName: "Running:Summarize_generate",
|
|
1000
|
-
summarizeCount: runCount,
|
|
1001
|
-
summarizeReason,
|
|
1002
|
-
},
|
|
1003
|
-
{
|
|
1004
|
-
eventName: "Running:Summarize_Op",
|
|
1005
|
-
summarizeCount: runCount,
|
|
1006
|
-
summarizeReason,
|
|
1007
|
-
},
|
|
1008
|
-
]), "unexpected log sequence");
|
|
1009
|
-
// Verify that heuristics are blocked while waiting for ack
|
|
1010
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
1011
|
-
assertRunCounts(1, 0, 0);
|
|
1012
|
-
await emitAck();
|
|
1013
|
-
const ackNackResult = await result.receivedSummaryAckOrNack;
|
|
1014
|
-
assert(ackNackResult.success, "enqueued summary should succeed");
|
|
1015
|
-
assert(ackNackResult.data.summaryAckOp.type === MessageType.SummaryAck, "should be ack");
|
|
1016
|
-
assert(ackNackResult.data.summaryAckOp.contents.handle === "test-ack-handle", "summary ack handle should be test-ack-handle");
|
|
1017
|
-
});
|
|
1018
|
-
it("Should summarize after specified sequence number after heuristics attempt finishes", async () => {
|
|
1019
|
-
const afterSequenceNumber = summaryConfig.maxOps * 2 + 10;
|
|
1020
|
-
// Should start running by heuristics
|
|
1021
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
1022
|
-
assertRunCounts(1, 0, 0);
|
|
1023
|
-
const result = summarizer.enqueueSummarize({
|
|
1024
|
-
reason,
|
|
1025
|
-
afterSequenceNumber,
|
|
1026
|
-
});
|
|
1027
|
-
assert(result.alreadyEnqueued === undefined, "should not be already enqueued");
|
|
1028
|
-
let submitRan = false;
|
|
1029
|
-
result.summarySubmitted.then(() => {
|
|
1030
|
-
submitRan = true;
|
|
1031
|
-
}, () => { });
|
|
1032
|
-
// Even after finishing first heuristic summary, enqueued shouldn't run yet.
|
|
1033
|
-
await emitAck();
|
|
1034
|
-
// Should start running by heuristics again.
|
|
1035
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
1036
|
-
assertRunCounts(2, 0, 0);
|
|
1037
|
-
await emitNextOp(20); // make sure enqueued is ready
|
|
1038
|
-
assert(submitRan === false, "enqueued summary should not run until 2nd heuristic ack");
|
|
1039
|
-
// After this ack, it should start running enqueued summary.
|
|
1040
|
-
await emitAck();
|
|
1041
|
-
assert(submitRan === true, "enqueued summary should run");
|
|
1042
|
-
assertRunCounts(3, 0, 0);
|
|
1043
|
-
const submitResult = await result.summarySubmitted;
|
|
1044
|
-
assert(submitResult.success, "enqueued summary should submit");
|
|
1045
|
-
assert(submitResult.data.stage === "submit", "enqueued summary submitted data stage should be submit");
|
|
1046
|
-
// 26 = 22 regular runtime ops + 2 summary ack ops + 2 summarize ops
|
|
1047
|
-
const expectedRefSeqNum = summaryConfig.maxOps * 2 + 26;
|
|
1048
|
-
assert.strictEqual(submitResult.data.referenceSequenceNumber, expectedRefSeqNum, "ref seq num");
|
|
1049
|
-
assert(submitResult.data.summaryTree !== undefined, "summary tree should exist");
|
|
1050
|
-
const broadcastResult = await result.summaryOpBroadcasted;
|
|
1051
|
-
assert(broadcastResult.success, "summary op should be broadcast");
|
|
1052
|
-
assert.strictEqual(broadcastResult.data.summarizeOp.referenceSequenceNumber, expectedRefSeqNum, "summarize op ref seq num should be same as summary seq");
|
|
1053
|
-
assert.strictEqual(broadcastResult.data.summarizeOp.sequenceNumber, expectedRefSeqNum + 1, "unexpected summary sequence number");
|
|
1054
|
-
assert.strictEqual(broadcastResult.data.summarizeOp.contents.handle, "test-broadcast-handle", "summarize op handle should be test-broadcast-handle");
|
|
1055
|
-
// Verify that heuristics are blocked while waiting for ack
|
|
1056
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
1057
|
-
assertRunCounts(3, 0, 0);
|
|
1058
|
-
await emitAck();
|
|
1059
|
-
const ackNackResult = await result.receivedSummaryAckOrNack;
|
|
1060
|
-
assert(ackNackResult.success, "enqueued summary should succeed");
|
|
1061
|
-
assert(ackNackResult.data.summaryAckOp.type === MessageType.SummaryAck, "should be ack");
|
|
1062
|
-
assert(ackNackResult.data.summaryAckOp.contents.handle === "test-ack-handle", "summary ack handle should be test-ack-handle");
|
|
1063
|
-
});
|
|
1064
|
-
it("Should reject subsequent enqueued summarize attempt unless overridden", async () => {
|
|
1065
|
-
await emitNextOp(2); // set ref seq to 2
|
|
1066
|
-
const afterSequenceNumber = 9;
|
|
1067
|
-
const result = summarizer.enqueueSummarize({
|
|
1068
|
-
reason,
|
|
1069
|
-
afterSequenceNumber,
|
|
1070
|
-
});
|
|
1071
|
-
assert(result.alreadyEnqueued === undefined, "should not be already enqueued");
|
|
1072
|
-
// While first attempt is still enqueued, it should reject subsequent ones
|
|
1073
|
-
const result2 = summarizer.enqueueSummarize({ reason: "test-fail" });
|
|
1074
|
-
assert(result2.alreadyEnqueued === true, "should be already enqueued");
|
|
1075
|
-
assert(result2.overridden === undefined, "should not be overridden");
|
|
1076
|
-
const result3 = summarizer.enqueueSummarize({
|
|
1077
|
-
reason: "test-override",
|
|
1078
|
-
override: true,
|
|
1079
|
-
});
|
|
1080
|
-
assert(result3.alreadyEnqueued === true, "should be already enqueued");
|
|
1081
|
-
assert(result3.overridden === true, "should be overridden");
|
|
1082
|
-
const firstResults = await Promise.all([
|
|
1083
|
-
result.summarySubmitted,
|
|
1084
|
-
result.summaryOpBroadcasted,
|
|
1085
|
-
result.receivedSummaryAckOrNack,
|
|
1086
|
-
]);
|
|
1087
|
-
for (const firstResult of firstResults) {
|
|
1088
|
-
assert(firstResult.success === false, "should fail because of override");
|
|
1089
|
-
}
|
|
1090
|
-
await emitAck();
|
|
1091
|
-
const newResults = await Promise.all([
|
|
1092
|
-
result3.summarySubmitted,
|
|
1093
|
-
result3.summaryOpBroadcasted,
|
|
1094
|
-
result3.receivedSummaryAckOrNack,
|
|
1095
|
-
]);
|
|
1096
|
-
for (const newResult of newResults) {
|
|
1097
|
-
assert(newResult.success === true, "should succeed");
|
|
1098
|
-
}
|
|
1099
|
-
});
|
|
1100
|
-
it("Should fail an enqueue summarize attempt if stopping", async () => {
|
|
1101
|
-
summarizer.waitStop(true).catch(() => { });
|
|
1102
|
-
const result1 = summarizer.enqueueSummarize({ reason: "test1" });
|
|
1103
|
-
assert(result1.alreadyEnqueued === undefined, "should not be already enqueued");
|
|
1104
|
-
const result2 = summarizer.enqueueSummarize({
|
|
1105
|
-
reason: "test2",
|
|
1106
|
-
afterSequenceNumber: 123,
|
|
1107
|
-
});
|
|
1108
|
-
assert(result2.alreadyEnqueued === undefined, "should not be already enqueued");
|
|
1109
|
-
const allResults = await Promise.all([
|
|
1110
|
-
result1.summarySubmitted,
|
|
1111
|
-
result1.summaryOpBroadcasted,
|
|
1112
|
-
result1.receivedSummaryAckOrNack,
|
|
1113
|
-
result2.summarySubmitted,
|
|
1114
|
-
result2.summaryOpBroadcasted,
|
|
1115
|
-
result2.receivedSummaryAckOrNack,
|
|
1116
|
-
]);
|
|
1117
|
-
for (const result of allResults) {
|
|
1118
|
-
assert(!result.success, "all results should fail");
|
|
1119
|
-
}
|
|
1120
|
-
});
|
|
1121
|
-
it("Should fail an enqueue summarize attempt if disposed", async () => {
|
|
1122
|
-
summarizer.dispose();
|
|
1123
|
-
const result1 = summarizer.enqueueSummarize({ reason: "test1" });
|
|
1124
|
-
assert(result1.alreadyEnqueued === undefined, "should not be already enqueued");
|
|
1125
|
-
const result2 = summarizer.enqueueSummarize({
|
|
1126
|
-
reason: "test2",
|
|
1127
|
-
afterSequenceNumber: 123,
|
|
1128
|
-
});
|
|
1129
|
-
assert(result2.alreadyEnqueued === undefined, "should not be already enqueued");
|
|
1130
|
-
const allResults = await Promise.all([
|
|
1131
|
-
result1.summarySubmitted,
|
|
1132
|
-
result1.summaryOpBroadcasted,
|
|
1133
|
-
result1.receivedSummaryAckOrNack,
|
|
1134
|
-
result2.summarySubmitted,
|
|
1135
|
-
result2.summaryOpBroadcasted,
|
|
1136
|
-
result2.receivedSummaryAckOrNack,
|
|
1137
|
-
]);
|
|
1138
|
-
for (const result of allResults) {
|
|
1139
|
-
assert(!result.success, "all results should fail");
|
|
1140
|
-
}
|
|
1141
|
-
});
|
|
1142
|
-
});
|
|
1143
|
-
describe("Summary Start", () => {
|
|
1144
|
-
it("Should summarize immediately if summary ack is missing at startup", async () => {
|
|
1145
|
-
assertRunCounts(0, 0, 0);
|
|
1146
|
-
// Simulate as summary op was in op stream.
|
|
1147
|
-
const summaryTimestamp = Date.now();
|
|
1148
|
-
emitBroadcast(summaryTimestamp);
|
|
1149
|
-
let startStatus = "starting";
|
|
1150
|
-
startRunningSummarizer().then(() => {
|
|
1151
|
-
startStatus = "started";
|
|
1152
|
-
}, () => {
|
|
1153
|
-
startStatus = "failed";
|
|
1154
|
-
});
|
|
1155
|
-
await flushPromises();
|
|
1156
|
-
assert.strictEqual(startStatus, "starting", "RunningSummarizer should still be starting since outstanding summary op");
|
|
1157
|
-
// Still should be waiting
|
|
1158
|
-
await emitNextOp(1, summaryTimestamp + summaryConfig.maxAckWaitTime - 1);
|
|
1159
|
-
assert.strictEqual(startStatus, "starting", "RunningSummarizer should still be starting since timestamp is within maxAckWaitTime");
|
|
1160
|
-
// Emit next op after maxAckWaitTime
|
|
1161
|
-
// clock.tick(summaryConfig.maxAckWaitTime + 1000);
|
|
1162
|
-
await emitNextOp(1, summaryTimestamp + summaryConfig.maxAckWaitTime);
|
|
1163
|
-
assert(mockLogger.matchEvents([
|
|
1164
|
-
{ eventName: "Running:MissingSummaryAckFoundByOps" },
|
|
1165
|
-
]), "unexpected log sequence 1");
|
|
1166
|
-
assert.strictEqual(startStatus, "started", "RunningSummarizer should be started from the above op");
|
|
1167
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
1168
|
-
assertRunCounts(1, 0, 0, "Should run summarizer once");
|
|
1169
|
-
assert(mockLogger.matchEvents([
|
|
1170
|
-
{ eventName: "Running:Summarize_generate", summarizeCount: runCount },
|
|
1171
|
-
{ eventName: "Running:Summarize_Op", summarizeCount: runCount },
|
|
1172
|
-
]), "unexpected log sequence 2");
|
|
1173
|
-
assert(!mockLogger.matchEvents([{ eventName: "Running:Summarize_end" }]), "No ack expected yet");
|
|
1174
|
-
// Now emit ack
|
|
1175
|
-
await emitAck();
|
|
1176
|
-
assert(mockLogger.matchEvents([
|
|
1177
|
-
{
|
|
1178
|
-
eventName: "Running:Summarize_end",
|
|
1179
|
-
summarizeCount: runCount,
|
|
1180
|
-
summarizerSuccessfulAttempts: runCount,
|
|
1181
|
-
summarizeReason: "maxOps",
|
|
1182
|
-
},
|
|
1183
|
-
]), "unexpected log sequence 3");
|
|
1184
|
-
});
|
|
1185
|
-
});
|
|
1186
|
-
describe("Disabled Heuristics", () => {
|
|
1187
|
-
it("Should not summarize after time or ops", async () => {
|
|
1188
|
-
await startRunningSummarizer(true /* disableHeuristics */);
|
|
1189
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
1190
|
-
assertRunCounts(0, 0, 0, "should not summarize after maxOps");
|
|
1191
|
-
await tickAndFlushPromises(summaryConfig.minIdleTime + 1);
|
|
1192
|
-
assertRunCounts(0, 0, 0, "should not summarize after minIdleTime");
|
|
1193
|
-
await tickAndFlushPromises(summaryConfig.maxTime + 1);
|
|
1194
|
-
assertRunCounts(0, 0, 0, "should not summarize after maxTime");
|
|
1195
|
-
await emitNextOp(summaryConfig.maxOps * 3 + 10000);
|
|
1196
|
-
await tickAndFlushPromises(summaryConfig.maxTime * 3 + summaryConfig.minIdleTime * 3 + 10000);
|
|
1197
|
-
assertRunCounts(0, 0, 0, "make extra sure");
|
|
1198
|
-
});
|
|
1199
|
-
it("Should not summarize before closing", async () => {
|
|
1200
|
-
await startRunningSummarizer(true /* disableHeuristics */);
|
|
1201
|
-
await emitNextOp(summaryConfig.minOpsForLastSummaryAttempt);
|
|
1202
|
-
const stopP = summarizer.waitStop(true);
|
|
1203
|
-
await flushPromises();
|
|
1204
|
-
await emitAck();
|
|
1205
|
-
await stopP;
|
|
1206
|
-
assertRunCounts(0, 0, 0, "should not perform lastSummary");
|
|
1207
|
-
});
|
|
1208
|
-
it("Should not summarize immediately if summary ack is missing at startup when disabled", async () => {
|
|
1209
|
-
assertRunCounts(0, 0, 0);
|
|
1210
|
-
// Simulate as summary op was in op stream.
|
|
1211
|
-
const summaryTimestamp = Date.now();
|
|
1212
|
-
emitBroadcast(summaryTimestamp);
|
|
1213
|
-
let startStatus = "starting";
|
|
1214
|
-
startRunningSummarizer(true /* disableHeuristics */).then(() => {
|
|
1215
|
-
startStatus = "started";
|
|
1216
|
-
}, () => {
|
|
1217
|
-
startStatus = "failed";
|
|
1218
|
-
});
|
|
1219
|
-
await flushPromises();
|
|
1220
|
-
assert.strictEqual(startStatus, "starting", "RunningSummarizer should still be starting since outstanding summary op");
|
|
1221
|
-
// Still should be waiting
|
|
1222
|
-
await emitNextOp(1, summaryTimestamp + summaryConfig.maxAckWaitTime - 1);
|
|
1223
|
-
assert.strictEqual(startStatus, "starting", "RunningSummarizer should still be starting since timestamp is within maxAckWaitTime");
|
|
1224
|
-
// Emit next op after maxAckWaitTime
|
|
1225
|
-
// clock.tick(summaryConfig.maxAckWaitTime + 1000);
|
|
1226
|
-
await emitNextOp(1, summaryTimestamp + summaryConfig.maxAckWaitTime);
|
|
1227
|
-
assert(mockLogger.matchEvents([
|
|
1228
|
-
{ eventName: "Running:MissingSummaryAckFoundByOps" },
|
|
1229
|
-
]), "unexpected log sequence 1");
|
|
1230
|
-
assert.strictEqual(startStatus, "started", "RunningSummarizer should be started from the above op");
|
|
1231
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
1232
|
-
assertRunCounts(0, 0, 0, "Should not run summarizer");
|
|
1233
|
-
});
|
|
1234
|
-
});
|
|
1235
|
-
describe("Summarize events", () => {
|
|
1236
|
-
/**
|
|
1237
|
-
* Helper function that creates a promise that would resolve when "summarize" event is emitted.
|
|
1238
|
-
*/
|
|
1239
|
-
async function getSummarizeEventPromise() {
|
|
1240
|
-
return new Promise((resolve) => {
|
|
1241
|
-
const handler = (props) => {
|
|
1242
|
-
summarizer.off("summarize", handler);
|
|
1243
|
-
resolve(props);
|
|
1244
|
-
};
|
|
1245
|
-
summarizer.on("summarize", handler);
|
|
1246
|
-
});
|
|
1247
|
-
}
|
|
1248
|
-
beforeEach(async () => {
|
|
1249
|
-
// Currently, summarize events are only logged with this feature.
|
|
1250
|
-
settings["Fluid.Summarizer.UseDynamicRetries"] = true;
|
|
1251
|
-
});
|
|
1252
|
-
it("should emit summarize event with success result", async () => {
|
|
1253
|
-
await startRunningSummarizer();
|
|
1254
|
-
const summarizePromiseP = getSummarizeEventPromise();
|
|
1255
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
1256
|
-
await emitAck();
|
|
1257
|
-
const eventProps = await summarizePromiseP;
|
|
1258
|
-
const expectedEventProps = {
|
|
1259
|
-
result: "success",
|
|
1260
|
-
currentAttempt: 1,
|
|
1261
|
-
maxAttempts: defaultMaxAttempts,
|
|
1262
|
-
};
|
|
1263
|
-
assert.deepStrictEqual(eventProps, expectedEventProps, "Summarize event not as expected");
|
|
1264
|
-
});
|
|
1265
|
-
it("should emit summarize event with failed result", async () => {
|
|
1266
|
-
await startRunningSummarizer();
|
|
1267
|
-
const summarizePromiseP = getSummarizeEventPromise();
|
|
1268
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
1269
|
-
await emitNack();
|
|
1270
|
-
const { error, ...eventProps } = await summarizePromiseP;
|
|
1271
|
-
const expectedEventProps = {
|
|
1272
|
-
result: "failure",
|
|
1273
|
-
currentAttempt: 1,
|
|
1274
|
-
maxAttempts: defaultMaxAttempts,
|
|
1275
|
-
};
|
|
1276
|
-
assert.deepStrictEqual(eventProps, expectedEventProps, "Summarize event not as expected");
|
|
1277
|
-
});
|
|
1278
|
-
it("should emit summarize event with canceled result", async () => {
|
|
1279
|
-
await startRunningSummarizer(undefined /* disableHeuristics */, undefined /* submitSummaryCallback */, {
|
|
1280
|
-
cancelled: true,
|
|
1281
|
-
waitCancelled: new Promise(() => { }),
|
|
1282
|
-
});
|
|
1283
|
-
const summarizePromiseP = getSummarizeEventPromise();
|
|
1284
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
1285
|
-
await emitNack();
|
|
1286
|
-
const eventProps = await summarizePromiseP;
|
|
1287
|
-
const expectedEventProps = {
|
|
1288
|
-
result: "canceled",
|
|
1289
|
-
currentAttempt: 1,
|
|
1290
|
-
maxAttempts: defaultMaxAttempts,
|
|
1291
|
-
};
|
|
1292
|
-
assert.deepStrictEqual(eventProps, expectedEventProps, "Summarize event not as expected");
|
|
1293
|
-
});
|
|
1294
|
-
it("should emit summarize event for every attempt with nack failure", async () => {
|
|
1295
|
-
await startRunningSummarizer();
|
|
1296
|
-
const retryAfterSeconds = 5;
|
|
1297
|
-
let summarizePromiseP = getSummarizeEventPromise();
|
|
1298
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
1299
|
-
// Nack failures are attempted defaultMaxAttempts times. Each attempt should emit "summarize" event.
|
|
1300
|
-
for (let attemptNumber = 1; attemptNumber <= defaultMaxAttempts; attemptNumber++) {
|
|
1301
|
-
await emitNack(retryAfterSeconds);
|
|
1302
|
-
const { error, ...eventProps } = await summarizePromiseP;
|
|
1303
|
-
const expectedEventProps = {
|
|
1304
|
-
result: "failure",
|
|
1305
|
-
currentAttempt: attemptNumber,
|
|
1306
|
-
maxAttempts: defaultMaxAttempts,
|
|
1307
|
-
};
|
|
1308
|
-
assert.deepStrictEqual(eventProps, expectedEventProps, `Summarize event for attempt ${attemptNumber} not as expected`);
|
|
1309
|
-
summarizePromiseP = getSummarizeEventPromise();
|
|
1310
|
-
// Wait for "retryAfterSeconds". The next attempt should start after this.
|
|
1311
|
-
await tickAndFlushPromises(retryAfterSeconds * 1000 + 1);
|
|
1312
|
-
}
|
|
1313
|
-
});
|
|
1314
|
-
it("should emit summarize event for every attempt with submit failure", async () => {
|
|
1315
|
-
const retryAfterSeconds = 5;
|
|
1316
|
-
// Callback that would result in summarization failed during submit.
|
|
1317
|
-
const submitSummaryCallback = async () => {
|
|
1318
|
-
const error = new RetriableSummaryError(`Fail summarization at base stage`, retryAfterSeconds);
|
|
1319
|
-
const failedResult = {
|
|
1320
|
-
stage: "base",
|
|
1321
|
-
referenceSequenceNumber: lastRefSeq,
|
|
1322
|
-
minimumSequenceNumber: 0,
|
|
1323
|
-
error,
|
|
1324
|
-
};
|
|
1325
|
-
return failedResult;
|
|
1326
|
-
};
|
|
1327
|
-
await startRunningSummarizer(undefined /* disableHeuristics */, submitSummaryCallback);
|
|
1328
|
-
let summarizePromiseP = getSummarizeEventPromise();
|
|
1329
|
-
await emitNextOp(summaryConfig.maxOps + 1);
|
|
1330
|
-
// Submit failures are attempted defaultMaxAttemptsForSubmitFailures times.
|
|
1331
|
-
// Each attempt should emit "summarize" event.
|
|
1332
|
-
for (let attemptNumber = 1; attemptNumber <= defaultMaxAttemptsForSubmitFailures; attemptNumber++) {
|
|
1333
|
-
const { error, ...eventProps } = await summarizePromiseP;
|
|
1334
|
-
const expectedEventProps = {
|
|
1335
|
-
result: "failure",
|
|
1336
|
-
currentAttempt: attemptNumber,
|
|
1337
|
-
maxAttempts: defaultMaxAttemptsForSubmitFailures,
|
|
1338
|
-
};
|
|
1339
|
-
assert.deepStrictEqual(eventProps, expectedEventProps, `Summarize event for attempt ${attemptNumber} not as expected`);
|
|
1340
|
-
summarizePromiseP = getSummarizeEventPromise();
|
|
1341
|
-
// Wait for "retryAfterSeconds". The next attempt should start after this.
|
|
1342
|
-
await tickAndFlushPromises(retryAfterSeconds * 1000 + 1);
|
|
1343
|
-
}
|
|
1344
|
-
});
|
|
1345
|
-
});
|
|
1346
|
-
});
|
|
1347
|
-
});
|
|
1348
|
-
});
|
|
1349
|
-
//# sourceMappingURL=runningSummarizer.spec.js.map
|