@fluidframework/container-runtime 2.0.0-dev.4.1.0.148229 → 2.0.0-dev.4.2.0.153917

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.
Files changed (152) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +69 -0
  3. package/dist/blobManager.d.ts +6 -14
  4. package/dist/blobManager.d.ts.map +1 -1
  5. package/dist/blobManager.js +50 -37
  6. package/dist/blobManager.js.map +1 -1
  7. package/dist/containerRuntime.d.ts +14 -1
  8. package/dist/containerRuntime.d.ts.map +1 -1
  9. package/dist/containerRuntime.js +37 -12
  10. package/dist/containerRuntime.js.map +1 -1
  11. package/dist/gc/gcHelpers.d.ts.map +1 -1
  12. package/dist/gc/gcHelpers.js +6 -6
  13. package/dist/gc/gcHelpers.js.map +1 -1
  14. package/dist/opLifecycle/index.d.ts +1 -0
  15. package/dist/opLifecycle/index.d.ts.map +1 -1
  16. package/dist/opLifecycle/index.js +3 -1
  17. package/dist/opLifecycle/index.js.map +1 -1
  18. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  19. package/dist/opLifecycle/opDecompressor.js +2 -1
  20. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  21. package/dist/opLifecycle/opGroupingManager.d.ts +14 -0
  22. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -0
  23. package/dist/opLifecycle/opGroupingManager.js +56 -0
  24. package/dist/opLifecycle/opGroupingManager.js.map +1 -0
  25. package/dist/opLifecycle/opSplitter.d.ts +1 -1
  26. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  27. package/dist/opLifecycle/opSplitter.js +5 -6
  28. package/dist/opLifecycle/opSplitter.js.map +1 -1
  29. package/dist/opLifecycle/outbox.d.ts +2 -0
  30. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  31. package/dist/opLifecycle/outbox.js +3 -3
  32. package/dist/opLifecycle/outbox.js.map +1 -1
  33. package/dist/opLifecycle/remoteMessageProcessor.d.ts +4 -2
  34. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  35. package/dist/opLifecycle/remoteMessageProcessor.js +30 -20
  36. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  37. package/dist/packageVersion.d.ts +1 -1
  38. package/dist/packageVersion.js +1 -1
  39. package/dist/packageVersion.js.map +1 -1
  40. package/dist/summary/index.d.ts +1 -1
  41. package/dist/summary/index.d.ts.map +1 -1
  42. package/dist/summary/index.js +3 -1
  43. package/dist/summary/index.js.map +1 -1
  44. package/dist/summary/runningSummarizer.d.ts +5 -3
  45. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  46. package/dist/summary/runningSummarizer.js +82 -67
  47. package/dist/summary/runningSummarizer.js.map +1 -1
  48. package/dist/summary/summarizer.d.ts.map +1 -1
  49. package/dist/summary/summarizer.js +1 -5
  50. package/dist/summary/summarizer.js.map +1 -1
  51. package/dist/summary/summarizerHeuristics.d.ts +1 -0
  52. package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
  53. package/dist/summary/summarizerHeuristics.js +3 -0
  54. package/dist/summary/summarizerHeuristics.js.map +1 -1
  55. package/dist/summary/summarizerNode/summarizerNode.js +1 -1
  56. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  57. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +128 -2
  58. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  59. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +4 -3
  60. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  61. package/dist/summary/summarizerTypes.d.ts +14 -2
  62. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  63. package/dist/summary/summarizerTypes.js.map +1 -1
  64. package/dist/summary/summaryGenerator.d.ts +28 -2
  65. package/dist/summary/summaryGenerator.d.ts.map +1 -1
  66. package/dist/summary/summaryGenerator.js +19 -16
  67. package/dist/summary/summaryGenerator.js.map +1 -1
  68. package/lib/blobManager.d.ts +6 -14
  69. package/lib/blobManager.d.ts.map +1 -1
  70. package/lib/blobManager.js +50 -37
  71. package/lib/blobManager.js.map +1 -1
  72. package/lib/containerRuntime.d.ts +14 -1
  73. package/lib/containerRuntime.d.ts.map +1 -1
  74. package/lib/containerRuntime.js +38 -13
  75. package/lib/containerRuntime.js.map +1 -1
  76. package/lib/gc/gcHelpers.d.ts.map +1 -1
  77. package/lib/gc/gcHelpers.js +6 -6
  78. package/lib/gc/gcHelpers.js.map +1 -1
  79. package/lib/opLifecycle/index.d.ts +1 -0
  80. package/lib/opLifecycle/index.d.ts.map +1 -1
  81. package/lib/opLifecycle/index.js +1 -0
  82. package/lib/opLifecycle/index.js.map +1 -1
  83. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  84. package/lib/opLifecycle/opDecompressor.js +2 -1
  85. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  86. package/lib/opLifecycle/opGroupingManager.d.ts +14 -0
  87. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -0
  88. package/lib/opLifecycle/opGroupingManager.js +52 -0
  89. package/lib/opLifecycle/opGroupingManager.js.map +1 -0
  90. package/lib/opLifecycle/opSplitter.d.ts +1 -1
  91. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  92. package/lib/opLifecycle/opSplitter.js +5 -6
  93. package/lib/opLifecycle/opSplitter.js.map +1 -1
  94. package/lib/opLifecycle/outbox.d.ts +2 -0
  95. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  96. package/lib/opLifecycle/outbox.js +3 -3
  97. package/lib/opLifecycle/outbox.js.map +1 -1
  98. package/lib/opLifecycle/remoteMessageProcessor.d.ts +4 -2
  99. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  100. package/lib/opLifecycle/remoteMessageProcessor.js +30 -20
  101. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  102. package/lib/packageVersion.d.ts +1 -1
  103. package/lib/packageVersion.js +1 -1
  104. package/lib/packageVersion.js.map +1 -1
  105. package/lib/summary/index.d.ts +1 -1
  106. package/lib/summary/index.d.ts.map +1 -1
  107. package/lib/summary/index.js +1 -0
  108. package/lib/summary/index.js.map +1 -1
  109. package/lib/summary/runningSummarizer.d.ts +5 -3
  110. package/lib/summary/runningSummarizer.d.ts.map +1 -1
  111. package/lib/summary/runningSummarizer.js +82 -67
  112. package/lib/summary/runningSummarizer.js.map +1 -1
  113. package/lib/summary/summarizer.d.ts.map +1 -1
  114. package/lib/summary/summarizer.js +1 -5
  115. package/lib/summary/summarizer.js.map +1 -1
  116. package/lib/summary/summarizerHeuristics.d.ts +1 -0
  117. package/lib/summary/summarizerHeuristics.d.ts.map +1 -1
  118. package/lib/summary/summarizerHeuristics.js +3 -0
  119. package/lib/summary/summarizerHeuristics.js.map +1 -1
  120. package/lib/summary/summarizerNode/summarizerNode.js +1 -1
  121. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  122. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +128 -2
  123. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  124. package/lib/summary/summarizerNode/summarizerNodeWithGc.js +3 -3
  125. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  126. package/lib/summary/summarizerTypes.d.ts +14 -2
  127. package/lib/summary/summarizerTypes.d.ts.map +1 -1
  128. package/lib/summary/summarizerTypes.js.map +1 -1
  129. package/lib/summary/summaryGenerator.d.ts +28 -2
  130. package/lib/summary/summaryGenerator.d.ts.map +1 -1
  131. package/lib/summary/summaryGenerator.js +17 -15
  132. package/lib/summary/summaryGenerator.js.map +1 -1
  133. package/package.json +19 -16
  134. package/src/blobManager.ts +64 -41
  135. package/src/containerRuntime.ts +70 -9
  136. package/src/gc/gcHelpers.ts +9 -6
  137. package/src/opLifecycle/README.md +106 -0
  138. package/src/opLifecycle/index.ts +1 -0
  139. package/src/opLifecycle/opDecompressor.ts +1 -0
  140. package/src/opLifecycle/opGroupingManager.ts +78 -0
  141. package/src/opLifecycle/opSplitter.ts +1 -5
  142. package/src/opLifecycle/outbox.ts +7 -3
  143. package/src/opLifecycle/remoteMessageProcessor.ts +38 -22
  144. package/src/packageVersion.ts +1 -1
  145. package/src/summary/index.ts +1 -1
  146. package/src/summary/runningSummarizer.ts +102 -80
  147. package/src/summary/summarizer.ts +0 -8
  148. package/src/summary/summarizerHeuristics.ts +4 -0
  149. package/src/summary/summarizerNode/summarizerNode.ts +1 -1
  150. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +3 -3
  151. package/src/summary/summarizerTypes.ts +20 -3
  152. package/src/summary/summaryGenerator.ts +22 -16
