@fluidframework/container-runtime 2.0.0-internal.1.1.1 → 2.0.0-internal.1.2.0.93071
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/batchManager.d.ts +32 -0
- package/dist/batchManager.d.ts.map +1 -0
- package/dist/batchManager.js +71 -0
- package/dist/batchManager.js.map +1 -0
- package/dist/containerRuntime.d.ts +44 -17
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +197 -95
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +4 -4
- package/dist/dataStoreContext.js +5 -5
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +0 -11
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +6 -43
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/runningSummarizer.js +1 -1
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/scheduleManager.js +1 -1
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summarizerTypes.d.ts +3 -3
- package/dist/summarizerTypes.js +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryCollection.d.ts +1 -0
- package/dist/summaryCollection.d.ts.map +1 -1
- package/dist/summaryCollection.js +32 -13
- package/dist/summaryCollection.js.map +1 -1
- package/lib/batchManager.d.ts +32 -0
- package/lib/batchManager.d.ts.map +1 -0
- package/lib/batchManager.js +67 -0
- package/lib/batchManager.js.map +1 -0
- package/lib/containerRuntime.d.ts +44 -17
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +200 -98
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +4 -4
- package/lib/dataStoreContext.js +5 -5
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +0 -11
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +6 -43
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/runningSummarizer.js +1 -1
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/scheduleManager.js +2 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summarizerTypes.d.ts +3 -3
- package/lib/summarizerTypes.js +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryCollection.d.ts +1 -0
- package/lib/summaryCollection.d.ts.map +1 -1
- package/lib/summaryCollection.js +32 -13
- package/lib/summaryCollection.js.map +1 -1
- package/package.json +17 -17
- package/src/batchManager.ts +88 -0
- package/src/containerRuntime.ts +273 -156
- package/src/dataStoreContext.ts +7 -7
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +6 -56
- package/src/runningSummarizer.ts +1 -1
- package/src/scheduleManager.ts +2 -2
- package/src/summarizerTypes.ts +3 -3
- package/src/summaryCollection.ts +33 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summarizerTypes.js","sourceRoot":"","sources":["../src/summarizerTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAuBH;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAA6B,aAAa,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n IEvent,\n IEventProvider,\n ITelemetryLogger,\n ITelemetryProperties,\n} from \"@fluidframework/common-definitions\";\nimport { ITelemetryLoggerPropertyBag } from \"@fluidframework/telemetry-utils\";\nimport {\n IFluidLoadable,\n} from \"@fluidframework/core-interfaces\";\nimport { ContainerWarning, IDeltaManager } from \"@fluidframework/container-definitions\";\nimport {\n ISequencedDocumentMessage,\n ISummaryTree,\n IDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport { ISummaryStats } from \"@fluidframework/runtime-definitions\";\nimport { ISummaryAckMessage, ISummaryNackMessage, ISummaryOpMessage } from \"./summaryCollection\";\nimport { SummarizeReason } from \"./summaryGenerator\";\nimport { ISummaryConfigurationHeuristics } from \".\";\n\n/**\n * @deprecated - This will be removed in a later release.\n */\nexport const ISummarizer: keyof IProvideSummarizer = \"ISummarizer\";\n\n/**\n * @deprecated - This will be removed in a later release.\n */\nexport interface IProvideSummarizer {\n /**\n * @deprecated - This will be removed in a later release.\n */\n readonly ISummarizer: ISummarizer;\n}\n\n/**\n * Similar to AbortSignal, but using promise instead of events\n * @param T - cancellation reason type\n */\nexport interface ICancellationToken<T> {\n /** Tells if this cancellable token is cancelled */\n readonly cancelled: boolean;\n /**\n * Promise that gets fulfilled when this cancellable token is cancelled\n * @returns reason of cancellation\n */\n readonly waitCancelled: Promise<T>;\n}\n\n/* Similar to AbortSignal, but using promise instead of events */\nexport type ISummaryCancellationToken = ICancellationToken<SummarizerStopReason>;\n\nexport interface ISummarizerInternalsProvider {\n /** Encapsulates the work to walk the internals of the running container to generate a summary */\n submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult>;\n\n /** Callback whenever a new SummaryAck is received, to update internal tracking state */\n refreshLatestSummaryAck(\n proposalHandle: string,\n ackHandle: string,\n summaryRefSeq: number,\n summaryLogger: ITelemetryLogger,\n ): Promise<void>;\n}\n\n/**\n * @deprecated Options that control the behavior of a running summarizer.\n * */\nexport interface ISummarizerOptions {\n /**\n * Set to true to disable the default heuristics from running; false by default.\n * This affects only the heuristics around when a summarizer should\n * submit summaries. So when it is disabled, summarizer clients should\n * not be expected to summarize unless an on-demand summary is requested.\n */\n disableHeuristics: boolean;\n}\n\nexport interface ISummarizingWarning extends ContainerWarning {\n readonly errorType: \"summarizingError\";\n readonly logged: boolean;\n}\n\nexport interface IConnectableRuntime {\n readonly disposed: boolean;\n readonly connected: boolean;\n readonly clientId: string | undefined;\n readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;\n once(event: \"connected\" | \"disconnected\" | \"dispose\", listener: () => void): this;\n}\n\nexport interface ISummarizerRuntime extends IConnectableRuntime {\n readonly logger: ITelemetryLogger;\n /** clientId of parent (non-summarizing) container that owns summarizer container */\n readonly summarizerClientId: string | undefined;\n closeFn(): void;\n /** @deprecated 1.0, please remove all implementations and usage */\n on(event: \"batchEnd\", listener: (error: any, op: ISequencedDocumentMessage) => void): this;\n /** @deprecated 1.0, please remove all implementations and usage */\n removeListener(event: \"batchEnd\", listener: (error: any, op: ISequencedDocumentMessage) => void): this;\n}\n\n/** Options affecting summarize behavior. */\nexport interface ISummarizeOptions {\n /** True to generate the full tree with no handle reuse optimizations; defaults to false */\n readonly fullTree?: boolean;\n /** True to ask the server what the latest summary is first; defaults to false */\n readonly refreshLatestAck?: boolean;\n}\n\nexport interface ISubmitSummaryOptions extends ISummarizeOptions {\n /** Logger to use for correlated summary events */\n readonly summaryLogger: ITelemetryLogger;\n /** Tells when summary process should be cancelled */\n readonly cancellationToken: ISummaryCancellationToken;\n}\n\nexport interface IOnDemandSummarizeOptions extends ISummarizeOptions {\n /** Reason for generating summary. */\n readonly reason: string;\n}\n\n/** Options to use when enqueueing a summarize attempt. */\nexport interface IEnqueueSummarizeOptions extends IOnDemandSummarizeOptions {\n /** If specified, The summarize attempt will not occur until after this sequence number. */\n readonly afterSequenceNumber?: number;\n /**\n * True to override the existing enqueued summarize attempt if there is one.\n * This will guarantee that this attempt gets enqueued. If override is false,\n * than an existing enqueued summarize attempt will block a new one from being\n * enqueued. There can only be one enqueued at a time. Defaults to false.\n */\n readonly override?: boolean;\n}\n\n/**\n * In addition to the normal summary tree + stats, this contains additional stats\n * only relevant at the root of the tree.\n */\nexport interface IGeneratedSummaryStats extends ISummaryStats {\n /** The total number of data stores in the container. */\n readonly dataStoreCount: number;\n /** The number of data stores that were summarized in this summary. */\n readonly summarizedDataStoreCount: number;\n /** The number of data stores whose GC reference state was updated in this summary. */\n readonly gcStateUpdatedDataStoreCount?: number;\n /** The size of the gc blobs in this summary. */\n readonly gcTotalBlobsSize?: number;\n /** The number of gc blobs in this summary. */\n readonly gcBlobNodeCount?: number;\n /** The summary number for a container's summary. Incremented on summaries throughout its lifetime. */\n readonly summaryNumber: number;\n}\n\n/** Base results for all submitSummary attempts. */\nexport interface IBaseSummarizeResult {\n readonly stage: \"base\";\n /** Error object related to failed summarize attempt. */\n readonly error: any;\n /** Reference sequence number as of the generate summary attempt. */\n readonly referenceSequenceNumber: number;\n readonly minimumSequenceNumber: number;\n}\n\n/** Results of submitSummary after generating the summary tree. */\nexport interface IGenerateSummaryTreeResult extends Omit<IBaseSummarizeResult, \"stage\"> {\n readonly stage: \"generate\";\n /** Generated summary tree. */\n readonly summaryTree: ISummaryTree;\n /** Stats for generated summary tree. */\n readonly summaryStats: IGeneratedSummaryStats;\n /** Time it took to generate the summary tree and stats. */\n readonly generateDuration: number;\n /** True if the full tree regeneration with no handle reuse optimizations was forced. */\n readonly forcedFullTree: boolean;\n}\n\n/** Results of submitSummary after uploading the tree to storage. */\nexport interface IUploadSummaryResult extends Omit<IGenerateSummaryTreeResult, \"stage\"> {\n readonly stage: \"upload\";\n /** The handle returned by storage pointing to the uploaded summary tree. */\n readonly handle: string;\n /** Time it took to upload the summary tree to storage. */\n readonly uploadDuration: number;\n}\n\n/** Results of submitSummary after submitting the summarize op. */\nexport interface ISubmitSummaryOpResult extends Omit<IUploadSummaryResult, \"stage\" | \"error\"> {\n readonly stage: \"submit\";\n /** The client sequence number of the summarize op submitted for the summary. */\n readonly clientSequenceNumber: number;\n /** Time it took to submit the summarize op to the broadcasting service. */\n readonly submitOpDuration: number;\n}\n\n/**\n * Strict type representing result of a submitSummary attempt.\n * The result consists of 4 possible stages, each with its own data.\n * The data is cumulative, so each stage will contain the data from the previous stages.\n * If the final \"submitted\" stage is not reached, the result may contain the error object.\n * Stages:\n * 1. \"base\" - stopped before the summary tree was even generated, and the result only contains the base data\n * 2. \"generate\" - the summary tree was generated, and the result will contain that tree + stats\n * 3. \"upload\" - the summary was uploaded to storage, and the result contains the server-provided handle\n * 4. \"submit\" - the summarize op was submitted, and the result contains the op client sequence number.\n */\nexport type SubmitSummaryResult =\n | IBaseSummarizeResult\n | IGenerateSummaryTreeResult\n | IUploadSummaryResult\n | ISubmitSummaryOpResult;\n\nexport interface IBroadcastSummaryResult {\n readonly summarizeOp: ISummaryOpMessage;\n readonly broadcastDuration: number;\n}\n\nexport interface IAckSummaryResult {\n readonly summaryAckOp: ISummaryAckMessage;\n readonly ackNackDuration: number;\n}\n\nexport interface INackSummaryResult {\n readonly summaryNackOp: ISummaryNackMessage;\n readonly ackNackDuration: number;\n}\n\nexport type SummarizeResultPart<TSuccess, TFailure = undefined> = {\n success: true;\n data: TSuccess;\n} | {\n success: false;\n data: TFailure | undefined;\n message: string;\n error: any;\n retryAfterSeconds?: number;\n};\n\nexport interface ISummarizeResults {\n /** Resolves when we generate, upload, and submit the summary. */\n readonly summarySubmitted: Promise<SummarizeResultPart<SubmitSummaryResult>>;\n /** Resolves when we observe our summarize op broadcast. */\n readonly summaryOpBroadcasted: Promise<SummarizeResultPart<IBroadcastSummaryResult>>;\n /** Resolves when we receive a summaryAck or summaryNack. */\n readonly receivedSummaryAckOrNack: Promise<SummarizeResultPart<IAckSummaryResult, INackSummaryResult>>;\n}\n\nexport type EnqueueSummarizeResult = (ISummarizeResults & {\n /**\n * Indicates that another summarize attempt is not already enqueued,\n * and this attempt has been enqueued.\n */\n readonly alreadyEnqueued?: undefined;\n}) | (ISummarizeResults & {\n /** Indicates that another summarize attempt was already enqueued. */\n readonly alreadyEnqueued: true;\n /**\n * Indicates that the other enqueued summarize attempt was abandoned,\n * and this attempt has been enqueued enqueued.\n */\n readonly overridden: true;\n}) | {\n /** Indicates that another summarize attempt was already enqueued. */\n readonly alreadyEnqueued: true;\n /**\n * Indicates that the other enqueued summarize attempt remains enqueued,\n * and this attempt has not been enqueued.\n */\n readonly overridden?: undefined;\n};\n\nexport type SummarizerStopReason =\n /** Summarizer client failed to summarize in all 3 consecutive attempts. */\n | \"failToSummarize\"\n /** Parent client reported that it is no longer connected. */\n | \"parentNotConnected\"\n /**\n * Parent client reported that it is no longer elected the summarizer.\n * This is the normal flow; a disconnect will always trigger the parent\n * client to no longer be elected as responsible for summaries. Then it\n * tries to stop its spawned summarizer client.\n */\n | \"parentShouldNotSummarize\"\n /** Summarizer client was disconnected */\n | \"summarizerClientDisconnected\"\n /* running summarizer threw an exception */\n | \"summarizerException\";\n\nexport interface ISummarizerEvents extends IEvent {\n /**\n * An event indicating that the Summarizer is having problems summarizing\n */\n (event: \"summarizingError\", listener: (error: ISummarizingWarning) => void);\n}\n\nexport interface ISummarizer extends\n IEventProvider<ISummarizerEvents>, IFluidLoadable, Partial<IProvideSummarizer> {\n /*\n * Asks summarizer to move to exit.\n * Summarizer will finish current processes, which may take a while.\n * For example, summarizer may complete last summary before exiting.\n */\n stop(reason: SummarizerStopReason): void;\n\n /* Closes summarizer. Any pending processes (summary in flight) are abandoned. */\n close(): void;\n\n run(onBehalfOf: string, disableHeuristics?: boolean): Promise<SummarizerStopReason>;\n\n /**\n * Attempts to generate a summary on demand. If already running, takes no action.\n * @param options - options controlling the summarize attempt\n * @returns an alreadyRunning promise if a summarize attempt is already in progress,\n * which will resolve when the current attempt completes. At that point caller can\n * decide to try again or not. Otherwise, it will return an object containing promises\n * that resolve as the summarize attempt progresses. They will resolve with success\n * false if a failure is encountered.\n */\n summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults;\n /**\n * Enqueue an attempt to summarize after the specified sequence number.\n * If afterSequenceNumber is provided, the summarize attempt is \"enqueued\"\n * to run once an eligible op comes in with sequenceNumber \\>= afterSequenceNumber.\n * @param options - options controlling the summarize attempt\n * @returns an object containing an alreadyEnqueued flag to indicate if another\n * summarize attempt has already been enqueued. It also may contain an overridden flag\n * when alreadyEnqueued is true, that indicates whether this attempt forced the\n * previous attempt to abort. If this attempt becomes enqueued, it returns an object\n * containing promises that resolve as the summarize attempt progresses. They will\n * resolve with success false if a failure is encountered.\n */\n enqueueSummarize(options: IEnqueueSummarizeOptions): EnqueueSummarizeResult;\n}\n\n/** Data about an attempt to summarize used for heuristics. */\nexport interface ISummarizeAttempt {\n /** Reference sequence number when summary was generated or attempted */\n readonly refSequenceNumber: number;\n\n /** Time of summary attempt after it was sent or attempted */\n readonly summaryTime: number;\n\n /** Sequence number of summary op */\n summarySequenceNumber?: number;\n}\n\n/** Data relevant for summary heuristics. */\nexport interface ISummarizeHeuristicData {\n /** Latest received op sequence number */\n lastOpSequenceNumber: number;\n\n /** Most recent summary attempt from this client */\n readonly lastAttempt: ISummarizeAttempt;\n\n /** Most recent summary that received an ack */\n readonly lastSuccessfulSummary: Readonly<ISummarizeAttempt>;\n\n /** Number of runtime ops since last summary */\n numRuntimeOps: number;\n\n /** Number of non-runtime ops since last summary */\n numNonRuntimeOps: number;\n\n /** Cumulative size in bytes of all the ops since the last summary */\n totalOpsSize: number;\n\n /** Wether or not this instance contains adjusted metrics due to missing op data */\n hasMissingOpData: boolean;\n\n /**\n * Updates lastAttempt and lastSuccessfulAttempt based on the last summary.\n * @param lastSummary - last ack summary\n */\n updateWithLastSummaryAckInfo(lastSummary: ISummarizeAttempt): void;\n\n /**\n * Records a summary attempt. If the attempt was successfully sent,\n * provide the reference sequence number, otherwise it will be set\n * to the last seen op sequence number.\n * @param referenceSequenceNumber - reference sequence number of sent summary\n */\n recordAttempt(referenceSequenceNumber?: number): void;\n\n /** Mark that the last sent summary attempt has received an ack */\n markLastAttemptAsSuccessful(): void;\n}\n\n/** Responsible for running heuristics determining when to summarize. */\nexport interface ISummarizeHeuristicRunner {\n /** Start specific heuristic trackers (ex: idle timer) */\n start(): void;\n\n /** Runs the heuristics to determine if it should try to summarize */\n run(): void;\n\n /** Runs a different heuristic to check if it should summarize before closing */\n shouldRunLastSummary(): boolean;\n\n /** Disposes of resources */\n dispose(): void;\n}\n\ntype ISummarizeTelemetryRequiredProperties =\n /** Reason code for attempting to summarize */\n \"reason\";\n\ntype ISummarizeTelemetryOptionalProperties =\n /** Number of attempts within the last time window, used for calculating the throttle delay. */\n \"summaryAttempts\" |\n /** Number of attempts within the current phase (currently capped at 2 ) */\n \"summaryAttemptsPerPhase\" |\n /** One-based count of phases we've attempted (used to index into an array of ISummarizeOptions */\n \"summaryAttemptPhase\" |\n keyof ISummarizeOptions;\n\nexport type ISummarizeTelemetryProperties =\n Pick<ITelemetryProperties, ISummarizeTelemetryRequiredProperties> &\n Partial<Pick<ITelemetryProperties, ISummarizeTelemetryOptionalProperties>>;\n\n/** Strategy used to heuristically determine when we should run a summary */\nexport interface ISummaryHeuristicStrategy {\n /** Summarize reason for this summarize heuristic strategy (ex: \"maxTime\") */\n summarizeReason: Readonly<SummarizeReason>;\n\n /**\n * Determines if this strategy's summarize criteria been met\n * @param configuration - summary configuration we are to check against\n * @param heuristicData - heuristic data used to confirm conditions are met\n */\n shouldRunSummary(configuration: ISummaryConfigurationHeuristics, heuristicData: ISummarizeHeuristicData): boolean;\n}\n\ntype SummaryGeneratorRequiredTelemetryProperties =\n /** True to generate the full tree with no handle reuse optimizations */\n \"fullTree\" |\n /** Time since we last attempted to generate a summary */\n \"timeSinceLastAttempt\" |\n /** Time since we last successfully generated a summary */\n \"timeSinceLastSummary\";\n\ntype SummaryGeneratorOptionalTelemetryProperties =\n /** Reference sequence number as of the generate summary attempt. */\n \"referenceSequenceNumber\" |\n /** minimum sequence number (at the reference sequence number) */\n \"minimumSequenceNumber\" |\n /** Delta between the current reference sequence number and the reference sequence number of the last attempt */\n \"opsSinceLastAttempt\" |\n /** Delta between the current reference sequence number and the reference sequence number of the last summary */\n \"opsSinceLastSummary\" |\n /** Delta in sum of op sizes between the current reference sequence number and the reference\n * sequence number of the last summary */\n \"opsSizesSinceLastSummary\" |\n /** Delta between the number of non-runtime ops since the last summary */\n \"nonRuntimeOpsSinceLastSummary\" |\n /** Wether or not this instance contains adjusted metrics due to missing op data */\n \"hasMissingOpData\" |\n /** Time it took to generate the summary tree and stats. */\n \"generateDuration\" |\n /** The handle returned by storage pointing to the uploaded summary tree. */\n \"handle\" |\n /** Time it took to upload the summary tree to storage. */\n \"uploadDuration\" |\n /** The client sequence number of the summarize op submitted for the summary. */\n \"clientSequenceNumber\" |\n /** Time it took for this summary to be acked after it was generated */\n \"ackWaitDuration\" |\n /** Reference sequence number of the ack/nack message */\n \"ackNackSequenceNumber\" |\n /** Actual sequence number of the summary op proposal. */\n \"summarySequenceNumber\" |\n /** Optional Retry-After time in seconds. If specified, the client should wait this many seconds before retrying. */\n \"nackRetryAfter\";\n\nexport type SummaryGeneratorTelemetry =\n Pick<ITelemetryProperties, SummaryGeneratorRequiredTelemetryProperties> &\n Partial<Pick<ITelemetryProperties, SummaryGeneratorOptionalTelemetryProperties>>;\n\nexport interface ISummarizeRunnerTelemetry extends ITelemetryLoggerPropertyBag {\n /** Number of times the summarizer run. */\n summarizeCount: () => number;\n /** Number of successful attempts to summarize. */\n summarizerSuccessfulAttempts: () => number;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"summarizerTypes.js","sourceRoot":"","sources":["../src/summarizerTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAuBH;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAA6B,aAAa,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n IEvent,\n IEventProvider,\n ITelemetryLogger,\n ITelemetryProperties,\n} from \"@fluidframework/common-definitions\";\nimport { ITelemetryLoggerPropertyBag } from \"@fluidframework/telemetry-utils\";\nimport {\n IFluidLoadable,\n} from \"@fluidframework/core-interfaces\";\nimport { ContainerWarning, IDeltaManager } from \"@fluidframework/container-definitions\";\nimport {\n ISequencedDocumentMessage,\n ISummaryTree,\n IDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport { ISummaryStats } from \"@fluidframework/runtime-definitions\";\nimport { ISummaryAckMessage, ISummaryNackMessage, ISummaryOpMessage } from \"./summaryCollection\";\nimport { SummarizeReason } from \"./summaryGenerator\";\nimport { ISummaryConfigurationHeuristics } from \".\";\n\n/**\n * @deprecated This will be removed in a later release.\n */\nexport const ISummarizer: keyof IProvideSummarizer = \"ISummarizer\";\n\n/**\n * @deprecated This will be removed in a later release.\n */\nexport interface IProvideSummarizer {\n /**\n * @deprecated This will be removed in a later release.\n */\n readonly ISummarizer: ISummarizer;\n}\n\n/**\n * Similar to AbortSignal, but using promise instead of events\n * @param T - cancellation reason type\n */\nexport interface ICancellationToken<T> {\n /** Tells if this cancellable token is cancelled */\n readonly cancelled: boolean;\n /**\n * Promise that gets fulfilled when this cancellable token is cancelled\n * @returns reason of cancellation\n */\n readonly waitCancelled: Promise<T>;\n}\n\n/* Similar to AbortSignal, but using promise instead of events */\nexport type ISummaryCancellationToken = ICancellationToken<SummarizerStopReason>;\n\nexport interface ISummarizerInternalsProvider {\n /** Encapsulates the work to walk the internals of the running container to generate a summary */\n submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult>;\n\n /** Callback whenever a new SummaryAck is received, to update internal tracking state */\n refreshLatestSummaryAck(\n proposalHandle: string,\n ackHandle: string,\n summaryRefSeq: number,\n summaryLogger: ITelemetryLogger,\n ): Promise<void>;\n}\n\n/**\n * @deprecated Options that control the behavior of a running summarizer.\n * */\nexport interface ISummarizerOptions {\n /**\n * Set to true to disable the default heuristics from running; false by default.\n * This affects only the heuristics around when a summarizer should\n * submit summaries. So when it is disabled, summarizer clients should\n * not be expected to summarize unless an on-demand summary is requested.\n */\n disableHeuristics: boolean;\n}\n\nexport interface ISummarizingWarning extends ContainerWarning {\n readonly errorType: \"summarizingError\";\n readonly logged: boolean;\n}\n\nexport interface IConnectableRuntime {\n readonly disposed: boolean;\n readonly connected: boolean;\n readonly clientId: string | undefined;\n readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;\n once(event: \"connected\" | \"disconnected\" | \"dispose\", listener: () => void): this;\n}\n\nexport interface ISummarizerRuntime extends IConnectableRuntime {\n readonly logger: ITelemetryLogger;\n /** clientId of parent (non-summarizing) container that owns summarizer container */\n readonly summarizerClientId: string | undefined;\n closeFn(): void;\n /** @deprecated 1.0, please remove all implementations and usage */\n on(event: \"batchEnd\", listener: (error: any, op: ISequencedDocumentMessage) => void): this;\n /** @deprecated 1.0, please remove all implementations and usage */\n removeListener(event: \"batchEnd\", listener: (error: any, op: ISequencedDocumentMessage) => void): this;\n}\n\n/** Options affecting summarize behavior. */\nexport interface ISummarizeOptions {\n /** True to generate the full tree with no handle reuse optimizations; defaults to false */\n readonly fullTree?: boolean;\n /** True to ask the server what the latest summary is first; defaults to false */\n readonly refreshLatestAck?: boolean;\n}\n\nexport interface ISubmitSummaryOptions extends ISummarizeOptions {\n /** Logger to use for correlated summary events */\n readonly summaryLogger: ITelemetryLogger;\n /** Tells when summary process should be cancelled */\n readonly cancellationToken: ISummaryCancellationToken;\n}\n\nexport interface IOnDemandSummarizeOptions extends ISummarizeOptions {\n /** Reason for generating summary. */\n readonly reason: string;\n}\n\n/** Options to use when enqueueing a summarize attempt. */\nexport interface IEnqueueSummarizeOptions extends IOnDemandSummarizeOptions {\n /** If specified, The summarize attempt will not occur until after this sequence number. */\n readonly afterSequenceNumber?: number;\n /**\n * True to override the existing enqueued summarize attempt if there is one.\n * This will guarantee that this attempt gets enqueued. If override is false,\n * than an existing enqueued summarize attempt will block a new one from being\n * enqueued. There can only be one enqueued at a time. Defaults to false.\n */\n readonly override?: boolean;\n}\n\n/**\n * In addition to the normal summary tree + stats, this contains additional stats\n * only relevant at the root of the tree.\n */\nexport interface IGeneratedSummaryStats extends ISummaryStats {\n /** The total number of data stores in the container. */\n readonly dataStoreCount: number;\n /** The number of data stores that were summarized in this summary. */\n readonly summarizedDataStoreCount: number;\n /** The number of data stores whose GC reference state was updated in this summary. */\n readonly gcStateUpdatedDataStoreCount?: number;\n /** The size of the gc blobs in this summary. */\n readonly gcTotalBlobsSize?: number;\n /** The number of gc blobs in this summary. */\n readonly gcBlobNodeCount?: number;\n /** The summary number for a container's summary. Incremented on summaries throughout its lifetime. */\n readonly summaryNumber: number;\n}\n\n/** Base results for all submitSummary attempts. */\nexport interface IBaseSummarizeResult {\n readonly stage: \"base\";\n /** Error object related to failed summarize attempt. */\n readonly error: any;\n /** Reference sequence number as of the generate summary attempt. */\n readonly referenceSequenceNumber: number;\n readonly minimumSequenceNumber: number;\n}\n\n/** Results of submitSummary after generating the summary tree. */\nexport interface IGenerateSummaryTreeResult extends Omit<IBaseSummarizeResult, \"stage\"> {\n readonly stage: \"generate\";\n /** Generated summary tree. */\n readonly summaryTree: ISummaryTree;\n /** Stats for generated summary tree. */\n readonly summaryStats: IGeneratedSummaryStats;\n /** Time it took to generate the summary tree and stats. */\n readonly generateDuration: number;\n /** True if the full tree regeneration with no handle reuse optimizations was forced. */\n readonly forcedFullTree: boolean;\n}\n\n/** Results of submitSummary after uploading the tree to storage. */\nexport interface IUploadSummaryResult extends Omit<IGenerateSummaryTreeResult, \"stage\"> {\n readonly stage: \"upload\";\n /** The handle returned by storage pointing to the uploaded summary tree. */\n readonly handle: string;\n /** Time it took to upload the summary tree to storage. */\n readonly uploadDuration: number;\n}\n\n/** Results of submitSummary after submitting the summarize op. */\nexport interface ISubmitSummaryOpResult extends Omit<IUploadSummaryResult, \"stage\" | \"error\"> {\n readonly stage: \"submit\";\n /** The client sequence number of the summarize op submitted for the summary. */\n readonly clientSequenceNumber: number;\n /** Time it took to submit the summarize op to the broadcasting service. */\n readonly submitOpDuration: number;\n}\n\n/**\n * Strict type representing result of a submitSummary attempt.\n * The result consists of 4 possible stages, each with its own data.\n * The data is cumulative, so each stage will contain the data from the previous stages.\n * If the final \"submitted\" stage is not reached, the result may contain the error object.\n * Stages:\n * 1. \"base\" - stopped before the summary tree was even generated, and the result only contains the base data\n * 2. \"generate\" - the summary tree was generated, and the result will contain that tree + stats\n * 3. \"upload\" - the summary was uploaded to storage, and the result contains the server-provided handle\n * 4. \"submit\" - the summarize op was submitted, and the result contains the op client sequence number.\n */\nexport type SubmitSummaryResult =\n | IBaseSummarizeResult\n | IGenerateSummaryTreeResult\n | IUploadSummaryResult\n | ISubmitSummaryOpResult;\n\nexport interface IBroadcastSummaryResult {\n readonly summarizeOp: ISummaryOpMessage;\n readonly broadcastDuration: number;\n}\n\nexport interface IAckSummaryResult {\n readonly summaryAckOp: ISummaryAckMessage;\n readonly ackNackDuration: number;\n}\n\nexport interface INackSummaryResult {\n readonly summaryNackOp: ISummaryNackMessage;\n readonly ackNackDuration: number;\n}\n\nexport type SummarizeResultPart<TSuccess, TFailure = undefined> = {\n success: true;\n data: TSuccess;\n} | {\n success: false;\n data: TFailure | undefined;\n message: string;\n error: any;\n retryAfterSeconds?: number;\n};\n\nexport interface ISummarizeResults {\n /** Resolves when we generate, upload, and submit the summary. */\n readonly summarySubmitted: Promise<SummarizeResultPart<SubmitSummaryResult>>;\n /** Resolves when we observe our summarize op broadcast. */\n readonly summaryOpBroadcasted: Promise<SummarizeResultPart<IBroadcastSummaryResult>>;\n /** Resolves when we receive a summaryAck or summaryNack. */\n readonly receivedSummaryAckOrNack: Promise<SummarizeResultPart<IAckSummaryResult, INackSummaryResult>>;\n}\n\nexport type EnqueueSummarizeResult = (ISummarizeResults & {\n /**\n * Indicates that another summarize attempt is not already enqueued,\n * and this attempt has been enqueued.\n */\n readonly alreadyEnqueued?: undefined;\n}) | (ISummarizeResults & {\n /** Indicates that another summarize attempt was already enqueued. */\n readonly alreadyEnqueued: true;\n /**\n * Indicates that the other enqueued summarize attempt was abandoned,\n * and this attempt has been enqueued enqueued.\n */\n readonly overridden: true;\n}) | {\n /** Indicates that another summarize attempt was already enqueued. */\n readonly alreadyEnqueued: true;\n /**\n * Indicates that the other enqueued summarize attempt remains enqueued,\n * and this attempt has not been enqueued.\n */\n readonly overridden?: undefined;\n};\n\nexport type SummarizerStopReason =\n /** Summarizer client failed to summarize in all 3 consecutive attempts. */\n | \"failToSummarize\"\n /** Parent client reported that it is no longer connected. */\n | \"parentNotConnected\"\n /**\n * Parent client reported that it is no longer elected the summarizer.\n * This is the normal flow; a disconnect will always trigger the parent\n * client to no longer be elected as responsible for summaries. Then it\n * tries to stop its spawned summarizer client.\n */\n | \"parentShouldNotSummarize\"\n /** Summarizer client was disconnected */\n | \"summarizerClientDisconnected\"\n /* running summarizer threw an exception */\n | \"summarizerException\";\n\nexport interface ISummarizerEvents extends IEvent {\n /**\n * An event indicating that the Summarizer is having problems summarizing\n */\n (event: \"summarizingError\", listener: (error: ISummarizingWarning) => void);\n}\n\nexport interface ISummarizer extends\n IEventProvider<ISummarizerEvents>, IFluidLoadable, Partial<IProvideSummarizer> {\n /*\n * Asks summarizer to move to exit.\n * Summarizer will finish current processes, which may take a while.\n * For example, summarizer may complete last summary before exiting.\n */\n stop(reason: SummarizerStopReason): void;\n\n /* Closes summarizer. Any pending processes (summary in flight) are abandoned. */\n close(): void;\n\n run(onBehalfOf: string, disableHeuristics?: boolean): Promise<SummarizerStopReason>;\n\n /**\n * Attempts to generate a summary on demand. If already running, takes no action.\n * @param options - options controlling the summarize attempt\n * @returns an alreadyRunning promise if a summarize attempt is already in progress,\n * which will resolve when the current attempt completes. At that point caller can\n * decide to try again or not. Otherwise, it will return an object containing promises\n * that resolve as the summarize attempt progresses. They will resolve with success\n * false if a failure is encountered.\n */\n summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults;\n /**\n * Enqueue an attempt to summarize after the specified sequence number.\n * If afterSequenceNumber is provided, the summarize attempt is \"enqueued\"\n * to run once an eligible op comes in with sequenceNumber \\>= afterSequenceNumber.\n * @param options - options controlling the summarize attempt\n * @returns an object containing an alreadyEnqueued flag to indicate if another\n * summarize attempt has already been enqueued. It also may contain an overridden flag\n * when alreadyEnqueued is true, that indicates whether this attempt forced the\n * previous attempt to abort. If this attempt becomes enqueued, it returns an object\n * containing promises that resolve as the summarize attempt progresses. They will\n * resolve with success false if a failure is encountered.\n */\n enqueueSummarize(options: IEnqueueSummarizeOptions): EnqueueSummarizeResult;\n}\n\n/** Data about an attempt to summarize used for heuristics. */\nexport interface ISummarizeAttempt {\n /** Reference sequence number when summary was generated or attempted */\n readonly refSequenceNumber: number;\n\n /** Time of summary attempt after it was sent or attempted */\n readonly summaryTime: number;\n\n /** Sequence number of summary op */\n summarySequenceNumber?: number;\n}\n\n/** Data relevant for summary heuristics. */\nexport interface ISummarizeHeuristicData {\n /** Latest received op sequence number */\n lastOpSequenceNumber: number;\n\n /** Most recent summary attempt from this client */\n readonly lastAttempt: ISummarizeAttempt;\n\n /** Most recent summary that received an ack */\n readonly lastSuccessfulSummary: Readonly<ISummarizeAttempt>;\n\n /** Number of runtime ops since last summary */\n numRuntimeOps: number;\n\n /** Number of non-runtime ops since last summary */\n numNonRuntimeOps: number;\n\n /** Cumulative size in bytes of all the ops since the last summary */\n totalOpsSize: number;\n\n /** Wether or not this instance contains adjusted metrics due to missing op data */\n hasMissingOpData: boolean;\n\n /**\n * Updates lastAttempt and lastSuccessfulAttempt based on the last summary.\n * @param lastSummary - last ack summary\n */\n updateWithLastSummaryAckInfo(lastSummary: ISummarizeAttempt): void;\n\n /**\n * Records a summary attempt. If the attempt was successfully sent,\n * provide the reference sequence number, otherwise it will be set\n * to the last seen op sequence number.\n * @param referenceSequenceNumber - reference sequence number of sent summary\n */\n recordAttempt(referenceSequenceNumber?: number): void;\n\n /** Mark that the last sent summary attempt has received an ack */\n markLastAttemptAsSuccessful(): void;\n}\n\n/** Responsible for running heuristics determining when to summarize. */\nexport interface ISummarizeHeuristicRunner {\n /** Start specific heuristic trackers (ex: idle timer) */\n start(): void;\n\n /** Runs the heuristics to determine if it should try to summarize */\n run(): void;\n\n /** Runs a different heuristic to check if it should summarize before closing */\n shouldRunLastSummary(): boolean;\n\n /** Disposes of resources */\n dispose(): void;\n}\n\ntype ISummarizeTelemetryRequiredProperties =\n /** Reason code for attempting to summarize */\n \"reason\";\n\ntype ISummarizeTelemetryOptionalProperties =\n /** Number of attempts within the last time window, used for calculating the throttle delay. */\n \"summaryAttempts\" |\n /** Number of attempts within the current phase (currently capped at 2 ) */\n \"summaryAttemptsPerPhase\" |\n /** One-based count of phases we've attempted (used to index into an array of ISummarizeOptions */\n \"summaryAttemptPhase\" |\n keyof ISummarizeOptions;\n\nexport type ISummarizeTelemetryProperties =\n Pick<ITelemetryProperties, ISummarizeTelemetryRequiredProperties> &\n Partial<Pick<ITelemetryProperties, ISummarizeTelemetryOptionalProperties>>;\n\n/** Strategy used to heuristically determine when we should run a summary */\nexport interface ISummaryHeuristicStrategy {\n /** Summarize reason for this summarize heuristic strategy (ex: \"maxTime\") */\n summarizeReason: Readonly<SummarizeReason>;\n\n /**\n * Determines if this strategy's summarize criteria been met\n * @param configuration - summary configuration we are to check against\n * @param heuristicData - heuristic data used to confirm conditions are met\n */\n shouldRunSummary(configuration: ISummaryConfigurationHeuristics, heuristicData: ISummarizeHeuristicData): boolean;\n}\n\ntype SummaryGeneratorRequiredTelemetryProperties =\n /** True to generate the full tree with no handle reuse optimizations */\n \"fullTree\" |\n /** Time since we last attempted to generate a summary */\n \"timeSinceLastAttempt\" |\n /** Time since we last successfully generated a summary */\n \"timeSinceLastSummary\";\n\ntype SummaryGeneratorOptionalTelemetryProperties =\n /** Reference sequence number as of the generate summary attempt. */\n \"referenceSequenceNumber\" |\n /** minimum sequence number (at the reference sequence number) */\n \"minimumSequenceNumber\" |\n /** Delta between the current reference sequence number and the reference sequence number of the last attempt */\n \"opsSinceLastAttempt\" |\n /** Delta between the current reference sequence number and the reference sequence number of the last summary */\n \"opsSinceLastSummary\" |\n /** Delta in sum of op sizes between the current reference sequence number and the reference\n * sequence number of the last summary */\n \"opsSizesSinceLastSummary\" |\n /** Delta between the number of non-runtime ops since the last summary */\n \"nonRuntimeOpsSinceLastSummary\" |\n /** Wether or not this instance contains adjusted metrics due to missing op data */\n \"hasMissingOpData\" |\n /** Time it took to generate the summary tree and stats. */\n \"generateDuration\" |\n /** The handle returned by storage pointing to the uploaded summary tree. */\n \"handle\" |\n /** Time it took to upload the summary tree to storage. */\n \"uploadDuration\" |\n /** The client sequence number of the summarize op submitted for the summary. */\n \"clientSequenceNumber\" |\n /** Time it took for this summary to be acked after it was generated */\n \"ackWaitDuration\" |\n /** Reference sequence number of the ack/nack message */\n \"ackNackSequenceNumber\" |\n /** Actual sequence number of the summary op proposal. */\n \"summarySequenceNumber\" |\n /** Optional Retry-After time in seconds. If specified, the client should wait this many seconds before retrying. */\n \"nackRetryAfter\";\n\nexport type SummaryGeneratorTelemetry =\n Pick<ITelemetryProperties, SummaryGeneratorRequiredTelemetryProperties> &\n Partial<Pick<ITelemetryProperties, SummaryGeneratorOptionalTelemetryProperties>>;\n\nexport interface ISummarizeRunnerTelemetry extends ITelemetryLoggerPropertyBag {\n /** Number of times the summarizer run. */\n summarizeCount: () => number;\n /** Number of successful attempts to summarize. */\n summarizerSuccessfulAttempts: () => number;\n}\n"]}
|
|
@@ -98,6 +98,7 @@ export declare class SummaryCollection extends TypedEventEmitter<ISummaryCollect
|
|
|
98
98
|
* @returns The latest acked summary
|
|
99
99
|
*/
|
|
100
100
|
waitSummaryAck(referenceSequenceNumber: number): Promise<IAckedSummary>;
|
|
101
|
+
private parseContent;
|
|
101
102
|
/**
|
|
102
103
|
* Handler for ops; only handles ops relating to summaries.
|
|
103
104
|
* @param op - op message to handle
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summaryCollection.d.ts","sourceRoot":"","sources":["../src/summaryCollection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3F,OAAO,EAAoB,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AACtE,OAAO,EACH,gBAAgB,EAChB,yBAAyB,EACzB,WAAW,EACX,eAAe,EACf,YAAY,EACZ,WAAW,EACd,MAAM,sCAAsC,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,yBAAyB;IAChE,IAAI,EAAE,WAAW,CAAC,SAAS,CAAC;IAC5B,QAAQ,EAAE,eAAe,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,yBAAyB;IACjE,IAAI,EAAE,WAAW,CAAC,UAAU,CAAC;IAC7B,QAAQ,EAAE,WAAW,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,yBAAyB;IAClE,IAAI,EAAE,WAAW,CAAC,WAAW,CAAC;IAC9B,QAAQ,EAAE,YAAY,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,aAAa,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC5C,WAAW,IAAI,OAAO,CAAC,kBAAkB,GAAG,mBAAmB,CAAC,CAAC;CACpE;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;CAC3C;AAoED;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,WAAW;IACtD,YAAY,CAAC,oBAAoB,EAAE,MAAM,GAAG,QAAQ,CAAC;IACrD,WAAW,IAAI,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;CACrD;AA8DD,oBAAY,iBAAiB,GAAG,WAAW,CAAC,SAAS,GAAG,WAAW,CAAC,UAAU,GAAG,WAAW,CAAC,WAAW,GAAG,SAAS,CAAC;AACrH,oBAAY,qBAAqB,GAAG,CAAC,EAAE,EAAE,yBAAyB,KAAK,IAAI,CAAC;AAC5E,MAAM,WAAW,0BAA2B,SAAQ,MAAM;IACtD,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,qBAAqB,OAAE;CAC/D;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,iBAAiB,CAAC,0BAA0B,CAAC;IAgC5E,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IA/B3B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA2C;IAE3E,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA8B;IAC/D,OAAO,CAAC,kBAAkB,CAAwB;IAElD,OAAO,CAAC,oBAAoB,CAAqB;IACjD,OAAO,CAAC,cAAc,CAAqB;IAC3C,OAAO,CAAC,8BAA8B,CAA2B;IACjE,OAAO,CAAC,OAAO,CAA4B;IAE3C,IAAW,SAAS,IAAI,aAAa,GAAG,SAAS,CAAyB;IAEnE,IAAI,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,IAAI,EAAE,UAAU,CAAC,qBAAqB,CAAC,GAAG,OAAO;IAI1F,IAAW,eAAe,WAGzB;IAEM,aAAa,CAAC,QAAQ,EAAE,MAAM,IAAI;IAIlC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,IAAI;gBAKvB,YAAY,EAAE,aAAa,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,EACxE,MAAM,EAAE,gBAAgB;
|
|
1
|
+
{"version":3,"file":"summaryCollection.d.ts","sourceRoot":"","sources":["../src/summaryCollection.ts"],"names":[],"mappings":"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"}
|
package/lib/summaryCollection.js
CHANGED
|
@@ -186,25 +186,44 @@ export class SummaryCollection extends TypedEventEmitter {
|
|
|
186
186
|
}
|
|
187
187
|
return this.lastAck;
|
|
188
188
|
}
|
|
189
|
+
parseContent(op) {
|
|
190
|
+
// back-compat: ADO #1385: Make this unconditional in the future,
|
|
191
|
+
// when Container.processRemoteMessage stops parsing contents. That said, we should move to
|
|
192
|
+
// listen for "op" events from ContainerRuntime, and parsing may not be required at all if
|
|
193
|
+
// ContainerRuntime.process() would parse it for all types of ops.
|
|
194
|
+
// Can make either of those changes only when LTS moves to a version that has no content
|
|
195
|
+
// parsing in loader layer!
|
|
196
|
+
if (typeof op.contents === "string") {
|
|
197
|
+
op.contents = JSON.parse(op.contents);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
189
200
|
/**
|
|
190
201
|
* Handler for ops; only handles ops relating to summaries.
|
|
191
202
|
* @param op - op message to handle
|
|
192
203
|
*/
|
|
193
|
-
handleOp(
|
|
204
|
+
handleOp(opArg) {
|
|
194
205
|
var _a;
|
|
206
|
+
const op = Object.assign({}, opArg);
|
|
195
207
|
switch (op.type) {
|
|
196
|
-
case MessageType.Summarize:
|
|
197
|
-
this.
|
|
198
|
-
return;
|
|
199
|
-
|
|
200
|
-
case MessageType.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
+
case MessageType.Summarize:
|
|
209
|
+
this.parseContent(op);
|
|
210
|
+
return this.handleSummaryOp(op);
|
|
211
|
+
case MessageType.SummaryAck:
|
|
212
|
+
case MessageType.SummaryNack:
|
|
213
|
+
// Old files (prior to PR #10077) may not contain this info
|
|
214
|
+
// back-compat: ADO #1385: remove cast when ISequencedDocumentMessage changes are propagated
|
|
215
|
+
if (op.data !== undefined) {
|
|
216
|
+
op.contents = JSON.parse(op.data);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
this.parseContent(op);
|
|
220
|
+
}
|
|
221
|
+
if (op.type === MessageType.SummaryAck) {
|
|
222
|
+
return this.handleSummaryAck(op);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
return this.handleSummaryNack(op);
|
|
226
|
+
}
|
|
208
227
|
default: {
|
|
209
228
|
// If the difference between timestamp of current op and last summary op is greater than
|
|
210
229
|
// the maxAckWaitTime, then we need to inform summarizer to not wait and summarize
|
|
@@ -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 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.sendTelemetryEvent({\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(\"op\", (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 private parseContent(op: ISequencedDocumentMessage) {\n // back-compat: ADO #1385: Make this unconditional in the future,\n // when Container.processRemoteMessage stops parsing contents. That said, we should move to\n // listen for \"op\" events from ContainerRuntime, and parsing may not be required at all if\n // ContainerRuntime.process() would parse it for all types of ops.\n // Can make either of those changes only when LTS moves to a version that has no content\n // parsing in loader layer!\n if (typeof op.contents === \"string\") {\n op.contents = JSON.parse(op.contents);\n }\n }\n\n /**\n * Handler for ops; only handles ops relating to summaries.\n * @param op - op message to handle\n */\n private handleOp(opArg: ISequencedDocumentMessage) {\n const op = { ...opArg };\n\n switch (op.type) {\n case MessageType.Summarize:\n this.parseContent(op);\n return this.handleSummaryOp(op as ISummaryOpMessage);\n case MessageType.SummaryAck:\n case MessageType.SummaryNack:\n // Old files (prior to PR #10077) may not contain this info\n // back-compat: ADO #1385: remove cast when ISequencedDocumentMessage changes are propagated\n if ((op as any).data !== undefined) {\n op.contents = JSON.parse((op as any).data);\n } else {\n this.parseContent(op);\n }\n if (op.type === MessageType.SummaryAck) {\n return this.handleSummaryAck(op as ISummaryAckMessage);\n } else {\n return this.handleSummaryNack(op as ISummaryNackMessage);\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.sendTelemetryEvent({\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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/container-runtime",
|
|
3
|
-
"version": "2.0.0-internal.1.
|
|
3
|
+
"version": "2.0.0-internal.1.2.0.93071",
|
|
4
4
|
"description": "Fluid container runtime",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -63,29 +63,29 @@
|
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
65
65
|
"@fluidframework/common-utils": "^1.0.0",
|
|
66
|
-
"@fluidframework/container-definitions": "
|
|
67
|
-
"@fluidframework/container-runtime-definitions": "
|
|
68
|
-
"@fluidframework/container-utils": "
|
|
69
|
-
"@fluidframework/core-interfaces": "
|
|
70
|
-
"@fluidframework/datastore": "
|
|
71
|
-
"@fluidframework/driver-definitions": "
|
|
72
|
-
"@fluidframework/driver-utils": "
|
|
73
|
-
"@fluidframework/garbage-collector": "
|
|
74
|
-
"@fluidframework/protocol-base": "^0.1037.
|
|
66
|
+
"@fluidframework/container-definitions": "2.0.0-internal.1.2.0.93071",
|
|
67
|
+
"@fluidframework/container-runtime-definitions": "2.0.0-internal.1.2.0.93071",
|
|
68
|
+
"@fluidframework/container-utils": "2.0.0-internal.1.2.0.93071",
|
|
69
|
+
"@fluidframework/core-interfaces": "2.0.0-internal.1.2.0.93071",
|
|
70
|
+
"@fluidframework/datastore": "2.0.0-internal.1.2.0.93071",
|
|
71
|
+
"@fluidframework/driver-definitions": "2.0.0-internal.1.2.0.93071",
|
|
72
|
+
"@fluidframework/driver-utils": "2.0.0-internal.1.2.0.93071",
|
|
73
|
+
"@fluidframework/garbage-collector": "2.0.0-internal.1.2.0.93071",
|
|
74
|
+
"@fluidframework/protocol-base": "^0.1037.2000-91174",
|
|
75
75
|
"@fluidframework/protocol-definitions": "^1.0.0",
|
|
76
|
-
"@fluidframework/runtime-definitions": "
|
|
77
|
-
"@fluidframework/runtime-utils": "
|
|
78
|
-
"@fluidframework/telemetry-utils": "
|
|
76
|
+
"@fluidframework/runtime-definitions": "2.0.0-internal.1.2.0.93071",
|
|
77
|
+
"@fluidframework/runtime-utils": "2.0.0-internal.1.2.0.93071",
|
|
78
|
+
"@fluidframework/telemetry-utils": "2.0.0-internal.1.2.0.93071",
|
|
79
79
|
"double-ended-queue": "^2.1.0-0",
|
|
80
80
|
"uuid": "^8.3.1"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
|
-
"@fluidframework/build-common": "^0.
|
|
84
|
-
"@fluidframework/build-tools": "^0.
|
|
83
|
+
"@fluidframework/build-common": "^1.0.0",
|
|
84
|
+
"@fluidframework/build-tools": "^0.4.4000",
|
|
85
85
|
"@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@^1.0.0",
|
|
86
86
|
"@fluidframework/eslint-config-fluid": "^0.28.2000",
|
|
87
|
-
"@fluidframework/mocha-test-setup": "
|
|
88
|
-
"@fluidframework/test-runtime-utils": "
|
|
87
|
+
"@fluidframework/mocha-test-setup": "2.0.0-internal.1.2.0.93071",
|
|
88
|
+
"@fluidframework/test-runtime-utils": "2.0.0-internal.1.2.0.93071",
|
|
89
89
|
"@microsoft/api-extractor": "^7.22.2",
|
|
90
90
|
"@rushstack/eslint-config": "^2.5.1",
|
|
91
91
|
"@types/double-ended-queue": "^2.1.0",
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { IBatchMessage } from "@fluidframework/container-definitions";
|
|
7
|
+
import { GenericError } from "@fluidframework/container-utils";
|
|
8
|
+
import { ContainerRuntimeMessage } from "./containerRuntime";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Message type used by BatchManager
|
|
12
|
+
*/
|
|
13
|
+
export type BatchMessage = IBatchMessage & {
|
|
14
|
+
localOpMetadata: unknown;
|
|
15
|
+
deserializedContent: ContainerRuntimeMessage;
|
|
16
|
+
referenceSequenceNumber: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Helper class that manages partial batch & rollback.
|
|
21
|
+
*/
|
|
22
|
+
export class BatchManager {
|
|
23
|
+
private pendingBatch: BatchMessage [] = [];
|
|
24
|
+
private batchContentSize = 0;
|
|
25
|
+
|
|
26
|
+
// The actual limit is 1Mb (socket.io and Kafka limits)
|
|
27
|
+
// We can't estimate it fully, as we
|
|
28
|
+
// - do not know what properties relay service will add
|
|
29
|
+
// - we do not stringify final op, thus we do not know how much escaping will be added.
|
|
30
|
+
private static readonly defaultMaxOpSizeInBytes = 950 * 1024;
|
|
31
|
+
|
|
32
|
+
public push(message: BatchMessage) {
|
|
33
|
+
this.pendingBatch.push(message);
|
|
34
|
+
this.batchContentSize += message.contents.length;
|
|
35
|
+
|
|
36
|
+
const opCount = this.pendingBatch.length;
|
|
37
|
+
const limit = BatchManager.defaultMaxOpSizeInBytes;
|
|
38
|
+
|
|
39
|
+
// Attempt to estimate batch size, aka socket message size.
|
|
40
|
+
// Each op has pretty large envelope, estimating to be 200 bytes.
|
|
41
|
+
// Also content will be strigified, and that adds a lot of overhead due to a lot of escape characters.
|
|
42
|
+
// Not taking it into account, as compression work should help there - compressed payload will be
|
|
43
|
+
// initially stored as base64, and that requires only 2 extra escape characters.
|
|
44
|
+
const socketMessageSize = this.batchContentSize + 200 * opCount;
|
|
45
|
+
|
|
46
|
+
if (socketMessageSize >= limit) {
|
|
47
|
+
// If the content length is larger than the client configured message size
|
|
48
|
+
// instead of splitting the content, we will fail by explicitly closing the container
|
|
49
|
+
throw new GenericError(
|
|
50
|
+
"BatchTooLarge",
|
|
51
|
+
/* error */ undefined,
|
|
52
|
+
{
|
|
53
|
+
opSize: message.contents.length,
|
|
54
|
+
batchContentSize: this.batchContentSize,
|
|
55
|
+
count: opCount,
|
|
56
|
+
limit,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public get empty() { return this.pendingBatch.length === 0; }
|
|
62
|
+
|
|
63
|
+
public popBatch() {
|
|
64
|
+
const batch = this.pendingBatch;
|
|
65
|
+
this.pendingBatch = [];
|
|
66
|
+
this.batchContentSize = 0;
|
|
67
|
+
return batch;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Capture the pending state at this point
|
|
72
|
+
*/
|
|
73
|
+
public checkpoint() {
|
|
74
|
+
const startPoint = this.pendingBatch.length;
|
|
75
|
+
return {
|
|
76
|
+
rollback: (process: (message: BatchMessage) => void) => {
|
|
77
|
+
for (let i = this.pendingBatch.length; i > startPoint;) {
|
|
78
|
+
i--;
|
|
79
|
+
const message = this.pendingBatch[i];
|
|
80
|
+
this.batchContentSize -= message.contents.length;
|
|
81
|
+
process(message);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
this.pendingBatch.length = startPoint;
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|