From 43ce18baf8f5b40a991beff11d59753791292d40 Mon Sep 17 00:00:00 2001 From: Joshua Smithrud <54606601+Josmithr@users.noreply.github.com> Date: Fri, 17 Jan 2025 12:41:16 -0800 Subject: [PATCH] refactor(container-runtime): Enable `@typescript-eslint/explicit-module-boundary-types` eslint rule and fix violations (#23597) One in a series of PRs working towards migrating the package to our `recommended` config. Plus a couple of misc. comment syntax fixes/improvements. [AB#3027](https://dev.azure.com/fluidframework/235294da-091d-4c29-84fc-cdfc3d90890b/_workitems/edit/3027) --- .../runtime/container-runtime/.eslintrc.cjs | 1 + .../container-runtime/src/batchTracker.ts | 3 +- .../src/blobManager/blobManager.ts | 10 +-- .../src/blobManager/blobManagerSnapSum.ts | 2 +- .../src/channelCollection.ts | 34 ++++---- .../src/containerHandleContext.ts | 4 +- .../container-runtime/src/containerRuntime.ts | 69 ++++++++------- .../container-runtime/src/dataStoreContext.ts | 83 +++++++++++-------- .../src/dataStoreContexts.ts | 18 ++-- .../src/dataStoreRegistry.ts | 2 +- .../src/deltaManagerProxies.ts | 8 +- .../container-runtime/src/deltaScheduler.ts | 2 +- .../src/gc/garbageCollection.ts | 6 +- .../container-runtime/src/gc/gcHelpers.ts | 6 +- .../src/gc/gcSummaryStateTracker.ts | 6 +- .../container-runtime/src/gc/gcTelemetry.ts | 6 +- .../src/gc/gcUnreferencedStateTracker.ts | 8 +- .../src/inboundBatchAggregator.ts | 2 +- .../src/opLifecycle/batchManager.ts | 6 +- .../src/opLifecycle/opDecompressor.ts | 2 +- .../src/opLifecycle/opSplitter.ts | 2 +- .../src/opLifecycle/outbox.ts | 14 ++-- .../src/opLifecycle/remoteMessageProcessor.ts | 2 +- .../src/pendingStateManager.ts | 10 +-- .../src/summary/documentSchema.ts | 6 +- .../src/summary/orderedClientElection.ts | 12 +-- .../summary/runWhileConnectedCoordinator.ts | 9 +- .../src/summary/runningSummarizer.ts | 9 +- .../src/summary/summarizer.ts | 22 +++-- .../src/summary/summarizerClientElection.ts | 4 +- .../src/summary/summarizerHeuristics.ts | 12 +-- .../summary/summarizerNode/summarizerNode.ts | 14 ++-- .../summarizerNode/summarizerNodeWithGc.ts | 8 +- .../src/summary/summaryCollection.ts | 12 +-- .../src/summary/summaryGenerator.ts | 6 +- .../src/summary/summaryManager.ts | 6 +- .../src/test/blobManager.spec.ts | 44 ++++++---- .../src/test/blobManager.stashed.spec.ts | 2 +- .../src/test/fuzz/summarizerFuzzMocks.ts | 12 +-- .../src/test/gc/gcUnitTestHelpers.ts | 6 +- .../src/test/summary/testQuorumClients.ts | 8 +- .../container-runtime/src/throttler.ts | 10 +-- .../src/dataStoreContext.ts | 6 +- 43 files changed, 291 insertions(+), 223 deletions(-) diff --git a/packages/runtime/container-runtime/.eslintrc.cjs b/packages/runtime/container-runtime/.eslintrc.cjs index c7a534e947c1..296e42636bd1 100644 --- a/packages/runtime/container-runtime/.eslintrc.cjs +++ b/packages/runtime/container-runtime/.eslintrc.cjs @@ -17,6 +17,7 @@ module.exports = { // #region TODO:AB#3027: remove overrides and upgrade config to `recommended` + "@typescript-eslint/explicit-module-boundary-types": "error", "@typescript-eslint/no-explicit-any": [ "error", { diff --git a/packages/runtime/container-runtime/src/batchTracker.ts b/packages/runtime/container-runtime/src/batchTracker.ts index 5d30995c59ee..81bee406dde3 100644 --- a/packages/runtime/container-runtime/src/batchTracker.ts +++ b/packages/runtime/container-runtime/src/batchTracker.ts @@ -84,4 +84,5 @@ export const BindBatchTracker = ( logger: ITelemetryLoggerExt, batchLengthThreshold: number = 1000, batchCountSamplingRate: number = 1000, -) => new BatchTracker(batchEventEmitter, logger, batchLengthThreshold, batchCountSamplingRate); +): BatchTracker => + new BatchTracker(batchEventEmitter, logger, batchLengthThreshold, batchCountSamplingRate); diff --git a/packages/runtime/container-runtime/src/blobManager/blobManager.ts b/packages/runtime/container-runtime/src/blobManager/blobManager.ts index 4888f40c53d6..bb5ed2873ebb 100644 --- a/packages/runtime/container-runtime/src/blobManager/blobManager.ts +++ b/packages/runtime/container-runtime/src/blobManager/blobManager.ts @@ -80,14 +80,14 @@ export class BlobHandle extends FluidHandleBase { this.absolutePath = generateHandleContextPath(path, this.routeContext); } - public attachGraph() { + public attachGraph(): void { if (!this.attached) { this.attached = true; this.onAttachGraph?.(); } } - public bind(handle: IFluidHandleInternal) { + public bind(handle: IFluidHandleInternal): void { throw new Error("Cannot bind to blob handle"); } } @@ -598,7 +598,7 @@ export class BlobManager extends TypedEventEmitter { * submitted to runtime while disconnected. * @param metadata - op metadata containing storage and/or local IDs */ - public reSubmit(metadata: Record | undefined) { + public reSubmit(metadata: Record | undefined): void { assert(!!metadata, 0x38b /* Resubmitted ops must have metadata */); const { localId, blobId }: { localId?: string; blobId?: string } = metadata; assert(localId !== undefined, 0x50d /* local ID not available on reSubmit */); @@ -615,7 +615,7 @@ export class BlobManager extends TypedEventEmitter { return this.sendBlobAttachOp(localId, blobId); } - public processBlobAttachMessage(message: ISequencedMessageEnvelope, local: boolean) { + public processBlobAttachMessage(message: ISequencedMessageEnvelope, local: boolean): void { const localId = (message.metadata as IBlobMetadata | undefined)?.localId; const blobId = (message.metadata as IBlobMetadata | undefined)?.blobId; @@ -785,7 +785,7 @@ export class BlobManager extends TypedEventEmitter { throw error; } - public setRedirectTable(table: Map) { + public setRedirectTable(table: Map): void { assert( this.runtime.attachState === AttachState.Detached, 0x252 /* "redirect table can only be set in detached container" */, diff --git a/packages/runtime/container-runtime/src/blobManager/blobManagerSnapSum.ts b/packages/runtime/container-runtime/src/blobManager/blobManagerSnapSum.ts index 8d6c54207c99..1bb42851b6b2 100644 --- a/packages/runtime/container-runtime/src/blobManager/blobManagerSnapSum.ts +++ b/packages/runtime/container-runtime/src/blobManager/blobManagerSnapSum.ts @@ -116,7 +116,7 @@ const summarizeV1 = ( export const getStorageIds = ( redirectTable: Map, attachState: AttachState, -) => { +): Set => { const ids = new Set(redirectTable.values()); // If we are detached, we will not have storage IDs, only undefined diff --git a/packages/runtime/container-runtime/src/channelCollection.ts b/packages/runtime/container-runtime/src/channelCollection.ts index cbdc1932484c..d1d31289ce44 100644 --- a/packages/runtime/container-runtime/src/channelCollection.ts +++ b/packages/runtime/container-runtime/src/channelCollection.ts @@ -247,7 +247,7 @@ function wrapContextForInnerChannel( /** * Returns the type of the given local data store from its package path. */ -export function getLocalDataStoreType(localDataStore: LocalFluidDataStoreContext) { +export function getLocalDataStoreType(localDataStore: LocalFluidDataStoreContext): string { return localDataStore.packagePath[localDataStore.packagePath.length - 1]; } @@ -392,7 +392,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable { * Not clear when it would be called and what it should do. * Currently this API is called by context only for root data stores. */ - public makeVisibleAndAttachGraph() { + public makeVisibleAndAttachGraph(): void { this.parentContext.makeLocallyVisible(); } @@ -595,7 +595,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable { this.contexts.bind(id); } - protected submitAttachChannelOp(localContext: LocalFluidDataStoreContext) { + protected submitAttachChannelOp(localContext: LocalFluidDataStoreContext): void { const message = this.generateAttachMessage(localContext); this.pendingAttach.set(localContext.id, message); this.parentContext.submitMessage(ContainerMessageType.Attach, message, undefined); @@ -672,7 +672,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable { pkg: Readonly, contextCtor: new (props: ILocalDetachedFluidDataStoreContextProps) => T, loadingGroupId?: string, - ) { + ): T { assert(loadingGroupId !== "", 0x974 /* loadingGroupId should not be the empty string */); const context = new contextCtor({ id, @@ -699,12 +699,12 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable { return context; } - public get disposed() { + public get disposed(): boolean { return this.disposeOnce.evaluated; } - public readonly dispose = () => this.disposeOnce.value; + public readonly dispose = (): void => this.disposeOnce.value; - public reSubmit(type: string, content: unknown, localOpMetadata: unknown) { + public reSubmit(type: string, content: unknown, localOpMetadata: unknown): void { switch (type) { case ContainerMessageType.Attach: case ContainerMessageType.Alias: @@ -717,7 +717,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable { } } - protected reSubmitChannelOp(type: string, content: unknown, localOpMetadata: unknown) { + protected reSubmitChannelOp(type: string, content: unknown, localOpMetadata: unknown): void { const envelope = content as IEnvelope; const context = this.contexts.get(envelope.address); // If the data store has been deleted, log an error and throw an error. If there are local changes for a @@ -735,7 +735,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable { context.reSubmit(innerContents.type, innerContents.content, localOpMetadata); } - public rollback(type: string, content: unknown, localOpMetadata: unknown) { + public rollback(type: string, content: unknown, localOpMetadata: unknown): void { assert(type === ContainerMessageType.FluidDataStoreOp, 0x8e8 /* type */); const envelope = content as IEnvelope; const context = this.contexts.get(envelope.address); @@ -768,7 +768,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable { } } - protected async applyStashedChannelChannelOp(envelope: IEnvelope) { + protected async applyStashedChannelChannelOp(envelope: IEnvelope): Promise { const context = this.contexts.get(envelope.address); // If the data store has been deleted, log an error and ignore this message. This helps prevent document // corruption in case the data store that stashed the op is deleted. @@ -854,7 +854,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable { message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown, - ) { + ): void { this.processMessages({ envelope: message, messagesContent: [ @@ -1096,7 +1096,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable { return true; } - public processSignal(messageArg: IInboundSignalMessage, local: boolean) { + public processSignal(messageArg: IInboundSignalMessage, local: boolean): void { const envelope = messageArg.content as IEnvelope; const fluidDataStoreId = envelope.address; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment @@ -1123,7 +1123,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable { context.processSignal(message, local); } - public setConnectionState(connected: boolean, clientId?: string) { + public setConnectionState(connected: boolean, clientId?: string): void { for (const [fluidDataStoreId, context] of this.contexts) { try { context.setConnectionState(connected, clientId); @@ -1333,7 +1333,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable { * After GC has run, called to notify this Container's data stores of routes that are used in it. * @param usedRoutes - The routes that are used in all data stores in this Container. */ - public updateUsedRoutes(usedRoutes: readonly string[]) { + public updateUsedRoutes(usedRoutes: readonly string[]): void { // Get a map of data store ids to routes used in it. const usedDataStoreRoutes = unpackChildNodesUsedRoutes(usedRoutes); @@ -1351,7 +1351,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable { } } - public deleteChild(dataStoreId: string) { + public deleteChild(dataStoreId: string): void { const dataStoreContext = this.contexts.get(dataStoreId); assert(dataStoreContext !== undefined, 0x2d7 /* No data store with specified id */); @@ -1423,7 +1423,7 @@ export class ChannelCollection implements IFluidDataStoreChannel, IDisposable { * * @param tombstonedRoutes - The routes that are tombstones in all data stores in this Container. */ - public updateTombstonedRoutes(tombstonedRoutes: readonly string[]) { + public updateTombstonedRoutes(tombstonedRoutes: readonly string[]): void { const tombstonedDataStoresSet: Set = new Set(); for (const route of tombstonedRoutes) { const pathParts = route.split("/"); @@ -1637,7 +1637,7 @@ export class ChannelCollectionFactory { return this; } diff --git a/packages/runtime/container-runtime/src/containerHandleContext.ts b/packages/runtime/container-runtime/src/containerHandleContext.ts index 27840fe415cd..31ce30cdd06c 100644 --- a/packages/runtime/container-runtime/src/containerHandleContext.ts +++ b/packages/runtime/container-runtime/src/containerHandleContext.ts @@ -14,7 +14,7 @@ export interface IContainerHandleContextRuntime { } export class ContainerFluidHandleContext implements IFluidHandleContext { - public get IFluidHandleContext() { + public get IFluidHandleContext(): IFluidHandleContext { return this; } public readonly absolutePath: string; @@ -37,7 +37,7 @@ export class ContainerFluidHandleContext implements IFluidHandleContext { throw new Error("can't attach container runtime form within container!"); } - public get isAttached() { + public get isAttached(): boolean { return this.runtime.attachState !== AttachState.Detached; } diff --git a/packages/runtime/container-runtime/src/containerRuntime.ts b/packages/runtime/container-runtime/src/containerRuntime.ts index 86e5de9abf65..6a3f4a943737 100644 --- a/packages/runtime/container-runtime/src/containerRuntime.ts +++ b/packages/runtime/container-runtime/src/containerRuntime.ts @@ -92,6 +92,7 @@ import { gcTreeKey, IInboundSignalMessage, type IRuntimeMessagesContent, + type ISummarizerNodeWithGC, } from "@fluidframework/runtime-definitions/internal"; import { GCDataBuilder, @@ -243,6 +244,7 @@ import { rootHasIsolatedChannels, summarizerClientType, wrapSummaryInChannelsTree, + type IDocumentSchemaFeatures, } from "./summary/index.js"; import { Throttler, formExponentialFn } from "./throttler.js"; @@ -730,7 +732,7 @@ export const makeLegacySendBatchFn = ) => number, deltaManager: Pick, "flush">, ) => - (batch: IBatch) => { + (batch: IBatch): number => { // Default to negative one to match Container.submitBatch behavior let clientSequenceNumber: number = -1; for (const message of batch.messages) { @@ -811,7 +813,7 @@ function lastMessageFromMetadata(metadata: IContainerRuntimeMetadata | undefined * We only want to log this once, to avoid spamming telemetry if we are wrong and these cases are hit commonly. */ export let getSingleUseLegacyLogCallback = (logger: ITelemetryLoggerExt, type: string) => { - return (codePath: string) => { + return (codePath: string): void => { logger.sendTelemetryEvent({ eventName: "LegacyMessageFormat", details: { codePath, type }, @@ -1207,7 +1209,7 @@ export class ContainerRuntime return this._storage; } - public get containerRuntime() { + public get containerRuntime(): ContainerRuntime { return this; } @@ -1259,9 +1261,13 @@ export class ContainerRuntime * has to deal with compressed ops as other clients might send them. * And in reverse, session schema can have compression Off, but feature gates / runtime options want it On. * In such case it will be off in session schema, however this client will propose change to schema, and once / if - * this op rountrips, compression will be On. Client can't send compressed ops until it's change in schema. + * this op roundtrips, compression will be On. Client can't send compressed ops until it's change in schema. */ - public get sessionSchema() { + public get sessionSchema(): { + [P in keyof IDocumentSchemaFeatures]?: IDocumentSchemaFeatures[P] extends boolean + ? true + : IDocumentSchemaFeatures[P]; + } { return this.documentsSchemaController.sessionSchema.runtime; } @@ -1277,13 +1283,13 @@ export class ContainerRuntime // In such case we have to process all ops, including those marked with savedOp === true. private readonly skipSavedCompressorOps: boolean; - public get idCompressorMode() { + public get idCompressorMode(): IdCompressorMode { return this.sessionSchema.idCompressorMode; } /** - * See IContainerRuntimeBase.idCompressor() for details. + * {@inheritDoc @fluidframework/runtime-definitions#IContainerRuntimeBase.idCompressor} */ - public get idCompressor() { + public get idCompressor(): (IIdCompressor & IIdCompressorCore) | undefined { // Expose ID Compressor only if it's On from the start. // If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else. // That's because any other usage will require immidiate loading of ID Compressor in next sessions in order @@ -1301,9 +1307,9 @@ export class ContainerRuntime protected _loadIdCompressor: Promise | undefined; /** - * See IContainerRuntimeBase.generateDocumentUniqueId() for details. + * {@inheritDoc @fluidframework/runtime-definitions#IContainerRuntimeBase.generateDocumentUniqueId} */ - public generateDocumentUniqueId() { + public generateDocumentUniqueId(): string | number { return this._idCompressor?.generateDocumentUniqueId() ?? uuid(); } @@ -1395,7 +1401,7 @@ export class ContainerRuntime } private _disposed = false; - public get disposed() { + public get disposed(): boolean { return this._disposed; } @@ -2144,7 +2150,7 @@ export class ContainerRuntime this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined; } - public onSchemaChange(schema: IDocumentSchemaCurrent) { + public onSchemaChange(schema: IDocumentSchemaCurrent): void { this.logger.sendTelemetryEvent({ eventName: "SchemaChangeAccept", sessionRuntimeSchema: JSON.stringify(schema), @@ -2171,7 +2177,7 @@ export class ContainerRuntime return ( summarizeInternal: SummarizeInternalFn, getGCDataFn: (fullGC?: boolean) => Promise, - ) => + ): ISummarizerNodeWithGC => this.summarizerNode.createChild( summarizeInternal, id, @@ -2181,19 +2187,22 @@ export class ContainerRuntime ); } - public deleteChildSummarizerNode(id: string) { + public deleteChildSummarizerNode(id: string): void { return this.summarizerNode.deleteChild(id); } - /* IFluidParentContext APIs that should not be called on Root */ - public makeLocallyVisible() { + // #region `IFluidParentContext` APIs that should not be called on Root + + public makeLocallyVisible(): void { assert(false, 0x8eb /* should not be called */); } - public setChannelDirty(address: string) { + public setChannelDirty(address: string): void { assert(false, 0x909 /* should not be called */); } + // #endregion + /** * Initializes the state from the base snapshot this container runtime loaded from. */ @@ -2491,7 +2500,7 @@ export class ContainerRuntime fullTree: boolean, trackState: boolean, telemetryContext?: ITelemetryContext, - ) { + ): void { this.addMetadataToSummary(summaryTree); if (this._idCompressor) { @@ -2684,7 +2693,7 @@ export class ContainerRuntime return this._loadIdCompressor; } - public setConnectionState(connected: boolean, clientId?: string) { + public setConnectionState(connected: boolean, clientId?: string): void { // Validate we have consistent state const currentClientId = this._audience.getSelf()?.clientId; assert(clientId === currentClientId, 0x977 /* input clientId does not match Audience */); @@ -2795,7 +2804,7 @@ export class ContainerRuntime raiseConnectedEvent(this.mc.logger, this, connected, clientId); } - public async notifyOpReplay(message: ISequencedDocumentMessage) { + public async notifyOpReplay(message: ISequencedDocumentMessage): Promise { await this.pendingStateManager.applyStashedOpsAt(message.sequenceNumber); } @@ -2804,7 +2813,7 @@ export class ContainerRuntime * @param messageCopy - Sequenced message for a distributed document. * @param local - true if the message was originally generated by the client receiving it. */ - public process({ ...messageCopy }: ISequencedDocumentMessage, local: boolean) { + public process({ ...messageCopy }: ISequencedDocumentMessage, local: boolean): void { // spread operator above ensure we make a shallow copy of message, as the processing flow will modify it. // There might be multiple container instances receiving the same message. @@ -3296,7 +3305,7 @@ export class ContainerRuntime } } - public processSignal(message: ISignalMessage, local: boolean) { + public processSignal(message: ISignalMessage, local: boolean): void { const envelope = message.content as ISignalEnvelope; const transformed: IInboundSignalMessage = { clientId: message.clientId, @@ -3595,7 +3604,7 @@ export class ContainerRuntime * Support for this option at container runtime is planned to be deprecated in the future. * */ - public submitSignal(type: string, content: unknown, targetClientId?: string) { + public submitSignal(type: string, content: unknown, targetClientId?: string): void { this.verifyNotClosed(); const envelope = this.createNewSignalEnvelope(undefined /* address */, type, content); return this.submitEnvelopedSignal(envelope, targetClientId); @@ -3790,7 +3799,7 @@ export class ContainerRuntime * @param usedRoutes - The routes that are used in all nodes in this Container. * @see IGarbageCollectionRuntime.updateUsedRoutes */ - public updateUsedRoutes(usedRoutes: readonly string[]) { + public updateUsedRoutes(usedRoutes: readonly string[]): void { // Update our summarizer node's used routes. Updating used routes in summarizer node before // summarizing is required and asserted by the the summarizer node. We are the root and are // always referenced, so the used routes is only self-route (empty string). @@ -3821,7 +3830,7 @@ export class ContainerRuntime * * @param tombstonedRoutes - Data store and attachment blob routes that are tombstones in this Container. */ - public updateTombstonedRoutes(tombstonedRoutes: readonly string[]) { + public updateTombstonedRoutes(tombstonedRoutes: readonly string[]): void { const { dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(tombstonedRoutes); this.channelCollection.updateTombstonedRoutes(dataStoreRoutes); } @@ -3918,7 +3927,11 @@ export class ContainerRuntime * @param toPath - The absolute path of the outbound node that is referenced. * @param messageTimestampMs - The timestamp of the message that added the reference. */ - public addedGCOutboundRoute(fromPath: string, toPath: string, messageTimestampMs?: number) { + public addedGCOutboundRoute( + fromPath: string, + toPath: string, + messageTimestampMs?: number, + ): void { // This is always called when processing an op so messageTimestampMs should exist. Due to back-compat // across the data store runtime / container runtime boundary, this may be undefined and if so, get // the timestamp from the last processed message which should exist. @@ -4410,7 +4423,7 @@ export class ContainerRuntime | ContainerMessageType.Alias | ContainerMessageType.Attach, // TODO: better typing - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any contents: any, localOpMetadata: unknown = undefined, ): void { @@ -4699,7 +4712,7 @@ export class ContainerRuntime /** * Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck */ - public async refreshLatestSummaryAck(options: IRefreshSummaryAckOptions) { + public async refreshLatestSummaryAck(options: IRefreshSummaryAckOptions): Promise { const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options; // proposalHandle is always passed from RunningSummarizer. assert(proposalHandle !== undefined, 0x766 /* proposalHandle should be available */); diff --git a/packages/runtime/container-runtime/src/dataStoreContext.ts b/packages/runtime/container-runtime/src/dataStoreContext.ts index 2de3cd8a4214..45cbdc4aa6e0 100644 --- a/packages/runtime/container-runtime/src/dataStoreContext.ts +++ b/packages/runtime/container-runtime/src/dataStoreContext.ts @@ -14,7 +14,11 @@ import { ITelemetryBaseProperties, type IEvent, } from "@fluidframework/core-interfaces"; -import { type IFluidHandleInternal } from "@fluidframework/core-interfaces/internal"; +import { + type IFluidHandleContext, + type IFluidHandleInternal, + type ITelemetryBaseLogger, +} from "@fluidframework/core-interfaces/internal"; import { assert, LazyPromise, unreachableCase } from "@fluidframework/core-utils/internal"; import { IClientDetails, IQuorumClients } from "@fluidframework/driver-definitions"; import { @@ -207,7 +211,7 @@ export abstract class FluidDataStoreContext return this.parentContext.clientDetails; } - public get baseLogger() { + public get baseLogger(): ITelemetryBaseLogger { return this.parentContext.baseLogger; } @@ -219,7 +223,7 @@ export abstract class FluidDataStoreContext return this.parentContext.connected; } - public get IFluidHandleContext() { + public get IFluidHandleContext(): IFluidHandleContext { return this.parentContext.IFluidHandleContext; } @@ -239,7 +243,7 @@ export abstract class FluidDataStoreContext } private _disposed = false; - public get disposed() { + public get disposed(): boolean { return this._disposed; } @@ -248,7 +252,7 @@ export abstract class FluidDataStoreContext * Tombstoned objects are eventually deleted by GC. */ private _tombstoned = false; - public get tombstoned() { + public get tombstoned(): boolean { return this._tombstoned; } /** @@ -434,11 +438,11 @@ export abstract class FluidDataStoreContext * This function is called to prevent ops from being generated from this data store once it has been deleted. Furthermore, this data store * should not receive any ops/signals. */ - public delete() { + public delete(): void { this.deleted = true; } - public setTombstone(tombstone: boolean) { + public setTombstone(tombstone: boolean): void { if (this.tombstoned === tombstone) { return; } @@ -488,7 +492,7 @@ export abstract class FluidDataStoreContext return this.channelP; } - protected async factoryFromPackagePath() { + protected async factoryFromPackagePath(): Promise { const packages = this.pkg; if (packages === undefined) { this.rejectDeferredRealize("packages is undefined"); @@ -589,7 +593,7 @@ export abstract class FluidDataStoreContext * @param clientId - ID of the client. Its old ID when in disconnected state and * its new client ID when we are connecting or connected. */ - public setConnectionState(connected: boolean, clientId?: string) { + public setConnectionState(connected: boolean, clientId?: string): void { // ConnectionState should not fail in tombstone mode as this is internally run this.verifyNotClosed("setConnectionState", false /* checkTombstone */); @@ -774,7 +778,7 @@ export abstract class FluidDataStoreContext * * @param usedRoutes - The routes that are used in this data store. */ - public updateUsedRoutes(usedRoutes: string[]) { + public updateUsedRoutes(usedRoutes: string[]): void { // Update the used routes in this data store's summarizer node. this.summarizerNode.updateUsedRoutes(usedRoutes); @@ -799,7 +803,11 @@ export abstract class FluidDataStoreContext * @param toPath - The absolute path of the outbound node that is referenced. * @param messageTimestampMs - The timestamp of the message that added the reference. */ - public addedGCOutboundRoute(fromPath: string, toPath: string, messageTimestampMs?: number) { + public addedGCOutboundRoute( + fromPath: string, + toPath: string, + messageTimestampMs?: number, + ): void { this.parentContext.addedGCOutboundRoute(fromPath, toPath, messageTimestampMs); } @@ -851,7 +859,7 @@ export abstract class FluidDataStoreContext * @param content - Content of the signal. Should be a JSON serializable object or primitive. * @param targetClientId - When specified, the signal is only sent to the provided client id. */ - public submitSignal(type: string, content: unknown, targetClientId?: string) { + public submitSignal(type: string, content: unknown, targetClientId?: string): void { this.verifyNotClosed("submitSignal"); assert(!!this.channel, 0x147 /* "Channel must exist on submitting signal" */); @@ -862,12 +870,12 @@ export abstract class FluidDataStoreContext * This is called by the data store channel when it becomes locally visible indicating that it is ready to become * globally visible now. */ - public makeLocallyVisible() { + public makeLocallyVisible(): void { assert(this.channel !== undefined, 0x2cf /* "undefined channel on datastore context" */); this.makeLocallyVisibleFn(); } - protected processPendingOps(channel: IFluidDataStoreChannel) { + protected processPendingOps(channel: IFluidDataStoreChannel): void { const baseSequenceNumber = this.baseSnapshotSequenceNumber ?? -1; assert( @@ -885,7 +893,7 @@ export abstract class FluidDataStoreContext this.pendingMessagesState = undefined; } - protected completeBindingRuntime(channel: IFluidDataStoreChannel) { + protected completeBindingRuntime(channel: IFluidDataStoreChannel): void { // And now mark the runtime active this.loaded = true; this.channel = channel; @@ -901,7 +909,10 @@ export abstract class FluidDataStoreContext Object.freeze(this.pkg); } - protected async bindRuntime(channel: IFluidDataStoreChannel, existing: boolean) { + protected async bindRuntime( + channel: IFluidDataStoreChannel, + existing: boolean, + ): Promise { if (this.channel) { throw new Error("Runtime already bound"); } @@ -970,12 +981,12 @@ export abstract class FluidDataStoreContext return {}; } - public reSubmit(type: string, contents: unknown, localOpMetadata: unknown) { + public reSubmit(type: string, contents: unknown, localOpMetadata: unknown): void { assert(!!this.channel, 0x14b /* "Channel must exist when resubmitting ops" */); this.channel.reSubmit(type, contents, localOpMetadata); } - public rollback(type: string, contents: unknown, localOpMetadata: unknown) { + public rollback(type: string, contents: unknown, localOpMetadata: unknown): void { if (!this.channel) { throw new Error("Channel must exist when rolling back ops"); } @@ -1046,7 +1057,7 @@ export abstract class FluidDataStoreContext * eventual consistency. For example, the next summary (say at ref seq# 100) may contain these changes whereas * other clients that are up-to-date till seq# 100 may not have them yet. */ - protected identifyLocalChangeInSummarizer(eventName: string, type?: string) { + protected identifyLocalChangeInSummarizer(eventName: string, type?: string): void { if ( this.clientDetails.type !== summarizerClientType || this.localChangesTelemetryCount <= 0 @@ -1073,7 +1084,7 @@ export abstract class FluidDataStoreContext return ( summarizeInternal: SummarizeInternalFn, getGCDataFn: (fullGC?: boolean) => Promise, - ) => + ): ISummarizerNodeWithGC => this.summarizerNode.createChild( summarizeInternal, id, @@ -1083,7 +1094,7 @@ export abstract class FluidDataStoreContext ); } - public deleteChildSummarizerNode(id: string) { + public deleteChildSummarizerNode(id: string): void { this.summarizerNode.deleteChild(id); } @@ -1121,17 +1132,21 @@ export class RemoteFluidDataStoreContext extends FluidDataStoreContext { } } - /* - This API should not be called for RemoteFluidDataStoreContext. But here is one scenario where it's not the case: - The scenario (hit by stashedOps.spec.ts, "resends attach op" UT is the following (as far as I understand): - 1. data store is being attached in attached container - 2. container state is serialized (stashed ops feature) - 3. new container instance is rehydrated (from stashed ops) - - As result, we create RemoteFluidDataStoreContext for this data store that is actually in "attaching" state (as of # 2). - But its state is set to attached when loading container from stashed ops - 4. attach op for this data store is processed - setAttachState() is called. - */ - public setAttachState(attachState: AttachState.Attaching | AttachState.Attached) {} + /** + * This API should not be called for RemoteFluidDataStoreContext. But here is one scenario where it's not the case: + * The scenario (hit by stashedOps.spec.ts, "resends attach op" UT is the following (as far as I understand): + * + * 1. data store is being attached in attached container + * + * 2. container state is serialized (stashed ops feature) + * + * 3. new container instance is rehydrated (from stashed ops) - + * As result, we create RemoteFluidDataStoreContext for this data store that is actually in "attaching" state * (as of # 2). + * But its state is set to attached when loading container from stashed ops. + * + * 4. attach op for this data store is processed - setAttachState() is called. + */ + public setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void {} private readonly initialSnapshotDetailsP = new LazyPromise(async () => { // Sequence number of the snapshot. @@ -1395,7 +1410,7 @@ export class LocalFluidDataStoreContextBase extends FluidDataStoreContext { * it was unreferenced. Thus the sweeping container should have loaded from a snapshot and thus creating a remote * context. */ - public delete() { + public delete(): void { // TODO: GC:Validation - potentially prevent this from happening or asserting. Maybe throw here. this.mc.logger.sendErrorEvent({ eventName: "GC_Deleted_DataStore_Unexpected_Delete", @@ -1482,7 +1497,7 @@ export class LocalDetachedFluidDataStoreContext * * If used incorrectly, this function can result in permanent data corruption. */ - public unsafe_AttachRuntimeSync(channel: IFluidDataStoreChannel) { + public unsafe_AttachRuntimeSync(channel: IFluidDataStoreChannel): IDataStore { this.channelP = Promise.resolve(channel); this.processPendingOps(channel); this.completeBindingRuntime(channel); diff --git a/packages/runtime/container-runtime/src/dataStoreContexts.ts b/packages/runtime/container-runtime/src/dataStoreContexts.ts index 81537188e559..526a8ec7bec1 100644 --- a/packages/runtime/container-runtime/src/dataStoreContexts.ts +++ b/packages/runtime/container-runtime/src/dataStoreContexts.ts @@ -67,20 +67,20 @@ export class DataStoreContexts return this._contexts.size; } - public get disposed() { + public get disposed(): boolean { return this.disposeOnce.evaluated; } - public readonly dispose = () => this.disposeOnce.value; + public readonly dispose = (): void => this.disposeOnce.value; - public notBoundLength() { + public notBoundLength(): number { return this.notBoundContexts.size; } - public isNotBound(id: string) { + public isNotBound(id: string): boolean { return this.notBoundContexts.has(id); } - public has(id: string) { + public has(id: string): boolean { return this._contexts.has(id); } @@ -102,7 +102,7 @@ export class DataStoreContexts private readonly _recentlyDeletedContexts: Map = new Map(); - public getRecentlyDeletedContext(id: string) { + public getRecentlyDeletedContext(id: string): FluidDataStoreContext | undefined { return this._recentlyDeletedContexts.get(id); } @@ -122,7 +122,7 @@ export class DataStoreContexts /** * Add the given context, marking it as to-be-bound */ - public addUnbound(context: LocalFluidDataStoreContext) { + public addUnbound(context: LocalFluidDataStoreContext): void { const id = context.id; assert(!this._contexts.has(id), 0x158 /* "Creating store with existing ID" */); @@ -165,7 +165,7 @@ export class DataStoreContexts /** * Update this context as bound */ - public bind(id: string) { + public bind(id: string): void { const removed: boolean = this.notBoundContexts.delete(id); assert(removed, 0x159 /* "The given id was not found in notBoundContexts to delete" */); @@ -194,7 +194,7 @@ export class DataStoreContexts * This could be because it's a local context that's been bound, or because it's a remote context. * @param context - The context to add */ - public addBoundOrRemoted(context: FluidDataStoreContext) { + public addBoundOrRemoted(context: FluidDataStoreContext): void { const id = context.id; assert(!this._contexts.has(id), 0x15d /* "Creating store with existing ID" */); diff --git a/packages/runtime/container-runtime/src/dataStoreRegistry.ts b/packages/runtime/container-runtime/src/dataStoreRegistry.ts index 51eba7f1239c..115c2a11aed0 100644 --- a/packages/runtime/container-runtime/src/dataStoreRegistry.ts +++ b/packages/runtime/container-runtime/src/dataStoreRegistry.ts @@ -20,7 +20,7 @@ export class FluidDataStoreRegistry implements IFluidDataStoreRegistry { FluidDataStoreRegistryEntry | Promise >; - public get IFluidDataStoreRegistry() { + public get IFluidDataStoreRegistry(): IFluidDataStoreRegistry { return this; } diff --git a/packages/runtime/container-runtime/src/deltaManagerProxies.ts b/packages/runtime/container-runtime/src/deltaManagerProxies.ts index 282b98b85e0b..6e3efceb80d1 100644 --- a/packages/runtime/container-runtime/src/deltaManagerProxies.ts +++ b/packages/runtime/container-runtime/src/deltaManagerProxies.ts @@ -59,11 +59,11 @@ export abstract class BaseDeltaManagerProxy return this.deltaManager.lastSequenceNumber; } - public get lastMessage() { + public get lastMessage(): ISequencedDocumentMessage | undefined { return this.deltaManager.lastMessage; } - public get lastKnownSeqNumber() { + public get lastKnownSeqNumber(): number { return this.deltaManager.lastKnownSeqNumber; } @@ -71,7 +71,7 @@ export abstract class BaseDeltaManagerProxy return this.deltaManager.initialSequenceNumber; } - public get hasCheckpointSequenceNumber() { + public get hasCheckpointSequenceNumber(): boolean { return this.deltaManager.hasCheckpointSequenceNumber; } @@ -218,7 +218,7 @@ export class DeltaManagerPendingOpsProxy extends BaseDeltaManagerProxy { return this.deltaManager.minimumSequenceNumber; } - public get lastMessage() { + public get lastMessage(): ISequencedDocumentMessage | undefined { if (this.deltaManager.lastMessage === undefined) { return this.deltaManager.lastMessage; } diff --git a/packages/runtime/container-runtime/src/deltaScheduler.ts b/packages/runtime/container-runtime/src/deltaScheduler.ts index d5aca9d6f326..e1adade7ac0f 100644 --- a/packages/runtime/container-runtime/src/deltaScheduler.ts +++ b/packages/runtime/container-runtime/src/deltaScheduler.ts @@ -59,7 +59,7 @@ export class DeltaScheduler { runtimeEventsEmitter.on("batchEnd", this.batchEnd); } - public dispose() { + public dispose(): void { this.deltaManager.inbound.off("idle", this.inboundQueueIdle); this.runtimeEventsEmitter.off("batchBegin", this.batchBegin); this.runtimeEventsEmitter.off("batchEnd", this.batchEnd); diff --git a/packages/runtime/container-runtime/src/gc/garbageCollection.ts b/packages/runtime/container-runtime/src/gc/garbageCollection.ts index 649f0981937e..0187a43a6c5b 100644 --- a/packages/runtime/container-runtime/src/gc/garbageCollection.ts +++ b/packages/runtime/container-runtime/src/gc/garbageCollection.ts @@ -926,7 +926,7 @@ export class GarbageCollector implements IGarbageCollector { messageContents: GarbageCollectionMessage[], messageTimestampMs: number, local: boolean, - ) { + ): void { for (const gcMessage of messageContents) { const gcMessageType = gcMessage.type; switch (gcMessageType) { @@ -1014,7 +1014,7 @@ export class GarbageCollector implements IGarbageCollector { request, headerData, additionalProps, - }: IGCNodeUpdatedProps) { + }: IGCNodeUpdatedProps): void { // If there is no reference timestamp to work with, no ops have been processed after creation. If so, skip // logging as nothing interesting would have happened worth logging. if (!this.shouldRunGC || timestampMs === undefined) { @@ -1116,7 +1116,7 @@ export class GarbageCollector implements IGarbageCollector { toNodePath: string, timestampMs: number, autorecovery?: true, - ) { + ): void { if (!this.shouldRunGC) { return; } diff --git a/packages/runtime/container-runtime/src/gc/gcHelpers.ts b/packages/runtime/container-runtime/src/gc/gcHelpers.ts index 92e6548efe0e..e5f393705ea0 100644 --- a/packages/runtime/container-runtime/src/gc/gcHelpers.ts +++ b/packages/runtime/container-runtime/src/gc/gcHelpers.ts @@ -162,7 +162,7 @@ export function cloneGCData(gcData: IGarbageCollectionData): IGarbageCollectionD export function concatGarbageCollectionData( gcData1: IGarbageCollectionData, gcData2: IGarbageCollectionData, -) { +): IGarbageCollectionData { const combinedGCData: IGarbageCollectionData = cloneGCData(gcData1); for (const [id, routes] of Object.entries(gcData2.gcNodes)) { if (combinedGCData.gcNodes[id] === undefined) { @@ -221,7 +221,9 @@ export async function getGCDataFromSnapshot( * @param gcDetails - The GC details of a node. * @returns A map of GC details of each children of the the given node. */ -export function unpackChildNodesGCDetails(gcDetails: IGarbageCollectionDetailsBase) { +export function unpackChildNodesGCDetails( + gcDetails: IGarbageCollectionDetailsBase, +): Map { const childGCDetailsMap: Map = new Map(); // If GC data is not available, bail out. diff --git a/packages/runtime/container-runtime/src/gc/gcSummaryStateTracker.ts b/packages/runtime/container-runtime/src/gc/gcSummaryStateTracker.ts index da6367ddf753..14521483fafc 100644 --- a/packages/runtime/container-runtime/src/gc/gcSummaryStateTracker.ts +++ b/packages/runtime/container-runtime/src/gc/gcSummaryStateTracker.ts @@ -61,7 +61,9 @@ export class GCSummaryStateTracker { /** * Called during GC initialization. Initialize the latest summary data from the base snapshot data. */ - public initializeBaseState(baseSnapshotData: IGarbageCollectionSnapshotData | undefined) { + public initializeBaseState( + baseSnapshotData: IGarbageCollectionSnapshotData | undefined, + ): void { if (baseSnapshotData === undefined) { return; } @@ -228,7 +230,7 @@ export class GCSummaryStateTracker { /** * Called to update the state from a GC run's stats. Used to update the count of data stores whose state updated. */ - public updateStateFromGCRunStats(stats: IGCStats) { + public updateStateFromGCRunStats(stats: IGCStats): void { this.updatedDSCountSinceLastSummary += stats.updatedDataStoreCount; } } diff --git a/packages/runtime/container-runtime/src/gc/gcTelemetry.ts b/packages/runtime/container-runtime/src/gc/gcTelemetry.ts index 764ece862e29..7c00856f60ef 100644 --- a/packages/runtime/container-runtime/src/gc/gcTelemetry.ts +++ b/packages/runtime/container-runtime/src/gc/gcTelemetry.ts @@ -184,7 +184,7 @@ export class GCTelemetryTracker { isTombstoned, ...otherNodeUsageProps }: INodeUsageProps, - ) { + ): void { // Note: For SubDataStore Load usage, trackedId will be the DataStore's id, not the full path in question. // This is necessary because the SubDataStore path may be unrecognized by GC (if suited for a custom request handler) const nodeStateTracker = this.getNodeStateTracker(trackedId); @@ -336,7 +336,7 @@ export class GCTelemetryTracker { previousGCData: IGarbageCollectionData, explicitReferences: Map, logger: ITelemetryLoggerExt, - ) { + ): void { for (const [nodeId, currentOutboundRoutes] of Object.entries(currentGCData.gcNodes)) { const previousRoutes = previousGCData.gcNodes[nodeId] ?? []; const explicitRoutes = explicitReferences.get(nodeId) ?? []; @@ -380,7 +380,7 @@ export class GCTelemetryTracker { * Log events that are pending in pendingEventsQueue. This is called after GC runs in the summarizer client * so that the state of an unreferenced node is updated. */ - public async logPendingEvents(logger: ITelemetryLoggerExt) { + public async logPendingEvents(logger: ITelemetryLoggerExt): Promise { // Events sent come only from the summarizer client. In between summaries, events are pushed to a queue and at // summary time they are then logged. // Events generated: diff --git a/packages/runtime/container-runtime/src/gc/gcUnreferencedStateTracker.ts b/packages/runtime/container-runtime/src/gc/gcUnreferencedStateTracker.ts index 8b3e712b8349..a131f4949536 100644 --- a/packages/runtime/container-runtime/src/gc/gcUnreferencedStateTracker.ts +++ b/packages/runtime/container-runtime/src/gc/gcUnreferencedStateTracker.ts @@ -126,8 +126,10 @@ export class UnreferencedStateTracker { this.updateTracking(currentReferenceTimestampMs); } - /* Updates the unreferenced state based on the provided timestamp. */ - public updateTracking(currentReferenceTimestampMs: number) { + /** + * Updates the unreferenced state based on the provided timestamp. + */ + public updateTracking(currentReferenceTimestampMs: number): void { const unreferencedDurationMs = currentReferenceTimestampMs - this.unreferencedTimestampMs; // Below we will set the appropriate timer (or none). Any running timers are superceded by the new currentReferenceTimestampMs @@ -180,7 +182,7 @@ export class UnreferencedStateTracker { /** * Stop tracking this node. Reset the unreferenced timers and state, if any. */ - public stopTracking() { + public stopTracking(): void { this.clearTimers(); this._state = UnreferencedState.Active; } diff --git a/packages/runtime/container-runtime/src/inboundBatchAggregator.ts b/packages/runtime/container-runtime/src/inboundBatchAggregator.ts index 5545dac3e80f..274847a7220d 100644 --- a/packages/runtime/container-runtime/src/inboundBatchAggregator.ts +++ b/packages/runtime/container-runtime/src/inboundBatchAggregator.ts @@ -54,7 +54,7 @@ export class InboundBatchAggregator { this.deltaManager.on("op", this.afterOpProcessing); } - public dispose() { + public dispose(): void { this.deltaManager.off("op", this.afterOpProcessing); this.deltaManager.inbound.off("push", this.trackPending); } diff --git a/packages/runtime/container-runtime/src/opLifecycle/batchManager.ts b/packages/runtime/container-runtime/src/opLifecycle/batchManager.ts index 9b6770c22ee9..3471f8d827aa 100644 --- a/packages/runtime/container-runtime/src/opLifecycle/batchManager.ts +++ b/packages/runtime/container-runtime/src/opLifecycle/batchManager.ts @@ -82,10 +82,10 @@ export class BatchManager { private batchContentSize = 0; private hasReentrantOps = false; - public get length() { + public get length(): number { return this.pendingBatch.length; } - public get contentSizeInBytes() { + public get contentSizeInBytes(): number { return this.batchContentSize; } @@ -139,7 +139,7 @@ export class BatchManager { return true; } - public get empty() { + public get empty(): boolean { return this.pendingBatch.length === 0; } diff --git a/packages/runtime/container-runtime/src/opLifecycle/opDecompressor.ts b/packages/runtime/container-runtime/src/opLifecycle/opDecompressor.ts index 2129e0a57bdf..178dd6800253 100644 --- a/packages/runtime/container-runtime/src/opLifecycle/opDecompressor.ts +++ b/packages/runtime/container-runtime/src/opLifecycle/opDecompressor.ts @@ -86,7 +86,7 @@ export class OpDecompressor { return false; } - public get currentlyUnrolling() { + public get currentlyUnrolling(): boolean { return this.activeBatch; } diff --git a/packages/runtime/container-runtime/src/opLifecycle/opSplitter.ts b/packages/runtime/container-runtime/src/opLifecycle/opSplitter.ts index 1d76aeb24f2b..52eaffac0841 100644 --- a/packages/runtime/container-runtime/src/opLifecycle/opSplitter.ts +++ b/packages/runtime/container-runtime/src/opLifecycle/opSplitter.ts @@ -63,7 +63,7 @@ export class OpSplitter { return this.chunkMap; } - public clearPartialChunks(clientId: string) { + public clearPartialChunks(clientId: string): void { if (this.chunkMap.has(clientId)) { this.chunkMap.delete(clientId); } diff --git a/packages/runtime/container-runtime/src/opLifecycle/outbox.ts b/packages/runtime/container-runtime/src/opLifecycle/outbox.ts index 09752c93056c..b0ce9cea5d54 100644 --- a/packages/runtime/container-runtime/src/opLifecycle/outbox.ts +++ b/packages/runtime/container-runtime/src/opLifecycle/outbox.ts @@ -219,13 +219,13 @@ export class Outbox { } } - public submit(message: BatchMessage) { + public submit(message: BatchMessage): void { this.maybeFlushPartialBatch(); this.addMessageToBatchManager(this.mainBatch, message); } - public submitBlobAttach(message: BatchMessage) { + public submitBlobAttach(message: BatchMessage): void { this.maybeFlushPartialBatch(); this.addMessageToBatchManager(this.blobAttachBatch, message); @@ -243,7 +243,7 @@ export class Outbox { } } - public submitIdAllocation(message: BatchMessage) { + public submitIdAllocation(message: BatchMessage): void { this.maybeFlushPartialBatch(); this.addMessageToBatchManager(this.idAllocationBatch, message); @@ -272,7 +272,7 @@ export class Outbox { * @param resubmittingBatchId - If defined, indicates this is a resubmission of a batch * with the given Batch ID, which must be preserved */ - public flush(resubmittingBatchId?: BatchId) { + public flush(resubmittingBatchId?: BatchId): void { if (this.isContextReentrant()) { const error = new UsageError("Flushing is not supported inside DDS event handlers"); this.params.closeContainer(error); @@ -512,7 +512,11 @@ export class Outbox { /** * Gets a checkpoint object per batch that facilitates iterating over the batch messages when rolling back. */ - public getBatchCheckpoints() { + public getBatchCheckpoints(): { + mainBatch: IBatchCheckpoint; + idAllocationBatch: IBatchCheckpoint; + blobAttachBatch: IBatchCheckpoint; + } { // This variable is declared with a specific type so that we have a standard import of the IBatchCheckpoint type. // When the type is inferred, the generated .d.ts uses a dynamic import which doesn't resolve. const mainBatch: IBatchCheckpoint = this.mainBatch.checkpoint(); diff --git a/packages/runtime/container-runtime/src/opLifecycle/remoteMessageProcessor.ts b/packages/runtime/container-runtime/src/opLifecycle/remoteMessageProcessor.ts index bc95ad92e722..051f301c1673 100644 --- a/packages/runtime/container-runtime/src/opLifecycle/remoteMessageProcessor.ts +++ b/packages/runtime/container-runtime/src/opLifecycle/remoteMessageProcessor.ts @@ -107,7 +107,7 @@ export class RemoteMessageProcessor { return this.opSplitter.chunks; } - public clearPartialMessagesFor(clientId: string) { + public clearPartialMessagesFor(clientId: string): void { this.opSplitter.clearPartialChunks(clientId); } diff --git a/packages/runtime/container-runtime/src/pendingStateManager.ts b/packages/runtime/container-runtime/src/pendingStateManager.ts index 802439e16b1e..8952bb44027c 100644 --- a/packages/runtime/container-runtime/src/pendingStateManager.ts +++ b/packages/runtime/container-runtime/src/pendingStateManager.ts @@ -270,10 +270,10 @@ export class PendingStateManager implements IDisposable { } } - public get disposed() { + public get disposed(): boolean { return this.disposeOnce.evaluated; } - public readonly dispose = () => this.disposeOnce.value; + public readonly dispose = (): void => this.disposeOnce.value; /** * The given batch has been flushed, and needs to be tracked locally until the corresponding @@ -287,7 +287,7 @@ export class PendingStateManager implements IDisposable { batch: BatchMessage[], clientSequenceNumber: number | undefined, ignoreBatchId?: boolean, - ) { + ): void { // clientId and batchStartCsn are used for generating the batchId so we can detect container forks // where this batch was submitted by two different clients rehydrating from the same local state. // In the typical case where the batch was actually sent, use the clientId and clientSequenceNumber. @@ -326,7 +326,7 @@ export class PendingStateManager implements IDisposable { * Applies stashed ops at their reference sequence number so they are ready to be ACKed or resubmitted * @param seqNum - Sequence number at which to apply ops. Will apply all ops if seqNum is undefined. */ - public async applyStashedOpsAt(seqNum?: number) { + public async applyStashedOpsAt(seqNum?: number): Promise { // apply stashed ops at sequence number while (!this.initialMessages.isEmpty()) { if (seqNum !== undefined) { @@ -610,7 +610,7 @@ export class PendingStateManager implements IDisposable { * states in its queue. This includes triggering resubmission of unacked ops. * ! Note: successfully resubmitting an op that has been successfully sequenced is not possible due to checks in the ConnectionStateHandler (Loader layer) */ - public replayPendingStates() { + public replayPendingStates(): void { assert( this.stateHandler.connected(), 0x172 /* "The connection state is not consistent with the runtime" */, diff --git a/packages/runtime/container-runtime/src/summary/documentSchema.ts b/packages/runtime/container-runtime/src/summary/documentSchema.ts index 6b054a03fb65..7afdefc620c4 100644 --- a/packages/runtime/container-runtime/src/summary/documentSchema.ts +++ b/packages/runtime/container-runtime/src/summary/documentSchema.ts @@ -614,7 +614,7 @@ export class DocumentsSchemaController { content: IDocumentSchemaChangeMessage, local: boolean, sequenceNumber: number, - ) { + ): boolean { return this.processDocumentSchemaMessages([content], local, sequenceNumber); } @@ -630,7 +630,7 @@ export class DocumentsSchemaController { contents: IDocumentSchemaChangeMessage[], local: boolean, sequenceNumber: number, - ) { + ): boolean { for (const content of contents) { this.validateSeqNumber(content.refSeq, this.documentSchema.refSeq, "content.refSeq"); this.validateSeqNumber(this.documentSchema.refSeq, sequenceNumber, "refSeq"); @@ -678,7 +678,7 @@ export class DocumentsSchemaController { return true; } - public onDisconnect() { + public onDisconnect(): void { this.sendOp = true; } } diff --git a/packages/runtime/container-runtime/src/summary/orderedClientElection.ts b/packages/runtime/container-runtime/src/summary/orderedClientElection.ts index db82a3d5b53d..855cce0a81c3 100644 --- a/packages/runtime/container-runtime/src/summary/orderedClientElection.ts +++ b/packages/runtime/container-runtime/src/summary/orderedClientElection.ts @@ -129,10 +129,10 @@ export class OrderedClientCollection private _youngestClient: LinkNode = this.rootNode; private readonly logger: ITelemetryLoggerExt; - public get count() { + public get count(): number { return this.clientMap.size; } - public get oldestClient() { + public get oldestClient(): ILinkedClient | undefined { return this.rootNode.youngerClient; } @@ -355,10 +355,10 @@ export class OrderedClientElection private _electedParent: ILinkedClient | undefined; private _electionSequenceNumber: number; - public get eligibleCount() { + public get eligibleCount(): number { return this._eligibleCount; } - public get electionSequenceNumber() { + public get electionSequenceNumber(): number { return this._electionSequenceNumber; } @@ -398,10 +398,10 @@ export class OrderedClientElection * * vii. SummaryManager running on B spawns a summarizer client, B'. electedParent === B, electedClient === B' */ - public get electedClient() { + public get electedClient(): ILinkedClient | undefined { return this._electedClient; } - public get electedParent() { + public get electedParent(): ILinkedClient | undefined { return this._electedParent; } diff --git a/packages/runtime/container-runtime/src/summary/runWhileConnectedCoordinator.ts b/packages/runtime/container-runtime/src/summary/runWhileConnectedCoordinator.ts index f6bc0082d231..76bca94a0eea 100644 --- a/packages/runtime/container-runtime/src/summary/runWhileConnectedCoordinator.ts +++ b/packages/runtime/container-runtime/src/summary/runWhileConnectedCoordinator.ts @@ -36,7 +36,7 @@ export class RunWhileConnectedCoordinator implements ICancellableSummarizerContr private _cancelled = false; private readonly stopDeferred = new Deferred(); - public get cancelled() { + public get cancelled(): boolean { if (!this._cancelled) { assert(this.active(), 0x25d /* "We should never connect as 'read'" */); @@ -63,7 +63,10 @@ export class RunWhileConnectedCoordinator implements ICancellableSummarizerContr return this.stopDeferred.promise; } - public static async create(runtime: IConnectableRuntime, active: () => boolean) { + public static async create( + runtime: IConnectableRuntime, + active: () => boolean, + ): Promise { const obj = new RunWhileConnectedCoordinator(runtime, active); await obj.waitStart(); return obj; @@ -87,7 +90,7 @@ export class RunWhileConnectedCoordinator implements ICancellableSummarizerContr * of non-summarized ops, where can make determination to continue with summary even if main * client is disconnected. */ - protected async waitStart() { + protected async waitStart(): Promise { if (this.runtime.disposed) { this.stop("summarizerClientDisconnected"); return; diff --git a/packages/runtime/container-runtime/src/summary/runningSummarizer.ts b/packages/runtime/container-runtime/src/summary/runningSummarizer.ts index 739978ea8aab..0776fc17bce3 100644 --- a/packages/runtime/container-runtime/src/summary/runningSummarizer.ts +++ b/packages/runtime/container-runtime/src/summary/runningSummarizer.ts @@ -23,6 +23,7 @@ import { createChildLogger, createChildMonitoringContext, isFluidError, + type ITelemetryLoggerExt, } from "@fluidframework/telemetry-utils/internal"; import { ISummaryConfiguration } from "../containerRuntime.js"; @@ -163,7 +164,7 @@ export class RunningSummarizer return summarizer; } - public get disposed() { + public get disposed(): boolean { return this._disposed; } private stopping = false; @@ -419,7 +420,9 @@ export class RunningSummarizer * but only if they're logging about that same summary. * @param summaryOpRefSeq - RefSeq number of the summary op, to ensure the log correlation will be correct */ - public tryGetCorrelatedLogger = (summaryOpRefSeq) => + public tryGetCorrelatedLogger = ( + summaryOpRefSeq: number, + ): ITelemetryLoggerExt | undefined => this.heuristicData.lastAttempt.refSequenceNumber === summaryOpRefSeq ? this.mc.logger : undefined; @@ -429,7 +432,7 @@ export class RunningSummarizer */ private heuristicRunnerMicroTaskExists = false; - public handleOp(op: ISequencedDocumentMessage, runtimeMessage: boolean) { + public handleOp(op: ISequencedDocumentMessage, runtimeMessage: boolean): void { this.heuristicData.lastOpSequenceNumber = op.sequenceNumber; if (runtimeMessage) { diff --git a/packages/runtime/container-runtime/src/summary/summarizer.ts b/packages/runtime/container-runtime/src/summary/summarizer.ts index 8bd598afa3f8..448c3fde0df8 100644 --- a/packages/runtime/container-runtime/src/summary/summarizer.ts +++ b/packages/runtime/container-runtime/src/summary/summarizer.ts @@ -55,14 +55,20 @@ export class SummarizingWarning super(errorMessage); } - static wrap(error: unknown, logged: boolean = false, logger: ITelemetryLoggerExt) { + static wrap( + error: unknown, + logged: boolean = false, + logger: ITelemetryLoggerExt, + ): SummarizingWarning { const newErrorFn = (errMsg: string) => new SummarizingWarning(errMsg, logged); return wrapErrorAndLog(error, newErrorFn, logger); } } -export const createSummarizingWarning = (errorMessage: string, logged: boolean) => - new SummarizingWarning(errorMessage, logged); +export const createSummarizingWarning = ( + errorMessage: string, + logged: boolean, +): SummarizingWarning => new SummarizingWarning(errorMessage, logged); /** * Summarizer is responsible for coordinating when to generate and send summaries. @@ -72,7 +78,7 @@ export const createSummarizingWarning = (errorMessage: string, logged: boolean) * @alpha */ export class Summarizer extends TypedEventEmitter implements ISummarizer { - public get ISummarizer() { + public get ISummarizer(): this { return this; } @@ -136,11 +142,11 @@ export class Summarizer extends TypedEventEmitter implements * the run promise, and also close the container. * @param reason - reason code for stopping */ - public stop(reason: SummarizerStopReason) { + public stop(reason: SummarizerStopReason): void { this.stopDeferred.resolve(reason); } - public close() { + public close(): void { // This will result in "summarizerClientDisconnected" stop reason recorded in telemetry, // unless stop() was called earlier this.dispose(); @@ -293,7 +299,7 @@ export class Summarizer extends TypedEventEmitter implements * properties. * Called by ContainerRuntime when it is disposed, as well as at the end the run(). */ - public dispose() { + public dispose(): void { // Given that the call can come from own ContainerRuntime, ensure that we stop all the processes. this.stop("summarizerClientDisconnected"); @@ -376,7 +382,7 @@ export class Summarizer extends TypedEventEmitter implements return this.runningSummarizer.enqueueSummarize(options); } - public recordSummaryAttempt?(summaryRefSeqNum?: number) { + public recordSummaryAttempt?(summaryRefSeqNum?: number): void { this._heuristicData?.recordAttempt(summaryRefSeqNum); } diff --git a/packages/runtime/container-runtime/src/summary/summarizerClientElection.ts b/packages/runtime/container-runtime/src/summary/summarizerClientElection.ts index 10ede7fd1176..a7f1dc013900 100644 --- a/packages/runtime/container-runtime/src/summary/summarizerClientElection.ts +++ b/packages/runtime/container-runtime/src/summary/summarizerClientElection.ts @@ -51,10 +51,10 @@ export class SummarizerClientElection */ private lastReportedSeq = 0; - public get electedClientId() { + public get electedClientId(): string | undefined { return this.clientElection.electedClient?.clientId; } - public get electedParentId() { + public get electedParentId(): string | undefined { return this.clientElection.electedParent?.clientId; } diff --git a/packages/runtime/container-runtime/src/summary/summarizerHeuristics.ts b/packages/runtime/container-runtime/src/summary/summarizerHeuristics.ts index a4f4c49c5646..f0bc78dd7192 100644 --- a/packages/runtime/container-runtime/src/summary/summarizerHeuristics.ts +++ b/packages/runtime/container-runtime/src/summary/summarizerHeuristics.ts @@ -68,12 +68,12 @@ export class SummarizeHeuristicData implements ISummarizeHeuristicData { this._lastSuccessfulSummary = { ...attemptBaseline }; } - public updateWithLastSummaryAckInfo(lastSummary: Readonly) { + public updateWithLastSummaryAckInfo(lastSummary: Readonly): void { this._lastAttempt = lastSummary; this._lastSuccessfulSummary = { ...lastSummary }; } - public recordAttempt(refSequenceNumber?: number) { + public recordAttempt(refSequenceNumber?: number): void { this._lastAttempt = { refSequenceNumber: refSequenceNumber ?? this.lastOpSequenceNumber, summaryTime: Date.now(), @@ -84,7 +84,7 @@ export class SummarizeHeuristicData implements ISummarizeHeuristicData { this.totalOpsSizeBefore = this.totalOpsSize; } - public markLastAttemptAsSuccessful() { + public markLastAttemptAsSuccessful(): void { this._lastSuccessfulSummary = { ...this.lastAttempt }; this.numNonRuntimeOps -= this.numNonRuntimeOpsBefore; @@ -151,11 +151,11 @@ export class SummarizeHeuristicRunner implements ISummarizeHeuristicRunner { ); } - public start() { + public start(): void { this.idleTimer?.start(this.idleTime); } - public run() { + public run(): void { for (const strategy of this.summarizeStrategies) { if (strategy.shouldRunSummary(this.configuration, this.heuristicData)) { return this.runSummarize(strategy.summarizeReason); @@ -183,7 +183,7 @@ export class SummarizeHeuristicRunner implements ISummarizeHeuristicRunner { return weightedOpsSinceLastAck >= minOpsForLastSummaryAttempt; } - public dispose() { + public dispose(): void { this.idleTimer?.clear(); } } diff --git a/packages/runtime/container-runtime/src/summary/summarizerNode/summarizerNode.ts b/packages/runtime/container-runtime/src/summary/summarizerNode/summarizerNode.ts index 8ba651ecca10..b1898444f3b7 100644 --- a/packages/runtime/container-runtime/src/summary/summarizerNode/summarizerNode.ts +++ b/packages/runtime/container-runtime/src/summary/summarizerNode/summarizerNode.ts @@ -61,7 +61,7 @@ export class SummarizerNode implements IRootSummarizerNode { * The reference sequence number of the most recent acked summary. * Returns 0 if there is not yet an acked summary. */ - public get referenceSequenceNumber() { + public get referenceSequenceNumber(): number { return this._lastSummaryReferenceSequenceNumber ?? 0; } @@ -323,7 +323,7 @@ export class SummarizerNode implements IRootSummarizerNode { * queue. We track this until we get an ack from the server for this summary. * @param proposalHandle - The handle of the summary that was uploaded to the server. */ - public completeSummary(proposalHandle: string) { + public completeSummary(proposalHandle: string): void { this.completeSummaryCore(proposalHandle, false /* parentSkipRecursion */); } @@ -335,7 +335,7 @@ export class SummarizerNode implements IRootSummarizerNode { * In that case, the children will not have work-in-progress state. * @param validate - true to validate that the in-progress summary is correct for all nodes. */ - protected completeSummaryCore(proposalHandle: string, parentSkipRecursion: boolean) { + protected completeSummaryCore(proposalHandle: string, parentSkipRecursion: boolean): void { assert( this.wipReferenceSequenceNumber !== undefined, 0x1a4 /* "Not tracking a summary" */, @@ -368,7 +368,7 @@ export class SummarizerNode implements IRootSummarizerNode { this.clearSummary(); } - public clearSummary() { + public clearSummary(): void { this.wipReferenceSequenceNumber = undefined; this.wipSummarizeCalled = false; this.wipSkipRecursion = false; @@ -482,7 +482,7 @@ export class SummarizerNode implements IRootSummarizerNode { } } - public updateBaseSummaryState(snapshot: ISnapshotTree) { + public updateBaseSummaryState(snapshot: ISnapshotTree): void { // Function deprecated. Empty declaration is kept around to compat failures. } @@ -609,7 +609,7 @@ export class SummarizerNode implements IRootSummarizerNode { * @param id - Initial id or path part of this node * */ - protected maybeUpdateChildState(child: SummarizerNode, id: string) { + protected maybeUpdateChildState(child: SummarizerNode, id: string): void { // If a summary is in progress, this child was created after the summary started. So, we need to update the // child's summary state as well. if (this.isSummaryInProgress()) { @@ -623,7 +623,7 @@ export class SummarizerNode implements IRootSummarizerNode { } } - protected addPendingSummary(key: string, pendingSummaryInfo: PendingSummaryInfo) { + protected addPendingSummary(key: string, pendingSummaryInfo: PendingSummaryInfo): void { this.pendingSummaries.set(key, pendingSummaryInfo); } diff --git a/packages/runtime/container-runtime/src/summary/summarizerNode/summarizerNodeWithGc.ts b/packages/runtime/container-runtime/src/summary/summarizerNode/summarizerNodeWithGc.ts index 05c2e4fa3db7..e002417dab67 100644 --- a/packages/runtime/container-runtime/src/summary/summarizerNode/summarizerNodeWithGc.ts +++ b/packages/runtime/container-runtime/src/summary/summarizerNode/summarizerNodeWithGc.ts @@ -267,7 +267,7 @@ export class SummarizerNodeWithGC extends SummarizerNode implements IRootSummari * @param parentSkipRecursion - true if the parent of this node skipped recursing the child nodes when summarizing. * In that case, the children will not have work-in-progress state. */ - protected completeSummaryCore(proposalHandle: string, parentSkipRecursion: boolean) { + protected completeSummaryCore(proposalHandle: string, parentSkipRecursion: boolean): void { let wipSerializedUsedRoutes: string | undefined; // If GC is disabled, don't set wip used routes. if (!this.gcDisabled) { @@ -292,7 +292,7 @@ export class SummarizerNodeWithGC extends SummarizerNode implements IRootSummari /** * Clears the work-in-progress state. */ - public clearSummary() { + public clearSummary(): void { this.wipSerializedUsedRoutes = undefined; this.wipChildNodesUsedRoutes = undefined; super.clearSummary(); @@ -405,7 +405,7 @@ export class SummarizerNodeWithGC extends SummarizerNode implements IRootSummari * @param child - The child node whose state is to be updated. * @param id - Initial id or path part of this node */ - protected maybeUpdateChildState(child: SummarizerNodeWithGC, id: string) { + protected maybeUpdateChildState(child: SummarizerNodeWithGC, id: string): void { super.maybeUpdateChildState(child, id); // If GC has run on this node and summarization isn't complete, this.wipSerializedUsedRoutes will be defined. @@ -457,7 +457,7 @@ export class SummarizerNodeWithGC extends SummarizerNode implements IRootSummari return this.usedRoutes.includes("") || this.usedRoutes.includes("/"); } - public updateUsedRoutes(usedRoutes: string[]) { + public updateUsedRoutes(usedRoutes: string[]): void { // Sort the given routes before updating. This will ensure that the routes compared in hasUsedStateChanged() // are in the same order. this.usedRoutes = usedRoutes.sort(); diff --git a/packages/runtime/container-runtime/src/summary/summaryCollection.ts b/packages/runtime/container-runtime/src/summary/summaryCollection.ts index 4493a14cfc8f..1f238488f8dd 100644 --- a/packages/runtime/container-runtime/src/summary/summaryCollection.ts +++ b/packages/runtime/container-runtime/src/summary/summaryCollection.ts @@ -270,18 +270,18 @@ export class SummaryCollection extends TypedEventEmitter void) { + public addOpListener(listener: () => void): void { this.deltaManager.on("op", listener); } - public removeOpListener(listener: () => void) { + public removeOpListener(listener: () => void): void { this.deltaManager.off("op", listener); } @@ -304,19 +304,19 @@ export class SummaryCollection extends TypedEventEmitter void, - ) { + ): void { this.maxAckWaitTime = maxAckWaitTime; this.pendingAckTimerTimeoutCallback = timeoutCallback; } - public unsetPendingAckTimerTimeoutCallback() { + public unsetPendingAckTimerTimeoutCallback(): void { this.maxAckWaitTime = undefined; this.pendingAckTimerTimeoutCallback = undefined; } diff --git a/packages/runtime/container-runtime/src/summary/summaryGenerator.ts b/packages/runtime/container-runtime/src/summary/summaryGenerator.ts index 20f0ef5f7342..944936607aa6 100644 --- a/packages/runtime/container-runtime/src/summary/summaryGenerator.ts +++ b/packages/runtime/container-runtime/src/summary/summaryGenerator.ts @@ -136,7 +136,7 @@ const summarizeErrors = { export type SummarizeErrorCode = keyof typeof summarizeErrors; // Helper functions to report failures and return. -export const getFailMessage = (errorCode: SummarizeErrorCode) => +export const getFailMessage = (errorCode: SummarizeErrorCode): string => `${errorCode}: ${summarizeErrors[errorCode]}`; export class SummarizeResultBuilder { @@ -161,7 +161,7 @@ export class SummarizeResultBuilder { error: IRetriableFailureError, submitFailureResult?: SubmitSummaryFailureData, nackSummaryResult?: INackSummaryResult, - ) { + ): void { assert( !this.receivedSummaryAckOrNack.isCompleted, 0x25e /* "no reason to call fail if all promises have been completed" */, @@ -576,7 +576,7 @@ export class SummaryGenerator { } } - public dispose() { + public dispose(): void { this.summarizeTimer.clear(); } } diff --git a/packages/runtime/container-runtime/src/summary/summaryManager.ts b/packages/runtime/container-runtime/src/summary/summaryManager.ts index 46e215ea2764..e76fccebda51 100644 --- a/packages/runtime/container-runtime/src/summary/summaryManager.ts +++ b/packages/runtime/container-runtime/src/summary/summaryManager.ts @@ -102,11 +102,11 @@ export class SummaryManager private summarizer?: ISummarizer; private _disposed = false; - public get disposed() { + public get disposed(): boolean { return this._disposed; } - public get currentState() { + public get currentState(): SummaryManagerState { return this.state; } @@ -444,7 +444,7 @@ export class SummaryManager return this.summarizer.enqueueSummarize(options); } - public dispose() { + public dispose(): void { this.clientElection.off("electedSummarizerChanged", this.refreshSummarizer); this.connectedState.off("connected", this.handleConnected); this.connectedState.off("disconnected", this.handleDisconnected); diff --git a/packages/runtime/container-runtime/src/test/blobManager.spec.ts b/packages/runtime/container-runtime/src/test/blobManager.spec.ts index ae2317ba3e00..3ec1a12b2c44 100644 --- a/packages/runtime/container-runtime/src/test/blobManager.spec.ts +++ b/packages/runtime/container-runtime/src/test/blobManager.spec.ts @@ -110,7 +110,7 @@ export class MockRuntime public disposed: boolean = false; - public get storage() { + public get storage(): IDocumentStorageService { return (this.attachState === AttachState.Detached ? this.detachedStorage : this.attachedStorage) as unknown as IDocumentStorageService; @@ -119,7 +119,7 @@ export class MockRuntime private processing = false; public unprocessedBlobs = new Set(); - public getStorage() { + public getStorage(): IDocumentStorageService { return { createBlob: async (blob) => { if (this.processing) { @@ -143,7 +143,7 @@ export class MockRuntime } as unknown as IDocumentStorageService; } - public sendBlobAttachOp(localId: string, blobId?: string) { + public sendBlobAttachOp(localId: string, blobId?: string): void { this.ops.push({ metadata: { localId, blobId } }); } @@ -156,13 +156,15 @@ export class MockRuntime return P; } - public async getBlob(blobHandle: IFluidHandleInternal) { + public async getBlob( + blobHandle: IFluidHandleInternal, + ): Promise { const pathParts = blobHandle.absolutePath.split("/"); const blobId = pathParts[2]; return this.blobManager.getBlob(blobId); } - public async getPendingLocalState() { + public async getPendingLocalState(): Promise<(unknown[] | IPendingBlobs | undefined)[]> { const pendingBlobs = await this.blobManager.attachAndGetPendingBlobs(); return [[...this.ops], pendingBlobs]; } @@ -181,7 +183,7 @@ export class MockRuntime private handlePs: Promise[] = []; private readonly deletedBlobs: string[] = []; - public processOps() { + public processOps(): void { assert(this.connected || this.ops.length === 0); this.ops.forEach((op) => this.blobManager.processBlobAttachMessage(op as ISequencedMessageEnvelope, true), @@ -193,7 +195,7 @@ export class MockRuntime resolve: boolean, canRetry: boolean = false, retryAfterSeconds?: number, - ) { + ): Promise { const blobPs = this.blobPs; this.blobPs = []; if (resolve) { @@ -207,14 +209,14 @@ export class MockRuntime await Promise.allSettled(blobPs).catch(() => {}); } - public async processHandles() { + public async processHandles(): Promise { const handlePs = this.handlePs; this.handlePs = []; const handles = (await Promise.all(handlePs)) as IFluidHandleInternal[]; handles.forEach((handle) => handle.attachGraph()); } - public async processAll() { + public async processAll(): Promise { while (this.blobPs.length + this.handlePs.length + this.ops.length > 0) { const p1 = this.processBlobs(true); const p2 = this.processHandles(); @@ -225,7 +227,10 @@ export class MockRuntime } } - public async attach() { + public async attach(): Promise<{ + ids: string[]; + redirectTable: [string, string][] | undefined; + }> { if (this.detachedStorage.blobs.size > 0) { const table = new Map(); for (const [detachedId, blob] of this.detachedStorage.blobs) { @@ -241,7 +246,7 @@ export class MockRuntime return summary; } - public async connect(delay = 0, processStashedWithRetry?: boolean) { + public async connect(delay = 0, processStashedWithRetry?: boolean): Promise { assert(!this.connected); await new Promise((resolve) => setTimeout(resolve, delay)); this.connected = true; @@ -254,7 +259,7 @@ export class MockRuntime ops.forEach((op) => this.blobManager.reSubmit((op as any).metadata)); } - public async processStashed(processStashedWithRetry?: boolean) { + public async processStashed(processStashedWithRetry?: boolean): Promise { const uploadP = this.blobManager.stashedBlobsUploadP; this.processing = true; if (processStashedWithRetry) { @@ -270,20 +275,22 @@ export class MockRuntime this.processing = false; } - public disconnect() { + public disconnect(): void { assert(this.connected); this.connected = false; this.emit("disconnected"); } - public async remoteUpload(blob: ArrayBufferLike) { + public async remoteUpload( + blob: ArrayBufferLike, + ): Promise<{ metadata: { localId: string; blobId: string } }> { const response = await this.storage.createBlob(blob); const op = { metadata: { localId: uuid(), blobId: response.id } }; this.blobManager.processBlobAttachMessage(op as ISequencedMessageEnvelope, false); return op; } - public deleteBlob(blobHandle: IFluidHandleInternal) { + public deleteBlob(blobHandle: IFluidHandleInternal): void { this.deletedBlobs.push(blobHandle.absolutePath); } @@ -292,7 +299,12 @@ export class MockRuntime } } -export const validateSummary = (runtime: MockRuntime) => { +export const validateSummary = ( + runtime: MockRuntime, +): { + ids: string[]; + redirectTable: [string, string][] | undefined; +} => { const summary = runtime.blobManager.summarize(); const ids: string[] = []; let redirectTable: [string, string][] | undefined; diff --git a/packages/runtime/container-runtime/src/test/blobManager.stashed.spec.ts b/packages/runtime/container-runtime/src/test/blobManager.stashed.spec.ts index 7a048119ff4c..5f17aec13278 100644 --- a/packages/runtime/container-runtime/src/test/blobManager.stashed.spec.ts +++ b/packages/runtime/container-runtime/src/test/blobManager.stashed.spec.ts @@ -19,7 +19,7 @@ import { IContainerHandleContextRuntime, } from "../containerHandleContext.js"; -export const failProxy = (handler: Partial = {}) => { +export const failProxy = (handler: Partial = {}): T => { const proxy: T = new Proxy(handler as T, { get: (t, p, r) => { if (p === "then") { diff --git a/packages/runtime/container-runtime/src/test/fuzz/summarizerFuzzMocks.ts b/packages/runtime/container-runtime/src/test/fuzz/summarizerFuzzMocks.ts index 144a6a2c99c0..d7079199cd4b 100644 --- a/packages/runtime/container-runtime/src/test/fuzz/summarizerFuzzMocks.ts +++ b/packages/runtime/container-runtime/src/test/fuzz/summarizerFuzzMocks.ts @@ -134,19 +134,19 @@ export class MockContainerRuntimeForSummarizer /** * Prepare a SummaryNack to be sent by the server */ - public prepareSummaryNack() { + public prepareSummaryNack(): void { this.nackScheduled = true; } /** * Call on the Summarizer object to summarize */ - public async summarize() { + public async summarize(): Promise { const result = this.summarizer.summarizeOnDemand({ reason: "fuzzTest", retryOnFailure: false, }); - return Promise.all([ + await Promise.all([ result.summarySubmitted, result.summaryOpBroadcasted, result.receivedSummaryAckOrNack, @@ -240,19 +240,19 @@ export class MockContainerRuntimeForSummarizer // Do nothing } - public setConnectedState(value: boolean) { + public setConnectedState(value: boolean): void { super.setConnectedState(value); this.connectedState.setConnectedState(value, this.clientId); this.summarizerClientElection.setClientId(this.clientId); } - public closeFn() { + public closeFn(): void { this.disposeFn(); } public disposed: boolean = false; - public disposeFn() { + public disposeFn(): void { this.connected = false; this.disposed = true; this.summaryManager.dispose(); diff --git a/packages/runtime/container-runtime/src/test/gc/gcUnitTestHelpers.ts b/packages/runtime/container-runtime/src/test/gc/gcUnitTestHelpers.ts index 7b239de804c0..96b846fb28ab 100644 --- a/packages/runtime/container-runtime/src/test/gc/gcUnitTestHelpers.ts +++ b/packages/runtime/container-runtime/src/test/gc/gcUnitTestHelpers.ts @@ -10,7 +10,11 @@ import { ReadAndParseBlob } from "@fluidframework/runtime-utils/internal"; * Creates a test config provider with the ability to set configs values and clear all config values. * @internal */ -export const createTestConfigProvider = () => { +export const createTestConfigProvider = (): { + getRawConfig: (name: string) => ConfigTypes; + set: (key: string, value: ConfigTypes) => void; + clear: () => void; +} => { const settings: Record = {}; return { getRawConfig: (name: string): ConfigTypes => settings[name], diff --git a/packages/runtime/container-runtime/src/test/summary/testQuorumClients.ts b/packages/runtime/container-runtime/src/test/summary/testQuorumClients.ts index 9952c51c238d..5cd135210e29 100644 --- a/packages/runtime/container-runtime/src/test/summary/testQuorumClients.ts +++ b/packages/runtime/container-runtime/src/test/summary/testQuorumClients.ts @@ -12,7 +12,7 @@ export class TestQuorumClients implements IQuorumClients { public disposed = false; - public dispose() { + public dispose(): void { this.disposed = true; } @@ -26,17 +26,17 @@ export class TestQuorumClients return this.members.get(clientId); } - public addClient(clientId: string, client: ISequencedClient) { + public addClient(clientId: string, client: ISequencedClient): void { this.members.set(clientId, client); this.emit("addMember", clientId, client); } - public removeClient(clientId: string) { + public removeClient(clientId: string): void { this.members.delete(clientId); this.emit("removeMember", clientId); } - public reset() { + public reset(): void { this.members.clear(); this.removeAllListeners(); } diff --git a/packages/runtime/container-runtime/src/throttler.ts b/packages/runtime/container-runtime/src/throttler.ts index 64504d6a7ad2..f1efb6f53a18 100644 --- a/packages/runtime/container-runtime/src/throttler.ts +++ b/packages/runtime/container-runtime/src/throttler.ts @@ -39,7 +39,7 @@ export interface IThrottler { export class Throttler implements IThrottler { private startTimes: number[] = []; - public get numAttempts() { + public get numAttempts(): number { return this.startTimes.length; } @@ -55,7 +55,7 @@ export class Throttler implements IThrottler { * Latest attempt time after compensating for the delay time itself * by adding the delay time to the actual time. */ - public get latestAttemptTime() { + public get latestAttemptTime(): number | undefined { return this.startTimes.length > 0 ? this.startTimes[this.startTimes.length - 1] : undefined; @@ -78,7 +78,7 @@ export class Throttler implements IThrottler { public readonly delayFn: (numAttempts: number) => number, ) {} - public getDelay() { + public getDelay(): number { const now = Date.now(); const latestAttemptTime = this.latestAttemptTime; @@ -150,7 +150,7 @@ export const formExponentialFnWithAttemptOffset = ( offset = 0, initialDelay = undefined as number | undefined, } = {}, -) => +): IThrottler["delayFn"] => formExponentialFn({ multiplier, coefficient: coefficient * Math.pow(multiplier, attemptOffset), @@ -176,7 +176,7 @@ export const formLinearFn = export const formLinearFnWithAttemptOffset = ( attemptOffset: number, { coefficient = 1, offset = 0 } = {}, -) => +): IThrottler["delayFn"] => formLinearFn({ coefficient, offset: coefficient * attemptOffset + offset, diff --git a/packages/runtime/runtime-definitions/src/dataStoreContext.ts b/packages/runtime/runtime-definitions/src/dataStoreContext.ts index f90955abc407..4ebcb1d03ec6 100644 --- a/packages/runtime/runtime-definitions/src/dataStoreContext.ts +++ b/packages/runtime/runtime-definitions/src/dataStoreContext.ts @@ -277,14 +277,14 @@ export interface IContainerRuntimeBase extends IEventProvider