@@ -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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport {\n\tassert,\n\tDeferred,\n\tIPromiseTimer,\n\tIPromiseTimerResult,\n\tTimer,\n} from \"@fluidframework/common-utils\";\nimport { MessageType } from \"@fluidframework/protocol-definitions\";\nimport { PerformanceEvent, LoggingError, ChildLogger } from \"@fluidframework/telemetry-utils\";\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} 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\nexport class SummarizeResultBuilder {\n\tpublic readonly summarySubmitted = new Deferred<SummarizeResultPart<SubmitSummaryResult>>();\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\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);\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 * 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 raiseSummarizingError: (errorMessage: string) => void,\n\t\tprivate readonly successfulSummaryCallback: () => void,\n\t\tprivate readonly summaryWatcher: Pick<IClientSummaryWatcher, \"watchSummary\">,\n\t\tprivate readonly logger: ITelemetryLogger,\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\t// Helper functions to report failures and return.\n\t\tconst getFailMessage = (errorCode: keyof typeof summarizeErrors) =>\n\t\t\t`${errorCode}: ${summarizeErrors[errorCode]}`;\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\tthis.raiseSummarizingError(summarizeErrors[errorCode]);\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 message = 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: errorCode,\n\t\t\t\t\tcategory,\n\t\t\t\t\tretryAfterSeconds,\n\t\t\t\t},\n\t\t\t\terror ?? message,\n\t\t\t); // disconnect & summaryAckTimeout do not have proper error.\n\t\t\tresultsBuilder.fail(message, error, nackSummaryResult, retryAfterSeconds);\n\t\t};\n\n\t\t// Wait to generate and send summary\n\t\tthis.summarizeTimer.start();\n\n\t\t// Use record type to prevent unexpected value types\n\t\tlet summaryData: SubmitSummaryResult | undefined;\n\t\ttry {\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\tconst opsSinceLastSummary =\n\t\t\t\treferenceSequenceNumber -\n\t\t\t\tthis.heuristicData.lastSuccessfulSummary.refSequenceNumber;\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:\n\t\t\t\t\treferenceSequenceNumber - this.heuristicData.lastAttempt.refSequenceNumber,\n\t\t\t\topsSinceLastSummary,\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 (summarizedDataStoreCount > gcStateUpdatedDataStoreCount + opsSinceLastSummary) {\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,\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\tthis.heuristicData.recordAttempt(summaryData?.referenceSequenceNumber);\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\");\n\t\t\t}\n\t\t\tif (waitBroadcastResult.result !== \"done\") {\n\t\t\t\treturn fail(\"summaryOpWaitTimeout\");\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};\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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport {\n\tassert,\n\tDeferred,\n\tIPromiseTimer,\n\tIPromiseTimerResult,\n\tTimer,\n} from \"@fluidframework/common-utils\";\nimport { MessageType } from \"@fluidframework/protocol-definitions\";\nimport { PerformanceEvent, LoggingError, ChildLogger } from \"@fluidframework/telemetry-utils\";\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} 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<SummarizeResultPart<SubmitSummaryResult>>();\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\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);\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 * 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: ITelemetryLogger,\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\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\t\t\tresultsBuilder.fail(reason, error, nackSummaryResult, retryAfterSeconds);\n\t\t};\n\n\t\t// Wait to generate and send summary\n\t\tthis.summarizeTimer.start();\n\n\t\t// Use record type to prevent unexpected value types\n\t\tlet summaryData: SubmitSummaryResult | undefined;\n\t\ttry {\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\tthis.heuristicData.recordAttempt(summaryData.referenceSequenceNumber);\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:\n\t\t\t\t\treferenceSequenceNumber - this.heuristicData.lastAttempt.refSequenceNumber,\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\");\n\t\t\t}\n\t\t\tif (waitBroadcastResult.result !== \"done\") {\n\t\t\t\treturn fail(\"summaryOpWaitTimeout\");\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};\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"]}
@@ -7,6 +7,7 @@ import { IDocumentStorageService } from "@fluidframework/driver-definitions";
7
7
  import { ISequencedDocumentMessage, ISnapshotTree } from "@fluidframework/protocol-definitions";
