@fluidframework/container-runtime 2.12.0 → 2.13.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/container-runtime.test-files.tar +0 -0
  3. package/dist/blobManager/blobManagerSnapSum.js.map +1 -1
  4. package/dist/channelCollection.js.map +1 -1
  5. package/dist/containerRuntime.d.ts.map +1 -1
  6. package/dist/containerRuntime.js.map +1 -1
  7. package/dist/gc/garbageCollection.d.ts.map +1 -1
  8. package/dist/gc/garbageCollection.js.map +1 -1
  9. package/dist/gc/gcConfigs.js +1 -1
  10. package/dist/gc/gcConfigs.js.map +1 -1
  11. package/dist/gc/gcHelpers.js.map +1 -1
  12. package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
  13. package/dist/opLifecycle/opDecompressor.js +0 -1
  14. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  15. package/dist/opLifecycle/opSplitter.js +0 -1
  16. package/dist/opLifecycle/opSplitter.js.map +1 -1
  17. package/dist/packageVersion.d.ts +1 -1
  18. package/dist/packageVersion.js +1 -1
  19. package/dist/packageVersion.js.map +1 -1
  20. package/dist/pendingStateManager.d.ts +4 -0
  21. package/dist/pendingStateManager.d.ts.map +1 -1
  22. package/dist/pendingStateManager.js +31 -1
  23. package/dist/pendingStateManager.js.map +1 -1
  24. package/dist/scheduleManager.js +0 -2
  25. package/dist/scheduleManager.js.map +1 -1
  26. package/dist/summary/summaryCollection.js +0 -2
  27. package/dist/summary/summaryCollection.js.map +1 -1
  28. package/lib/blobManager/blobManagerSnapSum.js.map +1 -1
  29. package/lib/channelCollection.js.map +1 -1
  30. package/lib/containerRuntime.d.ts.map +1 -1
  31. package/lib/containerRuntime.js.map +1 -1
  32. package/lib/gc/garbageCollection.d.ts.map +1 -1
  33. package/lib/gc/garbageCollection.js.map +1 -1
  34. package/lib/gc/gcConfigs.js +1 -1
  35. package/lib/gc/gcConfigs.js.map +1 -1
  36. package/lib/gc/gcHelpers.js.map +1 -1
  37. package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -1
  38. package/lib/opLifecycle/opDecompressor.js +0 -1
  39. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  40. package/lib/opLifecycle/opSplitter.js +0 -1
  41. package/lib/opLifecycle/opSplitter.js.map +1 -1
  42. package/lib/packageVersion.d.ts +1 -1
  43. package/lib/packageVersion.js +1 -1
  44. package/lib/packageVersion.js.map +1 -1
  45. package/lib/pendingStateManager.d.ts +4 -0
  46. package/lib/pendingStateManager.d.ts.map +1 -1
  47. package/lib/pendingStateManager.js +29 -0
  48. package/lib/pendingStateManager.js.map +1 -1
  49. package/lib/scheduleManager.js +0 -2
  50. package/lib/scheduleManager.js.map +1 -1
  51. package/lib/summary/summaryCollection.js +0 -2
  52. package/lib/summary/summaryCollection.js.map +1 -1
  53. package/package.json +19 -19
  54. package/src/blobManager/blobManagerSnapSum.ts +1 -1
  55. package/src/channelCollection.ts +1 -1
  56. package/src/containerRuntime.ts +2 -1
  57. package/src/gc/garbageCollection.ts +2 -1
  58. package/src/gc/gcConfigs.ts +1 -1
  59. package/src/gc/gcHelpers.ts +2 -2
  60. package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
  61. package/src/opLifecycle/opDecompressor.ts +1 -1
  62. package/src/opLifecycle/opSplitter.ts +1 -1
  63. package/src/packageVersion.ts +1 -1
  64. package/src/pendingStateManager.ts +38 -0
  65. package/src/scheduleManager.ts +2 -2
  66. package/src/summary/summaryCollection.ts +2 -2
@@ -21,7 +21,6 @@ class Summary {
21
21
  }
