@fluidframework/datastore 2.0.0-internal.5.4.0 → 2.0.0-internal.6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"remoteChannelContext.js","sourceRoot":"","sources":["../src/remoteChannelContext.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAEtD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAczD,OAAO,EACN,iBAAiB,EAEjB,gBAAgB,GAChB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAEN,6BAA6B,EAE7B,WAAW,EACX,+BAA+B,EAC/B,qBAAqB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,MAAM,OAAO,oBAAoB;IAWhC,YACC,OAA+B,EAC/B,gBAAwC,EACxC,cAAuC,EACvC,QAA0D,EAC1D,OAAkC,EAClC,0BAA2F,EAC1E,EAAU,EAC3B,YAA2B,EAC3B,QAA+B,EAC/B,UAAoD,EACpD,oBAAiD,EACjD,iBAA0B;QALT,OAAE,GAAF,EAAE,CAAQ;QAjBpB,aAAQ,GAAG,KAAK,CAAC;QACjB,YAAO,GAA4C,EAAE,CAAC;QAuB7D,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAEtF,IAAI,CAAC,SAAS,GAAG,iBAAiB,CAAC;YAClC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,SAAS,EAAE,sBAAsB;SACjC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,GAAG,6BAA6B,CAC5C,gBAAgB,CAAC,SAAS,EAC1B,QAAQ,EACR,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EACtB,0BAA0B,EAC1B,cAAc,EACd,IAAI,CAAC,SAAS,EACd,YAAY,EACZ,UAAU,CACV,CAAC;QAEF,IAAI,CAAC,QAAQ,GAAG,IAAI,WAAW,CAAW,KAAK,IAAI,EAAE;YACpD,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,MAAM,+BAA+B,CACpE,gBAAgB,EAChB,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,EAAE,EACP,QAAQ,EACR,iBAAiB,CACjB,CAAC;YAEF,MAAM,OAAO,GAAG,MAAM,WAAW,CAChC,OAAO,EACP,UAAU,EACV,OAAO,EACP,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,EAAE,CACP,CAAC;YAEF,2CAA2C;YAC3C,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAC;YACpE,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE;gBACnC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,OAAO,CACpC,OAAO,EACP,KAAK,EACL,SAAS,CAAC,qBAAqB,CAC/B,CAAC;aACF;YACD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAExE,kBAAkB;YAClB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;YACzB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YAErB,2GAA2G;YAC3G,wGAAwG;YACxG,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;YAC7E,OAAO,IAAI,CAAC,OAAO,CAAC;QACrB,CAAC,CAAC,CAAC;QAEH,MAAM,qBAAqB,GAAG,KAAK,EAClC,QAAiB,EACjB,UAAmB,EACnB,gBAAoC,EACpC,yBAAkE,EACjE,EAAE,CACH,IAAI,CAAC,iBAAiB,CACrB,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,yBAAyB,CACzB,CAAC;QAEH,IAAI,CAAC,cAAc,GAAG,oBAAoB,CACzC,qBAAqB,EACrB,KAAK,EAAE,MAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAC1D,CAAC;QAEF,IAAI,CAAC,mBAAmB,GAAG,IAAI,gBAAgB,CAC9C,oBAAoB,CAAC,wBAAwB,EAC7C,IAAI,CAAC,SAAS,CACd,CAAC;IACH,CAAC;IAED,qEAAqE;IAC9D,UAAU;QAChB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAEM,kBAAkB,CAAC,SAAkB,EAAE,QAAiB;QAC9D,oEAAoE;QACpE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YACnB,OAAO;SACP;QAED,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC7D,CAAC;IAEM,cAAc,CAAC,OAAY;QACjC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,sDAAsD,CAAC,CAAC;QACpF,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC9D,CAAC;IAEM,SAAS,CACf,OAAkC,EAClC,KAAc,EACd,eAAwB;QAExB,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAEvD,IAAI,IAAI,CAAC,QAAQ,EAAE;YAClB,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;SACvE;aAAM;YACN,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,2DAA2D,CAAC,CAAC;YAClF,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,KAAK,CAAC,4BAA4B,CAAC,CAAC;YACvE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3B,IAAI,CAAC,mBAAmB,CAAC,cAAc,CAAC,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;SAChF;IACF,CAAC;IAEM,QAAQ,CAAC,OAAY,EAAE,eAAwB;QACrD,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAExF,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAClE,CAAC;IAEM,QAAQ,CAAC,OAAY,EAAE,eAAwB;QACrD,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAExF,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAClE,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,SAAS,CACrB,WAAoB,KAAK,EACzB,aAAsB,IAAI,EAC1B,gBAAoC;QAEpC,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC;IAC9E,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAC9B,QAAiB,EACjB,UAAmB,EACnB,gBAAoC,EACpC,yBAAkE;QAElE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,eAAe,GAAG,MAAM,qBAAqB,CAClD,OAAO,EACP,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,yBAAyB,CACzB,CAAC;QACF,uCAAY,eAAe,KAAE,EAAE,EAAE,IAAI,CAAC,EAAE,IAAG;IAC5C,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,SAAS,CAAC,SAAkB,KAAK;QAC7C,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,iBAAiB,CAAC,SAAkB,KAAK;QACtD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxC,OAAO,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAEM,gBAAgB,CAAC,UAAoB;QAC3C;;;;;WAKG;QACH,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5C,CAAC;;AA9MuB,6CAAwB,GAAG,IAAI,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { LazyPromise } from \"@fluidframework/core-utils\";\nimport { IChannel, IFluidDataStoreRuntime } from \"@fluidframework/datastore-definitions\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { ISequencedDocumentMessage, ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport {\n\tCreateChildSummarizerNodeFn,\n\tIFluidDataStoreContext,\n\tIGarbageCollectionData,\n\tIExperimentalIncrementalSummaryContext,\n\tISummarizeInternalResult,\n\tISummarizeResult,\n\tISummarizerNodeWithGC,\n\tITelemetryContext,\n} from \"@fluidframework/runtime-definitions\";\nimport {\n\tcreateChildLogger,\n\tITelemetryLoggerExt,\n\tThresholdCounter,\n} from \"@fluidframework/telemetry-utils\";\nimport {\n\tChannelServiceEndpoints,\n\tcreateChannelServiceEndpoints,\n\tIChannelContext,\n\tloadChannel,\n\tloadChannelFactoryAndAttributes,\n\tsummarizeChannelAsync,\n} from \"./channelContext\";\nimport { ISharedObjectRegistry } from \"./dataStoreRuntime\";\n\nexport class RemoteChannelContext implements IChannelContext {\n\tprivate isLoaded = false;\n\tprivate pending: ISequencedDocumentMessage[] | undefined = [];\n\tprivate readonly channelP: Promise<IChannel>;\n\tprivate channel: IChannel | undefined;\n\tprivate readonly services: ChannelServiceEndpoints;\n\tprivate readonly summarizerNode: ISummarizerNodeWithGC;\n\tprivate readonly subLogger: ITelemetryLoggerExt;\n\tprivate readonly thresholdOpsCounter: ThresholdCounter;\n\tprivate static readonly pendingOpsCountThreshold = 1000;\n\n\tconstructor(\n\t\truntime: IFluidDataStoreRuntime,\n\t\tdataStoreContext: IFluidDataStoreContext,\n\t\tstorageService: IDocumentStorageService,\n\t\tsubmitFn: (content: any, localOpMetadata: unknown) => void,\n\t\tdirtyFn: (address: string) => void,\n\t\taddedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,\n\t\tprivate readonly id: string,\n\t\tbaseSnapshot: ISnapshotTree,\n\t\tregistry: ISharedObjectRegistry,\n\t\textraBlobs: Map<string, ArrayBufferLike> | undefined,\n\t\tcreateSummarizerNode: CreateChildSummarizerNodeFn,\n\t\tattachMessageType?: string,\n\t) {\n\t\tassert(!this.id.includes(\"/\"), 0x310 /* Channel context ID cannot contain slashes */);\n\n\t\tthis.subLogger = createChildLogger({\n\t\t\tlogger: runtime.logger,\n\t\t\tnamespace: \"RemoteChannelContext\",\n\t\t});\n\n\t\tthis.services = createChannelServiceEndpoints(\n\t\t\tdataStoreContext.connected,\n\t\t\tsubmitFn,\n\t\t\t() => dirtyFn(this.id),\n\t\t\taddedGCOutboundReferenceFn,\n\t\t\tstorageService,\n\t\t\tthis.subLogger,\n\t\t\tbaseSnapshot,\n\t\t\textraBlobs,\n\t\t);\n\n\t\tthis.channelP = new LazyPromise<IChannel>(async () => {\n\t\t\tconst { attributes, factory } = await loadChannelFactoryAndAttributes(\n\t\t\t\tdataStoreContext,\n\t\t\t\tthis.services,\n\t\t\t\tthis.id,\n\t\t\t\tregistry,\n\t\t\t\tattachMessageType,\n\t\t\t);\n\n\t\t\tconst channel = await loadChannel(\n\t\t\t\truntime,\n\t\t\t\tattributes,\n\t\t\t\tfactory,\n\t\t\t\tthis.services,\n\t\t\t\tthis.subLogger,\n\t\t\t\tthis.id,\n\t\t\t);\n\n\t\t\t// Send all pending messages to the channel\n\t\t\tassert(this.pending !== undefined, 0x23f /* \"pending undefined\" */);\n\t\t\tfor (const message of this.pending) {\n\t\t\t\tthis.services.deltaConnection.process(\n\t\t\t\t\tmessage,\n\t\t\t\t\tfalse,\n\t\t\t\t\tundefined /* localOpMetadata */,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.thresholdOpsCounter.send(\"ProcessPendingOps\", this.pending.length);\n\n\t\t\t// Commit changes.\n\t\t\tthis.channel = channel;\n\t\t\tthis.pending = undefined;\n\t\t\tthis.isLoaded = true;\n\n\t\t\t// Because have some await between we created the service and here, the connection state might have changed\n\t\t\t// and we don't propagate the connection state when we are not loaded. So we have to set it again here.\n\t\t\tthis.services.deltaConnection.setConnectionState(dataStoreContext.connected);\n\t\t\treturn this.channel;\n\t\t});\n\n\t\tconst thisSummarizeInternal = async (\n\t\t\tfullTree: boolean,\n\t\t\ttrackState: boolean,\n\t\t\ttelemetryContext?: ITelemetryContext,\n\t\t\tincrementalSummaryContext?: IExperimentalIncrementalSummaryContext,\n\t\t) =>\n\t\t\tthis.summarizeInternal(\n\t\t\t\tfullTree,\n\t\t\t\ttrackState,\n\t\t\t\ttelemetryContext,\n\t\t\t\tincrementalSummaryContext,\n\t\t\t);\n\n\t\tthis.summarizerNode = createSummarizerNode(\n\t\t\tthisSummarizeInternal,\n\t\t\tasync (fullGC?: boolean) => this.getGCDataInternal(fullGC),\n\t\t);\n\n\t\tthis.thresholdOpsCounter = new ThresholdCounter(\n\t\t\tRemoteChannelContext.pendingOpsCountThreshold,\n\t\t\tthis.subLogger,\n\t\t);\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/promise-function-async\n\tpublic getChannel(): Promise<IChannel> {\n\t\treturn this.channelP;\n\t}\n\n\tpublic setConnectionState(connected: boolean, clientId?: string) {\n\t\t// Connection events are ignored if the data store is not yet loaded\n\t\tif (!this.isLoaded) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.services.deltaConnection.setConnectionState(connected);\n\t}\n\n\tpublic applyStashedOp(content: any): unknown {\n\t\tassert(this.isLoaded, 0x194 /* \"Remote channel must be loaded when rebasing op\" */);\n\t\treturn this.services.deltaConnection.applyStashedOp(content);\n\t}\n\n\tpublic processOp(\n\t\tmessage: ISequencedDocumentMessage,\n\t\tlocal: boolean,\n\t\tlocalOpMetadata: unknown,\n\t): void {\n\t\tthis.summarizerNode.invalidate(message.sequenceNumber);\n\n\t\tif (this.isLoaded) {\n\t\t\tthis.services.deltaConnection.process(message, local, localOpMetadata);\n\t\t} else {\n\t\t\tassert(!local, 0x195 /* \"Remote channel must not be local when processing op\" */);\n\t\t\tassert(this.pending !== undefined, 0x23e /* \"pending is undefined\" */);\n\t\t\tthis.pending.push(message);\n\t\t\tthis.thresholdOpsCounter.sendIfMultiple(\"StorePendingOps\", this.pending.length);\n\t\t}\n\t}\n\n\tpublic reSubmit(content: any, localOpMetadata: unknown) {\n\t\tassert(this.isLoaded, 0x196 /* \"Remote channel must be loaded when resubmitting op\" */);\n\n\t\tthis.services.deltaConnection.reSubmit(content, localOpMetadata);\n\t}\n\n\tpublic rollback(content: any, localOpMetadata: unknown) {\n\t\tassert(this.isLoaded, 0x2f0 /* \"Remote channel must be loaded when rolling back op\" */);\n\n\t\tthis.services.deltaConnection.rollback(content, localOpMetadata);\n\t}\n\n\t/**\n\t * Returns a summary at the current sequence number.\n\t * @param fullTree - true to bypass optimizations and force a full summary tree\n\t * @param trackState - This tells whether we should track state from this summary.\n\t * @param telemetryContext - summary data passed through the layers for telemetry purposes\n\t */\n\tpublic async summarize(\n\t\tfullTree: boolean = false,\n\t\ttrackState: boolean = true,\n\t\ttelemetryContext?: ITelemetryContext,\n\t): Promise<ISummarizeResult> {\n\t\treturn this.summarizerNode.summarize(fullTree, trackState, telemetryContext);\n\t}\n\n\tprivate async summarizeInternal(\n\t\tfullTree: boolean,\n\t\ttrackState: boolean,\n\t\ttelemetryContext?: ITelemetryContext,\n\t\tincrementalSummaryContext?: IExperimentalIncrementalSummaryContext,\n\t): Promise<ISummarizeInternalResult> {\n\t\tconst channel = await this.getChannel();\n\t\tconst summarizeResult = await summarizeChannelAsync(\n\t\t\tchannel,\n\t\t\tfullTree,\n\t\t\ttrackState,\n\t\t\ttelemetryContext,\n\t\t\tincrementalSummaryContext,\n\t\t);\n\t\treturn { ...summarizeResult, id: this.id };\n\t}\n\n\t/**\n\t * Returns the data used for garbage collection. This includes a list of GC nodes that represent this context.\n\t * Each node has a set of outbound routes to other GC nodes in the document.\n\t * If there is no new data in this context since the last summary, previous GC data is used.\n\t * If there is new data, the GC data is generated again (by calling getGCDataInternal).\n\t * @param fullGC - true to bypass optimizations and force full generation of GC data.\n\t */\n\tpublic async getGCData(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n\t\treturn this.summarizerNode.getGCData(fullGC);\n\t}\n\n\t/**\n\t * Generates the data used for garbage collection. This is called when there is new data since last summary. It\n\t * loads the context and calls into the channel to get its GC data.\n\t * @param fullGC - true to bypass optimizations and force full generation of GC data.\n\t */\n\tprivate async getGCDataInternal(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n\t\tconst channel = await this.getChannel();\n\t\treturn channel.getGCData(fullGC);\n\t}\n\n\tpublic updateUsedRoutes(usedRoutes: string[]) {\n\t\t/**\n\t\t * Currently, DDSes are always considered referenced and are not garbage collected. Update the summarizer node's\n\t\t * used routes to contain a route to this channel context.\n\t\t * Once we have GC at DDS level, this will be updated to use the passed usedRoutes. See -\n\t\t * https://github.com/microsoft/FluidFramework/issues/4611\n\t\t */\n\t\tthis.summarizerNode.updateUsedRoutes([\"\"]);\n\t}\n}\n"]}
1
+ {"version":3,"file":"remoteChannelContext.js","sourceRoot":"","sources":["../src/remoteChannelContext.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { LazyPromise } from \"@fluidframework/core-utils\";\nimport { IChannel, IFluidDataStoreRuntime } from \"@fluidframework/datastore-definitions\";\nimport { IDocumentStorageService } from \"@fluidframework/driver-definitions\";\nimport { ISequencedDocumentMessage, ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport {\n\tCreateChildSummarizerNodeFn,\n\tIFluidDataStoreContext,\n\tIGarbageCollectionData,\n\tIExperimentalIncrementalSummaryContext,\n\tISummarizeInternalResult,\n\tISummarizeResult,\n\tISummarizerNodeWithGC,\n\tITelemetryContext,\n} from \"@fluidframework/runtime-definitions\";\nimport {\n\tcreateChildLogger,\n\tITelemetryLoggerExt,\n\tThresholdCounter,\n} from \"@fluidframework/telemetry-utils\";\nimport {\n\tChannelServiceEndpoints,\n\tcreateChannelServiceEndpoints,\n\tIChannelContext,\n\tloadChannel,\n\tloadChannelFactoryAndAttributes,\n\tsummarizeChannelAsync,\n} from \"./channelContext\";\nimport { ISharedObjectRegistry } from \"./dataStoreRuntime\";\n\nexport class RemoteChannelContext implements IChannelContext {\n\tprivate isLoaded = false;\n\tprivate pending: ISequencedDocumentMessage[] | undefined = [];\n\tprivate readonly channelP: Promise<IChannel>;\n\tprivate channel: IChannel | undefined;\n\tprivate readonly services: ChannelServiceEndpoints;\n\tprivate readonly summarizerNode: ISummarizerNodeWithGC;\n\tprivate readonly subLogger: ITelemetryLoggerExt;\n\tprivate readonly thresholdOpsCounter: ThresholdCounter;\n\tprivate static readonly pendingOpsCountThreshold = 1000;\n\n\tconstructor(\n\t\truntime: IFluidDataStoreRuntime,\n\t\tdataStoreContext: IFluidDataStoreContext,\n\t\tstorageService: IDocumentStorageService,\n\t\tsubmitFn: (content: any, localOpMetadata: unknown) => void,\n\t\tdirtyFn: (address: string) => void,\n\t\taddedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,\n\t\tprivate readonly id: string,\n\t\tbaseSnapshot: ISnapshotTree,\n\t\tregistry: ISharedObjectRegistry,\n\t\textraBlobs: Map<string, ArrayBufferLike> | undefined,\n\t\tcreateSummarizerNode: CreateChildSummarizerNodeFn,\n\t\tattachMessageType?: string,\n\t) {\n\t\tassert(!this.id.includes(\"/\"), 0x310 /* Channel context ID cannot contain slashes */);\n\n\t\tthis.subLogger = createChildLogger({\n\t\t\tlogger: runtime.logger,\n\t\t\tnamespace: \"RemoteChannelContext\",\n\t\t});\n\n\t\tthis.services = createChannelServiceEndpoints(\n\t\t\tdataStoreContext.connected,\n\t\t\tsubmitFn,\n\t\t\t() => dirtyFn(this.id),\n\t\t\taddedGCOutboundReferenceFn,\n\t\t\tstorageService,\n\t\t\tthis.subLogger,\n\t\t\tbaseSnapshot,\n\t\t\textraBlobs,\n\t\t);\n\n\t\tthis.channelP = new LazyPromise<IChannel>(async () => {\n\t\t\tconst { attributes, factory } = await loadChannelFactoryAndAttributes(\n\t\t\t\tdataStoreContext,\n\t\t\t\tthis.services,\n\t\t\t\tthis.id,\n\t\t\t\tregistry,\n\t\t\t\tattachMessageType,\n\t\t\t);\n\n\t\t\tconst channel = await loadChannel(\n\t\t\t\truntime,\n\t\t\t\tattributes,\n\t\t\t\tfactory,\n\t\t\t\tthis.services,\n\t\t\t\tthis.subLogger,\n\t\t\t\tthis.id,\n\t\t\t);\n\n\t\t\t// Send all pending messages to the channel\n\t\t\tassert(this.pending !== undefined, 0x23f /* \"pending undefined\" */);\n\t\t\tfor (const message of this.pending) {\n\t\t\t\tthis.services.deltaConnection.process(\n\t\t\t\t\tmessage,\n\t\t\t\t\tfalse,\n\t\t\t\t\tundefined /* localOpMetadata */,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.thresholdOpsCounter.send(\"ProcessPendingOps\", this.pending.length);\n\n\t\t\t// Commit changes.\n\t\t\tthis.channel = channel;\n\t\t\tthis.pending = undefined;\n\t\t\tthis.isLoaded = true;\n\n\t\t\t// Because have some await between we created the service and here, the connection state might have changed\n\t\t\t// and we don't propagate the connection state when we are not loaded. So we have to set it again here.\n\t\t\tthis.services.deltaConnection.setConnectionState(dataStoreContext.connected);\n\t\t\treturn this.channel;\n\t\t});\n\n\t\tconst thisSummarizeInternal = async (\n\t\t\tfullTree: boolean,\n\t\t\ttrackState: boolean,\n\t\t\ttelemetryContext?: ITelemetryContext,\n\t\t\tincrementalSummaryContext?: IExperimentalIncrementalSummaryContext,\n\t\t) =>\n\t\t\tthis.summarizeInternal(\n\t\t\t\tfullTree,\n\t\t\t\ttrackState,\n\t\t\t\ttelemetryContext,\n\t\t\t\tincrementalSummaryContext,\n\t\t\t);\n\n\t\tthis.summarizerNode = createSummarizerNode(\n\t\t\tthisSummarizeInternal,\n\t\t\tasync (fullGC?: boolean) => this.getGCDataInternal(fullGC),\n\t\t);\n\n\t\tthis.thresholdOpsCounter = new ThresholdCounter(\n\t\t\tRemoteChannelContext.pendingOpsCountThreshold,\n\t\t\tthis.subLogger,\n\t\t);\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/promise-function-async\n\tpublic getChannel(): Promise<IChannel> {\n\t\treturn this.channelP;\n\t}\n\n\tpublic setConnectionState(connected: boolean, clientId?: string) {\n\t\t// Connection events are ignored if the data store is not yet loaded\n\t\tif (!this.isLoaded) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.services.deltaConnection.setConnectionState(connected);\n\t}\n\n\tpublic applyStashedOp(content: any): unknown {\n\t\tassert(this.isLoaded, 0x194 /* \"Remote channel must be loaded when rebasing op\" */);\n\t\treturn this.services.deltaConnection.applyStashedOp(content);\n\t}\n\n\tpublic processOp(\n\t\tmessage: ISequencedDocumentMessage,\n\t\tlocal: boolean,\n\t\tlocalOpMetadata: unknown,\n\t): void {\n\t\tthis.summarizerNode.invalidate(message.sequenceNumber);\n\n\t\tif (this.isLoaded) {\n\t\t\tthis.services.deltaConnection.process(message, local, localOpMetadata);\n\t\t} else {\n\t\t\tassert(!local, 0x195 /* \"Remote channel must not be local when processing op\" */);\n\t\t\tassert(this.pending !== undefined, 0x23e /* \"pending is undefined\" */);\n\t\t\tthis.pending.push(message);\n\t\t\tthis.thresholdOpsCounter.sendIfMultiple(\"StorePendingOps\", this.pending.length);\n\t\t}\n\t}\n\n\tpublic reSubmit(content: any, localOpMetadata: unknown) {\n\t\tassert(this.isLoaded, 0x196 /* \"Remote channel must be loaded when resubmitting op\" */);\n\n\t\tthis.services.deltaConnection.reSubmit(content, localOpMetadata);\n\t}\n\n\tpublic rollback(content: any, localOpMetadata: unknown) {\n\t\tassert(this.isLoaded, 0x2f0 /* \"Remote channel must be loaded when rolling back op\" */);\n\n\t\tthis.services.deltaConnection.rollback(content, localOpMetadata);\n\t}\n\n\t/**\n\t * Returns a summary at the current sequence number.\n\t * @param fullTree - true to bypass optimizations and force a full summary tree\n\t * @param trackState - This tells whether we should track state from this summary.\n\t * @param telemetryContext - summary data passed through the layers for telemetry purposes\n\t */\n\tpublic async summarize(\n\t\tfullTree: boolean = false,\n\t\ttrackState: boolean = true,\n\t\ttelemetryContext?: ITelemetryContext,\n\t): Promise<ISummarizeResult> {\n\t\treturn this.summarizerNode.summarize(fullTree, trackState, telemetryContext);\n\t}\n\n\tprivate async summarizeInternal(\n\t\tfullTree: boolean,\n\t\ttrackState: boolean,\n\t\ttelemetryContext?: ITelemetryContext,\n\t\tincrementalSummaryContext?: IExperimentalIncrementalSummaryContext,\n\t): Promise<ISummarizeInternalResult> {\n\t\tconst channel = await this.getChannel();\n\t\tconst summarizeResult = await summarizeChannelAsync(\n\t\t\tchannel,\n\t\t\tfullTree,\n\t\t\ttrackState,\n\t\t\ttelemetryContext,\n\t\t\tincrementalSummaryContext,\n\t\t);\n\t\treturn { ...summarizeResult, id: this.id };\n\t}\n\n\t/**\n\t * Returns the data used for garbage collection. This includes a list of GC nodes that represent this context.\n\t * Each node has a set of outbound routes to other GC nodes in the document.\n\t * If there is no new data in this context since the last summary, previous GC data is used.\n\t * If there is new data, the GC data is generated again (by calling getGCDataInternal).\n\t * @param fullGC - true to bypass optimizations and force full generation of GC data.\n\t */\n\tpublic async getGCData(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n\t\treturn this.summarizerNode.getGCData(fullGC);\n\t}\n\n\t/**\n\t * Generates the data used for garbage collection. This is called when there is new data since last summary. It\n\t * loads the context and calls into the channel to get its GC data.\n\t * @param fullGC - true to bypass optimizations and force full generation of GC data.\n\t */\n\tprivate async getGCDataInternal(fullGC: boolean = false): Promise<IGarbageCollectionData> {\n\t\tconst channel = await this.getChannel();\n\t\treturn channel.getGCData(fullGC);\n\t}\n\n\tpublic updateUsedRoutes(usedRoutes: string[]) {\n\t\t/**\n\t\t * Currently, DDSes are always considered referenced and are not garbage collected. Update the summarizer node's\n\t\t * used routes to contain a route to this channel context.\n\t\t * Once we have GC at DDS level, this will be updated to use the passed usedRoutes. See -\n\t\t * https://github.com/microsoft/FluidFramework/issues/4611\n\t\t */\n\t\tthis.summarizerNode.updateUsedRoutes([\"\"]);\n\t}\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/datastore",
3
- "version": "2.0.0-internal.5.4.0",
3
+ "version": "2.0.0-internal.6.1.0",
4
4
  "description": "Fluid data store implementation",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -37,29 +37,29 @@
37
37
  "dependencies": {
38
38
  "@fluidframework/common-definitions": "^0.20.1",
39
39
  "@fluidframework/common-utils": "^1.1.1",
40
- "@fluidframework/container-definitions": ">=2.0.0-internal.5.4.0 <2.0.0-internal.5.5.0",
41
- "@fluidframework/container-utils": ">=2.0.0-internal.5.4.0 <2.0.0-internal.5.5.0",
42
- "@fluidframework/core-interfaces": ">=2.0.0-internal.5.4.0 <2.0.0-internal.5.5.0",
43
- "@fluidframework/core-utils": ">=2.0.0-internal.5.4.0 <2.0.0-internal.5.5.0",
44
- "@fluidframework/datastore-definitions": ">=2.0.0-internal.5.4.0 <2.0.0-internal.5.5.0",
45
- "@fluidframework/driver-definitions": ">=2.0.0-internal.5.4.0 <2.0.0-internal.5.5.0",
46
- "@fluidframework/driver-utils": ">=2.0.0-internal.5.4.0 <2.0.0-internal.5.5.0",
47
- "@fluidframework/protocol-base": "^0.1039.1000",
40
+ "@fluidframework/container-definitions": ">=2.0.0-internal.6.1.0 <2.0.0-internal.6.2.0",
41
+ "@fluidframework/container-utils": ">=2.0.0-internal.6.1.0 <2.0.0-internal.6.2.0",
42
+ "@fluidframework/core-interfaces": ">=2.0.0-internal.6.1.0 <2.0.0-internal.6.2.0",
43
+ "@fluidframework/core-utils": ">=2.0.0-internal.6.1.0 <2.0.0-internal.6.2.0",
44
+ "@fluidframework/datastore-definitions": ">=2.0.0-internal.6.1.0 <2.0.0-internal.6.2.0",
45
+ "@fluidframework/driver-definitions": ">=2.0.0-internal.6.1.0 <2.0.0-internal.6.2.0",
46
+ "@fluidframework/driver-utils": ">=2.0.0-internal.6.1.0 <2.0.0-internal.6.2.0",
47
+ "@fluidframework/protocol-base": "^1.0.0",
48
48
  "@fluidframework/protocol-definitions": "^1.1.0",
49
- "@fluidframework/runtime-definitions": ">=2.0.0-internal.5.4.0 <2.0.0-internal.5.5.0",
50
- "@fluidframework/runtime-utils": ">=2.0.0-internal.5.4.0 <2.0.0-internal.5.5.0",
51
- "@fluidframework/telemetry-utils": ">=2.0.0-internal.5.4.0 <2.0.0-internal.5.5.0",
49
+ "@fluidframework/runtime-definitions": ">=2.0.0-internal.6.1.0 <2.0.0-internal.6.2.0",
50
+ "@fluidframework/runtime-utils": ">=2.0.0-internal.6.1.0 <2.0.0-internal.6.2.0",
51
+ "@fluidframework/telemetry-utils": ">=2.0.0-internal.6.1.0 <2.0.0-internal.6.2.0",
52
52
  "lodash": "^4.17.21",
53
53
  "uuid": "^8.3.1"
54
54
  },
55
55
  "devDependencies": {
56
- "@fluid-tools/build-cli": "^0.21.0",
57
- "@fluidframework/build-common": "^1.2.0",
58
- "@fluidframework/build-tools": "^0.21.0",
59
- "@fluidframework/datastore-previous": "npm:@fluidframework/datastore@2.0.0-internal.5.2.0",
56
+ "@fluid-tools/build-cli": "^0.22.0",
57
+ "@fluidframework/build-common": "^2.0.0",
58
+ "@fluidframework/build-tools": "^0.22.0",
59
+ "@fluidframework/datastore-previous": "npm:@fluidframework/datastore@2.0.0-internal.6.0.0",
60
60
  "@fluidframework/eslint-config-fluid": "^2.0.0",
61
- "@fluidframework/mocha-test-setup": ">=2.0.0-internal.5.4.0 <2.0.0-internal.5.5.0",
62
- "@fluidframework/test-runtime-utils": ">=2.0.0-internal.5.4.0 <2.0.0-internal.5.5.0",
61
+ "@fluidframework/mocha-test-setup": ">=2.0.0-internal.6.1.0 <2.0.0-internal.6.2.0",
62
+ "@fluidframework/test-runtime-utils": ">=2.0.0-internal.6.1.0 <2.0.0-internal.6.2.0",
63
63
  "@microsoft/api-extractor": "^7.34.4",
64
64
  "@types/mocha": "^9.1.1",
65
65
  "@types/node": "^16.18.38",
@@ -39,6 +39,7 @@ import {
39
39
  IQuorumClients,
40
40
  } from "@fluidframework/protocol-definitions";
41
41
  import {
42
+ CreateChildSummarizerNodeParam,
42
43
  CreateSummarizerNodeSource,
43
44
  IAttachMessage,
44
45
  IEnvelope,
@@ -125,6 +126,9 @@ export class FluidDataStoreRuntime
125
126
  */
126
127
  public readonly entryPoint?: IFluidHandle<FluidObject>;
127
128
 
129
+ /**
130
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
131
+ */
128
132
  public get IFluidRouter() {
129
133
  return this;
130
134
  }
@@ -181,8 +185,7 @@ export class FluidDataStoreRuntime
181
185
  }
182
186
 
183
187
  private readonly contexts = new Map<string, IChannelContext>();
184
- private readonly contextsDeferred = new Map<string, Deferred<IChannelContext>>();
185
- private readonly pendingAttach = new Map<string, IAttachMessage>();
188
+ private readonly pendingAttach = new Set<string>();
186
189
 
187
190
  private readonly deferredAttached = new Deferred<void>();
188
191
  private readonly localChannelContextQueue = new Map<string, LocalChannelContextBase>();
@@ -320,11 +323,8 @@ export class FluidDataStoreRuntime
320
323
  }),
321
324
  );