8
8
  import { TypedEventEmitter } from "@fluidframework/common-utils";
9
9
  import { IContainerRuntime, IContainerRuntimeEvents } from "@fluidframework/container-runtime-definitions";
10
+ import { ICriticalContainerError } from "@fluidframework/container-definitions";
10
11
  import { IGarbageCollectionData, ISummaryTreeWithStats, ITelemetryContext } from "@fluidframework/runtime-definitions";
11
12
  import { ContainerRuntime } from "./containerRuntime";
12
13
  /**
@@ -39,6 +40,8 @@ export declare type IBlobManagerRuntime = Pick<IContainerRuntime, "attachState"
39
40
  export interface IPendingBlobs {
40
41
  [id: string]: {
41
42
  blob: string;
43
+ uploadTime?: number;
44
+ minTTLInSeconds?: number;
42
45
  };
43
46
  }
44
47
  export interface IBlobManagerEvents {
@@ -47,21 +50,10 @@ export interface IBlobManagerEvents {
47
50
  export declare class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
48
51
  private readonly routeContext;
49
52
  private readonly getStorage;
50
- /**
51
- * Submit a BlobAttach op. When a blob is uploaded, there is a short grace period before which the blob is
52
- * deleted. The BlobAttach op notifies the server that blob is in use. The server will then not delete the
53
- * the blob as long as it is listed as referenced in future summaries. The summarizing client will know to
54
- * include the storage ID in the summary when it sees the op.
55
- *
56
- * The op will also include a local ID to inform all clients of the relation to the storage ID, without
57
- * knowledge of which they cannot request the blob from storage. It's important that this op is sequenced
58
- * before any ops that reference the local ID, otherwise, an invalid handle could be added to the document.
59
- */
60
- private readonly sendBlobAttachOp;
61
53
  private readonly blobRequested;
