@fluidframework/container-runtime 2.0.0-internal.2.3.1 → 2.0.0-internal.3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/blobManager.d.ts +3 -1
  2. package/dist/blobManager.d.ts.map +1 -1
  3. package/dist/blobManager.js +35 -2
  4. package/dist/blobManager.js.map +1 -1
  5. package/dist/containerRuntime.d.ts +45 -42
  6. package/dist/containerRuntime.d.ts.map +1 -1
  7. package/dist/containerRuntime.js +89 -40
  8. package/dist/containerRuntime.js.map +1 -1
  9. package/dist/dataStoreContext.d.ts +1 -0
  10. package/dist/dataStoreContext.d.ts.map +1 -1
  11. package/dist/dataStoreContext.js +7 -2
  12. package/dist/dataStoreContext.js.map +1 -1
  13. package/dist/garbageCollection.d.ts +15 -7
  14. package/dist/garbageCollection.d.ts.map +1 -1
  15. package/dist/garbageCollection.js +96 -36
  16. package/dist/garbageCollection.js.map +1 -1
  17. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  18. package/dist/opLifecycle/outbox.js +0 -1
  19. package/dist/opLifecycle/outbox.js.map +1 -1
  20. package/dist/packageVersion.d.ts +1 -1
  21. package/dist/packageVersion.js +1 -1
  22. package/dist/packageVersion.js.map +1 -1
  23. package/dist/pendingStateManager.d.ts +4 -13
  24. package/dist/pendingStateManager.d.ts.map +1 -1
  25. package/dist/pendingStateManager.js +130 -160
  26. package/dist/pendingStateManager.js.map +1 -1
  27. package/dist/summarizer.js.map +1 -1
  28. package/dist/summarizerClientElection.d.ts +1 -2
  29. package/dist/summarizerClientElection.d.ts.map +1 -1
  30. package/dist/summarizerClientElection.js +3 -30
  31. package/dist/summarizerClientElection.js.map +1 -1
  32. package/dist/summarizerTypes.d.ts +0 -4
  33. package/dist/summarizerTypes.d.ts.map +1 -1
  34. package/dist/summarizerTypes.js.map +1 -1
  35. package/lib/blobManager.d.ts +3 -1
  36. package/lib/blobManager.d.ts.map +1 -1
  37. package/lib/blobManager.js +35 -2
  38. package/lib/blobManager.js.map +1 -1
  39. package/lib/containerRuntime.d.ts +45 -42
  40. package/lib/containerRuntime.d.ts.map +1 -1
  41. package/lib/containerRuntime.js +89 -40
  42. package/lib/containerRuntime.js.map +1 -1
  43. package/lib/dataStoreContext.d.ts +1 -0
  44. package/lib/dataStoreContext.d.ts.map +1 -1
  45. package/lib/dataStoreContext.js +7 -2
  46. package/lib/dataStoreContext.js.map +1 -1
  47. package/lib/garbageCollection.d.ts +15 -7
  48. package/lib/garbageCollection.d.ts.map +1 -1
  49. package/lib/garbageCollection.js +97 -37
  50. package/lib/garbageCollection.js.map +1 -1
  51. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  52. package/lib/opLifecycle/outbox.js +0 -1
  53. package/lib/opLifecycle/outbox.js.map +1 -1
  54. package/lib/packageVersion.d.ts +1 -1
  55. package/lib/packageVersion.js +1 -1
  56. package/lib/packageVersion.js.map +1 -1
  57. package/lib/pendingStateManager.d.ts +4 -13
  58. package/lib/pendingStateManager.d.ts.map +1 -1
  59. package/lib/pendingStateManager.js +130 -160
  60. package/lib/pendingStateManager.js.map +1 -1
  61. package/lib/summarizer.js.map +1 -1
  62. package/lib/summarizerClientElection.d.ts +1 -2
  63. package/lib/summarizerClientElection.d.ts.map +1 -1
  64. package/lib/summarizerClientElection.js +3 -30
  65. package/lib/summarizerClientElection.js.map +1 -1
  66. package/lib/summarizerTypes.d.ts +0 -4
  67. package/lib/summarizerTypes.d.ts.map +1 -1
  68. package/lib/summarizerTypes.js.map +1 -1
  69. package/package.json +55 -20
  70. package/src/blobManager.ts +41 -2
  71. package/src/containerRuntime.ts +118 -85
  72. package/src/dataStoreContext.ts +12 -6
  73. package/src/garbageCollection.ts +103 -34
  74. package/src/opLifecycle/outbox.ts +0 -2
  75. package/src/packageVersion.ts +1 -1
  76. package/src/pendingStateManager.ts +146 -187
  77. package/src/summarizer.ts +1 -1
  78. package/src/summarizerClientElection.ts +1 -30
  79. package/src/summarizerTypes.ts +0 -4
