@fluidframework/container-runtime 2.100.0 → 2.101.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/CHANGELOG.md +17 -0
- package/container-runtime.test-files.tar +0 -0
- package/dist/blobManager/blobManager.d.ts +3 -0
- package/dist/blobManager/blobManager.d.ts.map +1 -1
- package/dist/blobManager/blobManager.js +3 -0
- package/dist/blobManager/blobManager.js.map +1 -1
- package/dist/blobManager/blobManagerSnapSum.d.ts +3 -0
- package/dist/blobManager/blobManagerSnapSum.d.ts.map +1 -1
- package/dist/blobManager/blobManagerSnapSum.js +12 -5
- package/dist/blobManager/blobManagerSnapSum.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +3 -1
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +6 -1
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +10 -7
- package/dist/containerRuntime.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +4 -0
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +3 -2
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +10 -4
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -12
- package/dist/index.js.map +1 -1
- package/dist/metadata.d.ts +14 -0
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +2 -2
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +13 -3
- package/dist/opLifecycle/opSplitter.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/runtimeLayerCompatState.d.ts +1 -1
- package/dist/summary/summarizerTypes.d.ts +3 -1
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/lib/blobManager/blobManager.d.ts +3 -0
- package/lib/blobManager/blobManager.d.ts.map +1 -1
- package/lib/blobManager/blobManager.js +3 -0
- package/lib/blobManager/blobManager.js.map +1 -1
- package/lib/blobManager/blobManagerSnapSum.d.ts +3 -0
- package/lib/blobManager/blobManagerSnapSum.d.ts.map +1 -1
- package/lib/blobManager/blobManagerSnapSum.js +12 -5
- package/lib/blobManager/blobManagerSnapSum.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +3 -1
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +6 -1
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +10 -7
- package/lib/containerRuntime.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +4 -0
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +3 -2
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +10 -4
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/metadata.d.ts +14 -0
- package/lib/metadata.d.ts.map +1 -1
- package/lib/metadata.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +2 -2
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +13 -3
- package/lib/opLifecycle/opSplitter.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/runtimeLayerCompatState.d.ts +1 -1
- package/lib/summary/summarizerTypes.d.ts +3 -1
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/package.json +18 -18
- package/src/blobManager/blobManager.ts +3 -0
- package/src/blobManager/blobManagerSnapSum.ts +12 -5
- package/src/connectionTelemetry.ts +15 -10
- package/src/containerRuntime.ts +17 -8
- package/src/gc/garbageCollection.ts +8 -6
- package/src/gc/gcDefinitions.ts +11 -4
- package/src/index.ts +5 -0
- package/src/metadata.ts +14 -0
- package/src/opLifecycle/opGroupingManager.ts +2 -2
- package/src/opLifecycle/opSplitter.ts +13 -3
- package/src/packageVersion.ts +1 -1
- package/src/summary/summarizerTypes.ts +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summarizerTypes.js","sourceRoot":"","sources":["../../src/summary/summarizerTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAiCH,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tIDeltaManager,\n\tContainerWarning,\n} from \"@fluidframework/container-definitions/internal\";\nimport type {\n\tISummarizerEvents,\n\tSummarizerStopReason,\n} from \"@fluidframework/container-runtime-definitions/internal\";\nimport type {\n\tIEventProvider,\n\tITelemetryBaseProperties,\n\tITelemetryBaseLogger,\n} from \"@fluidframework/core-interfaces\";\nimport type { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentMessage,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport type { ISummaryStats } from \"@fluidframework/runtime-definitions/internal\";\nimport type { TelemetryContext } from \"@fluidframework/runtime-utils/internal\";\nimport type {\n\tITelemetryLoggerExt,\n\tITelemetryLoggerPropertyBag,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { SummarizeReason } from \"./summarizerUtils.js\";\nimport type {\n\tEnqueueSummarizeResult,\n\tISummarizeResults,\n} from \"./summaryDelayLoadedModule/index.js\";\n\nexport const summarizerClientType = \"summarizer\";\n\n/**\n * Similar to AbortSignal, but using promise instead of events\n * @param T - cancellation reason type\n * @internal\n */\nexport interface ICancellationToken<T> {\n\t/**\n\t * Tells if this cancellable token is cancelled\n\t */\n\treadonly cancelled: boolean;\n\t/**\n\t * Promise that gets fulfilled when this cancellable token is cancelled\n\t * @returns reason of cancellation\n\t */\n\treadonly waitCancelled: Promise<T>;\n}\n\n/**\n * Similar to AbortSignal, but using promise instead of events\n * @internal\n */\nexport type ISummaryCancellationToken = ICancellationToken<SummarizerStopReason>;\n\n/**\n * Data required to update internal tracking state after receiving a Summary Ack.\n * @internal\n */\nexport interface IRefreshSummaryAckOptions {\n\t/**\n\t * Handle from the ack's summary op.\n\t */\n\treadonly proposalHandle: string | undefined;\n\t/**\n\t * Handle from the summary ack just received\n\t */\n\treadonly ackHandle: string;\n\t/**\n\t * Reference sequence number from the ack's summary op\n\t */\n\treadonly summaryRefSeq: number;\n\t/**\n\t * Telemetry logger to which telemetry events will be forwarded.\n\t */\n\treadonly summaryLogger: ITelemetryLoggerExt;\n}\n\n/**\n * @internal\n */\nexport interface ISummarizerInternalsProvider {\n\t/**\n\t * Encapsulates the work to walk the internals of the running container to generate a summary\n\t */\n\tsubmitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult>;\n\n\t/**\n\t * Callback whenever a new SummaryAck is received, to update internal tracking state\n\t */\n\trefreshLatestSummaryAck(options: IRefreshSummaryAckOptions): Promise<void>;\n}\n\n/**\n * @internal\n */\nexport interface ISummarizingWarning extends ContainerWarning {\n\treadonly errorType: \"summarizingError\";\n\treadonly logged: boolean;\n}\n\n/**\n * @internal\n */\nexport interface IConnectableRuntime {\n\treadonly disposed: boolean;\n\treadonly connected: boolean;\n\treadonly clientId: string | undefined;\n\tonce(event: \"connected\" | \"disconnected\" | \"dispose\", listener: () => void): this;\n}\n\n/**\n * @internal\n */\nexport interface ISummarizerRuntime extends IConnectableRuntime {\n\treadonly baseLogger: ITelemetryBaseLogger;\n\t/**\n\t * clientId of parent (non-summarizing) container that owns summarizer container\n\t */\n\treadonly summarizerClientId: string | undefined;\n\treadonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;\n\tdisposeFn(): void;\n\tcloseFn(): void;\n\ton(\n\t\tevent: \"op\",\n\t\tlistener: (op: ISequencedDocumentMessage, runtimeMessage?: boolean) => void,\n\t): this;\n\toff(\n\t\tevent: \"op\",\n\t\tlistener: (op: ISequencedDocumentMessage, runtimeMessage?: boolean) => void,\n\t): this;\n}\n\n/**\n * Options affecting summarize behavior.\n * @legacy @beta\n */\nexport interface ISummarizeOptions {\n\t/**\n\t * True to generate the full tree with no handle reuse optimizations; defaults to false\n\t */\n\treadonly fullTree?: boolean;\n}\n\n/**\n * @internal\n */\nexport interface ISubmitSummaryOptions extends ISummarizeOptions {\n\t/**\n\t * Logger to use for correlated summary events\n\t */\n\treadonly summaryLogger: ITelemetryLoggerExt;\n\t/**\n\t * Tells when summary process should be cancelled\n\t */\n\treadonly cancellationToken: ISummaryCancellationToken;\n\t/**\n\t * Summarization may be attempted multiple times. This tells whether this is the final summarization attempt.\n\t */\n\treadonly finalAttempt?: boolean;\n\t/**\n\t * The sequence number of the latest summary used to validate if summary state is correct before summarizing\n\t */\n\treadonly latestSummaryRefSeqNum: number;\n\t/**\n\t * Shared telemetry context for the current summarize attempt.\n\t */\n\ttelemetryContext?: TelemetryContext;\n}\n\n/**\n * @legacy @beta\n */\nexport interface IOnDemandSummarizeOptions extends ISummarizeOptions {\n\t/**\n\t * Reason for generating summary.\n\t */\n\treadonly reason: string;\n\t/**\n\t * In case of a failure, will attempt to retry based on if the failure is retriable.\n\t */\n\treadonly retryOnFailure?: boolean;\n}\n\n/**\n * Options to use when enqueueing a summarize attempt.\n * @legacy @beta\n */\nexport interface IEnqueueSummarizeOptions extends IOnDemandSummarizeOptions {\n\t/**\n\t * If specified, The summarize attempt will not occur until after this sequence number.\n\t */\n\treadonly afterSequenceNumber?: number;\n\n\t/**\n\t * True to override the existing enqueued summarize attempt if there is one.\n\t * This will guarantee that this attempt gets enqueued. If override is false,\n\t * than an existing enqueued summarize attempt will block a new one from being\n\t * enqueued. There can only be one enqueued at a time. Defaults to false.\n\t */\n\treadonly 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 * @legacy @beta\n */\nexport interface IGeneratedSummaryStats extends ISummaryStats {\n\t/**\n\t * The total number of data stores in the container.\n\t */\n\treadonly dataStoreCount: number;\n\t/**\n\t * The number of data stores that were summarized in this summary.\n\t */\n\treadonly summarizedDataStoreCount: number;\n\t/**\n\t * The number of data stores whose GC reference state was updated in this summary.\n\t */\n\treadonly gcStateUpdatedDataStoreCount?: number;\n\t/**\n\t * The size of the gc blobs in this summary.\n\t */\n\treadonly gcTotalBlobsSize?: number;\n\t/**\n\t * The number of gc blobs in this summary.\n\t */\n\treadonly gcBlobNodeCount?: number;\n\t/**\n\t * The summary number for a container's summary. Incremented on summaries throughout its lifetime.\n\t */\n\treadonly summaryNumber: number;\n}\n\n/**\n * Type for summarization failures that are retriable.\n * @legacy @beta\n */\nexport interface IRetriableFailureError extends Error {\n\treadonly retryAfterSeconds?: number;\n}\n\n/**\n * Base results for all submitSummary attempts.\n * @legacy @beta\n */\nexport interface IBaseSummarizeResult {\n\treadonly stage: \"base\";\n\t/**\n\t * Retriable error object related to failed summarize attempt.\n\t */\n\treadonly error: IRetriableFailureError | undefined;\n\t/**\n\t * Reference sequence number as of the generate summary attempt.\n\t */\n\treadonly referenceSequenceNumber: number;\n\treadonly minimumSequenceNumber: number;\n}\n\n/**\n * Results of submitSummary after generating the summary tree.\n * @legacy @beta\n */\nexport interface IGenerateSummaryTreeResult extends Omit<IBaseSummarizeResult, \"stage\"> {\n\treadonly stage: \"generate\";\n\t/**\n\t * Generated summary tree.\n\t */\n\treadonly summaryTree: ISummaryTree;\n\t/**\n\t * Stats for generated summary tree.\n\t */\n\treadonly summaryStats: IGeneratedSummaryStats;\n\t/**\n\t * Time it took to generate the summary tree and stats.\n\t */\n\treadonly generateDuration: number;\n}\n\n/**\n * Results of submitSummary after uploading the tree to storage.\n * @legacy @beta\n */\nexport interface IUploadSummaryResult extends Omit<IGenerateSummaryTreeResult, \"stage\"> {\n\treadonly stage: \"upload\";\n\t/**\n\t * The handle returned by storage pointing to the uploaded summary tree.\n\t */\n\treadonly handle: string;\n\t/**\n\t * Time it took to upload the summary tree to storage.\n\t */\n\treadonly uploadDuration: number;\n}\n\n/**\n * Results of submitSummary after submitting the summarize op.\n * @legacy @beta\n */\nexport interface ISubmitSummaryOpResult extends Omit<IUploadSummaryResult, \"stage\" | \"error\"> {\n\treadonly stage: \"submit\";\n\t/**\n\t * The client sequence number of the summarize op submitted for the summary.\n\t */\n\treadonly clientSequenceNumber: number;\n\t/**\n\t * Time it took to submit the summarize op to the broadcasting service.\n\t */\n\treadonly submitOpDuration: number;\n}\n\n/**\n * Strict type representing result of a submitSummary attempt.\n * The result consists of 4 possible stages, each with its own data.\n * The data is cumulative, so each stage will contain the data from the previous stages.\n * If the final \"submitted\" stage is not reached, the result may contain the error object.\n *\n * Stages:\n *\n * 1. \"base\" - stopped before the summary tree was even generated, and the result only contains the base data\n *\n * 2. \"generate\" - the summary tree was generated, and the result will contain that tree + stats\n *\n * 3. \"upload\" - the summary was uploaded to storage, and the result contains the server-provided handle\n *\n * 4. \"submit\" - the summarize op was submitted, and the result contains the op client sequence number.\n * @legacy @beta\n */\nexport type SubmitSummaryResult =\n\t| IBaseSummarizeResult\n\t| IGenerateSummaryTreeResult\n\t| IUploadSummaryResult\n\t| ISubmitSummaryOpResult;\n\n/**\n * The stages of Summarize, used to describe how far progress succeeded in case of a failure at a later stage.\n * @legacy @beta\n */\nexport type SummaryStage = SubmitSummaryResult[\"stage\"] | \"unknown\";\n\n/**\n * The data in summarizer result when submit summary stage fails.\n * @legacy @beta\n */\nexport interface SubmitSummaryFailureData {\n\tstage: SummaryStage;\n}\n\n/**\n * @legacy @beta\n */\nexport type SummarizeResultPart<TSuccess, TFailure = undefined> =\n\t| {\n\t\t\tsuccess: true;\n\t\t\tdata: TSuccess;\n\t }\n\t| {\n\t\t\tsuccess: false;\n\t\t\tdata: TFailure | undefined;\n\t\t\tmessage: string;\n\t\t\terror: IRetriableFailureError;\n\t };\n\n/**\n * @legacy @beta\n */\nexport interface ISummarizer extends IEventProvider<ISummarizerEvents> {\n\t/**\n\t * Allows {@link ISummarizer} to be used with our {@link @fluidframework/core-interfaces#FluidObject} pattern.\n\t */\n\treadonly ISummarizer?: ISummarizer;\n\n\t/*\n\t * Asks summarizer to move to exit.\n\t * Summarizer will finish current processes, which may take a while.\n\t * For example, summarizer may complete last summary before exiting.\n\t */\n\tstop(reason: SummarizerStopReason): void;\n\n\t/* Closes summarizer. Any pending processes (summary in flight) are abandoned. */\n\tclose(): void;\n\n\trun(onBehalfOf: string): Promise<SummarizerStopReason>;\n\n\t/**\n\t * Attempts to generate a summary on demand. If already running, takes no action.\n\t * @param options - options controlling the summarize attempt\n\t * @returns an alreadyRunning promise if a summarize attempt is already in progress,\n\t * which will resolve when the current attempt completes. At that point caller can\n\t * decide to try again or not. Otherwise, it will return an object containing promises\n\t * that resolve as the summarize attempt progresses. They will resolve with success\n\t * false if a failure is encountered.\n\t */\n\tsummarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults;\n\t/**\n\t * Enqueue an attempt to summarize after the specified sequence number.\n\t * If afterSequenceNumber is provided, the summarize attempt is \"enqueued\"\n\t * to run once an eligible op comes in with sequenceNumber \\>= afterSequenceNumber.\n\t * @param options - options controlling the summarize attempt\n\t * @returns an object containing an alreadyEnqueued flag to indicate if another\n\t * summarize attempt has already been enqueued. It also may contain an overridden flag\n\t * when alreadyEnqueued is true, that indicates whether this attempt forced the\n\t * previous attempt to abort. If this attempt becomes enqueued, it returns an object\n\t * containing promises that resolve as the summarize attempt progresses. They will\n\t * resolve with success false if a failure is encountered.\n\t */\n\tenqueueSummarize(options: IEnqueueSummarizeOptions): EnqueueSummarizeResult;\n}\n\n/**\n * Data about an attempt to summarize used for heuristics.\n */\nexport interface ISummarizeAttempt {\n\t/**\n\t * Reference sequence number when summary was generated or attempted\n\t */\n\treadonly refSequenceNumber: number;\n\n\t/**\n\t * Time of summary attempt after it was sent or attempted\n\t */\n\treadonly summaryTime: number;\n\n\t/**\n\t * Sequence number of summary op\n\t */\n\tsummarySequenceNumber?: number;\n}\n\n/**\n * Data relevant for summary heuristics.\n */\nexport interface ISummarizeHeuristicData {\n\t/**\n\t * Latest received op sequence number\n\t */\n\tlastOpSequenceNumber: number;\n\n\t/**\n\t * Most recent summary attempt from this client\n\t */\n\treadonly lastAttempt: ISummarizeAttempt;\n\n\t/**\n\t * Most recent summary that received an ack\n\t */\n\treadonly lastSuccessfulSummary: Readonly<ISummarizeAttempt>;\n\n\t/**\n\t * Number of runtime ops since last summary\n\t */\n\tnumRuntimeOps: number;\n\n\t/**\n\t * Number of non-runtime ops since last summary\n\t */\n\tnumNonRuntimeOps: number;\n\n\t/**\n\t * Cumulative size in bytes of all the ops since the last summary\n\t */\n\ttotalOpsSize: number;\n\n\t/**\n\t * Wether or not this instance contains adjusted metrics due to missing op data\n\t */\n\thasMissingOpData: boolean;\n\n\t/**\n\t * Updates lastAttempt and lastSuccessfulAttempt based on the last summary.\n\t * @param lastSummary - last ack summary\n\t */\n\tupdateWithLastSummaryAckInfo(lastSummary: ISummarizeAttempt): void;\n\n\t/**\n\t * Records a summary attempt. If the attempt was successfully sent,\n\t * provide the reference sequence number, otherwise it will be set\n\t * to the last seen op sequence number.\n\t * @param referenceSequenceNumber - reference sequence number of sent summary\n\t */\n\trecordAttempt(referenceSequenceNumber?: number): void;\n\n\t/**\n\t * Mark that the last sent summary attempt has received an ack\n\t */\n\tmarkLastAttemptAsSuccessful(): void;\n\n\topsSinceLastSummary: number;\n}\n\n/**\n * Responsible for running heuristics determining when to summarize.\n */\nexport interface ISummarizeHeuristicRunner {\n\t/**\n\t * Start specific heuristic trackers (ex: idle timer)\n\t */\n\tstart(): void;\n\n\t/**\n\t * Runs the heuristics to determine if it should try to summarize\n\t */\n\trun(): void;\n\n\t/**\n\t * Runs a different heuristic to check if it should summarize before closing\n\t */\n\tshouldRunLastSummary(): boolean;\n\n\t/**\n\t * Disposes of resources\n\t */\n\tdispose(): void;\n}\n\ntype ISummarizeTelemetryRequiredProperties =\n\t/**\n\t * Reason code for attempting to summarize\n\t */\n\t\"summarizeReason\";\n\ntype ISummarizeTelemetryOptionalProperties =\n\t/**\n\t * Number of attempts within the last time window, used for calculating the throttle delay.\n\t */\n\t| \"summaryAttempts\"\n\t/**\n\t * Summarization may be attempted multiple times. This tells whether this is the final summarization attempt\n\t */\n\t| \"finalAttempt\"\n\t| keyof ISummarizeOptions;\n\nexport type ISummarizeTelemetryProperties = Pick<\n\tITelemetryBaseProperties,\n\tISummarizeTelemetryRequiredProperties\n> &\n\tPartial<Pick<ITelemetryBaseProperties, ISummarizeTelemetryOptionalProperties>>;\n\n/**\n * Strategy used to heuristically determine when we should run a summary\n */\nexport interface ISummaryHeuristicStrategy {\n\t/**\n\t * Summarize reason for this summarize heuristic strategy (ex: \"maxTime\")\n\t */\n\tsummarizeReason: Readonly<SummarizeReason>;\n\n\t/**\n\t * Determines if this strategy's summarize criteria been met\n\t * @param configuration - summary configuration we are to check against\n\t * @param heuristicData - heuristic data used to confirm conditions are met\n\t */\n\tshouldRunSummary(\n\t\tconfiguration: ISummaryConfigurationHeuristics,\n\t\theuristicData: ISummarizeHeuristicData,\n\t): boolean;\n}\n\ntype SummaryGeneratorRequiredTelemetryProperties =\n\t/**\n\t * True to generate the full tree with no handle reuse optimizations\n\t */\n\t| \"fullTree\"\n\t/**\n\t * Time since we last attempted to generate a summary\n\t */\n\t| \"timeSinceLastAttempt\"\n\t/**\n\t * Time since we last successfully generated a summary\n\t */\n\t| \"timeSinceLastSummary\";\n\ntype SummaryGeneratorOptionalTelemetryProperties =\n\t/**\n\t * Reference sequence number as of the generate summary attempt.\n\t */\n\t| \"referenceSequenceNumber\"\n\t/**\n\t * minimum sequence number (at the reference sequence number)\n\t */\n\t| \"minimumSequenceNumber\"\n\t/**\n\t * Delta between the current reference sequence number and the reference sequence number of the last attempt\n\t */\n\t| \"opsSinceLastAttempt\"\n\t/**\n\t * Delta between the current reference sequence number and the reference sequence number of the last summary\n\t */\n\t| \"opsSinceLastSummary\"\n\t/**\n\t * Delta in sum of op sizes between the current reference sequence number and the reference\n\t * sequence number of the last summary\n\t */\n\t| \"opsSizesSinceLastSummary\"\n\t/**\n\t * Delta between the number of non-runtime ops since the last summary\n\t */\n\t| \"nonRuntimeOpsSinceLastSummary\"\n\t/**\n\t * Delta between the number of runtime ops since the last summary\n\t */\n\t| \"runtimeOpsSinceLastSummary\"\n\t/**\n\t * Wether or not this instance contains adjusted metrics due to missing op data\n\t */\n\t| \"hasMissingOpData\"\n\t/**\n\t * Time it took to generate the summary tree and stats.\n\t */\n\t| \"generateDuration\"\n\t/**\n\t * The handle returned by storage pointing to the uploaded summary tree.\n\t */\n\t| \"handle\"\n\t/**\n\t * Time it took to upload the summary tree to storage.\n\t */\n\t| \"uploadDuration\"\n\t/**\n\t * The client sequence number of the summarize op submitted for the summary.\n\t */\n\t| \"clientSequenceNumber\"\n\t/**\n\t * Time it took for this summary to be acked after it was generated\n\t */\n\t| \"ackWaitDuration\"\n\t/**\n\t * Reference sequence number of the ack/nack message\n\t */\n\t| \"ackNackSequenceNumber\"\n\t/**\n\t * Actual sequence number of the summary op proposal.\n\t */\n\t| \"summarySequenceNumber\"\n\t/**\n\t * Optional Retry-After time in seconds. If specified, the client should wait this many seconds before retrying.\n\t */\n\t| \"nackRetryAfter\"\n\t/**\n\t * The stage at which the submit summary method failed at. This can help determine what type of failure we have\n\t */\n\t| \"stage\";\n\nexport type SummaryGeneratorTelemetry = Pick<\n\tITelemetryBaseProperties,\n\tSummaryGeneratorRequiredTelemetryProperties\n> &\n\tPartial<Pick<ITelemetryBaseProperties, SummaryGeneratorOptionalTelemetryProperties>>;\n\nexport interface ISummarizeRunnerTelemetry extends ITelemetryLoggerPropertyBag {\n\t/**\n\t * Number of times the summarizer run.\n\t */\n\tsummarizeCount: () => number;\n\t/**\n\t * Number of successful attempts to summarize.\n\t */\n\tsummarizerSuccessfulAttempts: () => number;\n}\n\n/**\n * @legacy @beta\n */\nexport interface ISummaryBaseConfiguration {\n\t/**\n\t * Delay before first attempt to spawn summarizing container.\n\t */\n\tinitialSummarizerDelayMs: number;\n\n\t/**\n\t * Defines the maximum allowed time to wait for a pending summary ack.\n\t * The maximum amount of time client will wait for a summarize is the minimum of\n\t * maxSummarizeAckWaitTime (currently 3 * 60 * 1000) and maxAckWaitTime.\n\t */\n\tmaxAckWaitTime: number;\n\t/**\n\t * Defines the maximum number of Ops in between Summaries that can be\n\t * allowed before forcibly electing a new summarizer client.\n\t */\n\tmaxOpsSinceLastSummary: number;\n}\n\n/**\n * @legacy @beta\n */\nexport interface ISummaryConfigurationHeuristics extends ISummaryBaseConfiguration {\n\tstate: \"enabled\";\n\t/**\n\t * Defines the maximum allowed time, since the last received Ack, before running the summary\n\t * with reason maxTime.\n\t * For example, say we receive ops one by one just before the idle time is triggered.\n\t * In this case, we still want to run a summary since it's been a while since the last summary.\n\t */\n\tmaxTime: number;\n\t/**\n\t * Defines the maximum number of Ops, since the last received Ack, that can be allowed\n\t * before running the summary with reason maxOps.\n\t */\n\tmaxOps: number;\n\t/**\n\t * Defines the minimum number of Ops, since the last received Ack, that can be allowed\n\t * before running the last summary.\n\t */\n\tminOpsForLastSummaryAttempt: number;\n\t/**\n\t * Defines the lower boundary for the allowed time in between summarizations.\n\t * Pairs with maxIdleTime to form a range.\n\t * For example, if we only receive 1 op, we don't want to have the same idle time as say 100 ops.\n\t * Based on the boundaries we set in minIdleTime and maxIdleTime, the idle time will change\n\t * linearly depending on the number of ops we receive.\n\t */\n\tminIdleTime: number;\n\t/**\n\t * Defines the upper boundary for the allowed time in between summarizations.\n\t * Pairs with minIdleTime to form a range.\n\t * For example, if we only receive 1 op, we don't want to have the same idle time as say 100 ops.\n\t * Based on the boundaries we set in minIdleTime and maxIdleTime, the idle time will change\n\t * linearly depending on the number of ops we receive.\n\t */\n\tmaxIdleTime: number;\n\t/**\n\t * Runtime op weight to use in heuristic summarizing.\n\t * This number is a multiplier on the number of runtime ops we process when running summarize heuristics.\n\t * For example: (multiplier) * (number of runtime ops) = weighted number of runtime ops\n\t */\n\truntimeOpWeight: number;\n\t/**\n\t * Non-runtime op weight to use in heuristic summarizing\n\t * This number is a multiplier on the number of non-runtime ops we process when running summarize heuristics.\n\t * For example: (multiplier) * (number of non-runtime ops) = weighted number of non-runtime ops\n\t */\n\tnonRuntimeOpWeight: number;\n\n\t/**\n\t * Number of ops since last summary needed before a non-runtime op can trigger running summary heuristics.\n\t *\n\t * Note: Any runtime ops sent before the threshold is reached will trigger heuristics normally.\n\t * This threshold ONLY applies to non-runtime ops triggering summaries.\n\t *\n\t * For example: Say the threshold is 20. Sending 19 non-runtime ops will not trigger any heuristic checks.\n\t * Sending the 20th non-runtime op will trigger the heuristic checks for summarizing.\n\t */\n\tnonRuntimeHeuristicThreshold?: number;\n}\n\n/**\n * @legacy @beta\n */\nexport interface ISummaryConfigurationDisableSummarizer {\n\tstate: \"disabled\";\n}\n\n/**\n * @legacy @beta\n */\nexport interface ISummaryConfigurationDisableHeuristics extends ISummaryBaseConfiguration {\n\tstate: \"disableHeuristics\";\n}\n\n/**\n * Configuration used internally to indicate on-demand summaries only (no election/heuristics).\n * @legacy @beta\n */\nexport interface ISummaryConfigurationWithSummaryOnRequest extends ISummaryBaseConfiguration {\n\tstate: \"summaryOnRequest\";\n}\n\n/**\n * @legacy @beta\n */\nexport type ISummaryConfiguration =\n\t| ISummaryConfigurationDisableSummarizer\n\t| ISummaryConfigurationDisableHeuristics\n\t| ISummaryConfigurationHeuristics\n\t| ISummaryConfigurationWithSummaryOnRequest;\n"]}
|
|
1
|
+
{"version":3,"file":"summarizerTypes.js","sourceRoot":"","sources":["../../src/summary/summarizerTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAiCH,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tIDeltaManager,\n\tContainerWarning,\n} from \"@fluidframework/container-definitions/internal\";\nimport type {\n\tISummarizerEvents,\n\tSummarizerStopReason,\n} from \"@fluidframework/container-runtime-definitions/internal\";\nimport type {\n\tIEventProvider,\n\tITelemetryBaseProperties,\n\tITelemetryBaseLogger,\n} from \"@fluidframework/core-interfaces\";\nimport type { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentMessage,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport type { ISummaryStats } from \"@fluidframework/runtime-definitions/internal\";\nimport type { TelemetryContext } from \"@fluidframework/runtime-utils/internal\";\nimport type {\n\tITelemetryLoggerExt,\n\tITelemetryLoggerPropertyBag,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { SummarizeReason } from \"./summarizerUtils.js\";\nimport type {\n\tEnqueueSummarizeResult,\n\tISummarizeResults,\n} from \"./summaryDelayLoadedModule/index.js\";\n\nexport const summarizerClientType = \"summarizer\";\n\n/**\n * Similar to AbortSignal, but using promise instead of events\n * @param T - cancellation reason type\n * @internal\n */\nexport interface ICancellationToken<T> {\n\t/**\n\t * Tells if this cancellable token is cancelled\n\t */\n\treadonly cancelled: boolean;\n\t/**\n\t * Promise that gets fulfilled when this cancellable token is cancelled\n\t * @returns reason of cancellation\n\t */\n\treadonly waitCancelled: Promise<T>;\n}\n\n/**\n * Similar to AbortSignal, but using promise instead of events\n * @internal\n */\nexport type ISummaryCancellationToken = ICancellationToken<SummarizerStopReason>;\n\n/**\n * Data required to update internal tracking state after receiving a Summary Ack.\n * @internal\n */\nexport interface IRefreshSummaryAckOptions {\n\t/**\n\t * Handle from the ack's summary op.\n\t */\n\treadonly proposalHandle: string | undefined;\n\t/**\n\t * Handle from the summary ack just received\n\t */\n\treadonly ackHandle: string;\n\t/**\n\t * Reference sequence number from the ack's summary op\n\t */\n\treadonly summaryRefSeq: number;\n\t/**\n\t * Telemetry logger to which telemetry events will be forwarded.\n\t */\n\treadonly summaryLogger: ITelemetryLoggerExt;\n}\n\n/**\n * @internal\n */\nexport interface ISummarizerInternalsProvider {\n\t/**\n\t * Encapsulates the work to walk the internals of the running container to generate a summary\n\t */\n\tsubmitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult>;\n\n\t/**\n\t * Callback whenever a new SummaryAck is received, to update internal tracking state\n\t */\n\trefreshLatestSummaryAck(options: IRefreshSummaryAckOptions): Promise<void>;\n}\n\n/**\n * @internal\n */\nexport interface ISummarizingWarning extends ContainerWarning {\n\treadonly errorType: \"summarizingError\";\n\treadonly logged: boolean;\n}\n\n/**\n * @internal\n */\nexport interface IConnectableRuntime {\n\treadonly disposed: boolean;\n\treadonly connected: boolean;\n\treadonly clientId: string | undefined;\n\tonce(event: \"connected\" | \"disconnected\" | \"dispose\", listener: () => void): this;\n}\n\n/**\n * @internal\n */\nexport interface ISummarizerRuntime extends IConnectableRuntime {\n\treadonly baseLogger: ITelemetryBaseLogger;\n\t/**\n\t * clientId of parent (non-summarizing) container that owns summarizer container\n\t */\n\treadonly summarizerClientId: string | undefined;\n\treadonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;\n\t/**\n\t * Initiate disposal of the container.\n\t */\n\tdisposeFn(): void;\n\ton(\n\t\tevent: \"op\",\n\t\tlistener: (op: ISequencedDocumentMessage, runtimeMessage?: boolean) => void,\n\t): this;\n\toff(\n\t\tevent: \"op\",\n\t\tlistener: (op: ISequencedDocumentMessage, runtimeMessage?: boolean) => void,\n\t): this;\n}\n\n/**\n * Options affecting summarize behavior.\n * @legacy @beta\n */\nexport interface ISummarizeOptions {\n\t/**\n\t * True to generate the full tree with no handle reuse optimizations; defaults to false\n\t */\n\treadonly fullTree?: boolean;\n}\n\n/**\n * @internal\n */\nexport interface ISubmitSummaryOptions extends ISummarizeOptions {\n\t/**\n\t * Logger to use for correlated summary events\n\t */\n\treadonly summaryLogger: ITelemetryLoggerExt;\n\t/**\n\t * Tells when summary process should be cancelled\n\t */\n\treadonly cancellationToken: ISummaryCancellationToken;\n\t/**\n\t * Summarization may be attempted multiple times. This tells whether this is the final summarization attempt.\n\t */\n\treadonly finalAttempt?: boolean;\n\t/**\n\t * The sequence number of the latest summary used to validate if summary state is correct before summarizing\n\t */\n\treadonly latestSummaryRefSeqNum: number;\n\t/**\n\t * Shared telemetry context for the current summarize attempt.\n\t */\n\ttelemetryContext?: TelemetryContext;\n}\n\n/**\n * @legacy @beta\n */\nexport interface IOnDemandSummarizeOptions extends ISummarizeOptions {\n\t/**\n\t * Reason for generating summary.\n\t */\n\treadonly reason: string;\n\t/**\n\t * In case of a failure, will attempt to retry based on if the failure is retriable.\n\t */\n\treadonly retryOnFailure?: boolean;\n}\n\n/**\n * Options to use when enqueueing a summarize attempt.\n * @legacy @beta\n */\nexport interface IEnqueueSummarizeOptions extends IOnDemandSummarizeOptions {\n\t/**\n\t * If specified, The summarize attempt will not occur until after this sequence number.\n\t */\n\treadonly afterSequenceNumber?: number;\n\n\t/**\n\t * True to override the existing enqueued summarize attempt if there is one.\n\t * This will guarantee that this attempt gets enqueued. If override is false,\n\t * than an existing enqueued summarize attempt will block a new one from being\n\t * enqueued. There can only be one enqueued at a time. Defaults to false.\n\t */\n\treadonly 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 * @legacy @beta\n */\nexport interface IGeneratedSummaryStats extends ISummaryStats {\n\t/**\n\t * The total number of data stores in the container.\n\t */\n\treadonly dataStoreCount: number;\n\t/**\n\t * The number of data stores that were summarized in this summary.\n\t */\n\treadonly summarizedDataStoreCount: number;\n\t/**\n\t * The number of data stores whose GC reference state was updated in this summary.\n\t */\n\treadonly gcStateUpdatedDataStoreCount?: number;\n\t/**\n\t * The size of the gc blobs in this summary.\n\t */\n\treadonly gcTotalBlobsSize?: number;\n\t/**\n\t * The number of gc blobs in this summary.\n\t */\n\treadonly gcBlobNodeCount?: number;\n\t/**\n\t * The summary number for a container's summary. Incremented on summaries throughout its lifetime.\n\t */\n\treadonly summaryNumber: number;\n}\n\n/**\n * Type for summarization failures that are retriable.\n * @legacy @beta\n */\nexport interface IRetriableFailureError extends Error {\n\treadonly retryAfterSeconds?: number;\n}\n\n/**\n * Base results for all submitSummary attempts.\n * @legacy @beta\n */\nexport interface IBaseSummarizeResult {\n\treadonly stage: \"base\";\n\t/**\n\t * Retriable error object related to failed summarize attempt.\n\t */\n\treadonly error: IRetriableFailureError | undefined;\n\t/**\n\t * Reference sequence number as of the generate summary attempt.\n\t */\n\treadonly referenceSequenceNumber: number;\n\treadonly minimumSequenceNumber: number;\n}\n\n/**\n * Results of submitSummary after generating the summary tree.\n * @legacy @beta\n */\nexport interface IGenerateSummaryTreeResult extends Omit<IBaseSummarizeResult, \"stage\"> {\n\treadonly stage: \"generate\";\n\t/**\n\t * Generated summary tree.\n\t */\n\treadonly summaryTree: ISummaryTree;\n\t/**\n\t * Stats for generated summary tree.\n\t */\n\treadonly summaryStats: IGeneratedSummaryStats;\n\t/**\n\t * Time it took to generate the summary tree and stats.\n\t */\n\treadonly generateDuration: number;\n}\n\n/**\n * Results of submitSummary after uploading the tree to storage.\n * @legacy @beta\n */\nexport interface IUploadSummaryResult extends Omit<IGenerateSummaryTreeResult, \"stage\"> {\n\treadonly stage: \"upload\";\n\t/**\n\t * The handle returned by storage pointing to the uploaded summary tree.\n\t */\n\treadonly handle: string;\n\t/**\n\t * Time it took to upload the summary tree to storage.\n\t */\n\treadonly uploadDuration: number;\n}\n\n/**\n * Results of submitSummary after submitting the summarize op.\n * @legacy @beta\n */\nexport interface ISubmitSummaryOpResult extends Omit<IUploadSummaryResult, \"stage\" | \"error\"> {\n\treadonly stage: \"submit\";\n\t/**\n\t * The client sequence number of the summarize op submitted for the summary.\n\t */\n\treadonly clientSequenceNumber: number;\n\t/**\n\t * Time it took to submit the summarize op to the broadcasting service.\n\t */\n\treadonly submitOpDuration: number;\n}\n\n/**\n * Strict type representing result of a submitSummary attempt.\n * The result consists of 4 possible stages, each with its own data.\n * The data is cumulative, so each stage will contain the data from the previous stages.\n * If the final \"submitted\" stage is not reached, the result may contain the error object.\n *\n * Stages:\n *\n * 1. \"base\" - stopped before the summary tree was even generated, and the result only contains the base data\n *\n * 2. \"generate\" - the summary tree was generated, and the result will contain that tree + stats\n *\n * 3. \"upload\" - the summary was uploaded to storage, and the result contains the server-provided handle\n *\n * 4. \"submit\" - the summarize op was submitted, and the result contains the op client sequence number.\n * @legacy @beta\n */\nexport type SubmitSummaryResult =\n\t| IBaseSummarizeResult\n\t| IGenerateSummaryTreeResult\n\t| IUploadSummaryResult\n\t| ISubmitSummaryOpResult;\n\n/**\n * The stages of Summarize, used to describe how far progress succeeded in case of a failure at a later stage.\n * @legacy @beta\n */\nexport type SummaryStage = SubmitSummaryResult[\"stage\"] | \"unknown\";\n\n/**\n * The data in summarizer result when submit summary stage fails.\n * @legacy @beta\n */\nexport interface SubmitSummaryFailureData {\n\tstage: SummaryStage;\n}\n\n/**\n * @legacy @beta\n */\nexport type SummarizeResultPart<TSuccess, TFailure = undefined> =\n\t| {\n\t\t\tsuccess: true;\n\t\t\tdata: TSuccess;\n\t }\n\t| {\n\t\t\tsuccess: false;\n\t\t\tdata: TFailure | undefined;\n\t\t\tmessage: string;\n\t\t\terror: IRetriableFailureError;\n\t };\n\n/**\n * @legacy @beta\n */\nexport interface ISummarizer extends IEventProvider<ISummarizerEvents> {\n\t/**\n\t * Allows {@link ISummarizer} to be used with our {@link @fluidframework/core-interfaces#FluidObject} pattern.\n\t */\n\treadonly ISummarizer?: ISummarizer;\n\n\t/*\n\t * Asks summarizer to move to exit.\n\t * Summarizer will finish current processes, which may take a while.\n\t * For example, summarizer may complete last summary before exiting.\n\t */\n\tstop(reason: SummarizerStopReason): void;\n\n\t/* Closes summarizer. Any pending processes (summary in flight) are abandoned. */\n\tclose(): void;\n\n\trun(onBehalfOf: string): Promise<SummarizerStopReason>;\n\n\t/**\n\t * Attempts to generate a summary on demand. If already running, takes no action.\n\t * @param options - options controlling the summarize attempt\n\t * @returns an alreadyRunning promise if a summarize attempt is already in progress,\n\t * which will resolve when the current attempt completes. At that point caller can\n\t * decide to try again or not. Otherwise, it will return an object containing promises\n\t * that resolve as the summarize attempt progresses. They will resolve with success\n\t * false if a failure is encountered.\n\t */\n\tsummarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults;\n\t/**\n\t * Enqueue an attempt to summarize after the specified sequence number.\n\t * If afterSequenceNumber is provided, the summarize attempt is \"enqueued\"\n\t * to run once an eligible op comes in with sequenceNumber \\>= afterSequenceNumber.\n\t * @param options - options controlling the summarize attempt\n\t * @returns an object containing an alreadyEnqueued flag to indicate if another\n\t * summarize attempt has already been enqueued. It also may contain an overridden flag\n\t * when alreadyEnqueued is true, that indicates whether this attempt forced the\n\t * previous attempt to abort. If this attempt becomes enqueued, it returns an object\n\t * containing promises that resolve as the summarize attempt progresses. They will\n\t * resolve with success false if a failure is encountered.\n\t */\n\tenqueueSummarize(options: IEnqueueSummarizeOptions): EnqueueSummarizeResult;\n}\n\n/**\n * Data about an attempt to summarize used for heuristics.\n */\nexport interface ISummarizeAttempt {\n\t/**\n\t * Reference sequence number when summary was generated or attempted\n\t */\n\treadonly refSequenceNumber: number;\n\n\t/**\n\t * Time of summary attempt after it was sent or attempted\n\t */\n\treadonly summaryTime: number;\n\n\t/**\n\t * Sequence number of summary op\n\t */\n\tsummarySequenceNumber?: number;\n}\n\n/**\n * Data relevant for summary heuristics.\n */\nexport interface ISummarizeHeuristicData {\n\t/**\n\t * Latest received op sequence number\n\t */\n\tlastOpSequenceNumber: number;\n\n\t/**\n\t * Most recent summary attempt from this client\n\t */\n\treadonly lastAttempt: ISummarizeAttempt;\n\n\t/**\n\t * Most recent summary that received an ack\n\t */\n\treadonly lastSuccessfulSummary: Readonly<ISummarizeAttempt>;\n\n\t/**\n\t * Number of runtime ops since last summary\n\t */\n\tnumRuntimeOps: number;\n\n\t/**\n\t * Number of non-runtime ops since last summary\n\t */\n\tnumNonRuntimeOps: number;\n\n\t/**\n\t * Cumulative size in bytes of all the ops since the last summary\n\t */\n\ttotalOpsSize: number;\n\n\t/**\n\t * Wether or not this instance contains adjusted metrics due to missing op data\n\t */\n\thasMissingOpData: boolean;\n\n\t/**\n\t * Updates lastAttempt and lastSuccessfulAttempt based on the last summary.\n\t * @param lastSummary - last ack summary\n\t */\n\tupdateWithLastSummaryAckInfo(lastSummary: ISummarizeAttempt): void;\n\n\t/**\n\t * Records a summary attempt. If the attempt was successfully sent,\n\t * provide the reference sequence number, otherwise it will be set\n\t * to the last seen op sequence number.\n\t * @param referenceSequenceNumber - reference sequence number of sent summary\n\t */\n\trecordAttempt(referenceSequenceNumber?: number): void;\n\n\t/**\n\t * Mark that the last sent summary attempt has received an ack\n\t */\n\tmarkLastAttemptAsSuccessful(): void;\n\n\topsSinceLastSummary: number;\n}\n\n/**\n * Responsible for running heuristics determining when to summarize.\n */\nexport interface ISummarizeHeuristicRunner {\n\t/**\n\t * Start specific heuristic trackers (ex: idle timer)\n\t */\n\tstart(): void;\n\n\t/**\n\t * Runs the heuristics to determine if it should try to summarize\n\t */\n\trun(): void;\n\n\t/**\n\t * Runs a different heuristic to check if it should summarize before closing\n\t */\n\tshouldRunLastSummary(): boolean;\n\n\t/**\n\t * Disposes of resources\n\t */\n\tdispose(): void;\n}\n\ntype ISummarizeTelemetryRequiredProperties =\n\t/**\n\t * Reason code for attempting to summarize\n\t */\n\t\"summarizeReason\";\n\ntype ISummarizeTelemetryOptionalProperties =\n\t/**\n\t * Number of attempts within the last time window, used for calculating the throttle delay.\n\t */\n\t| \"summaryAttempts\"\n\t/**\n\t * Summarization may be attempted multiple times. This tells whether this is the final summarization attempt\n\t */\n\t| \"finalAttempt\"\n\t| keyof ISummarizeOptions;\n\nexport type ISummarizeTelemetryProperties = Pick<\n\tITelemetryBaseProperties,\n\tISummarizeTelemetryRequiredProperties\n> &\n\tPartial<Pick<ITelemetryBaseProperties, ISummarizeTelemetryOptionalProperties>>;\n\n/**\n * Strategy used to heuristically determine when we should run a summary\n */\nexport interface ISummaryHeuristicStrategy {\n\t/**\n\t * Summarize reason for this summarize heuristic strategy (ex: \"maxTime\")\n\t */\n\tsummarizeReason: Readonly<SummarizeReason>;\n\n\t/**\n\t * Determines if this strategy's summarize criteria been met\n\t * @param configuration - summary configuration we are to check against\n\t * @param heuristicData - heuristic data used to confirm conditions are met\n\t */\n\tshouldRunSummary(\n\t\tconfiguration: ISummaryConfigurationHeuristics,\n\t\theuristicData: ISummarizeHeuristicData,\n\t): boolean;\n}\n\ntype SummaryGeneratorRequiredTelemetryProperties =\n\t/**\n\t * True to generate the full tree with no handle reuse optimizations\n\t */\n\t| \"fullTree\"\n\t/**\n\t * Time since we last attempted to generate a summary\n\t */\n\t| \"timeSinceLastAttempt\"\n\t/**\n\t * Time since we last successfully generated a summary\n\t */\n\t| \"timeSinceLastSummary\";\n\ntype SummaryGeneratorOptionalTelemetryProperties =\n\t/**\n\t * Reference sequence number as of the generate summary attempt.\n\t */\n\t| \"referenceSequenceNumber\"\n\t/**\n\t * minimum sequence number (at the reference sequence number)\n\t */\n\t| \"minimumSequenceNumber\"\n\t/**\n\t * Delta between the current reference sequence number and the reference sequence number of the last attempt\n\t */\n\t| \"opsSinceLastAttempt\"\n\t/**\n\t * Delta between the current reference sequence number and the reference sequence number of the last summary\n\t */\n\t| \"opsSinceLastSummary\"\n\t/**\n\t * Delta in sum of op sizes between the current reference sequence number and the reference\n\t * sequence number of the last summary\n\t */\n\t| \"opsSizesSinceLastSummary\"\n\t/**\n\t * Delta between the number of non-runtime ops since the last summary\n\t */\n\t| \"nonRuntimeOpsSinceLastSummary\"\n\t/**\n\t * Delta between the number of runtime ops since the last summary\n\t */\n\t| \"runtimeOpsSinceLastSummary\"\n\t/**\n\t * Wether or not this instance contains adjusted metrics due to missing op data\n\t */\n\t| \"hasMissingOpData\"\n\t/**\n\t * Time it took to generate the summary tree and stats.\n\t */\n\t| \"generateDuration\"\n\t/**\n\t * The handle returned by storage pointing to the uploaded summary tree.\n\t */\n\t| \"handle\"\n\t/**\n\t * Time it took to upload the summary tree to storage.\n\t */\n\t| \"uploadDuration\"\n\t/**\n\t * The client sequence number of the summarize op submitted for the summary.\n\t */\n\t| \"clientSequenceNumber\"\n\t/**\n\t * Time it took for this summary to be acked after it was generated\n\t */\n\t| \"ackWaitDuration\"\n\t/**\n\t * Reference sequence number of the ack/nack message\n\t */\n\t| \"ackNackSequenceNumber\"\n\t/**\n\t * Actual sequence number of the summary op proposal.\n\t */\n\t| \"summarySequenceNumber\"\n\t/**\n\t * Optional Retry-After time in seconds. If specified, the client should wait this many seconds before retrying.\n\t */\n\t| \"nackRetryAfter\"\n\t/**\n\t * The stage at which the submit summary method failed at. This can help determine what type of failure we have\n\t */\n\t| \"stage\";\n\nexport type SummaryGeneratorTelemetry = Pick<\n\tITelemetryBaseProperties,\n\tSummaryGeneratorRequiredTelemetryProperties\n> &\n\tPartial<Pick<ITelemetryBaseProperties, SummaryGeneratorOptionalTelemetryProperties>>;\n\nexport interface ISummarizeRunnerTelemetry extends ITelemetryLoggerPropertyBag {\n\t/**\n\t * Number of times the summarizer run.\n\t */\n\tsummarizeCount: () => number;\n\t/**\n\t * Number of successful attempts to summarize.\n\t */\n\tsummarizerSuccessfulAttempts: () => number;\n}\n\n/**\n * @legacy @beta\n */\nexport interface ISummaryBaseConfiguration {\n\t/**\n\t * Delay before first attempt to spawn summarizing container.\n\t */\n\tinitialSummarizerDelayMs: number;\n\n\t/**\n\t * Defines the maximum allowed time to wait for a pending summary ack.\n\t * The maximum amount of time client will wait for a summarize is the minimum of\n\t * maxSummarizeAckWaitTime (currently 3 * 60 * 1000) and maxAckWaitTime.\n\t */\n\tmaxAckWaitTime: number;\n\t/**\n\t * Defines the maximum number of Ops in between Summaries that can be\n\t * allowed before forcibly electing a new summarizer client.\n\t */\n\tmaxOpsSinceLastSummary: number;\n}\n\n/**\n * @legacy @beta\n */\nexport interface ISummaryConfigurationHeuristics extends ISummaryBaseConfiguration {\n\tstate: \"enabled\";\n\t/**\n\t * Defines the maximum allowed time, since the last received Ack, before running the summary\n\t * with reason maxTime.\n\t * For example, say we receive ops one by one just before the idle time is triggered.\n\t * In this case, we still want to run a summary since it's been a while since the last summary.\n\t */\n\tmaxTime: number;\n\t/**\n\t * Defines the maximum number of Ops, since the last received Ack, that can be allowed\n\t * before running the summary with reason maxOps.\n\t */\n\tmaxOps: number;\n\t/**\n\t * Defines the minimum number of Ops, since the last received Ack, that can be allowed\n\t * before running the last summary.\n\t */\n\tminOpsForLastSummaryAttempt: number;\n\t/**\n\t * Defines the lower boundary for the allowed time in between summarizations.\n\t * Pairs with maxIdleTime to form a range.\n\t * For example, if we only receive 1 op, we don't want to have the same idle time as say 100 ops.\n\t * Based on the boundaries we set in minIdleTime and maxIdleTime, the idle time will change\n\t * linearly depending on the number of ops we receive.\n\t */\n\tminIdleTime: number;\n\t/**\n\t * Defines the upper boundary for the allowed time in between summarizations.\n\t * Pairs with minIdleTime to form a range.\n\t * For example, if we only receive 1 op, we don't want to have the same idle time as say 100 ops.\n\t * Based on the boundaries we set in minIdleTime and maxIdleTime, the idle time will change\n\t * linearly depending on the number of ops we receive.\n\t */\n\tmaxIdleTime: number;\n\t/**\n\t * Runtime op weight to use in heuristic summarizing.\n\t * This number is a multiplier on the number of runtime ops we process when running summarize heuristics.\n\t * For example: (multiplier) * (number of runtime ops) = weighted number of runtime ops\n\t */\n\truntimeOpWeight: number;\n\t/**\n\t * Non-runtime op weight to use in heuristic summarizing\n\t * This number is a multiplier on the number of non-runtime ops we process when running summarize heuristics.\n\t * For example: (multiplier) * (number of non-runtime ops) = weighted number of non-runtime ops\n\t */\n\tnonRuntimeOpWeight: number;\n\n\t/**\n\t * Number of ops since last summary needed before a non-runtime op can trigger running summary heuristics.\n\t *\n\t * Note: Any runtime ops sent before the threshold is reached will trigger heuristics normally.\n\t * This threshold ONLY applies to non-runtime ops triggering summaries.\n\t *\n\t * For example: Say the threshold is 20. Sending 19 non-runtime ops will not trigger any heuristic checks.\n\t * Sending the 20th non-runtime op will trigger the heuristic checks for summarizing.\n\t */\n\tnonRuntimeHeuristicThreshold?: number;\n}\n\n/**\n * @legacy @beta\n */\nexport interface ISummaryConfigurationDisableSummarizer {\n\tstate: \"disabled\";\n}\n\n/**\n * @legacy @beta\n */\nexport interface ISummaryConfigurationDisableHeuristics extends ISummaryBaseConfiguration {\n\tstate: \"disableHeuristics\";\n}\n\n/**\n * Configuration used internally to indicate on-demand summaries only (no election/heuristics).\n * @legacy @beta\n */\nexport interface ISummaryConfigurationWithSummaryOnRequest extends ISummaryBaseConfiguration {\n\tstate: \"summaryOnRequest\";\n}\n\n/**\n * @legacy @beta\n */\nexport type ISummaryConfiguration =\n\t| ISummaryConfigurationDisableSummarizer\n\t| ISummaryConfigurationDisableHeuristics\n\t| ISummaryConfigurationHeuristics\n\t| ISummaryConfigurationWithSummaryOnRequest;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/container-runtime",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.101.1",
|
|
4
4
|
"description": "Fluid container runtime",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -119,18 +119,18 @@
|
|
|
119
119
|
"temp-directory": "nyc/.nyc_output"
|
|
120
120
|
},
|
|
121
121
|
"dependencies": {
|
|
122
|
-
"@fluid-internal/client-utils": "~2.
|
|
123
|
-
"@fluidframework/container-definitions": "~2.
|
|
124
|
-
"@fluidframework/container-runtime-definitions": "~2.
|
|
125
|
-
"@fluidframework/core-interfaces": "~2.
|
|
126
|
-
"@fluidframework/core-utils": "~2.
|
|
127
|
-
"@fluidframework/datastore": "~2.
|
|
128
|
-
"@fluidframework/driver-definitions": "~2.
|
|
129
|
-
"@fluidframework/driver-utils": "~2.
|
|
130
|
-
"@fluidframework/id-compressor": "~2.
|
|
131
|
-
"@fluidframework/runtime-definitions": "~2.
|
|
132
|
-
"@fluidframework/runtime-utils": "~2.
|
|
133
|
-
"@fluidframework/telemetry-utils": "~2.
|
|
122
|
+
"@fluid-internal/client-utils": "~2.101.1",
|
|
123
|
+
"@fluidframework/container-definitions": "~2.101.1",
|
|
124
|
+
"@fluidframework/container-runtime-definitions": "~2.101.1",
|
|
125
|
+
"@fluidframework/core-interfaces": "~2.101.1",
|
|
126
|
+
"@fluidframework/core-utils": "~2.101.1",
|
|
127
|
+
"@fluidframework/datastore": "~2.101.1",
|
|
128
|
+
"@fluidframework/driver-definitions": "~2.101.1",
|
|
129
|
+
"@fluidframework/driver-utils": "~2.101.1",
|
|
130
|
+
"@fluidframework/id-compressor": "~2.101.1",
|
|
131
|
+
"@fluidframework/runtime-definitions": "~2.101.1",
|
|
132
|
+
"@fluidframework/runtime-utils": "~2.101.1",
|
|
133
|
+
"@fluidframework/telemetry-utils": "~2.101.1",
|
|
134
134
|
"@tylerbu/sorted-btree-es6": "^2.1.1",
|
|
135
135
|
"double-ended-queue": "^2.1.0-0",
|
|
136
136
|
"lz4js": "^0.2.0",
|
|
@@ -140,16 +140,16 @@
|
|
|
140
140
|
"devDependencies": {
|
|
141
141
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
142
142
|
"@biomejs/biome": "~2.4.5",
|
|
143
|
-
"@fluid-internal/mocha-test-setup": "~2.
|
|
144
|
-
"@fluid-private/stochastic-test-utils": "~2.
|
|
145
|
-
"@fluid-private/test-pairwise-generator": "~2.
|
|
146
|
-
"@fluid-tools/benchmark": "^0.
|
|
143
|
+
"@fluid-internal/mocha-test-setup": "~2.101.1",
|
|
144
|
+
"@fluid-private/stochastic-test-utils": "~2.101.1",
|
|
145
|
+
"@fluid-private/test-pairwise-generator": "~2.101.1",
|
|
146
|
+
"@fluid-tools/benchmark": "^0.59.0",
|
|
147
147
|
"@fluid-tools/build-cli": "^0.65.0",
|
|
148
148
|
"@fluidframework/build-common": "^2.0.3",
|
|
149
149
|
"@fluidframework/build-tools": "^0.65.0",
|
|
150
150
|
"@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.92.0",
|
|
151
151
|
"@fluidframework/eslint-config-fluid": "^9.0.0",
|
|
152
|
-
"@fluidframework/test-runtime-utils": "~2.
|
|
152
|
+
"@fluidframework/test-runtime-utils": "~2.101.1",
|
|
153
153
|
"@microsoft/api-extractor": "7.58.1",
|
|
154
154
|
"@types/double-ended-queue": "^2.1.0",
|
|
155
155
|
"@types/lz4js": "^0.2.0",
|
|
@@ -229,6 +229,9 @@ interface IBlobManagerInternalEvents {
|
|
|
229
229
|
|
|
230
230
|
const createAbortError = (): LoggingError => new LoggingError("uploadBlob aborted");
|
|
231
231
|
|
|
232
|
+
/**
|
|
233
|
+
* @internal
|
|
234
|
+
*/
|
|
232
235
|
export const blobManagerBasePath = "_blobs";
|
|
233
236
|
|
|
234
237
|
export class BlobManager {
|
|
@@ -18,6 +18,9 @@ export interface IBlobManagerLoadInfo {
|
|
|
18
18
|
redirectTable?: [string, string][];
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
21
24
|
export const redirectTableBlobName = ".redirectTable";
|
|
22
25
|
|
|
23
26
|
/**
|
|
@@ -57,11 +60,15 @@ export const toRedirectTable = (
|
|
|
57
60
|
blobManagerLoadInfo: IBlobManagerLoadInfo,
|
|
58
61
|
logger: ITelemetryLoggerExt,
|
|
59
62
|
): Map<string, string> => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
const count = blobManagerLoadInfo.ids?.length ?? 0;
|
|
64
|
+
const redirectTableLength = blobManagerLoadInfo.redirectTable?.length ?? 0;
|
|
65
|
+
if (count > 0 || redirectTableLength > 0) {
|
|
66
|
+
logger.sendTelemetryEvent({
|
|
67
|
+
eventName: "AttachmentBlobsLoaded",
|
|
68
|
+
count,
|
|
69
|
+
redirectTable: redirectTableLength,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
65
72
|
const redirectTable = new Map<string, string>(blobManagerLoadInfo.redirectTable);
|
|
66
73
|
if (blobManagerLoadInfo.ids !== undefined) {
|
|
67
74
|
for (const storageId of blobManagerLoadInfo.ids) {
|
|
@@ -7,6 +7,7 @@ import { performanceNow } from "@fluid-internal/client-utils";
|
|
|
7
7
|
import type { IDeltaManagerFull } from "@fluidframework/container-definitions/internal";
|
|
8
8
|
import type { IContainerRuntimeEvents } from "@fluidframework/container-runtime-definitions/internal";
|
|
9
9
|
import type { ITelemetryBaseLogger, IEventProvider } from "@fluidframework/core-interfaces";
|
|
10
|
+
import { LogLevel } from "@fluidframework/core-interfaces";
|
|
10
11
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
11
12
|
import {
|
|
12
13
|
type IDocumentMessage,
|
|
@@ -303,16 +304,20 @@ class OpPerfTelemetry {
|
|
|
303
304
|
|
|
304
305
|
private reportGettingUpToDate(): void {
|
|
305
306
|
this.connectionOpSeqNumber = undefined;
|
|
306
|
-
this.logger.sendPerformanceEvent(
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
307
|
+
this.logger.sendPerformanceEvent(
|
|
308
|
+
{
|
|
309
|
+
eventName: "ConnectionSpeed",
|
|
310
|
+
duration: performanceNow() - this.connectionStartTime,
|
|
311
|
+
ops: this.gap,
|
|
312
|
+
// track time to connect only for first connection.
|
|
313
|
+
timeToConnect: this.firstConnection
|
|
314
|
+
? formatTick(this.connectionStartTime - this.bootTime)
|
|
315
|
+
: undefined,
|
|
316
|
+
firstConnection: this.firstConnection,
|
|
317
|
+
},
|
|
318
|
+
undefined, // error
|
|
319
|
+
LogLevel.info,
|
|
320
|
+
);
|
|
316
321
|
}
|
|
317
322
|
|
|
318
323
|
private recordPingTime(latency: number): void {
|
package/src/containerRuntime.ts
CHANGED
|
@@ -57,6 +57,7 @@ import type {
|
|
|
57
57
|
ITelemetryBaseLogger,
|
|
58
58
|
Listenable,
|
|
59
59
|
} from "@fluidframework/core-interfaces";
|
|
60
|
+
import { LogLevel } from "@fluidframework/core-interfaces";
|
|
60
61
|
import type {
|
|
61
62
|
IFluidHandleContext,
|
|
62
63
|
IFluidHandleInternal,
|
|
@@ -1335,7 +1336,12 @@ export class ContainerRuntime
|
|
|
1335
1336
|
targetClientId?: string,
|
|
1336
1337
|
) => void;
|
|
1337
1338
|
public readonly disposeFn: (error?: ICriticalContainerError) => void;
|
|
1338
|
-
|
|
1339
|
+
|
|
1340
|
+
/**
|
|
1341
|
+
* Initiate closing of the container due to a critical error.
|
|
1342
|
+
* @param error - The critical error that caused the container to close.
|
|
1343
|
+
*/
|
|
1344
|
+
private readonly closeFn: (error: ICriticalContainerError) => void;
|
|
1339
1345
|
|
|
1340
1346
|
public get flushMode(): FlushMode {
|
|
1341
1347
|
return this._flushMode;
|
|
@@ -1917,6 +1923,7 @@ export class ContainerRuntime
|
|
|
1917
1923
|
|
|
1918
1924
|
this.garbageCollector = GarbageCollector.create({
|
|
1919
1925
|
runtime: this,
|
|
1926
|
+
closeFn: this.closeFn,
|
|
1920
1927
|
gcOptions: runtimeOptions.gcOptions,
|
|
1921
1928
|
baseSnapshot,
|
|
1922
1929
|
baseLogger: this.mc.logger,
|
|
@@ -2133,13 +2140,6 @@ export class ContainerRuntime
|
|
|
2133
2140
|
// (We have to call flush _before_ processing a runtime op, but after is ok for non-runtime op)
|
|
2134
2141
|
this.deltaManager.on("op", () => this.flush());
|
|
2135
2142
|
|
|
2136
|
-
// logging hardware telemetry
|
|
2137
|
-
this.baseLogger.send({
|
|
2138
|
-
category: "generic",
|
|
2139
|
-
eventName: "DeviceSpec",
|
|
2140
|
-
...getDeviceSpec(),
|
|
2141
|
-
});
|
|
2142
|
-
|
|
2143
2143
|
this.mc.logger.sendTelemetryEvent({
|
|
2144
2144
|
eventName: "ContainerLoadStats",
|
|
2145
2145
|
...this.createContainerMetadata,
|
|
@@ -2162,6 +2162,8 @@ export class ContainerRuntime
|
|
|
2162
2162
|
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
2163
2163
|
initialSequenceNumber: this.deltaManager.initialSequenceNumber,
|
|
2164
2164
|
minVersionForCollab: this.minVersionForCollab,
|
|
2165
|
+
// logging hardware telemetry
|
|
2166
|
+
deviceSpec: { ...getDeviceSpec() },
|
|
2165
2167
|
});
|
|
2166
2168
|
|
|
2167
2169
|
ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.baseLogger);
|
|
@@ -2395,12 +2397,18 @@ export class ContainerRuntime
|
|
|
2395
2397
|
}
|
|
2396
2398
|
}
|
|
2397
2399
|
|
|
2400
|
+
public close(): void {
|
|
2401
|
+
this.garbageCollector.dispose();
|
|
2402
|
+
}
|
|
2403
|
+
|
|
2398
2404
|
public dispose(error?: Error): void {
|
|
2399
2405
|
if (this._disposed) {
|
|
2400
2406
|
return;
|
|
2401
2407
|
}
|
|
2402
2408
|
this._disposed = true;
|
|
2403
2409
|
|
|
2410
|
+
// The ContainerRuntimeDisposed event is redundant with the loader's ContainerDispose event
|
|
2411
|
+
// (see #27126) and can be removed once the change for ContainerDispose has saturated in telemetry.
|
|
2404
2412
|
this.mc.logger.sendTelemetryEvent(
|
|
2405
2413
|
{
|
|
2406
2414
|
eventName: "ContainerRuntimeDisposed",
|
|
@@ -2409,6 +2417,7 @@ export class ContainerRuntime
|
|
|
2409
2417
|
attachState: this.attachState,
|
|
2410
2418
|
},
|
|
2411
2419
|
error,
|
|
2420
|
+
LogLevel.info,
|
|
2412
2421
|
);
|
|
2413
2422
|
|
|
2414
2423
|
if (this.summaryManager !== undefined) {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import type { ICriticalContainerError } from "@fluidframework/container-definitions";
|
|
6
7
|
import type { IRequest } from "@fluidframework/core-interfaces";
|
|
7
8
|
import { assert, LazyPromise, Timer } from "@fluidframework/core-utils/internal";
|
|
8
9
|
import type { ISnapshotTree } from "@fluidframework/driver-definitions/internal";
|
|
@@ -141,6 +142,10 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
141
142
|
private completedRuns = 0;
|
|
142
143
|
|
|
143
144
|
private readonly runtime: IGarbageCollectionRuntime;
|
|
145
|
+
/**
|
|
146
|
+
* Called when the runtime should close because of an error.
|
|
147
|
+
*/
|
|
148
|
+
private readonly closeFn: (error: ICriticalContainerError) => void;
|
|
144
149
|
private readonly isSummarizerClient: boolean;
|
|
145
150
|
|
|
146
151
|
private readonly summaryStateTracker: GCSummaryStateTracker;
|
|
@@ -168,6 +173,7 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
168
173
|
|
|
169
174
|
protected constructor(createParams: IGarbageCollectorCreateParams) {
|
|
170
175
|
this.runtime = createParams.runtime;
|
|
176
|
+
this.closeFn = createParams.closeFn;
|
|
171
177
|
this.isSummarizerClient = createParams.isSummarizerClient;
|
|
172
178
|
this.getNodePackagePath = createParams.getNodePackagePath;
|
|
173
179
|
this.getLastSummaryTimestampMs = createParams.getLastSummaryTimestampMs;
|
|
@@ -202,14 +208,10 @@ export class GarbageCollector implements IGarbageCollector {
|
|
|
202
208
|
}
|
|
203
209
|
timeoutMs = overrideSessionExpiryTimeoutMs ?? timeoutMs;
|
|
204
210
|
if (timeoutMs <= 0) {
|
|
205
|
-
this.
|
|
206
|
-
new ClientSessionExpiredError(`Client session expired.`, timeoutMs),
|
|
207
|
-
);
|
|
211
|
+
this.closeFn(new ClientSessionExpiredError(`Client session expired.`, timeoutMs));
|
|
208
212
|
}
|
|
209
213
|
this.sessionExpiryTimer = new Timer(timeoutMs, () => {
|
|
210
|
-
this.
|
|
211
|
-
new ClientSessionExpiredError(`Client session expired.`, timeoutMs),
|
|
212
|
-
);
|
|
214
|
+
this.closeFn(new ClientSessionExpiredError(`Client session expired.`, timeoutMs));
|
|
213
215
|
});
|
|
214
216
|
this.sessionExpiryTimer.start();
|
|
215
217
|
this.sessionExpiryTimerStarted = Date.now();
|
package/src/gc/gcDefinitions.ts
CHANGED
|
@@ -363,10 +363,6 @@ export interface IGarbageCollectionRuntime {
|
|
|
363
363
|
* Returns the type of the GC node.
|
|
364
364
|
*/
|
|
365
365
|
getNodeType(nodePath: string): GCNodeType;
|
|
366
|
-
/**
|
|
367
|
-
* Called when the runtime should close because of an error.
|
|
368
|
-
*/
|
|
369
|
-
closeFn: (error?: ICriticalContainerError) => void;
|
|
370
366
|
}
|
|
371
367
|
|
|
372
368
|
/**
|
|
@@ -453,6 +449,12 @@ export interface IGarbageCollector {
|
|
|
453
449
|
*/
|
|
454
450
|
isNodeDeleted(nodePath: string): boolean;
|
|
455
451
|
setConnectionState(canSendOps: boolean, clientId?: string): void;
|
|
452
|
+
/**
|
|
453
|
+
* Cancels all GC timers and clears tracked state so timers do not keep the event loop alive
|
|
454
|
+
* or leak memory.
|
|
455
|
+
* @remarks
|
|
456
|
+
* This is idempotent - it is safe to call multiple times.
|
|
457
|
+
*/
|
|
456
458
|
dispose(): void;
|
|
457
459
|
}
|
|
458
460
|
|
|
@@ -497,6 +499,11 @@ export interface IGCNodeUpdatedProps {
|
|
|
497
499
|
*/
|
|
498
500
|
export interface IGarbageCollectorCreateParams {
|
|
499
501
|
readonly runtime: IGarbageCollectionRuntime;
|
|
502
|
+
/**
|
|
503
|
+
* Initiate closing of the container due to an error.
|
|
504
|
+
*/
|
|
505
|
+
readonly closeFn: (error: ICriticalContainerError) => void;
|
|
506
|
+
|
|
500
507
|
readonly gcOptions: IGCRuntimeOptions;
|
|
501
508
|
readonly baseLogger: ITelemetryLoggerExt;
|
|
502
509
|
readonly existing: boolean;
|
package/src/index.ts
CHANGED
|
@@ -30,6 +30,11 @@ export type {
|
|
|
30
30
|
} from "./messageTypes.js";
|
|
31
31
|
export { ContainerMessageType } from "./messageTypes.js";
|
|
32
32
|
export type { IBlobManagerLoadInfo } from "./blobManager/index.js";
|
|
33
|
+
export {
|
|
34
|
+
blobManagerBasePath,
|
|
35
|
+
blobsTreeName,
|
|
36
|
+
redirectTableBlobName,
|
|
37
|
+
} from "./blobManager/index.js";
|
|
33
38
|
export type { IDataStoreAliasMessage } from "./dataStore.js";
|
|
34
39
|
export { FluidDataStoreRegistry } from "./dataStoreRegistry.js";
|
|
35
40
|
export {
|
package/src/metadata.ts
CHANGED
|
@@ -40,6 +40,20 @@ export interface IBatchMetadata {
|
|
|
40
40
|
* Maybe set on first message of a batch, to the batchId generated when resubmitting (set/fixed on first resubmit)
|
|
41
41
|
*/
|
|
42
42
|
batchId?: BatchId;
|
|
43
|
+
/**
|
|
44
|
+
* Set on the envelope of a grouped batch op to the number of inner ops it contains.
|
|
45
|
+
* Exposed on the wire so consumers can record batch sizes in telemetry without parsing the grouped batch contents.
|
|
46
|
+
*
|
|
47
|
+
* Observable values:
|
|
48
|
+
* - Absent: either this is not a grouped batch envelope (e.g. a singleton batch that bypassed grouping), OR the producing runtime predates this field. Until the rollout is complete, telemetry consumers should treat absence as ambiguous and parse the envelope contents if a precise count is required for a grouped batch.
|
|
49
|
+
* - `0`: empty-grouped-batch placeholder produced when a resubmitted batch becomes empty.
|
|
50
|
+
* - `N` (N \> 0): grouped batch with N inner ops. For a chunked grouped batch this appears only on the last chunk's envelope (intermediate chunks carry no metadata).
|
|
51
|
+
*
|
|
52
|
+
* The field is intentionally advisory-only: the runtime does not validate that an inbound value matches the batch's actual inner op count. It is consumed exclusively by off-runtime telemetry.
|
|
53
|
+
*
|
|
54
|
+
* The field is always (re)stamped at outbound time from the current batch's actual size — `groupBatch` reads `batch.messages.length` directly, `createEmptyGroupedBatch` always writes `0`, and the chunking path only ever sees freshly-grouped envelopes from the same flush. It is never propagated from stashed pending state to the wire: on resubmit, ops re-enter grouping and the count is recomputed from the (possibly squashed, dropped, or added) outbound batch. This means the wire value always reflects the actual outbound size, even when the resubmitted batch differs from the original.
|
|
55
|
+
*/
|
|
56
|
+
groupedOpCount?: number;
|
|
43
57
|
}
|
|
44
58
|
|
|
45
59
|
/**
|
|
@@ -100,7 +100,7 @@ export class OpGroupingManager {
|
|
|
100
100
|
const serializedOp = JSON.stringify(emptyGroupedBatch);
|
|
101
101
|
|
|
102
102
|
const placeholderMessage: LocalEmptyBatchPlaceholder = {
|
|
103
|
-
metadata: { batchId: resubmittingBatchId },
|
|
103
|
+
metadata: { batchId: resubmittingBatchId, groupedOpCount: 0 },
|
|
104
104
|
localOpMetadata: { emptyBatch: true },
|
|
105
105
|
referenceSequenceNumber,
|
|
106
106
|
runtimeOp: emptyGroupedBatch,
|
|
@@ -169,7 +169,7 @@ export class OpGroupingManager {
|
|
|
169
169
|
...batch,
|
|
170
170
|
messages: [
|
|
171
171
|
{
|
|
172
|
-
metadata: { batchId: groupedBatchId },
|
|
172
|
+
metadata: { batchId: groupedBatchId, groupedOpCount: batch.messages.length },
|
|
173
173
|
referenceSequenceNumber: batch.messages[0].referenceSequenceNumber,
|
|
174
174
|
contents: serializedContent,
|
|
175
175
|
},
|
|
@@ -171,12 +171,22 @@ export class OpSplitter {
|
|
|
171
171
|
);
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
// The last chunk will be part of the new batch and needs to
|
|
175
|
-
//
|
|
174
|
+
// The last chunk will be part of the new batch and needs to preserve the
|
|
175
|
+
// batch metadata of the original batch. groupedOpCount is surfaced here
|
|
176
|
+
// (and only here, not on intermediate chunks) because intermediate chunks
|
|
177
|
+
// don't carry ops — they carry parts of a payload that only become ops
|
|
178
|
+
// once the last chunk is processed and the payload is reassembled.
|
|
179
|
+
// Stamping every chunk would let an observer double-count messages.
|
|
180
|
+
// batchId is deliberately not forwarded — it's a runtime dedup field
|
|
181
|
+
// consumed only after processChunk restores originalMetadata, not by
|
|
182
|
+
// wire observers.
|
|
176
183
|
const lastChunk = chunkToBatchMessage(
|
|
177
184
|
chunks[chunks.length - 1],
|
|
178
185
|
batch.referenceSequenceNumber,
|
|
179
|
-
{
|
|
186
|
+
{
|
|
187
|
+
batch: firstMessage.metadata?.batch,
|
|
188
|
+
groupedOpCount: firstMessage.metadata?.groupedOpCount,
|
|
189
|
+
},
|
|
180
190
|
);
|
|
181
191
|
|
|
182
192
|
this.logger.sendPerformanceEvent({
|
package/src/packageVersion.ts
CHANGED
|
@@ -125,8 +125,10 @@ export interface ISummarizerRuntime extends IConnectableRuntime {
|
|
|
125
125
|
*/
|
|
126
126
|
readonly summarizerClientId: string | undefined;
|
|
127
127
|
readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;
|
|
128
|
+
/**
|
|
129
|
+
* Initiate disposal of the container.
|
|
130
|
+
*/
|
|
128
131
|
disposeFn(): void;
|
|
129
|
-
closeFn(): void;
|
|
130
132
|
on(
|
|
131
133
|
event: "op",
|
|
132
134
|
listener: (op: ISequencedDocumentMessage, runtimeMessage?: boolean) => void,
|