62
54
  private readonly isBlobDeleted;
63
55
  private readonly runtime;
64
- private readonly getCurrentReferenceTimestampMs;
56
+ private readonly closeContainer;
65
57
  static readonly basePath = "_blobs";
66
58
  private static readonly redirectTableBlobName;
67
59
  private readonly mc;
@@ -93,6 +85,7 @@ export declare class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
93
85
  * Tombstone is a temporary feature that imitates a blob getting swept by garbage collection.
94
86
  */
95
87
  private readonly tombstonedBlobs;
88
+ private readonly sendBlobAttachOp;
96
89
  constructor(routeContext: IFluidHandleContext, snapshot: IBlobManagerLoadInfo, getStorage: () => IDocumentStorageService,
97
90
  /**
98
91
  * Submit a BlobAttach op. When a blob is uploaded, there is a short grace period before which the blob is
@@ -104,7 +97,7 @@ export declare class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
104
97
  * knowledge of which they cannot request the blob from storage. It's important that this op is sequenced
105
98
  * before any ops that reference the local ID, otherwise, an invalid handle could be added to the document.
106
99
  */
107
- sendBlobAttachOp: (localId: string, storageId?: string) => void, blobRequested: (blobPath: string) => void, isBlobDeleted: (blobPath: string) => boolean, runtime: IBlobManagerRuntime, stashedBlobs: IPendingBlobs | undefined, getCurrentReferenceTimestampMs: () => number | undefined);
100
+ sendBlobAttachOp: (localId: string, storageId?: string) => void, blobRequested: (blobPath: string) => void, isBlobDeleted: (blobPath: string) => boolean, runtime: IBlobManagerRuntime, stashedBlobs: IPendingBlobs | undefined, closeContainer: (error?: ICriticalContainerError) => void);
108
101
  private get pendingOfflineUploads();