22
22
  static createFromOp(op) {
23
23
  // TODO: Verify whether this should be able to handle server-generated ops (with null clientId)
24
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
25
24
  const summary = new Summary(op.clientId, op.clientSequenceNumber);
26
25
  summary.broadcast(op);
27
26
  return summary;
@@ -252,7 +251,6 @@ class SummaryCollection extends client_utils_1.TypedEventEmitter {
252
251
  let summary;
253
252
  // Check if summary already being watched, broadcast if so
254
253
  // TODO: Verify whether this should be able to handle server-generated ops (with null clientId)
255
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
256
254
  const watcher = this.summaryWatchers.get(op.clientId);
257
255
  if (watcher) {
258
256
  summary = watcher.tryGetSummary(op.clientSequenceNumber);
@@ -1 +1 @@
1
- {"version":3,"file":"summaryCollection.js","sourceRoot":"","sources":["../../src/summary/summaryCollection.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 { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { IDeltaManager } from \"@fluidframework/container-definitions/internal\";\nimport { IDisposable, IEvent } from \"@fluidframework/core-interfaces\";\nimport { assert, Deferred } from \"@fluidframework/core-utils/internal\";\nimport {\n\tIDocumentMessage,\n\tISummaryAck,\n\tISummaryContent,\n\tISummaryNack,\n\tMessageType,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils/internal\";\n\n/**\n * Interface for summary op messages with typed contents.\n * @legacy\n * @alpha\n */\nexport interface ISummaryOpMessage extends ISequencedDocumentMessage {\n\ttype: MessageType.Summarize;\n\tcontents: ISummaryContent;\n}\n\n/**\n * Interface for summary ack messages with typed contents.\n * @legacy\n * @alpha\n */\nexport interface ISummaryAckMessage extends ISequencedDocumentMessage {\n\ttype: MessageType.SummaryAck;\n\tcontents: ISummaryAck;\n}\n\n/**\n * Interface for summary nack messages with typed contents.\n * @legacy\n * @alpha\n */\nexport interface ISummaryNackMessage extends ISequencedDocumentMessage {\n\ttype: MessageType.SummaryNack;\n\tcontents: ISummaryNack;\n}\n\n/**\n * A single summary which can be tracked as it goes through its life cycle.\n * The life cycle is: Local to Broadcast to Acked/Nacked.\n * @legacy\n * @alpha\n */\nexport interface ISummary {\n\treadonly clientId: string;\n\treadonly clientSequenceNumber: number;\n\twaitBroadcast(): Promise<ISummaryOpMessage>;\n\twaitAckNack(): Promise<ISummaryAckMessage | ISummaryNackMessage>;\n}\n\n/**\n * A single summary which has already been acked by the server.\n * @legacy\n * @alpha\n */\nexport interface IAckedSummary {\n\treadonly summaryOp: ISummaryOpMessage;\n\treadonly summaryAck: ISummaryAckMessage;\n}\n\nenum SummaryState {\n\tLocal = 0,\n\tBroadcast = 1,\n\tAcked = 2,\n\tNacked = -1,\n}\n\nclass Summary implements ISummary {\n\tpublic static createLocal(clientId: string, clientSequenceNumber: number) {\n\t\treturn new Summary(clientId, clientSequenceNumber);\n\t}\n\tpublic static createFromOp(op: ISummaryOpMessage) {\n\t\t// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)\n\t\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n\t\tconst summary = new Summary(op.clientId as string, op.clientSequenceNumber);\n\t\tsummary.broadcast(op);\n\t\treturn summary;\n\t}\n\n\tprivate state = SummaryState.Local;\n\n\tprivate _summaryOp?: ISummaryOpMessage;\n\tprivate _summaryAckNack?: ISummaryAckMessage | ISummaryNackMessage;\n\n\tprivate readonly defSummaryOp = new Deferred<void>();\n\tprivate readonly defSummaryAck = new Deferred<void>();\n\n\tpublic get summaryOp() {\n\t\treturn this._summaryOp;\n\t}\n\tpublic get summaryAckNack() {\n\t\treturn this._summaryAckNack;\n\t}\n\n\tprivate constructor(\n\t\tpublic readonly clientId: string,\n\t\tpublic readonly clientSequenceNumber: number,\n\t) {}\n\n\tpublic hasBeenAcked(): this is IAckedSummary {\n\t\treturn this.state === SummaryState.Acked;\n\t}\n\n\tpublic broadcast(op: ISummaryOpMessage) {\n\t\tassert(\n\t\t\tthis.state === SummaryState.Local,\n\t\t\t0x175 /* \"Can only broadcast if summarizer starts in local state\" */,\n\t\t);\n\t\tthis._summaryOp = op;\n\t\tthis.defSummaryOp.resolve();\n\t\tthis.state = SummaryState.Broadcast;\n\t\treturn true;\n\t}\n\n\tpublic ackNack(op: ISummaryAckMessage | ISummaryNackMessage) {\n\t\tassert(\n\t\t\tthis.state === SummaryState.Broadcast,\n\t\t\t0x176 /* \"Can only ack/nack if summarizer is in broadcasting state\" */,\n\t\t);\n\t\tthis._summaryAckNack = op;\n\t\tthis.defSummaryAck.resolve();\n\t\tthis.state = op.type === MessageType.SummaryAck ? SummaryState.Acked : SummaryState.Nacked;\n\t\treturn true;\n\t}\n\n\tpublic async waitBroadcast(): Promise<ISummaryOpMessage> {\n\t\tawait this.defSummaryOp.promise;\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\treturn this._summaryOp!;\n\t}\n\n\tpublic async waitAckNack(): Promise<ISummaryAckMessage | ISummaryNackMessage> {\n\t\tawait this.defSummaryAck.promise;\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\treturn this._summaryAckNack!;\n\t}\n}\n\n/**\n * Watches summaries created by a specific client.\n * @legacy\n * @alpha\n */\nexport interface IClientSummaryWatcher extends IDisposable {\n\twatchSummary(clientSequenceNumber: number): ISummary;\n\twaitFlushed(): Promise<IAckedSummary | undefined>;\n}\n\n/**\n * This class watches summaries created by a specific client.\n * It should be created and managed from a SummaryCollection.\n */\nclass ClientSummaryWatcher implements IClientSummaryWatcher {\n\t// key: clientSeqNum\n\tprivate readonly localSummaries = new Map<number, Summary>();\n\tprivate _disposed = false;\n\n\tpublic get disposed() {\n\t\treturn this._disposed;\n\t}\n\n\tpublic constructor(\n\t\tpublic readonly clientId: string,\n\t\tprivate readonly summaryCollection: SummaryCollection,\n\t) {}\n\n\t/**\n\t * Watches for a specific sent summary op.\n\t * @param clientSequenceNumber - client sequence number of sent summary op\n\t */\n\tpublic watchSummary(clientSequenceNumber: number): ISummary {\n\t\tlet summary = this.localSummaries.get(clientSequenceNumber);\n\t\tif (!summary) {\n\t\t\tsummary = Summary.createLocal(this.clientId, clientSequenceNumber);\n\t\t\tthis.localSummaries.set(summary.clientSequenceNumber, summary);\n\t\t}\n\t\treturn summary;\n\t}\n\n\t/**\n\t * Waits until all of the pending summaries in the underlying SummaryCollection\n\t * are acked/nacked.\n\t */\n\t// eslint-disable-next-line @typescript-eslint/promise-function-async\n\tpublic waitFlushed() {\n\t\treturn this.summaryCollection.waitFlushed();\n\t}\n\n\t/**\n\t * Gets a watched summary or returns undefined if not watched.\n\t * @param clientSequenceNumber - client sequence number of sent summary op\n\t */\n\tpublic tryGetSummary(clientSequenceNumber: number) {\n\t\treturn this.localSummaries.get(clientSequenceNumber);\n\t}\n\n\t/**\n\t * Starts watching a summary made by this client.\n\t * @param summary - summary to start watching\n\t */\n\tpublic setSummary(summary: Summary) {\n\t\tthis.localSummaries.set(summary.clientSequenceNumber, summary);\n\t}\n\n\tpublic dispose() {\n\t\tthis.summaryCollection.removeWatcher(this.clientId);\n\t\tthis._disposed = true;\n\t}\n}\n/**\n * @legacy\n * @alpha\n */\nexport type OpActionEventName =\n\t| MessageType.Summarize\n\t| MessageType.SummaryAck\n\t| MessageType.SummaryNack\n\t| \"default\";\n\n/**\n * @legacy\n * @alpha\n */\nexport type OpActionEventListener = (op: ISequencedDocumentMessage) => void;\n\n/**\n * @legacy\n * @alpha\n */\nexport interface ISummaryCollectionOpEvents extends IEvent {\n\t(event: OpActionEventName, listener: OpActionEventListener);\n}\n\n/**\n * Data structure that looks at the op stream to track summaries as they\n * are broadcast, acked and nacked.\n * It provides functionality for watching specific summaries.\n * @legacy\n * @alpha\n */\nexport class SummaryCollection extends TypedEventEmitter<ISummaryCollectionOpEvents> {\n\t// key: clientId\n\tprivate readonly summaryWatchers = new Map<string, ClientSummaryWatcher>();\n\t// key: summarySeqNum\n\tprivate readonly pendingSummaries = new Map<number, Summary>();\n\tprivate refreshWaitNextAck = new Deferred<void>();\n\n\tprivate lastSummaryTimestamp: number | undefined;\n\tprivate maxAckWaitTime: number | undefined;\n\tprivate pendingAckTimerTimeoutCallback: (() => void) | undefined;\n\tprivate lastAck: IAckedSummary | undefined;\n\n\tpublic get latestAck(): IAckedSummary | undefined {\n\t\treturn this.lastAck;\n\t}\n\n\tpublic emit(event: OpActionEventName, ...args: Parameters<OpActionEventListener>): boolean {\n\t\treturn super.emit(event, ...args);\n\t}\n\n\tpublic get opsSinceLastAck() {\n\t\treturn (\n\t\t\tthis.deltaManager.lastSequenceNumber -\n\t\t\t(this.lastAck?.summaryAck.sequenceNumber ?? this.deltaManager.initialSequenceNumber)\n\t\t);\n\t}\n\n\tpublic addOpListener(listener: () => void) {\n\t\tthis.deltaManager.on(\"op\", listener);\n\t}\n\n\tpublic removeOpListener(listener: () => void) {\n\t\tthis.deltaManager.off(\"op\", listener);\n\t}\n\n\tpublic constructor(\n\t\tprivate readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t) {\n\t\tsuper();\n\t\tthis.deltaManager.on(\"op\", (op) => this.handleOp(op));\n\t}\n\n\t/**\n\t * Creates and returns a summary watcher for a specific client.\n\t * This will allow for local sent summaries to be better tracked.\n\t * @param clientId - client id for watcher\n\t */\n\tpublic createWatcher(clientId: string): IClientSummaryWatcher {\n\t\tconst watcher = new ClientSummaryWatcher(clientId, this);\n\t\tthis.summaryWatchers.set(clientId, watcher);\n\t\treturn watcher;\n\t}\n\n\tpublic removeWatcher(clientId: string) {\n\t\tthis.summaryWatchers.delete(clientId);\n\t}\n\n\tpublic setPendingAckTimerTimeoutCallback(\n\t\tmaxAckWaitTime: number,\n\t\ttimeoutCallback: () => void,\n\t) {\n\t\tthis.maxAckWaitTime = maxAckWaitTime;\n\t\tthis.pendingAckTimerTimeoutCallback = timeoutCallback;\n\t}\n\n\tpublic unsetPendingAckTimerTimeoutCallback() {\n\t\tthis.maxAckWaitTime = undefined;\n\t\tthis.pendingAckTimerTimeoutCallback = undefined;\n\t}\n\n\t/**\n\t * Returns a promise that resolves once all pending summary ops\n\t * have been acked or nacked.\n\t */\n\tpublic async waitFlushed(): Promise<IAckedSummary | undefined> {\n\t\twhile (this.pendingSummaries.size > 0) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/promise-function-async\n\t\t\tconst promises = Array.from(this.pendingSummaries, ([, summary]) =>\n\t\t\t\tsummary.waitAckNack(),\n\t\t\t);\n\t\t\tawait Promise.all(promises);\n\t\t}\n\t\treturn this.lastAck;\n\t}\n\n\t/**\n\t * Returns a promise that resolves once a summary is acked that has a reference\n\t * sequence number greater than or equal to the passed in sequence number.\n\t * @param referenceSequenceNumber - reference sequence number to wait for\n\t * @returns The latest acked summary\n\t */\n\tpublic async waitSummaryAck(referenceSequenceNumber: number): Promise<IAckedSummary> {\n\t\twhile (\n\t\t\t!this.lastAck ||\n\t\t\tthis.lastAck.summaryOp.referenceSequenceNumber < referenceSequenceNumber\n\t\t) {\n\t\t\tawait this.refreshWaitNextAck.promise;\n\t\t}\n\t\treturn this.lastAck;\n\t}\n\n\tprivate parseContent(op: ISequencedDocumentMessage) {\n\t\t// This should become unconditional once (Loader LTS) reaches 2.4 or later\n\t\t// There will be a long time of needing both cases, until LTS catches up to the change.\n\t\t// That said, we may instead move to listen for \"op\" events from ContainerRuntime,\n\t\t// and parsing may not be required at all if ContainerRuntime.process() continues to parse it for all types of ops.\n\t\tif (typeof op.contents === \"string\") {\n\t\t\top.contents = JSON.parse(op.contents);\n\t\t}\n\t}\n\n\t/**\n\t * Handler for ops; only handles ops relating to summaries.\n\t * @param op - op message to handle\n\t */\n\tprivate handleOp(opArg: ISequencedDocumentMessage) {\n\t\tconst op = { ...opArg };\n\n\t\tswitch (op.type) {\n\t\t\tcase MessageType.Summarize:\n\t\t\t\tthis.parseContent(op);\n\t\t\t\treturn this.handleSummaryOp(op as ISummaryOpMessage);\n\t\t\tcase MessageType.SummaryAck:\n\t\t\tcase MessageType.SummaryNack:\n\t\t\t\t// Old files (prior to PR #10077) may not contain this info\n\t\t\t\tif (op.data !== undefined) {\n\t\t\t\t\top.contents = JSON.parse(op.data);\n\t\t\t\t} else {\n\t\t\t\t\tthis.parseContent(op);\n\t\t\t\t}\n\t\t\t\treturn op.type === MessageType.SummaryAck\n\t\t\t\t\t? this.handleSummaryAck(op as ISummaryAckMessage)\n\t\t\t\t\t: this.handleSummaryNack(op as ISummaryNackMessage);\n\t\t\tdefault: {\n\t\t\t\t// If the difference between timestamp of current op and last summary op is greater than\n\t\t\t\t// the maxAckWaitTime, then we need to inform summarizer to not wait and summarize\n\t\t\t\t// immediately as we have already waited for maxAckWaitTime.\n\t\t\t\tconst lastOpTimestamp = op.timestamp;\n\t\t\t\tif (\n\t\t\t\t\tthis.lastSummaryTimestamp !== undefined &&\n\t\t\t\t\tthis.maxAckWaitTime !== undefined &&\n\t\t\t\t\tlastOpTimestamp - this.lastSummaryTimestamp >= this.maxAckWaitTime\n\t\t\t\t) {\n\t\t\t\t\tthis.pendingAckTimerTimeoutCallback?.();\n\t\t\t\t}\n\t\t\t\tthis.emit(\"default\", op);\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handleSummaryOp(op: ISummaryOpMessage) {\n\t\tlet summary: Summary | undefined;\n\n\t\t// Check if summary already being watched, broadcast if so\n\t\t// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)\n\t\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n\t\tconst watcher = this.summaryWatchers.get(op.clientId as string);\n\t\tif (watcher) {\n\t\t\tsummary = watcher.tryGetSummary(op.clientSequenceNumber);\n\t\t\tif (summary) {\n\t\t\t\tsummary.broadcast(op);\n\t\t\t}\n\t\t}\n\n\t\t// If not watched, create from op\n\t\tif (!summary) {\n\t\t\tsummary = Summary.createFromOp(op);\n\t\t\tif (watcher) {\n\t\t\t\twatcher.setSummary(summary);\n\t\t\t}\n\t\t}\n\t\tthis.pendingSummaries.set(op.sequenceNumber, summary);\n\t\tthis.lastSummaryTimestamp = op.timestamp;\n\t\tthis.emit(MessageType.Summarize, op);\n\t}\n\n\tprivate handleSummaryAck(op: ISummaryAckMessage) {\n\t\tconst seq = op.contents.summaryProposal.summarySequenceNumber;\n\t\tconst summary = this.pendingSummaries.get(seq);\n\t\t// eslint-disable-next-line @typescript-eslint/prefer-optional-chain -- optional chain is not logically equivalent\n\t\tif (!summary || summary.summaryOp === undefined) {\n\t\t\t// Summary ack without an op should be rare. We could fetch the\n\t\t\t// reference sequence number from the snapshot, but instead we\n\t\t\t// will not emit this ack. It should be the case that the summary\n\t\t\t// op that this ack is for is earlier than this file was loaded\n\t\t\t// from. i.e. initialSequenceNumber > summarySequenceNumber.\n\t\t\t// We really don't care about it for now, since it is older than\n\t\t\t// the one we loaded from.\n\t\t\tif (seq > this.deltaManager.initialSequenceNumber) {\n\t\t\t\t// Potential causes for it to be later than our initialSequenceNumber\n\t\t\t\t// are that the summaryOp was nacked then acked, double-acked, or\n\t\t\t\t// the summarySequenceNumber is incorrect.\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"SummaryAckWithoutOp\",\n\t\t\t\t\tsequenceNumber: op.sequenceNumber, // summary ack seq #\n\t\t\t\t\tsummarySequenceNumber: seq, // missing summary seq #\n\t\t\t\t\tinitialSequenceNumber: this.deltaManager.initialSequenceNumber,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tsummary.ackNack(op);\n\t\tthis.pendingSummaries.delete(seq);\n\n\t\t// Track latest ack\n\t\tif (\n\t\t\t!this.lastAck ||\n\t\t\tseq > this.lastAck.summaryAck.contents.summaryProposal.summarySequenceNumber\n\t\t) {\n\t\t\tthis.lastAck = {\n\t\t\t\tsummaryOp: summary.summaryOp,\n\t\t\t\tsummaryAck: op,\n\t\t\t};\n\t\t\tthis.refreshWaitNextAck.resolve();\n\t\t\tthis.refreshWaitNextAck = new Deferred<void>();\n\t\t\tthis.emit(MessageType.SummaryAck, op);\n\t\t}\n\t}\n\n\tprivate handleSummaryNack(op: ISummaryNackMessage) {\n\t\tconst seq = op.contents.summaryProposal.summarySequenceNumber;\n\t\tconst summary = this.pendingSummaries.get(seq);\n\t\tif (summary) {\n\t\t\tsummary.ackNack(op);\n\t\t\tthis.pendingSummaries.delete(seq);\n\t\t\tthis.emit(MessageType.SummaryNack, op);\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"summaryCollection.js","sourceRoot":"","sources":["../../src/summary/summaryCollection.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAAiE;AAGjE,kEAAuE;AACvE,0EAOqD;AAwDrD,IAAK,YAKJ;AALD,WAAK,YAAY;IAChB,iDAAS,CAAA;IACT,yDAAa,CAAA;IACb,iDAAS,CAAA;IACT,oDAAW,CAAA;AACZ,CAAC,EALI,YAAY,KAAZ,YAAY,QAKhB;AAED,MAAM,OAAO;IACL,MAAM,CAAC,WAAW,CAAC,QAAgB,EAAE,oBAA4B;QACvE,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;IACpD,CAAC;IACM,MAAM,CAAC,YAAY,CAAC,EAAqB;QAC/C,+FAA+F;QAE/F,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,EAAE,CAAC,QAAkB,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC;QAC5E,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACtB,OAAO,OAAO,CAAC;IAChB,CAAC;IAUD,IAAW,SAAS;QACnB,OAAO,IAAI,CAAC,UAAU,CAAC;IACxB,CAAC;IACD,IAAW,cAAc;QACxB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC7B,CAAC;IAED,YACiB,QAAgB,EAChB,oBAA4B;QAD5B,aAAQ,GAAR,QAAQ,CAAQ;QAChB,yBAAoB,GAApB,oBAAoB,CAAQ;QAjBrC,UAAK,GAAG,YAAY,CAAC,KAAK,CAAC;QAKlB,iBAAY,GAAG,IAAI,mBAAQ,EAAQ,CAAC;QACpC,kBAAa,GAAG,IAAI,mBAAQ,EAAQ,CAAC;IAYnD,CAAC;IAEG,YAAY;QAClB,OAAO,IAAI,CAAC,KAAK,KAAK,YAAY,CAAC,KAAK,CAAC;IAC1C,CAAC;IAEM,SAAS,CAAC,EAAqB;QACrC,IAAA,iBAAM,EACL,IAAI,CAAC,KAAK,KAAK,YAAY,CAAC,KAAK,EACjC,KAAK,CAAC,8DAA8D,CACpE,CAAC;QACF,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC,SAAS,CAAC;QACpC,OAAO,IAAI,CAAC;IACb,CAAC;IAEM,OAAO,CAAC,EAA4C;QAC1D,IAAA,iBAAM,EACL,IAAI,CAAC,KAAK,KAAK,YAAY,CAAC,SAAS,EACrC,KAAK,CAAC,gEAAgE,CACtE,CAAC;QACF,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,KAAK,sBAAW,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC;QAC3F,OAAO,IAAI,CAAC;IACb,CAAC;IAEM,KAAK,CAAC,aAAa;QACzB,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC;QAChC,oEAAoE;QACpE,OAAO,IAAI,CAAC,UAAW,CAAC;IACzB,CAAC;IAEM,KAAK,CAAC,WAAW;QACvB,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;QACjC,oEAAoE;QACpE,OAAO,IAAI,CAAC,eAAgB,CAAC;IAC9B,CAAC;CACD;AAYD;;;GAGG;AACH,MAAM,oBAAoB;IAKzB,IAAW,QAAQ;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,YACiB,QAAgB,EACf,iBAAoC;QADrC,aAAQ,GAAR,QAAQ,CAAQ;QACf,sBAAiB,GAAjB,iBAAiB,CAAmB;QAVtD,oBAAoB;QACH,mBAAc,GAAG,IAAI,GAAG,EAAmB,CAAC;QACrD,cAAS,GAAG,KAAK,CAAC;IASvB,CAAC;IAEJ;;;OAGG;IACI,YAAY,CAAC,oBAA4B;QAC/C,IAAI,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAC5D,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;YACnE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,OAAO,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,qEAAqE;IAC9D,WAAW;QACjB,OAAO,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,CAAC;IAC7C,CAAC;IAED;;;OAGG;IACI,aAAa,CAAC,oBAA4B;QAChD,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACtD,CAAC;IAED;;;OAGG;IACI,UAAU,CAAC,OAAgB;QACjC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC;IAEM,OAAO;QACb,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACvB,CAAC;CACD;AAyBD;;;;;;GAMG;AACH,MAAa,iBAAkB,SAAQ,gCAA6C;IAYnF,IAAW,SAAS;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAEM,IAAI,CAAC,KAAwB,EAAE,GAAG,IAAuC;QAC/E,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,IAAW,eAAe;QACzB,OAAO,CACN,IAAI,CAAC,YAAY,CAAC,kBAAkB;YACpC,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,IAAI,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAAC,CACpF,CAAC;IACH,CAAC;IAEM,aAAa,CAAC,QAAoB;QACxC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACtC,CAAC;IAEM,gBAAgB,CAAC,QAAoB;QAC3C,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACvC,CAAC;IAED,YACkB,YAAwE,EACxE,MAA2B;QAE5C,KAAK,EAAE,CAAC;QAHS,iBAAY,GAAZ,YAAY,CAA4D;QACxE,WAAM,GAAN,MAAM,CAAqB;QApC7C,gBAAgB;QACC,oBAAe,GAAG,IAAI,GAAG,EAAgC,CAAC;QAC3E,qBAAqB;QACJ,qBAAgB,GAAG,IAAI,GAAG,EAAmB,CAAC;QACvD,uBAAkB,GAAG,IAAI,mBAAQ,EAAQ,CAAC;QAmCjD,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IACvD,CAAC;IAED;;;;OAIG;IACI,aAAa,CAAC,QAAgB;QACpC,MAAM,OAAO,GAAG,IAAI,oBAAoB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5C,OAAO,OAAO,CAAC;IAChB,CAAC;IAEM,aAAa,CAAC,QAAgB;QACpC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IAEM,iCAAiC,CACvC,cAAsB,EACtB,eAA2B;QAE3B,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,8BAA8B,GAAG,eAAe,CAAC;IACvD,CAAC;IAEM,mCAAmC;QACzC,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAChC,IAAI,CAAC,8BAA8B,GAAG,SAAS,CAAC;IACjD,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,WAAW;QACvB,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACvC,qEAAqE;YACrE,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,CAClE,OAAO,CAAC,WAAW,EAAE,CACrB,CAAC;YACF,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,cAAc,CAAC,uBAA+B;QAC1D,OACC,CAAC,IAAI,CAAC,OAAO;YACb,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,uBAAuB,GAAG,uBAAuB,EACvE,CAAC;YACF,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;QACvC,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAEO,YAAY,CAAC,EAA6B;QACjD,0EAA0E;QAC1E,uFAAuF;QACvF,kFAAkF;QAClF,mHAAmH;QACnH,IAAI,OAAO,EAAE,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACrC,EAAE,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;QACvC,CAAC;IACF,CAAC;IAED;;;OAGG;IACK,QAAQ,CAAC,KAAgC;QAChD,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;QAExB,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,sBAAW,CAAC,SAAS;gBACzB,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;gBACtB,OAAO,IAAI,CAAC,eAAe,CAAC,EAAuB,CAAC,CAAC;YACtD,KAAK,sBAAW,CAAC,UAAU,CAAC;YAC5B,KAAK,sBAAW,CAAC,WAAW;gBAC3B,2DAA2D;gBAC3D,IAAI,EAAE,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;oBAC3B,EAAE,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;gBACnC,CAAC;qBAAM,CAAC;oBACP,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;gBACvB,CAAC;gBACD,OAAO,EAAE,CAAC,IAAI,KAAK,sBAAW,CAAC,UAAU;oBACxC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAwB,CAAC;oBACjD,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAyB,CAAC,CAAC;YACtD,OAAO,CAAC,CAAC,CAAC;gBACT,wFAAwF;gBACxF,kFAAkF;gBAClF,4DAA4D;gBAC5D,MAAM,eAAe,GAAG,EAAE,CAAC,SAAS,CAAC;gBACrC,IACC,IAAI,CAAC,oBAAoB,KAAK,SAAS;oBACvC,IAAI,CAAC,cAAc,KAAK,SAAS;oBACjC,eAAe,GAAG,IAAI,CAAC,oBAAoB,IAAI,IAAI,CAAC,cAAc,EACjE,CAAC;oBACF,IAAI,CAAC,8BAA8B,EAAE,EAAE,CAAC;gBACzC,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;gBAEzB,OAAO;YACR,CAAC;QACF,CAAC;IACF,CAAC;IAEO,eAAe,CAAC,EAAqB;QAC5C,IAAI,OAA4B,CAAC;QAEjC,0DAA0D;QAC1D,+FAA+F;QAE/F,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,QAAkB,CAAC,CAAC;QAChE,IAAI,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC;YACzD,IAAI,OAAO,EAAE,CAAC;gBACb,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YACvB,CAAC;QACF,CAAC;QAED,iCAAiC;QACjC,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YACnC,IAAI,OAAO,EAAE,CAAC;gBACb,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAC7B,CAAC;QACF,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QACtD,IAAI,CAAC,oBAAoB,GAAG,EAAE,CAAC,SAAS,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,sBAAW,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACtC,CAAC;IAEO,gBAAgB,CAAC,EAAsB;QAC9C,MAAM,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,qBAAqB,CAAC;QAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/C,kHAAkH;QAClH,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACjD,+DAA+D;YAC/D,8DAA8D;YAC9D,iEAAiE;YACjE,+DAA+D;YAC/D,4DAA4D;YAC5D,gEAAgE;YAChE,0BAA0B;YAC1B,IAAI,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,qBAAqB,EAAE,CAAC;gBACnD,qEAAqE;gBACrE,iEAAiE;gBACjE,0CAA0C;gBAC1C,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC;oBAC9B,SAAS,EAAE,qBAAqB;oBAChC,cAAc,EAAE,EAAE,CAAC,cAAc,EAAE,oBAAoB;oBACvD,qBAAqB,EAAE,GAAG,EAAE,wBAAwB;oBACpD,qBAAqB,EAAE,IAAI,CAAC,YAAY,CAAC,qBAAqB;iBAC9D,CAAC,CAAC;YACJ,CAAC;YACD,OAAO;QACR,CAAC;QACD,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACpB,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAElC,mBAAmB;QACnB,IACC,CAAC,IAAI,CAAC,OAAO;YACb,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,qBAAqB,EAC3E,CAAC;YACF,IAAI,CAAC,OAAO,GAAG;gBACd,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,UAAU,EAAE,EAAE;aACd,CAAC;YACF,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC,kBAAkB,GAAG,IAAI,mBAAQ,EAAQ,CAAC;YAC/C,IAAI,CAAC,IAAI,CAAC,sBAAW,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACvC,CAAC;IACF,CAAC;IAEO,iBAAiB,CAAC,EAAuB;QAChD,MAAM,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,qBAAqB,CAAC;QAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACpB,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,CAAC,IAAI,CAAC,sBAAW,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACxC,CAAC;IACF,CAAC;CACD;AAvOD,8CAuOC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { IDeltaManager } from \"@fluidframework/container-definitions/internal\";\nimport { IDisposable, IEvent } from \"@fluidframework/core-interfaces\";\nimport { assert, Deferred } from \"@fluidframework/core-utils/internal\";\nimport {\n\tIDocumentMessage,\n\tISummaryAck,\n\tISummaryContent,\n\tISummaryNack,\n\tMessageType,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils/internal\";\n\n/**\n * Interface for summary op messages with typed contents.\n * @legacy\n * @alpha\n */\nexport interface ISummaryOpMessage extends ISequencedDocumentMessage {\n\ttype: MessageType.Summarize;\n\tcontents: ISummaryContent;\n}\n\n/**\n * Interface for summary ack messages with typed contents.\n * @legacy\n * @alpha\n */\nexport interface ISummaryAckMessage extends ISequencedDocumentMessage {\n\ttype: MessageType.SummaryAck;\n\tcontents: ISummaryAck;\n}\n\n/**\n * Interface for summary nack messages with typed contents.\n * @legacy\n * @alpha\n */\nexport interface ISummaryNackMessage extends ISequencedDocumentMessage {\n\ttype: MessageType.SummaryNack;\n\tcontents: ISummaryNack;\n}\n\n/**\n * A single summary which can be tracked as it goes through its life cycle.\n * The life cycle is: Local to Broadcast to Acked/Nacked.\n * @legacy\n * @alpha\n */\nexport interface ISummary {\n\treadonly clientId: string;\n\treadonly clientSequenceNumber: number;\n\twaitBroadcast(): Promise<ISummaryOpMessage>;\n\twaitAckNack(): Promise<ISummaryAckMessage | ISummaryNackMessage>;\n}\n\n/**\n * A single summary which has already been acked by the server.\n * @legacy\n * @alpha\n */\nexport interface IAckedSummary {\n\treadonly summaryOp: ISummaryOpMessage;\n\treadonly summaryAck: ISummaryAckMessage;\n}\n\nenum SummaryState {\n\tLocal = 0,\n\tBroadcast = 1,\n\tAcked = 2,\n\tNacked = -1,\n}\n\nclass Summary implements ISummary {\n\tpublic static createLocal(clientId: string, clientSequenceNumber: number) {\n\t\treturn new Summary(clientId, clientSequenceNumber);\n\t}\n\tpublic static createFromOp(op: ISummaryOpMessage) {\n\t\t// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)\n\n\t\tconst summary = new Summary(op.clientId as string, op.clientSequenceNumber);\n\t\tsummary.broadcast(op);\n\t\treturn summary;\n\t}\n\n\tprivate state = SummaryState.Local;\n\n\tprivate _summaryOp?: ISummaryOpMessage;\n\tprivate _summaryAckNack?: ISummaryAckMessage | ISummaryNackMessage;\n\n\tprivate readonly defSummaryOp = new Deferred<void>();\n\tprivate readonly defSummaryAck = new Deferred<void>();\n\n\tpublic get summaryOp() {\n\t\treturn this._summaryOp;\n\t}\n\tpublic get summaryAckNack() {\n\t\treturn this._summaryAckNack;\n\t}\n\n\tprivate constructor(\n\t\tpublic readonly clientId: string,\n\t\tpublic readonly clientSequenceNumber: number,\n\t) {}\n\n\tpublic hasBeenAcked(): this is IAckedSummary {\n\t\treturn this.state === SummaryState.Acked;\n\t}\n\n\tpublic broadcast(op: ISummaryOpMessage) {\n\t\tassert(\n\t\t\tthis.state === SummaryState.Local,\n\t\t\t0x175 /* \"Can only broadcast if summarizer starts in local state\" */,\n\t\t);\n\t\tthis._summaryOp = op;\n\t\tthis.defSummaryOp.resolve();\n\t\tthis.state = SummaryState.Broadcast;\n\t\treturn true;\n\t}\n\n\tpublic ackNack(op: ISummaryAckMessage | ISummaryNackMessage) {\n\t\tassert(\n\t\t\tthis.state === SummaryState.Broadcast,\n\t\t\t0x176 /* \"Can only ack/nack if summarizer is in broadcasting state\" */,\n\t\t);\n\t\tthis._summaryAckNack = op;\n\t\tthis.defSummaryAck.resolve();\n\t\tthis.state = op.type === MessageType.SummaryAck ? SummaryState.Acked : SummaryState.Nacked;\n\t\treturn true;\n\t}\n\n\tpublic async waitBroadcast(): Promise<ISummaryOpMessage> {\n\t\tawait this.defSummaryOp.promise;\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\treturn this._summaryOp!;\n\t}\n\n\tpublic async waitAckNack(): Promise<ISummaryAckMessage | ISummaryNackMessage> {\n\t\tawait this.defSummaryAck.promise;\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\treturn this._summaryAckNack!;\n\t}\n}\n\n/**\n * Watches summaries created by a specific client.\n * @legacy\n * @alpha\n */\nexport interface IClientSummaryWatcher extends IDisposable {\n\twatchSummary(clientSequenceNumber: number): ISummary;\n\twaitFlushed(): Promise<IAckedSummary | undefined>;\n}\n\n/**\n * This class watches summaries created by a specific client.\n * It should be created and managed from a SummaryCollection.\n */\nclass ClientSummaryWatcher implements IClientSummaryWatcher {\n\t// key: clientSeqNum\n\tprivate readonly localSummaries = new Map<number, Summary>();\n\tprivate _disposed = false;\n\n\tpublic get disposed() {\n\t\treturn this._disposed;\n\t}\n\n\tpublic constructor(\n\t\tpublic readonly clientId: string,\n\t\tprivate readonly summaryCollection: SummaryCollection,\n\t) {}\n\n\t/**\n\t * Watches for a specific sent summary op.\n\t * @param clientSequenceNumber - client sequence number of sent summary op\n\t */\n\tpublic watchSummary(clientSequenceNumber: number): ISummary {\n\t\tlet summary = this.localSummaries.get(clientSequenceNumber);\n\t\tif (!summary) {\n\t\t\tsummary = Summary.createLocal(this.clientId, clientSequenceNumber);\n\t\t\tthis.localSummaries.set(summary.clientSequenceNumber, summary);\n\t\t}\n\t\treturn summary;\n\t}\n\n\t/**\n\t * Waits until all of the pending summaries in the underlying SummaryCollection\n\t * are acked/nacked.\n\t */\n\t// eslint-disable-next-line @typescript-eslint/promise-function-async\n\tpublic waitFlushed() {\n\t\treturn this.summaryCollection.waitFlushed();\n\t}\n\n\t/**\n\t * Gets a watched summary or returns undefined if not watched.\n\t * @param clientSequenceNumber - client sequence number of sent summary op\n\t */\n\tpublic tryGetSummary(clientSequenceNumber: number) {\n\t\treturn this.localSummaries.get(clientSequenceNumber);\n\t}\n\n\t/**\n\t * Starts watching a summary made by this client.\n\t * @param summary - summary to start watching\n\t */\n\tpublic setSummary(summary: Summary) {\n\t\tthis.localSummaries.set(summary.clientSequenceNumber, summary);\n\t}\n\n\tpublic dispose() {\n\t\tthis.summaryCollection.removeWatcher(this.clientId);\n\t\tthis._disposed = true;\n\t}\n}\n/**\n * @legacy\n * @alpha\n */\nexport type OpActionEventName =\n\t| MessageType.Summarize\n\t| MessageType.SummaryAck\n\t| MessageType.SummaryNack\n\t| \"default\";\n\n/**\n * @legacy\n * @alpha\n */\nexport type OpActionEventListener = (op: ISequencedDocumentMessage) => void;\n\n/**\n * @legacy\n * @alpha\n */\nexport interface ISummaryCollectionOpEvents extends IEvent {\n\t(event: OpActionEventName, listener: OpActionEventListener);\n}\n\n/**\n * Data structure that looks at the op stream to track summaries as they\n * are broadcast, acked and nacked.\n * It provides functionality for watching specific summaries.\n * @legacy\n * @alpha\n */\nexport class SummaryCollection extends TypedEventEmitter<ISummaryCollectionOpEvents> {\n\t// key: clientId\n\tprivate readonly summaryWatchers = new Map<string, ClientSummaryWatcher>();\n\t// key: summarySeqNum\n\tprivate readonly pendingSummaries = new Map<number, Summary>();\n\tprivate refreshWaitNextAck = new Deferred<void>();\n\n\tprivate lastSummaryTimestamp: number | undefined;\n\tprivate maxAckWaitTime: number | undefined;\n\tprivate pendingAckTimerTimeoutCallback: (() => void) | undefined;\n\tprivate lastAck: IAckedSummary | undefined;\n\n\tpublic get latestAck(): IAckedSummary | undefined {\n\t\treturn this.lastAck;\n\t}\n\n\tpublic emit(event: OpActionEventName, ...args: Parameters<OpActionEventListener>): boolean {\n\t\treturn super.emit(event, ...args);\n\t}\n\n\tpublic get opsSinceLastAck() {\n\t\treturn (\n\t\t\tthis.deltaManager.lastSequenceNumber -\n\t\t\t(this.lastAck?.summaryAck.sequenceNumber ?? this.deltaManager.initialSequenceNumber)\n\t\t);\n\t}\n\n\tpublic addOpListener(listener: () => void) {\n\t\tthis.deltaManager.on(\"op\", listener);\n\t}\n\n\tpublic removeOpListener(listener: () => void) {\n\t\tthis.deltaManager.off(\"op\", listener);\n\t}\n\n\tpublic constructor(\n\t\tprivate readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t) {\n\t\tsuper();\n\t\tthis.deltaManager.on(\"op\", (op) => this.handleOp(op));\n\t}\n\n\t/**\n\t * Creates and returns a summary watcher for a specific client.\n\t * This will allow for local sent summaries to be better tracked.\n\t * @param clientId - client id for watcher\n\t */\n\tpublic createWatcher(clientId: string): IClientSummaryWatcher {\n\t\tconst watcher = new ClientSummaryWatcher(clientId, this);\n\t\tthis.summaryWatchers.set(clientId, watcher);\n\t\treturn watcher;\n\t}\n\n\tpublic removeWatcher(clientId: string) {\n\t\tthis.summaryWatchers.delete(clientId);\n\t}\n\n\tpublic setPendingAckTimerTimeoutCallback(\n\t\tmaxAckWaitTime: number,\n\t\ttimeoutCallback: () => void,\n\t) {\n\t\tthis.maxAckWaitTime = maxAckWaitTime;\n\t\tthis.pendingAckTimerTimeoutCallback = timeoutCallback;\n\t}\n\n\tpublic unsetPendingAckTimerTimeoutCallback() {\n\t\tthis.maxAckWaitTime = undefined;\n\t\tthis.pendingAckTimerTimeoutCallback = undefined;\n\t}\n\n\t/**\n\t * Returns a promise that resolves once all pending summary ops\n\t * have been acked or nacked.\n\t */\n\tpublic async waitFlushed(): Promise<IAckedSummary | undefined> {\n\t\twhile (this.pendingSummaries.size > 0) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/promise-function-async\n\t\t\tconst promises = Array.from(this.pendingSummaries, ([, summary]) =>\n\t\t\t\tsummary.waitAckNack(),\n\t\t\t);\n\t\t\tawait Promise.all(promises);\n\t\t}\n\t\treturn this.lastAck;\n\t}\n\n\t/**\n\t * Returns a promise that resolves once a summary is acked that has a reference\n\t * sequence number greater than or equal to the passed in sequence number.\n\t * @param referenceSequenceNumber - reference sequence number to wait for\n\t * @returns The latest acked summary\n\t */\n\tpublic async waitSummaryAck(referenceSequenceNumber: number): Promise<IAckedSummary> {\n\t\twhile (\n\t\t\t!this.lastAck ||\n\t\t\tthis.lastAck.summaryOp.referenceSequenceNumber < referenceSequenceNumber\n\t\t) {\n\t\t\tawait this.refreshWaitNextAck.promise;\n\t\t}\n\t\treturn this.lastAck;\n\t}\n\n\tprivate parseContent(op: ISequencedDocumentMessage) {\n\t\t// This should become unconditional once (Loader LTS) reaches 2.4 or later\n\t\t// There will be a long time of needing both cases, until LTS catches up to the change.\n\t\t// That said, we may instead move to listen for \"op\" events from ContainerRuntime,\n\t\t// and parsing may not be required at all if ContainerRuntime.process() continues to parse it for all types of ops.\n\t\tif (typeof op.contents === \"string\") {\n\t\t\top.contents = JSON.parse(op.contents);\n\t\t}\n\t}\n\n\t/**\n\t * Handler for ops; only handles ops relating to summaries.\n\t * @param op - op message to handle\n\t */\n\tprivate handleOp(opArg: ISequencedDocumentMessage) {\n\t\tconst op = { ...opArg };\n\n\t\tswitch (op.type) {\n\t\t\tcase MessageType.Summarize:\n\t\t\t\tthis.parseContent(op);\n\t\t\t\treturn this.handleSummaryOp(op as ISummaryOpMessage);\n\t\t\tcase MessageType.SummaryAck:\n\t\t\tcase MessageType.SummaryNack:\n\t\t\t\t// Old files (prior to PR #10077) may not contain this info\n\t\t\t\tif (op.data !== undefined) {\n\t\t\t\t\top.contents = JSON.parse(op.data);\n\t\t\t\t} else {\n\t\t\t\t\tthis.parseContent(op);\n\t\t\t\t}\n\t\t\t\treturn op.type === MessageType.SummaryAck\n\t\t\t\t\t? this.handleSummaryAck(op as ISummaryAckMessage)\n\t\t\t\t\t: this.handleSummaryNack(op as ISummaryNackMessage);\n\t\t\tdefault: {\n\t\t\t\t// If the difference between timestamp of current op and last summary op is greater than\n\t\t\t\t// the maxAckWaitTime, then we need to inform summarizer to not wait and summarize\n\t\t\t\t// immediately as we have already waited for maxAckWaitTime.\n\t\t\t\tconst lastOpTimestamp = op.timestamp;\n\t\t\t\tif (\n\t\t\t\t\tthis.lastSummaryTimestamp !== undefined &&\n\t\t\t\t\tthis.maxAckWaitTime !== undefined &&\n\t\t\t\t\tlastOpTimestamp - this.lastSummaryTimestamp >= this.maxAckWaitTime\n\t\t\t\t) {\n\t\t\t\t\tthis.pendingAckTimerTimeoutCallback?.();\n\t\t\t\t}\n\t\t\t\tthis.emit(\"default\", op);\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handleSummaryOp(op: ISummaryOpMessage) {\n\t\tlet summary: Summary | undefined;\n\n\t\t// Check if summary already being watched, broadcast if so\n\t\t// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)\n\n\t\tconst watcher = this.summaryWatchers.get(op.clientId as string);\n\t\tif (watcher) {\n\t\t\tsummary = watcher.tryGetSummary(op.clientSequenceNumber);\n\t\t\tif (summary) {\n\t\t\t\tsummary.broadcast(op);\n\t\t\t}\n\t\t}\n\n\t\t// If not watched, create from op\n\t\tif (!summary) {\n\t\t\tsummary = Summary.createFromOp(op);\n\t\t\tif (watcher) {\n\t\t\t\twatcher.setSummary(summary);\n\t\t\t}\n\t\t}\n\t\tthis.pendingSummaries.set(op.sequenceNumber, summary);\n\t\tthis.lastSummaryTimestamp = op.timestamp;\n\t\tthis.emit(MessageType.Summarize, op);\n\t}\n\n\tprivate handleSummaryAck(op: ISummaryAckMessage) {\n\t\tconst seq = op.contents.summaryProposal.summarySequenceNumber;\n\t\tconst summary = this.pendingSummaries.get(seq);\n\t\t// eslint-disable-next-line @typescript-eslint/prefer-optional-chain -- optional chain is not logically equivalent\n\t\tif (!summary || summary.summaryOp === undefined) {\n\t\t\t// Summary ack without an op should be rare. We could fetch the\n\t\t\t// reference sequence number from the snapshot, but instead we\n\t\t\t// will not emit this ack. It should be the case that the summary\n\t\t\t// op that this ack is for is earlier than this file was loaded\n\t\t\t// from. i.e. initialSequenceNumber > summarySequenceNumber.\n\t\t\t// We really don't care about it for now, since it is older than\n\t\t\t// the one we loaded from.\n\t\t\tif (seq > this.deltaManager.initialSequenceNumber) {\n\t\t\t\t// Potential causes for it to be later than our initialSequenceNumber\n\t\t\t\t// are that the summaryOp was nacked then acked, double-acked, or\n\t\t\t\t// the summarySequenceNumber is incorrect.\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"SummaryAckWithoutOp\",\n\t\t\t\t\tsequenceNumber: op.sequenceNumber, // summary ack seq #\n\t\t\t\t\tsummarySequenceNumber: seq, // missing summary seq #\n\t\t\t\t\tinitialSequenceNumber: this.deltaManager.initialSequenceNumber,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tsummary.ackNack(op);\n\t\tthis.pendingSummaries.delete(seq);\n\n\t\t// Track latest ack\n\t\tif (\n\t\t\t!this.lastAck ||\n\t\t\tseq > this.lastAck.summaryAck.contents.summaryProposal.summarySequenceNumber\n\t\t) {\n\t\t\tthis.lastAck = {\n\t\t\t\tsummaryOp: summary.summaryOp,\n\t\t\t\tsummaryAck: op,\n\t\t\t};\n\t\t\tthis.refreshWaitNextAck.resolve();\n\t\t\tthis.refreshWaitNextAck = new Deferred<void>();\n\t\t\tthis.emit(MessageType.SummaryAck, op);\n\t\t}\n\t}\n\n\tprivate handleSummaryNack(op: ISummaryNackMessage) {\n\t\tconst seq = op.contents.summaryProposal.summarySequenceNumber;\n\t\tconst summary = this.pendingSummaries.get(seq);\n\t\tif (summary) {\n\t\t\tsummary.ackNack(op);\n\t\t\tthis.pendingSummaries.delete(seq);\n\t\t\tthis.emit(MessageType.SummaryNack, op);\n\t\t}\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"blobManagerSnapSum.js","sourceRoot":"","sources":["../../src/blobManager/blobManagerSnapSum.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,WAAW,GAEX,MAAM,gDAAgD,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAErE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAa5E,MAAM,CAAC,MAAM,qBAAqB,GAAG,gBAAgB,CAAC;AAEtD;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAEtC;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAC3C,OAA4E,EAC5C,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAEpD,MAAM,MAAM,GAAG,KAAK,EACnB,OAA4E,EAC5C,EAAE;IAClC,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAE7D,IAAI,CAAC,SAAS,EAAE,CAAC;QAChB,OAAO,EAAE,CAAC;IACX,CAAC;IACD,IAAI,oBAAoB,GAAuB,EAAE,CAAC;IAClD,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACvD,IAAI,OAAO,EAAE,CAAC;QACb,oBAAoB,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC;SACzC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,qBAAqB,CAAC;SAC/C,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAErB,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,oBAAoB,EAAE,CAAC;AACrD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAC9B,QAA8B,EAC9B,MAA2B,EAC3B,WAAwB,EACU,EAAE;IACpC,MAAM,CAAC,kBAAkB,CAAC;QACzB,SAAS,EAAE,uBAAuB;QAClC,KAAK,EAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,IAAI,CAAC;QAChC,aAAa,EAAE,QAAQ,CAAC,aAAa,EAAE,MAAM;KAC7C,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,IAAI,GAAG,CAA6B,QAAQ,CAAC,aAAa,CAAC,CAAC;IAClF,MAAM,QAAQ,GAAG,WAAW,KAAK,WAAW,CAAC,QAAQ,CAAC;IACtD,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC;QAClB,yEAAyE;QACzE,8CAA8C;QAC9C,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,aAAa,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACxC,aAA8C,EAC9C,WAAwB,EACA,EAAE,CAAC,WAAW,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;AAEpE,MAAM,WAAW,GAAG,CACnB,aAA8C,EAC9C,WAAwB,EACA,EAAE;IAC1B,MAAM,UAAU,GAAG,aAAa,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IAE7D,gHAAgH;IAChH,MAAM,OAAO,GACZ,UAAU,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC;IACjF,MAAM,OAAO,GAAG,IAAI,kBAAkB,EAAE,CAAC;IACzC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QAC1B,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,wEAAwE;IACxE,IAAI,aAAa,CAAC,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QACzC,OAAO,CAAC,OAAO,CACd,qBAAqB;QACrB,8BAA8B;QAC9B,IAAI,CAAC,SAAS,CACb,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CACzC,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,OAAO,KAAK,SAAS,CAC/C,CACD,CACD,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC,cAAc,EAAE,CAAC;AACjC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAC5B,aAA8C,EAC9C,WAAwB,EACvB,EAAE;IACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAqB,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;IAEhE,mEAAmE;IACnE,MAAM,qBAAqB,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAEpD,uGAAuG;IACvG,oGAAoG;IACpG,MAAM,CACL,CAAC,qBAAqB,IAAI,CAAC,WAAW,KAAK,WAAW,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,EAClF,KAAK,CAAC,gGAAgG,CACtG,CAAC;IAEF,OAAO,GAAkB,CAAC;AAC3B,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tAttachState,\n\ttype IContainerContext,\n} from \"@fluidframework/container-definitions/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { readAndParse } from \"@fluidframework/driver-utils/internal\";\nimport type { ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions/internal\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils/internal\";\nimport type { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils/internal\";\n\n/**\n * Information from a snapshot needed to load BlobManager\n * @legacy\n * @alpha\n */\nexport interface IBlobManagerLoadInfo {\n\tids?: string[];\n\tredirectTable?: [string, string][];\n}\n\nexport const redirectTableBlobName = \".redirectTable\";\n\n/**\n * @internal\n */\nexport const blobsTreeName = \".blobs\";\n\n/**\n * Reads blobs needed to load BlobManager from storage.\n *\n */\nexport const loadBlobManagerLoadInfo = async (\n\tcontext: Pick<IContainerContext, \"baseSnapshot\" | \"storage\" | \"attachState\">,\n): Promise<IBlobManagerLoadInfo> => loadV1(context);\n\nconst loadV1 = async (\n\tcontext: Pick<IContainerContext, \"baseSnapshot\" | \"storage\" | \"attachState\">,\n): Promise<IBlobManagerLoadInfo> => {\n\tconst blobsTree = context.baseSnapshot?.trees[blobsTreeName];\n\n\tif (!blobsTree) {\n\t\treturn {};\n\t}\n\tlet redirectTableEntries: [string, string][] = [];\n\tconst tableId = blobsTree.blobs[redirectTableBlobName];\n\tif (tableId) {\n\t\tredirectTableEntries = await readAndParse(context.storage, tableId);\n\t}\n\tconst ids = Object.entries(blobsTree.blobs)\n\t\t.filter(([k, _]) => k !== redirectTableBlobName)\n\t\t.map(([_, v]) => v);\n\n\treturn { ids, redirectTable: redirectTableEntries };\n};\n\nexport const toRedirectTable = (\n\tsnapshot: IBlobManagerLoadInfo,\n\tlogger: ITelemetryLoggerExt,\n\tattachState: AttachState,\n): Map<string, string | undefined> => {\n\tlogger.sendTelemetryEvent({\n\t\teventName: \"AttachmentBlobsLoaded\",\n\t\tcount: snapshot.ids?.length ?? 0,\n\t\tredirectTable: snapshot.redirectTable?.length,\n\t});\n\tconst redirectTable = new Map<string, string | undefined>(snapshot.redirectTable);\n\tconst detached = attachState !== AttachState.Attached;\n\tif (snapshot.ids) {\n\t\t// If we are detached, we don't have storage IDs yet, so set to undefined\n\t\t// Otherwise, set identity (id -> id) entries.\n\t\tsnapshot.ids.forEach((entry) => redirectTable.set(entry, detached ? undefined : entry));\n\t}\n\treturn redirectTable;\n};\n\nexport const summarizeBlobManagerState = (\n\tredirectTable: Map<string, string | undefined>,\n\tattachState: AttachState,\n): ISummaryTreeWithStats => summarizeV1(redirectTable, attachState);\n\nconst summarizeV1 = (\n\tredirectTable: Map<string, string | undefined>,\n\tattachState: AttachState,\n): ISummaryTreeWithStats => {\n\tconst storageIds = getStorageIds(redirectTable, attachState);\n\n\t// if storageIds is empty, it means we are detached and have only local IDs, or that there are no blobs attached\n\tconst blobIds =\n\t\tstorageIds.size > 0 ? Array.from(storageIds) : Array.from(redirectTable.keys());\n\tconst builder = new SummaryTreeBuilder();\n\tblobIds.forEach((blobId) => {\n\t\tbuilder.addAttachment(blobId);\n\t});\n\n\t// Any non-identity entries in the table need to be saved in the summary\n\tif (redirectTable.size > blobIds.length) {\n\t\tbuilder.addBlob(\n\t\t\tredirectTableBlobName,\n\t\t\t// filter out identity entries\n\t\t\tJSON.stringify(\n\t\t\t\tArray.from(redirectTable.entries()).filter(\n\t\t\t\t\t([localId, storageId]) => localId !== storageId,\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t}\n\n\treturn builder.getSummaryTree();\n};\n\nexport const getStorageIds = (\n\tredirectTable: Map<string, string | undefined>,\n\tattachState: AttachState,\n) => {\n\tconst ids = new Set<string | undefined>(redirectTable.values());\n\n\t// If we are detached, we will not have storage IDs, only undefined\n\tconst undefinedValueInTable = ids.delete(undefined);\n\n\t// For a detached container, entries are inserted into the redirect table with an undefined storage ID.\n\t// For an attached container, entries are inserted w/storage ID after the BlobAttach op round-trips.\n\tassert(\n\t\t!undefinedValueInTable || (attachState === AttachState.Detached && ids.size === 0),\n\t\t0x382 /* 'redirectTable' must contain only undefined while detached / defined values while attached */,\n\t);\n\n\treturn ids as Set<string>;\n};\n"]}
1
+ {"version":3,"file":"blobManagerSnapSum.js","sourceRoot":"","sources":["../../src/blobManager/blobManagerSnapSum.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\tAttachState,\n\ttype IContainerContext,\n} from \"@fluidframework/container-definitions/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { readAndParse } from \"@fluidframework/driver-utils/internal\";\nimport type { ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions/internal\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils/internal\";\nimport type { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils/internal\";\n\n/**\n * Information from a snapshot needed to load BlobManager\n * @legacy\n * @alpha\n */\nexport interface IBlobManagerLoadInfo {\n\tids?: string[];\n\tredirectTable?: [string, string][];\n}\n\nexport const redirectTableBlobName = \".redirectTable\";\n\n/**\n * @internal\n */\nexport const blobsTreeName = \".blobs\";\n\n/**\n * Reads blobs needed to load BlobManager from storage.\n *\n */\nexport const loadBlobManagerLoadInfo = async (\n\tcontext: Pick<IContainerContext, \"baseSnapshot\" | \"storage\" | \"attachState\">,\n): Promise<IBlobManagerLoadInfo> => loadV1(context);\n\nconst loadV1 = async (\n\tcontext: Pick<IContainerContext, \"baseSnapshot\" | \"storage\" | \"attachState\">,\n): Promise<IBlobManagerLoadInfo> => {\n\tconst blobsTree = context.baseSnapshot?.trees[blobsTreeName];\n\n\tif (!blobsTree) {\n\t\treturn {};\n\t}\n\tlet redirectTableEntries: [string, string][] = [];\n\tconst tableId: string | undefined = blobsTree.blobs[redirectTableBlobName];\n\tif (tableId) {\n\t\tredirectTableEntries = await readAndParse(context.storage, tableId);\n\t}\n\tconst ids = Object.entries(blobsTree.blobs)\n\t\t.filter(([k, _]) => k !== redirectTableBlobName)\n\t\t.map(([_, v]) => v);\n\n\treturn { ids, redirectTable: redirectTableEntries };\n};\n\nexport const toRedirectTable = (\n\tsnapshot: IBlobManagerLoadInfo,\n\tlogger: ITelemetryLoggerExt,\n\tattachState: AttachState,\n): Map<string, string | undefined> => {\n\tlogger.sendTelemetryEvent({\n\t\teventName: \"AttachmentBlobsLoaded\",\n\t\tcount: snapshot.ids?.length ?? 0,\n\t\tredirectTable: snapshot.redirectTable?.length,\n\t});\n\tconst redirectTable = new Map<string, string | undefined>(snapshot.redirectTable);\n\tconst detached = attachState !== AttachState.Attached;\n\tif (snapshot.ids) {\n\t\t// If we are detached, we don't have storage IDs yet, so set to undefined\n\t\t// Otherwise, set identity (id -> id) entries.\n\t\tsnapshot.ids.forEach((entry) => redirectTable.set(entry, detached ? undefined : entry));\n\t}\n\treturn redirectTable;\n};\n\nexport const summarizeBlobManagerState = (\n\tredirectTable: Map<string, string | undefined>,\n\tattachState: AttachState,\n): ISummaryTreeWithStats => summarizeV1(redirectTable, attachState);\n\nconst summarizeV1 = (\n\tredirectTable: Map<string, string | undefined>,\n\tattachState: AttachState,\n): ISummaryTreeWithStats => {\n\tconst storageIds = getStorageIds(redirectTable, attachState);\n\n\t// if storageIds is empty, it means we are detached and have only local IDs, or that there are no blobs attached\n\tconst blobIds =\n\t\tstorageIds.size > 0 ? Array.from(storageIds) : Array.from(redirectTable.keys());\n\tconst builder = new SummaryTreeBuilder();\n\tblobIds.forEach((blobId) => {\n\t\tbuilder.addAttachment(blobId);\n\t});\n\n\t// Any non-identity entries in the table need to be saved in the summary\n\tif (redirectTable.size > blobIds.length) {\n\t\tbuilder.addBlob(\n\t\t\tredirectTableBlobName,\n\t\t\t// filter out identity entries\n\t\t\tJSON.stringify(\n\t\t\t\tArray.from(redirectTable.entries()).filter(\n\t\t\t\t\t([localId, storageId]) => localId !== storageId,\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t}\n\n\treturn builder.getSummaryTree();\n};\n\nexport const getStorageIds = (\n\tredirectTable: Map<string, string | undefined>,\n\tattachState: AttachState,\n) => {\n\tconst ids = new Set<string | undefined>(redirectTable.values());\n\n\t// If we are detached, we will not have storage IDs, only undefined\n\tconst undefinedValueInTable = ids.delete(undefined);\n\n\t// For a detached container, entries are inserted into the redirect table with an undefined storage ID.\n\t// For an attached container, entries are inserted w/storage ID after the BlobAttach op round-trips.\n\tassert(\n\t\t!undefinedValueInTable || (attachState === AttachState.Detached && ids.size === 0),\n\t\t0x382 /* 'redirectTable' must contain only undefined while detached / defined values while attached */,\n\t);\n\n\treturn ids as Set<string>;\n};\n"]}