322
325
  }
323
- const deferred = new Deferred<IChannelContext>();
324
- deferred.resolve(channelContext);
325
326
 
326
327
  this.contexts.set(path, channelContext);
327
- this.contextsDeferred.set(path, deferred);
328
328
  });
329
329
  }
330
330
 
@@ -383,6 +383,9 @@ export class FluidDataStoreRuntime
383
383
  return this.request(request);
384
384
  }
385
385
 
386
+ /**
387
+ * @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
388
+ */
386
389
  public async request(request: IRequest): Promise<IResponse> {
387
390
  try {
388
391
  const parser = RequestParser.create(request);
@@ -393,11 +396,10 @@ export class FluidDataStoreRuntime
393
396
  }
394
397
 
395
398
  // Check for a data type reference first
396
- if (this.contextsDeferred.has(id) && parser.isLeaf(1)) {
399
+ const context = this.contexts.get(id);
400
+ if (context !== undefined && parser.isLeaf(1)) {
397
401
  try {
398
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
399
- const value = await this.contextsDeferred.get(id)!.promise;
400
- const channel = await value.getChannel();
402
+ const channel = await context.getChannel();
401
403
 
402
404
  return { mimeType: "fluid/object", status: 200, value: channel };
403
405
  } catch (error) {
@@ -420,18 +422,12 @@ export class FluidDataStoreRuntime
420
422
  public async getChannel(id: string): Promise<IChannel> {
421
423
  this.verifyNotClosed();
422
424
 
423
- // TODO we don't assume any channels (even root) in the runtime. If you request a channel that doesn't exist
424
- // we will never resolve the promise. May want a flag to getChannel that doesn't wait for the promise if
425
- // it doesn't exist
426
- if (!this.contextsDeferred.has(id)) {
427
- this.contextsDeferred.set(id, new Deferred<IChannelContext>());
425
+ const context = this.contexts.get(id);
426
+ if (context === undefined) {
427
+ throw new LoggingError("Channel does not exist");
428
428
  }
429
429
 
430
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
431
- const context = await this.contextsDeferred.get(id)!.promise;
432
- const channel = await context.getChannel();
433
-
434
- return channel;
430
+ return context.getChannel();
435
431
  }
436
432
 
437
433
  public createChannel(id: string = uuid(), type: string): IChannel {
@@ -458,15 +454,6 @@ export class FluidDataStoreRuntime
458
454
  );
459
455
  this.contexts.set(id, context);
460
456
 
461
- if (this.contextsDeferred.has(id)) {
462
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
463
- this.contextsDeferred.get(id)!.resolve(context);
464
- } else {
465
- const deferred = new Deferred<IChannelContext>();
466
- deferred.resolve(context);
467
- this.contextsDeferred.set(id, deferred);
468
- }
469
-
470
457
  // Channels (DDS) should not be created in summarizer client.
471
458
  this.identifyLocalChangeInSummarizer("DDSCreatedInSummarizer", id, type);
472
459
 
@@ -587,6 +574,34 @@ export class FluidDataStoreRuntime
587
574
  return this.dataStoreContext.uploadBlob(blob, signal);
588
575
  }
589
576
 
577
+ private createRemoteChannelContext(
578
+ attachMessage: IAttachMessage,
579
+ summarizerNodeParams: CreateChildSummarizerNodeParam,
580
+ ) {
581
+ const flatBlobs = new Map<string, ArrayBufferLike>();
582
+ const snapshotTree = buildSnapshotTree(attachMessage.snapshot.entries, flatBlobs);
583
+
584
+ return new RemoteChannelContext(
585
+ this,
586
+ this.dataStoreContext,
587
+ this.dataStoreContext.storage,
588
+ (content, localContentMetadata) =>
589
+ this.submitChannelOp(attachMessage.id, content, localContentMetadata),
590
+ (address: string) => this.setChannelDirty(address),
591
+ (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) =>
592
+ this.addedGCOutboundReference(srcHandle, outboundHandle),
593
+ attachMessage.id,
594
+ snapshotTree,
595
+ this.sharedObjectRegistry,
596
+ flatBlobs,
597
+ this.dataStoreContext.getCreateChildSummarizerNodeFn(
598
+ attachMessage.id,
599
+ summarizerNodeParams,
600
+ ),
601
+ attachMessage.type,
602
+ );
603
+ }
604
+
590
605
  public process(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown) {
591
606
  this.verifyNotClosed();
592
607
 
@@ -601,49 +616,23 @@ export class FluidDataStoreRuntime
601
616
  // Otherwise mark it as officially attached.
602
617
  if (local) {
603
618
  assert(
604
- this.pendingAttach.has(id),
619
+ this.pendingAttach.delete(id),
605
620
  0x17c /* "Unexpected attach (local) channel OP" */,
606
621
  );
607
- this.pendingAttach.delete(id);
608
622
  } else {
609
623
  assert(!this.contexts.has(id), 0x17d /* "Unexpected attach channel OP" */);
610
624
 
611
- const flatBlobs = new Map<string, ArrayBufferLike>();
612
- const snapshotTree = buildSnapshotTree(
613
- attachMessage.snapshot.entries,
614
- flatBlobs,
615
- );
625
+ const summarizerNodeParams = {
626
+ type: CreateSummarizerNodeSource.FromAttach,
627
+ sequenceNumber: message.sequenceNumber,
628
+ snapshot: attachMessage.snapshot,
629
+ };
616
630
 
617
- const remoteChannelContext = new RemoteChannelContext(
618
- this,
619
- this.dataStoreContext,
620
- this.dataStoreContext.storage,
621
- (content, localContentMetadata) =>
622
- this.submitChannelOp(id, content, localContentMetadata),
623
- (address: string) => this.setChannelDirty(address),
624
- (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) =>
625
- this.addedGCOutboundReference(srcHandle, outboundHandle),
626
- id,
627
- snapshotTree,
628
- this.sharedObjectRegistry,
629
- flatBlobs,
630
- this.dataStoreContext.getCreateChildSummarizerNodeFn(id, {
631
- type: CreateSummarizerNodeSource.FromAttach,
632
- sequenceNumber: message.sequenceNumber,
633
- snapshot: attachMessage.snapshot,
634
- }),
635
- attachMessage.type,
631
+ const remoteChannelContext = this.createRemoteChannelContext(
632
+ attachMessage,
633
+ summarizerNodeParams,
636
634
  );
637
-
638
635
  this.contexts.set(id, remoteChannelContext);
639
- if (this.contextsDeferred.has(id)) {
640
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
641
- this.contextsDeferred.get(id)!.resolve(remoteChannelContext);
642
- } else {
643
- const deferred = new Deferred<IChannelContext>();
644
- deferred.resolve(remoteChannelContext);
645
- this.contextsDeferred.set(id, deferred);
646
- }
647
636
  }
648
637
  break;
649
638
  }
@@ -923,7 +912,7 @@ export class FluidDataStoreRuntime
923
912
  snapshot,
924
913
  type: channel.attributes.type,
925
914
  };
926
- this.pendingAttach.set(channel.id, message);
915
+ this.pendingAttach.add(channel.id);
927
916
  this.submit(DataStoreMessageType.Attach, message);
928
917
 
929
918
  const context = this.contexts.get(channel.id) as LocalChannelContextBase;
@@ -1001,11 +990,35 @@ export class FluidDataStoreRuntime
1001
990
  }
1002
991
 
1003
992
  public async applyStashedOp(content: any): Promise<unknown> {
1004
- const envelope = content as IEnvelope;
1005
- const channelContext = this.contexts.get(envelope.address);
1006
- assert(!!channelContext, 0x184 /* "There should be a channel context for the op" */);
1007
- await channelContext.getChannel();
1008
- return channelContext.applyStashedOp(envelope.contents);
993
+ const type = content?.type as DataStoreMessageType;
994
+ switch (type) {
995
+ case DataStoreMessageType.Attach: {
996
+ const attachMessage = content.content as IAttachMessage;
997
+ // local means this node will throw if summarized; this is fine because only interactive clients will have stashed ops
998
+ const summarizerNodeParams: CreateChildSummarizerNodeParam = {
999
+ type: CreateSummarizerNodeSource.Local,
1000
+ };
1001
+ const context = this.createRemoteChannelContext(
1002
+ attachMessage,
1003
+ summarizerNodeParams,
1004
+ );
1005
+ this.pendingAttach.add(attachMessage.id);
1006
+ this.contexts.set(attachMessage.id, context);
1007
+ return;
1008
+ }
1009
+ case DataStoreMessageType.ChannelOp: {
1010
+ const envelope = content.content as IEnvelope;
1011
+ const channelContext = this.contexts.get(envelope.address);
1012
+ assert(
1013
+ !!channelContext,
1014
+ 0x184 /* "There should be a channel context for the op" */,
1015
+ );
1016
+ await channelContext.getChannel();
1017
+ return channelContext.applyStashedOp(envelope.contents);
1018
+ }
1019
+ default:
1020
+ unreachableCase(type);
1021
+ }
1009
1022
  }
1010
1023
 
1011
1024
  private setChannelDirty(address: string): void {