109
102
  get hasPendingOfflineUploads(): boolean;
110
103
  get hasPendingBlobs(): boolean;
@@ -142,7 +135,6 @@ export declare class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
142
135
  * @param metadata - op metadata containing storage and/or local IDs
143
136
  */
144
137
  reSubmit(metadata: Record<string, unknown> | undefined): void;
145
- private logTimeInfo;
146
138
  processBlobAttachOp(message: ISequencedDocumentMessage, local: boolean): void;
147
139
  /**
148
140
  * Reads blobs needed to load BlobManager from storage.
@@ -1 +1 @@
1
- {"version":3,"file":"blobManager.d.ts","sourceRoot":"","sources":["../src/blobManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"blobManager.d.ts","sourceRoot":"","sources":["../src/blobManager.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ import { createResponseError, generateHandleContextPath, responseToException, Su
7
7
  import { assert, bufferToString, Deferred, stringToBuffer, TypedEventEmitter, } from "@fluidframework/common-utils";
8
8
  import { AttachState } from "@fluidframework/container-definitions";
9
9
  import { ChildLogger, loggerToMonitoringContext, PerformanceEvent, } from "@fluidframework/telemetry-utils";
10
+ import { GenericError } from "@fluidframework/container-utils";
10
11
  import { TombstoneResponseHeaderKey } from "./containerRuntime";
11
12
  import { sendGCUnexpectedUsageEvent, sweepAttachmentBlobsKey, throwOnTombstoneLoadKey } from "./gc";
12
13
  import { Throttler, formExponentialFn } from "./throttler";
@@ -82,15 +83,14 @@ export class BlobManager extends TypedEventEmitter {
82
83
  blobRequested,
83
84
  // Called to check if a blob has been deleted by GC.
84
85
  // blobPath's format - `/<BlobManager.basePath>/<blobId>`.
85
- isBlobDeleted, runtime, stashedBlobs = {}, getCurrentReferenceTimestampMs) {
86
+ isBlobDeleted, runtime, stashedBlobs = {}, closeContainer) {
86
87
  super();
87
88
  this.routeContext = routeContext;
88
89
  this.getStorage = getStorage;
89
- this.sendBlobAttachOp = sendBlobAttachOp;
90
90
  this.blobRequested = blobRequested;
91
91
  this.isBlobDeleted = isBlobDeleted;
92
92
  this.runtime = runtime;
93
- this.getCurrentReferenceTimestampMs = getCurrentReferenceTimestampMs;
93
+ this.closeContainer = closeContainer;
94
94
  /**
95
95
  * Blobs which have not been uploaded or for which we have not yet seen a BlobAttach op round-trip.
96
96
  * Until we see the op round-trip, there is a possibility we may need to re-upload the blob, so
@@ -123,6 +123,21 @@ export class BlobManager extends TypedEventEmitter {
123
123
  // Begin uploading stashed blobs from previous container instance
124
124
  Object.entries(stashedBlobs).forEach(([localId, entry]) => {
125
125
  const blob = stringToBuffer(entry.blob, "base64");
126
+ if (entry.minTTLInSeconds && entry.uploadTime) {
127
+ const timeLapseSinceLocalUpload = (Date.now() - entry.uploadTime) / 1000;
128
+ // stashed entries with more than half-life in storage will not be reuploaded
129
+ if (entry.minTTLInSeconds - timeLapseSinceLocalUpload > entry.minTTLInSeconds / 2) {
130
+ this.pendingBlobs.set(localId, {
131
+ blob,
132
+ status: PendingBlobStatus.OfflinePendingOp,
133
+ handleP: new Deferred(),
134
+ uploadP: undefined,
135
+ uploadTime: entry.uploadTime,
136
+ minTTLInSeconds: entry.minTTLInSeconds,
137
+ });
138
+ return;
139
+ }
140
+ }
126
141
  this.pendingBlobs.set(localId, {
127
142
  blob,
128
143
  status: PendingBlobStatus.OfflinePendingUpload,
@@ -130,6 +145,30 @@ export class BlobManager extends TypedEventEmitter {
130
145
  uploadP: this.uploadBlob(localId, blob),
131
146
  });
132
147
  });
148
+ this.sendBlobAttachOp = (localId, blobId) => {
149
+ const pendingEntry = this.pendingBlobs.get(localId);
150
+ if ((pendingEntry === null || pendingEntry === void 0 ? void 0 : pendingEntry.uploadTime) && (pendingEntry === null || pendingEntry === void 0 ? void 0 : pendingEntry.minTTLInSeconds)) {
151
+ const secondsSinceUpload = (Date.now() - pendingEntry.uploadTime) / 1000;
152
+ const expired = pendingEntry.minTTLInSeconds - secondsSinceUpload < 0;
153
+ this.mc.logger.sendTelemetryEvent({
154
+ eventName: "sendBlobAttach",
155
+ entryStatus: pendingEntry.status,
156
+ secondsSinceUpload,
157
+ minTTLInSeconds: pendingEntry.minTTLInSeconds,
158
+ expired,
159
+ });
160
+ if (expired) {
161
+ // we want to avoid submitting ops with broken handles
162
+ this.closeContainer(new GenericError("Trying to submit a BlobAttach for expired blob", undefined, {
163
+ localId,
164
+ blobId,
165
+ entryStatus: pendingEntry.status,
166
+ secondsSinceUpload,
167
+ }));
168
+ }
169
+ }
170
+ return sendBlobAttachOp(localId, blobId);
171
+ };
133
172
  }
134
173
  get pendingOfflineUploads() {
135
174
  return Array.from(this.pendingBlobs.values()).filter((e) => e.status === PendingBlobStatus.OfflinePendingUpload);
@@ -262,9 +301,8 @@ export class BlobManager extends TypedEventEmitter {
262
301
  assert((entry === null || entry === void 0 ? void 0 : entry.status) === PendingBlobStatus.OnlinePendingUpload ||
263
302
  (entry === null || entry === void 0 ? void 0 : entry.status) === PendingBlobStatus.OfflinePendingUpload, 0x386 /* Must have pending blob entry for uploaded blob */);
