@fluidframework/container-runtime 0.48.5 → 0.49.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/containerRuntime.d.ts +1 -7
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +3 -13
- package/dist/containerRuntime.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +8 -3
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +1 -1
- package/dist/summarizer.js.map +1 -1
- package/dist/summarizerTypes.d.ts +11 -7
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryCollection.d.ts +2 -0
- package/dist/summaryCollection.d.ts.map +1 -1
- package/dist/summaryCollection.js +6 -0
- package/dist/summaryCollection.js.map +1 -1
- package/dist/summaryGenerator.d.ts +5 -5
- package/dist/summaryGenerator.d.ts.map +1 -1
- package/dist/summaryGenerator.js +5 -6
- package/dist/summaryGenerator.js.map +1 -1
- package/dist/summaryManager.d.ts +1 -1
- package/dist/summaryManager.d.ts.map +1 -1
- package/dist/summaryManager.js +23 -12
- package/dist/summaryManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +1 -7
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +3 -13
- package/lib/containerRuntime.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +8 -3
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/summarizer.d.ts.map +1 -1
- package/lib/summarizer.js +1 -1
- package/lib/summarizer.js.map +1 -1
- package/lib/summarizerTypes.d.ts +11 -7
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryCollection.d.ts +2 -0
- package/lib/summaryCollection.d.ts.map +1 -1
- package/lib/summaryCollection.js +6 -0
- package/lib/summaryCollection.js.map +1 -1
- package/lib/summaryGenerator.d.ts +5 -5
- package/lib/summaryGenerator.d.ts.map +1 -1
- package/lib/summaryGenerator.js +6 -7
- package/lib/summaryGenerator.js.map +1 -1
- package/lib/summaryManager.d.ts +1 -1
- package/lib/summaryManager.d.ts.map +1 -1
- package/lib/summaryManager.js +24 -13
- package/lib/summaryManager.js.map +1 -1
- package/package.json +15 -15
- package/src/containerRuntime.ts +3 -12
- package/src/packageVersion.ts +1 -1
- package/src/runningSummarizer.ts +11 -3
- package/src/summarizer.ts +1 -0
- package/src/summarizerTypes.ts +12 -6
- package/src/summaryCollection.ts +8 -0
- package/src/summaryGenerator.ts +18 -11
- package/src/summaryManager.ts +25 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summaryCollection.js","sourceRoot":"","sources":["../src/summaryCollection.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IDisposable, IEvent, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { Deferred, assert, TypedEventEmitter } from \"@fluidframework/common-utils\";\nimport { IDeltaManager } from \"@fluidframework/container-definitions\";\nimport {\n IDocumentMessage,\n ISequencedDocumentMessage,\n ISummaryAck,\n ISummaryContent,\n ISummaryNack,\n MessageType,\n} from \"@fluidframework/protocol-definitions\";\n\n/**\n * Interface for summary op messages with typed contents.\n */\nexport interface ISummaryOpMessage extends ISequencedDocumentMessage {\n type: MessageType.Summarize;\n contents: ISummaryContent;\n}\n\n/**\n * Interface for summary ack messages with typed contents.\n */\nexport interface ISummaryAckMessage extends ISequencedDocumentMessage {\n type: MessageType.SummaryAck;\n contents: ISummaryAck;\n}\n\n/**\n * Interface for summary nack messages with typed contents.\n */\nexport interface ISummaryNackMessage extends ISequencedDocumentMessage {\n type: MessageType.SummaryNack;\n contents: ISummaryNack;\n}\n\n/**\n * A single summary which can be tracked as it goes through its life cycle.\n * The life cycle is: Local to Broadcast to Acked/Nacked.\n */\nexport interface ISummary {\n readonly clientId: string;\n readonly clientSequenceNumber: number;\n waitBroadcast(): Promise<ISummaryOpMessage>;\n waitAckNack(): Promise<ISummaryAckMessage | ISummaryNackMessage>;\n}\n\n/**\n * A single summary which has already been acked by the server.\n */\nexport interface IAckedSummary {\n readonly summaryOp: ISummaryOpMessage;\n readonly summaryAck: ISummaryAckMessage;\n}\n\nenum SummaryState {\n Local = 0,\n Broadcast = 1,\n Acked = 2,\n Nacked = -1,\n}\n\nclass Summary implements ISummary {\n public static createLocal(clientId: string, clientSequenceNumber: number) {\n return new Summary(clientId, clientSequenceNumber);\n }\n public static createFromOp(op: ISummaryOpMessage) {\n const summary = new Summary(op.clientId, op.clientSequenceNumber);\n summary.broadcast(op);\n return summary;\n }\n\n private state = SummaryState.Local;\n\n private _summaryOp?: ISummaryOpMessage;\n private _summaryAckNack?: ISummaryAckMessage | ISummaryNackMessage;\n\n private readonly defSummaryOp = new Deferred<void>();\n private readonly defSummaryAck = new Deferred<void>();\n\n public get summaryOp() { return this._summaryOp; }\n public get summaryAckNack() { return this._summaryAckNack; }\n\n private constructor(\n public readonly clientId: string,\n public readonly clientSequenceNumber: number) { }\n\n public hasBeenAcked(): this is IAckedSummary {\n return this.state === SummaryState.Acked;\n }\n\n public broadcast(op: ISummaryOpMessage) {\n assert(this.state === SummaryState.Local, 0x175 /* \"Can only broadcast if summarizer starts in local state\" */);\n this._summaryOp = op;\n this.defSummaryOp.resolve();\n this.state = SummaryState.Broadcast;\n return true;\n }\n\n public ackNack(op: ISummaryAckMessage | ISummaryNackMessage) {\n assert(this.state === SummaryState.Broadcast,\n 0x176 /* \"Can only ack/nack if summarizer is in broadcasting state\" */);\n this._summaryAckNack = op;\n this.defSummaryAck.resolve();\n this.state = op.type === MessageType.SummaryAck ? SummaryState.Acked : SummaryState.Nacked;\n return true;\n }\n\n public async waitBroadcast(): Promise<ISummaryOpMessage> {\n await this.defSummaryOp.promise;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this._summaryOp!;\n }\n\n public async waitAckNack(): Promise<ISummaryAckMessage | ISummaryNackMessage> {\n await this.defSummaryAck.promise;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this._summaryAckNack!;\n }\n}\n\n/**\n * Watches summaries created by a specific client.\n */\nexport interface IClientSummaryWatcher extends IDisposable {\n watchSummary(clientSequenceNumber: number): ISummary;\n waitFlushed(): Promise<IAckedSummary | undefined>;\n}\n\n/**\n * This class watches summaries created by a specific client.\n * It should be created and managed from a SummaryCollection.\n */\nclass ClientSummaryWatcher implements IClientSummaryWatcher {\n // key: clientSeqNum\n private readonly localSummaries = new Map<number, Summary>();\n private _disposed = false;\n\n public get disposed() { return this._disposed; }\n\n public constructor(\n public readonly clientId: string,\n private readonly summaryCollection: SummaryCollection,\n ) { }\n\n /**\n * Watches for a specific sent summary op.\n * @param clientSequenceNumber - client sequence number of sent summary op\n */\n public watchSummary(clientSequenceNumber: number): ISummary {\n let summary = this.localSummaries.get(clientSequenceNumber);\n if (!summary) {\n summary = Summary.createLocal(this.clientId, clientSequenceNumber);\n this.localSummaries.set(summary.clientSequenceNumber, summary);\n }\n return summary;\n }\n\n /**\n * Waits until all of the pending summaries in the underlying SummaryCollection\n * are acked/nacked.\n */\n // eslint-disable-next-line @typescript-eslint/promise-function-async\n public waitFlushed() {\n return this.summaryCollection.waitFlushed();\n }\n\n /**\n * Gets a watched summary or returns undefined if not watched.\n * @param clientSequenceNumber - client sequence number of sent summary op\n */\n public tryGetSummary(clientSequenceNumber: number) {\n return this.localSummaries.get(clientSequenceNumber);\n }\n\n /**\n * Starts watching a summary made by this client.\n * @param summary - summary to start watching\n */\n public setSummary(summary: Summary) {\n this.localSummaries.set(summary.clientSequenceNumber, summary);\n }\n\n public dispose() {\n this.summaryCollection.removeWatcher(this.clientId);\n this._disposed = true;\n }\n}\n\nexport type OpActionEventName = MessageType.Summarize | MessageType.SummaryAck | MessageType.SummaryNack | \"default\";\nexport type OpActionEventListener = (op: ISequencedDocumentMessage) => void;\nexport interface ISummaryCollectionOpEvents extends IEvent {\n (event: OpActionEventName, listener: OpActionEventListener);\n}\n\n/**\n * Data structure that looks at the op stream to track summaries as they\n * are broadcast, acked and nacked.\n * It provides functionality for watching specific summaries.\n */\nexport class SummaryCollection extends TypedEventEmitter<ISummaryCollectionOpEvents> {\n // key: clientId\n private readonly summaryWatchers = new Map<string, ClientSummaryWatcher>();\n // key: summarySeqNum\n private readonly pendingSummaries = new Map<number, Summary>();\n private refreshWaitNextAck = new Deferred<void>();\n\n private lastSummaryTimestamp: number | undefined;\n private maxAckWaitTime: number | undefined;\n private pendingAckTimerTimeoutCallback: (() => void) | undefined;\n private lastAck: IAckedSummary | undefined;\n\n public get latestAck(): IAckedSummary | undefined { return this.lastAck; }\n\n public emit(event: OpActionEventName, ...args: Parameters<OpActionEventListener>): boolean {\n return super.emit(event, ...args);\n }\n\n public get opsSinceLastAck() {\n return this.deltaManager.lastSequenceNumber -\n (this.lastAck?.summaryAck.sequenceNumber ?? this.deltaManager.initialSequenceNumber);\n }\n\n public constructor(\n private readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n private readonly logger: ITelemetryLogger,\n ) {\n super();\n this.deltaManager.on(\n \"op\",\n (op) => this.handleOp(op));\n }\n\n /**\n * Creates and returns a summary watcher for a specific client.\n * This will allow for local sent summaries to be better tracked.\n * @param clientId - client id for watcher\n */\n public createWatcher(clientId: string): IClientSummaryWatcher {\n const watcher = new ClientSummaryWatcher(clientId, this);\n this.summaryWatchers.set(clientId, watcher);\n return watcher;\n }\n\n public removeWatcher(clientId: string) {\n this.summaryWatchers.delete(clientId);\n }\n\n public setPendingAckTimerTimeoutCallback(maxAckWaitTime: number, timeoutCallback: () => void) {\n this.maxAckWaitTime = maxAckWaitTime;\n this.pendingAckTimerTimeoutCallback = timeoutCallback;\n }\n\n public unsetPendingAckTimerTimeoutCallback() {\n this.maxAckWaitTime = undefined;\n this.pendingAckTimerTimeoutCallback = undefined;\n }\n\n /**\n * Returns a promise that resolves once all pending summary ops\n * have been acked or nacked.\n */\n public async waitFlushed(): Promise<IAckedSummary | undefined> {\n while (this.pendingSummaries.size > 0) {\n // eslint-disable-next-line @typescript-eslint/promise-function-async\n const promises = Array.from(this.pendingSummaries, ([, summary]) => summary.waitAckNack());\n await Promise.all(promises);\n }\n return this.lastAck;\n }\n\n /**\n * Returns a promise that resolves once a summary is acked that has a reference\n * sequence number greater than or equal to the passed in sequence number.\n * @param referenceSequenceNumber - reference sequence number to wait for\n * @returns The latest acked summary\n */\n public async waitSummaryAck(referenceSequenceNumber: number): Promise<IAckedSummary> {\n while (!this.lastAck || this.lastAck.summaryOp.referenceSequenceNumber < referenceSequenceNumber) {\n await this.refreshWaitNextAck.promise;\n }\n return this.lastAck;\n }\n\n /**\n * Handler for ops; only handles ops relating to summaries.\n * @param op - op message to handle\n */\n private handleOp(op: ISequencedDocumentMessage) {\n switch (op.type) {\n case MessageType.Summarize: {\n this.handleSummaryOp(op as ISummaryOpMessage);\n return;\n }\n case MessageType.SummaryAck: {\n this.handleSummaryAck(op as ISummaryAckMessage);\n return;\n }\n case MessageType.SummaryNack: {\n this.handleSummaryNack(op as ISummaryNackMessage);\n return;\n }\n default: {\n // If the difference between timestamp of current op and last summary op is greater than\n // the maxAckWaitTime, then we need to inform summarizer to not wait and summarize\n // immediately as we have already waited for maxAckWaitTime.\n const lastOpTimestamp = op.timestamp;\n if (this.lastSummaryTimestamp !== undefined &&\n this.maxAckWaitTime !== undefined &&\n lastOpTimestamp - this.lastSummaryTimestamp >= this.maxAckWaitTime\n ) {\n this.pendingAckTimerTimeoutCallback?.();\n }\n this.emit(\"default\", op);\n\n return;\n }\n }\n }\n\n private handleSummaryOp(op: ISummaryOpMessage) {\n let summary: Summary | undefined;\n\n // Check if summary already being watched, broadcast if so\n const watcher = this.summaryWatchers.get(op.clientId);\n if (watcher) {\n summary = watcher.tryGetSummary(op.clientSequenceNumber);\n if (summary) {\n summary.broadcast(op);\n }\n }\n\n // If not watched, create from op\n if (!summary) {\n summary = Summary.createFromOp(op);\n if (watcher) {\n watcher.setSummary(summary);\n }\n }\n this.pendingSummaries.set(op.sequenceNumber, summary);\n this.lastSummaryTimestamp = op.timestamp;\n this.emit(MessageType.Summarize, op);\n }\n\n private handleSummaryAck(op: ISummaryAckMessage) {\n const seq = op.contents.summaryProposal.summarySequenceNumber;\n const summary = this.pendingSummaries.get(seq);\n if (!summary || summary.summaryOp === undefined) {\n // Summary ack without an op should be rare. We could fetch the\n // reference sequence number from the snapshot, but instead we\n // will not emit this ack. It should be the case that the summary\n // op that this ack is for is earlier than this file was loaded\n // from. i.e. initialSequenceNumber > summarySequenceNumber.\n // We really don't care about it for now, since it is older than\n // the one we loaded from.\n if (seq >= this.deltaManager.initialSequenceNumber) {\n // Potential causes for it to be later than our initialSequenceNumber\n // are that the summaryOp was nacked then acked, double-acked, or\n // the summarySequenceNumber is incorrect.\n this.logger.sendErrorEvent({\n eventName: \"SummaryAckWithoutOp\",\n sequenceNumber: op.sequenceNumber, // summary ack seq #\n summarySequenceNumber: seq, // missing summary seq #\n initialSequenceNumber: this.deltaManager.initialSequenceNumber,\n });\n }\n return;\n }\n summary.ackNack(op);\n this.pendingSummaries.delete(seq);\n\n // Track latest ack\n if (!this.lastAck || seq > this.lastAck.summaryAck.contents.summaryProposal.summarySequenceNumber) {\n this.lastAck = {\n summaryOp: summary.summaryOp,\n summaryAck: op,\n };\n this.refreshWaitNextAck.resolve();\n this.refreshWaitNextAck = new Deferred<void>();\n this.emit(MessageType.SummaryAck, op);\n }\n }\n\n private handleSummaryNack(op: ISummaryNackMessage) {\n const seq = op.contents.summaryProposal.summarySequenceNumber;\n const summary = this.pendingSummaries.get(seq);\n if (summary) {\n summary.ackNack(op);\n this.pendingSummaries.delete(seq);\n this.emit(MessageType.SummaryNack, op);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"summaryCollection.js","sourceRoot":"","sources":["../src/summaryCollection.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IDisposable, IEvent, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { Deferred, assert, TypedEventEmitter } from \"@fluidframework/common-utils\";\nimport { IDeltaManager } from \"@fluidframework/container-definitions\";\nimport {\n IDocumentMessage,\n ISequencedDocumentMessage,\n ISummaryAck,\n ISummaryContent,\n ISummaryNack,\n MessageType,\n} from \"@fluidframework/protocol-definitions\";\n\n/**\n * Interface for summary op messages with typed contents.\n */\nexport interface ISummaryOpMessage extends ISequencedDocumentMessage {\n type: MessageType.Summarize;\n contents: ISummaryContent;\n}\n\n/**\n * Interface for summary ack messages with typed contents.\n */\nexport interface ISummaryAckMessage extends ISequencedDocumentMessage {\n type: MessageType.SummaryAck;\n contents: ISummaryAck;\n}\n\n/**\n * Interface for summary nack messages with typed contents.\n */\nexport interface ISummaryNackMessage extends ISequencedDocumentMessage {\n type: MessageType.SummaryNack;\n contents: ISummaryNack;\n}\n\n/**\n * A single summary which can be tracked as it goes through its life cycle.\n * The life cycle is: Local to Broadcast to Acked/Nacked.\n */\nexport interface ISummary {\n readonly clientId: string;\n readonly clientSequenceNumber: number;\n waitBroadcast(): Promise<ISummaryOpMessage>;\n waitAckNack(): Promise<ISummaryAckMessage | ISummaryNackMessage>;\n}\n\n/**\n * A single summary which has already been acked by the server.\n */\nexport interface IAckedSummary {\n readonly summaryOp: ISummaryOpMessage;\n readonly summaryAck: ISummaryAckMessage;\n}\n\nenum SummaryState {\n Local = 0,\n Broadcast = 1,\n Acked = 2,\n Nacked = -1,\n}\n\nclass Summary implements ISummary {\n public static createLocal(clientId: string, clientSequenceNumber: number) {\n return new Summary(clientId, clientSequenceNumber);\n }\n public static createFromOp(op: ISummaryOpMessage) {\n const summary = new Summary(op.clientId, op.clientSequenceNumber);\n summary.broadcast(op);\n return summary;\n }\n\n private state = SummaryState.Local;\n\n private _summaryOp?: ISummaryOpMessage;\n private _summaryAckNack?: ISummaryAckMessage | ISummaryNackMessage;\n\n private readonly defSummaryOp = new Deferred<void>();\n private readonly defSummaryAck = new Deferred<void>();\n\n public get summaryOp() { return this._summaryOp; }\n public get summaryAckNack() { return this._summaryAckNack; }\n\n private constructor(\n public readonly clientId: string,\n public readonly clientSequenceNumber: number) { }\n\n public hasBeenAcked(): this is IAckedSummary {\n return this.state === SummaryState.Acked;\n }\n\n public broadcast(op: ISummaryOpMessage) {\n assert(this.state === SummaryState.Local, 0x175 /* \"Can only broadcast if summarizer starts in local state\" */);\n this._summaryOp = op;\n this.defSummaryOp.resolve();\n this.state = SummaryState.Broadcast;\n return true;\n }\n\n public ackNack(op: ISummaryAckMessage | ISummaryNackMessage) {\n assert(this.state === SummaryState.Broadcast,\n 0x176 /* \"Can only ack/nack if summarizer is in broadcasting state\" */);\n this._summaryAckNack = op;\n this.defSummaryAck.resolve();\n this.state = op.type === MessageType.SummaryAck ? SummaryState.Acked : SummaryState.Nacked;\n return true;\n }\n\n public async waitBroadcast(): Promise<ISummaryOpMessage> {\n await this.defSummaryOp.promise;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this._summaryOp!;\n }\n\n public async waitAckNack(): Promise<ISummaryAckMessage | ISummaryNackMessage> {\n await this.defSummaryAck.promise;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this._summaryAckNack!;\n }\n}\n\n/**\n * Watches summaries created by a specific client.\n */\nexport interface IClientSummaryWatcher extends IDisposable {\n watchSummary(clientSequenceNumber: number): ISummary;\n waitFlushed(): Promise<IAckedSummary | undefined>;\n}\n\n/**\n * This class watches summaries created by a specific client.\n * It should be created and managed from a SummaryCollection.\n */\nclass ClientSummaryWatcher implements IClientSummaryWatcher {\n // key: clientSeqNum\n private readonly localSummaries = new Map<number, Summary>();\n private _disposed = false;\n\n public get disposed() { return this._disposed; }\n\n public constructor(\n public readonly clientId: string,\n private readonly summaryCollection: SummaryCollection,\n ) { }\n\n /**\n * Watches for a specific sent summary op.\n * @param clientSequenceNumber - client sequence number of sent summary op\n */\n public watchSummary(clientSequenceNumber: number): ISummary {\n let summary = this.localSummaries.get(clientSequenceNumber);\n if (!summary) {\n summary = Summary.createLocal(this.clientId, clientSequenceNumber);\n this.localSummaries.set(summary.clientSequenceNumber, summary);\n }\n return summary;\n }\n\n /**\n * Waits until all of the pending summaries in the underlying SummaryCollection\n * are acked/nacked.\n */\n // eslint-disable-next-line @typescript-eslint/promise-function-async\n public waitFlushed() {\n return this.summaryCollection.waitFlushed();\n }\n\n /**\n * Gets a watched summary or returns undefined if not watched.\n * @param clientSequenceNumber - client sequence number of sent summary op\n */\n public tryGetSummary(clientSequenceNumber: number) {\n return this.localSummaries.get(clientSequenceNumber);\n }\n\n /**\n * Starts watching a summary made by this client.\n * @param summary - summary to start watching\n */\n public setSummary(summary: Summary) {\n this.localSummaries.set(summary.clientSequenceNumber, summary);\n }\n\n public dispose() {\n this.summaryCollection.removeWatcher(this.clientId);\n this._disposed = true;\n }\n}\n\nexport type OpActionEventName = MessageType.Summarize | MessageType.SummaryAck | MessageType.SummaryNack | \"default\";\nexport type OpActionEventListener = (op: ISequencedDocumentMessage) => void;\nexport interface ISummaryCollectionOpEvents extends IEvent {\n (event: OpActionEventName, listener: OpActionEventListener);\n}\n\n/**\n * Data structure that looks at the op stream to track summaries as they\n * are broadcast, acked and nacked.\n * It provides functionality for watching specific summaries.\n */\nexport class SummaryCollection extends TypedEventEmitter<ISummaryCollectionOpEvents> {\n // key: clientId\n private readonly summaryWatchers = new Map<string, ClientSummaryWatcher>();\n // key: summarySeqNum\n private readonly pendingSummaries = new Map<number, Summary>();\n private refreshWaitNextAck = new Deferred<void>();\n\n private lastSummaryTimestamp: number | undefined;\n private maxAckWaitTime: number | undefined;\n private pendingAckTimerTimeoutCallback: (() => void) | undefined;\n private lastAck: IAckedSummary | undefined;\n\n public get latestAck(): IAckedSummary | undefined { return this.lastAck; }\n\n public emit(event: OpActionEventName, ...args: Parameters<OpActionEventListener>): boolean {\n return super.emit(event, ...args);\n }\n\n public get opsSinceLastAck() {\n return this.deltaManager.lastSequenceNumber -\n (this.lastAck?.summaryAck.sequenceNumber ?? this.deltaManager.initialSequenceNumber);\n }\n\n public addOpListener(listener: () => void) {\n this.deltaManager.on(\"op\", listener);\n }\n\n public removeOpListener(listener: () => void) {\n this.deltaManager.off(\"op\", listener);\n }\n\n public constructor(\n private readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n private readonly logger: ITelemetryLogger,\n ) {\n super();\n this.deltaManager.on(\n \"op\",\n (op) => this.handleOp(op));\n }\n\n /**\n * Creates and returns a summary watcher for a specific client.\n * This will allow for local sent summaries to be better tracked.\n * @param clientId - client id for watcher\n */\n public createWatcher(clientId: string): IClientSummaryWatcher {\n const watcher = new ClientSummaryWatcher(clientId, this);\n this.summaryWatchers.set(clientId, watcher);\n return watcher;\n }\n\n public removeWatcher(clientId: string) {\n this.summaryWatchers.delete(clientId);\n }\n\n public setPendingAckTimerTimeoutCallback(maxAckWaitTime: number, timeoutCallback: () => void) {\n this.maxAckWaitTime = maxAckWaitTime;\n this.pendingAckTimerTimeoutCallback = timeoutCallback;\n }\n\n public unsetPendingAckTimerTimeoutCallback() {\n this.maxAckWaitTime = undefined;\n this.pendingAckTimerTimeoutCallback = undefined;\n }\n\n /**\n * Returns a promise that resolves once all pending summary ops\n * have been acked or nacked.\n */\n public async waitFlushed(): Promise<IAckedSummary | undefined> {\n while (this.pendingSummaries.size > 0) {\n // eslint-disable-next-line @typescript-eslint/promise-function-async\n const promises = Array.from(this.pendingSummaries, ([, summary]) => summary.waitAckNack());\n await Promise.all(promises);\n }\n return this.lastAck;\n }\n\n /**\n * Returns a promise that resolves once a summary is acked that has a reference\n * sequence number greater than or equal to the passed in sequence number.\n * @param referenceSequenceNumber - reference sequence number to wait for\n * @returns The latest acked summary\n */\n public async waitSummaryAck(referenceSequenceNumber: number): Promise<IAckedSummary> {\n while (!this.lastAck || this.lastAck.summaryOp.referenceSequenceNumber < referenceSequenceNumber) {\n await this.refreshWaitNextAck.promise;\n }\n return this.lastAck;\n }\n\n /**\n * Handler for ops; only handles ops relating to summaries.\n * @param op - op message to handle\n */\n private handleOp(op: ISequencedDocumentMessage) {\n switch (op.type) {\n case MessageType.Summarize: {\n this.handleSummaryOp(op as ISummaryOpMessage);\n return;\n }\n case MessageType.SummaryAck: {\n this.handleSummaryAck(op as ISummaryAckMessage);\n return;\n }\n case MessageType.SummaryNack: {\n this.handleSummaryNack(op as ISummaryNackMessage);\n return;\n }\n default: {\n // If the difference between timestamp of current op and last summary op is greater than\n // the maxAckWaitTime, then we need to inform summarizer to not wait and summarize\n // immediately as we have already waited for maxAckWaitTime.\n const lastOpTimestamp = op.timestamp;\n if (this.lastSummaryTimestamp !== undefined &&\n this.maxAckWaitTime !== undefined &&\n lastOpTimestamp - this.lastSummaryTimestamp >= this.maxAckWaitTime\n ) {\n this.pendingAckTimerTimeoutCallback?.();\n }\n this.emit(\"default\", op);\n\n return;\n }\n }\n }\n\n private handleSummaryOp(op: ISummaryOpMessage) {\n let summary: Summary | undefined;\n\n // Check if summary already being watched, broadcast if so\n const watcher = this.summaryWatchers.get(op.clientId);\n if (watcher) {\n summary = watcher.tryGetSummary(op.clientSequenceNumber);\n if (summary) {\n summary.broadcast(op);\n }\n }\n\n // If not watched, create from op\n if (!summary) {\n summary = Summary.createFromOp(op);\n if (watcher) {\n watcher.setSummary(summary);\n }\n }\n this.pendingSummaries.set(op.sequenceNumber, summary);\n this.lastSummaryTimestamp = op.timestamp;\n this.emit(MessageType.Summarize, op);\n }\n\n private handleSummaryAck(op: ISummaryAckMessage) {\n const seq = op.contents.summaryProposal.summarySequenceNumber;\n const summary = this.pendingSummaries.get(seq);\n if (!summary || summary.summaryOp === undefined) {\n // Summary ack without an op should be rare. We could fetch the\n // reference sequence number from the snapshot, but instead we\n // will not emit this ack. It should be the case that the summary\n // op that this ack is for is earlier than this file was loaded\n // from. i.e. initialSequenceNumber > summarySequenceNumber.\n // We really don't care about it for now, since it is older than\n // the one we loaded from.\n if (seq >= this.deltaManager.initialSequenceNumber) {\n // Potential causes for it to be later than our initialSequenceNumber\n // are that the summaryOp was nacked then acked, double-acked, or\n // the summarySequenceNumber is incorrect.\n this.logger.sendErrorEvent({\n eventName: \"SummaryAckWithoutOp\",\n sequenceNumber: op.sequenceNumber, // summary ack seq #\n summarySequenceNumber: seq, // missing summary seq #\n initialSequenceNumber: this.deltaManager.initialSequenceNumber,\n });\n }\n return;\n }\n summary.ackNack(op);\n this.pendingSummaries.delete(seq);\n\n // Track latest ack\n if (!this.lastAck || seq > this.lastAck.summaryAck.contents.summaryProposal.summarySequenceNumber) {\n this.lastAck = {\n summaryOp: summary.summaryOp,\n summaryAck: op,\n };\n this.refreshWaitNextAck.resolve();\n this.refreshWaitNextAck = new Deferred<void>();\n this.emit(MessageType.SummaryAck, op);\n }\n }\n\n private handleSummaryNack(op: ISummaryNackMessage) {\n const seq = op.contents.summaryProposal.summarySequenceNumber;\n const summary = this.pendingSummaries.get(seq);\n if (summary) {\n summary.ackNack(op);\n this.pendingSummaries.delete(seq);\n this.emit(MessageType.SummaryNack, op);\n }\n }\n}\n"]}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { ITelemetryLogger, ITelemetryProperties } from "@fluidframework/common-definitions";
|
|
6
6
|
import { Deferred, IPromiseTimer, IPromiseTimerResult } from "@fluidframework/common-utils";
|
|
7
|
-
import {
|
|
7
|
+
import { IAckSummaryResult, INackSummaryResult, ISummarizeOptions, IBroadcastSummaryResult, ISummarizeResults, ISummarizeHeuristicData, ISubmitSummaryOptions, SubmitSummaryResult, SummarizeResultPart, ISummaryCancellationToken } from "./summarizerTypes";
|
|
8
8
|
import { IClientSummaryWatcher } from "./summaryCollection";
|
|
9
9
|
export declare type raceTimerResult<T> = {
|
|
10
10
|
result: "done";
|
|
@@ -58,10 +58,10 @@ export declare type SummarizeReason =
|
|
|
58
58
|
/** Enqueue summarize attempt with specified reason. */
|
|
59
59
|
| `enqueue;${string}`;
|
|
60
60
|
export declare class SummarizeResultBuilder {
|
|
61
|
-
readonly summarySubmitted: Deferred<SummarizeResultPart<SubmitSummaryResult>>;
|
|
62
|
-
readonly summaryOpBroadcasted: Deferred<SummarizeResultPart<IBroadcastSummaryResult>>;
|
|
63
|
-
readonly receivedSummaryAckOrNack: Deferred<SummarizeResultPart<
|
|
64
|
-
fail(message: string, error: any, nackSummaryResult?:
|
|
61
|
+
readonly summarySubmitted: Deferred<SummarizeResultPart<SubmitSummaryResult, undefined>>;
|
|
62
|
+
readonly summaryOpBroadcasted: Deferred<SummarizeResultPart<IBroadcastSummaryResult, undefined>>;
|
|
63
|
+
readonly receivedSummaryAckOrNack: Deferred<SummarizeResultPart<IAckSummaryResult, INackSummaryResult>>;
|
|
64
|
+
fail(message: string, error: any, nackSummaryResult?: INackSummaryResult, retryAfterSeconds?: number): void;
|
|
65
65
|
build(): ISummarizeResults;
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summaryGenerator.d.ts","sourceRoot":"","sources":["../src/summaryGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC5F,OAAO,
|
|
1
|
+
{"version":3,"file":"summaryGenerator.d.ts","sourceRoot":"","sources":["../src/summaryGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC5F,OAAO,EAEH,QAAQ,EACR,aAAa,EACb,mBAAmB,EAEtB,MAAM,8BAA8B,CAAC;AAItC,OAAO,EACH,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,oBAAY,eAAe,CAAC,CAAC,IACzB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAC5B;IAAE,MAAM,EAAE,mBAAmB,CAAC,aAAa,CAAC,CAAA;CAAE,GAC9C;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC;AAE5B,uEAAuE;AACvE,wBAAsB,SAAS,CAAC,CAAC,EAC7B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,KAAK,EAAE,OAAO,CAAC,mBAAmB,CAAC,EACnC,iBAAiB,CAAC,EAAE,yBAAyB,GAC9C,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAS7B;AAMD,oBAAY,eAAe;AACvB;;;;;GAKG;AACD,MAAM;AACR;;;;GAIG;GACD,SAAS;AACX;;;;;;GAMG;GACD,QAAQ;AACV;;;GAGG;GACD,QAAQ,MAAM,KAAK,MAAM,EAAE;AAC7B;;;;;;GAMG;GACD,aAAa;AACf,4DAA4D;GAC1D,QAAQ,MAAM,EAAE;AAClB,yDAAyD;GACvD,YAAY,MAAM,EAAE;AACtB,uDAAuD;GACrD,WAAW,MAAM,EAAE,CAAC;AA6B1B,qBAAa,sBAAsB;IAC/B,SAAgB,gBAAgB,gEAA4D;IAC5F,SAAgB,oBAAoB,oEAAgE;IACpG,SAAgB,wBAAwB,uEACuC;IAExE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,iBAAiB,CAAC,EAAE,kBAAkB,EAAE,iBAAiB,CAAC,EAAE,MAAM;IAUpG,KAAK,IAAI,iBAAiB;CAOpC;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAGrB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAP3B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;gBAElB,eAAe,EAAE,aAAa,EAC9B,aAAa,EAAE,uBAAuB,EACtC,qBAAqB,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,OAAO,CAAC,mBAAmB,CAAC,EACvF,qBAAqB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,EAClD,cAAc,EAAE,IAAI,CAAC,qBAAqB,EAAE,cAAc,CAAC,EAC3D,MAAM,EAAE,gBAAgB;IAQ7C;;;;;;OAMG;IACI,SAAS,CACZ,cAAc,EAAE,oBAAoB,EACpC,OAAO,EAAE,iBAAiB,EAC1B,iBAAiB,EAAE,yBAAyB,EAC5C,cAAc,yBAA+B,GAC9C,iBAAiB;YAWN,aAAa;IA8K3B,OAAO,CAAC,qBAAqB;IAatB,OAAO;CAGjB"}
|
package/lib/summaryGenerator.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { assert, Deferred, Timer } from "@fluidframework/common-utils";
|
|
5
|
+
import { assert, Deferred, Timer, } from "@fluidframework/common-utils";
|
|
6
6
|
import { MessageType } from "@fluidframework/protocol-definitions";
|
|
7
7
|
import { PerformanceEvent, LoggingError, ChildLogger } from "@fluidframework/telemetry-utils";
|
|
8
8
|
import { getRetryDelaySecondsFromError } from "@fluidframework/driver-utils";
|
|
@@ -205,23 +205,22 @@ export class SummaryGenerator {
|
|
|
205
205
|
this.heuristicData.markLastAttemptAsSuccessful();
|
|
206
206
|
summarizeEvent.end(Object.assign(Object.assign({}, telemetryProps), { handle: ackNackOp.contents.handle, message: "summaryAck" }));
|
|
207
207
|
resultsBuilder.receivedSummaryAckOrNack.resolve({ success: true, data: {
|
|
208
|
-
|
|
208
|
+
summaryAckOp: ackNackOp,
|
|
209
209
|
ackNackDuration,
|
|
210
210
|
} });
|
|
211
211
|
}
|
|
212
212
|
else {
|
|
213
213
|
// Check for retryDelay in summaryNack response.
|
|
214
214
|
// back-compat: cast needed until dep on protocol-definitions version bump
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const message = (_a = ackNackOp.contents.message) !== null && _a !== void 0 ? _a : ackNackOp.contents.errorMessage;
|
|
215
|
+
assert(ackNackOp.type === MessageType.SummaryNack, 0x274 /* "type check" */);
|
|
216
|
+
const summaryNack = ackNackOp.contents;
|
|
217
|
+
const message = (_a = summaryNack.message) !== null && _a !== void 0 ? _a : ackNackOp.contents.errorMessage;
|
|
219
218
|
const retryAfterSeconds = summaryNack === null || summaryNack === void 0 ? void 0 : summaryNack.retryAfter;
|
|
220
219
|
const error = new LoggingError(`summaryNack: ${message}`, { retryAfterSeconds });
|
|
221
220
|
logger.sendErrorEvent(Object.assign(Object.assign({ eventName: "SummaryNack" }, generateTelemetryProps), { retryAfterSeconds }), error);
|
|
222
221
|
assert(getRetryDelaySecondsFromError(error) === retryAfterSeconds, 0x25f /* "retryAfterSeconds" */);
|
|
223
222
|
// This will only set resultsBuilder.receivedSummaryAckOrNack, as other promises are already set.
|
|
224
|
-
return fail("summaryNack", error, Object.assign(Object.assign({}, telemetryProps), { nackRetryAfter: retryAfterSeconds }), {
|
|
223
|
+
return fail("summaryNack", error, Object.assign(Object.assign({}, telemetryProps), { nackRetryAfter: retryAfterSeconds }), { summaryNackOp: ackNackOp, ackNackDuration });
|
|
225
224
|
}
|
|
226
225
|
}
|
|
227
226
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summaryGenerator.js","sourceRoot":"","sources":["../src/summaryGenerator.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger, ITelemetryProperties } from \"@fluidframework/common-definitions\";\nimport { assert, Deferred, IPromiseTimer, IPromiseTimerResult, Timer } from \"@fluidframework/common-utils\";\nimport { MessageType } from \"@fluidframework/protocol-definitions\";\nimport { PerformanceEvent, LoggingError, ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { getRetryDelaySecondsFromError } from \"@fluidframework/driver-utils\";\nimport {\n IAckNackSummaryResult,\n ISummarizeOptions,\n IBroadcastSummaryResult,\n ISummarizeResults,\n ISummarizeHeuristicData,\n ISubmitSummaryOptions,\n SubmitSummaryResult,\n SummarizeResultPart,\n ISummaryCancellationToken,\n} from \"./summarizerTypes\";\nimport { IClientSummaryWatcher } from \"./summaryCollection\";\n\nexport type raceTimerResult<T> =\n { result: \"done\"; value: T } |\n { result: IPromiseTimerResult[\"timerResult\"] } |\n { result: \"cancelled\" };\n\n/** Helper function to wait for a promise or PromiseTimer to elapse. */\nexport async function raceTimer<T>(\n promise: Promise<T>,\n timer: Promise<IPromiseTimerResult>,\n cancellationToken?: ISummaryCancellationToken,\n): Promise<raceTimerResult<T>> {\n const promises: Promise<raceTimerResult<T>>[] = [\n promise.then((value) => ({ result: \"done\", value } as const)),\n timer.then(({ timerResult: result }) => ({ result } as const)),\n ];\n if (cancellationToken !== undefined) {\n promises.push(cancellationToken.waitCancelled.then(() => ({ result: \"cancelled\" } as const)));\n }\n return Promise.race(promises);\n}\n\n// Send some telemetry if generate summary takes too long\nconst maxSummarizeTimeoutTime = 20000; // 20 sec\nconst maxSummarizeTimeoutCount = 5; // Double and resend 5 times\n\nexport type SummarizeReason =\n /**\n * Attempt to summarize after idle timeout has elapsed.\n * Idle timer restarts whenever an op is received. So this\n * triggers only after some amount of time has passed with\n * no ops being received.\n */\n | \"idle\"\n /**\n * Attempt to summarize after a maximum time since last\n * successful summary has passed. This measures time since\n * last summary ack op was processed.\n */\n | \"maxTime\"\n /**\n * Attempt to summarize after a maximum number of ops have\n * passed since the last successful summary. This compares\n * op sequence numbers with the reference sequence number\n * of the summarize op corresponding to the last summary\n * ack op.\n */\n | \"maxOps\"\n /**\n * Special case to generate a summary in response to a Save op.\n * @deprecated - do not use save ops\n */\n | `save;${string}: ${string}`\n /**\n * Special case to attempt to summarize one last time before the\n * summarizer client closes itself. This is to prevent cases where\n * the summarizer client never gets a chance to summarize, because\n * there are too many outstanding ops and/or parent client cannot\n * stay connected long enough for summarizer client to catch up.\n */\n | \"lastSummary\"\n /** Previous summary attempt failed, and we are retrying. */\n | `retry${number}`\n /** On-demand summary requested with specified reason. */\n | `onDemand;${string}`\n /** Enqueue summarize attempt with specified reason. */\n | `enqueue;${string}`;\n\nconst summarizeErrors = {\n /**\n * Error encountered while generating the summary tree, uploading\n * it to storage, or submitting the op. It could be a result of\n * the client becoming disconnected while generating or an actual error.\n */\n submitSummaryFailure: \"Error while generating, uploading, or submitting summary\",\n /**\n * The summaryAckWaitTimeout time has elapsed before receiving the summarize op\n * sent by this summarize attempt. It is expected to be broadcast quickly.\n */\n summaryOpWaitTimeout: \"Timeout while waiting for summarize op broadcast\",\n /**\n * The summaryAckWaitTimeout time has elapsed before receiving either a\n * summaryAck or summaryNack op from the server in response to this\n * summarize attempt. It is expected that the server should respond.\n */\n summaryAckWaitTimeout: \"Timeout while waiting for summaryAck/summaryNack op\",\n /**\n * The server responded with a summaryNack op, thus rejecting this\n * summarize attempt.\n */\n summaryNack: \"Server rejected summary via summaryNack op\",\n\n disconnect: \"Summary cancelled due to summarizer or main client disconnect\",\n} as const;\n\nexport class SummarizeResultBuilder {\n public readonly summarySubmitted = new Deferred<SummarizeResultPart<SubmitSummaryResult>>();\n public readonly summaryOpBroadcasted = new Deferred<SummarizeResultPart<IBroadcastSummaryResult>>();\n public readonly receivedSummaryAckOrNack = new Deferred<SummarizeResultPart<IAckNackSummaryResult>>();\n\n public fail(message: string, error: any, nackSummaryResult?: IAckNackSummaryResult, retryAfterSeconds?: number) {\n assert(!this.receivedSummaryAckOrNack.isCompleted,\n 0x25e /* \"no reason to call fail if all promises have been completed\" */);\n\n const result: SummarizeResultPart<undefined> =\n { success: false, message, data: undefined, error, retryAfterSeconds } as const;\n this.summarySubmitted.resolve(result);\n this.summaryOpBroadcasted.resolve(result);\n this.receivedSummaryAckOrNack.resolve({ ...result, data: nackSummaryResult });\n }\n public build(): ISummarizeResults {\n return {\n summarySubmitted: this.summarySubmitted.promise,\n summaryOpBroadcasted: this.summaryOpBroadcasted.promise,\n receivedSummaryAckOrNack: this.receivedSummaryAckOrNack.promise,\n } as const;\n }\n}\n\n/**\n * This class generates and tracks a summary attempt.\n */\nexport class SummaryGenerator {\n private readonly summarizeTimer: Timer;\n constructor(\n private readonly pendingAckTimer: IPromiseTimer,\n private readonly heuristicData: ISummarizeHeuristicData,\n private readonly submitSummaryCallback: (options: ISubmitSummaryOptions) => Promise<SubmitSummaryResult>,\n private readonly raiseSummarizingError: (errorCode: string) => void,\n private readonly summaryWatcher: Pick<IClientSummaryWatcher, \"watchSummary\">,\n private readonly logger: ITelemetryLogger,\n ) {\n this.summarizeTimer = new Timer(\n maxSummarizeTimeoutTime,\n () => this.summarizeTimerHandler(maxSummarizeTimeoutTime, 1),\n );\n }\n\n /**\n * Generates summary and listens for broadcast and ack/nack.\n * Returns true for ack, false for nack, and undefined for failure or timeout.\n * @param reason - reason for summarizing\n * @param options - refreshLatestAck to fetch summary ack info from server,\n * fullTree to generate tree without any summary handles even if unchanged\n */\n public summarize(\n summarizeProps: ITelemetryProperties,\n options: ISummarizeOptions,\n cancellationToken: ISummaryCancellationToken,\n resultsBuilder = new SummarizeResultBuilder(),\n ): ISummarizeResults {\n this.summarizeCore(summarizeProps, options, resultsBuilder, cancellationToken)\n .catch((error) => {\n const message = \"UnexpectedSummarizeError\";\n this.logger.sendErrorEvent({ eventName: message, ...summarizeProps }, error);\n resultsBuilder.fail(message, error);\n });\n\n return resultsBuilder.build();\n }\n\n private async summarizeCore(\n summarizeProps: ITelemetryProperties,\n options: ISummarizeOptions,\n resultsBuilder: SummarizeResultBuilder,\n cancellationToken: ISummaryCancellationToken,\n ): Promise<void> {\n const { refreshLatestAck, fullTree } = options;\n const logger = ChildLogger.create(this.logger, undefined, { all: summarizeProps });\n const summarizeEvent = PerformanceEvent.start(logger, {\n eventName: \"Summarize\",\n refreshLatestAck,\n fullTree,\n timeSinceLastAttempt: Date.now() - this.heuristicData.lastAttempt.summaryTime,\n timeSinceLastSummary: Date.now() - this.heuristicData.lastSuccessfulSummary.summaryTime,\n });\n // Helper functions to report failures and return.\n const getFailMessage =\n (errorCode: keyof typeof summarizeErrors) => `${errorCode}: ${summarizeErrors[errorCode]}`;\n const fail = (\n errorCode: keyof typeof summarizeErrors,\n error?: any,\n properties?: ITelemetryProperties,\n nackSummaryResult?: IAckNackSummaryResult,\n ) => {\n this.raiseSummarizingError(summarizeErrors[errorCode]);\n // UploadSummary may fail with 429 and retryAfter - respect that\n // Summary Nack also can have retryAfter, it's parsed below and comes as a property.\n const retryAfterSeconds = getRetryDelaySecondsFromError(error);\n\n // Report any failure as an error unless it was due to cancellation (like \"disconnected\" error)\n summarizeEvent.cancel({\n ...properties,\n reason: errorCode,\n category: cancellationToken.cancelled ? \"generic\" : \"error\",\n retryAfterSeconds,\n }, error);\n resultsBuilder.fail(getFailMessage(errorCode), error, nackSummaryResult, retryAfterSeconds);\n };\n\n // Wait to generate and send summary\n this.summarizeTimer.start();\n // Use record type to prevent unexpected value types\n let summaryData: SubmitSummaryResult | undefined;\n let generateTelemetryProps: Record<string, string | number | boolean | undefined> = {};\n try {\n summaryData = await this.submitSummaryCallback({\n fullTree,\n refreshLatestAck,\n summaryLogger: logger,\n cancellationToken,\n });\n\n // Cumulatively add telemetry properties based on how far generateSummary went.\n const { referenceSequenceNumber: refSequenceNumber } = summaryData;\n generateTelemetryProps = {\n refSequenceNumber,\n opsSinceLastAttempt: refSequenceNumber - this.heuristicData.lastAttempt.refSequenceNumber,\n opsSinceLastSummary: refSequenceNumber - this.heuristicData.lastSuccessfulSummary.refSequenceNumber,\n };\n if (summaryData.stage !== \"base\") {\n generateTelemetryProps = {\n ...generateTelemetryProps,\n ...summaryData.summaryStats,\n generateDuration: summaryData.generateDuration,\n };\n\n if (summaryData.stage !== \"generate\") {\n generateTelemetryProps = {\n ...generateTelemetryProps,\n handle: summaryData.handle,\n uploadDuration: summaryData.uploadDuration,\n };\n\n if (summaryData.stage !== \"upload\") {\n generateTelemetryProps = {\n ...generateTelemetryProps,\n clientSequenceNumber: summaryData.clientSequenceNumber,\n };\n }\n }\n }\n\n if (summaryData.stage !== \"submit\") {\n return fail(\"submitSummaryFailure\", summaryData.error, generateTelemetryProps);\n }\n\n // Log event here on summary success only, as Summarize_cancel duplicates failure logging.\n logger.sendTelemetryEvent({ eventName: \"GenerateSummary\", ...generateTelemetryProps });\n resultsBuilder.summarySubmitted.resolve({ success: true, data: summaryData });\n } catch (error) {\n return fail(\"submitSummaryFailure\", error);\n } finally {\n this.heuristicData.recordAttempt(summaryData?.referenceSequenceNumber);\n this.summarizeTimer.clear();\n }\n\n try {\n const pendingTimeoutP = this.pendingAckTimer.start();\n const summary = this.summaryWatcher.watchSummary(summaryData.clientSequenceNumber);\n\n // Wait for broadcast\n const waitBroadcastResult = await raceTimer(summary.waitBroadcast(), pendingTimeoutP, cancellationToken);\n if (waitBroadcastResult.result === \"cancelled\") {\n return fail(\"disconnect\");\n }\n if (waitBroadcastResult.result !== \"done\") {\n return fail(\"summaryOpWaitTimeout\");\n }\n const summarizeOp = waitBroadcastResult.value;\n\n const broadcastDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n resultsBuilder.summaryOpBroadcasted.resolve({\n success: true,\n data: { summarizeOp, broadcastDuration },\n });\n this.heuristicData.lastAttempt.summarySequenceNumber = summarizeOp.sequenceNumber;\n logger.sendTelemetryEvent({\n eventName: \"SummaryOp\",\n duration: broadcastDuration,\n refSequenceNumber: summarizeOp.referenceSequenceNumber,\n summarySequenceNumber: summarizeOp.sequenceNumber,\n handle: summarizeOp.contents.handle,\n });\n\n // Wait for ack/nack\n const waitAckNackResult = await raceTimer(summary.waitAckNack(), pendingTimeoutP, cancellationToken);\n if (waitAckNackResult.result === \"cancelled\") {\n return fail(\"disconnect\");\n }\n if (waitAckNackResult.result !== \"done\") {\n return fail(\"summaryAckWaitTimeout\");\n }\n const ackNackOp = waitAckNackResult.value;\n this.pendingAckTimer.clear();\n\n // Update for success/failure\n const ackNackDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n const telemetryProps: Record<string, number> = {\n ackWaitDuration: ackNackDuration,\n sequenceNumber: ackNackOp.sequenceNumber,\n summarySequenceNumber: ackNackOp.contents.summaryProposal.summarySequenceNumber,\n };\n if (ackNackOp.type === MessageType.SummaryAck) {\n this.heuristicData.markLastAttemptAsSuccessful();\n summarizeEvent.end({ ...telemetryProps, handle: ackNackOp.contents.handle, message: \"summaryAck\" });\n resultsBuilder.receivedSummaryAckOrNack.resolve({ success: true, data: {\n summaryAckNackOp: ackNackOp,\n ackNackDuration,\n }});\n } else {\n // Check for retryDelay in summaryNack response.\n // back-compat: cast needed until dep on protocol-definitions version bump\n const summaryNack = ackNackOp.type === MessageType.SummaryNack\n ? ackNackOp.contents as { message?: string; retryAfter?: number; }\n : undefined;\n const message = (ackNackOp.contents as { message?: string }).message ?? ackNackOp.contents.errorMessage;\n const retryAfterSeconds = summaryNack?.retryAfter;\n\n const error = new LoggingError(`summaryNack: ${message}`, { retryAfterSeconds });\n logger.sendErrorEvent(\n { eventName: \"SummaryNack\", ...generateTelemetryProps, retryAfterSeconds }, error);\n assert(getRetryDelaySecondsFromError(error) === retryAfterSeconds, 0x25f /* \"retryAfterSeconds\" */);\n // This will only set resultsBuilder.receivedSummaryAckOrNack, as other promises are already set.\n return fail(\n \"summaryNack\",\n error,\n { ...telemetryProps, nackRetryAfter: retryAfterSeconds },\n { summaryAckNackOp: ackNackOp, ackNackDuration },\n );\n }\n } finally {\n this.pendingAckTimer.clear();\n }\n }\n\n private summarizeTimerHandler(time: number, count: number) {\n this.logger.sendPerformanceEvent({\n eventName: \"SummarizeTimeout\",\n timeoutTime: time,\n timeoutCount: count,\n });\n if (count < maxSummarizeTimeoutCount) {\n // Double and start a new timer\n const nextTime = time * 2;\n this.summarizeTimer.start(nextTime, () => this.summarizeTimerHandler(nextTime, count + 1));\n }\n }\n\n public dispose() {\n this.summarizeTimer.clear();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"summaryGenerator.js","sourceRoot":"","sources":["../src/summaryGenerator.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger, ITelemetryProperties } from \"@fluidframework/common-definitions\";\nimport {\n assert,\n Deferred,\n IPromiseTimer,\n IPromiseTimerResult,\n Timer,\n} from \"@fluidframework/common-utils\";\nimport { MessageType } from \"@fluidframework/protocol-definitions\";\nimport { PerformanceEvent, LoggingError, ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { getRetryDelaySecondsFromError } from \"@fluidframework/driver-utils\";\nimport {\n IAckSummaryResult,\n INackSummaryResult,\n ISummarizeOptions,\n IBroadcastSummaryResult,\n ISummarizeResults,\n ISummarizeHeuristicData,\n ISubmitSummaryOptions,\n SubmitSummaryResult,\n SummarizeResultPart,\n ISummaryCancellationToken,\n} from \"./summarizerTypes\";\nimport { IClientSummaryWatcher } from \"./summaryCollection\";\n\nexport type raceTimerResult<T> =\n { result: \"done\"; value: T } |\n { result: IPromiseTimerResult[\"timerResult\"] } |\n { result: \"cancelled\" };\n\n/** Helper function to wait for a promise or PromiseTimer to elapse. */\nexport async function raceTimer<T>(\n promise: Promise<T>,\n timer: Promise<IPromiseTimerResult>,\n cancellationToken?: ISummaryCancellationToken,\n): Promise<raceTimerResult<T>> {\n const promises: Promise<raceTimerResult<T>>[] = [\n promise.then((value) => ({ result: \"done\", value } as const)),\n timer.then(({ timerResult: result }) => ({ result } as const)),\n ];\n if (cancellationToken !== undefined) {\n promises.push(cancellationToken.waitCancelled.then(() => ({ result: \"cancelled\" } as const)));\n }\n return Promise.race(promises);\n}\n\n// Send some telemetry if generate summary takes too long\nconst maxSummarizeTimeoutTime = 20000; // 20 sec\nconst maxSummarizeTimeoutCount = 5; // Double and resend 5 times\n\nexport type SummarizeReason =\n /**\n * Attempt to summarize after idle timeout has elapsed.\n * Idle timer restarts whenever an op is received. So this\n * triggers only after some amount of time has passed with\n * no ops being received.\n */\n | \"idle\"\n /**\n * Attempt to summarize after a maximum time since last\n * successful summary has passed. This measures time since\n * last summary ack op was processed.\n */\n | \"maxTime\"\n /**\n * Attempt to summarize after a maximum number of ops have\n * passed since the last successful summary. This compares\n * op sequence numbers with the reference sequence number\n * of the summarize op corresponding to the last summary\n * ack op.\n */\n | \"maxOps\"\n /**\n * Special case to generate a summary in response to a Save op.\n * @deprecated - do not use save ops\n */\n | `save;${string}: ${string}`\n /**\n * Special case to attempt to summarize one last time before the\n * summarizer client closes itself. This is to prevent cases where\n * the summarizer client never gets a chance to summarize, because\n * there are too many outstanding ops and/or parent client cannot\n * stay connected long enough for summarizer client to catch up.\n */\n | \"lastSummary\"\n /** Previous summary attempt failed, and we are retrying. */\n | `retry${number}`\n /** On-demand summary requested with specified reason. */\n | `onDemand;${string}`\n /** Enqueue summarize attempt with specified reason. */\n | `enqueue;${string}`;\n\nconst summarizeErrors = {\n /**\n * Error encountered while generating the summary tree, uploading\n * it to storage, or submitting the op. It could be a result of\n * the client becoming disconnected while generating or an actual error.\n */\n submitSummaryFailure: \"Error while generating, uploading, or submitting summary\",\n /**\n * The summaryAckWaitTimeout time has elapsed before receiving the summarize op\n * sent by this summarize attempt. It is expected to be broadcast quickly.\n */\n summaryOpWaitTimeout: \"Timeout while waiting for summarize op broadcast\",\n /**\n * The summaryAckWaitTimeout time has elapsed before receiving either a\n * summaryAck or summaryNack op from the server in response to this\n * summarize attempt. It is expected that the server should respond.\n */\n summaryAckWaitTimeout: \"Timeout while waiting for summaryAck/summaryNack op\",\n /**\n * The server responded with a summaryNack op, thus rejecting this\n * summarize attempt.\n */\n summaryNack: \"Server rejected summary via summaryNack op\",\n\n disconnect: \"Summary cancelled due to summarizer or main client disconnect\",\n} as const;\n\nexport class SummarizeResultBuilder {\n public readonly summarySubmitted = new Deferred<SummarizeResultPart<SubmitSummaryResult>>();\n public readonly summaryOpBroadcasted = new Deferred<SummarizeResultPart<IBroadcastSummaryResult>>();\n public readonly receivedSummaryAckOrNack =\n new Deferred<SummarizeResultPart<IAckSummaryResult, INackSummaryResult>>();\n\n public fail(message: string, error: any, nackSummaryResult?: INackSummaryResult, retryAfterSeconds?: number) {\n assert(!this.receivedSummaryAckOrNack.isCompleted,\n 0x25e /* \"no reason to call fail if all promises have been completed\" */);\n\n const result: SummarizeResultPart<undefined> =\n { success: false, message, data: undefined, error, retryAfterSeconds } as const;\n this.summarySubmitted.resolve(result);\n this.summaryOpBroadcasted.resolve(result);\n this.receivedSummaryAckOrNack.resolve({ ...result, data: nackSummaryResult });\n }\n public build(): ISummarizeResults {\n return {\n summarySubmitted: this.summarySubmitted.promise,\n summaryOpBroadcasted: this.summaryOpBroadcasted.promise,\n receivedSummaryAckOrNack: this.receivedSummaryAckOrNack.promise,\n } as const;\n }\n}\n\n/**\n * This class generates and tracks a summary attempt.\n */\nexport class SummaryGenerator {\n private readonly summarizeTimer: Timer;\n constructor(\n private readonly pendingAckTimer: IPromiseTimer,\n private readonly heuristicData: ISummarizeHeuristicData,\n private readonly submitSummaryCallback: (options: ISubmitSummaryOptions) => Promise<SubmitSummaryResult>,\n private readonly raiseSummarizingError: (errorCode: string) => void,\n private readonly summaryWatcher: Pick<IClientSummaryWatcher, \"watchSummary\">,\n private readonly logger: ITelemetryLogger,\n ) {\n this.summarizeTimer = new Timer(\n maxSummarizeTimeoutTime,\n () => this.summarizeTimerHandler(maxSummarizeTimeoutTime, 1),\n );\n }\n\n /**\n * Generates summary and listens for broadcast and ack/nack.\n * Returns true for ack, false for nack, and undefined for failure or timeout.\n * @param reason - reason for summarizing\n * @param options - refreshLatestAck to fetch summary ack info from server,\n * fullTree to generate tree without any summary handles even if unchanged\n */\n public summarize(\n summarizeProps: ITelemetryProperties,\n options: ISummarizeOptions,\n cancellationToken: ISummaryCancellationToken,\n resultsBuilder = new SummarizeResultBuilder(),\n ): ISummarizeResults {\n this.summarizeCore(summarizeProps, options, resultsBuilder, cancellationToken)\n .catch((error) => {\n const message = \"UnexpectedSummarizeError\";\n this.logger.sendErrorEvent({ eventName: message, ...summarizeProps }, error);\n resultsBuilder.fail(message, error);\n });\n\n return resultsBuilder.build();\n }\n\n private async summarizeCore(\n summarizeProps: ITelemetryProperties,\n options: ISummarizeOptions,\n resultsBuilder: SummarizeResultBuilder,\n cancellationToken: ISummaryCancellationToken,\n ): Promise<void> {\n const { refreshLatestAck, fullTree } = options;\n const logger = ChildLogger.create(this.logger, undefined, { all: summarizeProps });\n const summarizeEvent = PerformanceEvent.start(logger, {\n eventName: \"Summarize\",\n refreshLatestAck,\n fullTree,\n timeSinceLastAttempt: Date.now() - this.heuristicData.lastAttempt.summaryTime,\n timeSinceLastSummary: Date.now() - this.heuristicData.lastSuccessfulSummary.summaryTime,\n });\n // Helper functions to report failures and return.\n const getFailMessage =\n (errorCode: keyof typeof summarizeErrors) => `${errorCode}: ${summarizeErrors[errorCode]}`;\n const fail = (\n errorCode: keyof typeof summarizeErrors,\n error?: any,\n properties?: ITelemetryProperties,\n nackSummaryResult?: INackSummaryResult,\n ) => {\n this.raiseSummarizingError(summarizeErrors[errorCode]);\n // UploadSummary may fail with 429 and retryAfter - respect that\n // Summary Nack also can have retryAfter, it's parsed below and comes as a property.\n const retryAfterSeconds = getRetryDelaySecondsFromError(error);\n\n // Report any failure as an error unless it was due to cancellation (like \"disconnected\" error)\n summarizeEvent.cancel({\n ...properties,\n reason: errorCode,\n category: cancellationToken.cancelled ? \"generic\" : \"error\",\n retryAfterSeconds,\n }, error);\n resultsBuilder.fail(getFailMessage(errorCode), error, nackSummaryResult, retryAfterSeconds);\n };\n\n // Wait to generate and send summary\n this.summarizeTimer.start();\n // Use record type to prevent unexpected value types\n let summaryData: SubmitSummaryResult | undefined;\n let generateTelemetryProps: Record<string, string | number | boolean | undefined> = {};\n try {\n summaryData = await this.submitSummaryCallback({\n fullTree,\n refreshLatestAck,\n summaryLogger: logger,\n cancellationToken,\n });\n\n // Cumulatively add telemetry properties based on how far generateSummary went.\n const { referenceSequenceNumber: refSequenceNumber } = summaryData;\n generateTelemetryProps = {\n refSequenceNumber,\n opsSinceLastAttempt: refSequenceNumber - this.heuristicData.lastAttempt.refSequenceNumber,\n opsSinceLastSummary: refSequenceNumber - this.heuristicData.lastSuccessfulSummary.refSequenceNumber,\n };\n if (summaryData.stage !== \"base\") {\n generateTelemetryProps = {\n ...generateTelemetryProps,\n ...summaryData.summaryStats,\n generateDuration: summaryData.generateDuration,\n };\n\n if (summaryData.stage !== \"generate\") {\n generateTelemetryProps = {\n ...generateTelemetryProps,\n handle: summaryData.handle,\n uploadDuration: summaryData.uploadDuration,\n };\n\n if (summaryData.stage !== \"upload\") {\n generateTelemetryProps = {\n ...generateTelemetryProps,\n clientSequenceNumber: summaryData.clientSequenceNumber,\n };\n }\n }\n }\n\n if (summaryData.stage !== \"submit\") {\n return fail(\"submitSummaryFailure\", summaryData.error, generateTelemetryProps);\n }\n\n // Log event here on summary success only, as Summarize_cancel duplicates failure logging.\n logger.sendTelemetryEvent({ eventName: \"GenerateSummary\", ...generateTelemetryProps });\n resultsBuilder.summarySubmitted.resolve({ success: true, data: summaryData });\n } catch (error) {\n return fail(\"submitSummaryFailure\", error);\n } finally {\n this.heuristicData.recordAttempt(summaryData?.referenceSequenceNumber);\n this.summarizeTimer.clear();\n }\n\n try {\n const pendingTimeoutP = this.pendingAckTimer.start();\n const summary = this.summaryWatcher.watchSummary(summaryData.clientSequenceNumber);\n\n // Wait for broadcast\n const waitBroadcastResult = await raceTimer(summary.waitBroadcast(), pendingTimeoutP, cancellationToken);\n if (waitBroadcastResult.result === \"cancelled\") {\n return fail(\"disconnect\");\n }\n if (waitBroadcastResult.result !== \"done\") {\n return fail(\"summaryOpWaitTimeout\");\n }\n const summarizeOp = waitBroadcastResult.value;\n\n const broadcastDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n resultsBuilder.summaryOpBroadcasted.resolve({\n success: true,\n data: { summarizeOp, broadcastDuration },\n });\n this.heuristicData.lastAttempt.summarySequenceNumber = summarizeOp.sequenceNumber;\n logger.sendTelemetryEvent({\n eventName: \"SummaryOp\",\n duration: broadcastDuration,\n refSequenceNumber: summarizeOp.referenceSequenceNumber,\n summarySequenceNumber: summarizeOp.sequenceNumber,\n handle: summarizeOp.contents.handle,\n });\n\n // Wait for ack/nack\n const waitAckNackResult = await raceTimer(summary.waitAckNack(), pendingTimeoutP, cancellationToken);\n if (waitAckNackResult.result === \"cancelled\") {\n return fail(\"disconnect\");\n }\n if (waitAckNackResult.result !== \"done\") {\n return fail(\"summaryAckWaitTimeout\");\n }\n const ackNackOp = waitAckNackResult.value;\n this.pendingAckTimer.clear();\n\n // Update for success/failure\n const ackNackDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;\n const telemetryProps: Record<string, number> = {\n ackWaitDuration: ackNackDuration,\n sequenceNumber: ackNackOp.sequenceNumber,\n summarySequenceNumber: ackNackOp.contents.summaryProposal.summarySequenceNumber,\n };\n if (ackNackOp.type === MessageType.SummaryAck) {\n this.heuristicData.markLastAttemptAsSuccessful();\n summarizeEvent.end({ ...telemetryProps, handle: ackNackOp.contents.handle, message: \"summaryAck\" });\n resultsBuilder.receivedSummaryAckOrNack.resolve({ success: true, data: {\n summaryAckOp: ackNackOp,\n ackNackDuration,\n }});\n } else {\n // Check for retryDelay in summaryNack response.\n // back-compat: cast needed until dep on protocol-definitions version bump\n assert(ackNackOp.type === MessageType.SummaryNack, 0x274 /* \"type check\" */);\n const summaryNack = ackNackOp.contents as { message?: string; retryAfter?: number; };\n const message = summaryNack.message ?? ackNackOp.contents.errorMessage;\n const retryAfterSeconds = summaryNack?.retryAfter;\n\n const error = new LoggingError(`summaryNack: ${message}`, { retryAfterSeconds });\n logger.sendErrorEvent(\n { eventName: \"SummaryNack\", ...generateTelemetryProps, retryAfterSeconds }, error);\n assert(getRetryDelaySecondsFromError(error) === retryAfterSeconds, 0x25f /* \"retryAfterSeconds\" */);\n // This will only set resultsBuilder.receivedSummaryAckOrNack, as other promises are already set.\n return fail(\n \"summaryNack\",\n error,\n { ...telemetryProps, nackRetryAfter: retryAfterSeconds },\n { summaryNackOp: ackNackOp, ackNackDuration },\n );\n }\n } finally {\n this.pendingAckTimer.clear();\n }\n }\n\n private summarizeTimerHandler(time: number, count: number) {\n this.logger.sendPerformanceEvent({\n eventName: \"SummarizeTimeout\",\n timeoutTime: time,\n timeoutCount: count,\n });\n if (count < maxSummarizeTimeoutCount) {\n // Double and start a new timer\n const nextTime = time * 2;\n this.summarizeTimer.start(nextTime, () => this.summarizeTimerHandler(nextTime, count + 1));\n }\n }\n\n public dispose() {\n this.summarizeTimer.clear();\n }\n}\n"]}
|
package/lib/summaryManager.d.ts
CHANGED
|
@@ -67,7 +67,7 @@ export declare class SummaryManager extends TypedEventEmitter<ISummaryManagerEve
|
|
|
67
67
|
private _disposed;
|
|
68
68
|
get disposed(): boolean;
|
|
69
69
|
get currentState(): SummaryManagerState;
|
|
70
|
-
constructor(clientElection: ISummarizerClientElection, connectedState: IConnectedState, summaryCollection: Pick<SummaryCollection, "opsSinceLastAck">, parentLogger: ITelemetryLogger,
|
|
70
|
+
constructor(clientElection: ISummarizerClientElection, connectedState: IConnectedState, summaryCollection: Pick<SummaryCollection, "opsSinceLastAck" | "addOpListener" | "removeOpListener">, parentLogger: ITelemetryLogger,
|
|
71
71
|
/** Creates summarizer by asking interactive container to spawn summarizing container and
|
|
72
72
|
* get back its Summarizer instance. */
|
|
73
73
|
requestSummarizerFn: () => Promise<ISummarizer>, startThrottler: IThrottler, { initialDelayMs, opsToBypassInitialDelay, }?: Readonly<Partial<ISummaryManagerConfig>>, summarizerOptions?: Readonly<Partial<ISummarizerOptions>> | undefined);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summaryManager.d.ts","sourceRoot":"","sources":["../src/summaryManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3G,OAAO,
|
|
1
|
+
{"version":3,"file":"summaryManager.d.ts","sourceRoot":"","sources":["../src/summaryManager.ts"],"names":[],"mappings":"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"}
|
package/lib/summaryManager.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { TypedEventEmitter, assert } from "@fluidframework/common-utils";
|
|
6
6
|
import { ChildLogger, PerformanceEvent } from "@fluidframework/telemetry-utils";
|
|
7
7
|
import { LoaderHeader } from "@fluidframework/container-definitions";
|
|
8
8
|
import { DriverHeader } from "@fluidframework/driver-definitions";
|
|
@@ -185,18 +185,12 @@ export class SummaryManager extends TypedEventEmitter {
|
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
187
|
stop(reason) {
|
|
188
|
+
var _a;
|
|
188
189
|
assert(this.state === SummaryManagerState.Running || this.state === SummaryManagerState.Starting, 0x265 /* "Expected: Starting or Running" */);
|
|
189
190
|
this.state = SummaryManagerState.Stopping;
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
this.summarizer.stop(reason);
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
// Should not be possible to hit this case
|
|
197
|
-
this.logger.sendErrorEvent({ eventName: "StopCalledWithoutRunningSummarizer", reason });
|
|
198
|
-
this.state = SummaryManagerState.Off;
|
|
199
|
-
}
|
|
191
|
+
// Stopping the running summarizer client should trigger a change
|
|
192
|
+
// in states when the running summarizer closes
|
|
193
|
+
(_a = this.summarizer) === null || _a === void 0 ? void 0 : _a.stop(reason);
|
|
200
194
|
}
|
|
201
195
|
/**
|
|
202
196
|
* Implements initial delay before creating summarizer
|
|
@@ -206,7 +200,7 @@ export class SummaryManager extends TypedEventEmitter {
|
|
|
206
200
|
async delayBeforeCreatingSummarizer() {
|
|
207
201
|
// throttle creation of new summarizer containers to prevent spamming the server with websocket connections
|
|
208
202
|
let delayMs = this.startThrottler.getDelay();
|
|
209
|
-
if (delayMs > 0 && delayMs
|
|
203
|
+
if (delayMs > 0 && delayMs > this.startThrottler.maxDelayMs) {
|
|
210
204
|
this.emit("summarizerWarning", createSummarizingWarning("summaryManagerCreateSummarizerMaxThrottleDelay", false));
|
|
211
205
|
}
|
|
212
206
|
// We have been elected the summarizer. Some day we may be able to summarize with a live document but for
|
|
@@ -233,7 +227,24 @@ export class SummaryManager extends TypedEventEmitter {
|
|
|
233
227
|
delayMs = Math.max(delayMs, this.initialDelayMs);
|
|
234
228
|
}
|
|
235
229
|
if (delayMs > 0) {
|
|
236
|
-
|
|
230
|
+
let timer;
|
|
231
|
+
let resolveOpPromiseFn;
|
|
232
|
+
// Create a listener that will break the delay if we've exceeded the initial delay ops count.
|
|
233
|
+
const opsListenerFn = () => {
|
|
234
|
+
if (this.summaryCollection.opsSinceLastAck >= this.opsToBypassInitialDelay) {
|
|
235
|
+
clearTimeout(timer);
|
|
236
|
+
resolveOpPromiseFn();
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
// Create a Promise that will resolve when the delay expires.
|
|
240
|
+
const delayPromise = new Promise((resolve) => {
|
|
241
|
+
timer = setTimeout(() => resolve(), delayMs);
|
|
242
|
+
});
|
|
243
|
+
// Create a Promise that will resolve if the ops count passes the threshold.
|
|
244
|
+
const opPromise = new Promise((resolve) => { resolveOpPromiseFn = resolve; });
|
|
245
|
+
this.summaryCollection.addOpListener(opsListenerFn);
|
|
246
|
+
await Promise.race([delayPromise, opPromise]);
|
|
247
|
+
this.summaryCollection.removeOpListener(opsListenerFn);
|
|
237
248
|
}
|
|
238
249
|
return startWithInitialDelay;
|
|
239
250
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summaryManager.js","sourceRoot":"","sources":["../src/summaryManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IDisposable, IEvent, IEventProvider, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { delay, TypedEventEmitter, assert } from \"@fluidframework/common-utils\";\nimport { ChildLogger, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { IFluidRouter, IRequest } from \"@fluidframework/core-interfaces\";\nimport { IDeltaManager, LoaderHeader } from \"@fluidframework/container-definitions\";\nimport { DriverHeader } from \"@fluidframework/driver-definitions\";\nimport { requestFluidObject } from \"@fluidframework/runtime-utils\";\nimport { createSummarizingWarning } from \"./summarizer\";\nimport { ISummarizerClientElection, summarizerClientType } from \"./summarizerClientElection\";\nimport { IThrottler } from \"./throttler\";\nimport { ISummarizer, ISummarizerOptions, ISummarizingWarning, SummarizerStopReason } from \"./summarizerTypes\";\nimport { SummaryCollection } from \"./summaryCollection\";\n\nconst defaultInitialDelayMs = 5000;\nconst defaultOpsToBypassInitialDelay = 4000;\n\nexport enum SummaryManagerState {\n Off = 0,\n Starting = 1,\n Running = 2,\n Stopping = 3,\n}\n\n// Please note that all reasons in this list are not errors,\n// and thus they are not raised today to parent container as error.\n// If this needs to be changed in future, we should re-evaluate what and how we raise to summarizer\ntype StopReason = Extract<SummarizerStopReason, \"parentNotConnected\" | \"parentShouldNotSummarize\">;\ntype ShouldSummarizeState =\n | { shouldSummarize: true; }\n | { shouldSummarize: false; stopReason: StopReason; };\n\nexport interface IConnectedEvents extends IEvent {\n (event: \"connected\", listener: (clientId: string) => void);\n (event: \"disconnected\", listener: () => void);\n}\n\n/**\n * IConnectedState describes an object that SummaryManager can watch to observe connection/disconnection.\n *\n * Under current implementation, its role will be fulfilled by the ContainerRuntime, but this could be replaced\n * with anything else that fulfills the contract if we want to shift the layer that the SummaryManager lives at.\n */\nexport interface IConnectedState extends IEventProvider<IConnectedEvents> {\n readonly connected: boolean;\n\n /**\n * Under current implementation this is undefined if we've never connected, otherwise it's the clientId from our\n * latest connection (even if we've since disconnected!). Although this happens to be the behavior we want in\n * SummaryManager, I suspect that globally we may eventually want to modify this behavior (e.g. make clientId\n * undefined while disconnected). To protect against this, let's assume this field can't be trusted while\n * disconnected and instead separately track \"latest clientId\" in SummaryManager.\n */\n readonly clientId: string | undefined;\n}\n\nexport interface ISummaryManagerEvents extends IEvent {\n (event: \"summarizerWarning\", listener: (warning: ISummarizingWarning) => void);\n}\n\nexport interface ISummaryManagerConfig {\n initialDelayMs: number;\n opsToBypassInitialDelay: number;\n}\n\n/**\n * SummaryManager is created by parent container (i.e. interactive container with clientType !== \"summarizer\") only.\n * It observes changes in calculated summarizer and reacts to changes by either creating summarizer client or\n * stopping existing summarizer client.\n */\nexport class SummaryManager extends TypedEventEmitter<ISummaryManagerEvents> implements IDisposable {\n private readonly logger: ITelemetryLogger;\n private readonly opsToBypassInitialDelay: number;\n private readonly initialDelayMs: number;\n private latestClientId: string | undefined;\n private state = SummaryManagerState.Off;\n private summarizer?: ISummarizer;\n private _disposed = false;\n\n public get disposed() {\n return this._disposed;\n }\n\n public get currentState() { return this.state; }\n\n constructor(\n private readonly clientElection: ISummarizerClientElection,\n private readonly connectedState: IConnectedState,\n private readonly summaryCollection: Pick<SummaryCollection, \"opsSinceLastAck\">,\n parentLogger: ITelemetryLogger,\n /** Creates summarizer by asking interactive container to spawn summarizing container and\n * get back its Summarizer instance. */\n private readonly requestSummarizerFn: () => Promise<ISummarizer>,\n private readonly startThrottler: IThrottler,\n {\n initialDelayMs = defaultInitialDelayMs,\n opsToBypassInitialDelay = defaultOpsToBypassInitialDelay,\n }: Readonly<Partial<ISummaryManagerConfig>> = {},\n private readonly summarizerOptions?: Readonly<Partial<ISummarizerOptions>>,\n ) {\n super();\n\n this.logger = ChildLogger.create(\n parentLogger,\n \"SummaryManager\",\n {all:{ clientId: () => this.latestClientId }});\n\n this.connectedState.on(\"connected\", this.handleConnected);\n this.connectedState.on(\"disconnected\", this.handleDisconnected);\n this.latestClientId = this.connectedState.clientId;\n\n this.opsToBypassInitialDelay = opsToBypassInitialDelay;\n this.initialDelayMs = initialDelayMs;\n }\n\n /**\n * Until start is called, the SummaryManager won't begin attempting to start summarization. This ensures there's\n * a window between construction and starting where the caller can attach listeners.\n */\n public start(): void {\n this.clientElection.on(\"electedSummarizerChanged\", this.refreshSummarizer);\n this.refreshSummarizer();\n }\n\n private readonly handleConnected = (clientId: string) => {\n this.latestClientId = clientId;\n // If we have a summarizer, it should have been either cancelled on disconnected by now.\n // But because of lastSummary process, it can still hang around, so there is not much we can\n // check or assert.\n this.refreshSummarizer();\n };\n\n private readonly handleDisconnected = () => {\n this.refreshSummarizer();\n };\n\n private getShouldSummarizeState(): ShouldSummarizeState {\n if (!this.connectedState.connected) {\n return { shouldSummarize: false, stopReason: \"parentNotConnected\" };\n } else if (this.connectedState.clientId !== this.clientElection.electedClientId) {\n return { shouldSummarize: false, stopReason: \"parentShouldNotSummarize\" };\n } else if (this.disposed) {\n assert(false, 0x260 /* \"Disposed should mean disconnected!\" */);\n } else {\n return { shouldSummarize: true };\n }\n }\n\n private readonly refreshSummarizer = () => {\n // Transition states depending on shouldSummarize, which is a calculated property\n // that is only true if this client is connected and is the elected summarizer.\n const shouldSummarizeState = this.getShouldSummarizeState();\n switch (this.state) {\n case SummaryManagerState.Off: {\n if (shouldSummarizeState.shouldSummarize) {\n this.startSummarization();\n }\n return;\n }\n case SummaryManagerState.Starting: {\n // Cannot take any action until summarizer is created\n // state transition will occur after creation\n return;\n }\n case SummaryManagerState.Running: {\n if (shouldSummarizeState.shouldSummarize === false) {\n this.stop(shouldSummarizeState.stopReason);\n }\n return;\n }\n case SummaryManagerState.Stopping: {\n // Cannot take any action until running summarizer finishes\n // state transition will occur after it stops\n return;\n }\n default: {\n return;\n }\n }\n };\n\n private startSummarization() {\n assert(this.state === SummaryManagerState.Off, 0x261 /* \"Expected: off\" */);\n this.state = SummaryManagerState.Starting;\n\n assert(this.summarizer === undefined, 0x262 /* \"Old summarizer is still working!\" */);\n\n let reason = \"unknown\";\n\n this.delayBeforeCreatingSummarizer().then(async (startWithInitialDelay: boolean) => {\n // Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore\n // but only if creation was delayed. If it was not, then we want to ensure we always create\n // a summarizer to kick off lastSummary. Without that, we would not be able to summarize and get\n // document out of broken state if it has too many ops and ordering service keeps nacking main\n // container (and thus it goes into cycle of reconnects)\n if (startWithInitialDelay && this.getShouldSummarizeState().shouldSummarize === false) {\n return;\n }\n\n const summarizer = await this.requestSummarizerFn();\n\n // Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore\n const shouldSummarizeState = this.getShouldSummarizeState();\n if (shouldSummarizeState.shouldSummarize === false) {\n summarizer.stop(shouldSummarizeState.stopReason);\n return;\n }\n\n assert(this.state === SummaryManagerState.Starting, 0x263 /* \"Expected: starting\" */);\n this.state = SummaryManagerState.Running;\n\n summarizer.on(\"summarizingError\",\n (warning: ISummarizingWarning) => this.emit(\"summarizerWarning\", warning));\n this.summarizer = summarizer;\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const clientId = this.latestClientId!;\n\n reason = await PerformanceEvent.timedExecAsync(\n this.logger,\n { eventName: \"RunningSummarizer\", attempt: this.startThrottler.numAttempts },\n async () => summarizer.run(clientId, this.summarizerOptions),\n );\n }).catch((error) => {\n // Most of exceptions happen due to container being closed while loading it, due to\n // summarizer container loosing connection while load.\n // Not worth reporting such errors as errors. That said, we might miss some real errors if\n // we ignore blindly, so try to narrow signature we are looking for - skip logging\n // error only if this client should no longer be a summarizer (which in practice\n // means it also lost connection), and error happened on load (we do not have summarizer).\n // We could add error.fluidErrorCode !== \"containerClosedWithoutErrorDuringLoad\" check to narrow it down,\n // but that does not seem to be necessary.\n if (this.getShouldSummarizeState().shouldSummarize || this.summarizer !== undefined) {\n this.logger.sendErrorEvent({ eventName: \"SummarizerException\" }, error);\n this.emit(\"summarizerWarning\", error);\n\n // Note that summarizer may keep going (like doing last summary).\n // Ideally we await stopping process, but this code path is due to a bug\n // that needs to be fixed either way.\n this.stop(\"summarizerException\");\n }\n }).finally(() => {\n assert(this.state !== SummaryManagerState.Off, 0x264 /* \"Expected: Not Off\" */);\n this.state = SummaryManagerState.Off;\n\n this.summarizer = undefined;\n\n this.logger.sendTelemetryEvent({\n eventName: \"EndingSummarizer\",\n reason,\n });\n\n if (this.getShouldSummarizeState().shouldSummarize) {\n this.startSummarization();\n }\n });\n }\n\n private stop(reason: SummarizerStopReason) {\n assert(this.state === SummaryManagerState.Running || this.state === SummaryManagerState.Starting,\n 0x265 /* \"Expected: Starting or Running\" */);\n this.state = SummaryManagerState.Stopping;\n\n if (this.summarizer !== undefined) {\n // Stopping the running summarizer client should trigger a change\n // in states when the running summarizer closes\n this.summarizer.stop(reason);\n } else {\n // Should not be possible to hit this case\n this.logger.sendErrorEvent({ eventName: \"StopCalledWithoutRunningSummarizer\", reason });\n this.state = SummaryManagerState.Off;\n }\n }\n\n /**\n * Implements initial delay before creating summarizer\n * @returns true, if creation is delayed due to heuristics (not many ops to summarize).\n * False if summarizer should start immediately due to too many unsummarized ops.\n */\n private async delayBeforeCreatingSummarizer(): Promise<boolean> {\n // throttle creation of new summarizer containers to prevent spamming the server with websocket connections\n let delayMs = this.startThrottler.getDelay();\n if (delayMs > 0 && delayMs >= this.startThrottler.maxDelayMs) {\n this.emit(\n \"summarizerWarning\",\n createSummarizingWarning(\"summaryManagerCreateSummarizerMaxThrottleDelay\", false),\n );\n }\n\n // We have been elected the summarizer. Some day we may be able to summarize with a live document but for\n // now we play it safe and launch a second copy.\n this.logger.sendTelemetryEvent({\n eventName: \"CreatingSummarizer\",\n throttlerDelay: delayMs,\n initialDelay: this.initialDelayMs,\n opsSinceLastAck: this.summaryCollection.opsSinceLastAck,\n opsToBypassInitialDelay: this.opsToBypassInitialDelay,\n });\n\n // This delay helps ensure that last summarizer that might be left from previous client\n // has enough time to complete its last summary and thus new summarizer not conflict with previous one.\n // If, however, there are too many unsummarized ops, try to resolve it as quickly as possible, with\n // understanding that we may see nacks because of such quick action.\n // A better design would be for summarizer election logic to always select current summarizer as\n // summarizing client (i.e. clientType === \"summarizer\" can be elected) to ensure that nobody else can\n // summarizer while it finishes its work and moves to exit.\n // It also helps with pure boot scenario (single client) to offset expensive work a bit out from\n // critical boot sequence.\n let startWithInitialDelay = false;\n if (this.summaryCollection.opsSinceLastAck < this.opsToBypassInitialDelay) {\n startWithInitialDelay = true;\n delayMs = Math.max(delayMs, this.initialDelayMs);\n }\n\n if (delayMs > 0) {\n await delay(delayMs);\n }\n return startWithInitialDelay;\n }\n\n public readonly summarizeOnDemand: ISummarizer[\"summarizeOnDemand\"] = (...args) => {\n if (this.summarizer === undefined) {\n throw Error(\"No running summarizer client\");\n // TODO: could spawn a summarizer client temporarily.\n }\n return this.summarizer.summarizeOnDemand(...args);\n };\n\n public readonly enqueueSummarize: ISummarizer[\"enqueueSummarize\"] = (...args) => {\n if (this.summarizer === undefined) {\n throw Error(\"No running summarizer client\");\n // TODO: could spawn a summarizer client temporarily.\n }\n return this.summarizer.enqueueSummarize(...args);\n };\n\n public dispose() {\n this.clientElection.off(\"electedSummarizerChanged\", this.refreshSummarizer);\n this.connectedState.off(\"connected\", this.handleConnected);\n this.connectedState.off(\"disconnected\", this.handleDisconnected);\n this._disposed = true;\n }\n}\n\n/**\n * Forms a function that will request a Summarizer.\n * @param loaderRouter - the loader acting as an IFluidRouter\n * @param deltaManager - delta manager to get last sequence number\n */\nexport const formRequestSummarizerFn = (\n loaderRouter: IFluidRouter,\n deltaManager: Pick<IDeltaManager<unknown, unknown>, \"lastSequenceNumber\">,\n) => async () => {\n // TODO eventually we may wish to spawn an execution context from which to run this\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 [LoaderHeader.sequenceNumber]: deltaManager.lastSequenceNumber,\n },\n url: \"/_summarizer\",\n };\n\n const fluidObject = await requestFluidObject(loaderRouter, request);\n const summarizer = fluidObject.ISummarizer;\n\n if (!summarizer) {\n return Promise.reject(new Error(\"Fluid object does not implement ISummarizer\"));\n }\n\n return summarizer;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"summaryManager.js","sourceRoot":"","sources":["../src/summaryManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IDisposable, IEvent, IEventProvider, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { TypedEventEmitter, assert } from \"@fluidframework/common-utils\";\nimport { ChildLogger, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { IFluidRouter, IRequest } from \"@fluidframework/core-interfaces\";\nimport { IDeltaManager, LoaderHeader } from \"@fluidframework/container-definitions\";\nimport { DriverHeader } from \"@fluidframework/driver-definitions\";\nimport { requestFluidObject } from \"@fluidframework/runtime-utils\";\nimport { createSummarizingWarning } from \"./summarizer\";\nimport { ISummarizerClientElection, summarizerClientType } from \"./summarizerClientElection\";\nimport { IThrottler } from \"./throttler\";\nimport { ISummarizer, ISummarizerOptions, ISummarizingWarning, SummarizerStopReason } from \"./summarizerTypes\";\nimport { SummaryCollection } from \"./summaryCollection\";\n\nconst defaultInitialDelayMs = 5000;\nconst defaultOpsToBypassInitialDelay = 4000;\n\nexport enum SummaryManagerState {\n Off = 0,\n Starting = 1,\n Running = 2,\n Stopping = 3,\n}\n\n// Please note that all reasons in this list are not errors,\n// and thus they are not raised today to parent container as error.\n// If this needs to be changed in future, we should re-evaluate what and how we raise to summarizer\ntype StopReason = Extract<SummarizerStopReason, \"parentNotConnected\" | \"parentShouldNotSummarize\">;\ntype ShouldSummarizeState =\n | { shouldSummarize: true; }\n | { shouldSummarize: false; stopReason: StopReason; };\n\nexport interface IConnectedEvents extends IEvent {\n (event: \"connected\", listener: (clientId: string) => void);\n (event: \"disconnected\", listener: () => void);\n}\n\n/**\n * IConnectedState describes an object that SummaryManager can watch to observe connection/disconnection.\n *\n * Under current implementation, its role will be fulfilled by the ContainerRuntime, but this could be replaced\n * with anything else that fulfills the contract if we want to shift the layer that the SummaryManager lives at.\n */\nexport interface IConnectedState extends IEventProvider<IConnectedEvents> {\n readonly connected: boolean;\n\n /**\n * Under current implementation this is undefined if we've never connected, otherwise it's the clientId from our\n * latest connection (even if we've since disconnected!). Although this happens to be the behavior we want in\n * SummaryManager, I suspect that globally we may eventually want to modify this behavior (e.g. make clientId\n * undefined while disconnected). To protect against this, let's assume this field can't be trusted while\n * disconnected and instead separately track \"latest clientId\" in SummaryManager.\n */\n readonly clientId: string | undefined;\n}\n\nexport interface ISummaryManagerEvents extends IEvent {\n (event: \"summarizerWarning\", listener: (warning: ISummarizingWarning) => void);\n}\n\nexport interface ISummaryManagerConfig {\n initialDelayMs: number;\n opsToBypassInitialDelay: number;\n}\n\n/**\n * SummaryManager is created by parent container (i.e. interactive container with clientType !== \"summarizer\") only.\n * It observes changes in calculated summarizer and reacts to changes by either creating summarizer client or\n * stopping existing summarizer client.\n */\nexport class SummaryManager extends TypedEventEmitter<ISummaryManagerEvents> implements IDisposable {\n private readonly logger: ITelemetryLogger;\n private readonly opsToBypassInitialDelay: number;\n private readonly initialDelayMs: number;\n private latestClientId: string | undefined;\n private state = SummaryManagerState.Off;\n private summarizer?: ISummarizer;\n private _disposed = false;\n\n public get disposed() {\n return this._disposed;\n }\n\n public get currentState() { return this.state; }\n\n constructor(\n private readonly clientElection: ISummarizerClientElection,\n private readonly connectedState: IConnectedState,\n private readonly summaryCollection:\n Pick<SummaryCollection, \"opsSinceLastAck\" | \"addOpListener\" | \"removeOpListener\">,\n parentLogger: ITelemetryLogger,\n /** Creates summarizer by asking interactive container to spawn summarizing container and\n * get back its Summarizer instance. */\n private readonly requestSummarizerFn: () => Promise<ISummarizer>,\n private readonly startThrottler: IThrottler,\n {\n initialDelayMs = defaultInitialDelayMs,\n opsToBypassInitialDelay = defaultOpsToBypassInitialDelay,\n }: Readonly<Partial<ISummaryManagerConfig>> = {},\n private readonly summarizerOptions?: Readonly<Partial<ISummarizerOptions>>,\n ) {\n super();\n\n this.logger = ChildLogger.create(\n parentLogger,\n \"SummaryManager\",\n {all:{ clientId: () => this.latestClientId }});\n\n this.connectedState.on(\"connected\", this.handleConnected);\n this.connectedState.on(\"disconnected\", this.handleDisconnected);\n this.latestClientId = this.connectedState.clientId;\n\n this.opsToBypassInitialDelay = opsToBypassInitialDelay;\n this.initialDelayMs = initialDelayMs;\n }\n\n /**\n * Until start is called, the SummaryManager won't begin attempting to start summarization. This ensures there's\n * a window between construction and starting where the caller can attach listeners.\n */\n public start(): void {\n this.clientElection.on(\"electedSummarizerChanged\", this.refreshSummarizer);\n this.refreshSummarizer();\n }\n\n private readonly handleConnected = (clientId: string) => {\n this.latestClientId = clientId;\n // If we have a summarizer, it should have been either cancelled on disconnected by now.\n // But because of lastSummary process, it can still hang around, so there is not much we can\n // check or assert.\n this.refreshSummarizer();\n };\n\n private readonly handleDisconnected = () => {\n this.refreshSummarizer();\n };\n\n private getShouldSummarizeState(): ShouldSummarizeState {\n if (!this.connectedState.connected) {\n return { shouldSummarize: false, stopReason: \"parentNotConnected\" };\n } else if (this.connectedState.clientId !== this.clientElection.electedClientId) {\n return { shouldSummarize: false, stopReason: \"parentShouldNotSummarize\" };\n } else if (this.disposed) {\n assert(false, 0x260 /* \"Disposed should mean disconnected!\" */);\n } else {\n return { shouldSummarize: true };\n }\n }\n\n private readonly refreshSummarizer = () => {\n // Transition states depending on shouldSummarize, which is a calculated property\n // that is only true if this client is connected and is the elected summarizer.\n const shouldSummarizeState = this.getShouldSummarizeState();\n switch (this.state) {\n case SummaryManagerState.Off: {\n if (shouldSummarizeState.shouldSummarize) {\n this.startSummarization();\n }\n return;\n }\n case SummaryManagerState.Starting: {\n // Cannot take any action until summarizer is created\n // state transition will occur after creation\n return;\n }\n case SummaryManagerState.Running: {\n if (shouldSummarizeState.shouldSummarize === false) {\n this.stop(shouldSummarizeState.stopReason);\n }\n return;\n }\n case SummaryManagerState.Stopping: {\n // Cannot take any action until running summarizer finishes\n // state transition will occur after it stops\n return;\n }\n default: {\n return;\n }\n }\n };\n\n private startSummarization() {\n assert(this.state === SummaryManagerState.Off, 0x261 /* \"Expected: off\" */);\n this.state = SummaryManagerState.Starting;\n\n assert(this.summarizer === undefined, 0x262 /* \"Old summarizer is still working!\" */);\n\n let reason = \"unknown\";\n\n this.delayBeforeCreatingSummarizer().then(async (startWithInitialDelay: boolean) => {\n // Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore\n // but only if creation was delayed. If it was not, then we want to ensure we always create\n // a summarizer to kick off lastSummary. Without that, we would not be able to summarize and get\n // document out of broken state if it has too many ops and ordering service keeps nacking main\n // container (and thus it goes into cycle of reconnects)\n if (startWithInitialDelay && this.getShouldSummarizeState().shouldSummarize === false) {\n return;\n }\n\n const summarizer = await this.requestSummarizerFn();\n\n // Re-validate that it need to be running. Due to asynchrony, it may be not the case anymore\n const shouldSummarizeState = this.getShouldSummarizeState();\n if (shouldSummarizeState.shouldSummarize === false) {\n summarizer.stop(shouldSummarizeState.stopReason);\n return;\n }\n\n assert(this.state === SummaryManagerState.Starting, 0x263 /* \"Expected: starting\" */);\n this.state = SummaryManagerState.Running;\n\n summarizer.on(\"summarizingError\",\n (warning: ISummarizingWarning) => this.emit(\"summarizerWarning\", warning));\n this.summarizer = summarizer;\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const clientId = this.latestClientId!;\n\n reason = await PerformanceEvent.timedExecAsync(\n this.logger,\n { eventName: \"RunningSummarizer\", attempt: this.startThrottler.numAttempts },\n async () => summarizer.run(clientId, this.summarizerOptions),\n );\n }).catch((error) => {\n // Most of exceptions happen due to container being closed while loading it, due to\n // summarizer container loosing connection while load.\n // Not worth reporting such errors as errors. That said, we might miss some real errors if\n // we ignore blindly, so try to narrow signature we are looking for - skip logging\n // error only if this client should no longer be a summarizer (which in practice\n // means it also lost connection), and error happened on load (we do not have summarizer).\n // We could add error.fluidErrorCode !== \"containerClosedWithoutErrorDuringLoad\" check to narrow it down,\n // but that does not seem to be necessary.\n if (this.getShouldSummarizeState().shouldSummarize || this.summarizer !== undefined) {\n this.logger.sendErrorEvent({ eventName: \"SummarizerException\" }, error);\n this.emit(\"summarizerWarning\", error);\n\n // Note that summarizer may keep going (like doing last summary).\n // Ideally we await stopping process, but this code path is due to a bug\n // that needs to be fixed either way.\n this.stop(\"summarizerException\");\n }\n }).finally(() => {\n assert(this.state !== SummaryManagerState.Off, 0x264 /* \"Expected: Not Off\" */);\n this.state = SummaryManagerState.Off;\n\n this.summarizer = undefined;\n\n this.logger.sendTelemetryEvent({\n eventName: \"EndingSummarizer\",\n reason,\n });\n\n if (this.getShouldSummarizeState().shouldSummarize) {\n this.startSummarization();\n }\n });\n }\n\n private stop(reason: SummarizerStopReason) {\n assert(this.state === SummaryManagerState.Running || this.state === SummaryManagerState.Starting,\n 0x265 /* \"Expected: Starting or Running\" */);\n this.state = SummaryManagerState.Stopping;\n\n // Stopping the running summarizer client should trigger a change\n // in states when the running summarizer closes\n this.summarizer?.stop(reason);\n }\n\n /**\n * Implements initial delay before creating summarizer\n * @returns true, if creation is delayed due to heuristics (not many ops to summarize).\n * False if summarizer should start immediately due to too many unsummarized ops.\n */\n private async delayBeforeCreatingSummarizer(): Promise<boolean> {\n // throttle creation of new summarizer containers to prevent spamming the server with websocket connections\n let delayMs = this.startThrottler.getDelay();\n if (delayMs > 0 && delayMs > this.startThrottler.maxDelayMs) {\n this.emit(\n \"summarizerWarning\",\n createSummarizingWarning(\"summaryManagerCreateSummarizerMaxThrottleDelay\", false),\n );\n }\n\n // We have been elected the summarizer. Some day we may be able to summarize with a live document but for\n // now we play it safe and launch a second copy.\n this.logger.sendTelemetryEvent({\n eventName: \"CreatingSummarizer\",\n throttlerDelay: delayMs,\n initialDelay: this.initialDelayMs,\n opsSinceLastAck: this.summaryCollection.opsSinceLastAck,\n opsToBypassInitialDelay: this.opsToBypassInitialDelay,\n });\n\n // This delay helps ensure that last summarizer that might be left from previous client\n // has enough time to complete its last summary and thus new summarizer not conflict with previous one.\n // If, however, there are too many unsummarized ops, try to resolve it as quickly as possible, with\n // understanding that we may see nacks because of such quick action.\n // A better design would be for summarizer election logic to always select current summarizer as\n // summarizing client (i.e. clientType === \"summarizer\" can be elected) to ensure that nobody else can\n // summarizer while it finishes its work and moves to exit.\n // It also helps with pure boot scenario (single client) to offset expensive work a bit out from\n // critical boot sequence.\n let startWithInitialDelay = false;\n if (this.summaryCollection.opsSinceLastAck < this.opsToBypassInitialDelay) {\n startWithInitialDelay = true;\n delayMs = Math.max(delayMs, this.initialDelayMs);\n }\n\n if (delayMs > 0) {\n let timer;\n let resolveOpPromiseFn;\n // Create a listener that will break the delay if we've exceeded the initial delay ops count.\n const opsListenerFn = () => {\n if (this.summaryCollection.opsSinceLastAck >= this.opsToBypassInitialDelay) {\n clearTimeout(timer);\n resolveOpPromiseFn();\n }\n };\n // Create a Promise that will resolve when the delay expires.\n const delayPromise = new Promise<void>((resolve) => {\n timer = setTimeout(() => resolve(), delayMs);\n });\n // Create a Promise that will resolve if the ops count passes the threshold.\n const opPromise = new Promise<void>((resolve) => { resolveOpPromiseFn = resolve; });\n this.summaryCollection.addOpListener(opsListenerFn);\n await Promise.race([ delayPromise, opPromise ]);\n this.summaryCollection.removeOpListener(opsListenerFn);\n }\n return startWithInitialDelay;\n }\n\n public readonly summarizeOnDemand: ISummarizer[\"summarizeOnDemand\"] = (...args) => {\n if (this.summarizer === undefined) {\n throw Error(\"No running summarizer client\");\n // TODO: could spawn a summarizer client temporarily.\n }\n return this.summarizer.summarizeOnDemand(...args);\n };\n\n public readonly enqueueSummarize: ISummarizer[\"enqueueSummarize\"] = (...args) => {\n if (this.summarizer === undefined) {\n throw Error(\"No running summarizer client\");\n // TODO: could spawn a summarizer client temporarily.\n }\n return this.summarizer.enqueueSummarize(...args);\n };\n\n public dispose() {\n this.clientElection.off(\"electedSummarizerChanged\", this.refreshSummarizer);\n this.connectedState.off(\"connected\", this.handleConnected);\n this.connectedState.off(\"disconnected\", this.handleDisconnected);\n this._disposed = true;\n }\n}\n\n/**\n * Forms a function that will request a Summarizer.\n * @param loaderRouter - the loader acting as an IFluidRouter\n * @param deltaManager - delta manager to get last sequence number\n */\nexport const formRequestSummarizerFn = (\n loaderRouter: IFluidRouter,\n deltaManager: Pick<IDeltaManager<unknown, unknown>, \"lastSequenceNumber\">,\n) => async () => {\n // TODO eventually we may wish to spawn an execution context from which to run this\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 [LoaderHeader.sequenceNumber]: deltaManager.lastSequenceNumber,\n },\n url: \"/_summarizer\",\n };\n\n const fluidObject = await requestFluidObject(loaderRouter, request);\n const summarizer = fluidObject.ISummarizer;\n\n if (!summarizer) {\n return Promise.reject(new Error(\"Fluid object does not implement ISummarizer\"));\n }\n\n return summarizer;\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/container-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.49.1",
|
|
4
4
|
"description": "Fluid container runtime",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": "https://github.com/microsoft/FluidFramework",
|
|
@@ -58,27 +58,27 @@
|
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
60
60
|
"@fluidframework/common-utils": "^0.32.1",
|
|
61
|
-
"@fluidframework/container-definitions": "^0.
|
|
62
|
-
"@fluidframework/container-runtime-definitions": "^0.
|
|
63
|
-
"@fluidframework/container-utils": "^0.
|
|
61
|
+
"@fluidframework/container-definitions": "^0.40.0",
|
|
62
|
+
"@fluidframework/container-runtime-definitions": "^0.49.1",
|
|
63
|
+
"@fluidframework/container-utils": "^0.49.1",
|
|
64
64
|
"@fluidframework/core-interfaces": "^0.39.7",
|
|
65
|
-
"@fluidframework/datastore": "^0.
|
|
66
|
-
"@fluidframework/driver-definitions": "^0.
|
|
67
|
-
"@fluidframework/driver-utils": "^0.
|
|
68
|
-
"@fluidframework/garbage-collector": "^0.
|
|
69
|
-
"@fluidframework/protocol-base": "^0.
|
|
70
|
-
"@fluidframework/protocol-definitions": "^0.
|
|
71
|
-
"@fluidframework/runtime-definitions": "^0.
|
|
72
|
-
"@fluidframework/runtime-utils": "^0.
|
|
73
|
-
"@fluidframework/telemetry-utils": "^0.
|
|
65
|
+
"@fluidframework/datastore": "^0.49.1",
|
|
66
|
+
"@fluidframework/driver-definitions": "^0.40.0",
|
|
67
|
+
"@fluidframework/driver-utils": "^0.49.1",
|
|
68
|
+
"@fluidframework/garbage-collector": "^0.49.1",
|
|
69
|
+
"@fluidframework/protocol-base": "^0.1032.0",
|
|
70
|
+
"@fluidframework/protocol-definitions": "^0.1025.0",
|
|
71
|
+
"@fluidframework/runtime-definitions": "^0.49.1",
|
|
72
|
+
"@fluidframework/runtime-utils": "^0.49.1",
|
|
73
|
+
"@fluidframework/telemetry-utils": "^0.49.1",
|
|
74
74
|
"double-ended-queue": "^2.1.0-0",
|
|
75
75
|
"uuid": "^8.3.1"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"@fluidframework/build-common": "^0.23.0",
|
|
79
79
|
"@fluidframework/eslint-config-fluid": "^0.23.0",
|
|
80
|
-
"@fluidframework/mocha-test-setup": "^0.
|
|
81
|
-
"@fluidframework/test-runtime-utils": "^0.
|
|
80
|
+
"@fluidframework/mocha-test-setup": "^0.49.1",
|
|
81
|
+
"@fluidframework/test-runtime-utils": "^0.49.1",
|
|
82
82
|
"@microsoft/api-extractor": "^7.16.1",
|
|
83
83
|
"@types/double-ended-queue": "^2.1.0",
|
|
84
84
|
"@types/mocha": "^8.2.2",
|