@@ -1 +1 @@
1
- {"version":3,"file":"pendingStateManager.js","sourceRoot":"","sources":["../src/pendingStateManager.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 { IDisposable } from \"@fluidframework/common-definitions\";\nimport { assert, Lazy } from \"@fluidframework/common-utils\";\nimport { ICriticalContainerError } from \"@fluidframework/container-definitions\";\nimport { DataProcessingError } from \"@fluidframework/container-utils\";\nimport {\n ISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport Deque from \"double-ended-queue\";\nimport { ContainerMessageType } from \"./containerRuntime\";\nimport { pkgVersion } from \"./packageVersion\";\n\n/**\n * This represents a message that has been submitted and is added to the pending queue when `submit` is called on the\n * ContainerRuntime. This message has either not been ack'd by the server or has not been submitted to the server yet.\n */\nexport interface IPendingMessage {\n type: \"message\";\n messageType: ContainerMessageType;\n clientSequenceNumber: number;\n referenceSequenceNumber: number;\n content: any;\n localOpMetadata: unknown;\n opMetadata: Record<string, unknown> | undefined;\n}\n\n/**\n * This represents an explicit flush call and is added to the pending queue when flush is called on the ContainerRuntime\n * to flush pending messages.\n */\nexport interface IPendingFlush {\n type: \"flush\";\n}\n\nexport type IPendingState = IPendingMessage | IPendingFlush;\n\nexport interface IPendingLocalState {\n /**\n * list of pending states, including ops and batch information\n */\n pendingStates: IPendingState[];\n}\n\nexport interface IRuntimeStateHandler{\n connected(): boolean;\n clientId(): string | undefined;\n close(error?: ICriticalContainerError): void;\n applyStashedOp: (type: ContainerMessageType, content: ISequencedDocumentMessage) => Promise<unknown>;\n flush(): void;\n reSubmit(\n type: ContainerMessageType,\n content: any,\n localOpMetadata: unknown,\n opMetadata: Record<string, unknown> | undefined): void;\n rollback(\n type: ContainerMessageType,\n content: any,\n localOpMetadata: unknown): void;\n orderSequentially(callback: () => void): void;\n}\n\n/**\n * PendingStateManager is responsible for maintaining the messages that have not been sent or have not yet been\n * acknowledged by the server. It also maintains the batch information for both automatically and manually flushed\n * batches along with the messages.\n * When the Container reconnects, it replays the pending states, which includes manual flushing\n * of messages and triggering resubmission of unacked ops.\n *\n * It verifies that all the ops are acked, are received in the right order and batch information is correct.\n */\nexport class PendingStateManager implements IDisposable {\n private readonly pendingStates = new Deque<IPendingState>();\n private readonly initialStates: Deque<IPendingState>;\n private readonly disposeOnce = new Lazy<void>(() => {\n this.initialStates.clear();\n this.pendingStates.clear();\n });\n\n // Maintains the count of messages that are currently unacked.\n private _pendingMessagesCount: number = 0;\n public get pendingMessagesCount(): number {\n return this._pendingMessagesCount;\n }\n\n // Indicates whether we are processing a batch.\n private isProcessingBatch: boolean = false;\n\n // This stores the first message in the batch that we are processing. This is used to verify that we get\n // the correct batch metadata.\n private pendingBatchBeginMessage: ISequencedDocumentMessage | undefined;\n\n private clientId: string | undefined;\n\n /**\n * Called to check if there are any pending messages in the pending state queue.\n * @returns A boolean indicating whether there are messages or not.\n */\n public hasPendingMessages(): boolean {\n return this._pendingMessagesCount !== 0 || !this.initialStates.isEmpty();\n }\n\n public getLocalState(): IPendingLocalState | undefined {\n assert(this.initialStates.isEmpty(), 0x2e9 /* \"Must call getLocalState() after applying initial states\" */);\n if (this.hasPendingMessages()) {\n return {\n pendingStates: this.pendingStates.toArray().map(\n // delete localOpMetadata since it may not be serializable\n // and will be regenerated by applyStashedOp()\n (state) => state.type === \"message\" ? { ...state, localOpMetadata: undefined } : state),\n };\n }\n }\n\n constructor(\n private readonly stateHandler: IRuntimeStateHandler,\n initialLocalState: IPendingLocalState | undefined,\n ) {\n this.initialStates = new Deque<IPendingState>(initialLocalState?.pendingStates ?? []);\n }\n\n public get disposed() { return this.disposeOnce.evaluated; }\n public readonly dispose = () => this.disposeOnce.value;\n\n /**\n * Called when a message is submitted locally. Adds the message and the associated details to the pending state\n * queue.\n * @param type - The container message type.\n * @param clientSequenceNumber - The clientSequenceNumber associated with the message.\n * @param content - The message content.\n * @param localOpMetadata - The local metadata associated with the message.\n */\n public onSubmitMessage(\n type: ContainerMessageType,\n clientSequenceNumber: number,\n referenceSequenceNumber: number,\n content: any,\n localOpMetadata: unknown,\n opMetadata: Record<string, unknown> | undefined,\n ) {\n const pendingMessage: IPendingMessage = {\n type: \"message\",\n messageType: type,\n clientSequenceNumber,\n referenceSequenceNumber,\n content,\n localOpMetadata,\n opMetadata,\n };\n\n this.pendingStates.push(pendingMessage);\n\n this._pendingMessagesCount++;\n }\n\n /**\n * Called when flush() is called on the ContainerRuntime to manually flush messages.\n */\n public onFlush() {\n // If the previous state is not a message, flush is a no-op.\n const previousState = this.pendingStates.peekBack();\n if (previousState?.type !== \"message\") {\n return;\n }\n\n // An explicit flush is interesting and is tracked only if there are messages sent in TurnBased mode.\n this.pendingStates.push({ type: \"flush\" });\n }\n\n /**\n * Applies stashed ops at their reference sequence number so they are ready to be ACKed or resubmitted\n * @param seqNum - Sequence number at which to apply ops. Will apply all ops if seqNum is undefined.\n */\n public async applyStashedOpsAt(seqNum?: number) {\n // apply stashed ops at sequence number\n while (!this.initialStates.isEmpty()) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const nextState = this.initialStates.peekFront()!;\n if (nextState.type === \"message\") {\n if (seqNum !== undefined) {\n if (nextState.referenceSequenceNumber > seqNum) {\n break; // nothing left to do at this sequence number\n } else if (nextState.referenceSequenceNumber < seqNum) {\n throw new Error(\"loaded from snapshot too recent to apply stashed ops\");\n }\n }\n\n // applyStashedOp will cause the DDS to behave as if it has sent the op but not actually send it\n const localOpMetadata =\n await this.stateHandler.applyStashedOp(nextState.messageType, nextState.content);\n nextState.localOpMetadata = localOpMetadata;\n }\n\n // then we push onto pendingStates which will cause PendingStateManager to resubmit when we connect\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const firstPendingState = this.initialStates.shift()!;\n this.pendingStates.push(firstPendingState);\n if (firstPendingState.type === \"message\") {\n this._pendingMessagesCount++;\n }\n }\n }\n\n /**\n * Processes a local message once its ack'd by the server. It verifies that there was no data corruption and that\n * the batch information was preserved for batch messages.\n * @param message - The message that got ack'd and needs to be processed.\n */\n public processPendingLocalMessage(message: ISequencedDocumentMessage): unknown {\n // Pre-processing part - This may be the start of a batch.\n this.maybeProcessBatchBegin(message);\n\n // Get the next state from the pending queue and verify that it is of type \"message\".\n const pendingState = this.peekNextPendingState();\n assert(pendingState.type === \"message\", 0x169 /* \"No pending message found for this remote message\" */);\n this.pendingStates.shift();\n\n // Processing part - Verify that there has been no data corruption.\n // The clientSequenceNumber of the incoming message must match that of the pending message.\n if (pendingState.clientSequenceNumber !== message.clientSequenceNumber) {\n // Close the container because this could indicate data corruption.\n const error = DataProcessingError.create(\n \"pending local message clientSequenceNumber mismatch\",\n \"unexpectedAckReceived\",\n message,\n { expectedClientSequenceNumber: pendingState.clientSequenceNumber },\n );\n\n this.stateHandler.close(error);\n return;\n }\n\n this._pendingMessagesCount--;\n assert(this._pendingMessagesCount >= 0, 0x3d6 /* positive */);\n\n // Post-processing part - If we are processing a batch then this could be the last message in the batch.\n this.maybeProcessBatchEnd(message);\n\n return pendingState.localOpMetadata;\n }\n\n /**\n * This message could be the first message in batch. If so, set batch state marking the beginning of a batch.\n * @param message - The message that is being processed.\n */\n private maybeProcessBatchBegin(message: ISequencedDocumentMessage) {\n /**\n * We are checking if the next message is the start of a batch. It can happen in the following scenarios:\n *\n * 1. The FlushMode was set to TurnBased before this message was sent.\n *\n * 2. The FlushMode was already TurnBased and a flush was called before this message was sent. This essentially\n * means that the flush marked the end of a previous batch and beginning of a new batch.\n *\n * Keep reading pending states from the queue until we encounter a message. It's possible that the FlushMode was\n * updated a bunch of times without sending any messages.\n */\n while (this.peekNextPendingState().type !== \"message\") {\n this.pendingStates.shift();\n }\n\n // This message is the first in a batch if the \"batch\" property on the metadata is set to true\n if (message.metadata?.batch) {\n // We should not already be processing a batch and there should be no pending batch begin message.\n assert(!this.isProcessingBatch && this.pendingBatchBeginMessage === undefined,\n 0x16b /* \"The pending batch state indicates we are already processing a batch\" */);\n\n // Set the pending batch state indicating we have started processing a batch.\n this.pendingBatchBeginMessage = message;\n this.isProcessingBatch = true;\n }\n }\n\n /**\n * This message could be the last message in batch. If so, clear batch state since the batch is complete.\n * @param message - The message that is being processed.\n */\n private maybeProcessBatchEnd(message: ISequencedDocumentMessage) {\n if (!this.isProcessingBatch) {\n return;\n }\n\n const nextPendingState = this.peekNextPendingState();\n if (nextPendingState.type === \"message\") {\n return;\n }\n\n // There should be a pending batch begin message.\n assert(this.pendingBatchBeginMessage !== undefined, 0x16d /* \"There is no pending batch begin message\" */);\n\n // Get the batch begin metadata from the first message in the batch.\n const batchBeginMetadata = this.pendingBatchBeginMessage.metadata?.batch;\n\n // There could be just a single message in the batch. If so, it should not have any batch metadata. If there\n // are multiple messages in the batch, verify that we got the correct batch begin and end metadata.\n if (this.pendingBatchBeginMessage === message) {\n assert(batchBeginMetadata === undefined,\n 0x16e /* \"Batch with single message should not have batch metadata\" */);\n } else {\n // Get the batch metadata from the last message in the batch.\n const batchEndMetadata = message.metadata?.batch;\n if (batchBeginMetadata !== true || batchEndMetadata !== false) {\n this.stateHandler.close(DataProcessingError.create(\n \"Pending batch inconsistency\", // Formerly known as asserts 0x16f and 0x170\n \"processPendingLocalMessage\",\n message,\n {\n runtimeVersion: pkgVersion,\n batchClientId: this.pendingBatchBeginMessage.clientId,\n clientId: this.stateHandler.clientId(),\n hasBatchStart: batchBeginMetadata === true,\n hasBatchEnd: batchEndMetadata === false,\n messageType: message.type,\n batchStartSequenceNumber: this.pendingBatchBeginMessage.clientSequenceNumber,\n pendingMessagesCount: this.pendingMessagesCount,\n nextPendingState: nextPendingState.type,\n }));\n }\n }\n\n // Clear the pending batch state now that we have processed the entire batch.\n this.pendingBatchBeginMessage = undefined;\n this.isProcessingBatch = false;\n }\n\n /**\n * Returns the next pending state from the pending state queue.\n */\n private peekNextPendingState(): IPendingState {\n const nextPendingState = this.pendingStates.peekFront();\n assert(!!nextPendingState, 0x171 /* \"No pending state found for the remote message\" */);\n return nextPendingState;\n }\n\n /**\n * Called when the Container's connection state changes. If the Container gets connected, it replays all the pending\n * states in its queue. This includes triggering resubmission of unacked ops.\n */\n public replayPendingStates() {\n assert(this.stateHandler.connected(), 0x172 /* \"The connection state is not consistent with the runtime\" */);\n\n // This assert suggests we are about to send same ops twice, which will result in data loss.\n assert(this.clientId !== this.stateHandler.clientId(),\n 0x173 /* \"replayPendingStates called twice for same clientId!\" */);\n this.clientId = this.stateHandler.clientId();\n\n assert(this.initialStates.isEmpty(), 0x174 /* \"initial states should be empty before replaying pending\" */);\n\n let pendingStatesCount = this.pendingStates.length;\n if (pendingStatesCount === 0) {\n return;\n }\n\n // Reset the pending message count because all these messages will be removed from the queue.\n this._pendingMessagesCount = 0;\n\n const messageBatchQueue = new Deque<IPendingMessage>();\n\n // Process exactly `pendingStatesCount` items in the queue as it represents the number of states that were\n // pending when we connected. This is important because the `reSubmitFn` might add more items in the queue\n // which must not be replayed.\n while (pendingStatesCount > 0) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const pendingState = this.pendingStates.shift()!;\n switch (pendingState.type) {\n case \"message\":\n assert(pendingState.opMetadata?.batch !== false || messageBatchQueue.length > 0,\n 0x41b /* We cannot process batches in chunks */);\n /**\n * We want to ensure grouped messages get processed in a batch.\n * Note: It is not possible for the PendingStateManager to receive a partially acked batch. It will\n * either receive the whole batch ack or nothing at all.\n */\n if (messageBatchQueue.length > 0 || pendingState.opMetadata?.batch) {\n messageBatchQueue.enqueue(pendingState);\n } else {\n this.stateHandler.reSubmit(\n pendingState.messageType,\n pendingState.content,\n pendingState.localOpMetadata,\n pendingState.opMetadata);\n }\n break;\n case \"flush\":\n /**\n * A \"flush\" call can indicate the end of a batch.\n * We can't rely on the \"batch\" property in the message metadata as it gets\n * updated elsewhere and it is not the same object instance that gets updated.\n */\n if (messageBatchQueue.length > 0) {\n this.stateHandler.orderSequentially(() => {\n while (messageBatchQueue.length > 0) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const message = messageBatchQueue.dequeue()!;\n this.stateHandler.reSubmit(\n message.messageType,\n message.content,\n message.localOpMetadata,\n message.opMetadata);\n }\n });\n }\n assert(messageBatchQueue.length === 0, 0x41c /* cannot flush in the middle of a batch */);\n this.stateHandler.flush();\n break;\n default:\n break;\n }\n pendingStatesCount--;\n }\n\n // There are some cases where ops are stashed but not flushed. We need to ensure they are resubmitted\n while (messageBatchQueue.length > 0) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const message = messageBatchQueue.dequeue()!;\n this.stateHandler.reSubmit(\n message.messageType,\n message.content,\n message.localOpMetadata,\n message.opMetadata);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"pendingStateManager.js","sourceRoot":"","sources":["../src/pendingStateManager.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 { IDisposable } from \"@fluidframework/common-definitions\";\nimport { assert, Lazy } from \"@fluidframework/common-utils\";\nimport { ICriticalContainerError } from \"@fluidframework/container-definitions\";\nimport { DataProcessingError } from \"@fluidframework/container-utils\";\nimport {\n ISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport Deque from \"double-ended-queue\";\nimport { ContainerMessageType } from \"./containerRuntime\";\nimport { pkgVersion } from \"./packageVersion\";\n\n/**\n * This represents a message that has been submitted and is added to the pending queue when `submit` is called on the\n * ContainerRuntime. This message has either not been ack'd by the server or has not been submitted to the server yet.\n */\nexport interface IPendingMessage {\n type: \"message\";\n messageType: ContainerMessageType;\n clientSequenceNumber: number;\n referenceSequenceNumber: number;\n content: any;\n localOpMetadata: unknown;\n opMetadata: Record<string, unknown> | undefined;\n}\n\n/**\n * This represents an explicit flush call and is added to the pending queue when flush is called on the ContainerRuntime\n * to flush pending messages.\n * @deprecated Use batch metadata on IPendingMessage instead. To be removed in 2.0.0-internal.4.0.0 (AB#2496)\n */\nexport interface IPendingFlush {\n type: \"flush\";\n}\n\nexport type IPendingState = IPendingMessage | IPendingFlush;\n\nexport interface IPendingLocalState {\n /**\n * list of pending states, including ops and batch information\n */\n pendingStates: IPendingState[];\n}\n\nexport interface IRuntimeStateHandler {\n connected(): boolean;\n clientId(): string | undefined;\n close(error?: ICriticalContainerError): void;\n applyStashedOp: (type: ContainerMessageType, content: ISequencedDocumentMessage) => Promise<unknown>;\n reSubmit(\n type: ContainerMessageType,\n content: any,\n localOpMetadata: unknown,\n opMetadata: Record<string, unknown> | undefined): void;\n rollback(\n type: ContainerMessageType,\n content: any,\n localOpMetadata: unknown): void;\n orderSequentially(callback: () => void): void;\n}\n\n/**\n * PendingStateManager is responsible for maintaining the messages that have not been sent or have not yet been\n * acknowledged by the server. It also maintains the batch information for both automatically and manually flushed\n * batches along with the messages.\n * When the Container reconnects, it replays the pending states, which includes manual flushing\n * of messages and triggering resubmission of unacked ops.\n *\n * It verifies that all the ops are acked, are received in the right order and batch information is correct.\n */\nexport class PendingStateManager implements IDisposable {\n private readonly pendingMessages = new Deque<IPendingMessage>();\n private readonly initialMessages = new Deque<IPendingMessage>();\n private readonly disposeOnce = new Lazy<void>(() => {\n this.initialMessages.clear();\n this.pendingMessages.clear();\n });\n\n public get pendingMessagesCount(): number {\n return this.pendingMessages.length;\n }\n\n // Indicates whether we are processing a batch.\n private isProcessingBatch: boolean = false;\n\n // This stores the first message in the batch that we are processing. This is used to verify that we get\n // the correct batch metadata.\n private pendingBatchBeginMessage: ISequencedDocumentMessage | undefined;\n\n private clientId: string | undefined;\n\n /**\n * Called to check if there are any pending messages in the pending message queue.\n * @returns A boolean indicating whether there are messages or not.\n */\n public hasPendingMessages(): boolean {\n return !this.pendingMessages.isEmpty() || !this.initialMessages.isEmpty();\n }\n\n public getLocalState(): IPendingLocalState | undefined {\n assert(this.initialMessages.isEmpty(), 0x2e9 /* \"Must call getLocalState() after applying initial states\" */);\n if (!this.pendingMessages.isEmpty()) {\n return {\n pendingStates: this.pendingMessages.toArray().reduce((arr, message) => {\n // delete localOpMetadata since it may not be serializable\n // and will be regenerated by applyStashedOp()\n arr.push({ ...message, localOpMetadata: undefined });\n\n // TODO: Remove in 2.0.0-internal.4.0.0 (AB#2496)\n if (message.opMetadata?.batch === false) {\n arr.push({ type: \"flush\" });\n }\n return arr;\n }, new Array<IPendingState>()),\n };\n }\n }\n\n constructor(\n private readonly stateHandler: IRuntimeStateHandler,\n initialLocalState: IPendingLocalState | undefined,\n ) {\n /**\n * Convert old local state format to the new format\n * The old format contained \"flush\" messages as the indicator of batch ends\n * The new format instead uses batch metadata on the last message to indicate batch ends\n * ! TODO: Remove this conversion in \"2.0.0-internal.4.0.0\" as rollback from future version will be new format\n * AB#2496 tracks removal\n */\n if (initialLocalState?.pendingStates) {\n const pendingStates = initialLocalState?.pendingStates;\n let currentlyBatching = false;\n for (let i = 0; i < pendingStates.length; i++) {\n const initialState = pendingStates[i];\n\n // Skip over \"flush\" messages\n if (initialState.type === \"message\") {\n if (initialState.opMetadata?.batch) {\n currentlyBatching = true;\n } else if (initialState.opMetadata?.batch === false) {\n currentlyBatching = false;\n } else if (\n // End of batch if we are currently batching and this is last message or next message is flush\n currentlyBatching\n && (i === pendingStates.length - 1 || pendingStates[i + 1].type === \"flush\")\n ) {\n currentlyBatching = false;\n initialState.opMetadata = { ...initialState.opMetadata, batch: false };\n }\n this.initialMessages.push(initialState);\n }\n }\n }\n }\n\n public get disposed() { return this.disposeOnce.evaluated; }\n public readonly dispose = () => this.disposeOnce.value;\n\n /**\n * Called when a message is submitted locally. Adds the message and the associated details to the pending state\n * queue.\n * @param type - The container message type.\n * @param clientSequenceNumber - The clientSequenceNumber associated with the message.\n * @param content - The message content.\n * @param localOpMetadata - The local metadata associated with the message.\n */\n public onSubmitMessage(\n type: ContainerMessageType,\n clientSequenceNumber: number,\n referenceSequenceNumber: number,\n content: any,\n localOpMetadata: unknown,\n opMetadata: Record<string, unknown> | undefined,\n ) {\n const pendingMessage: IPendingMessage = {\n type: \"message\",\n messageType: type,\n clientSequenceNumber,\n referenceSequenceNumber,\n content,\n localOpMetadata,\n opMetadata,\n };\n\n this.pendingMessages.push(pendingMessage);\n }\n\n /**\n * Applies stashed ops at their reference sequence number so they are ready to be ACKed or resubmitted\n * @param seqNum - Sequence number at which to apply ops. Will apply all ops if seqNum is undefined.\n */\n public async applyStashedOpsAt(seqNum?: number) {\n // apply stashed ops at sequence number\n while (!this.initialMessages.isEmpty()) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const nextMessage = this.initialMessages.peekFront()!;\n if (seqNum !== undefined) {\n if (nextMessage.referenceSequenceNumber > seqNum) {\n break; // nothing left to do at this sequence number\n }\n if (nextMessage.referenceSequenceNumber < seqNum) {\n throw new Error(\"loaded from snapshot too recent to apply stashed ops\");\n }\n }\n\n // applyStashedOp will cause the DDS to behave as if it has sent the op but not actually send it\n const localOpMetadata =\n await this.stateHandler.applyStashedOp(nextMessage.messageType, nextMessage.content);\n nextMessage.localOpMetadata = localOpMetadata;\n\n // then we push onto pendingMessages which will cause PendingStateManager to resubmit when we connect\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.pendingMessages.push(this.initialMessages.shift()!);\n }\n }\n\n /**\n * Processes a local message once its ack'd by the server. It verifies that there was no data corruption and that\n * the batch information was preserved for batch messages.\n * @param message - The message that got ack'd and needs to be processed.\n */\n public processPendingLocalMessage(message: ISequencedDocumentMessage): unknown {\n // Pre-processing part - This may be the start of a batch.\n this.maybeProcessBatchBegin(message);\n\n // Get the next message from the pending queue. Verify a message exists.\n const pendingMessage = this.pendingMessages.peekFront();\n assert(pendingMessage !== undefined, 0x169 /* \"No pending message found for this remote message\" */);\n this.pendingMessages.shift();\n\n // Processing part - Verify that there has been no data corruption.\n // The clientSequenceNumber of the incoming message must match that of the pending message.\n if (pendingMessage.clientSequenceNumber !== message.clientSequenceNumber) {\n // Close the container because this could indicate data corruption.\n const error = DataProcessingError.create(\n \"pending local message clientSequenceNumber mismatch\",\n \"unexpectedAckReceived\",\n message,\n { expectedClientSequenceNumber: pendingMessage.clientSequenceNumber },\n );\n\n this.stateHandler.close(error);\n return;\n }\n\n // Post-processing part - If we are processing a batch then this could be the last message in the batch.\n this.maybeProcessBatchEnd(message);\n\n return pendingMessage.localOpMetadata;\n }\n\n /**\n * This message could be the first message in batch. If so, set batch state marking the beginning of a batch.\n * @param message - The message that is being processed.\n */\n private maybeProcessBatchBegin(message: ISequencedDocumentMessage) {\n // This message is the first in a batch if the \"batch\" property on the metadata is set to true\n if (message.metadata?.batch) {\n // We should not already be processing a batch and there should be no pending batch begin message.\n assert(!this.isProcessingBatch && this.pendingBatchBeginMessage === undefined,\n 0x16b /* \"The pending batch state indicates we are already processing a batch\" */);\n\n // Set the pending batch state indicating we have started processing a batch.\n this.pendingBatchBeginMessage = message;\n this.isProcessingBatch = true;\n }\n }\n\n /**\n * This message could be the last message in batch. If so, clear batch state since the batch is complete.\n * @param message - The message that is being processed.\n */\n private maybeProcessBatchEnd(message: ISequencedDocumentMessage) {\n if (!this.isProcessingBatch) {\n return;\n }\n\n // There should be a pending batch begin message.\n assert(this.pendingBatchBeginMessage !== undefined, 0x16d /* \"There is no pending batch begin message\" */);\n\n const batchEndMetadata = message.metadata?.batch;\n if (this.pendingMessages.isEmpty() || batchEndMetadata === false) {\n // Get the batch begin metadata from the first message in the batch.\n const batchBeginMetadata = this.pendingBatchBeginMessage.metadata?.batch;\n\n // There could be just a single message in the batch. If so, it should not have any batch metadata. If there\n // are multiple messages in the batch, verify that we got the correct batch begin and end metadata.\n if (this.pendingBatchBeginMessage === message) {\n assert(batchBeginMetadata === undefined,\n 0x16e /* \"Batch with single message should not have batch metadata\" */);\n } else {\n if (batchBeginMetadata !== true || batchEndMetadata !== false) {\n this.stateHandler.close(DataProcessingError.create(\n \"Pending batch inconsistency\", // Formerly known as asserts 0x16f and 0x170\n \"processPendingLocalMessage\",\n message,\n {\n runtimeVersion: pkgVersion,\n batchClientId: this.pendingBatchBeginMessage.clientId,\n clientId: this.stateHandler.clientId(),\n hasBatchStart: batchBeginMetadata === true,\n hasBatchEnd: batchEndMetadata === false,\n messageType: message.type,\n batchStartSequenceNumber: this.pendingBatchBeginMessage.clientSequenceNumber,\n pendingMessagesCount: this.pendingMessagesCount,\n }));\n }\n }\n\n // Clear the pending batch state now that we have processed the entire batch.\n this.pendingBatchBeginMessage = undefined;\n this.isProcessingBatch = false;\n }\n }\n\n /**\n * Called when the Container's connection state changes. If the Container gets connected, it replays all the pending\n * states in its queue. This includes triggering resubmission of unacked ops.\n */\n public replayPendingStates() {\n assert(this.stateHandler.connected(), 0x172 /* \"The connection state is not consistent with the runtime\" */);\n\n // This assert suggests we are about to send same ops twice, which will result in data loss.\n assert(this.clientId !== this.stateHandler.clientId(),\n 0x173 /* \"replayPendingStates called twice for same clientId!\" */);\n this.clientId = this.stateHandler.clientId();\n\n assert(this.initialMessages.isEmpty(), 0x174 /* \"initial states should be empty before replaying pending\" */);\n\n let pendingMessagesCount = this.pendingMessages.length;\n if (pendingMessagesCount === 0) {\n return;\n }\n\n // Process exactly `pendingMessagesCount` items in the queue as it represents the number of messages that were\n // pending when we connected. This is important because the `reSubmitFn` might add more items in the queue\n // which must not be replayed.\n while (pendingMessagesCount > 0) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n let pendingMessage = this.pendingMessages.shift()!;\n pendingMessagesCount--;\n assert(pendingMessage.opMetadata?.batch !== false, 0x41b /* We cannot process batches in chunks */);\n\n /**\n * We want to ensure grouped messages get processed in a batch.\n * Note: It is not possible for the PendingStateManager to receive a partially acked batch. It will\n * either receive the whole batch ack or nothing at all.\n */\n if (pendingMessage.opMetadata?.batch) {\n assert(pendingMessagesCount > 0, 0x554 /* Last pending message cannot be a batch begin */);\n\n this.stateHandler.orderSequentially(() => {\n while (pendingMessagesCount >= 0) { // check is >= because batch end may be last pending message\n this.stateHandler.reSubmit(\n pendingMessage.messageType,\n pendingMessage.content,\n pendingMessage.localOpMetadata,\n pendingMessage.opMetadata);\n\n if (pendingMessage.opMetadata?.batch === false) {\n break;\n }\n assert(pendingMessagesCount > 0, 0x555 /* No batch end found */);\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n pendingMessage = this.pendingMessages.shift()!;\n pendingMessagesCount--;\n assert(pendingMessage.opMetadata?.batch !== true,\n 0x556 /* Batch start needs a corresponding batch end */);\n }\n });\n } else {\n this.stateHandler.reSubmit(\n pendingMessage.messageType,\n pendingMessage.content,\n pendingMessage.localOpMetadata,\n pendingMessage.opMetadata);\n }\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"summarizer.js","sourceRoot":"","sources":["../src/summarizer.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 { EventEmitter } from \"events\";\nimport { Deferred } from \"@fluidframework/common-utils\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { ILoader, LoaderHeader } from \"@fluidframework/container-definitions\";\nimport { UsageError } from \"@fluidframework/container-utils\";\nimport { DriverErrorType, DriverHeader } from \"@fluidframework/driver-definitions\";\nimport { requestFluidObject } from \"@fluidframework/runtime-utils\";\nimport {\n ChildLogger,\n IFluidErrorBase,\n isFluidError,\n LoggingError,\n wrapErrorAndLog,\n} from \"@fluidframework/telemetry-utils\";\nimport {\n FluidObject,\n IFluidHandleContext,\n IFluidHandle,\n IRequest,\n} from \"@fluidframework/core-interfaces\";\nimport { ISummaryConfiguration } from \"./containerRuntime\";\nimport { ICancellableSummarizerController } from \"./runWhileConnectedCoordinator\";\nimport { summarizerClientType } from \"./summarizerClientElection\";\nimport { IAckedSummary, SummaryCollection } from \"./summaryCollection\";\nimport { SummarizerHandle } from \"./summarizerHandle\";\nimport { RunningSummarizer } from \"./runningSummarizer\";\nimport {\n ISummarizer,\n ISummarizerInternalsProvider,\n ISummarizerRuntime,\n ISummarizingWarning,\n SummarizerStopReason,\n} from \"./summarizerTypes\";\nimport { SummarizeHeuristicData } from \"./summarizerHeuristics\";\nimport { SummarizeResultBuilder } from \"./summaryGenerator\";\nimport { IConnectableRuntime } from \".\";\n\nconst summarizingError = \"summarizingError\";\n\nexport class SummarizingWarning extends LoggingError implements ISummarizingWarning, IFluidErrorBase {\n readonly errorType = summarizingError;\n readonly canRetry = true;\n\n constructor(\n errorMessage: string,\n readonly logged: boolean = false,\n ) {\n super(errorMessage);\n }\n\n static wrap(error: any, logged: boolean = false, logger: ITelemetryLogger) {\n const newErrorFn = (errMsg: string) => new SummarizingWarning(errMsg, logged);\n return wrapErrorAndLog<SummarizingWarning>(error, newErrorFn, logger);\n }\n}\n\nexport const createSummarizingWarning =\n (errorMessage: string, logged: boolean) => new SummarizingWarning(errorMessage, logged);\n\n/**\n * Summarizer is responsible for coordinating when to generate and send summaries.\n * It is the main entry point for summary work.\n * It is created only by summarizing container (i.e. one with clientType === \"summarizer\")\n */\nexport class Summarizer extends EventEmitter implements ISummarizer {\n public get IFluidLoadable() { return this; }\n public get ISummarizer() { return this; }\n\n private readonly logger: ITelemetryLogger;\n private runningSummarizer?: RunningSummarizer;\n private _disposed: boolean = false;\n private starting: boolean = false;\n\n private readonly innerHandle: IFluidHandle<this>;\n\n public get handle(): IFluidHandle<this> { return this.innerHandle; }\n private readonly stopDeferred = new Deferred<SummarizerStopReason>();\n\n constructor(\n url: string,\n /** Reference to runtime that created this object.\n * i.e. runtime with clientType === \"summarizer\"\n */\n private readonly runtime: ISummarizerRuntime,\n private readonly configurationGetter: () => ISummaryConfiguration,\n /** Represents an object that can generate summary.\n * In practical terms, it's same runtime (this.runtime) with clientType === \"summarizer\".\n */\n private readonly internalsProvider: ISummarizerInternalsProvider,\n handleContext: IFluidHandleContext,\n public readonly summaryCollection: SummaryCollection,\n private readonly runCoordinatorCreateFn:\n (runtime: IConnectableRuntime) => Promise<ICancellableSummarizerController>,\n ) {\n super();\n this.logger = ChildLogger.create(this.runtime.logger, \"Summarizer\");\n this.innerHandle = new SummarizerHandle(this, url, handleContext);\n }\n\n /**\n * Creates a Summarizer and its underlying client.\n * Note that different implementations of ILoader will handle the URL differently.\n * ILoader provided by a ContainerRuntime is a RelativeLoader, which will treat URL's\n * starting with \"/\" as relative to the Container. The general ILoader\n * interface will expect an absolute URL and will not handle \"/\".\n * @param loader - the loader that resolves the request\n * @param url - the URL used to resolve the container\n */\n public static async create(\n loader: ILoader,\n url: string): Promise<ISummarizer> {\n const request: IRequest = {\n headers: {\n [LoaderHeader.cache]: false,\n [LoaderHeader.clientDetails]: {\n capabilities: { interactive: false },\n type: summarizerClientType,\n },\n [DriverHeader.summarizingClient]: true,\n [LoaderHeader.reconnect]: false,\n },\n url,\n };\n\n const resolvedContainer = await loader.resolve(request);\n const fluidObject =\n await requestFluidObject<FluidObject<ISummarizer>>(resolvedContainer, { url: \"_summarizer\" });\n if (fluidObject.ISummarizer === undefined) {\n throw new UsageError(\"Fluid object does not implement ISummarizer\");\n }\n return fluidObject.ISummarizer;\n }\n\n public async run(onBehalfOf: string): Promise<SummarizerStopReason> {\n try {\n return await this.runCore(onBehalfOf);\n } catch (error) {\n this.stop(\"summarizerException\");\n throw SummarizingWarning.wrap(error, false /* logged */, this.logger);\n } finally {\n this.close();\n }\n }\n\n /**\n * Stops the summarizer from running. This will complete\n * the run promise, and also close the container.\n * @param reason - reason code for stopping\n */\n public stop(reason: SummarizerStopReason) {\n this.stopDeferred.resolve(reason);\n }\n\n public close() {\n // This will result in \"summarizerClientDisconnected\" stop reason recorded in telemetry,\n // unless stop() was called earlier\n this.dispose();\n (this.runtime.disposeFn ?? this.runtime.closeFn)()\n }\n\n private async runCore(onBehalfOf: string): Promise<SummarizerStopReason> {\n const runCoordinator: ICancellableSummarizerController = await this.runCoordinatorCreateFn(this.runtime);\n\n // Wait for either external signal to cancel, or loss of connectivity.\n const stopP = Promise.race([runCoordinator.waitCancelled, this.stopDeferred.promise]);\n void stopP.then((reason) => {\n this.logger.sendTelemetryEvent({\n eventName: \"StoppingSummarizer\",\n onBehalfOf,\n reason,\n });\n });\n\n if (runCoordinator.cancelled) {\n return runCoordinator.waitCancelled;\n }\n\n const runningSummarizer = await this.start(onBehalfOf, runCoordinator);\n\n // Wait for either external signal to cancel, or loss of connectivity.\n const stopReason = await stopP;\n\n // There are two possible approaches here:\n // 1. Propagate cancellation from this.stopDeferred to runCoordinator. This will ensure that we move to the exit\n // faster, including breaking out of the RunningSummarizer.trySummarize() faster.\n // We could create new coordinator and pass it to waitStop() -> trySummarizeOnce(\"lastSummary\") flow.\n // The con of this approach is that we might cancel active summary, and lastSummary will fail because it\n // did not wait for ack/nack from previous summary. Plus we disregard any 429 kind of info from service\n // that way (i.e. trySummarize() loop might have been waiting for 5 min because storage told us so).\n // In general, it's more wasted resources.\n // 2. We can not do it and make waitStop() do last summary only if there was no active summary. This ensures\n // that client behaves properly (from server POV) and we do not waste resources. But, it may mean we wait\n // substantially longer for trySummarize() retries to play out and thus this summary loop may run into\n // conflict with new summarizer client starting on different client.\n // As of now, #2 is implemented. It's more forward looking, as issue #7279 suggests changing design for new\n // summarizer client to not be created until current summarizer fully moves to exit, and that would reduce\n // cons of #2 substantially.\n\n // Cleanup after running\n await runningSummarizer.waitStop(\n !runCoordinator.cancelled && Summarizer.stopReasonCanRunLastSummary(stopReason));\n\n // Propagate reason and ensure that if someone is waiting for cancellation token, they are moving to exit\n runCoordinator.stop(stopReason);\n\n return stopReason;\n }\n\n /**\n * Should we try to run a last summary for the given stop reason?\n * Currently only allows \"parentNotConnected\"\n * @param stopReason - SummarizerStopReason\n * @returns - true if the stop reason can run a last summary\n */\n public static stopReasonCanRunLastSummary(stopReason: SummarizerStopReason): boolean {\n return stopReason === \"parentNotConnected\";\n }\n\n /**\n * Put the summarizer in a started state, including creating and initializing the RunningSummarizer.\n * The start request can come either from the SummaryManager (in the auto-summarize case) or from the user\n * (in the on-demand case).\n * @param onBehalfOf - ID of the client that requested that the summarizer start\n * @param runCoordinator - cancellation token\n * @param newConfig - Summary configuration to override the existing config when invoking the RunningSummarizer.\n * @returns - Promise that is fulfilled when the RunningSummarizer is ready\n */\n private async start(\n onBehalfOf: string,\n runCoordinator: ICancellableSummarizerController): Promise<RunningSummarizer> {\n if (this.runningSummarizer) {\n if (this.runningSummarizer.disposed) {\n throw new UsageError(\"Starting a disposed summarizer\");\n }\n return this.runningSummarizer;\n }\n if (this.starting) {\n throw new UsageError(\"Attempting to start a summarizer that is already starting\");\n }\n this.starting = true;\n // Initialize values and first ack (time is not exact)\n this.logger.sendTelemetryEvent({\n eventName: \"RunningSummarizer\",\n onBehalfOf,\n initSummarySeqNumber: this.runtime.deltaManager.initialSequenceNumber,\n config: JSON.stringify(this.configurationGetter()),\n });\n\n // Summarizing container ID (with clientType === \"summarizer\")\n const clientId = this.runtime.clientId;\n if (clientId === undefined) {\n throw new UsageError(\"clientId should be defined if connected.\");\n }\n\n const runningSummarizer = await RunningSummarizer.start(\n this.logger,\n this.summaryCollection.createWatcher(clientId),\n this.configurationGetter(),\n async (...args) => this.internalsProvider.submitSummary(...args), // submitSummaryCallback\n new SummarizeHeuristicData(\n this.runtime.deltaManager.lastSequenceNumber,\n { /** summary attempt baseline for heuristics */\n refSequenceNumber: this.runtime.deltaManager.initialSequenceNumber,\n summaryTime: Date.now(),\n } as const,\n ),\n (errorMessage: string) => {\n if (!this._disposed) {\n this.logger.sendErrorEvent({ eventName: \"summarizingError\" },\n createSummarizingWarning(errorMessage, true));\n }\n },\n this.summaryCollection,\n runCoordinator /* cancellationToken */,\n (reason) => runCoordinator.stop(reason), /* stopSummarizerCallback */\n this.runtime,\n );\n this.runningSummarizer = runningSummarizer;\n this.starting = false;\n\n // Handle summary acks\n // Note: no exceptions are thrown from handleSummaryAcks handler as it handles all exceptions\n this.handleSummaryAcks().catch((error) => {\n this.logger.sendErrorEvent({ eventName: \"HandleSummaryAckFatalError\" }, error);\n });\n\n return runningSummarizer;\n }\n\n /**\n * Disposes of resources after running. This cleanup will\n * clear any outstanding timers and reset some of the state\n * properties.\n * Called by ContainerRuntime when it is disposed, as well as at the end the run().\n */\n public dispose() {\n // Given that the call can come from own ContainerRuntime, ensure that we stop all the processes.\n this.stop(\"summarizerClientDisconnected\");\n\n this._disposed = true;\n if (this.runningSummarizer) {\n this.runningSummarizer.dispose();\n this.runningSummarizer = undefined;\n }\n }\n\n public readonly summarizeOnDemand: ISummarizer[\"summarizeOnDemand\"] = (...args) => {\n try {\n if (this._disposed || this.runningSummarizer?.disposed) {\n throw new UsageError(\"Summarizer is already disposed.\");\n }\n if (this.runtime.summarizerClientId !== undefined &&\n this.runtime.summarizerClientId !== this.runtime.clientId) {\n // If there is an elected summarizer, and it's not this one, don't allow on-demand summary.\n // This is to prevent the on-demand summary and heuristic-based summary from stepping on\n // each other.\n throw new UsageError(\"On-demand summary attempted while an elected summarizer is present\");\n }\n const builder = new SummarizeResultBuilder();\n if (this.runningSummarizer) {\n // Summarizer is already running. Go ahead and start.\n return this.runningSummarizer.summarizeOnDemand(builder, ...args);\n }\n\n // Summarizer isn't running, so we need to start it, which is an async operation.\n // Manage the promise related to creating the cancellation token here.\n // The promises related to starting, summarizing,\n // and submitting are communicated to the caller through the results builder.\n const coordinatorCreateP = this.runCoordinatorCreateFn(this.runtime);\n\n coordinatorCreateP.then((runCoordinator) => {\n // Successfully created the cancellation token. Start the summarizer.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const startP = this.start(this.runtime.clientId!, runCoordinator);\n startP.then(async (runningSummarizer) => {\n // Successfully started the summarizer. Run it.\n runningSummarizer.summarizeOnDemand(builder, ...args);\n // Wait for a command to stop or loss of connectivity before tearing down the summarizer and client.\n const stopReason = await Promise.race([this.stopDeferred.promise, runCoordinator.waitCancelled]);\n await runningSummarizer.waitStop(false);\n runCoordinator.stop(stopReason);\n this.close();\n }).catch((reason) => {\n builder.fail(\"Failed to start summarizer\", reason);\n });\n }).catch((reason) => {\n builder.fail(\"Failed to create cancellation token\", reason);\n });\n\n return builder.build();\n } catch (error) {\n throw SummarizingWarning.wrap(error, false /* logged */, this.logger);\n }\n };\n\n public readonly enqueueSummarize: ISummarizer[\"enqueueSummarize\"] = (...args) => {\n if (this._disposed || this.runningSummarizer === undefined || this.runningSummarizer.disposed) {\n throw new UsageError(\"Summarizer is not running or already disposed.\");\n }\n return this.runningSummarizer.enqueueSummarize(...args);\n };\n\n private async handleSummaryAcks() {\n let refSequenceNumber = this.runtime.deltaManager.initialSequenceNumber;\n let ack: IAckedSummary | undefined;\n while (this.runningSummarizer) {\n const summaryLogger = this.runningSummarizer.tryGetCorrelatedLogger(refSequenceNumber) ?? this.logger;\n try {\n // Initialize ack with undefined if exception happens inside of waitSummaryAck on second iteration,\n // we record undefined, not previous handles.\n ack = undefined;\n ack = await this.summaryCollection.waitSummaryAck(refSequenceNumber);\n refSequenceNumber = ack.summaryOp.referenceSequenceNumber;\n const summaryOpHandle = ack.summaryOp.contents.handle;\n const summaryAckHandle = ack.summaryAck.contents.handle;\n // Make sure we block any summarizer from being executed/enqueued while\n // executing the refreshLatestSummaryAck.\n // https://dev.azure.com/fluidframework/internal/_workitems/edit/779\n await this.runningSummarizer.lockedRefreshSummaryAckAction(async () =>\n this.internalsProvider.refreshLatestSummaryAck({\n proposalHandle: summaryOpHandle,\n ackHandle: summaryAckHandle,\n summaryRefSeq: refSequenceNumber,\n summaryLogger },\n ).catch(async (error) => {\n // If the error is 404, so maybe the fetched version no longer exists on server. We just\n // ignore this error in that case, as that means we will have another summaryAck for the\n // latest version with which we will refresh the state. However in case of single commit\n // summary, we might me missing a summary ack, so in that case we are still fine as the\n // code in `submitSummary` function in container runtime, will refresh the latest state\n // by calling `refreshLatestSummaryAckFromServer` and we will be fine.\n if (isFluidError(error)\n && error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError) {\n summaryLogger.sendTelemetryEvent({\n eventName: \"HandleSummaryAckErrorIgnored\",\n referenceSequenceNumber: refSequenceNumber,\n proposalHandle: summaryOpHandle,\n ackHandle: summaryAckHandle,\n }, error);\n } else {\n throw error;\n }\n }),\n );\n } catch (error) {\n summaryLogger.sendErrorEvent({\n eventName: \"HandleSummaryAckError\",\n referenceSequenceNumber: refSequenceNumber,\n handle: ack?.summaryOp?.contents?.handle,\n ackHandle: ack?.summaryAck?.contents?.handle,\n }, error);\n }\n refSequenceNumber++;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"summarizer.js","sourceRoot":"","sources":["../src/summarizer.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 { EventEmitter } from \"events\";\nimport { Deferred } from \"@fluidframework/common-utils\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { ILoader, LoaderHeader } from \"@fluidframework/container-definitions\";\nimport { UsageError } from \"@fluidframework/container-utils\";\nimport { DriverErrorType, DriverHeader } from \"@fluidframework/driver-definitions\";\nimport { requestFluidObject } from \"@fluidframework/runtime-utils\";\nimport {\n ChildLogger,\n IFluidErrorBase,\n isFluidError,\n LoggingError,\n wrapErrorAndLog,\n} from \"@fluidframework/telemetry-utils\";\nimport {\n FluidObject,\n IFluidHandleContext,\n IFluidHandle,\n IRequest,\n} from \"@fluidframework/core-interfaces\";\nimport { ISummaryConfiguration } from \"./containerRuntime\";\nimport { ICancellableSummarizerController } from \"./runWhileConnectedCoordinator\";\nimport { summarizerClientType } from \"./summarizerClientElection\";\nimport { IAckedSummary, SummaryCollection } from \"./summaryCollection\";\nimport { SummarizerHandle } from \"./summarizerHandle\";\nimport { RunningSummarizer } from \"./runningSummarizer\";\nimport {\n ISummarizer,\n ISummarizerInternalsProvider,\n ISummarizerRuntime,\n ISummarizingWarning,\n SummarizerStopReason,\n} from \"./summarizerTypes\";\nimport { SummarizeHeuristicData } from \"./summarizerHeuristics\";\nimport { SummarizeResultBuilder } from \"./summaryGenerator\";\nimport { IConnectableRuntime } from \".\";\n\nconst summarizingError = \"summarizingError\";\n\nexport class SummarizingWarning extends LoggingError implements ISummarizingWarning, IFluidErrorBase {\n readonly errorType = summarizingError;\n readonly canRetry = true;\n\n constructor(\n errorMessage: string,\n readonly logged: boolean = false,\n ) {\n super(errorMessage);\n }\n\n static wrap(error: any, logged: boolean = false, logger: ITelemetryLogger) {\n const newErrorFn = (errMsg: string) => new SummarizingWarning(errMsg, logged);\n return wrapErrorAndLog<SummarizingWarning>(error, newErrorFn, logger);\n }\n}\n\nexport const createSummarizingWarning =\n (errorMessage: string, logged: boolean) => new SummarizingWarning(errorMessage, logged);\n\n/**\n * Summarizer is responsible for coordinating when to generate and send summaries.\n * It is the main entry point for summary work.\n * It is created only by summarizing container (i.e. one with clientType === \"summarizer\")\n */\nexport class Summarizer extends EventEmitter implements ISummarizer {\n public get IFluidLoadable() { return this; }\n public get ISummarizer() { return this; }\n\n private readonly logger: ITelemetryLogger;\n private runningSummarizer?: RunningSummarizer;\n private _disposed: boolean = false;\n private starting: boolean = false;\n\n private readonly innerHandle: IFluidHandle<this>;\n\n public get handle(): IFluidHandle<this> { return this.innerHandle; }\n private readonly stopDeferred = new Deferred<SummarizerStopReason>();\n\n constructor(\n url: string,\n /** Reference to runtime that created this object.\n * i.e. runtime with clientType === \"summarizer\"\n */\n private readonly runtime: ISummarizerRuntime,\n private readonly configurationGetter: () => ISummaryConfiguration,\n /** Represents an object that can generate summary.\n * In practical terms, it's same runtime (this.runtime) with clientType === \"summarizer\".\n */\n private readonly internalsProvider: ISummarizerInternalsProvider,\n handleContext: IFluidHandleContext,\n public readonly summaryCollection: SummaryCollection,\n private readonly runCoordinatorCreateFn:\n (runtime: IConnectableRuntime) => Promise<ICancellableSummarizerController>,\n ) {\n super();\n this.logger = ChildLogger.create(this.runtime.logger, \"Summarizer\");\n this.innerHandle = new SummarizerHandle(this, url, handleContext);\n }\n\n /**\n * Creates a Summarizer and its underlying client.\n * Note that different implementations of ILoader will handle the URL differently.\n * ILoader provided by a ContainerRuntime is a RelativeLoader, which will treat URL's\n * starting with \"/\" as relative to the Container. The general ILoader\n * interface will expect an absolute URL and will not handle \"/\".\n * @param loader - the loader that resolves the request\n * @param url - the URL used to resolve the container\n */\n public static async create(\n loader: ILoader,\n url: string): Promise<ISummarizer> {\n const request: IRequest = {\n headers: {\n [LoaderHeader.cache]: false,\n [LoaderHeader.clientDetails]: {\n capabilities: { interactive: false },\n type: summarizerClientType,\n },\n [DriverHeader.summarizingClient]: true,\n [LoaderHeader.reconnect]: false,\n },\n url,\n };\n\n const resolvedContainer = await loader.resolve(request);\n const fluidObject =\n await requestFluidObject<FluidObject<ISummarizer>>(resolvedContainer, { url: \"_summarizer\" });\n if (fluidObject.ISummarizer === undefined) {\n throw new UsageError(\"Fluid object does not implement ISummarizer\");\n }\n return fluidObject.ISummarizer;\n }\n\n public async run(onBehalfOf: string): Promise<SummarizerStopReason> {\n try {\n return await this.runCore(onBehalfOf);\n } catch (error) {\n this.stop(\"summarizerException\");\n throw SummarizingWarning.wrap(error, false /* logged */, this.logger);\n } finally {\n this.close();\n }\n }\n\n /**\n * Stops the summarizer from running. This will complete\n * the run promise, and also close the container.\n * @param reason - reason code for stopping\n */\n public stop(reason: SummarizerStopReason) {\n this.stopDeferred.resolve(reason);\n }\n\n public close() {\n // This will result in \"summarizerClientDisconnected\" stop reason recorded in telemetry,\n // unless stop() was called earlier\n this.dispose();\n (this.runtime.disposeFn ?? this.runtime.closeFn)();\n }\n\n private async runCore(onBehalfOf: string): Promise<SummarizerStopReason> {\n const runCoordinator: ICancellableSummarizerController = await this.runCoordinatorCreateFn(this.runtime);\n\n // Wait for either external signal to cancel, or loss of connectivity.\n const stopP = Promise.race([runCoordinator.waitCancelled, this.stopDeferred.promise]);\n void stopP.then((reason) => {\n this.logger.sendTelemetryEvent({\n eventName: \"StoppingSummarizer\",\n onBehalfOf,\n reason,\n });\n });\n\n if (runCoordinator.cancelled) {\n return runCoordinator.waitCancelled;\n }\n\n const runningSummarizer = await this.start(onBehalfOf, runCoordinator);\n\n // Wait for either external signal to cancel, or loss of connectivity.\n const stopReason = await stopP;\n\n // There are two possible approaches here:\n // 1. Propagate cancellation from this.stopDeferred to runCoordinator. This will ensure that we move to the exit\n // faster, including breaking out of the RunningSummarizer.trySummarize() faster.\n // We could create new coordinator and pass it to waitStop() -> trySummarizeOnce(\"lastSummary\") flow.\n // The con of this approach is that we might cancel active summary, and lastSummary will fail because it\n // did not wait for ack/nack from previous summary. Plus we disregard any 429 kind of info from service\n // that way (i.e. trySummarize() loop might have been waiting for 5 min because storage told us so).\n // In general, it's more wasted resources.\n // 2. We can not do it and make waitStop() do last summary only if there was no active summary. This ensures\n // that client behaves properly (from server POV) and we do not waste resources. But, it may mean we wait\n // substantially longer for trySummarize() retries to play out and thus this summary loop may run into\n // conflict with new summarizer client starting on different client.\n // As of now, #2 is implemented. It's more forward looking, as issue #7279 suggests changing design for new\n // summarizer client to not be created until current summarizer fully moves to exit, and that would reduce\n // cons of #2 substantially.\n\n // Cleanup after running\n await runningSummarizer.waitStop(\n !runCoordinator.cancelled && Summarizer.stopReasonCanRunLastSummary(stopReason));\n\n // Propagate reason and ensure that if someone is waiting for cancellation token, they are moving to exit\n runCoordinator.stop(stopReason);\n\n return stopReason;\n }\n\n /**\n * Should we try to run a last summary for the given stop reason?\n * Currently only allows \"parentNotConnected\"\n * @param stopReason - SummarizerStopReason\n * @returns - true if the stop reason can run a last summary\n */\n public static stopReasonCanRunLastSummary(stopReason: SummarizerStopReason): boolean {\n return stopReason === \"parentNotConnected\";\n }\n\n /**\n * Put the summarizer in a started state, including creating and initializing the RunningSummarizer.\n * The start request can come either from the SummaryManager (in the auto-summarize case) or from the user\n * (in the on-demand case).\n * @param onBehalfOf - ID of the client that requested that the summarizer start\n * @param runCoordinator - cancellation token\n * @param newConfig - Summary configuration to override the existing config when invoking the RunningSummarizer.\n * @returns - Promise that is fulfilled when the RunningSummarizer is ready\n */\n private async start(\n onBehalfOf: string,\n runCoordinator: ICancellableSummarizerController): Promise<RunningSummarizer> {\n if (this.runningSummarizer) {\n if (this.runningSummarizer.disposed) {\n throw new UsageError(\"Starting a disposed summarizer\");\n }\n return this.runningSummarizer;\n }\n if (this.starting) {\n throw new UsageError(\"Attempting to start a summarizer that is already starting\");\n }\n this.starting = true;\n // Initialize values and first ack (time is not exact)\n this.logger.sendTelemetryEvent({\n eventName: \"RunningSummarizer\",\n onBehalfOf,\n initSummarySeqNumber: this.runtime.deltaManager.initialSequenceNumber,\n config: JSON.stringify(this.configurationGetter()),\n });\n\n // Summarizing container ID (with clientType === \"summarizer\")\n const clientId = this.runtime.clientId;\n if (clientId === undefined) {\n throw new UsageError(\"clientId should be defined if connected.\");\n }\n\n const runningSummarizer = await RunningSummarizer.start(\n this.logger,\n this.summaryCollection.createWatcher(clientId),\n this.configurationGetter(),\n async (...args) => this.internalsProvider.submitSummary(...args), // submitSummaryCallback\n new SummarizeHeuristicData(\n this.runtime.deltaManager.lastSequenceNumber,\n { /** summary attempt baseline for heuristics */\n refSequenceNumber: this.runtime.deltaManager.initialSequenceNumber,\n summaryTime: Date.now(),\n } as const,\n ),\n (errorMessage: string) => {\n if (!this._disposed) {\n this.logger.sendErrorEvent({ eventName: \"summarizingError\" },\n createSummarizingWarning(errorMessage, true));\n }\n },\n this.summaryCollection,\n runCoordinator /* cancellationToken */,\n (reason) => runCoordinator.stop(reason), /* stopSummarizerCallback */\n this.runtime,\n );\n this.runningSummarizer = runningSummarizer;\n this.starting = false;\n\n // Handle summary acks\n // Note: no exceptions are thrown from handleSummaryAcks handler as it handles all exceptions\n this.handleSummaryAcks().catch((error) => {\n this.logger.sendErrorEvent({ eventName: \"HandleSummaryAckFatalError\" }, error);\n });\n\n return runningSummarizer;\n }\n\n /**\n * Disposes of resources after running. This cleanup will\n * clear any outstanding timers and reset some of the state\n * properties.\n * Called by ContainerRuntime when it is disposed, as well as at the end the run().\n */\n public dispose() {\n // Given that the call can come from own ContainerRuntime, ensure that we stop all the processes.\n this.stop(\"summarizerClientDisconnected\");\n\n this._disposed = true;\n if (this.runningSummarizer) {\n this.runningSummarizer.dispose();\n this.runningSummarizer = undefined;\n }\n }\n\n public readonly summarizeOnDemand: ISummarizer[\"summarizeOnDemand\"] = (...args) => {\n try {\n if (this._disposed || this.runningSummarizer?.disposed) {\n throw new UsageError(\"Summarizer is already disposed.\");\n }\n if (this.runtime.summarizerClientId !== undefined &&\n this.runtime.summarizerClientId !== this.runtime.clientId) {\n // If there is an elected summarizer, and it's not this one, don't allow on-demand summary.\n // This is to prevent the on-demand summary and heuristic-based summary from stepping on\n // each other.\n throw new UsageError(\"On-demand summary attempted while an elected summarizer is present\");\n }\n const builder = new SummarizeResultBuilder();\n if (this.runningSummarizer) {\n // Summarizer is already running. Go ahead and start.\n return this.runningSummarizer.summarizeOnDemand(builder, ...args);\n }\n\n // Summarizer isn't running, so we need to start it, which is an async operation.\n // Manage the promise related to creating the cancellation token here.\n // The promises related to starting, summarizing,\n // and submitting are communicated to the caller through the results builder.\n const coordinatorCreateP = this.runCoordinatorCreateFn(this.runtime);\n\n coordinatorCreateP.then((runCoordinator) => {\n // Successfully created the cancellation token. Start the summarizer.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const startP = this.start(this.runtime.clientId!, runCoordinator);\n startP.then(async (runningSummarizer) => {\n // Successfully started the summarizer. Run it.\n runningSummarizer.summarizeOnDemand(builder, ...args);\n // Wait for a command to stop or loss of connectivity before tearing down the summarizer and client.\n const stopReason = await Promise.race([this.stopDeferred.promise, runCoordinator.waitCancelled]);\n await runningSummarizer.waitStop(false);\n runCoordinator.stop(stopReason);\n this.close();\n }).catch((reason) => {\n builder.fail(\"Failed to start summarizer\", reason);\n });\n }).catch((reason) => {\n builder.fail(\"Failed to create cancellation token\", reason);\n });\n\n return builder.build();\n } catch (error) {\n throw SummarizingWarning.wrap(error, false /* logged */, this.logger);\n }\n };\n\n public readonly enqueueSummarize: ISummarizer[\"enqueueSummarize\"] = (...args) => {\n if (this._disposed || this.runningSummarizer === undefined || this.runningSummarizer.disposed) {\n throw new UsageError(\"Summarizer is not running or already disposed.\");\n }\n return this.runningSummarizer.enqueueSummarize(...args);\n };\n\n private async handleSummaryAcks() {\n let refSequenceNumber = this.runtime.deltaManager.initialSequenceNumber;\n let ack: IAckedSummary | undefined;\n while (this.runningSummarizer) {\n const summaryLogger = this.runningSummarizer.tryGetCorrelatedLogger(refSequenceNumber) ?? this.logger;\n try {\n // Initialize ack with undefined if exception happens inside of waitSummaryAck on second iteration,\n // we record undefined, not previous handles.\n ack = undefined;\n ack = await this.summaryCollection.waitSummaryAck(refSequenceNumber);\n refSequenceNumber = ack.summaryOp.referenceSequenceNumber;\n const summaryOpHandle = ack.summaryOp.contents.handle;\n const summaryAckHandle = ack.summaryAck.contents.handle;\n // Make sure we block any summarizer from being executed/enqueued while\n // executing the refreshLatestSummaryAck.\n // https://dev.azure.com/fluidframework/internal/_workitems/edit/779\n await this.runningSummarizer.lockedRefreshSummaryAckAction(async () =>\n this.internalsProvider.refreshLatestSummaryAck({\n proposalHandle: summaryOpHandle,\n ackHandle: summaryAckHandle,\n summaryRefSeq: refSequenceNumber,\n summaryLogger },\n ).catch(async (error) => {\n // If the error is 404, so maybe the fetched version no longer exists on server. We just\n // ignore this error in that case, as that means we will have another summaryAck for the\n // latest version with which we will refresh the state. However in case of single commit\n // summary, we might me missing a summary ack, so in that case we are still fine as the\n // code in `submitSummary` function in container runtime, will refresh the latest state\n // by calling `refreshLatestSummaryAckFromServer` and we will be fine.\n if (isFluidError(error)\n && error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError) {\n summaryLogger.sendTelemetryEvent({\n eventName: \"HandleSummaryAckErrorIgnored\",\n referenceSequenceNumber: refSequenceNumber,\n proposalHandle: summaryOpHandle,\n ackHandle: summaryAckHandle,\n }, error);\n } else {\n throw error;\n }\n }),\n );\n } catch (error) {\n summaryLogger.sendErrorEvent({\n eventName: \"HandleSummaryAckError\",\n referenceSequenceNumber: refSequenceNumber,\n handle: ack?.summaryOp?.contents?.handle,\n ackHandle: ack?.summaryAck?.contents?.handle,\n }, error);\n }\n refSequenceNumber++;\n }\n }\n}\n"]}
@@ -25,7 +25,6 @@ export declare class SummarizerClientElection extends TypedEventEmitter<ISummari
25
25
  private readonly summaryCollection;