264
303
  entry.storageId = response.id;
265
- entry.localUploadTime = Date.now();
304
+ entry.uploadTime = Date.now();
266
305
  entry.minTTLInSeconds = response.minTTLInSeconds;
267
- entry.serverUploadTime = this.getCurrentReferenceTimestampMs();
268
306
  if (this.runtime.connected) {
269
307
  if (entry.status === PendingBlobStatus.OnlinePendingUpload) {
270
308
  // Send a blob attach op. This serves two purposes:
@@ -272,7 +310,6 @@ export class BlobManager extends TypedEventEmitter {
272
310
  // until its storage ID is added to the next summary.
273
311
  // 2. It will create a local ID to storage ID mapping in all clients which is needed to retrieve the
274
312
  // blob from the server via the storage ID.
275
- this.logTimeInfo(entry, "sendBlobAttachResolveTTL");
276
313
  this.sendBlobAttachOp(localId, response.id);
277
314
  if (this.storageIds.has(response.id)) {
278
315
  // The blob is de-duped. Set up a local ID to storage ID mapping and return the blob. Since this is
@@ -336,7 +373,6 @@ export class BlobManager extends TypedEventEmitter {
336
373
  * is called on reconnection.
337
374
  */
338
375
  if (entry.status !== PendingBlobStatus.OnlinePendingOp) {
339
- this.logTimeInfo(entry, "sendBlobAttachTransitionOfflineTTL");
340
376
  this.sendBlobAttachOp(localId, entry.storageId);
341
377
  }
342
378
  entry.status =
@@ -355,9 +391,6 @@ export class BlobManager extends TypedEventEmitter {
355
391
  const { localId, blobId } = metadata;
356
392
  assert(localId !== undefined, 0x50d /* local ID not available on reSubmit */);
357
393
  const pendingEntry = this.pendingBlobs.get(localId);
358
- if (pendingEntry) {
359
- this.logTimeInfo(pendingEntry, "sendBlobAttachResubmitTTL");
360
- }
361
394
  if (!blobId) {
362
395
  // We submitted this op while offline. The blob should have been uploaded by now.
363
396
  assert((pendingEntry === null || pendingEntry === void 0 ? void 0 : pendingEntry.status) === PendingBlobStatus.OfflinePendingOp &&
@@ -366,32 +399,6 @@ export class BlobManager extends TypedEventEmitter {
366
399
  }
367
400
  return this.sendBlobAttachOp(localId, blobId);
368
401
  }
369
- logTimeInfo(pendingEntry, eventName) {
370
- var _a, _b;
371
- let timeLapseSinceLocalUpload = 0;
372
- let timeLapseSinceServerUpload = 0;
373
- let expiredUsingLocalTime;
374
- let expiredUsingServerTime;
375
- if (pendingEntry.localUploadTime) {
376
- timeLapseSinceLocalUpload = (Date.now() - pendingEntry.localUploadTime) / 1000;
377
- expiredUsingLocalTime =
378
- ((_a = pendingEntry.minTTLInSeconds) !== null && _a !== void 0 ? _a : 0) - timeLapseSinceLocalUpload < 0 ? true : false;
379
- }
380
- if (pendingEntry.serverUploadTime) {
381
- timeLapseSinceServerUpload = (Date.now() - pendingEntry.serverUploadTime) / 1000;
382
- expiredUsingServerTime =
383
- ((_b = pendingEntry.minTTLInSeconds) !== null && _b !== void 0 ? _b : 0) - timeLapseSinceServerUpload < 0 ? true : false;
384
- }
385
- this.mc.logger.sendTelemetryEvent({
386
- eventName,
387
- entryStatus: pendingEntry.status,
388
- timeLapseSinceLocalUpload,
389
- timeLapseSinceServerUpload,
390
- minTTLInSeconds: pendingEntry.minTTLInSeconds,
391
- expiredUsingLocalTime,
392
- expiredUsingServerTime,
393
- });
394
- }
395
402
  processBlobAttachOp(message, local) {
396
403
  var _a, _b;
397
404
  const localId = (_a = message.metadata) === null || _a === void 0 ? void 0 : _a.localId;
@@ -647,7 +654,13 @@ export class BlobManager extends TypedEventEmitter {
647
654
  getPendingBlobs() {
648
655
  const blobs = {};
649
656
  for (const [key, entry] of this.pendingBlobs) {
650
- blobs[key] = { blob: bufferToString(entry.blob, "base64") };
657
+ blobs[key] = entry.minTTLInSeconds
658
+ ? {
659
+ blob: bufferToString(entry.blob, "base64"),
660
+ uploadTime: entry.uploadTime,
661
+ minTTLInSeconds: entry.minTTLInSeconds,
662
+ }
663
+ : { blob: bufferToString(entry.blob, "base64") };
651
664
  }
652
665
  return blobs;
653
666
  }