@fluidframework/container-runtime 2.0.0-internal.5.3.1 → 2.0.0-internal.5.4.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 +9 -0
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +9 -1
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +55 -12
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +2 -2
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +43 -11
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +189 -137
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +3 -0
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +24 -27
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.js +1 -1
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStores.d.ts +1 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +14 -24
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js +2 -0
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +5 -5
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +12 -5
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +1 -0
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +1 -0
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +15 -22
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/id-compressor/idCompressor.d.ts +3 -3
- package/dist/id-compressor/idCompressor.d.ts.map +1 -1
- package/dist/id-compressor/idCompressor.js +3 -1
- package/dist/id-compressor/idCompressor.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts +2 -2
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +1 -1
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +2 -2
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +1 -1
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +2 -2
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +1 -1
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +6 -5
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +5 -12
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +6 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +7 -1
- 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 +4 -1
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +21 -12
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +1 -1
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +1 -1
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +3 -5
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +10 -28
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.js +1 -1
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +5 -5
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +7 -10
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +4 -3
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +4 -8
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +5 -1
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +2 -3
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +6 -2
- package/dist/summary/summaryManager.js.map +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 +9 -1
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +55 -12
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +3 -3
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +43 -11
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +188 -137
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js +3 -0
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +26 -29
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.js +2 -2
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStores.d.ts +1 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +15 -25
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/lib/deltaManagerSummarizerProxy.js +2 -0
- package/lib/deltaManagerSummarizerProxy.js.map +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +6 -6
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +13 -6
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +1 -0
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +1 -0
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +16 -23
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/id-compressor/idCompressor.d.ts +3 -3
- package/lib/id-compressor/idCompressor.d.ts.map +1 -1
- package/lib/id-compressor/idCompressor.js +3 -1
- package/lib/id-compressor/idCompressor.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts +2 -2
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +2 -2
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts +2 -2
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +2 -2
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +2 -2
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +2 -2
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +6 -5
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +6 -13
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +6 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +7 -1
- 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 +4 -1
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +21 -12
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +2 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +2 -2
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +3 -5
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +11 -29
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.js +2 -2
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +5 -5
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +8 -11
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +4 -3
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +5 -9
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +6 -2
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +2 -3
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +7 -3
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +16 -16
- package/src/batchTracker.ts +2 -2
- package/src/blobManager.ts +70 -13
- package/src/connectionTelemetry.ts +7 -3
- package/src/containerRuntime.ts +287 -150
- package/src/dataStore.ts +3 -0
- package/src/dataStoreContext.ts +31 -33
- package/src/dataStoreContexts.ts +2 -2
- package/src/dataStores.ts +15 -18
- package/src/deltaManagerSummarizerProxy.ts +2 -0
- package/src/deltaScheduler.ts +6 -10
- package/src/gc/garbageCollection.ts +13 -8
- package/src/gc/gcHelpers.ts +1 -0
- package/src/gc/gcTelemetry.ts +12 -8
- package/src/id-compressor/idCompressor.ts +6 -5
- package/src/opLifecycle/opCompressor.ts +4 -3
- package/src/opLifecycle/opDecompressor.ts +4 -3
- package/src/opLifecycle/opSplitter.ts +4 -3
- package/src/opLifecycle/outbox.ts +13 -25
- package/src/opLifecycle/remoteMessageProcessor.ts +8 -2
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +22 -10
- package/src/scheduleManager.ts +2 -2
- package/src/summary/orderedClientElection.ts +2 -2
- package/src/summary/runningSummarizer.ts +18 -44
- package/src/summary/summarizer.ts +2 -2
- package/src/summary/summarizerNode/summarizerNode.ts +13 -15
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +8 -7
- package/src/summary/summaryGenerator.ts +6 -2
- package/src/summary/summaryManager.ts +9 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summaryGenerator.js","sourceRoot":"","sources":["../../src/summary/summaryGenerator.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tITelemetryLoggerExt,\n\tPerformanceEvent,\n\tLoggingError,\n\tChildLogger,\n} from \"@fluidframework/telemetry-utils\";\nimport { ITelemetryProperties } from \"@fluidframework/core-interfaces\";\n\nimport {\n\tassert,\n\tDeferred,\n\tIPromiseTimer,\n\tIPromiseTimerResult,\n\tTimer,\n} from \"@fluidframework/common-utils\";\nimport { MessageType } from \"@fluidframework/protocol-definitions\";\nimport { getRetryDelaySecondsFromError } from \"@fluidframework/driver-utils\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport {\n\tIAckSummaryResult,\n\tINackSummaryResult,\n\tISummarizeOptions,\n\tIBroadcastSummaryResult,\n\tISummarizeResults,\n\tISummarizeHeuristicData,\n\tISubmitSummaryOptions,\n\tSubmitSummaryResult,\n\tSummarizeResultPart,\n\tISummaryCancellationToken,\n\tISummarizeTelemetryProperties,\n\tSummaryGeneratorTelemetry,\n\tSummaryStage,\n\tSubmitSummaryFailureData,\n} from \"./summarizerTypes\";\nimport { IClientSummaryWatcher } from \"./summaryCollection\";\n\nexport type raceTimerResult<T> =\n\t| { result: \"done\"; value: T }\n\t| { result: IPromiseTimerResult[\"timerResult\"] }\n\t| { result: \"cancelled\" };\n\n/** Helper function to wait for a promise or PromiseTimer to elapse. */\nexport async function raceTimer<T>(\n\tpromise: Promise<T>,\n\ttimer: Promise<IPromiseTimerResult>,\n\tcancellationToken?: ISummaryCancellationToken,\n): Promise<raceTimerResult<T>> {\n\tconst promises: Promise<raceTimerResult<T>>[] = [\n\t\tpromise.then((value) => ({ result: \"done\", value } as const)),\n\t\ttimer.then(({ timerResult: result }) => ({ result } as const)),\n\t];\n\tif (cancellationToken !== undefined) {\n\t\tpromises.push(\n\t\t\tcancellationToken.waitCancelled.then(() => ({ result: \"cancelled\" } as const)),\n\t\t);\n\t}\n\treturn Promise.race(promises);\n}\n\n// Send some telemetry if generate summary takes too long\nconst maxSummarizeTimeoutTime = 20000; // 20 sec\nconst maxSummarizeTimeoutCount = 5; // Double and resend 5 times\n\nexport type SummarizeReason =\n\t/**\n\t * Attempt to summarize after idle timeout has elapsed.\n\t * Idle timer restarts whenever an op is received. So this\n\t * triggers only after some amount of time has passed with\n\t * no ops being received.\n\t */\n\t| \"idle\"\n\t/**\n\t * Attempt to summarize after a maximum time since last\n\t * successful summary has passed. This measures time since\n\t * last summary ack op was processed.\n\t */\n\t| \"maxTime\"\n\t/**\n\t * Attempt to summarize after a maximum number of ops have\n\t * passed since the last successful summary. This compares\n\t * op sequence numbers with the reference sequence number\n\t * of the summarize op corresponding to the last summary\n\t * ack op.\n\t */\n\t| \"maxOps\"\n\t/**\n\t * Special case to attempt to summarize one last time before the\n\t * summarizer client closes itself. This is to prevent cases where\n\t * the summarizer client never gets a chance to summarize, because\n\t * there are too many outstanding ops and/or parent client cannot\n\t * stay connected long enough for summarizer client to catch up.\n\t */\n\t| \"lastSummary\"\n\t/** On-demand summary requested with specified reason. */\n\t| `onDemand;${string}`\n\t/** Enqueue summarize attempt with specified reason. */\n\t| `enqueue;${string}`;\n\nconst summarizeErrors = {\n\t/**\n\t * Error encountered while generating the summary tree, uploading\n\t * it to storage, or submitting the op. It could be a result of\n\t * the client becoming disconnected while generating or an actual error.\n\t */\n\tsubmitSummaryFailure: \"Error while generating, uploading, or submitting summary\",\n\t/**\n\t * The summaryAckWaitTimeout time has elapsed before receiving the summarize op\n\t * sent by this summarize attempt. It is expected to be broadcast quickly.\n\t */\n\tsummaryOpWaitTimeout: \"Timeout while waiting for summarize op broadcast\",\n\t/**\n\t * The summaryAckWaitTimeout time has elapsed before receiving either a\n\t * summaryAck or summaryNack op from the server in response to this\n\t * summarize attempt. It is expected that the server should respond.\n\t */\n\tsummaryAckWaitTimeout: \"Timeout while waiting for summaryAck/summaryNack op\",\n\t/**\n\t * The server responded with a summaryNack op, thus rejecting this\n\t * summarize attempt.\n\t */\n\tsummaryNack: \"Server rejected summary via summaryNack op\",\n\n\tdisconnect: \"Summary cancelled due to summarizer or main client disconnect\",\n} as const;\n\n// Helper functions to report failures and return.\nexport const getFailMessage = (errorCode: keyof typeof summarizeErrors) =>\n\t`${errorCode}: ${summarizeErrors[errorCode]}`;\n\nexport class SummarizeResultBuilder {\n\tpublic readonly summarySubmitted = new Deferred<\n\t\tSummarizeResultPart<SubmitSummaryResult, SubmitSummaryFailureData>\n\t>();\n\tpublic readonly summaryOpBroadcasted = new Deferred<\n\t\tSummarizeResultPart<IBroadcastSummaryResult>\n\t>();\n\tpublic readonly receivedSummaryAckOrNack = new Deferred<\n\t\tSummarizeResultPart<IAckSummaryResult, INackSummaryResult>\n\t>();\n\n\tpublic fail(\n\t\tmessage: string,\n\t\terror: any,\n\t\tstage: SummaryStage = \"unknown\",\n\t\tnackSummaryResult?: INackSummaryResult,\n\t\tretryAfterSeconds?: number,\n\t) {\n\t\tassert(\n\t\t\t!this.receivedSummaryAckOrNack.isCompleted,\n\t\t\t0x25e /* \"no reason to call fail if all promises have been completed\" */,\n\t\t);\n\n\t\tconst result: SummarizeResultPart<undefined> = {\n\t\t\tsuccess: false,\n\t\t\tmessage,\n\t\t\tdata: undefined,\n\t\t\terror,\n\t\t\tretryAfterSeconds,\n\t\t} as const;\n\t\tthis.summarySubmitted.resolve({ ...result, data: { stage } });\n\t\tthis.summaryOpBroadcasted.resolve(result);\n\t\tthis.receivedSummaryAckOrNack.resolve({ ...result, data: nackSummaryResult });\n\t}\n\tpublic build(): ISummarizeResults {\n\t\treturn {\n\t\t\tsummarySubmitted: this.summarySubmitted.promise,\n\t\t\tsummaryOpBroadcasted: this.summaryOpBroadcasted.promise,\n\t\t\treceivedSummaryAckOrNack: this.receivedSummaryAckOrNack.promise,\n\t\t} as const;\n\t}\n}\n\n/**\n * Errors type for errors hit during summary that may be retriable.\n */\nexport class RetriableSummaryError extends LoggingError {\n\tpublic readonly canRetry = this.retryAfterSeconds !== undefined;\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly retryAfterSeconds?: number,\n\t\tprops?: ITelemetryProperties,\n\t) {\n\t\tsuper(message, props);\n\t}\n}\n\n/**\n * This class generates and tracks a summary attempt.\n */\nexport class SummaryGenerator {\n\tprivate readonly summarizeTimer: Timer;\n\tconstructor(\n\t\tprivate readonly pendingAckTimer: IPromiseTimer,\n\t\tprivate readonly heuristicData: ISummarizeHeuristicData,\n\t\tprivate readonly submitSummaryCallback: (\n\t\t\toptions: ISubmitSummaryOptions,\n\t\t) => Promise<SubmitSummaryResult>,\n\t\tprivate readonly successfulSummaryCallback: () => void,\n\t\tprivate readonly summaryWatcher: Pick<IClientSummaryWatcher, \"watchSummary\">,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t) {\n\t\tthis.summarizeTimer = new Timer(maxSummarizeTimeoutTime, () =>\n\t\t\tthis.summarizeTimerHandler(maxSummarizeTimeoutTime, 1),\n\t\t);\n\t}\n\n\t/**\n\t * Generates summary and listens for broadcast and ack/nack.\n\t * Returns true for ack, false for nack, and undefined for failure or timeout.\n\t * @param reason - reason for summarizing\n\t * @param options - refreshLatestAck to fetch summary ack info from server,\n\t * fullTree to generate tree without any summary handles even if unchanged\n\t */\n\tpublic summarize(\n\t\tsummarizeProps: ISummarizeTelemetryProperties,\n\t\toptions: ISummarizeOptions,\n\t\tcancellationToken: ISummaryCancellationToken,\n\t\tresultsBuilder = new SummarizeResultBuilder(),\n\t): ISummarizeResults {\n\t\tthis.summarizeCore(summarizeProps, options, resultsBuilder, cancellationToken).catch(\n\t\t\t(error) => {\n\t\t\t\tconst message = \"UnexpectedSummarizeError\";\n\t\t\t\tthis.logger.sendErrorEvent({ eventName: message, ...summarizeProps }, error);\n\t\t\t\tresultsBuilder.fail(message, error);\n\t\t\t},\n\t\t);\n\n\t\treturn resultsBuilder.build();\n\t}\n\n\tprivate async summarizeCore(\n\t\tsummarizeProps: ISummarizeTelemetryProperties,\n\t\toptions: ISummarizeOptions,\n\t\tresultsBuilder: SummarizeResultBuilder,\n\t\tcancellationToken: ISummaryCancellationToken,\n\t): Promise<void> {\n\t\tconst { refreshLatestAck, fullTree } = options;\n\t\tconst logger = ChildLogger.create(this.logger, undefined, { all: summarizeProps });\n\n\t\t// Note: timeSinceLastAttempt and timeSinceLastSummary for the\n\t\t// first summary are basically the time since the summarizer was loaded.\n\t\tconst timeSinceLastAttempt = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n\t\tconst timeSinceLastSummary =\n\t\t\tDate.now() - this.heuristicData.lastSuccessfulSummary.summaryTime;\n\t\tlet summarizeTelemetryProps: SummaryGeneratorTelemetry = {\n\t\t\tfullTree,\n\t\t\ttimeSinceLastAttempt,\n\t\t\ttimeSinceLastSummary,\n\t\t};\n\n\t\tconst summarizeEvent = PerformanceEvent.start(\n\t\t\tlogger,\n\t\t\t{\n\t\t\t\teventName: \"Summarize\",\n\t\t\t\trefreshLatestAck,\n\t\t\t\t...summarizeTelemetryProps,\n\t\t\t},\n\t\t\t{ start: true, end: true, cancel: \"generic\" },\n\t\t);\n\n\t\tlet summaryData: SubmitSummaryResult | undefined;\n\t\tconst fail = (\n\t\t\terrorCode: keyof typeof summarizeErrors,\n\t\t\terror?: any,\n\t\t\tproperties?: SummaryGeneratorTelemetry,\n\t\t\tnackSummaryResult?: INackSummaryResult,\n\t\t) => {\n\t\t\t// UploadSummary may fail with 429 and retryAfter - respect that\n\t\t\t// Summary Nack also can have retryAfter, it's parsed below and comes as a property.\n\t\t\tconst retryAfterSeconds = getRetryDelaySecondsFromError(error);\n\n\t\t\t// Report any failure as an error unless it was due to cancellation (like \"disconnected\" error)\n\t\t\t// If failure happened on upload, we may not yet realized that socket disconnected, so check\n\t\t\t// offlineError too.\n\t\t\tconst category =\n\t\t\t\tcancellationToken.cancelled || error?.errorType === DriverErrorType.offlineError\n\t\t\t\t\t? \"generic\"\n\t\t\t\t\t: \"error\";\n\n\t\t\tconst reason = getFailMessage(errorCode);\n\t\t\tsummarizeEvent.cancel(\n\t\t\t\t{\n\t\t\t\t\t...properties,\n\t\t\t\t\treason,\n\t\t\t\t\tcategory,\n\t\t\t\t\tretryAfterSeconds,\n\t\t\t\t},\n\t\t\t\terror ?? reason,\n\t\t\t); // disconnect & summaryAckTimeout do not have proper error.\n\n\t\t\t// If summarize did not hit an unexpected error, summaryData would be available. Otherwise, the state is\n\t\t\t// unknown.\n\t\t\tconst stage = summaryData?.stage ?? \"unknown\";\n\t\t\tresultsBuilder.fail(reason, error, stage, nackSummaryResult, retryAfterSeconds);\n\t\t};\n\n\t\t// Wait to generate and send summary\n\t\tthis.summarizeTimer.start();\n\t\ttry {\n\t\t\t// Need to save refSeqNum before we record new attempt (happens as part of submitSummaryCallback)\n\t\t\tconst lastAttemptRefSeqNum = this.heuristicData.lastAttempt.refSequenceNumber;\n\n\t\t\tsummaryData = await this.submitSummaryCallback({\n\t\t\t\tfullTree,\n\t\t\t\trefreshLatestAck,\n\t\t\t\tsummaryLogger: logger,\n\t\t\t\tcancellationToken,\n\t\t\t});\n\n\t\t\t// Cumulatively add telemetry properties based on how far generateSummary went.\n\t\t\tconst referenceSequenceNumber = summaryData.referenceSequenceNumber;\n\t\t\tsummarizeTelemetryProps = {\n\t\t\t\t...summarizeTelemetryProps,\n\t\t\t\treferenceSequenceNumber,\n\t\t\t\tminimumSequenceNumber: summaryData.minimumSequenceNumber,\n\t\t\t\topsSinceLastAttempt: referenceSequenceNumber - lastAttemptRefSeqNum,\n\t\t\t\topsSinceLastSummary:\n\t\t\t\t\treferenceSequenceNumber -\n\t\t\t\t\tthis.heuristicData.lastSuccessfulSummary.refSequenceNumber,\n\t\t\t\tstage: summaryData.stage,\n\t\t\t};\n\t\t\tsummarizeTelemetryProps = this.addSummaryDataToTelemetryProps(\n\t\t\t\tsummaryData,\n\t\t\t\tsummarizeTelemetryProps,\n\t\t\t);\n\n\t\t\tif (summaryData.stage !== \"submit\") {\n\t\t\t\treturn fail(\"submitSummaryFailure\", summaryData.error, summarizeTelemetryProps);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * With incremental summaries, if the full tree was not summarized, only data stores that changed should\n\t\t\t * be summarized. A data store is considered changed if either or both of the following is true:\n\t\t\t * - It has received an op.\n\t\t\t * - Its reference state changed, i.e., it went from referenced to unreferenced or vice-versa.\n\t\t\t *\n\t\t\t * In the extreme case, every op can be for a different data store and each op can result in the reference\n\t\t\t * state change of multiple data stores. So, the total number of data stores that are summarized should not\n\t\t\t * exceed the number of ops since last summary + number of data store whose reference state changed.\n\t\t\t */\n\t\t\tif (!fullTree && !summaryData.forcedFullTree) {\n\t\t\t\tconst { summarizedDataStoreCount, gcStateUpdatedDataStoreCount = 0 } =\n\t\t\t\t\tsummaryData.summaryStats;\n\t\t\t\tif (\n\t\t\t\t\tsummarizedDataStoreCount >\n\t\t\t\t\tgcStateUpdatedDataStoreCount + this.heuristicData.opsSinceLastSummary\n\t\t\t\t) {\n\t\t\t\t\tlogger.sendErrorEvent({\n\t\t\t\t\t\teventName: \"IncrementalSummaryViolation\",\n\t\t\t\t\t\tsummarizedDataStoreCount,\n\t\t\t\t\t\tgcStateUpdatedDataStoreCount,\n\t\t\t\t\t\topsSinceLastSummary: this.heuristicData.opsSinceLastSummary,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Log event here on summary success only, as Summarize_cancel duplicates failure logging.\n\t\t\tsummarizeEvent.reportEvent(\"generate\", { ...summarizeTelemetryProps });\n\t\t\tresultsBuilder.summarySubmitted.resolve({ success: true, data: summaryData });\n\t\t} catch (error) {\n\t\t\treturn fail(\"submitSummaryFailure\", error);\n\t\t} finally {\n\t\t\tif (summaryData === undefined) {\n\t\t\t\tthis.heuristicData.recordAttempt();\n\t\t\t}\n\t\t\tthis.summarizeTimer.clear();\n\t\t}\n\n\t\ttry {\n\t\t\tconst pendingTimeoutP = this.pendingAckTimer.start();\n\t\t\tconst summary = this.summaryWatcher.watchSummary(summaryData.clientSequenceNumber);\n\n\t\t\t// Wait for broadcast\n\t\t\tconst waitBroadcastResult = await raceTimer(\n\t\t\t\tsummary.waitBroadcast(),\n\t\t\t\tpendingTimeoutP,\n\t\t\t\tcancellationToken,\n\t\t\t);\n\t\t\tif (waitBroadcastResult.result === \"cancelled\") {\n\t\t\t\treturn fail(\"disconnect\", summaryData.stage);\n\t\t\t}\n\t\t\tif (waitBroadcastResult.result !== \"done\") {\n\t\t\t\treturn fail(\"summaryOpWaitTimeout\", summaryData.stage);\n\t\t\t}\n\t\t\tconst summarizeOp = waitBroadcastResult.value;\n\n\t\t\tconst broadcastDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n\t\t\tresultsBuilder.summaryOpBroadcasted.resolve({\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: { summarizeOp, broadcastDuration },\n\t\t\t});\n\n\t\t\tthis.heuristicData.lastAttempt.summarySequenceNumber = summarizeOp.sequenceNumber;\n\t\t\tlogger.sendTelemetryEvent({\n\t\t\t\teventName: \"Summarize_Op\",\n\t\t\t\tduration: broadcastDuration,\n\t\t\t\treferenceSequenceNumber: summarizeOp.referenceSequenceNumber,\n\t\t\t\tsummarySequenceNumber: summarizeOp.sequenceNumber,\n\t\t\t\thandle: summarizeOp.contents.handle,\n\t\t\t});\n\n\t\t\t// Wait for ack/nack\n\t\t\tconst waitAckNackResult = await raceTimer(\n\t\t\t\tsummary.waitAckNack(),\n\t\t\t\tpendingTimeoutP,\n\t\t\t\tcancellationToken,\n\t\t\t);\n\t\t\tif (waitAckNackResult.result === \"cancelled\") {\n\t\t\t\treturn fail(\"disconnect\");\n\t\t\t}\n\t\t\tif (waitAckNackResult.result !== \"done\") {\n\t\t\t\treturn fail(\"summaryAckWaitTimeout\");\n\t\t\t}\n\t\t\tconst ackNackOp = waitAckNackResult.value;\n\t\t\tthis.pendingAckTimer.clear();\n\n\t\t\t// Update for success/failure\n\t\t\tconst ackNackDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n\n\t\t\t// adding new properties\n\t\t\tsummarizeTelemetryProps = {\n\t\t\t\tackWaitDuration: ackNackDuration,\n\t\t\t\tackNackSequenceNumber: ackNackOp.sequenceNumber,\n\t\t\t\tsummarySequenceNumber: ackNackOp.contents.summaryProposal.summarySequenceNumber,\n\t\t\t\t...summarizeTelemetryProps,\n\t\t\t};\n\t\t\tif (ackNackOp.type === MessageType.SummaryAck) {\n\t\t\t\tthis.heuristicData.markLastAttemptAsSuccessful();\n\t\t\t\tthis.successfulSummaryCallback();\n\t\t\t\tsummarizeEvent.end({\n\t\t\t\t\t...summarizeTelemetryProps,\n\t\t\t\t\thandle: ackNackOp.contents.handle,\n\t\t\t\t});\n\t\t\t\tresultsBuilder.receivedSummaryAckOrNack.resolve({\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tsummaryAckOp: ackNackOp,\n\t\t\t\t\t\tackNackDuration,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Check for retryDelay in summaryNack response.\n\t\t\t\tassert(ackNackOp.type === MessageType.SummaryNack, 0x274 /* \"type check\" */);\n\t\t\t\tconst summaryNack = ackNackOp.contents;\n\t\t\t\tconst errorMessage = summaryNack?.message;\n\t\t\t\tconst retryAfterSeconds = summaryNack?.retryAfter;\n\n\t\t\t\t// pre-0.58 error message prefix: summaryNack\n\t\t\t\tconst error = new LoggingError(`Received summaryNack`, {\n\t\t\t\t\tretryAfterSeconds,\n\t\t\t\t\terrorMessage,\n\t\t\t\t});\n\n\t\t\t\tassert(\n\t\t\t\t\tgetRetryDelaySecondsFromError(error) === retryAfterSeconds,\n\t\t\t\t\t0x25f /* \"retryAfterSeconds\" */,\n\t\t\t\t);\n\t\t\t\t// This will only set resultsBuilder.receivedSummaryAckOrNack, as other promises are already set.\n\t\t\t\treturn fail(\n\t\t\t\t\t\"summaryNack\",\n\t\t\t\t\terror,\n\t\t\t\t\t{ ...summarizeTelemetryProps, nackRetryAfter: retryAfterSeconds },\n\t\t\t\t\t{ summaryNackOp: ackNackOp, ackNackDuration },\n\t\t\t\t);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.pendingAckTimer.clear();\n\t\t}\n\t}\n\n\tprivate addSummaryDataToTelemetryProps(\n\t\tsummaryData: SubmitSummaryResult,\n\t\tinitialProps: SummaryGeneratorTelemetry,\n\t): SummaryGeneratorTelemetry {\n\t\tswitch (summaryData.stage) {\n\t\t\tcase \"base\":\n\t\t\t\treturn initialProps;\n\n\t\t\tcase \"generate\":\n\t\t\t\treturn {\n\t\t\t\t\t...initialProps,\n\t\t\t\t\t...summaryData.summaryStats,\n\t\t\t\t\tgenerateDuration: summaryData.generateDuration,\n\t\t\t\t};\n\n\t\t\tcase \"upload\":\n\t\t\t\treturn {\n\t\t\t\t\t...initialProps,\n\t\t\t\t\t...summaryData.summaryStats,\n\t\t\t\t\tgenerateDuration: summaryData.generateDuration,\n\t\t\t\t\thandle: summaryData.handle,\n\t\t\t\t\tuploadDuration: summaryData.uploadDuration,\n\t\t\t\t};\n\n\t\t\tcase \"submit\":\n\t\t\t\treturn {\n\t\t\t\t\t...initialProps,\n\t\t\t\t\t...summaryData.summaryStats,\n\t\t\t\t\tgenerateDuration: summaryData.generateDuration,\n\t\t\t\t\thandle: summaryData.handle,\n\t\t\t\t\tuploadDuration: summaryData.uploadDuration,\n\t\t\t\t\tclientSequenceNumber: summaryData.clientSequenceNumber,\n\t\t\t\t\thasMissingOpData: this.heuristicData.hasMissingOpData,\n\t\t\t\t\topsSizesSinceLastSummary: this.heuristicData.totalOpsSize,\n\t\t\t\t\tnonRuntimeOpsSinceLastSummary: this.heuristicData.numNonRuntimeOps,\n\t\t\t\t\truntimeOpsSinceLastSummary: this.heuristicData.numRuntimeOps,\n\t\t\t\t};\n\n\t\t\tdefault:\n\t\t\t\tassert(true, 0x397 /* Unexpected summary stage */);\n\t\t}\n\n\t\treturn initialProps;\n\t}\n\n\tprivate summarizeTimerHandler(time: number, count: number) {\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\teventName: \"SummarizeTimeout\",\n\t\t\ttimeoutTime: time,\n\t\t\ttimeoutCount: count,\n\t\t});\n\t\tif (count < maxSummarizeTimeoutCount) {\n\t\t\t// Double and start a new timer\n\t\t\tconst nextTime = time * 2;\n\t\t\tthis.summarizeTimer.start(nextTime, () =>\n\t\t\t\tthis.summarizeTimerHandler(nextTime, count + 1),\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic dispose() {\n\t\tthis.summarizeTimer.clear();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"summaryGenerator.js","sourceRoot":"","sources":["../../src/summary/summaryGenerator.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tITelemetryLoggerExt,\n\tPerformanceEvent,\n\tLoggingError,\n\tcreateChildLogger,\n} from \"@fluidframework/telemetry-utils\";\nimport { ITelemetryProperties } from \"@fluidframework/core-interfaces\";\n\nimport {\n\tassert,\n\tDeferred,\n\tIPromiseTimer,\n\tIPromiseTimerResult,\n\tTimer,\n} from \"@fluidframework/common-utils\";\nimport { MessageType } from \"@fluidframework/protocol-definitions\";\nimport { getRetryDelaySecondsFromError } from \"@fluidframework/driver-utils\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport {\n\tIAckSummaryResult,\n\tINackSummaryResult,\n\tISummarizeOptions,\n\tIBroadcastSummaryResult,\n\tISummarizeResults,\n\tISummarizeHeuristicData,\n\tISubmitSummaryOptions,\n\tSubmitSummaryResult,\n\tSummarizeResultPart,\n\tISummaryCancellationToken,\n\tISummarizeTelemetryProperties,\n\tSummaryGeneratorTelemetry,\n\tSummaryStage,\n\tSubmitSummaryFailureData,\n} from \"./summarizerTypes\";\nimport { IClientSummaryWatcher } from \"./summaryCollection\";\n\nexport type raceTimerResult<T> =\n\t| { result: \"done\"; value: T }\n\t| { result: IPromiseTimerResult[\"timerResult\"] }\n\t| { result: \"cancelled\" };\n\n/** Helper function to wait for a promise or PromiseTimer to elapse. */\nexport async function raceTimer<T>(\n\tpromise: Promise<T>,\n\ttimer: Promise<IPromiseTimerResult>,\n\tcancellationToken?: ISummaryCancellationToken,\n): Promise<raceTimerResult<T>> {\n\tconst promises: Promise<raceTimerResult<T>>[] = [\n\t\tpromise.then((value) => ({ result: \"done\", value } as const)),\n\t\ttimer.then(({ timerResult: result }) => ({ result } as const)),\n\t];\n\tif (cancellationToken !== undefined) {\n\t\tpromises.push(\n\t\t\tcancellationToken.waitCancelled.then(() => ({ result: \"cancelled\" } as const)),\n\t\t);\n\t}\n\treturn Promise.race(promises);\n}\n\n// Send some telemetry if generate summary takes too long\nconst maxSummarizeTimeoutTime = 20000; // 20 sec\nconst maxSummarizeTimeoutCount = 5; // Double and resend 5 times\n\nexport type SummarizeReason =\n\t/**\n\t * Attempt to summarize after idle timeout has elapsed.\n\t * Idle timer restarts whenever an op is received. So this\n\t * triggers only after some amount of time has passed with\n\t * no ops being received.\n\t */\n\t| \"idle\"\n\t/**\n\t * Attempt to summarize after a maximum time since last\n\t * successful summary has passed. This measures time since\n\t * last summary ack op was processed.\n\t */\n\t| \"maxTime\"\n\t/**\n\t * Attempt to summarize after a maximum number of ops have\n\t * passed since the last successful summary. This compares\n\t * op sequence numbers with the reference sequence number\n\t * of the summarize op corresponding to the last summary\n\t * ack op.\n\t */\n\t| \"maxOps\"\n\t/**\n\t * Special case to attempt to summarize one last time before the\n\t * summarizer client closes itself. This is to prevent cases where\n\t * the summarizer client never gets a chance to summarize, because\n\t * there are too many outstanding ops and/or parent client cannot\n\t * stay connected long enough for summarizer client to catch up.\n\t */\n\t| \"lastSummary\"\n\t/** On-demand summary requested with specified reason. */\n\t| `onDemand;${string}`\n\t/** Enqueue summarize attempt with specified reason. */\n\t| `enqueue;${string}`;\n\nconst summarizeErrors = {\n\t/**\n\t * Error encountered while generating the summary tree, uploading\n\t * it to storage, or submitting the op. It could be a result of\n\t * the client becoming disconnected while generating or an actual error.\n\t */\n\tsubmitSummaryFailure: \"Error while generating, uploading, or submitting summary\",\n\t/**\n\t * The summaryAckWaitTimeout time has elapsed before receiving the summarize op\n\t * sent by this summarize attempt. It is expected to be broadcast quickly.\n\t */\n\tsummaryOpWaitTimeout: \"Timeout while waiting for summarize op broadcast\",\n\t/**\n\t * The summaryAckWaitTimeout time has elapsed before receiving either a\n\t * summaryAck or summaryNack op from the server in response to this\n\t * summarize attempt. It is expected that the server should respond.\n\t */\n\tsummaryAckWaitTimeout: \"Timeout while waiting for summaryAck/summaryNack op\",\n\t/**\n\t * The server responded with a summaryNack op, thus rejecting this\n\t * summarize attempt.\n\t */\n\tsummaryNack: \"Server rejected summary via summaryNack op\",\n\n\tdisconnect: \"Summary cancelled due to summarizer or main client disconnect\",\n} as const;\n\n// Helper functions to report failures and return.\nexport const getFailMessage = (errorCode: keyof typeof summarizeErrors) =>\n\t`${errorCode}: ${summarizeErrors[errorCode]}`;\n\nexport class SummarizeResultBuilder {\n\tpublic readonly summarySubmitted = new Deferred<\n\t\tSummarizeResultPart<SubmitSummaryResult, SubmitSummaryFailureData>\n\t>();\n\tpublic readonly summaryOpBroadcasted = new Deferred<\n\t\tSummarizeResultPart<IBroadcastSummaryResult>\n\t>();\n\tpublic readonly receivedSummaryAckOrNack = new Deferred<\n\t\tSummarizeResultPart<IAckSummaryResult, INackSummaryResult>\n\t>();\n\n\tpublic fail(\n\t\tmessage: string,\n\t\terror: any,\n\t\tstage: SummaryStage = \"unknown\",\n\t\tnackSummaryResult?: INackSummaryResult,\n\t\tretryAfterSeconds?: number,\n\t) {\n\t\tassert(\n\t\t\t!this.receivedSummaryAckOrNack.isCompleted,\n\t\t\t0x25e /* \"no reason to call fail if all promises have been completed\" */,\n\t\t);\n\n\t\tconst result: SummarizeResultPart<undefined> = {\n\t\t\tsuccess: false,\n\t\t\tmessage,\n\t\t\tdata: undefined,\n\t\t\terror,\n\t\t\tretryAfterSeconds,\n\t\t} as const;\n\t\tthis.summarySubmitted.resolve({ ...result, data: { stage } });\n\t\tthis.summaryOpBroadcasted.resolve(result);\n\t\tthis.receivedSummaryAckOrNack.resolve({ ...result, data: nackSummaryResult });\n\t}\n\tpublic build(): ISummarizeResults {\n\t\treturn {\n\t\t\tsummarySubmitted: this.summarySubmitted.promise,\n\t\t\tsummaryOpBroadcasted: this.summaryOpBroadcasted.promise,\n\t\t\treceivedSummaryAckOrNack: this.receivedSummaryAckOrNack.promise,\n\t\t} as const;\n\t}\n}\n\n/**\n * Errors type for errors hit during summary that may be retriable.\n */\nexport class RetriableSummaryError extends LoggingError {\n\tpublic readonly canRetry = this.retryAfterSeconds !== undefined;\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly retryAfterSeconds?: number,\n\t\tprops?: ITelemetryProperties,\n\t) {\n\t\tsuper(message, props);\n\t}\n}\n\n/**\n * This class generates and tracks a summary attempt.\n */\nexport class SummaryGenerator {\n\tprivate readonly summarizeTimer: Timer;\n\tconstructor(\n\t\tprivate readonly pendingAckTimer: IPromiseTimer,\n\t\tprivate readonly heuristicData: ISummarizeHeuristicData,\n\t\tprivate readonly submitSummaryCallback: (\n\t\t\toptions: ISubmitSummaryOptions,\n\t\t) => Promise<SubmitSummaryResult>,\n\t\tprivate readonly successfulSummaryCallback: () => void,\n\t\tprivate readonly summaryWatcher: Pick<IClientSummaryWatcher, \"watchSummary\">,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t) {\n\t\tthis.summarizeTimer = new Timer(maxSummarizeTimeoutTime, () =>\n\t\t\tthis.summarizeTimerHandler(maxSummarizeTimeoutTime, 1),\n\t\t);\n\t}\n\n\t/**\n\t * Generates summary and listens for broadcast and ack/nack.\n\t * Returns true for ack, false for nack, and undefined for failure or timeout.\n\t * @param reason - reason for summarizing\n\t * @param options - refreshLatestAck to fetch summary ack info from server,\n\t * fullTree to generate tree without any summary handles even if unchanged\n\t */\n\tpublic summarize(\n\t\tsummarizeProps: ISummarizeTelemetryProperties,\n\t\toptions: ISummarizeOptions,\n\t\tcancellationToken: ISummaryCancellationToken,\n\t\tresultsBuilder = new SummarizeResultBuilder(),\n\t): ISummarizeResults {\n\t\tthis.summarizeCore(summarizeProps, options, resultsBuilder, cancellationToken).catch(\n\t\t\t(error) => {\n\t\t\t\tconst message = \"UnexpectedSummarizeError\";\n\t\t\t\tthis.logger.sendErrorEvent({ eventName: message, ...summarizeProps }, error);\n\t\t\t\tresultsBuilder.fail(message, error);\n\t\t\t},\n\t\t);\n\n\t\treturn resultsBuilder.build();\n\t}\n\n\tprivate async summarizeCore(\n\t\tsummarizeProps: ISummarizeTelemetryProperties,\n\t\toptions: ISummarizeOptions,\n\t\tresultsBuilder: SummarizeResultBuilder,\n\t\tcancellationToken: ISummaryCancellationToken,\n\t): Promise<void> {\n\t\tconst { refreshLatestAck, fullTree } = options;\n\t\tconst logger = createChildLogger({\n\t\t\tlogger: this.logger,\n\t\t\tnamespace: undefined,\n\t\t\tproperties: { all: summarizeProps },\n\t\t});\n\n\t\t// Note: timeSinceLastAttempt and timeSinceLastSummary for the\n\t\t// first summary are basically the time since the summarizer was loaded.\n\t\tconst timeSinceLastAttempt = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n\t\tconst timeSinceLastSummary =\n\t\t\tDate.now() - this.heuristicData.lastSuccessfulSummary.summaryTime;\n\t\tlet summarizeTelemetryProps: SummaryGeneratorTelemetry = {\n\t\t\tfullTree,\n\t\t\ttimeSinceLastAttempt,\n\t\t\ttimeSinceLastSummary,\n\t\t};\n\n\t\tconst summarizeEvent = PerformanceEvent.start(\n\t\t\tlogger,\n\t\t\t{\n\t\t\t\teventName: \"Summarize\",\n\t\t\t\trefreshLatestAck,\n\t\t\t\t...summarizeTelemetryProps,\n\t\t\t},\n\t\t\t{ start: true, end: true, cancel: \"generic\" },\n\t\t);\n\n\t\tlet summaryData: SubmitSummaryResult | undefined;\n\t\tconst fail = (\n\t\t\terrorCode: keyof typeof summarizeErrors,\n\t\t\terror?: any,\n\t\t\tproperties?: SummaryGeneratorTelemetry,\n\t\t\tnackSummaryResult?: INackSummaryResult,\n\t\t) => {\n\t\t\t// UploadSummary may fail with 429 and retryAfter - respect that\n\t\t\t// Summary Nack also can have retryAfter, it's parsed below and comes as a property.\n\t\t\tconst retryAfterSeconds = getRetryDelaySecondsFromError(error);\n\n\t\t\t// Report any failure as an error unless it was due to cancellation (like \"disconnected\" error)\n\t\t\t// If failure happened on upload, we may not yet realized that socket disconnected, so check\n\t\t\t// offlineError too.\n\t\t\tconst category =\n\t\t\t\tcancellationToken.cancelled || error?.errorType === DriverErrorType.offlineError\n\t\t\t\t\t? \"generic\"\n\t\t\t\t\t: \"error\";\n\n\t\t\tconst reason = getFailMessage(errorCode);\n\t\t\tsummarizeEvent.cancel(\n\t\t\t\t{\n\t\t\t\t\t...properties,\n\t\t\t\t\treason,\n\t\t\t\t\tcategory,\n\t\t\t\t\tretryAfterSeconds,\n\t\t\t\t},\n\t\t\t\terror ?? reason,\n\t\t\t); // disconnect & summaryAckTimeout do not have proper error.\n\n\t\t\t// If summarize did not hit an unexpected error, summaryData would be available. Otherwise, the state is\n\t\t\t// unknown.\n\t\t\tconst stage = summaryData?.stage ?? \"unknown\";\n\t\t\tresultsBuilder.fail(reason, error, stage, nackSummaryResult, retryAfterSeconds);\n\t\t};\n\n\t\t// Wait to generate and send summary\n\t\tthis.summarizeTimer.start();\n\t\ttry {\n\t\t\t// Need to save refSeqNum before we record new attempt (happens as part of submitSummaryCallback)\n\t\t\tconst lastAttemptRefSeqNum = this.heuristicData.lastAttempt.refSequenceNumber;\n\n\t\t\tsummaryData = await this.submitSummaryCallback({\n\t\t\t\tfullTree,\n\t\t\t\trefreshLatestAck,\n\t\t\t\tsummaryLogger: logger,\n\t\t\t\tcancellationToken,\n\t\t\t});\n\n\t\t\t// Cumulatively add telemetry properties based on how far generateSummary went.\n\t\t\tconst referenceSequenceNumber = summaryData.referenceSequenceNumber;\n\t\t\tsummarizeTelemetryProps = {\n\t\t\t\t...summarizeTelemetryProps,\n\t\t\t\treferenceSequenceNumber,\n\t\t\t\tminimumSequenceNumber: summaryData.minimumSequenceNumber,\n\t\t\t\topsSinceLastAttempt: referenceSequenceNumber - lastAttemptRefSeqNum,\n\t\t\t\topsSinceLastSummary:\n\t\t\t\t\treferenceSequenceNumber -\n\t\t\t\t\tthis.heuristicData.lastSuccessfulSummary.refSequenceNumber,\n\t\t\t\tstage: summaryData.stage,\n\t\t\t};\n\t\t\tsummarizeTelemetryProps = this.addSummaryDataToTelemetryProps(\n\t\t\t\tsummaryData,\n\t\t\t\tsummarizeTelemetryProps,\n\t\t\t);\n\n\t\t\tif (summaryData.stage !== \"submit\") {\n\t\t\t\treturn fail(\"submitSummaryFailure\", summaryData.error, summarizeTelemetryProps);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * With incremental summaries, if the full tree was not summarized, only data stores that changed should\n\t\t\t * be summarized. A data store is considered changed if either or both of the following is true:\n\t\t\t * - It has received an op.\n\t\t\t * - Its reference state changed, i.e., it went from referenced to unreferenced or vice-versa.\n\t\t\t *\n\t\t\t * In the extreme case, every op can be for a different data store and each op can result in the reference\n\t\t\t * state change of multiple data stores. So, the total number of data stores that are summarized should not\n\t\t\t * exceed the number of ops since last summary + number of data store whose reference state changed.\n\t\t\t */\n\t\t\tif (!fullTree && !summaryData.forcedFullTree) {\n\t\t\t\tconst { summarizedDataStoreCount, gcStateUpdatedDataStoreCount = 0 } =\n\t\t\t\t\tsummaryData.summaryStats;\n\t\t\t\tif (\n\t\t\t\t\tsummarizedDataStoreCount >\n\t\t\t\t\tgcStateUpdatedDataStoreCount + this.heuristicData.opsSinceLastSummary\n\t\t\t\t) {\n\t\t\t\t\tlogger.sendErrorEvent({\n\t\t\t\t\t\teventName: \"IncrementalSummaryViolation\",\n\t\t\t\t\t\tsummarizedDataStoreCount,\n\t\t\t\t\t\tgcStateUpdatedDataStoreCount,\n\t\t\t\t\t\topsSinceLastSummary: this.heuristicData.opsSinceLastSummary,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Log event here on summary success only, as Summarize_cancel duplicates failure logging.\n\t\t\tsummarizeEvent.reportEvent(\"generate\", { ...summarizeTelemetryProps });\n\t\t\tresultsBuilder.summarySubmitted.resolve({ success: true, data: summaryData });\n\t\t} catch (error) {\n\t\t\treturn fail(\"submitSummaryFailure\", error);\n\t\t} finally {\n\t\t\tif (summaryData === undefined) {\n\t\t\t\tthis.heuristicData.recordAttempt();\n\t\t\t}\n\t\t\tthis.summarizeTimer.clear();\n\t\t}\n\n\t\ttry {\n\t\t\tconst pendingTimeoutP = this.pendingAckTimer.start();\n\t\t\tconst summary = this.summaryWatcher.watchSummary(summaryData.clientSequenceNumber);\n\n\t\t\t// Wait for broadcast\n\t\t\tconst waitBroadcastResult = await raceTimer(\n\t\t\t\tsummary.waitBroadcast(),\n\t\t\t\tpendingTimeoutP,\n\t\t\t\tcancellationToken,\n\t\t\t);\n\t\t\tif (waitBroadcastResult.result === \"cancelled\") {\n\t\t\t\treturn fail(\"disconnect\", summaryData.stage);\n\t\t\t}\n\t\t\tif (waitBroadcastResult.result !== \"done\") {\n\t\t\t\treturn fail(\"summaryOpWaitTimeout\", summaryData.stage);\n\t\t\t}\n\t\t\tconst summarizeOp = waitBroadcastResult.value;\n\n\t\t\tconst broadcastDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n\t\t\tresultsBuilder.summaryOpBroadcasted.resolve({\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: { summarizeOp, broadcastDuration },\n\t\t\t});\n\n\t\t\tthis.heuristicData.lastAttempt.summarySequenceNumber = summarizeOp.sequenceNumber;\n\t\t\tlogger.sendTelemetryEvent({\n\t\t\t\teventName: \"Summarize_Op\",\n\t\t\t\tduration: broadcastDuration,\n\t\t\t\treferenceSequenceNumber: summarizeOp.referenceSequenceNumber,\n\t\t\t\tsummarySequenceNumber: summarizeOp.sequenceNumber,\n\t\t\t\thandle: summarizeOp.contents.handle,\n\t\t\t});\n\n\t\t\t// Wait for ack/nack\n\t\t\tconst waitAckNackResult = await raceTimer(\n\t\t\t\tsummary.waitAckNack(),\n\t\t\t\tpendingTimeoutP,\n\t\t\t\tcancellationToken,\n\t\t\t);\n\t\t\tif (waitAckNackResult.result === \"cancelled\") {\n\t\t\t\treturn fail(\"disconnect\");\n\t\t\t}\n\t\t\tif (waitAckNackResult.result !== \"done\") {\n\t\t\t\treturn fail(\"summaryAckWaitTimeout\");\n\t\t\t}\n\t\t\tconst ackNackOp = waitAckNackResult.value;\n\t\t\tthis.pendingAckTimer.clear();\n\n\t\t\t// Update for success/failure\n\t\t\tconst ackNackDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n\n\t\t\t// adding new properties\n\t\t\tsummarizeTelemetryProps = {\n\t\t\t\tackWaitDuration: ackNackDuration,\n\t\t\t\tackNackSequenceNumber: ackNackOp.sequenceNumber,\n\t\t\t\tsummarySequenceNumber: ackNackOp.contents.summaryProposal.summarySequenceNumber,\n\t\t\t\t...summarizeTelemetryProps,\n\t\t\t};\n\t\t\tif (ackNackOp.type === MessageType.SummaryAck) {\n\t\t\t\tthis.heuristicData.markLastAttemptAsSuccessful();\n\t\t\t\tthis.successfulSummaryCallback();\n\t\t\t\tsummarizeEvent.end({\n\t\t\t\t\t...summarizeTelemetryProps,\n\t\t\t\t\thandle: ackNackOp.contents.handle,\n\t\t\t\t});\n\t\t\t\tresultsBuilder.receivedSummaryAckOrNack.resolve({\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tsummaryAckOp: ackNackOp,\n\t\t\t\t\t\tackNackDuration,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Check for retryDelay in summaryNack response.\n\t\t\t\tassert(ackNackOp.type === MessageType.SummaryNack, 0x274 /* \"type check\" */);\n\t\t\t\tconst summaryNack = ackNackOp.contents;\n\t\t\t\tconst errorMessage = summaryNack?.message;\n\t\t\t\tconst retryAfterSeconds = summaryNack?.retryAfter;\n\n\t\t\t\t// pre-0.58 error message prefix: summaryNack\n\t\t\t\tconst error = new LoggingError(`Received summaryNack`, {\n\t\t\t\t\tretryAfterSeconds,\n\t\t\t\t\terrorMessage,\n\t\t\t\t});\n\n\t\t\t\tassert(\n\t\t\t\t\tgetRetryDelaySecondsFromError(error) === retryAfterSeconds,\n\t\t\t\t\t0x25f /* \"retryAfterSeconds\" */,\n\t\t\t\t);\n\t\t\t\t// This will only set resultsBuilder.receivedSummaryAckOrNack, as other promises are already set.\n\t\t\t\treturn fail(\n\t\t\t\t\t\"summaryNack\",\n\t\t\t\t\terror,\n\t\t\t\t\t{ ...summarizeTelemetryProps, nackRetryAfter: retryAfterSeconds },\n\t\t\t\t\t{ summaryNackOp: ackNackOp, ackNackDuration },\n\t\t\t\t);\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.pendingAckTimer.clear();\n\t\t}\n\t}\n\n\tprivate addSummaryDataToTelemetryProps(\n\t\tsummaryData: SubmitSummaryResult,\n\t\tinitialProps: SummaryGeneratorTelemetry,\n\t): SummaryGeneratorTelemetry {\n\t\tswitch (summaryData.stage) {\n\t\t\tcase \"base\":\n\t\t\t\treturn initialProps;\n\n\t\t\tcase \"generate\":\n\t\t\t\treturn {\n\t\t\t\t\t...initialProps,\n\t\t\t\t\t...summaryData.summaryStats,\n\t\t\t\t\tgenerateDuration: summaryData.generateDuration,\n\t\t\t\t};\n\n\t\t\tcase \"upload\":\n\t\t\t\treturn {\n\t\t\t\t\t...initialProps,\n\t\t\t\t\t...summaryData.summaryStats,\n\t\t\t\t\tgenerateDuration: summaryData.generateDuration,\n\t\t\t\t\thandle: summaryData.handle,\n\t\t\t\t\tuploadDuration: summaryData.uploadDuration,\n\t\t\t\t};\n\n\t\t\tcase \"submit\":\n\t\t\t\treturn {\n\t\t\t\t\t...initialProps,\n\t\t\t\t\t...summaryData.summaryStats,\n\t\t\t\t\tgenerateDuration: summaryData.generateDuration,\n\t\t\t\t\thandle: summaryData.handle,\n\t\t\t\t\tuploadDuration: summaryData.uploadDuration,\n\t\t\t\t\tclientSequenceNumber: summaryData.clientSequenceNumber,\n\t\t\t\t\thasMissingOpData: this.heuristicData.hasMissingOpData,\n\t\t\t\t\topsSizesSinceLastSummary: this.heuristicData.totalOpsSize,\n\t\t\t\t\tnonRuntimeOpsSinceLastSummary: this.heuristicData.numNonRuntimeOps,\n\t\t\t\t\truntimeOpsSinceLastSummary: this.heuristicData.numRuntimeOps,\n\t\t\t\t};\n\n\t\t\tdefault:\n\t\t\t\tassert(true, 0x397 /* Unexpected summary stage */);\n\t\t}\n\n\t\treturn initialProps;\n\t}\n\n\tprivate summarizeTimerHandler(time: number, count: number) {\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\teventName: \"SummarizeTimeout\",\n\t\t\ttimeoutTime: time,\n\t\t\ttimeoutCount: count,\n\t\t});\n\t\tif (count < maxSummarizeTimeoutCount) {\n\t\t\t// Double and start a new timer\n\t\t\tconst nextTime = time * 2;\n\t\t\tthis.summarizeTimer.start(nextTime, () =>\n\t\t\t\tthis.summarizeTimerHandler(nextTime, count + 1),\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic dispose() {\n\t\tthis.summarizeTimer.clear();\n\t}\n}\n"]}
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { IEvent, IEventProvider } from "@fluidframework/common-definitions";
|
|
6
|
-
import { IDisposable } from "@fluidframework/core-interfaces";
|
|
7
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
6
|
+
import { IDisposable, ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
8
7
|
import { IThrottler } from "../throttler";
|
|
9
8
|
import { ISummarizerClientElection } from "./summarizerClientElection";
|
|
10
9
|
import { ISummarizer } from "./summarizerTypes";
|
|
@@ -63,7 +62,7 @@ export declare class SummaryManager implements IDisposable {
|
|
|
63
62
|
private _disposed;
|
|
64
63
|
get disposed(): boolean;
|
|
65
64
|
get currentState(): SummaryManagerState;
|
|
66
|
-
constructor(clientElection: ISummarizerClientElection, connectedState: IConnectedState, summaryCollection: Pick<SummaryCollection, "opsSinceLastAck" | "addOpListener" | "removeOpListener">, parentLogger:
|
|
65
|
+
constructor(clientElection: ISummarizerClientElection, connectedState: IConnectedState, summaryCollection: Pick<SummaryCollection, "opsSinceLastAck" | "addOpListener" | "removeOpListener">, parentLogger: ITelemetryBaseLogger,
|
|
67
66
|
/** Creates summarizer by asking interactive container to spawn summarizing container and
|
|
68
67
|
* get back its Summarizer instance. */
|
|
69
68
|
requestSummarizerFn: () => Promise<ISummarizer>, startThrottler: IThrottler, { initialDelayMs, opsToBypassInitialDelay, }?: Readonly<Partial<ISummaryManagerConfig>>, disableHeuristics?: boolean | undefined);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summaryManager.d.ts","sourceRoot":"","sources":["../../src/summary/summaryManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"summaryManager.d.ts","sourceRoot":"","sources":["../../src/summary/summaryManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -92,8 +92,12 @@ class SummaryManager {
|
|
|
92
92
|
}
|
|
93
93
|
return this.summarizer.enqueueSummarize(...args);
|
|
94
94
|
};
|
|
95
|
-
this.logger = telemetry_utils_1.
|
|
96
|
-
|
|
95
|
+
this.logger = (0, telemetry_utils_1.createChildLogger)({
|
|
96
|
+
logger: parentLogger,
|
|
97
|
+
namespace: "SummaryManager",
|
|
98
|
+
properties: {
|
|
99
|
+
all: { clientId: () => this.latestClientId },
|
|
100
|
+
},
|
|
97
101
|
});
|
|
98
102
|
this.connectedState.on("connected", this.handleConnected);
|
|
99
103
|
this.connectedState.on("disconnected", this.handleDisconnected);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summaryManager.js","sourceRoot":"","sources":["../../src/summary/summaryManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IEvent, IEventProvider } from \"@fluidframework/common-definitions\";\nimport { IDisposable } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport {\n\tChildLogger,\n\tITelemetryLoggerExt,\n\tPerformanceEvent,\n} from \"@fluidframework/telemetry-utils\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport { IThrottler } from \"../throttler\";\nimport { ISummarizerClientElection } from \"./summarizerClientElection\";\nimport { ISummarizer, SummarizerStopReason } from \"./summarizerTypes\";\nimport { SummaryCollection } from \"./summaryCollection\";\nimport { Summarizer } from \"./summarizer\";\n\nconst defaultInitialDelayMs = 5000;\nconst defaultOpsToBypassInitialDelay = 4000;\n\nexport enum SummaryManagerState {\n\tOff = 0,\n\tStarting = 1,\n\tRunning = 2,\n\tStopping = 3,\n}\n\n// Please note that all reasons in this list are not errors,\n// and thus they are not raised today to parent container as error.\n// If this needs to be changed in future, we should re-evaluate what and how we raise to summarizer\ntype StopReason = Extract<\n\tSummarizerStopReason,\n\t\"parentNotConnected\" | \"notElectedParent\" | \"notElectedClient\"\n>;\ntype ShouldSummarizeState =\n\t| { shouldSummarize: true }\n\t| { shouldSummarize: false; stopReason: StopReason };\n\nexport interface IConnectedEvents extends IEvent {\n\t(event: \"connected\", listener: (clientId: string) => void);\n\t(event: \"disconnected\", listener: () => void);\n}\n\n/**\n * IConnectedState describes an object that SummaryManager can watch to observe connection/disconnection.\n *\n * Under current implementation, its role will be fulfilled by the ContainerRuntime, but this could be replaced\n * with anything else that fulfills the contract if we want to shift the layer that the SummaryManager lives at.\n */\nexport interface IConnectedState extends IEventProvider<IConnectedEvents> {\n\treadonly connected: boolean;\n\n\t/**\n\t * Under current implementation this is undefined if we've never connected, otherwise it's the clientId from our\n\t * latest connection (even if we've since disconnected!). Although this happens to be the behavior we want in\n\t * SummaryManager, I suspect that globally we may eventually want to modify this behavior (e.g. make clientId\n\t * undefined while disconnected). To protect against this, let's assume this field can't be trusted while\n\t * disconnected and instead separately track \"latest clientId\" in SummaryManager.\n\t */\n\treadonly clientId: string | undefined;\n}\n\nexport interface ISummaryManagerConfig {\n\tinitialDelayMs: number;\n\topsToBypassInitialDelay: number;\n}\n\n/**\n * SummaryManager is created by parent container (i.e. interactive container with clientType !== \"summarizer\") only.\n * It observes changes in calculated summarizer and reacts to changes by either creating summarizer client or\n * stopping existing summarizer client.\n */\nexport class SummaryManager implements IDisposable {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\tprivate readonly opsToBypassInitialDelay: number;\n\tprivate readonly initialDelayMs: number;\n\tprivate latestClientId: string | undefined;\n\tprivate state = SummaryManagerState.Off;\n\tprivate summarizer?: ISummarizer;\n\tprivate _disposed = false;\n\n\tpublic get disposed() {\n\t\treturn this._disposed;\n\t}\n\n\tpublic get currentState() {\n\t\treturn this.state;\n\t}\n\n\tconstructor(\n\t\tprivate readonly clientElection: ISummarizerClientElection,\n\t\tprivate readonly connectedState: IConnectedState,\n\t\tprivate readonly summaryCollection: Pick<\n\t\t\tSummaryCollection,\n\t\t\t\"opsSinceLastAck\" | \"addOpListener\" | \"removeOpListener\"\n\t\t>,\n\t\tparentLogger: ITelemetryLoggerExt,\n\t\t/** Creates summarizer by asking interactive container to spawn summarizing container and\n\t\t * get back its Summarizer instance. */\n\t\tprivate readonly requestSummarizerFn: () => Promise<ISummarizer>,\n\t\tprivate readonly startThrottler: IThrottler,\n\t\t{\n\t\t\tinitialDelayMs = defaultInitialDelayMs,\n\t\t\topsToBypassInitialDelay = defaultOpsToBypassInitialDelay,\n\t\t}: Readonly<Partial<ISummaryManagerConfig>> = {},\n\t\tprivate readonly disableHeuristics?: boolean,\n\t) {\n\t\tthis.logger = ChildLogger.create(parentLogger, \"SummaryManager\", {\n\t\t\tall: { clientId: () => this.latestClientId },\n\t\t});\n\n\t\tthis.connectedState.on(\"connected\", this.handleConnected);\n\t\tthis.connectedState.on(\"disconnected\", this.handleDisconnected);\n\t\tthis.latestClientId = this.connectedState.clientId;\n\n\t\tthis.opsToBypassInitialDelay = opsToBypassInitialDelay;\n\t\tthis.initialDelayMs = initialDelayMs;\n\t}\n\n\t/**\n\t * Until start is called, the SummaryManager won't begin attempting to start summarization. This ensures there's\n\t * a window between construction and starting where the caller can attach listeners.\n\t */\n\tpublic start(): void {\n\t\tthis.clientElection.on(\"electedSummarizerChanged\", this.refreshSummarizer);\n\t\tthis.refreshSummarizer();\n\t}\n\n\tprivate readonly handleConnected = (clientId: string) => {\n\t\tthis.latestClientId = clientId;\n\t\t// If we have a summarizer, it should have been either cancelled on disconnected by now.\n\t\t// But because of lastSummary process, it can still hang around, so there is not much we can\n\t\t// check or assert.\n\t\tthis.refreshSummarizer();\n\t};\n\n\tprivate readonly handleDisconnected = () => {\n\t\tthis.refreshSummarizer();\n\t};\n\n\tprivate static readonly isStartingOrRunning = (state: SummaryManagerState) =>\n\t\tstate === SummaryManagerState.Starting || state === SummaryManagerState.Running;\n\n\tprivate getShouldSummarizeState(): ShouldSummarizeState {\n\t\t// Note that if we're in the Running state, the electedClient may be a summarizer client, so we can't\n\t\t// enforce connectedState.clientId === clientElection.electedClientId. But once we're Running, we should\n\t\t// only transition to Stopping when the electedParentId changes. Stopping the summarizer without\n\t\t// changing the electedParent will just cause us to transition to Starting again.\n\n\t\t// New Parent has been elected and it is not the current client, or\n\t\tif (this.connectedState.clientId !== this.clientElection.electedParentId) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"notElectedParent\" };\n\t\t}\n\n\t\t// We are not already running the summarizer and we are not the current elected client id.\n\t\tif (\n\t\t\tthis.state !== SummaryManagerState.Running &&\n\t\t\tthis.connectedState.clientId !== this.clientElection.electedClientId\n\t\t) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"notElectedClient\" };\n\t\t}\n\n\t\tif (!this.connectedState.connected) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"parentNotConnected\" };\n\t\t}\n\n\t\tif (this.disposed) {\n\t\t\tassert(false, 0x260 /* \"Disposed should mean disconnected!\" */);\n\t\t} else {\n\t\t\treturn { shouldSummarize: true };\n\t\t}\n\t}\n\n\tprivate readonly refreshSummarizer = () => {\n\t\t// Transition states depending on shouldSummarize, which is a calculated property\n\t\t// that is only true if this client is connected and is the elected summarizer.\n\t\tconst shouldSummarizeState = this.getShouldSummarizeState();\n\t\tswitch (this.state) {\n\t\t\tcase SummaryManagerState.Off: {\n\t\t\t\tif (shouldSummarizeState.shouldSummarize) {\n\t\t\t\t\tthis.startSummarization();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase SummaryManagerState.Starting: {\n\t\t\t\t// Cannot take any action until summarizer is created\n\t\t\t\t// state transition will occur after creation\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase SummaryManagerState.Running: {\n\t\t\t\tif (shouldSummarizeState.shouldSummarize === false) {\n\t\t\t\t\tthis.stop(shouldSummarizeState.stopReason);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase SummaryManagerState.Stopping: {\n\t\t\t\t// Cannot take any action until running summarizer finishes\n\t\t\t\t// state transition will occur after it stops\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t};\n\n\tprivate startSummarization() {\n\t\tassert(this.state === SummaryManagerState.Off, 0x261 /* \"Expected: off\" */);\n\t\tthis.state = SummaryManagerState.Starting;\n\n\t\tassert(this.summarizer === undefined, 0x262 /* \"Old summarizer is still working!\" */);\n\n\t\tthis.delayBeforeCreatingSummarizer()\n\t\t\t.then(async (startWithInitialDelay: boolean) => {\n\t\t\t\t// Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore\n\t\t\t\t// but only if creation was delayed. If it was not, then we want to ensure we always create\n\t\t\t\t// a summarizer to kick off lastSummary. Without that, we would not be able to summarize and get\n\t\t\t\t// document out of broken state if it has too many ops and ordering service keeps nacking main\n\t\t\t\t// container (and thus it goes into cycle of reconnects)\n\t\t\t\t// If we can't run the LastSummary, simply return as to avoid paying the cost of launching\n\t\t\t\t// the summarizer at all.\n\t\t\t\tconst shouldSummarizeStateEarlyStage = this.getShouldSummarizeState();\n\t\t\t\tif (\n\t\t\t\t\tstartWithInitialDelay &&\n\t\t\t\t\tshouldSummarizeStateEarlyStage.shouldSummarize === false\n\t\t\t\t) {\n\t\t\t\t\treturn `early exit ${shouldSummarizeStateEarlyStage.stopReason}`;\n\t\t\t\t}\n\n\t\t\t\t// We transition to Running before requesting the summarizer, because after requesting we can't predict\n\t\t\t\t// when the electedClient will be replaced with the new summarizer client.\n\t\t\t\t// The alternative would be to let connectedState.clientId !== clientElection.electedClientId when\n\t\t\t\t// state === Starting || state === Running.\n\t\t\t\tassert(\n\t\t\t\t\tthis.state === SummaryManagerState.Starting,\n\t\t\t\t\t0x263 /* \"Expected: starting\" */,\n\t\t\t\t);\n\t\t\t\tthis.state = SummaryManagerState.Running;\n\n\t\t\t\tconst summarizer = await this.requestSummarizerFn();\n\t\t\t\tthis.summarizer = summarizer;\n\n\t\t\t\t// Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore\n\t\t\t\t// If we can't run the LastSummary, simply return as to avoid paying the cost of launching\n\t\t\t\t// the summarizer at all.\n\t\t\t\tconst shouldSummarizeState = this.getShouldSummarizeState();\n\t\t\t\tif (shouldSummarizeState.shouldSummarize === false) {\n\t\t\t\t\t// In order to allow the last summary to run, we not only need a stop reason that would\n\t\t\t\t\t// allow it but also, startWithInitialDelay to be false (start the summarization immediately),\n\t\t\t\t\t// which would happen when we have a high enough number of unsummarized ops.\n\t\t\t\t\tif (\n\t\t\t\t\t\tstartWithInitialDelay ||\n\t\t\t\t\t\t!Summarizer.stopReasonCanRunLastSummary(shouldSummarizeState.stopReason)\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.state = SummaryManagerState.Starting;\n\t\t\t\t\t\tsummarizer.stop(shouldSummarizeState.stopReason);\n\t\t\t\t\t\treturn `early exit after starting summarizer ${shouldSummarizeState.stopReason}`;\n\t\t\t\t\t}\n\t\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"LastAttemptToSummarize\",\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tconst clientId = this.latestClientId!;\n\n\t\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\t\tthis.logger,\n\t\t\t\t\t{ eventName: \"RunningSummarizer\", attempt: this.startThrottler.numAttempts },\n\t\t\t\t\tasync () => summarizer.run(clientId, this.disableHeuristics),\n\t\t\t\t);\n\t\t\t})\n\t\t\t.then((reason: string) => {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"EndingSummarizer\",\n\t\t\t\t\treason,\n\t\t\t\t});\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"EndingSummarizer\",\n\t\t\t\t\t\treason: \"exception\",\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\n\t\t\t\t// Most of exceptions happen due to container being closed while loading it, due to\n\t\t\t\t// summarizer container loosing connection while load.\n\t\t\t\t// Not worth reporting such errors as errors. That said, we might miss some real errors if\n\t\t\t\t// we ignore blindly, so try to narrow signature we are looking for - skip logging\n\t\t\t\t// error only if this client should no longer be a summarizer (which in practice\n\t\t\t\t// means it also lost connection), and error happened on load (we do not have summarizer).\n\t\t\t\t// We could annotate the error raised in Container.load where the container closed during load with no error\n\t\t\t\t// and check for that case here, but that does not seem to be necessary.\n\t\t\t\tif (\n\t\t\t\t\tthis.getShouldSummarizeState().shouldSummarize ||\n\t\t\t\t\tthis.summarizer !== undefined\n\t\t\t\t) {\n\t\t\t\t\t// Report any failure as an error unless it was due to cancellation (like \"disconnected\" error)\n\t\t\t\t\t// If failure happened on container load, we may not yet realized that socket disconnected, so check\n\t\t\t\t\t// offlineError.\n\t\t\t\t\tconst category =\n\t\t\t\t\t\terror?.errorType === DriverErrorType.offlineError ? \"generic\" : \"error\";\n\t\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"SummarizerException\",\n\t\t\t\t\t\t\tcategory,\n\t\t\t\t\t\t},\n\t\t\t\t\t\terror,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tassert(this.state !== SummaryManagerState.Off, 0x264 /* \"Expected: Not Off\" */);\n\t\t\t\tthis.state = SummaryManagerState.Off;\n\n\t\t\t\tthis.summarizer?.close();\n\t\t\t\tthis.summarizer = undefined;\n\n\t\t\t\tif (this.getShouldSummarizeState().shouldSummarize) {\n\t\t\t\t\tthis.startSummarization();\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\tprivate stop(reason: SummarizerStopReason) {\n\t\tif (!SummaryManager.isStartingOrRunning(this.state)) {\n\t\t\treturn;\n\t\t}\n\t\tthis.state = SummaryManagerState.Stopping;\n\n\t\t// Stopping the running summarizer client should trigger a change\n\t\t// in states when the running summarizer closes\n\t\tthis.summarizer?.stop(reason);\n\t}\n\n\t/**\n\t * Implements initial delay before creating summarizer\n\t * @returns `true`, if creation is delayed due to heuristics (not many ops to summarize).\n\t * `false` if summarizer should start immediately due to too many unsummarized ops.\n\t */\n\tprivate async delayBeforeCreatingSummarizer(): Promise<boolean> {\n\t\t// throttle creation of new summarizer containers to prevent spamming the server with websocket connections\n\t\tlet delayMs = this.startThrottler.getDelay();\n\n\t\t// We have been elected the summarizer. Some day we may be able to summarize with a live document but for\n\t\t// now we play it safe and launch a second copy.\n\t\tthis.logger.sendTelemetryEvent({\n\t\t\teventName: \"CreatingSummarizer\",\n\t\t\tthrottlerDelay: delayMs,\n\t\t\tinitialDelay: this.initialDelayMs,\n\t\t\tstartThrottlerMaxDelayMs: this.startThrottler.maxDelayMs,\n\t\t\topsSinceLastAck: this.summaryCollection.opsSinceLastAck,\n\t\t\topsToBypassInitialDelay: this.opsToBypassInitialDelay,\n\t\t\telectedParentId: this.clientElection.electedParentId,\n\t\t\telectedClientId: this.clientElection.electedClientId,\n\t\t});\n\n\t\t// This delay helps ensure that last summarizer that might be left from previous client\n\t\t// has enough time to complete its last summary and thus new summarizer not conflict with previous one.\n\t\t// If, however, there are too many unsummarized ops, try to resolve it as quickly as possible, with\n\t\t// understanding that we may see nacks because of such quick action.\n\t\t// A better design would be for summarizer election logic to always select current summarizer as\n\t\t// summarizing client (i.e. clientType === \"summarizer\" can be elected) to ensure that nobody else can\n\t\t// summarizer while it finishes its work and moves to exit.\n\t\t// It also helps with pure boot scenario (single client) to offset expensive work a bit out from\n\t\t// critical boot sequence.\n\t\tlet startWithInitialDelay = false;\n\t\tif (this.summaryCollection.opsSinceLastAck < this.opsToBypassInitialDelay) {\n\t\t\tstartWithInitialDelay = true;\n\t\t\tdelayMs = Math.max(delayMs, this.initialDelayMs);\n\t\t}\n\n\t\tif (delayMs > 0) {\n\t\t\tlet timer;\n\t\t\tlet resolveOpPromiseFn;\n\t\t\t// Create a listener that will break the delay if we've exceeded the initial delay ops count.\n\t\t\tconst opsListenerFn = () => {\n\t\t\t\tif (this.summaryCollection.opsSinceLastAck >= this.opsToBypassInitialDelay) {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\tresolveOpPromiseFn();\n\t\t\t\t}\n\t\t\t};\n\t\t\t// Create a Promise that will resolve when the delay expires.\n\t\t\tconst delayPromise = new Promise<void>((resolve) => {\n\t\t\t\ttimer = setTimeout(() => resolve(), delayMs);\n\t\t\t});\n\t\t\t// Create a Promise that will resolve if the ops count passes the threshold.\n\t\t\tconst opPromise = new Promise<void>((resolve) => {\n\t\t\t\tresolveOpPromiseFn = resolve;\n\t\t\t});\n\t\t\tthis.summaryCollection.addOpListener(opsListenerFn);\n\t\t\tawait Promise.race([delayPromise, opPromise]);\n\t\t\tthis.summaryCollection.removeOpListener(opsListenerFn);\n\t\t}\n\t\treturn startWithInitialDelay;\n\t}\n\n\tpublic readonly summarizeOnDemand: ISummarizer[\"summarizeOnDemand\"] = (...args) => {\n\t\tif (this.summarizer === undefined) {\n\t\t\tthrow Error(\"No running summarizer client\");\n\t\t\t// TODO: could spawn a summarizer client temporarily.\n\t\t}\n\t\treturn this.summarizer.summarizeOnDemand(...args);\n\t};\n\n\tpublic readonly enqueueSummarize: ISummarizer[\"enqueueSummarize\"] = (...args) => {\n\t\tif (this.summarizer === undefined) {\n\t\t\tthrow Error(\"No running summarizer client\");\n\t\t\t// TODO: could spawn a summarizer client temporarily.\n\t\t}\n\t\treturn this.summarizer.enqueueSummarize(...args);\n\t};\n\n\tpublic dispose() {\n\t\tthis.clientElection.off(\"electedSummarizerChanged\", this.refreshSummarizer);\n\t\tthis.connectedState.off(\"connected\", this.handleConnected);\n\t\tthis.connectedState.off(\"disconnected\", this.handleDisconnected);\n\t\tthis._disposed = true;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"summaryManager.js","sourceRoot":"","sources":["../../src/summary/summaryManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IEvent, IEventProvider } from \"@fluidframework/common-definitions\";\nimport { IDisposable, ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport {\n\tcreateChildLogger,\n\tITelemetryLoggerExt,\n\tPerformanceEvent,\n} from \"@fluidframework/telemetry-utils\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport { IThrottler } from \"../throttler\";\nimport { ISummarizerClientElection } from \"./summarizerClientElection\";\nimport { ISummarizer, SummarizerStopReason } from \"./summarizerTypes\";\nimport { SummaryCollection } from \"./summaryCollection\";\nimport { Summarizer } from \"./summarizer\";\n\nconst defaultInitialDelayMs = 5000;\nconst defaultOpsToBypassInitialDelay = 4000;\n\nexport enum SummaryManagerState {\n\tOff = 0,\n\tStarting = 1,\n\tRunning = 2,\n\tStopping = 3,\n}\n\n// Please note that all reasons in this list are not errors,\n// and thus they are not raised today to parent container as error.\n// If this needs to be changed in future, we should re-evaluate what and how we raise to summarizer\ntype StopReason = Extract<\n\tSummarizerStopReason,\n\t\"parentNotConnected\" | \"notElectedParent\" | \"notElectedClient\"\n>;\ntype ShouldSummarizeState =\n\t| { shouldSummarize: true }\n\t| { shouldSummarize: false; stopReason: StopReason };\n\nexport interface IConnectedEvents extends IEvent {\n\t(event: \"connected\", listener: (clientId: string) => void);\n\t(event: \"disconnected\", listener: () => void);\n}\n\n/**\n * IConnectedState describes an object that SummaryManager can watch to observe connection/disconnection.\n *\n * Under current implementation, its role will be fulfilled by the ContainerRuntime, but this could be replaced\n * with anything else that fulfills the contract if we want to shift the layer that the SummaryManager lives at.\n */\nexport interface IConnectedState extends IEventProvider<IConnectedEvents> {\n\treadonly connected: boolean;\n\n\t/**\n\t * Under current implementation this is undefined if we've never connected, otherwise it's the clientId from our\n\t * latest connection (even if we've since disconnected!). Although this happens to be the behavior we want in\n\t * SummaryManager, I suspect that globally we may eventually want to modify this behavior (e.g. make clientId\n\t * undefined while disconnected). To protect against this, let's assume this field can't be trusted while\n\t * disconnected and instead separately track \"latest clientId\" in SummaryManager.\n\t */\n\treadonly clientId: string | undefined;\n}\n\nexport interface ISummaryManagerConfig {\n\tinitialDelayMs: number;\n\topsToBypassInitialDelay: number;\n}\n\n/**\n * SummaryManager is created by parent container (i.e. interactive container with clientType !== \"summarizer\") only.\n * It observes changes in calculated summarizer and reacts to changes by either creating summarizer client or\n * stopping existing summarizer client.\n */\nexport class SummaryManager implements IDisposable {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\tprivate readonly opsToBypassInitialDelay: number;\n\tprivate readonly initialDelayMs: number;\n\tprivate latestClientId: string | undefined;\n\tprivate state = SummaryManagerState.Off;\n\tprivate summarizer?: ISummarizer;\n\tprivate _disposed = false;\n\n\tpublic get disposed() {\n\t\treturn this._disposed;\n\t}\n\n\tpublic get currentState() {\n\t\treturn this.state;\n\t}\n\n\tconstructor(\n\t\tprivate readonly clientElection: ISummarizerClientElection,\n\t\tprivate readonly connectedState: IConnectedState,\n\t\tprivate readonly summaryCollection: Pick<\n\t\t\tSummaryCollection,\n\t\t\t\"opsSinceLastAck\" | \"addOpListener\" | \"removeOpListener\"\n\t\t>,\n\t\tparentLogger: ITelemetryBaseLogger,\n\t\t/** Creates summarizer by asking interactive container to spawn summarizing container and\n\t\t * get back its Summarizer instance. */\n\t\tprivate readonly requestSummarizerFn: () => Promise<ISummarizer>,\n\t\tprivate readonly startThrottler: IThrottler,\n\t\t{\n\t\t\tinitialDelayMs = defaultInitialDelayMs,\n\t\t\topsToBypassInitialDelay = defaultOpsToBypassInitialDelay,\n\t\t}: Readonly<Partial<ISummaryManagerConfig>> = {},\n\t\tprivate readonly disableHeuristics?: boolean,\n\t) {\n\t\tthis.logger = createChildLogger({\n\t\t\tlogger: parentLogger,\n\t\t\tnamespace: \"SummaryManager\",\n\t\t\tproperties: {\n\t\t\t\tall: { clientId: () => this.latestClientId },\n\t\t\t},\n\t\t});\n\n\t\tthis.connectedState.on(\"connected\", this.handleConnected);\n\t\tthis.connectedState.on(\"disconnected\", this.handleDisconnected);\n\t\tthis.latestClientId = this.connectedState.clientId;\n\n\t\tthis.opsToBypassInitialDelay = opsToBypassInitialDelay;\n\t\tthis.initialDelayMs = initialDelayMs;\n\t}\n\n\t/**\n\t * Until start is called, the SummaryManager won't begin attempting to start summarization. This ensures there's\n\t * a window between construction and starting where the caller can attach listeners.\n\t */\n\tpublic start(): void {\n\t\tthis.clientElection.on(\"electedSummarizerChanged\", this.refreshSummarizer);\n\t\tthis.refreshSummarizer();\n\t}\n\n\tprivate readonly handleConnected = (clientId: string) => {\n\t\tthis.latestClientId = clientId;\n\t\t// If we have a summarizer, it should have been either cancelled on disconnected by now.\n\t\t// But because of lastSummary process, it can still hang around, so there is not much we can\n\t\t// check or assert.\n\t\tthis.refreshSummarizer();\n\t};\n\n\tprivate readonly handleDisconnected = () => {\n\t\tthis.refreshSummarizer();\n\t};\n\n\tprivate static readonly isStartingOrRunning = (state: SummaryManagerState) =>\n\t\tstate === SummaryManagerState.Starting || state === SummaryManagerState.Running;\n\n\tprivate getShouldSummarizeState(): ShouldSummarizeState {\n\t\t// Note that if we're in the Running state, the electedClient may be a summarizer client, so we can't\n\t\t// enforce connectedState.clientId === clientElection.electedClientId. But once we're Running, we should\n\t\t// only transition to Stopping when the electedParentId changes. Stopping the summarizer without\n\t\t// changing the electedParent will just cause us to transition to Starting again.\n\n\t\t// New Parent has been elected and it is not the current client, or\n\t\tif (this.connectedState.clientId !== this.clientElection.electedParentId) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"notElectedParent\" };\n\t\t}\n\n\t\t// We are not already running the summarizer and we are not the current elected client id.\n\t\tif (\n\t\t\tthis.state !== SummaryManagerState.Running &&\n\t\t\tthis.connectedState.clientId !== this.clientElection.electedClientId\n\t\t) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"notElectedClient\" };\n\t\t}\n\n\t\tif (!this.connectedState.connected) {\n\t\t\treturn { shouldSummarize: false, stopReason: \"parentNotConnected\" };\n\t\t}\n\n\t\tif (this.disposed) {\n\t\t\tassert(false, 0x260 /* \"Disposed should mean disconnected!\" */);\n\t\t} else {\n\t\t\treturn { shouldSummarize: true };\n\t\t}\n\t}\n\n\tprivate readonly refreshSummarizer = () => {\n\t\t// Transition states depending on shouldSummarize, which is a calculated property\n\t\t// that is only true if this client is connected and is the elected summarizer.\n\t\tconst shouldSummarizeState = this.getShouldSummarizeState();\n\t\tswitch (this.state) {\n\t\t\tcase SummaryManagerState.Off: {\n\t\t\t\tif (shouldSummarizeState.shouldSummarize) {\n\t\t\t\t\tthis.startSummarization();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase SummaryManagerState.Starting: {\n\t\t\t\t// Cannot take any action until summarizer is created\n\t\t\t\t// state transition will occur after creation\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase SummaryManagerState.Running: {\n\t\t\t\tif (shouldSummarizeState.shouldSummarize === false) {\n\t\t\t\t\tthis.stop(shouldSummarizeState.stopReason);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase SummaryManagerState.Stopping: {\n\t\t\t\t// Cannot take any action until running summarizer finishes\n\t\t\t\t// state transition will occur after it stops\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t};\n\n\tprivate startSummarization() {\n\t\tassert(this.state === SummaryManagerState.Off, 0x261 /* \"Expected: off\" */);\n\t\tthis.state = SummaryManagerState.Starting;\n\n\t\tassert(this.summarizer === undefined, 0x262 /* \"Old summarizer is still working!\" */);\n\n\t\tthis.delayBeforeCreatingSummarizer()\n\t\t\t.then(async (startWithInitialDelay: boolean) => {\n\t\t\t\t// Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore\n\t\t\t\t// but only if creation was delayed. If it was not, then we want to ensure we always create\n\t\t\t\t// a summarizer to kick off lastSummary. Without that, we would not be able to summarize and get\n\t\t\t\t// document out of broken state if it has too many ops and ordering service keeps nacking main\n\t\t\t\t// container (and thus it goes into cycle of reconnects)\n\t\t\t\t// If we can't run the LastSummary, simply return as to avoid paying the cost of launching\n\t\t\t\t// the summarizer at all.\n\t\t\t\tconst shouldSummarizeStateEarlyStage = this.getShouldSummarizeState();\n\t\t\t\tif (\n\t\t\t\t\tstartWithInitialDelay &&\n\t\t\t\t\tshouldSummarizeStateEarlyStage.shouldSummarize === false\n\t\t\t\t) {\n\t\t\t\t\treturn `early exit ${shouldSummarizeStateEarlyStage.stopReason}`;\n\t\t\t\t}\n\n\t\t\t\t// We transition to Running before requesting the summarizer, because after requesting we can't predict\n\t\t\t\t// when the electedClient will be replaced with the new summarizer client.\n\t\t\t\t// The alternative would be to let connectedState.clientId !== clientElection.electedClientId when\n\t\t\t\t// state === Starting || state === Running.\n\t\t\t\tassert(\n\t\t\t\t\tthis.state === SummaryManagerState.Starting,\n\t\t\t\t\t0x263 /* \"Expected: starting\" */,\n\t\t\t\t);\n\t\t\t\tthis.state = SummaryManagerState.Running;\n\n\t\t\t\tconst summarizer = await this.requestSummarizerFn();\n\t\t\t\tthis.summarizer = summarizer;\n\n\t\t\t\t// Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore\n\t\t\t\t// If we can't run the LastSummary, simply return as to avoid paying the cost of launching\n\t\t\t\t// the summarizer at all.\n\t\t\t\tconst shouldSummarizeState = this.getShouldSummarizeState();\n\t\t\t\tif (shouldSummarizeState.shouldSummarize === false) {\n\t\t\t\t\t// In order to allow the last summary to run, we not only need a stop reason that would\n\t\t\t\t\t// allow it but also, startWithInitialDelay to be false (start the summarization immediately),\n\t\t\t\t\t// which would happen when we have a high enough number of unsummarized ops.\n\t\t\t\t\tif (\n\t\t\t\t\t\tstartWithInitialDelay ||\n\t\t\t\t\t\t!Summarizer.stopReasonCanRunLastSummary(shouldSummarizeState.stopReason)\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.state = SummaryManagerState.Starting;\n\t\t\t\t\t\tsummarizer.stop(shouldSummarizeState.stopReason);\n\t\t\t\t\t\treturn `early exit after starting summarizer ${shouldSummarizeState.stopReason}`;\n\t\t\t\t\t}\n\t\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"LastAttemptToSummarize\",\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tconst clientId = this.latestClientId!;\n\n\t\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\t\tthis.logger,\n\t\t\t\t\t{ eventName: \"RunningSummarizer\", attempt: this.startThrottler.numAttempts },\n\t\t\t\t\tasync () => summarizer.run(clientId, this.disableHeuristics),\n\t\t\t\t);\n\t\t\t})\n\t\t\t.then((reason: string) => {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"EndingSummarizer\",\n\t\t\t\t\treason,\n\t\t\t\t});\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"EndingSummarizer\",\n\t\t\t\t\t\treason: \"exception\",\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\n\t\t\t\t// Most of exceptions happen due to container being closed while loading it, due to\n\t\t\t\t// summarizer container loosing connection while load.\n\t\t\t\t// Not worth reporting such errors as errors. That said, we might miss some real errors if\n\t\t\t\t// we ignore blindly, so try to narrow signature we are looking for - skip logging\n\t\t\t\t// error only if this client should no longer be a summarizer (which in practice\n\t\t\t\t// means it also lost connection), and error happened on load (we do not have summarizer).\n\t\t\t\t// We could annotate the error raised in Container.load where the container closed during load with no error\n\t\t\t\t// and check for that case here, but that does not seem to be necessary.\n\t\t\t\tif (\n\t\t\t\t\tthis.getShouldSummarizeState().shouldSummarize ||\n\t\t\t\t\tthis.summarizer !== undefined\n\t\t\t\t) {\n\t\t\t\t\t// Report any failure as an error unless it was due to cancellation (like \"disconnected\" error)\n\t\t\t\t\t// If failure happened on container load, we may not yet realized that socket disconnected, so check\n\t\t\t\t\t// offlineError.\n\t\t\t\t\tconst category =\n\t\t\t\t\t\terror?.errorType === DriverErrorType.offlineError ? \"generic\" : \"error\";\n\t\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"SummarizerException\",\n\t\t\t\t\t\t\tcategory,\n\t\t\t\t\t\t},\n\t\t\t\t\t\terror,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tassert(this.state !== SummaryManagerState.Off, 0x264 /* \"Expected: Not Off\" */);\n\t\t\t\tthis.state = SummaryManagerState.Off;\n\n\t\t\t\tthis.summarizer?.close();\n\t\t\t\tthis.summarizer = undefined;\n\n\t\t\t\tif (this.getShouldSummarizeState().shouldSummarize) {\n\t\t\t\t\tthis.startSummarization();\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\tprivate stop(reason: SummarizerStopReason) {\n\t\tif (!SummaryManager.isStartingOrRunning(this.state)) {\n\t\t\treturn;\n\t\t}\n\t\tthis.state = SummaryManagerState.Stopping;\n\n\t\t// Stopping the running summarizer client should trigger a change\n\t\t// in states when the running summarizer closes\n\t\tthis.summarizer?.stop(reason);\n\t}\n\n\t/**\n\t * Implements initial delay before creating summarizer\n\t * @returns `true`, if creation is delayed due to heuristics (not many ops to summarize).\n\t * `false` if summarizer should start immediately due to too many unsummarized ops.\n\t */\n\tprivate async delayBeforeCreatingSummarizer(): Promise<boolean> {\n\t\t// throttle creation of new summarizer containers to prevent spamming the server with websocket connections\n\t\tlet delayMs = this.startThrottler.getDelay();\n\n\t\t// We have been elected the summarizer. Some day we may be able to summarize with a live document but for\n\t\t// now we play it safe and launch a second copy.\n\t\tthis.logger.sendTelemetryEvent({\n\t\t\teventName: \"CreatingSummarizer\",\n\t\t\tthrottlerDelay: delayMs,\n\t\t\tinitialDelay: this.initialDelayMs,\n\t\t\tstartThrottlerMaxDelayMs: this.startThrottler.maxDelayMs,\n\t\t\topsSinceLastAck: this.summaryCollection.opsSinceLastAck,\n\t\t\topsToBypassInitialDelay: this.opsToBypassInitialDelay,\n\t\t\telectedParentId: this.clientElection.electedParentId,\n\t\t\telectedClientId: this.clientElection.electedClientId,\n\t\t});\n\n\t\t// This delay helps ensure that last summarizer that might be left from previous client\n\t\t// has enough time to complete its last summary and thus new summarizer not conflict with previous one.\n\t\t// If, however, there are too many unsummarized ops, try to resolve it as quickly as possible, with\n\t\t// understanding that we may see nacks because of such quick action.\n\t\t// A better design would be for summarizer election logic to always select current summarizer as\n\t\t// summarizing client (i.e. clientType === \"summarizer\" can be elected) to ensure that nobody else can\n\t\t// summarizer while it finishes its work and moves to exit.\n\t\t// It also helps with pure boot scenario (single client) to offset expensive work a bit out from\n\t\t// critical boot sequence.\n\t\tlet startWithInitialDelay = false;\n\t\tif (this.summaryCollection.opsSinceLastAck < this.opsToBypassInitialDelay) {\n\t\t\tstartWithInitialDelay = true;\n\t\t\tdelayMs = Math.max(delayMs, this.initialDelayMs);\n\t\t}\n\n\t\tif (delayMs > 0) {\n\t\t\tlet timer;\n\t\t\tlet resolveOpPromiseFn;\n\t\t\t// Create a listener that will break the delay if we've exceeded the initial delay ops count.\n\t\t\tconst opsListenerFn = () => {\n\t\t\t\tif (this.summaryCollection.opsSinceLastAck >= this.opsToBypassInitialDelay) {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\tresolveOpPromiseFn();\n\t\t\t\t}\n\t\t\t};\n\t\t\t// Create a Promise that will resolve when the delay expires.\n\t\t\tconst delayPromise = new Promise<void>((resolve) => {\n\t\t\t\ttimer = setTimeout(() => resolve(), delayMs);\n\t\t\t});\n\t\t\t// Create a Promise that will resolve if the ops count passes the threshold.\n\t\t\tconst opPromise = new Promise<void>((resolve) => {\n\t\t\t\tresolveOpPromiseFn = resolve;\n\t\t\t});\n\t\t\tthis.summaryCollection.addOpListener(opsListenerFn);\n\t\t\tawait Promise.race([delayPromise, opPromise]);\n\t\t\tthis.summaryCollection.removeOpListener(opsListenerFn);\n\t\t}\n\t\treturn startWithInitialDelay;\n\t}\n\n\tpublic readonly summarizeOnDemand: ISummarizer[\"summarizeOnDemand\"] = (...args) => {\n\t\tif (this.summarizer === undefined) {\n\t\t\tthrow Error(\"No running summarizer client\");\n\t\t\t// TODO: could spawn a summarizer client temporarily.\n\t\t}\n\t\treturn this.summarizer.summarizeOnDemand(...args);\n\t};\n\n\tpublic readonly enqueueSummarize: ISummarizer[\"enqueueSummarize\"] = (...args) => {\n\t\tif (this.summarizer === undefined) {\n\t\t\tthrow Error(\"No running summarizer client\");\n\t\t\t// TODO: could spawn a summarizer client temporarily.\n\t\t}\n\t\treturn this.summarizer.enqueueSummarize(...args);\n\t};\n\n\tpublic dispose() {\n\t\tthis.clientElection.off(\"electedSummarizerChanged\", this.refreshSummarizer);\n\t\tthis.connectedState.off(\"connected\", this.handleConnected);\n\t\tthis.connectedState.off(\"disconnected\", this.handleDisconnected);\n\t\tthis._disposed = true;\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batchTracker.d.ts","sourceRoot":"","sources":["../src/batchTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"batchTracker.d.ts","sourceRoot":"","sources":["../src/batchTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,mBAAmB,EAAqB,MAAM,iCAAiC,CAAC;AAIzF,qBAAa,YAAY;IAOvB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IANnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,wBAAwB,CAAqB;IACrD,OAAO,CAAC,iBAAiB,CAAa;IACtC,OAAO,CAAC,6BAA6B,CAAqB;gBAGxC,iBAAiB,EAAE,YAAY,EAChD,MAAM,EAAE,mBAAmB,EAC3B,oBAAoB,EAAE,MAAM,EAC5B,sBAAsB,EAAE,MAAM,EAC9B,gBAAgB,GAAE,MAAM,MAAgC;CA8CzD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,sBACT,YAAY,UACvB,mBAAmB,yBACL,MAAM,2BACJ,MAAM,iBAC+D,CAAC"}
|
package/lib/batchTracker.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { createChildLogger } from "@fluidframework/telemetry-utils";
|
|
6
6
|
import { assert, performance } from "@fluidframework/common-utils";
|
|
7
7
|
export class BatchTracker {
|
|
8
8
|
constructor(batchEventEmitter, logger, batchLengthThreshold, batchCountSamplingRate, dateTimeProvider = () => performance.now()) {
|
|
9
9
|
this.batchEventEmitter = batchEventEmitter;
|
|
10
10
|
this.trackedBatchCount = 0;
|
|
11
|
-
this.logger =
|
|
11
|
+
this.logger = createChildLogger({ logger, namespace: "Batching" });
|
|
12
12
|
this.batchEventEmitter.on("batchBegin", (message) => {
|
|
13
13
|
this.startBatchSequenceNumber = message.sequenceNumber;
|
|
14
14
|
this.batchProcessingStartTimeStamp = dateTimeProvider();
|
package/lib/batchTracker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batchTracker.js","sourceRoot":"","sources":["../src/batchTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAuB,
|
|
1
|
+
{"version":3,"file":"batchTracker.js","sourceRoot":"","sources":["../src/batchTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAuB,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzF,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAGnE,MAAM,OAAO,YAAY;IAMxB,YACkB,iBAA+B,EAChD,MAA2B,EAC3B,oBAA4B,EAC5B,sBAA8B,EAC9B,mBAAiC,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;QAJvC,sBAAiB,GAAjB,iBAAiB,CAAc;QAJzC,sBAAiB,GAAW,CAAC,CAAC;QAUrC,IAAI,CAAC,MAAM,GAAG,iBAAiB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;QAEnE,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,OAAkC,EAAE,EAAE;YAC9E,IAAI,CAAC,wBAAwB,GAAG,OAAO,CAAC,cAAc,CAAC;YACvD,IAAI,CAAC,6BAA6B,GAAG,gBAAgB,EAAE,CAAC;YACxD,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,iBAAiB,CAAC,EAAE,CACxB,UAAU,EACV,CAAC,KAAsB,EAAE,OAAkC,EAAE,EAAE;YAC9D,MAAM,CACL,IAAI,CAAC,wBAAwB,KAAK,SAAS;gBAC1C,IAAI,CAAC,6BAA6B,KAAK,SAAS,EACjD,KAAK,CAAC,4CAA4C,CAClD,CAAC;YAEF,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,wBAAwB,GAAG,CAAC,CAAC;YAC1E,IAAI,MAAM,IAAI,oBAAoB,EAAE;gBACnC,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC;oBAChC,SAAS,EAAE,cAAc;oBACzB,MAAM;oBACN,SAAS,EAAE,oBAAoB;oBAC/B,sBAAsB,EAAE,OAAO,CAAC,cAAc;oBAC9C,QAAQ,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC,6BAA6B;oBACjE,UAAU,EAAE,KAAK,KAAK,SAAS;iBAC/B,CAAC,CAAC;aACH;YAED,IAAI,IAAI,CAAC,iBAAiB,GAAG,sBAAsB,KAAK,CAAC,EAAE;gBAC1D,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC;oBAChC,SAAS,EAAE,QAAQ;oBACnB,MAAM;oBACN,YAAY,EAAE,sBAAsB;oBACpC,sBAAsB,EAAE,OAAO,CAAC,cAAc;oBAC9C,QAAQ,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC,6BAA6B;iBACjE,CAAC,CAAC;aACH;YAED,IAAI,CAAC,wBAAwB,GAAG,SAAS,CAAC;YAC1C,IAAI,CAAC,6BAA6B,GAAG,SAAS,CAAC;QAChD,CAAC,CACD,CAAC;IACH,CAAC;CACD;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC/B,iBAA+B,EAC/B,MAA2B,EAC3B,uBAA+B,IAAI,EACnC,yBAAiC,IAAI,EACpC,EAAE,CAAC,IAAI,YAAY,CAAC,iBAAiB,EAAE,MAAM,EAAE,oBAAoB,EAAE,sBAAsB,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { EventEmitter } from \"events\";\nimport { ITelemetryLoggerExt, createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { assert, performance } from \"@fluidframework/common-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\n\nexport class BatchTracker {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\tprivate startBatchSequenceNumber: number | undefined;\n\tprivate trackedBatchCount: number = 0;\n\tprivate batchProcessingStartTimeStamp: number | undefined;\n\n\tconstructor(\n\t\tprivate readonly batchEventEmitter: EventEmitter,\n\t\tlogger: ITelemetryLoggerExt,\n\t\tbatchLengthThreshold: number,\n\t\tbatchCountSamplingRate: number,\n\t\tdateTimeProvider: () => number = () => performance.now(),\n\t) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"Batching\" });\n\n\t\tthis.batchEventEmitter.on(\"batchBegin\", (message: ISequencedDocumentMessage) => {\n\t\t\tthis.startBatchSequenceNumber = message.sequenceNumber;\n\t\t\tthis.batchProcessingStartTimeStamp = dateTimeProvider();\n\t\t\tthis.trackedBatchCount++;\n\t\t});\n\n\t\tthis.batchEventEmitter.on(\n\t\t\t\"batchEnd\",\n\t\t\t(error: any | undefined, message: ISequencedDocumentMessage) => {\n\t\t\t\tassert(\n\t\t\t\t\tthis.startBatchSequenceNumber !== undefined &&\n\t\t\t\t\t\tthis.batchProcessingStartTimeStamp !== undefined,\n\t\t\t\t\t0x2ba /* \"batchBegin must fire before batchEnd\" */,\n\t\t\t\t);\n\n\t\t\t\tconst length = message.sequenceNumber - this.startBatchSequenceNumber + 1;\n\t\t\t\tif (length >= batchLengthThreshold) {\n\t\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\t\teventName: \"LengthTooBig\",\n\t\t\t\t\t\tlength,\n\t\t\t\t\t\tthreshold: batchLengthThreshold,\n\t\t\t\t\t\tbatchEndSequenceNumber: message.sequenceNumber,\n\t\t\t\t\t\tduration: dateTimeProvider() - this.batchProcessingStartTimeStamp,\n\t\t\t\t\t\tbatchError: error !== undefined,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (this.trackedBatchCount % batchCountSamplingRate === 0) {\n\t\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\t\teventName: \"Length\",\n\t\t\t\t\t\tlength,\n\t\t\t\t\t\tsamplingRate: batchCountSamplingRate,\n\t\t\t\t\t\tbatchEndSequenceNumber: message.sequenceNumber,\n\t\t\t\t\t\tduration: dateTimeProvider() - this.batchProcessingStartTimeStamp,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tthis.startBatchSequenceNumber = undefined;\n\t\t\t\tthis.batchProcessingStartTimeStamp = undefined;\n\t\t\t},\n\t\t);\n\t}\n}\n\n/**\n * Track batch sizes in terms of op counts and processing times\n *\n * @param batchEventEmitter - event emitter which tracks the lifecycle of batch operations\n * @param logger - See {@link @fluidframework/common-definitions#ITelemetryLoggerExt}\n * @param batchLengthThreshold - threshold for the length of a batch when to send an error event\n * @param batchCountSamplingRate - rate for batches for which to send an event with its characteristics\n */\nexport const BindBatchTracker = (\n\tbatchEventEmitter: EventEmitter,\n\tlogger: ITelemetryLoggerExt,\n\tbatchLengthThreshold: number = 1000,\n\tbatchCountSamplingRate: number = 1000,\n) => new BatchTracker(batchEventEmitter, logger, batchLengthThreshold, batchCountSamplingRate);\n"]}
|
package/lib/blobManager.d.ts
CHANGED
|
@@ -38,6 +38,12 @@ export interface IBlobManagerLoadInfo {
|
|
|
38
38
|
redirectTable?: [string, string][];
|
|
39
39
|
}
|
|
40
40
|
export declare type IBlobManagerRuntime = Pick<IContainerRuntime, "attachState" | "connected" | "logger" | "clientDetails"> & Pick<ContainerRuntime, "gcTombstoneEnforcementAllowed"> & TypedEventEmitter<IContainerRuntimeEvents>;
|
|
41
|
+
export declare enum PendingBlobStatus {
|
|
42
|
+
OnlinePendingUpload = 0,
|
|
43
|
+
OnlinePendingOp = 1,
|
|
44
|
+
OfflinePendingUpload = 2,
|
|
45
|
+
OfflinePendingOp = 3
|
|
46
|
+
}
|
|
41
47
|
export interface IPendingBlobs {
|
|
42
48
|
[id: string]: {
|
|
43
49
|
blob: string;
|
|
@@ -104,6 +110,7 @@ export declare class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
104
110
|
private get pendingOfflineUploads();
|
|
105
111
|
get hasPendingOfflineUploads(): boolean;
|
|
106
112
|
get hasPendingBlobs(): boolean;
|
|
113
|
+
private createAbortError;
|
|
107
114
|
/**
|
|
108
115
|
* Upload blobs added while offline. This must be completed before connecting and resubmitting ops.
|
|
109
116
|
*/
|
|
@@ -121,7 +128,7 @@ export declare class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
121
128
|
getBlob(blobId: string): Promise<ArrayBufferLike>;
|
|
122
129
|
private getBlobHandle;
|
|
123
130
|
private createBlobDetached;
|
|
124
|
-
createBlob(blob: ArrayBufferLike): Promise<IFluidHandle<ArrayBufferLike>>;
|
|
131
|
+
createBlob(blob: ArrayBufferLike, signal?: AbortSignal): Promise<IFluidHandle<ArrayBufferLike>>;
|
|
125
132
|
private uploadBlob;
|
|
126
133
|
/**
|
|
127
134
|
* Set up a mapping in the redirect table from fromId to toId. Also, notify the runtime that a reference is added
|
|
@@ -129,6 +136,7 @@ export declare class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
129
136
|
*/
|
|
130
137
|
private setRedirection;
|
|
131
138
|
private deletePendingBlobMaybe;
|
|
139
|
+
private deletePendingBlob;
|
|
132
140
|
private onUploadResolve;
|
|
133
141
|
private onUploadReject;
|
|
134
142
|
private transitionToOffline;
|
package/lib/blobManager.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blobManager.d.ts","sourceRoot":"","sources":["../src/blobManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAEN,yBAAyB,EACzB,aAAa,EACb,MAAM,sCAAsC,CAAC;AAO9C,OAAO,EAKN,iBAAiB,EACjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACN,iBAAiB,EACjB,uBAAuB,EACvB,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAe,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAO7F,OAAO,EACN,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EAAE,gBAAgB,EAA8B,MAAM,oBAAoB,CAAC;AAMlF;;;;;;GAMG;AACH,qBAAa,UAAW,YAAW,YAAY,CAAC,eAAe,CAAC;aAc9C,IAAI,EAAE,MAAM;aACZ,YAAY,EAAE,mBAAmB;IAC1C,GAAG,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC;IAC9B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;IAhBhC,OAAO,CAAC,QAAQ,CAAkB;IAElC,IAAW,YAAY,IAAI,YAAY,CAEtC;IAED,IAAW,UAAU,IAAI,OAAO,CAE/B;IAED,SAAgB,YAAY,EAAE,MAAM,CAAC;gBAGpB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,mBAAmB,EAC1C,GAAG,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,EACb,aAAa,CAAC,SAAQ,IAAI,aAAA;IAKrC,WAAW;IAOX,IAAI,CAAC,MAAM,EAAE,YAAY;CAGhC;AAmBD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;CACnC;AAID,oBAAY,mBAAmB,GAAG,IAAI,CACrC,iBAAiB,EACjB,aAAa,GAAG,WAAW,GAAG,QAAQ,GAAG,eAAe,CACxD,GACA,IAAI,CAAC,gBAAgB,EAAE,+BAA+B,CAAC,GACvD,iBAAiB,CAAC,uBAAuB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"blobManager.d.ts","sourceRoot":"","sources":["../src/blobManager.ts"],"names":[],"mappings":"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"}
|
package/lib/blobManager.js
CHANGED
|
@@ -6,7 +6,7 @@ import { v4 as uuid } from "uuid";
|
|
|
6
6
|
import { createResponseError, generateHandleContextPath, responseToException, SummaryTreeBuilder, } from "@fluidframework/runtime-utils";
|
|
7
7
|
import { assert, bufferToString, Deferred, stringToBuffer, TypedEventEmitter, } from "@fluidframework/common-utils";
|
|
8
8
|
import { AttachState } from "@fluidframework/container-definitions";
|
|
9
|
-
import {
|
|
9
|
+
import { LoggingError, createChildMonitoringContext, PerformanceEvent, } from "@fluidframework/telemetry-utils";
|
|
10
10
|
import { GenericError } from "@fluidframework/container-utils";
|
|
11
11
|
import { TombstoneResponseHeaderKey } from "./containerRuntime";
|
|
12
12
|
import { sendGCUnexpectedUsageEvent, sweepAttachmentBlobsKey, throwOnTombstoneLoadKey } from "./gc";
|
|
@@ -63,7 +63,7 @@ class CancellableThrottler {
|
|
|
63
63
|
}
|
|
64
64
|
// Note that while offline we "submit" an op before uploading the blob, but we always
|
|
65
65
|
// expect blobs to be uploaded before we actually see the op round-trip
|
|
66
|
-
var PendingBlobStatus;
|
|
66
|
+
export var PendingBlobStatus;
|
|
67
67
|
(function (PendingBlobStatus) {
|
|
68
68
|
PendingBlobStatus[PendingBlobStatus["OnlinePendingUpload"] = 0] = "OnlinePendingUpload";
|
|
69
69
|
PendingBlobStatus[PendingBlobStatus["OnlinePendingOp"] = 1] = "OnlinePendingOp";
|
|
@@ -117,7 +117,10 @@ export class BlobManager extends TypedEventEmitter {
|
|
|
117
117
|
* Tombstone is a temporary feature that imitates a blob getting swept by garbage collection.
|
|
118
118
|
*/
|
|
119
119
|
this.tombstonedBlobs = new Set();
|
|
120
|
-
this.mc =
|
|
120
|
+
this.mc = createChildMonitoringContext({
|
|
121
|
+
logger: this.runtime.logger,
|
|
122
|
+
namespace: "BlobManager",
|
|
123
|
+
});
|
|
121
124
|
// Read the feature flag that tells whether to throw when a tombstone blob is requested.
|
|
122
125
|
this.throwOnTombstoneLoad =
|
|
123
126
|
this.mc.config.getBoolean(throwOnTombstoneLoadKey) === true &&
|
|
@@ -158,6 +161,8 @@ export class BlobManager extends TypedEventEmitter {
|
|
|
158
161
|
});
|
|
159
162
|
this.sendBlobAttachOp = (localId, blobId) => {
|
|
160
163
|
const pendingEntry = this.pendingBlobs.get(localId);
|
|
164
|
+
assert(pendingEntry !== undefined, 0x725 /* Must have pending blob entry for upcoming op */);
|
|
165
|
+
pendingEntry.opsent = true;
|
|
161
166
|
if ((pendingEntry === null || pendingEntry === void 0 ? void 0 : pendingEntry.uploadTime) && (pendingEntry === null || pendingEntry === void 0 ? void 0 : pendingEntry.minTTLInSeconds)) {
|
|
162
167
|
const secondsSinceUpload = (Date.now() - pendingEntry.uploadTime) / 1000;
|
|
163
168
|
const expired = pendingEntry.minTTLInSeconds - secondsSinceUpload < 0;
|
|
@@ -191,6 +196,13 @@ export class BlobManager extends TypedEventEmitter {
|
|
|
191
196
|
return ((this.runtime.attachState !== AttachState.Attached && this.redirectTable.size > 0) ||
|
|
192
197
|
this.pendingBlobs.size > 0);
|
|
193
198
|
}
|
|
199
|
+
createAbortError(pending) {
|
|
200
|
+
return new LoggingError("uploadBlob aborted", {
|
|
201
|
+
acked: pending === null || pending === void 0 ? void 0 : pending.acked,
|
|
202
|
+
status: pending === null || pending === void 0 ? void 0 : pending.status,
|
|
203
|
+
uploadTime: pending === null || pending === void 0 ? void 0 : pending.uploadTime,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
194
206
|
/**
|
|
195
207
|
* Upload blobs added while offline. This must be completed before connecting and resubmitting ops.
|
|
196
208
|
*/
|
|
@@ -273,7 +285,7 @@ export class BlobManager extends TypedEventEmitter {
|
|
|
273
285
|
this.setRedirection(response.id, undefined);
|
|
274
286
|
return this.getBlobHandle(response.id);
|
|
275
287
|
}
|
|
276
|
-
async createBlob(blob) {
|
|
288
|
+
async createBlob(blob, signal) {
|
|
277
289
|
if (this.runtime.attachState === AttachState.Detached) {
|
|
278
290
|
return this.createBlobDetached(blob);
|
|
279
291
|
}
|
|
@@ -283,6 +295,9 @@ export class BlobManager extends TypedEventEmitter {
|
|
|
283
295
|
await new Promise((resolve) => this.runtime.once("attached", resolve));
|
|
284
296
|
}
|
|
285
297
|
assert(this.runtime.attachState === AttachState.Attached, 0x385 /* For clarity and paranoid defense against adding future attachment states */);
|
|
298
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
299
|
+
throw this.createAbortError();
|
|
300
|
+
}
|
|
286
301
|
// Create a local ID for the blob. After uploading it to storage and before returning it, a local ID to
|
|
287
302
|
// storage ID mapping is created.
|
|
288
303
|
const localId = uuid();
|
|
@@ -293,9 +308,19 @@ export class BlobManager extends TypedEventEmitter {
|
|
|
293
308
|
uploadP: this.uploadBlob(localId, blob),
|
|
294
309
|
attached: false,
|
|
295
310
|
acked: false,
|
|
311
|
+
abortSignal: signal,
|
|
312
|
+
opsent: false,
|
|
296
313
|
};
|
|
297
314
|
this.pendingBlobs.set(localId, pendingEntry);
|
|
298
|
-
|
|
315
|
+
const abortListener = () => {
|
|
316
|
+
if (!pendingEntry.acked) {
|
|
317
|
+
pendingEntry.handleP.reject(this.createAbortError(pendingEntry));
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
signal === null || signal === void 0 ? void 0 : signal.addEventListener("abort", abortListener, { once: true });
|
|
321
|
+
return pendingEntry.handleP.promise.finally(() => {
|
|
322
|
+
signal === null || signal === void 0 ? void 0 : signal.removeEventListener("abort", abortListener);
|
|
323
|
+
});
|
|
299
324
|
}
|
|
300
325
|
async uploadBlob(localId, blob) {
|
|
301
326
|
return PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "createBlob" }, async () => this.getStorage().createBlob(blob), { end: true, cancel: this.runtime.connected ? "error" : "generic" }).then((response) => this.onUploadResolve(localId, response), async (err) => this.onUploadReject(localId, err));
|
|
@@ -311,17 +336,23 @@ export class BlobManager extends TypedEventEmitter {
|
|
|
311
336
|
if (this.pendingBlobs.has(id)) {
|
|
312
337
|
const entry = this.pendingBlobs.get(id);
|
|
313
338
|
if ((entry === null || entry === void 0 ? void 0 : entry.attached) && (entry === null || entry === void 0 ? void 0 : entry.acked)) {
|
|
314
|
-
this.
|
|
315
|
-
if (!this.hasPendingBlobs) {
|
|
316
|
-
this.emit("noPendingBlobs");
|
|
317
|
-
}
|
|
339
|
+
this.deletePendingBlob(id);
|
|
318
340
|
}
|
|
319
341
|
}
|
|
320
342
|
}
|
|
343
|
+
deletePendingBlob(id) {
|
|
344
|
+
if (this.pendingBlobs.delete(id) && !this.hasPendingBlobs) {
|
|
345
|
+
this.emit("noPendingBlobs");
|
|
346
|
+
}
|
|
347
|
+
}
|
|
321
348
|
onUploadResolve(localId, response) {
|
|
322
|
-
var _a;
|
|
349
|
+
var _a, _b;
|
|
323
350
|
const entry = this.pendingBlobs.get(localId);
|
|
324
351
|
assert(entry !== undefined, 0x6c8 /* pending blob entry not found for uploaded blob */);
|
|
352
|
+
if (((_a = entry.abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) === true && !entry.opsent) {
|
|
353
|
+
this.deletePendingBlob(localId);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
325
356
|
assert(entry.status === PendingBlobStatus.OnlinePendingUpload ||
|
|
326
357
|
entry.status === PendingBlobStatus.OfflinePendingUpload, 0x386 /* Must have pending blob entry for uploaded blob */);
|
|
327
358
|
entry.storageId = response.id;
|
|
@@ -347,7 +378,7 @@ export class BlobManager extends TypedEventEmitter {
|
|
|
347
378
|
// If there is already an op for this storage ID, append the local ID to the list. Once any op for
|
|
348
379
|
// this storage ID is ack'd, all pending blobs for it can be resolved since the op will keep the
|
|
349
380
|
// blob alive in storage.
|
|
350
|
-
this.opsInFlight.set(response.id, ((
|
|
381
|
+
this.opsInFlight.set(response.id, ((_b = this.opsInFlight.get(response.id)) !== null && _b !== void 0 ? _b : []).concat(localId));
|
|
351
382
|
entry.status = PendingBlobStatus.OnlinePendingOp;
|
|
352
383
|
}
|
|
353
384
|
}
|
|
@@ -367,8 +398,13 @@ export class BlobManager extends TypedEventEmitter {
|
|
|
367
398
|
return response;
|
|
368
399
|
}
|
|
369
400
|
async onUploadReject(localId, error) {
|
|
401
|
+
var _a;
|
|
370
402
|
const entry = this.pendingBlobs.get(localId);
|
|
371
403
|
assert(!!entry, 0x387 /* Must have pending blob entry for blob which failed to upload */);
|
|
404
|
+
if (((_a = entry.abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) === true && !entry.opsent) {
|
|
405
|
+
this.deletePendingBlob(localId);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
372
408
|
if (!this.runtime.connected) {
|
|
373
409
|
if (entry.status === PendingBlobStatus.OnlinePendingUpload) {
|
|
374
410
|
this.transitionToOffline(localId);
|
|
@@ -424,9 +460,16 @@ export class BlobManager extends TypedEventEmitter {
|
|
|
424
460
|
return this.sendBlobAttachOp(localId, blobId);
|
|
425
461
|
}
|
|
426
462
|
processBlobAttachOp(message, local) {
|
|
427
|
-
var _a, _b;
|
|
463
|
+
var _a, _b, _c;
|
|
428
464
|
const localId = (_a = message.metadata) === null || _a === void 0 ? void 0 : _a.localId;
|
|
429
465
|
const blobId = (_b = message.metadata) === null || _b === void 0 ? void 0 : _b.blobId;
|
|
466
|
+
if (localId) {
|
|
467
|
+
const pendingEntry = this.pendingBlobs.get(localId);
|
|
468
|
+
if ((_c = pendingEntry === null || pendingEntry === void 0 ? void 0 : pendingEntry.abortSignal) === null || _c === void 0 ? void 0 : _c.aborted) {
|
|
469
|
+
this.deletePendingBlob(localId);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
430
473
|
assert(blobId !== undefined, 0x12a /* "Missing blob id on metadata" */);
|
|
431
474
|
// Set up a mapping from local ID to storage ID. This is crucial since without this the blob cannot be
|
|
432
475
|
// requested from the server.
|