26
26
  readonly clientElection: IOrderedClientElection;
27
27
  private readonly maxOpsSinceLastSummary;
28
- private readonly electionEnabled;
29
28
  /**
30
29
  * Used to calculate number of ops since last summary ack for the current elected client.
31
30
  * This will be undefined if there is no elected summarizer, or no summary ack has been
@@ -41,7 +40,7 @@ export declare class SummarizerClientElection extends TypedEventEmitter<ISummari
41
40
  private lastReportedSeq;
42
41
  get electedClientId(): string | undefined;
43
42
  get electedParentId(): string | undefined;
44
- constructor(logger: ITelemetryLogger, summaryCollection: IEventProvider<ISummaryCollectionOpEvents>, clientElection: IOrderedClientElection, maxOpsSinceLastSummary: number, electionEnabled: boolean);
43
+ constructor(logger: ITelemetryLogger, summaryCollection: IEventProvider<ISummaryCollectionOpEvents>, clientElection: IOrderedClientElection, maxOpsSinceLastSummary: number);
45
44
  serialize(): ISerializedElection;
46
45
  static isClientEligible(client: ITrackedClient): boolean;
47
46
  static readonly clientDetailsPermitElection: (details: IClientDetails) => boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"summarizerClientElection.d.ts","sourceRoot":"","sources":["../src/summarizerClientElection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC9F,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAe,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACtG,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEjE,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAEjD,MAAM,WAAW,+BAAgC,SAAQ,MAAM;IAC3D,CAAC,KAAK,EAAE,0BAA0B,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CAClE;AAED,MAAM,WAAW,yBAA0B,SAAQ,cAAc,CAAC,+BAA+B,CAAC;IAC9F,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;CAChD;AAED;;;;GAIG;AACH,qBAAa,wBACT,SAAQ,iBAAiB,CAAC,+BAA+B,CACzD,YAAW,yBAAyB;IAuBhC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;aAClB,cAAc,EAAE,sBAAsB;IACtD,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe;IA1BpC;;;;;OAKG;IACH,OAAO,CAAC,0BAA0B,CAAqB;IACvD;;;;OAIG;IACH,OAAO,CAAC,eAAe,CAAK;IAE5B,IAAW,eAAe,uBAEzB;IACD,IAAW,eAAe,uBAEzB;gBAGoB,MAAM,EAAE,gBAAgB,EACxB,iBAAiB,EAAE,cAAc,CAAC,0BAA0B,CAAC,EAC9D,cAAc,EAAE,sBAAsB,EACrC,sBAAsB,EAAE,MAAM,EAC9B,eAAe,EAAE,OAAO;IAoFtC,SAAS,IAAI,mBAAmB;WASzB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO;IAS/D,gBAAuB,2BAA2B,YAAa,cAAc,KAAG,OAAO,CACT;CACjF"}
1
+ {"version":3,"file":"summarizerClientElection.d.ts","sourceRoot":"","sources":["../src/summarizerClientElection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC9F,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAe,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACtG,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEjE,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAEjD,MAAM,WAAW,+BAAgC,SAAQ,MAAM;IAC3D,CAAC,KAAK,EAAE,0BAA0B,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CAClE;AAED,MAAM,WAAW,yBAA0B,SAAQ,cAAc,CAAC,+BAA+B,CAAC;IAC9F,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;CAChD;AAED;;;;GAIG;AACH,qBAAa,wBACT,SAAQ,iBAAiB,CAAC,+BAA+B,CACzD,YAAW,yBAAyB;IAuBhC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;aAClB,cAAc,EAAE,sBAAsB;IACtD,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IAzB3C;;;;;OAKG;IACH,OAAO,CAAC,0BAA0B,CAAqB;IACvD;;;;OAIG;IACH,OAAO,CAAC,eAAe,CAAK;IAE5B,IAAW,eAAe,uBAEzB;IACD,IAAW,eAAe,uBAEzB;gBAGoB,MAAM,EAAE,gBAAgB,EACxB,iBAAiB,EAAE,cAAc,CAAC,0BAA0B,CAAC,EAC9D,cAAc,EAAE,sBAAsB,EACrC,sBAAsB,EAAE,MAAM;IAwD5C,SAAS,IAAI,mBAAmB;WASzB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO;IAS/D,gBAAuB,2BAA2B,YAAa,cAAc,KAAG,OAAO,CACT;CACjF"}
@@ -11,13 +11,12 @@ export const summarizerClientType = "summarizer";
11
11
  * for some configured number of ops.
12
12
  */
13
13
  export class SummarizerClientElection extends TypedEventEmitter {
14
- constructor(logger, summaryCollection, clientElection, maxOpsSinceLastSummary, electionEnabled) {
14
+ constructor(logger, summaryCollection, clientElection, maxOpsSinceLastSummary) {
15
15
  super();
16
16
  this.logger = logger;
17
17
  this.summaryCollection = summaryCollection;
18
18
  this.clientElection = clientElection;
19
19
  this.maxOpsSinceLastSummary = maxOpsSinceLastSummary;
20
- this.electionEnabled = electionEnabled;
21
20
  /**
22
21
  * Used to prevent excess logging by recording the sequence number that we last reported at,
23
22
  * and making sure we don't report another event to telemetry. If things work as intended,
@@ -27,7 +26,7 @@ export class SummarizerClientElection extends TypedEventEmitter {
27
26
  // On every inbound op, if enough ops pass without seeing a summary ack (per elected client),
28
27
  // elect a new client and log to telemetry.
29
28
  this.summaryCollection.on("default", ({ sequenceNumber }) => {
30
- var _a, _b, _c;
29
+ var _a, _b;
31
30
  const electedClientId = this.electedClientId;
32
31
  if (electedClientId === undefined) {
33
32
  // Reset election if no elected client, but eligible clients are connected.
@@ -39,7 +38,7 @@ export class SummarizerClientElection extends TypedEventEmitter {
39
38
  }
40
39
  return;
41
40
  }
42
- let electionSequenceNumber = this.clientElection.electionSequenceNumber;
41
+ const electionSequenceNumber = this.clientElection.electionSequenceNumber;
43
42
  const opsWithoutSummary = sequenceNumber - ((_a = this.lastSummaryAckSeqForClient) !== null && _a !== void 0 ? _a : electionSequenceNumber);
44
43
  if (opsWithoutSummary > this.maxOpsSinceLastSummary) {
45
44
  // Log and elect a new summarizer client.
@@ -51,35 +50,9 @@ export class SummarizerClientElection extends TypedEventEmitter {
51
50
  lastSummaryAckSeqForClient: this.lastSummaryAckSeqForClient,
52
51
  electionSequenceNumber,
53
52
  nextElectedClientId: (_b = this.clientElection.peekNextElectedClient()) === null || _b === void 0 ? void 0 : _b.clientId,
54
- electionEnabled: this.electionEnabled,
55
53
  });
56
54
  this.lastReportedSeq = sequenceNumber;
57
55
  }
58
- if (this.electionEnabled) {
59
- const previousParentId = this.electedParentId;
60
- this.clientElection.incrementElectedClient(sequenceNumber);
61
- // Verify that state incremented as expected. This should be reliable,
62
- // since all of OrderedClientElection is synchronous.
63
- electionSequenceNumber = this.clientElection.electionSequenceNumber;
64
- if (sequenceNumber > ((_c = this.lastSummaryAckSeqForClient) !== null && _c !== void 0 ? _c : electionSequenceNumber)) {
65
- if (opsSinceLastReport > this.maxOpsSinceLastSummary) {
66
- this.logger.sendErrorEvent({
67
- eventName: "UnexpectedElectionSequenceNumber",
68
- // Expected to be undefined
69
- lastSummaryAckSeqForClient: this.lastSummaryAckSeqForClient,
70
- // Expected to be same as op sequenceNumber
71
- electionSequenceNumber,
72
- sequenceNumber,
73
- previousClientId: electedClientId,
74
- previousParentId,
75
- electedParentId: this.electedParentId,
76
- electedClientId: this.electedClientId,
77
- opsSinceLastReport,
78
- maxOpsSinceLastSummary,
79
- });
80
- }
81
- }
82
- }
83
56
  }
84
57
  });
85
58
  // When a summary ack comes in, reset our op seq counter.
@@ -1 +1 @@
1
- {"version":3,"file":"summarizerClientElection.js","sourceRoot":"","sources":["../src/summarizerClientElection.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IEvent, IEventProvider, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { TypedEventEmitter } from \"@fluidframework/common-utils\";\nimport { IClientDetails, MessageType } from \"@fluidframework/protocol-definitions\";\nimport { IOrderedClientElection, ISerializedElection, ITrackedClient } from \"./orderedClientElection\";\nimport { ISummaryCollectionOpEvents } from \"./summaryCollection\";\n\nexport const summarizerClientType = \"summarizer\";\n\nexport interface ISummarizerClientElectionEvents extends IEvent {\n (event: \"electedSummarizerChanged\", handler: () => void): void;\n}\n\nexport interface ISummarizerClientElection extends IEventProvider<ISummarizerClientElectionEvents> {\n readonly electedClientId: string | undefined;\n readonly electedParentId: string | undefined;\n}\n\n/**\n * This class encapsulates logic around tracking the elected summarizer client.\n * It will handle updating the elected client when a summary ack hasn't been seen\n * for some configured number of ops.\n */\nexport class SummarizerClientElection\n extends TypedEventEmitter<ISummarizerClientElectionEvents>\n implements ISummarizerClientElection {\n /**\n * Used to calculate number of ops since last summary ack for the current elected client.\n * This will be undefined if there is no elected summarizer, or no summary ack has been\n * observed since this client was elected.\n * When a summary ack comes in, this will be set to the sequence number of the summary ack.\n */\n private lastSummaryAckSeqForClient: number | undefined;\n /**\n * Used to prevent excess logging by recording the sequence number that we last reported at,\n * and making sure we don't report another event to telemetry. If things work as intended,\n * this is not needed, otherwise it could report an event on every op in worst case scenario.\n */\n private lastReportedSeq = 0;\n\n public get electedClientId() {\n return this.clientElection.electedClient?.clientId;\n }\n public get electedParentId() {\n return this.clientElection.electedParent?.clientId;\n }\n\n constructor(\n private readonly logger: ITelemetryLogger,\n private readonly summaryCollection: IEventProvider<ISummaryCollectionOpEvents>,\n public readonly clientElection: IOrderedClientElection,\n private readonly maxOpsSinceLastSummary: number,\n private readonly electionEnabled: boolean,\n ) {\n super();\n // On every inbound op, if enough ops pass without seeing a summary ack (per elected client),\n // elect a new client and log to telemetry.\n this.summaryCollection.on(\"default\", ({ sequenceNumber }) => {\n const electedClientId = this.electedClientId;\n if (electedClientId === undefined) {\n // Reset election if no elected client, but eligible clients are connected.\n // This should be uncommon, but is possible if the initial state of the\n // ordered client election contains an undefined client id or one not found\n // in the quorum (the latter would already log an error).\n if (this.clientElection.eligibleCount > 0) {\n this.clientElection.resetElectedClient(sequenceNumber);\n }\n return;\n }\n let electionSequenceNumber = this.clientElection.electionSequenceNumber;\n const opsWithoutSummary = sequenceNumber - (this.lastSummaryAckSeqForClient ?? electionSequenceNumber);\n if (opsWithoutSummary > this.maxOpsSinceLastSummary) {\n // Log and elect a new summarizer client.\n const opsSinceLastReport = sequenceNumber - this.lastReportedSeq;\n if (opsSinceLastReport > this.maxOpsSinceLastSummary) {\n this.logger.sendTelemetryEvent({\n eventName: \"ElectedClientNotSummarizing\",\n electedClientId,\n lastSummaryAckSeqForClient: this.lastSummaryAckSeqForClient,\n electionSequenceNumber,\n nextElectedClientId: this.clientElection.peekNextElectedClient()?.clientId,\n electionEnabled: this.electionEnabled,\n });\n this.lastReportedSeq = sequenceNumber;\n }\n\n if (this.electionEnabled) {\n const previousParentId = this.electedParentId;\n this.clientElection.incrementElectedClient(sequenceNumber);\n\n // Verify that state incremented as expected. This should be reliable,\n // since all of OrderedClientElection is synchronous.\n electionSequenceNumber = this.clientElection.electionSequenceNumber;\n if (sequenceNumber > (this.lastSummaryAckSeqForClient ?? electionSequenceNumber)) {\n if (opsSinceLastReport > this.maxOpsSinceLastSummary) {\n this.logger.sendErrorEvent({\n eventName: \"UnexpectedElectionSequenceNumber\",\n // Expected to be undefined\n lastSummaryAckSeqForClient: this.lastSummaryAckSeqForClient,\n // Expected to be same as op sequenceNumber\n electionSequenceNumber,\n sequenceNumber,\n previousClientId: electedClientId,\n previousParentId,\n electedParentId: this.electedParentId,\n electedClientId: this.electedClientId,\n opsSinceLastReport,\n maxOpsSinceLastSummary,\n });\n }\n }\n }\n }\n });\n\n // When a summary ack comes in, reset our op seq counter.\n this.summaryCollection.on(MessageType.SummaryAck, (op) => {\n this.lastSummaryAckSeqForClient = op.sequenceNumber;\n });\n\n // Use oldest client election for unanimously and deterministically deciding\n // which client should summarize.\n this.clientElection.on(\"election\", (client, sequenceNumber) => {\n this.lastSummaryAckSeqForClient = undefined;\n if (client === undefined && this.clientElection.eligibleCount > 0) {\n // If no client is valid for election, reset to the oldest again.\n // Also make extra sure not to get stuck in an infinite loop here:\n // If there are no eligible clients, just wait until a client joins\n // and will be auto-elected.\n this.clientElection.resetElectedClient(sequenceNumber);\n }\n // Election can trigger a change in SummaryManager state.\n this.emit(\"electedSummarizerChanged\");\n });\n }\n\n public serialize(): ISerializedElection {\n const { electedClientId, electedParentId, electionSequenceNumber } = this.clientElection.serialize();\n return {\n electedClientId,\n electedParentId,\n electionSequenceNumber: this.lastSummaryAckSeqForClient ?? electionSequenceNumber,\n };\n }\n\n public static isClientEligible(client: ITrackedClient): boolean {\n const details = client.client.details;\n if (details === undefined) {\n // Very old clients back-compat\n return true;\n }\n return SummarizerClientElection.clientDetailsPermitElection(details);\n }\n\n public static readonly clientDetailsPermitElection = (details: IClientDetails): boolean =>\n details.capabilities.interactive || details.type === summarizerClientType;\n}\n"]}
1
+ {"version":3,"file":"summarizerClientElection.js","sourceRoot":"","sources":["../src/summarizerClientElection.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IEvent, IEventProvider, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { TypedEventEmitter } from \"@fluidframework/common-utils\";\nimport { IClientDetails, MessageType } from \"@fluidframework/protocol-definitions\";\nimport { IOrderedClientElection, ISerializedElection, ITrackedClient } from \"./orderedClientElection\";\nimport { ISummaryCollectionOpEvents } from \"./summaryCollection\";\n\nexport const summarizerClientType = \"summarizer\";\n\nexport interface ISummarizerClientElectionEvents extends IEvent {\n (event: \"electedSummarizerChanged\", handler: () => void): void;\n}\n\nexport interface ISummarizerClientElection extends IEventProvider<ISummarizerClientElectionEvents> {\n readonly electedClientId: string | undefined;\n readonly electedParentId: string | undefined;\n}\n\n/**\n * This class encapsulates logic around tracking the elected summarizer client.\n * It will handle updating the elected client when a summary ack hasn't been seen\n * for some configured number of ops.\n */\nexport class SummarizerClientElection\n extends TypedEventEmitter<ISummarizerClientElectionEvents>\n implements ISummarizerClientElection {\n /**\n * Used to calculate number of ops since last summary ack for the current elected client.\n * This will be undefined if there is no elected summarizer, or no summary ack has been\n * observed since this client was elected.\n * When a summary ack comes in, this will be set to the sequence number of the summary ack.\n */\n private lastSummaryAckSeqForClient: number | undefined;\n /**\n * Used to prevent excess logging by recording the sequence number that we last reported at,\n * and making sure we don't report another event to telemetry. If things work as intended,\n * this is not needed, otherwise it could report an event on every op in worst case scenario.\n */\n private lastReportedSeq = 0;\n\n public get electedClientId() {\n return this.clientElection.electedClient?.clientId;\n }\n public get electedParentId() {\n return this.clientElection.electedParent?.clientId;\n }\n\n constructor(\n private readonly logger: ITelemetryLogger,\n private readonly summaryCollection: IEventProvider<ISummaryCollectionOpEvents>,\n public readonly clientElection: IOrderedClientElection,\n private readonly maxOpsSinceLastSummary: number,\n ) {\n super();\n // On every inbound op, if enough ops pass without seeing a summary ack (per elected client),\n // elect a new client and log to telemetry.\n this.summaryCollection.on(\"default\", ({ sequenceNumber }) => {\n const electedClientId = this.electedClientId;\n if (electedClientId === undefined) {\n // Reset election if no elected client, but eligible clients are connected.\n // This should be uncommon, but is possible if the initial state of the\n // ordered client election contains an undefined client id or one not found\n // in the quorum (the latter would already log an error).\n if (this.clientElection.eligibleCount > 0) {\n this.clientElection.resetElectedClient(sequenceNumber);\n }\n return;\n }\n const electionSequenceNumber = this.clientElection.electionSequenceNumber;\n const opsWithoutSummary = sequenceNumber - (this.lastSummaryAckSeqForClient ?? electionSequenceNumber);\n if (opsWithoutSummary > this.maxOpsSinceLastSummary) {\n // Log and elect a new summarizer client.\n const opsSinceLastReport = sequenceNumber - this.lastReportedSeq;\n if (opsSinceLastReport > this.maxOpsSinceLastSummary) {\n this.logger.sendTelemetryEvent({\n eventName: \"ElectedClientNotSummarizing\",\n electedClientId,\n lastSummaryAckSeqForClient: this.lastSummaryAckSeqForClient,\n electionSequenceNumber,\n nextElectedClientId: this.clientElection.peekNextElectedClient()?.clientId,\n });\n this.lastReportedSeq = sequenceNumber;\n }\n }\n });\n\n // When a summary ack comes in, reset our op seq counter.\n this.summaryCollection.on(MessageType.SummaryAck, (op) => {\n this.lastSummaryAckSeqForClient = op.sequenceNumber;\n });\n\n // Use oldest client election for unanimously and deterministically deciding\n // which client should summarize.\n this.clientElection.on(\"election\", (client, sequenceNumber) => {\n this.lastSummaryAckSeqForClient = undefined;\n if (client === undefined && this.clientElection.eligibleCount > 0) {\n // If no client is valid for election, reset to the oldest again.\n // Also make extra sure not to get stuck in an infinite loop here:\n // If there are no eligible clients, just wait until a client joins\n // and will be auto-elected.\n this.clientElection.resetElectedClient(sequenceNumber);\n }\n // Election can trigger a change in SummaryManager state.\n this.emit(\"electedSummarizerChanged\");\n });\n }\n\n public serialize(): ISerializedElection {\n const { electedClientId, electedParentId, electionSequenceNumber } = this.clientElection.serialize();\n return {\n electedClientId,\n electedParentId,\n electionSequenceNumber: this.lastSummaryAckSeqForClient ?? electionSequenceNumber,\n };\n }\n\n public static isClientEligible(client: ITrackedClient): boolean {\n const details = client.client.details;\n if (details === undefined) {\n // Very old clients back-compat\n return true;\n }\n return SummarizerClientElection.clientDetailsPermitElection(details);\n }\n\n public static readonly clientDetailsPermitElection = (details: IClientDetails): boolean =>\n details.capabilities.interactive || details.type === summarizerClientType;\n}\n"]}
@@ -73,10 +73,6 @@ export interface ISummarizerRuntime extends IConnectableRuntime {
73
73
  readonly summarizerClientId: string | undefined;
74
74
  disposeFn?(): void;
75
75
  closeFn(): void;
76
- /** @deprecated 1.0, please remove all implementations and usage */
77
- on(event: "batchEnd", listener: (error: any, op: ISequencedDocumentMessage) => void): this;
78
- /** @deprecated 1.0, please remove all implementations and usage */
79
- removeListener(event: "batchEnd", listener: (error: any, op: ISequencedDocumentMessage) => void): this;
80
76
  }
81
77
  /** Options affecting summarize behavior. */
82
78
  export interface ISummarizeOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"summarizerTypes.d.ts","sourceRoot":"","sources":["../src/summarizerTypes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"summarizerTypes.d.ts","sourceRoot":"","sources":["../src/summarizerTypes.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"summarizerTypes.js","sourceRoot":"","sources":["../src/summarizerTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAuBH;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAA6B,aAAa,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n IEvent,\n IEventProvider,\n ITelemetryLogger,\n ITelemetryProperties,\n} from \"@fluidframework/common-definitions\";\nimport { ITelemetryLoggerPropertyBag } from \"@fluidframework/telemetry-utils\";\nimport {\n IFluidLoadable,\n} from \"@fluidframework/core-interfaces\";\nimport { ContainerWarning, IDeltaManager } from \"@fluidframework/container-definitions\";\nimport {\n ISequencedDocumentMessage,\n ISummaryTree,\n IDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport { ISummaryStats } from \"@fluidframework/runtime-definitions\";\nimport { ISummaryAckMessage, ISummaryNackMessage, ISummaryOpMessage } from \"./summaryCollection\";\nimport { SummarizeReason } from \"./summaryGenerator\";\nimport { ISummaryConfigurationHeuristics } from \".\";\n\n/**\n * @deprecated This will be removed in a later release.\n */\nexport const ISummarizer: keyof IProvideSummarizer = \"ISummarizer\";\n\n/**\n * @deprecated This will be removed in a later release.\n */\nexport interface IProvideSummarizer {\n /**\n * @deprecated This will be removed in a later release.\n */\n readonly ISummarizer: ISummarizer;\n}\n\n/**\n * Similar to AbortSignal, but using promise instead of events\n * @param T - cancellation reason type\n */\nexport interface ICancellationToken<T> {\n /** Tells if this cancellable token is cancelled */\n readonly cancelled: boolean;\n /**\n * Promise that gets fulfilled when this cancellable token is cancelled\n * @returns reason of cancellation\n */\n readonly waitCancelled: Promise<T>;\n}\n\n/* Similar to AbortSignal, but using promise instead of events */\nexport type ISummaryCancellationToken = ICancellationToken<SummarizerStopReason>;\n\nexport interface ISummarizerInternalsProvider {\n /** Encapsulates the work to walk the internals of the running container to generate a summary */\n submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult>;\n\n /** Callback whenever a new SummaryAck is received, to update internal tracking state */\n refreshLatestSummaryAck(options: IRefreshSummaryAckOptions): Promise<void>;\n}\n\n/**\n * @deprecated Options that control the behavior of a running summarizer.\n * */\nexport interface ISummarizerOptions {\n /**\n * Set to true to disable the default heuristics from running; false by default.\n * This affects only the heuristics around when a summarizer should\n * submit summaries. So when it is disabled, summarizer clients should\n * not be expected to summarize unless an on-demand summary is requested.\n */\n disableHeuristics: boolean;\n}\n\nexport interface ISummarizingWarning extends ContainerWarning {\n readonly errorType: \"summarizingError\";\n readonly logged: boolean;\n}\n\nexport interface IConnectableRuntime {\n readonly disposed: boolean;\n readonly connected: boolean;\n readonly clientId: string | undefined;\n readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;\n once(event: \"connected\" | \"disconnected\" | \"dispose\", listener: () => void): this;\n}\n\nexport interface ISummarizerRuntime extends IConnectableRuntime {\n readonly logger: ITelemetryLogger;\n /** clientId of parent (non-summarizing) container that owns summarizer container */\n readonly summarizerClientId: string | undefined;\n disposeFn?(): void;\n closeFn(): void;\n /** @deprecated 1.0, please remove all implementations and usage */\n on(event: \"batchEnd\", listener: (error: any, op: ISequencedDocumentMessage) => void): this;\n /** @deprecated 1.0, please remove all implementations and usage */\n removeListener(event: \"batchEnd\", listener: (error: any, op: ISequencedDocumentMessage) => void): this;\n}\n\n/** Options affecting summarize behavior. */\nexport interface ISummarizeOptions {\n /** True to generate the full tree with no handle reuse optimizations; defaults to false */\n readonly fullTree?: boolean;\n /** True to ask the server what the latest summary is first; defaults to false */\n readonly refreshLatestAck?: boolean;\n}\n\n/**\n * Data required to update internal tracking state after receiving a Summary Ack.\n */\n export interface IRefreshSummaryAckOptions {\n /** Handle from the ack's summary op. */\n readonly proposalHandle: string | undefined;\n /** Handle from the summary ack just received */\n readonly ackHandle: string;\n /** Reference sequence number from the ack's summary op */\n readonly summaryRefSeq: number;\n /** Telemetry logger to which telemetry events will be forwarded. */\n readonly summaryLogger: ITelemetryLogger;\n}\n\nexport interface ISubmitSummaryOptions extends ISummarizeOptions {\n /** Logger to use for correlated summary events */\n readonly summaryLogger: ITelemetryLogger;\n /** Tells when summary process should be cancelled */\n readonly cancellationToken: ISummaryCancellationToken;\n}\n\nexport interface IOnDemandSummarizeOptions extends ISummarizeOptions {\n /** Reason for generating summary. */\n readonly reason: string;\n}\n\n/** Options to use when enqueueing a summarize attempt. */\nexport interface IEnqueueSummarizeOptions extends IOnDemandSummarizeOptions {\n /** If specified, The summarize attempt will not occur until after this sequence number. */\n readonly afterSequenceNumber?: number;\n\n /**\n * True to override the existing enqueued summarize attempt if there is one.\n * This will guarantee that this attempt gets enqueued. If override is false,\n * than an existing enqueued summarize attempt will block a new one from being\n * enqueued. There can only be one enqueued at a time. Defaults to false.\n */\n readonly override?: boolean;\n}\n\n/**\n * In addition to the normal summary tree + stats, this contains additional stats\n * only relevant at the root of the tree.\n */\nexport interface IGeneratedSummaryStats extends ISummaryStats {\n /** The total number of data stores in the container. */\n readonly dataStoreCount: number;\n /** The number of data stores that were summarized in this summary. */\n readonly summarizedDataStoreCount: number;\n /** The number of data stores whose GC reference state was updated in this summary. */\n readonly gcStateUpdatedDataStoreCount?: number;\n /** The size of the gc blobs in this summary. */\n readonly gcTotalBlobsSize?: number;\n /** The number of gc blobs in this summary. */\n readonly gcBlobNodeCount?: number;\n /** The summary number for a container's summary. Incremented on summaries throughout its lifetime. */\n readonly summaryNumber: number;\n}\n\n/** Base results for all submitSummary attempts. */\nexport interface IBaseSummarizeResult {\n readonly stage: \"base\";\n /** Error object related to failed summarize attempt. */\n readonly error: any;\n /** Reference sequence number as of the generate summary attempt. */\n readonly referenceSequenceNumber: number;\n readonly minimumSequenceNumber: number;\n}\n\n/** Results of submitSummary after generating the summary tree. */\nexport interface IGenerateSummaryTreeResult extends Omit<IBaseSummarizeResult, \"stage\"> {\n readonly stage: \"generate\";\n /** Generated summary tree. */\n readonly summaryTree: ISummaryTree;\n /** Stats for generated summary tree. */\n readonly summaryStats: IGeneratedSummaryStats;\n /** Time it took to generate the summary tree and stats. */\n readonly generateDuration: number;\n /** True if the full tree regeneration with no handle reuse optimizations was forced. */\n readonly forcedFullTree: boolean;\n}\n\n/** Results of submitSummary after uploading the tree to storage. */\nexport interface IUploadSummaryResult extends Omit<IGenerateSummaryTreeResult, \"stage\"> {\n readonly stage: \"upload\";\n /** The handle returned by storage pointing to the uploaded summary tree. */\n readonly handle: string;\n /** Time it took to upload the summary tree to storage. */\n readonly uploadDuration: number;\n}\n\n/** Results of submitSummary after submitting the summarize op. */\nexport interface ISubmitSummaryOpResult extends Omit<IUploadSummaryResult, \"stage\" | \"error\"> {\n readonly stage: \"submit\";\n /** The client sequence number of the summarize op submitted for the summary. */\n readonly clientSequenceNumber: number;\n /** Time it took to submit the summarize op to the broadcasting service. */\n readonly submitOpDuration: number;\n}\n\n/**\n * Strict type representing result of a submitSummary attempt.\n * The result consists of 4 possible stages, each with its own data.\n * The data is cumulative, so each stage will contain the data from the previous stages.\n * If the final \"submitted\" stage is not reached, the result may contain the error object.\n *\n * Stages:\n *\n * 1. \"base\" - stopped before the summary tree was even generated, and the result only contains the base data\n *\n * 2. \"generate\" - the summary tree was generated, and the result will contain that tree + stats\n *\n * 3. \"upload\" - the summary was uploaded to storage, and the result contains the server-provided handle\n *\n * 4. \"submit\" - the summarize op was submitted, and the result contains the op client sequence number.\n */\nexport type SubmitSummaryResult =\n | IBaseSummarizeResult\n | IGenerateSummaryTreeResult\n | IUploadSummaryResult\n | ISubmitSummaryOpResult;\n\nexport interface IBroadcastSummaryResult {\n readonly summarizeOp: ISummaryOpMessage;\n readonly broadcastDuration: number;\n}\n\nexport interface IAckSummaryResult {\n readonly summaryAckOp: ISummaryAckMessage;\n readonly ackNackDuration: number;\n}\n\nexport interface INackSummaryResult {\n readonly summaryNackOp: ISummaryNackMessage;\n readonly ackNackDuration: number;\n}\n\nexport type SummarizeResultPart<TSuccess, TFailure = undefined> = {\n success: true;\n data: TSuccess;\n} | {\n success: false;\n data: TFailure | undefined;\n message: string;\n error: any;\n retryAfterSeconds?: number;\n};\n\nexport interface ISummarizeResults {\n /** Resolves when we generate, upload, and submit the summary. */\n readonly summarySubmitted: Promise<SummarizeResultPart<SubmitSummaryResult>>;\n /** Resolves when we observe our summarize op broadcast. */\n readonly summaryOpBroadcasted: Promise<SummarizeResultPart<IBroadcastSummaryResult>>;\n /** Resolves when we receive a summaryAck or summaryNack. */\n readonly receivedSummaryAckOrNack: Promise<SummarizeResultPart<IAckSummaryResult, INackSummaryResult>>;\n}\n\nexport type EnqueueSummarizeResult = (ISummarizeResults & {\n /**\n * Indicates that another summarize attempt is not already enqueued,\n * and this attempt has been enqueued.\n */\n readonly alreadyEnqueued?: undefined;\n}) | (ISummarizeResults & {\n /** Indicates that another summarize attempt was already enqueued. */\n readonly alreadyEnqueued: true;\n /**\n * Indicates that the other enqueued summarize attempt was abandoned,\n * and this attempt has been enqueued enqueued.\n */\n readonly overridden: true;\n}) | {\n /** Indicates that another summarize attempt was already enqueued. */\n readonly alreadyEnqueued: true;\n /**\n * Indicates that the other enqueued summarize attempt remains enqueued,\n * and this attempt has not been enqueued.\n */\n readonly overridden?: undefined;\n};\n\nexport type SummarizerStopReason =\n /** Summarizer client failed to summarize in all 3 consecutive attempts. */\n | \"failToSummarize\"\n /** Parent client reported that it is no longer connected. */\n | \"parentNotConnected\"\n /**\n * Parent client reported that it is no longer elected the summarizer.\n * This is the normal flow; a disconnect will always trigger the parent\n * client to no longer be elected as responsible for summaries. Then it\n * tries to stop its spawned summarizer client.\n */\n | \"notElectedParent\"\n /**\n * We are not already running the summarizer and we are not the current elected client id.\n */\n | \"notElectedClient\"\n /** Summarizer client was disconnected */\n | \"summarizerClientDisconnected\"\n /* running summarizer threw an exception */\n | \"summarizerException\";\n\nexport interface ISummarizerEvents extends IEvent {\n /**\n * An event indicating that the Summarizer is having problems summarizing\n */\n (event: \"summarizingError\", listener: (error: ISummarizingWarning) => void);\n}\n\nexport interface ISummarizer extends\n IEventProvider<ISummarizerEvents>, IFluidLoadable, Partial<IProvideSummarizer> {\n /*\n * Asks summarizer to move to exit.\n * Summarizer will finish current processes, which may take a while.\n * For example, summarizer may complete last summary before exiting.\n */\n stop(reason: SummarizerStopReason): void;\n\n /* Closes summarizer. Any pending processes (summary in flight) are abandoned. */\n close(): void;\n\n run(onBehalfOf: string, disableHeuristics?: boolean): Promise<SummarizerStopReason>;\n\n /**\n * Attempts to generate a summary on demand. If already running, takes no action.\n * @param options - options controlling the summarize attempt\n * @returns an alreadyRunning promise if a summarize attempt is already in progress,\n * which will resolve when the current attempt completes. At that point caller can\n * decide to try again or not. Otherwise, it will return an object containing promises\n * that resolve as the summarize attempt progresses. They will resolve with success\n * false if a failure is encountered.\n */\n summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults;\n /**\n * Enqueue an attempt to summarize after the specified sequence number.\n * If afterSequenceNumber is provided, the summarize attempt is \"enqueued\"\n * to run once an eligible op comes in with sequenceNumber \\>= afterSequenceNumber.\n * @param options - options controlling the summarize attempt\n * @returns an object containing an alreadyEnqueued flag to indicate if another\n * summarize attempt has already been enqueued. It also may contain an overridden flag\n * when alreadyEnqueued is true, that indicates whether this attempt forced the\n * previous attempt to abort. If this attempt becomes enqueued, it returns an object\n * containing promises that resolve as the summarize attempt progresses. They will\n * resolve with success false if a failure is encountered.\n */\n enqueueSummarize(options: IEnqueueSummarizeOptions): EnqueueSummarizeResult;\n}\n\n/** Data about an attempt to summarize used for heuristics. */\nexport interface ISummarizeAttempt {\n /** Reference sequence number when summary was generated or attempted */\n readonly refSequenceNumber: number;\n\n /** Time of summary attempt after it was sent or attempted */\n readonly summaryTime: number;\n\n /** Sequence number of summary op */\n summarySequenceNumber?: number;\n}\n\n/** Data relevant for summary heuristics. */\nexport interface ISummarizeHeuristicData {\n /** Latest received op sequence number */\n lastOpSequenceNumber: number;\n\n /** Most recent summary attempt from this client */\n readonly lastAttempt: ISummarizeAttempt;\n\n /** Most recent summary that received an ack */\n readonly lastSuccessfulSummary: Readonly<ISummarizeAttempt>;\n\n /** Number of runtime ops since last summary */\n numRuntimeOps: number;\n\n /** Number of non-runtime ops since last summary */\n numNonRuntimeOps: number;\n\n /** Cumulative size in bytes of all the ops since the last summary */\n totalOpsSize: number;\n\n /** Wether or not this instance contains adjusted metrics due to missing op data */\n hasMissingOpData: boolean;\n\n /**\n * Updates lastAttempt and lastSuccessfulAttempt based on the last summary.\n * @param lastSummary - last ack summary\n */\n updateWithLastSummaryAckInfo(lastSummary: ISummarizeAttempt): void;\n\n /**\n * Records a summary attempt. If the attempt was successfully sent,\n * provide the reference sequence number, otherwise it will be set\n * to the last seen op sequence number.\n * @param referenceSequenceNumber - reference sequence number of sent summary\n */\n recordAttempt(referenceSequenceNumber?: number): void;\n\n /** Mark that the last sent summary attempt has received an ack */\n markLastAttemptAsSuccessful(): void;\n}\n\n/** Responsible for running heuristics determining when to summarize. */\nexport interface ISummarizeHeuristicRunner {\n /** Start specific heuristic trackers (ex: idle timer) */\n start(): void;\n\n /** Runs the heuristics to determine if it should try to summarize */\n run(): void;\n\n /** Runs a different heuristic to check if it should summarize before closing */\n shouldRunLastSummary(): boolean;\n\n /** Disposes of resources */\n dispose(): void;\n}\n\ntype ISummarizeTelemetryRequiredProperties =\n /** Reason code for attempting to summarize */\n \"reason\";\n\ntype ISummarizeTelemetryOptionalProperties =\n /** Number of attempts within the last time window, used for calculating the throttle delay. */\n \"summaryAttempts\" |\n /** Number of attempts within the current phase (currently capped at 2 ) */\n \"summaryAttemptsPerPhase\" |\n /** One-based count of phases we've attempted (used to index into an array of ISummarizeOptions */\n \"summaryAttemptPhase\" |\n keyof ISummarizeOptions;\n\nexport type ISummarizeTelemetryProperties =\n Pick<ITelemetryProperties, ISummarizeTelemetryRequiredProperties> &\n Partial<Pick<ITelemetryProperties, ISummarizeTelemetryOptionalProperties>>;\n\n/** Strategy used to heuristically determine when we should run a summary */\nexport interface ISummaryHeuristicStrategy {\n /** Summarize reason for this summarize heuristic strategy (ex: \"maxTime\") */\n summarizeReason: Readonly<SummarizeReason>;\n\n /**\n * Determines if this strategy's summarize criteria been met\n * @param configuration - summary configuration we are to check against\n * @param heuristicData - heuristic data used to confirm conditions are met\n */\n shouldRunSummary(configuration: ISummaryConfigurationHeuristics, heuristicData: ISummarizeHeuristicData): boolean;\n}\n\ntype SummaryGeneratorRequiredTelemetryProperties =\n /** True to generate the full tree with no handle reuse optimizations */\n \"fullTree\" |\n /** Time since we last attempted to generate a summary */\n \"timeSinceLastAttempt\" |\n /** Time since we last successfully generated a summary */\n \"timeSinceLastSummary\";\n\ntype SummaryGeneratorOptionalTelemetryProperties =\n /** Reference sequence number as of the generate summary attempt. */\n \"referenceSequenceNumber\" |\n /** minimum sequence number (at the reference sequence number) */\n \"minimumSequenceNumber\" |\n /** Delta between the current reference sequence number and the reference sequence number of the last attempt */\n \"opsSinceLastAttempt\" |\n /** Delta between the current reference sequence number and the reference sequence number of the last summary */\n \"opsSinceLastSummary\" |\n /**\n * Delta in sum of op sizes between the current reference sequence number and the reference\n * sequence number of the last summary\n */\n \"opsSizesSinceLastSummary\" |\n /** Delta between the number of non-runtime ops since the last summary */\n \"nonRuntimeOpsSinceLastSummary\" |\n /** Wether or not this instance contains adjusted metrics due to missing op data */\n \"hasMissingOpData\" |\n /** Time it took to generate the summary tree and stats. */\n \"generateDuration\" |\n /** The handle returned by storage pointing to the uploaded summary tree. */\n \"handle\" |\n /** Time it took to upload the summary tree to storage. */\n \"uploadDuration\" |\n /** The client sequence number of the summarize op submitted for the summary. */\n \"clientSequenceNumber\" |\n /** Time it took for this summary to be acked after it was generated */\n \"ackWaitDuration\" |\n /** Reference sequence number of the ack/nack message */\n \"ackNackSequenceNumber\" |\n /** Actual sequence number of the summary op proposal. */\n \"summarySequenceNumber\" |\n /** Optional Retry-After time in seconds. If specified, the client should wait this many seconds before retrying. */\n \"nackRetryAfter\";\n\nexport type SummaryGeneratorTelemetry =\n Pick<ITelemetryProperties, SummaryGeneratorRequiredTelemetryProperties> &\n Partial<Pick<ITelemetryProperties, SummaryGeneratorOptionalTelemetryProperties>>;\n\nexport interface ISummarizeRunnerTelemetry extends ITelemetryLoggerPropertyBag {\n /** Number of times the summarizer run. */\n summarizeCount: () => number;\n /** Number of successful attempts to summarize. */\n summarizerSuccessfulAttempts: () => number;\n}\n"]}
1
+ {"version":3,"file":"summarizerTypes.js","sourceRoot":"","sources":["../src/summarizerTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAuBH;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAA6B,aAAa,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n IEvent,\n IEventProvider,\n ITelemetryLogger,\n ITelemetryProperties,\n} from \"@fluidframework/common-definitions\";\nimport { ITelemetryLoggerPropertyBag } from \"@fluidframework/telemetry-utils\";\nimport {\n IFluidLoadable,\n} from \"@fluidframework/core-interfaces\";\nimport { ContainerWarning, IDeltaManager } from \"@fluidframework/container-definitions\";\nimport {\n ISequencedDocumentMessage,\n ISummaryTree,\n IDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport { ISummaryStats } from \"@fluidframework/runtime-definitions\";\nimport { ISummaryAckMessage, ISummaryNackMessage, ISummaryOpMessage } from \"./summaryCollection\";\nimport { SummarizeReason } from \"./summaryGenerator\";\nimport { ISummaryConfigurationHeuristics } from \".\";\n\n/**\n * @deprecated This will be removed in a later release.\n */\nexport const ISummarizer: keyof IProvideSummarizer = \"ISummarizer\";\n\n/**\n * @deprecated This will be removed in a later release.\n */\nexport interface IProvideSummarizer {\n /**\n * @deprecated This will be removed in a later release.\n */\n readonly ISummarizer: ISummarizer;\n}\n\n/**\n * Similar to AbortSignal, but using promise instead of events\n * @param T - cancellation reason type\n */\nexport interface ICancellationToken<T> {\n /** Tells if this cancellable token is cancelled */\n readonly cancelled: boolean;\n /**\n * Promise that gets fulfilled when this cancellable token is cancelled\n * @returns reason of cancellation\n */\n readonly waitCancelled: Promise<T>;\n}\n\n/* Similar to AbortSignal, but using promise instead of events */\nexport type ISummaryCancellationToken = ICancellationToken<SummarizerStopReason>;\n\nexport interface ISummarizerInternalsProvider {\n /** Encapsulates the work to walk the internals of the running container to generate a summary */\n submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult>;\n\n /** Callback whenever a new SummaryAck is received, to update internal tracking state */\n refreshLatestSummaryAck(options: IRefreshSummaryAckOptions): Promise<void>;\n}\n\n/**\n * @deprecated Options that control the behavior of a running summarizer.\n * */\nexport interface ISummarizerOptions {\n /**\n * Set to true to disable the default heuristics from running; false by default.\n * This affects only the heuristics around when a summarizer should\n * submit summaries. So when it is disabled, summarizer clients should\n * not be expected to summarize unless an on-demand summary is requested.\n */\n disableHeuristics: boolean;\n}\n\nexport interface ISummarizingWarning extends ContainerWarning {\n readonly errorType: \"summarizingError\";\n readonly logged: boolean;\n}\n\nexport interface IConnectableRuntime {\n readonly disposed: boolean;\n readonly connected: boolean;\n readonly clientId: string | undefined;\n readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;\n once(event: \"connected\" | \"disconnected\" | \"dispose\", listener: () => void): this;\n}\n\nexport interface ISummarizerRuntime extends IConnectableRuntime {\n readonly logger: ITelemetryLogger;\n /** clientId of parent (non-summarizing) container that owns summarizer container */\n readonly summarizerClientId: string | undefined;\n disposeFn?(): void;\n closeFn(): void;\n}\n\n/** Options affecting summarize behavior. */\nexport interface ISummarizeOptions {\n /** True to generate the full tree with no handle reuse optimizations; defaults to false */\n readonly fullTree?: boolean;\n /** True to ask the server what the latest summary is first; defaults to false */\n readonly refreshLatestAck?: boolean;\n}\n\n/**\n * Data required to update internal tracking state after receiving a Summary Ack.\n */\n export interface IRefreshSummaryAckOptions {\n /** Handle from the ack's summary op. */\n readonly proposalHandle: string | undefined;\n /** Handle from the summary ack just received */\n readonly ackHandle: string;\n /** Reference sequence number from the ack's summary op */\n readonly summaryRefSeq: number;\n /** Telemetry logger to which telemetry events will be forwarded. */\n readonly summaryLogger: ITelemetryLogger;\n}\n\nexport interface ISubmitSummaryOptions extends ISummarizeOptions {\n /** Logger to use for correlated summary events */\n readonly summaryLogger: ITelemetryLogger;\n /** Tells when summary process should be cancelled */\n readonly cancellationToken: ISummaryCancellationToken;\n}\n\nexport interface IOnDemandSummarizeOptions extends ISummarizeOptions {\n /** Reason for generating summary. */\n readonly reason: string;\n}\n\n/** Options to use when enqueueing a summarize attempt. */\nexport interface IEnqueueSummarizeOptions extends IOnDemandSummarizeOptions {\n /** If specified, The summarize attempt will not occur until after this sequence number. */\n readonly afterSequenceNumber?: number;\n\n /**\n * True to override the existing enqueued summarize attempt if there is one.\n * This will guarantee that this attempt gets enqueued. If override is false,\n * than an existing enqueued summarize attempt will block a new one from being\n * enqueued. There can only be one enqueued at a time. Defaults to false.\n */\n readonly override?: boolean;\n}\n\n/**\n * In addition to the normal summary tree + stats, this contains additional stats\n * only relevant at the root of the tree.\n */\nexport interface IGeneratedSummaryStats extends ISummaryStats {\n /** The total number of data stores in the container. */\n readonly dataStoreCount: number;\n /** The number of data stores that were summarized in this summary. */\n readonly summarizedDataStoreCount: number;\n /** The number of data stores whose GC reference state was updated in this summary. */\n readonly gcStateUpdatedDataStoreCount?: number;\n /** The size of the gc blobs in this summary. */\n readonly gcTotalBlobsSize?: number;\n /** The number of gc blobs in this summary. */\n readonly gcBlobNodeCount?: number;\n /** The summary number for a container's summary. Incremented on summaries throughout its lifetime. */\n readonly summaryNumber: number;\n}\n\n/** Base results for all submitSummary attempts. */\nexport interface IBaseSummarizeResult {\n readonly stage: \"base\";\n /** Error object related to failed summarize attempt. */\n readonly error: any;\n /** Reference sequence number as of the generate summary attempt. */\n readonly referenceSequenceNumber: number;\n readonly minimumSequenceNumber: number;\n}\n\n/** Results of submitSummary after generating the summary tree. */\nexport interface IGenerateSummaryTreeResult extends Omit<IBaseSummarizeResult, \"stage\"> {\n readonly stage: \"generate\";\n /** Generated summary tree. */\n readonly summaryTree: ISummaryTree;\n /** Stats for generated summary tree. */\n readonly summaryStats: IGeneratedSummaryStats;\n /** Time it took to generate the summary tree and stats. */\n readonly generateDuration: number;\n /** True if the full tree regeneration with no handle reuse optimizations was forced. */\n readonly forcedFullTree: boolean;\n}\n\n/** Results of submitSummary after uploading the tree to storage. */\nexport interface IUploadSummaryResult extends Omit<IGenerateSummaryTreeResult, \"stage\"> {\n readonly stage: \"upload\";\n /** The handle returned by storage pointing to the uploaded summary tree. */\n readonly handle: string;\n /** Time it took to upload the summary tree to storage. */\n readonly uploadDuration: number;\n}\n\n/** Results of submitSummary after submitting the summarize op. */\nexport interface ISubmitSummaryOpResult extends Omit<IUploadSummaryResult, \"stage\" | \"error\"> {\n readonly stage: \"submit\";\n /** The client sequence number of the summarize op submitted for the summary. */\n readonly clientSequenceNumber: number;\n /** Time it took to submit the summarize op to the broadcasting service. */\n readonly submitOpDuration: number;\n}\n\n/**\n * Strict type representing result of a submitSummary attempt.\n * The result consists of 4 possible stages, each with its own data.\n * The data is cumulative, so each stage will contain the data from the previous stages.\n * If the final \"submitted\" stage is not reached, the result may contain the error object.\n *\n * Stages:\n *\n * 1. \"base\" - stopped before the summary tree was even generated, and the result only contains the base data\n *\n * 2. \"generate\" - the summary tree was generated, and the result will contain that tree + stats\n *\n * 3. \"upload\" - the summary was uploaded to storage, and the result contains the server-provided handle\n *\n * 4. \"submit\" - the summarize op was submitted, and the result contains the op client sequence number.\n */\nexport type SubmitSummaryResult =\n | IBaseSummarizeResult\n | IGenerateSummaryTreeResult\n | IUploadSummaryResult\n | ISubmitSummaryOpResult;\n\nexport interface IBroadcastSummaryResult {\n readonly summarizeOp: ISummaryOpMessage;\n readonly broadcastDuration: number;\n}\n\nexport interface IAckSummaryResult {\n readonly summaryAckOp: ISummaryAckMessage;\n readonly ackNackDuration: number;\n}\n\nexport interface INackSummaryResult {\n readonly summaryNackOp: ISummaryNackMessage;\n readonly ackNackDuration: number;\n}\n\nexport type SummarizeResultPart<TSuccess, TFailure = undefined> = {\n success: true;\n data: TSuccess;\n} | {\n success: false;\n data: TFailure | undefined;\n message: string;\n error: any;\n retryAfterSeconds?: number;\n};\n\nexport interface ISummarizeResults {\n /** Resolves when we generate, upload, and submit the summary. */\n readonly summarySubmitted: Promise<SummarizeResultPart<SubmitSummaryResult>>;\n /** Resolves when we observe our summarize op broadcast. */\n readonly summaryOpBroadcasted: Promise<SummarizeResultPart<IBroadcastSummaryResult>>;\n /** Resolves when we receive a summaryAck or summaryNack. */\n readonly receivedSummaryAckOrNack: Promise<SummarizeResultPart<IAckSummaryResult, INackSummaryResult>>;\n}\n\nexport type EnqueueSummarizeResult = (ISummarizeResults & {\n /**\n * Indicates that another summarize attempt is not already enqueued,\n * and this attempt has been enqueued.\n */\n readonly alreadyEnqueued?: undefined;\n}) | (ISummarizeResults & {\n /** Indicates that another summarize attempt was already enqueued. */\n readonly alreadyEnqueued: true;\n /**\n * Indicates that the other enqueued summarize attempt was abandoned,\n * and this attempt has been enqueued enqueued.\n */\n readonly overridden: true;\n}) | {\n /** Indicates that another summarize attempt was already enqueued. */\n readonly alreadyEnqueued: true;\n /**\n * Indicates that the other enqueued summarize attempt remains enqueued,\n * and this attempt has not been enqueued.\n */\n readonly overridden?: undefined;\n};\n\nexport type SummarizerStopReason =\n /** Summarizer client failed to summarize in all 3 consecutive attempts. */\n | \"failToSummarize\"\n /** Parent client reported that it is no longer connected. */\n | \"parentNotConnected\"\n /**\n * Parent client reported that it is no longer elected the summarizer.\n * This is the normal flow; a disconnect will always trigger the parent\n * client to no longer be elected as responsible for summaries. Then it\n * tries to stop its spawned summarizer client.\n */\n | \"notElectedParent\"\n /**\n * We are not already running the summarizer and we are not the current elected client id.\n */\n | \"notElectedClient\"\n /** Summarizer client was disconnected */\n | \"summarizerClientDisconnected\"\n /* running summarizer threw an exception */\n | \"summarizerException\";\n\nexport interface ISummarizerEvents extends IEvent {\n /**\n * An event indicating that the Summarizer is having problems summarizing\n */\n (event: \"summarizingError\", listener: (error: ISummarizingWarning) => void);\n}\n\nexport interface ISummarizer extends\n IEventProvider<ISummarizerEvents>, IFluidLoadable, Partial<IProvideSummarizer> {\n /*\n * Asks summarizer to move to exit.\n * Summarizer will finish current processes, which may take a while.\n * For example, summarizer may complete last summary before exiting.\n */\n stop(reason: SummarizerStopReason): void;\n\n /* Closes summarizer. Any pending processes (summary in flight) are abandoned. */\n close(): void;\n\n run(onBehalfOf: string, disableHeuristics?: boolean): Promise<SummarizerStopReason>;\n\n /**\n * Attempts to generate a summary on demand. If already running, takes no action.\n * @param options - options controlling the summarize attempt\n * @returns an alreadyRunning promise if a summarize attempt is already in progress,\n * which will resolve when the current attempt completes. At that point caller can\n * decide to try again or not. Otherwise, it will return an object containing promises\n * that resolve as the summarize attempt progresses. They will resolve with success\n * false if a failure is encountered.\n */\n summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults;\n /**\n * Enqueue an attempt to summarize after the specified sequence number.\n * If afterSequenceNumber is provided, the summarize attempt is \"enqueued\"\n * to run once an eligible op comes in with sequenceNumber \\>= afterSequenceNumber.\n * @param options - options controlling the summarize attempt\n * @returns an object containing an alreadyEnqueued flag to indicate if another\n * summarize attempt has already been enqueued. It also may contain an overridden flag\n * when alreadyEnqueued is true, that indicates whether this attempt forced the\n * previous attempt to abort. If this attempt becomes enqueued, it returns an object\n * containing promises that resolve as the summarize attempt progresses. They will\n * resolve with success false if a failure is encountered.\n */\n enqueueSummarize(options: IEnqueueSummarizeOptions): EnqueueSummarizeResult;\n}\n\n/** Data about an attempt to summarize used for heuristics. */\nexport interface ISummarizeAttempt {\n /** Reference sequence number when summary was generated or attempted */\n readonly refSequenceNumber: number;\n\n /** Time of summary attempt after it was sent or attempted */\n readonly summaryTime: number;\n\n /** Sequence number of summary op */\n summarySequenceNumber?: number;\n}\n\n/** Data relevant for summary heuristics. */\nexport interface ISummarizeHeuristicData {\n /** Latest received op sequence number */\n lastOpSequenceNumber: number;\n\n /** Most recent summary attempt from this client */\n readonly lastAttempt: ISummarizeAttempt;\n\n /** Most recent summary that received an ack */\n readonly lastSuccessfulSummary: Readonly<ISummarizeAttempt>;\n\n /** Number of runtime ops since last summary */\n numRuntimeOps: number;\n\n /** Number of non-runtime ops since last summary */\n numNonRuntimeOps: number;\n\n /** Cumulative size in bytes of all the ops since the last summary */\n totalOpsSize: number;\n\n /** Wether or not this instance contains adjusted metrics due to missing op data */\n hasMissingOpData: boolean;\n\n /**\n * Updates lastAttempt and lastSuccessfulAttempt based on the last summary.\n * @param lastSummary - last ack summary\n */\n updateWithLastSummaryAckInfo(lastSummary: ISummarizeAttempt): void;\n\n /**\n * Records a summary attempt. If the attempt was successfully sent,\n * provide the reference sequence number, otherwise it will be set\n * to the last seen op sequence number.\n * @param referenceSequenceNumber - reference sequence number of sent summary\n */\n recordAttempt(referenceSequenceNumber?: number): void;\n\n /** Mark that the last sent summary attempt has received an ack */\n markLastAttemptAsSuccessful(): void;\n}\n\n/** Responsible for running heuristics determining when to summarize. */\nexport interface ISummarizeHeuristicRunner {\n /** Start specific heuristic trackers (ex: idle timer) */\n start(): void;\n\n /** Runs the heuristics to determine if it should try to summarize */\n run(): void;\n\n /** Runs a different heuristic to check if it should summarize before closing */\n shouldRunLastSummary(): boolean;\n\n /** Disposes of resources */\n dispose(): void;\n}\n\ntype ISummarizeTelemetryRequiredProperties =\n /** Reason code for attempting to summarize */\n \"reason\";\n\ntype ISummarizeTelemetryOptionalProperties =\n /** Number of attempts within the last time window, used for calculating the throttle delay. */\n \"summaryAttempts\" |\n /** Number of attempts within the current phase (currently capped at 2 ) */\n \"summaryAttemptsPerPhase\" |\n /** One-based count of phases we've attempted (used to index into an array of ISummarizeOptions */\n \"summaryAttemptPhase\" |\n keyof ISummarizeOptions;\n\nexport type ISummarizeTelemetryProperties =\n Pick<ITelemetryProperties, ISummarizeTelemetryRequiredProperties> &\n Partial<Pick<ITelemetryProperties, ISummarizeTelemetryOptionalProperties>>;\n\n/** Strategy used to heuristically determine when we should run a summary */\nexport interface ISummaryHeuristicStrategy {\n /** Summarize reason for this summarize heuristic strategy (ex: \"maxTime\") */\n summarizeReason: Readonly<SummarizeReason>;\n\n /**\n * Determines if this strategy's summarize criteria been met\n * @param configuration - summary configuration we are to check against\n * @param heuristicData - heuristic data used to confirm conditions are met\n */\n shouldRunSummary(configuration: ISummaryConfigurationHeuristics, heuristicData: ISummarizeHeuristicData): boolean;\n}\n\ntype SummaryGeneratorRequiredTelemetryProperties =\n /** True to generate the full tree with no handle reuse optimizations */\n \"fullTree\" |\n /** Time since we last attempted to generate a summary */\n \"timeSinceLastAttempt\" |\n /** Time since we last successfully generated a summary */\n \"timeSinceLastSummary\";\n\ntype SummaryGeneratorOptionalTelemetryProperties =\n /** Reference sequence number as of the generate summary attempt. */\n \"referenceSequenceNumber\" |\n /** minimum sequence number (at the reference sequence number) */\n \"minimumSequenceNumber\" |\n /** Delta between the current reference sequence number and the reference sequence number of the last attempt */\n \"opsSinceLastAttempt\" |\n /** Delta between the current reference sequence number and the reference sequence number of the last summary */\n \"opsSinceLastSummary\" |\n /**\n * Delta in sum of op sizes between the current reference sequence number and the reference\n * sequence number of the last summary\n */\n \"opsSizesSinceLastSummary\" |\n /** Delta between the number of non-runtime ops since the last summary */\n \"nonRuntimeOpsSinceLastSummary\" |\n /** Wether or not this instance contains adjusted metrics due to missing op data */\n \"hasMissingOpData\" |\n /** Time it took to generate the summary tree and stats. */\n \"generateDuration\" |\n /** The handle returned by storage pointing to the uploaded summary tree. */\n \"handle\" |\n /** Time it took to upload the summary tree to storage. */\n \"uploadDuration\" |\n /** The client sequence number of the summarize op submitted for the summary. */\n \"clientSequenceNumber\" |\n /** Time it took for this summary to be acked after it was generated */\n \"ackWaitDuration\" |\n /** Reference sequence number of the ack/nack message */\n \"ackNackSequenceNumber\" |\n /** Actual sequence number of the summary op proposal. */\n \"summarySequenceNumber\" |\n /** Optional Retry-After time in seconds. If specified, the client should wait this many seconds before retrying. */\n \"nackRetryAfter\";\n\nexport type SummaryGeneratorTelemetry =\n Pick<ITelemetryProperties, SummaryGeneratorRequiredTelemetryProperties> &\n Partial<Pick<ITelemetryProperties, SummaryGeneratorOptionalTelemetryProperties>>;\n\nexport interface ISummarizeRunnerTelemetry extends ITelemetryLoggerPropertyBag {\n /** Number of times the summarizer run. */\n summarizeCount: () => number;\n /** Number of successful attempts to summarize. */\n summarizerSuccessfulAttempts: () => number;\n}\n"]}