@fluidframework/odsp-driver 2.41.0-338186 → 2.41.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.
- package/CHANGELOG.md +4 -0
- package/api-report/odsp-driver.legacy.alpha.api.md +1 -4
- package/dist/createOdspCreateContainerRequest.d.ts +2 -17
- package/dist/createOdspCreateContainerRequest.d.ts.map +1 -1
- package/dist/createOdspCreateContainerRequest.js +1 -1
- package/dist/createOdspCreateContainerRequest.js.map +1 -1
- package/dist/odspDelayLoadedDeltaStream.d.ts +2 -0
- package/dist/odspDelayLoadedDeltaStream.d.ts.map +1 -1
- package/dist/odspDelayLoadedDeltaStream.js +18 -3
- package/dist/odspDelayLoadedDeltaStream.js.map +1 -1
- package/dist/odspDocumentDeltaConnection.d.ts +2 -1
- package/dist/odspDocumentDeltaConnection.d.ts.map +1 -1
- package/dist/odspDocumentDeltaConnection.js +2 -2
- package/dist/odspDocumentDeltaConnection.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/createOdspCreateContainerRequest.d.ts +2 -17
- package/lib/createOdspCreateContainerRequest.d.ts.map +1 -1
- package/lib/createOdspCreateContainerRequest.js +1 -1
- package/lib/createOdspCreateContainerRequest.js.map +1 -1
- package/lib/odspDelayLoadedDeltaStream.d.ts +2 -0
- package/lib/odspDelayLoadedDeltaStream.d.ts.map +1 -1
- package/lib/odspDelayLoadedDeltaStream.js +18 -3
- package/lib/odspDelayLoadedDeltaStream.js.map +1 -1
- package/lib/odspDocumentDeltaConnection.d.ts +2 -1
- package/lib/odspDocumentDeltaConnection.d.ts.map +1 -1
- package/lib/odspDocumentDeltaConnection.js +2 -2
- package/lib/odspDocumentDeltaConnection.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +12 -12
- package/src/createOdspCreateContainerRequest.ts +1 -45
- package/src/odspDelayLoadedDeltaStream.ts +20 -0
- package/src/odspDocumentDeltaConnection.ts +2 -1
- package/src/packageVersion.ts +1 -1
|
@@ -31,8 +31,9 @@ export declare class OdspDocumentDeltaConnection extends DocumentDeltaConnection
|
|
|
31
31
|
* @param timeoutMs - time limit on making the connection
|
|
32
32
|
* @param epochTracker - track epoch changes
|
|
33
33
|
* @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache
|
|
34
|
+
* @param connectionId - (optional) connection ID for the connection
|
|
34
35
|
*/
|
|
35
|
-
static create(tenantId: string, documentId: string, token: string | null, client: IClient, url: string, telemetryLogger: ITelemetryLoggerExt, timeoutMs: number, epochTracker: EpochTracker, socketReferenceKeyPrefix: string | undefined): Promise<OdspDocumentDeltaConnection>;
|
|
36
|
+
static create(tenantId: string, documentId: string, token: string | null, client: IClient, url: string, telemetryLogger: ITelemetryLoggerExt, timeoutMs: number, epochTracker: EpochTracker, socketReferenceKeyPrefix: string | undefined, connectionId?: string): Promise<OdspDocumentDeltaConnection>;
|
|
36
37
|
private socketReference;
|
|
37
38
|
private readonly requestOpsNoncePrefix;
|
|
38
39
|
private pushCallCounter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspDocumentDeltaConnection.d.ts","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAC7D,OAAO,EACN,eAAe,EACf,QAAQ,EACR,gBAAgB,EAEhB,kBAAkB,EAGlB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EAAE,SAAS,EAAE,MAAM,kDAAkD,CAAC;AAC7E,OAAO,EACN,eAAe,EACf,mBAAmB,EAEnB,MAAM,0CAA0C,CAAC;AAKlD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AASjD,MAAM,WAAW,WAAW;IAC3B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AA2LD;;GAEG;AACH,qBAAa,2BAA4B,SAAQ,uBAAuB;
|
|
1
|
+
{"version":3,"file":"odspDocumentDeltaConnection.d.ts","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.ts"],"names":[],"mappings":"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"}
|
|
@@ -160,10 +160,11 @@ export class OdspDocumentDeltaConnection extends DocumentDeltaConnection {
|
|
|
160
160
|
* @param timeoutMs - time limit on making the connection
|
|
161
161
|
* @param epochTracker - track epoch changes
|
|
162
162
|
* @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache
|
|
163
|
+
* @param connectionId - (optional) connection ID for the connection
|
|
163
164
|
*/
|
|
164
165
|
static async create(tenantId, documentId,
|
|
165
166
|
// eslint-disable-next-line @rushstack/no-new-null
|
|
166
|
-
token, client, url, telemetryLogger, timeoutMs, epochTracker, socketReferenceKeyPrefix) {
|
|
167
|
+
token, client, url, telemetryLogger, timeoutMs, epochTracker, socketReferenceKeyPrefix, connectionId = uuid()) {
|
|
167
168
|
const mc = loggerToMonitoringContext(telemetryLogger);
|
|
168
169
|
// enable multiplexing when the websocket url does not include the tenant/document id
|
|
169
170
|
const parsedUrl = new URL(url);
|
|
@@ -174,7 +175,6 @@ export class OdspDocumentDeltaConnection extends DocumentDeltaConnection {
|
|
|
174
175
|
const socketReferenceKey = enableMultiplexing ? key : `${key},${tenantId},${documentId}`;
|
|
175
176
|
const socketReference = OdspDocumentDeltaConnection.getOrCreateSocketIoReference(timeoutMs, socketReferenceKey, url, enableMultiplexing, tenantId, documentId, telemetryLogger);
|
|
176
177
|
const socket = socketReference.socket;
|
|
177
|
-
const connectionId = uuid();
|
|
178
178
|
const connectMessage = {
|
|
179
179
|
client,
|
|
180
180
|
id: documentId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspDocumentDeltaConnection.js","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.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 { TypedEventEmitter, performanceNow } from \"@fluid-internal/client-utils\";\nimport { IEvent } from \"@fluidframework/core-interfaces\";\nimport { assert, Deferred } from \"@fluidframework/core-utils/internal\";\nimport { DocumentDeltaConnection } from \"@fluidframework/driver-base/internal\";\nimport { IClient } from \"@fluidframework/driver-definitions\";\nimport {\n\tIAnyDriverError,\n\tIConnect,\n\tIDocumentMessage,\n\tINack,\n\tISentSignalMessage,\n\tISequencedDocumentMessage,\n\tISignalMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { createGenericNetworkError } from \"@fluidframework/driver-utils/internal\";\nimport { OdspError } from \"@fluidframework/odsp-driver-definitions/internal\";\nimport {\n\tIFluidErrorBase,\n\tITelemetryLoggerExt,\n\tloggerToMonitoringContext,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { Socket } from \"socket.io-client\";\nimport { v4 as uuid } from \"uuid\";\n\nimport { IFlushOpsResponse, IGetOpsResponse, IOdspSocketError } from \"./contracts.js\";\nimport { EpochTracker } from \"./epochTracker.js\";\nimport { errorObjectFromSocketError } from \"./odspError.js\";\nimport { pkgVersion } from \"./packageVersion.js\";\nimport { SocketIOClientStatic } from \"./socketModule.js\";\n\nconst protocolVersions = [\"^0.4.0\", \"^0.3.0\", \"^0.2.0\", \"^0.1.0\"];\nconst feature_get_ops = \"api_get_ops\";\nconst feature_flush_ops = \"api_flush_ops\";\n\nexport interface FlushResult {\n\tlastPersistedSequenceNumber?: number;\n\tretryAfter?: number;\n}\n\n// How long to wait before disconnecting the socket after the last reference is removed\n// This allows reconnection after receiving a nack to be smooth\nconst socketReferenceBufferTime = 2000;\n\ninterface ISocketEvents extends IEvent {\n\t(\n\t\tevent: \"disconnect\",\n\t\tlistener: (error: IFluidErrorBase & OdspError, clientId?: string) => void,\n\t);\n}\n\nclass SocketReference extends TypedEventEmitter<ISocketEvents> {\n\tprivate references: number = 1;\n\tprivate delayDeleteTimeout: ReturnType<typeof setTimeout> | undefined;\n\tprivate _socket: Socket | undefined;\n\n\t// When making decisions about socket reuse, we do not reuse disconnected socket.\n\t// But we want to differentiate the following case from disconnected case:\n\t// Socket that never connected and never failed, it's in \"attempting to connect\" mode\n\t// such sockets should be reused, despite socket.disconnected === true\n\tprivate isPendingInitialConnection = true;\n\n\t// Map of all existing socket io sockets. [url, tenantId, documentId] -> socket\n\tprivate static readonly socketIoSockets: Map<string, SocketReference> = new Map();\n\n\tpublic static find(key: string, logger: ITelemetryLoggerExt): SocketReference | undefined {\n\t\tconst socketReference = SocketReference.socketIoSockets.get(key);\n\n\t\t// Verify the socket is healthy before reusing it\n\t\tif (socketReference?.disconnected) {\n\t\t\t// The socket is in a bad state. fully remove the reference\n\t\t\tsocketReference.closeSocket();\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (socketReference) {\n\t\t\t// Clear the pending deletion if there is one\n\t\t\tsocketReference.clearTimer();\n\t\t\tsocketReference.references++;\n\t\t}\n\n\t\treturn socketReference;\n\t}\n\n\t/**\n\t * Removes a reference for the given key\n\t * Once the ref count hits 0, the socket is disconnected and removed\n\t */\n\tpublic removeSocketIoReference(): void {\n\t\tassert(this.references > 0, 0x09f /* \"No more socketIO refs to remove!\" */);\n\t\tthis.references--;\n\n\t\t// see comment in disconnected() getter\n\t\tthis.isPendingInitialConnection = false;\n\n\t\tif (this.disconnected) {\n\t\t\tthis.closeSocket();\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.references === 0 && this.delayDeleteTimeout === undefined) {\n\t\t\tthis.delayDeleteTimeout = setTimeout(() => {\n\t\t\t\t// We should not get here with active users.\n\t\t\t\tassert(this.references === 0, 0x0a0 /* \"Unexpected socketIO references on timeout\" */);\n\t\t\t\tthis.closeSocket();\n\t\t\t}, socketReferenceBufferTime);\n\t\t}\n\t}\n\n\tpublic get socket(): Socket {\n\t\tif (!this._socket) {\n\t\t\tthrow new Error(`Invalid socket for key \"${this.key}`);\n\t\t}\n\t\treturn this._socket;\n\t}\n\n\tpublic constructor(\n\t\tpublic readonly key: string,\n\t\tsocket: Socket,\n\t) {\n\t\tsuper();\n\n\t\tthis._socket = socket;\n\t\tassert(!SocketReference.socketIoSockets.has(key), 0x220 /* \"socket key collision\" */);\n\t\tSocketReference.socketIoSockets.set(key, this);\n\n\t\t// Server sends this event when it wants to disconnect a particular client in which case the client id would\n\t\t// be present or if it wants to disconnect all the clients. The server always closes the socket in case all\n\t\t// clients needs to be disconnected. So fully remove the socket reference in this case.\n\t\tsocket.on(\"server_disconnect\", this.serverDisconnectEventHandler);\n\t}\n\n\tprivate readonly serverDisconnectEventHandler = (\n\t\tsocketError: IOdspSocketError,\n\t\tclientId?: string,\n\t): void => {\n\t\t// Treat all errors as recoverable, and rely on joinSession / reconnection flow to\n\t\t// filter out retryable vs. non-retryable cases.\n\t\tconst error = errorObjectFromSocketError(socketError, \"server_disconnect\");\n\t\terror.addTelemetryProperties({ disconnectClientId: clientId });\n\t\terror.canRetry = true;\n\n\t\t// see comment in disconnected() getter\n\t\t// Setting it here to ensure socket reuse does not happen if new request to connect\n\t\t// comes in from \"disconnect\" listener below, before we close socket.\n\t\tthis.isPendingInitialConnection = false;\n\n\t\tif (clientId === undefined) {\n\t\t\t// We could first raise \"disconnect\" event, but that may result in socket reuse due to\n\t\t\t// new connection comming in. So, it's better to have more explicit flow to make it impossible.\n\t\t\tthis.closeSocket(error);\n\t\t} else {\n\t\t\tthis.emit(\"disconnect\", error, clientId);\n\t\t}\n\t};\n\n\tprivate clearTimer(): void {\n\t\tif (this.delayDeleteTimeout !== undefined) {\n\t\t\tclearTimeout(this.delayDeleteTimeout);\n\t\t\tthis.delayDeleteTimeout = undefined;\n\t\t}\n\t}\n\n\tpublic closeSocket(error?: IAnyDriverError): void {\n\t\tif (!this._socket) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._socket.off(\"server_disconnect\", this.serverDisconnectEventHandler);\n\t\tthis.clearTimer();\n\n\t\tassert(\n\t\t\tSocketReference.socketIoSockets.get(this.key) === this,\n\t\t\t0x0a1 /* \"Socket reference set unexpectedly does not point to this socket!\" */,\n\t\t);\n\n\t\t// First, remove socket to ensure no socket reuse is possible.\n\t\tSocketReference.socketIoSockets.delete(this.key);\n\n\t\t// Block access to socket. From now on, calls like flush() or requestOps()\n\t\t// Disconnect flow should be synchronous and result in system fully forgetting about this connection / socket.\n\t\tconst socket = this._socket;\n\t\tthis._socket = undefined;\n\n\t\t// Let all connections know they need to go through disconnect flow.\n\t\tthis.emit(\n\t\t\t\"disconnect\",\n\t\t\terror ??\n\t\t\t\tcreateGenericNetworkError(\n\t\t\t\t\t\"Socket closed without error\",\n\t\t\t\t\t{ canRetry: true },\n\t\t\t\t\t{ driverVersion: pkgVersion },\n\t\t\t\t),\n\t\t\tundefined /* clientId */,\n\t\t);\n\n\t\t// We should not have any users now, assuming synchronous disconnect flow in response to\n\t\t// \"disconnect\" event\n\t\tassert(\n\t\t\tthis.references === 0,\n\t\t\t0x412 /* Nobody should be connected to this socket at this point! */,\n\t\t);\n\n\t\tsocket.disconnect();\n\t}\n\n\tpublic get disconnected(): boolean {\n\t\tif (this._socket === undefined) {\n\t\t\treturn true;\n\t\t}\n\t\tif (this.socket.connected) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We have a socket that is not connected. Possible cases:\n\t\t// 1) It was connected some time ago and lost connection. We do not want to reuse it.\n\t\t// 2) It failed to connect (was never connected).\n\t\t// 3) It was just created and never had a chance to connect - connection is in process.\n\t\t// We have to differentiate 1 from 2-3 (specifically 1 & 3) in order to be able to reuse socket in #3.\n\t\t// We will use the fact that socket had some activity. I.e. if socket disconnected, or client stopped using\n\t\t// socket, then removeSocketIoReference() will be called for it, and it will be the indiction that it's not #3.\n\t\treturn !this.isPendingInitialConnection;\n\t}\n}\n\n/**\n * Represents a connection to a stream of delta updates\n */\nexport class OdspDocumentDeltaConnection extends DocumentDeltaConnection {\n\t/**\n\t * Create a OdspDocumentDeltaConnection\n\t * If url #1 fails to connect, will try url #2 if applicable.\n\t *\n\t * @param tenantId - the ID of the tenant\n\t * @param documentId - document ID\n\t * @param token - authorization token for storage service\n\t * @param client - information about the client\n\t * @param mode - mode of the client\n\t * @param url - websocket URL\n\t * @param telemetryLogger - optional telemetry logger\n\t * @param timeoutMs - time limit on making the connection\n\t * @param epochTracker - track epoch changes\n\t * @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache\n\t */\n\tpublic static async create(\n\t\ttenantId: string,\n\t\tdocumentId: string,\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\ttoken: string | null,\n\t\tclient: IClient,\n\t\turl: string,\n\t\ttelemetryLogger: ITelemetryLoggerExt,\n\t\ttimeoutMs: number,\n\t\tepochTracker: EpochTracker,\n\t\tsocketReferenceKeyPrefix: string | undefined,\n\t): Promise<OdspDocumentDeltaConnection> {\n\t\tconst mc = loggerToMonitoringContext(telemetryLogger);\n\n\t\t// enable multiplexing when the websocket url does not include the tenant/document id\n\t\tconst parsedUrl = new URL(url);\n\t\tconst enableMultiplexing =\n\t\t\t!parsedUrl.searchParams.has(\"documentId\") && !parsedUrl.searchParams.has(\"tenantId\");\n\n\t\t// do not include the specific tenant/doc id in the ref key when multiplexing\n\t\t// this will allow multiple documents to share the same websocket connection\n\t\tconst key = socketReferenceKeyPrefix ? `${socketReferenceKeyPrefix},${url}` : url;\n\t\tconst socketReferenceKey = enableMultiplexing ? key : `${key},${tenantId},${documentId}`;\n\n\t\tconst socketReference = OdspDocumentDeltaConnection.getOrCreateSocketIoReference(\n\t\t\ttimeoutMs,\n\t\t\tsocketReferenceKey,\n\t\t\turl,\n\t\t\tenableMultiplexing,\n\t\t\ttenantId,\n\t\t\tdocumentId,\n\t\t\ttelemetryLogger,\n\t\t);\n\n\t\tconst socket = socketReference.socket;\n\t\tconst connectionId = uuid();\n\t\tconst connectMessage: IConnect = {\n\t\t\tclient,\n\t\t\tid: documentId,\n\t\t\tmode: client.mode,\n\t\t\ttenantId,\n\t\t\ttoken, // Token is going to indicate tenant level information, etc...\n\t\t\tversions: protocolVersions,\n\t\t\tdriverVersion: pkgVersion,\n\t\t\tnonce: connectionId,\n\t\t\tepoch: epochTracker.fluidEpoch,\n\t\t\trelayUserAgent: [client.details.environment, ` driverVersion:${pkgVersion}`].join(\";\"),\n\t\t};\n\n\t\tconnectMessage.supportedFeatures = {};\n\n\t\t// Reference to this client supporting get_ops flow.\n\t\tif (mc.config.getBoolean(\"Fluid.Driver.Odsp.GetOpsEnabled\") !== false) {\n\t\t\tconnectMessage.supportedFeatures[feature_get_ops] = true;\n\t\t}\n\n\t\tconst deltaConnection = new OdspDocumentDeltaConnection(\n\t\t\tsocket,\n\t\t\tdocumentId,\n\t\t\tsocketReference,\n\t\t\ttelemetryLogger,\n\t\t\tenableMultiplexing,\n\t\t\tconnectionId,\n\t\t);\n\n\t\ttry {\n\t\t\tawait deltaConnection.initialize(connectMessage, timeoutMs);\n\t\t\tawait epochTracker.validateEpoch(deltaConnection.details.epoch, \"push\");\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t} catch (error: any) {\n\t\t\tif (error !== null && typeof error === \"object\") {\n\t\t\t\t// We have to special-case error types here in terms of what is re-triable.\n\t\t\t\t// These errors have to re-retried, we just need new joinSession result to connect to right server:\n\t\t\t\t// 400: Invalid tenant or document id. The WebSocket is connected to a different document\n\t\t\t\t// Document is full (with retryAfter)\n\t\t\t\t// 404: Invalid document. The document \\\"local/w1-...\\\" does not exist\n\t\t\t\t// But this has to stay not-retriable:\n\t\t\t\t// 406: Unsupported client protocol. This path is the only gatekeeper, have to fail!\n\t\t\t\t// 409: Epoch Version Mismatch. Client epoch and server epoch does not match, so app needs\n\t\t\t\t// to be refreshed.\n\t\t\t\t// This one is fine either way\n\t\t\t\t// 401/403: Code will retry once with new token either way, then it becomes fatal - on this path\n\t\t\t\t// and on join Session path.\n\t\t\t\t// 501: (Fluid not enabled): this is fine either way, as joinSession is gatekeeper\n\t\t\t\t// eslint-disable-next-line unicorn/no-lonely-if, @typescript-eslint/no-unsafe-member-access\n\t\t\t\tif (error.statusCode === 400 || error.statusCode === 404) {\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\t\terror.canRetry = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn deltaConnection;\n\t}\n\n\tprivate socketReference: SocketReference | undefined;\n\n\tprivate readonly requestOpsNoncePrefix: string;\n\tprivate pushCallCounter = 0;\n\tprivate readonly getOpsMap: Map<string, { start: number; from: number; to: number }> =\n\t\tnew Map();\n\tprivate flushOpNonce: string | undefined;\n\tprivate flushDeferred: Deferred<FlushResult> | undefined;\n\tprivate connectionNotYetDisposedTimeout: ReturnType<typeof setTimeout> | undefined;\n\t// Due to socket reuse(multiplexing), we can get \"disconnect\" event from other clients in the socket reference.\n\t// So, a race condition could happen, where this client is establishing connection and listening for \"connect_document_success\"\n\t// on the socket among other events, but we get \"disconnect\" event on the socket reference from other clients, in which case,\n\t// we dispose connection object and stop listening to further events on the socket. Due to this we get stuck as the connection\n\t// is not yet established and so we don't return any connection object to the client(connection manager). So, we remain stuck.\n\t// In order to handle this, we use this deferred promise to keep track of connection initialization and reject this promise with\n\t// error in the disconnectCore so that the caller can know and handle the error.\n\tprivate connectionInitializeDeferredP: Deferred<void> | undefined;\n\n\t/**\n\t * Error raising for socket.io issues\n\t */\n\tprotected createErrorObject(\n\t\thandler: string,\n\t\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\n\t\terror?: any,\n\t\tcanRetry = true,\n\t): IAnyDriverError {\n\t\t// Note: we suspect the incoming error object is either:\n\t\t// - a socketError: add it to the OdspError object for driver to be able to parse it and reason over it.\n\t\t// - anything else: let base class handle it\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\treturn canRetry && Number.isInteger(error?.code) && typeof error?.message === \"string\"\n\t\t\t? errorObjectFromSocketError(error as IOdspSocketError, handler)\n\t\t\t: super.createErrorObject(handler, error, canRetry);\n\t}\n\n\t/**\n\t * Gets or create a socket io connection for the given key\n\t */\n\tprivate static getOrCreateSocketIoReference(\n\t\ttimeoutMs: number,\n\t\tkey: string,\n\t\turl: string,\n\t\tenableMultiplexing: boolean,\n\t\ttenantId: string,\n\t\tdocumentId: string,\n\t\tlogger: ITelemetryLoggerExt,\n\t): SocketReference {\n\t\t// eslint-disable-next-line unicorn/no-array-callback-reference, unicorn/no-array-method-this-argument\n\t\tconst existingSocketReference = SocketReference.find(key, logger);\n\t\tif (existingSocketReference) {\n\t\t\treturn existingSocketReference;\n\t\t}\n\n\t\tconst query = enableMultiplexing ? undefined : { documentId, tenantId };\n\n\t\tconst socket = SocketIOClientStatic(url, {\n\t\t\tmultiplex: false, // Don't rely on socket.io built-in multiplexing\n\t\t\tquery,\n\t\t\treconnection: false,\n\t\t\ttransports: [\"websocket\"],\n\t\t\ttimeout: timeoutMs,\n\t\t});\n\n\t\treturn new SocketReference(key, socket);\n\t}\n\n\t/**\n\t * @param socket - websocket to be used\n\t * @param documentId - ID of the document\n\t * @param details - details of the websocket connection\n\t * @param socketReferenceKey - socket reference key\n\t * @param enableMultiplexing - If the websocket is multiplexing multiple documents\n\t */\n\tprivate constructor(\n\t\tsocket: Socket,\n\t\tdocumentId: string,\n\t\tsocketReference: SocketReference,\n\t\tlogger: ITelemetryLoggerExt,\n\t\tprivate readonly enableMultiplexing?: boolean,\n\t\tconnectionId?: string,\n\t) {\n\t\tsuper(socket, documentId, logger, false, connectionId);\n\t\tthis.socketReference = socketReference;\n\t\tthis.requestOpsNoncePrefix = `${uuid()}-`;\n\t}\n\n\t/**\n\t * Retrieves ops from PUSH\n\t * @param from - inclusive\n\t * @param to - exclusive\n\t * @returns ops retrieved\n\t */\n\tpublic requestOps(from: number, to: number): void {\n\t\tassert(!this.socketReference?.disconnected, 0x413 /* non-active socket */);\n\n\t\t// Given that to is exclusive, we should be asking for at least something!\n\t\tassert(to > from, 0x272 /* \"empty request\" */);\n\n\t\t// PUSH may disable this functionality\n\t\t// back-compat: remove cast to any once latest version of IConnected is consumed\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n\t\tif ((this.details as any).supportedFeatures?.[feature_get_ops] !== true) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.pushCallCounter++;\n\t\tconst nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;\n\t\tconst start = performanceNow();\n\n\t\t// We may keep keep accumulating memory for nothing, if we are not getting responses.\n\t\t// Note that we should not have overlapping requests, as DeltaManager allows only one\n\t\t// outstanding request to storage, and that's the only way to get here.\n\t\t// But requests could be cancelled, and thus overlapping requests might be in the picture\n\t\t// If it happens, we do not care about stale requests.\n\t\t// So track some number of requests, but log if we get too many in flight - that likely\n\t\t// indicates an error somewhere.\n\t\tif (this.getOpsMap.size >= 5) {\n\t\t\tlet time = start;\n\t\t\tlet key: string | undefined;\n\t\t\tfor (const [keyCandidate, value] of this.getOpsMap.entries()) {\n\t\t\t\tif (value.start <= time || key === undefined) {\n\t\t\t\t\ttime = value.start;\n\t\t\t\t\tkey = keyCandidate;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst payloadToDelete = this.getOpsMap.get(key!)!;\n\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\teventName: \"GetOpsTooMany\",\n\t\t\t\tnonce,\n\t\t\t\tfrom: payloadToDelete.from,\n\t\t\t\tto: payloadToDelete.to,\n\t\t\t\tlength: payloadToDelete.to - payloadToDelete.from,\n\t\t\t\tduration: performanceNow() - payloadToDelete.start,\n\t\t\t});\n\t\t\tthis.getOpsMap.delete(key!);\n\t\t}\n\t\tthis.getOpsMap.set(nonce, {\n\t\t\tstart,\n\t\t\tfrom,\n\t\t\tto,\n\t\t});\n\t\tthis.socket.emit(\"get_ops\", this.clientId, {\n\t\t\tnonce,\n\t\t\tfrom,\n\t\t\tto: to - 1,\n\t\t});\n\t}\n\n\tpublic async flush(): Promise<FlushResult> {\n\t\tassert(!this.socketReference?.disconnected, 0x414 /* non-active socket */);\n\n\t\t// back-compat: remove cast to any once latest version of IConnected is consumed\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n\t\tif ((this.details as any).supportedFeatures?.[feature_flush_ops] !== true) {\n\t\t\t// Once single-commit summary is enabled end-to-end, flush support is a must!\n\t\t\t// The only alternative is change in design where SPO fetches ops from PUSH OR\n\t\t\t// summary includes required ops and SPO has some validation mechanism to ensure\n\t\t\t// they are not forged by client.\n\t\t\t// If design changes, we can reconsider it, but right now it's non-recoverable failure.\n\t\t\tthis.logger.sendErrorEvent({ eventName: \"FlushOpsNotSupported\" });\n\t\t\tthrow new Error(\n\t\t\t\t\"flush() API is not supported by PUSH, required for single-commit summaries\",\n\t\t\t);\n\t\t}\n\n\t\tthis.pushCallCounter++;\n\t\tconst nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;\n\t\t// There should be only one flush ops in flight, kicked out by upload summary workflow\n\t\t// That said, it could timeout and request could be repeated, so theoretically we can\n\t\t// get overlapping requests, but it should be very rare\n\t\tif (this.flushDeferred !== undefined) {\n\t\t\tthis.logger.sendErrorEvent({ eventName: \"FlushOpsTooMany\" });\n\t\t\tthis.flushDeferred.reject(\n\t\t\t\t\"process involving flush() was cancelled OR unsupported concurrency\",\n\t\t\t);\n\t\t}\n\t\tthis.socket.emit(\"flush_ops\", this.clientId, { nonce });\n\n\t\tthis.flushOpNonce = nonce;\n\t\tthis.flushDeferred = new Deferred<FlushResult>();\n\t\treturn this.flushDeferred.promise;\n\t}\n\n\tprotected disconnectHandler = (\n\t\terror: IFluidErrorBase & OdspError,\n\t\tclientId?: string,\n\t): void => {\n\t\tif (clientId === undefined || clientId === this.clientId) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: \"ServerDisconnect\",\n\t\t\t\t\tdriverVersion: pkgVersion,\n\t\t\t\t\tdetails: JSON.stringify({\n\t\t\t\t\t\t...this.getConnectionDetailsProps(),\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t\terror,\n\t\t\t);\n\t\t\tthis.disconnect(error);\n\t\t}\n\t};\n\n\tprotected async initialize(connectMessage: IConnect, timeout: number): Promise<void> {\n\t\tassert(!this.socketReference?.disconnected, 0x415 /* non-active socket */);\n\n\t\tif (this.enableMultiplexing) {\n\t\t\t// multiplex compatible early handlers\n\t\t\tthis.earlyOpHandler = (\n\t\t\t\tmessageDocumentId: string,\n\t\t\t\tmsgs: ISequencedDocumentMessage[],\n\t\t\t): void => {\n\t\t\t\tif (this.documentId === messageDocumentId) {\n\t\t\t\t\tthis.queuedMessages.push(...msgs);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.earlySignalHandler = (\n\t\t\t\tmsg: ISignalMessage | ISignalMessage[],\n\t\t\t\tmessageDocumentId?: string,\n\t\t\t): void => {\n\t\t\t\tif (messageDocumentId === undefined || messageDocumentId === this.documentId) {\n\t\t\t\t\tif (Array.isArray(msg)) {\n\t\t\t\t\t\tthis.queuedSignals.push(...msg);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.queuedSignals.push(msg);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tthis.socketReference!.on(\"disconnect\", this.disconnectHandler);\n\n\t\tthis.addTrackedListener(\"get_ops_response\", (result: IGetOpsResponse) => {\n\t\t\tconst messages = result.messages;\n\t\t\tconst data = this.getOpsMap.get(result.nonce);\n\t\t\t// Due to socket multiplexing, this client may not have asked for any data\n\t\t\t// If so, there it most likely does not need these ops (otherwise it already asked for them)\n\t\t\t// Also we may have deleted entry in this.getOpsMap due to too many requests and too slow response.\n\t\t\t// But not processing such result may push us into infinite loop of fast requests and dropping all responses\n\t\t\tif (data !== undefined || result.nonce.startsWith(this.requestOpsNoncePrefix)) {\n\t\t\t\tthis.getOpsMap.delete(result.nonce);\n\t\t\t\tconst common = {\n\t\t\t\t\teventName: \"GetOps\",\n\t\t\t\t\t// We need nonce only to pair with GetOpsTooMany events, i.e. when record was deleted\n\t\t\t\t\tnonce: data === undefined ? result.nonce : undefined,\n\t\t\t\t\tcode: result.code,\n\t\t\t\t\tfrom: data?.from,\n\t\t\t\t\tto: data?.to,\n\t\t\t\t\tduration: data === undefined ? undefined : performanceNow() - data.start,\n\t\t\t\t};\n\t\t\t\tif (messages !== undefined && messages.length > 0) {\n\t\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\t\t...common,\n\t\t\t\t\t\tfirst: messages[0].sequenceNumber,\n\t\t\t\t\t\tlast: messages[messages.length - 1].sequenceNumber,\n\t\t\t\t\t\tlength: messages.length,\n\t\t\t\t\t});\n\t\t\t\t\tthis.emit(\"op\", this.documentId, messages);\n\t\t\t\t} else {\n\t\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\t\t...common,\n\t\t\t\t\t\tlength: 0,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.addTrackedListener(\"flush_ops_response\", (result: IFlushOpsResponse) => {\n\t\t\tif (this.flushOpNonce === result.nonce) {\n\t\t\t\tconst seq = result.lastPersistedSequenceNumber;\n\t\t\t\tlet category: \"generic\" | \"error\" = \"generic\";\n\t\t\t\tif (result.lastPersistedSequenceNumber === undefined || result.code !== 200) {\n\t\t\t\t\tswitch (result.code) {\n\t\t\t\t\t\tcase 409:\n\t\t\t\t\t\tcase 429: {\n\t\t\t\t\t\t\tcategory = \"error\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 204: {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\tcategory = \"error\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"FlushResult\",\n\t\t\t\t\tcode: result.code,\n\t\t\t\t\tsequenceNumber: seq,\n\t\t\t\t\tcategory,\n\t\t\t\t});\n\t\t\t\tthis.flushDeferred!.resolve(result);\n\t\t\t\tthis.flushDeferred = undefined;\n\t\t\t\tthis.flushOpNonce = undefined;\n\t\t\t}\n\t\t});\n\n\t\tthis.connectionInitializeDeferredP = new Deferred<void>();\n\n\t\tsuper\n\t\t\t.initialize(connectMessage, timeout)\n\t\t\t.then(() => this.connectionInitializeDeferredP?.resolve())\n\t\t\t.catch((error) => this.connectionInitializeDeferredP?.reject(error));\n\n\t\tawait this.connectionInitializeDeferredP.promise.finally(() => {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"ConnectionAttemptInfo\",\n\t\t\t\t...this.getConnectionDetailsProps(),\n\t\t\t});\n\t\t});\n\t}\n\n\tprotected addTrackedListener(event: string, listener: (...args: any[]) => void): void {\n\t\t// override some event listeners in order to support multiple documents/clients over the same websocket\n\t\tswitch (event) {\n\t\t\tcase \"op\": {\n\t\t\t\t// per document op handling\n\t\t\t\tsuper.addTrackedListener(\n\t\t\t\t\tevent,\n\t\t\t\t\t(documentId: string, msgs: ISequencedDocumentMessage[]) => {\n\t\t\t\t\t\tif (!this.enableMultiplexing || this.documentId === documentId) {\n\t\t\t\t\t\t\tlistener(documentId, msgs);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"signal\": {\n\t\t\t\t// per document signal handling\n\t\t\t\tsuper.addTrackedListener(\n\t\t\t\t\tevent,\n\t\t\t\t\t(msg: ISignalMessage | ISignalMessage[], documentId?: string) => {\n\t\t\t\t\t\tif (!this.enableMultiplexing) {\n\t\t\t\t\t\t\tlistener(msg, documentId);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\tdocumentId !== undefined,\n\t\t\t\t\t\t\t0xa65 /* documentId is required when multiplexing is enabled. */,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (documentId !== this.documentId) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst msgs = Array.isArray(msg) ? msg : [msg];\n\n\t\t\t\t\t\tconst filteredMsgs = msgs.filter(\n\t\t\t\t\t\t\t(m) => !m.targetClientId || m.targetClientId === this.clientId,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (filteredMsgs.length > 0) {\n\t\t\t\t\t\t\t// This ternary is needed for signal-based layer compat tests to pass,\n\t\t\t\t\t\t\t// specifically the layer version combination where you have an old loader and the most recent driver layer.\n\t\t\t\t\t\t\t// Old loader doesn't send or receive batched signals (ISignalMessage[]),\n\t\t\t\t\t\t\t// so only individual ISignalMessage's should be passed when there's one element for backcompat.\n\t\t\t\t\t\t\tlistener(filteredMsgs.length === 1 ? filteredMsgs[0] : filteredMsgs, documentId);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"nack\": {\n\t\t\t\t// per client / document nack handling\n\t\t\t\tsuper.addTrackedListener(event, (clientIdOrDocumentId: string, nacks: INack[]) => {\n\t\t\t\t\tconst handle =\n\t\t\t\t\t\tclientIdOrDocumentId.length === 0 ||\n\t\t\t\t\t\tclientIdOrDocumentId === this.documentId ||\n\t\t\t\t\t\tclientIdOrDocumentId === this.clientId;\n\t\t\t\t\tconst { code, type, message, retryAfter } = nacks[0]?.content ?? {};\n\t\t\t\t\tconst { clientSequenceNumber, referenceSequenceNumber } = nacks[0]?.operation ?? {};\n\t\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"ServerNack\",\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\tmessage,\n\t\t\t\t\t\tretryAfterSeconds: retryAfter,\n\t\t\t\t\t\tclientId: this.clientId,\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\tclientSequenceNumber,\n\t\t\t\t\t\treferenceSequenceNumber,\n\t\t\t\t\t\topType: nacks[0]?.operation?.type,\n\t\t\t\t\t});\n\t\t\t\t\tif (handle) {\n\t\t\t\t\t\tthis.emit(\"nack\", clientIdOrDocumentId, nacks);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tsuper.addTrackedListener(event, listener);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic get disposed(): boolean {\n\t\tif (!(this._disposed || this.socket.connected)) {\n\t\t\t// Send error event if this connection is not yet disposed after socket is disconnected for 15s.\n\t\t\t// eslint-disable-next-line unicorn/no-lonely-if\n\t\t\tif (this.connectionNotYetDisposedTimeout === undefined) {\n\t\t\t\tthis.connectionNotYetDisposedTimeout = setTimeout(() => {\n\t\t\t\t\tif (!this._disposed) {\n\t\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\t\teventName: \"ConnectionNotYetDisposed\",\n\t\t\t\t\t\t\tdriverVersion: pkgVersion,\n\t\t\t\t\t\t\tdetails: JSON.stringify({\n\t\t\t\t\t\t\t\t...this.getConnectionDetailsProps(),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}, 15000);\n\t\t\t}\n\t\t}\n\t\treturn this._disposed;\n\t}\n\n\t/**\n\t * Returns true in case the connection is not yet disposed and the socket is also connected. The expectation is\n\t * that it will be called only after connection is fully established. i.e. there should no way to submit an op\n\t * while we are connecting, as connection object is not exposed to Loader layer until connection is established.\n\t */\n\tprivate get connected(): boolean {\n\t\treturn !this.disposed && this.socket.connected;\n\t}\n\n\tprotected override emitMessages(type: \"submitOp\", messages: IDocumentMessage[][]): void;\n\tprotected override emitMessages(\n\t\ttype: \"submitSignal\",\n\t\tmessages: string[][] | ISentSignalMessage[],\n\t): void;\n\tprotected override emitMessages(type: string, messages: unknown): void {\n\t\t// Only submit the op/signals if we are connected.\n\t\tif (this.connected) {\n\t\t\tthis.socket.emit(type, this.clientId, messages);\n\t\t}\n\t}\n\n\t/**\n\t * Submits a new delta operation to the server\n\t * @param message - delta operation to submit\n\t */\n\tpublic submit(messages: IDocumentMessage[]): void {\n\t\tthis.emitMessages(\"submitOp\", [messages]);\n\t}\n\n\t/**\n\t * Submits a new signal to the server\n\t *\n\t * @param content - Content of the signal.\n\t * @param targetClientId - When specified, the signal is only sent to the provided client id.\n\t */\n\tpublic submitSignal(content: string, targetClientId?: string): void {\n\t\tconst signal: ISentSignalMessage = {\n\t\t\tcontent,\n\t\t\ttargetClientId,\n\t\t};\n\n\t\tthis.emitMessages(\"submitSignal\", [signal]);\n\t}\n\n\t/**\n\t * Critical path where we need to also close the socket for an error.\n\t * @param error - Error causing the socket to close.\n\t */\n\tprotected closeSocketCore(error: IAnyDriverError): void {\n\t\tconst socket = this.socketReference;\n\t\tassert(socket !== undefined, 0x416 /* reentrancy not supported in close socket */);\n\t\tsocket.closeSocket(error);\n\t\tassert(\n\t\t\tthis.socketReference === undefined,\n\t\t\t0x417 /* disconnect flow did not work correctly */,\n\t\t);\n\t}\n\n\t/**\n\t * Disconnect from the websocket\n\t */\n\tprotected disconnectCore(err: IAnyDriverError): void {\n\t\tconst socket = this.socketReference;\n\t\tassert(socket !== undefined, 0x0a2 /* \"reentrancy not supported!\" */);\n\t\tthis.socketReference = undefined;\n\n\t\tsocket.off(\"disconnect\", this.disconnectHandler);\n\t\tif (this.hasDetails) {\n\t\t\t// tell the server we are disconnecting this client from the document\n\t\t\tthis.socket.emit(\"disconnect_document\", this.clientId, this.documentId);\n\t\t}\n\n\t\tsocket.removeSocketIoReference();\n\t\tif (\n\t\t\tthis.connectionInitializeDeferredP !== undefined &&\n\t\t\t!this.connectionInitializeDeferredP.isCompleted\n\t\t) {\n\t\t\tthis.connectionInitializeDeferredP.reject(err);\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"odspDocumentDeltaConnection.js","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.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 { TypedEventEmitter, performanceNow } from \"@fluid-internal/client-utils\";\nimport { IEvent } from \"@fluidframework/core-interfaces\";\nimport { assert, Deferred } from \"@fluidframework/core-utils/internal\";\nimport { DocumentDeltaConnection } from \"@fluidframework/driver-base/internal\";\nimport { IClient } from \"@fluidframework/driver-definitions\";\nimport {\n\tIAnyDriverError,\n\tIConnect,\n\tIDocumentMessage,\n\tINack,\n\tISentSignalMessage,\n\tISequencedDocumentMessage,\n\tISignalMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { createGenericNetworkError } from \"@fluidframework/driver-utils/internal\";\nimport { OdspError } from \"@fluidframework/odsp-driver-definitions/internal\";\nimport {\n\tIFluidErrorBase,\n\tITelemetryLoggerExt,\n\tloggerToMonitoringContext,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { Socket } from \"socket.io-client\";\nimport { v4 as uuid } from \"uuid\";\n\nimport { IFlushOpsResponse, IGetOpsResponse, IOdspSocketError } from \"./contracts.js\";\nimport { EpochTracker } from \"./epochTracker.js\";\nimport { errorObjectFromSocketError } from \"./odspError.js\";\nimport { pkgVersion } from \"./packageVersion.js\";\nimport { SocketIOClientStatic } from \"./socketModule.js\";\n\nconst protocolVersions = [\"^0.4.0\", \"^0.3.0\", \"^0.2.0\", \"^0.1.0\"];\nconst feature_get_ops = \"api_get_ops\";\nconst feature_flush_ops = \"api_flush_ops\";\n\nexport interface FlushResult {\n\tlastPersistedSequenceNumber?: number;\n\tretryAfter?: number;\n}\n\n// How long to wait before disconnecting the socket after the last reference is removed\n// This allows reconnection after receiving a nack to be smooth\nconst socketReferenceBufferTime = 2000;\n\ninterface ISocketEvents extends IEvent {\n\t(\n\t\tevent: \"disconnect\",\n\t\tlistener: (error: IFluidErrorBase & OdspError, clientId?: string) => void,\n\t);\n}\n\nclass SocketReference extends TypedEventEmitter<ISocketEvents> {\n\tprivate references: number = 1;\n\tprivate delayDeleteTimeout: ReturnType<typeof setTimeout> | undefined;\n\tprivate _socket: Socket | undefined;\n\n\t// When making decisions about socket reuse, we do not reuse disconnected socket.\n\t// But we want to differentiate the following case from disconnected case:\n\t// Socket that never connected and never failed, it's in \"attempting to connect\" mode\n\t// such sockets should be reused, despite socket.disconnected === true\n\tprivate isPendingInitialConnection = true;\n\n\t// Map of all existing socket io sockets. [url, tenantId, documentId] -> socket\n\tprivate static readonly socketIoSockets: Map<string, SocketReference> = new Map();\n\n\tpublic static find(key: string, logger: ITelemetryLoggerExt): SocketReference | undefined {\n\t\tconst socketReference = SocketReference.socketIoSockets.get(key);\n\n\t\t// Verify the socket is healthy before reusing it\n\t\tif (socketReference?.disconnected) {\n\t\t\t// The socket is in a bad state. fully remove the reference\n\t\t\tsocketReference.closeSocket();\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (socketReference) {\n\t\t\t// Clear the pending deletion if there is one\n\t\t\tsocketReference.clearTimer();\n\t\t\tsocketReference.references++;\n\t\t}\n\n\t\treturn socketReference;\n\t}\n\n\t/**\n\t * Removes a reference for the given key\n\t * Once the ref count hits 0, the socket is disconnected and removed\n\t */\n\tpublic removeSocketIoReference(): void {\n\t\tassert(this.references > 0, 0x09f /* \"No more socketIO refs to remove!\" */);\n\t\tthis.references--;\n\n\t\t// see comment in disconnected() getter\n\t\tthis.isPendingInitialConnection = false;\n\n\t\tif (this.disconnected) {\n\t\t\tthis.closeSocket();\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.references === 0 && this.delayDeleteTimeout === undefined) {\n\t\t\tthis.delayDeleteTimeout = setTimeout(() => {\n\t\t\t\t// We should not get here with active users.\n\t\t\t\tassert(this.references === 0, 0x0a0 /* \"Unexpected socketIO references on timeout\" */);\n\t\t\t\tthis.closeSocket();\n\t\t\t}, socketReferenceBufferTime);\n\t\t}\n\t}\n\n\tpublic get socket(): Socket {\n\t\tif (!this._socket) {\n\t\t\tthrow new Error(`Invalid socket for key \"${this.key}`);\n\t\t}\n\t\treturn this._socket;\n\t}\n\n\tpublic constructor(\n\t\tpublic readonly key: string,\n\t\tsocket: Socket,\n\t) {\n\t\tsuper();\n\n\t\tthis._socket = socket;\n\t\tassert(!SocketReference.socketIoSockets.has(key), 0x220 /* \"socket key collision\" */);\n\t\tSocketReference.socketIoSockets.set(key, this);\n\n\t\t// Server sends this event when it wants to disconnect a particular client in which case the client id would\n\t\t// be present or if it wants to disconnect all the clients. The server always closes the socket in case all\n\t\t// clients needs to be disconnected. So fully remove the socket reference in this case.\n\t\tsocket.on(\"server_disconnect\", this.serverDisconnectEventHandler);\n\t}\n\n\tprivate readonly serverDisconnectEventHandler = (\n\t\tsocketError: IOdspSocketError,\n\t\tclientId?: string,\n\t): void => {\n\t\t// Treat all errors as recoverable, and rely on joinSession / reconnection flow to\n\t\t// filter out retryable vs. non-retryable cases.\n\t\tconst error = errorObjectFromSocketError(socketError, \"server_disconnect\");\n\t\terror.addTelemetryProperties({ disconnectClientId: clientId });\n\t\terror.canRetry = true;\n\n\t\t// see comment in disconnected() getter\n\t\t// Setting it here to ensure socket reuse does not happen if new request to connect\n\t\t// comes in from \"disconnect\" listener below, before we close socket.\n\t\tthis.isPendingInitialConnection = false;\n\n\t\tif (clientId === undefined) {\n\t\t\t// We could first raise \"disconnect\" event, but that may result in socket reuse due to\n\t\t\t// new connection comming in. So, it's better to have more explicit flow to make it impossible.\n\t\t\tthis.closeSocket(error);\n\t\t} else {\n\t\t\tthis.emit(\"disconnect\", error, clientId);\n\t\t}\n\t};\n\n\tprivate clearTimer(): void {\n\t\tif (this.delayDeleteTimeout !== undefined) {\n\t\t\tclearTimeout(this.delayDeleteTimeout);\n\t\t\tthis.delayDeleteTimeout = undefined;\n\t\t}\n\t}\n\n\tpublic closeSocket(error?: IAnyDriverError): void {\n\t\tif (!this._socket) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._socket.off(\"server_disconnect\", this.serverDisconnectEventHandler);\n\t\tthis.clearTimer();\n\n\t\tassert(\n\t\t\tSocketReference.socketIoSockets.get(this.key) === this,\n\t\t\t0x0a1 /* \"Socket reference set unexpectedly does not point to this socket!\" */,\n\t\t);\n\n\t\t// First, remove socket to ensure no socket reuse is possible.\n\t\tSocketReference.socketIoSockets.delete(this.key);\n\n\t\t// Block access to socket. From now on, calls like flush() or requestOps()\n\t\t// Disconnect flow should be synchronous and result in system fully forgetting about this connection / socket.\n\t\tconst socket = this._socket;\n\t\tthis._socket = undefined;\n\n\t\t// Let all connections know they need to go through disconnect flow.\n\t\tthis.emit(\n\t\t\t\"disconnect\",\n\t\t\terror ??\n\t\t\t\tcreateGenericNetworkError(\n\t\t\t\t\t\"Socket closed without error\",\n\t\t\t\t\t{ canRetry: true },\n\t\t\t\t\t{ driverVersion: pkgVersion },\n\t\t\t\t),\n\t\t\tundefined /* clientId */,\n\t\t);\n\n\t\t// We should not have any users now, assuming synchronous disconnect flow in response to\n\t\t// \"disconnect\" event\n\t\tassert(\n\t\t\tthis.references === 0,\n\t\t\t0x412 /* Nobody should be connected to this socket at this point! */,\n\t\t);\n\n\t\tsocket.disconnect();\n\t}\n\n\tpublic get disconnected(): boolean {\n\t\tif (this._socket === undefined) {\n\t\t\treturn true;\n\t\t}\n\t\tif (this.socket.connected) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We have a socket that is not connected. Possible cases:\n\t\t// 1) It was connected some time ago and lost connection. We do not want to reuse it.\n\t\t// 2) It failed to connect (was never connected).\n\t\t// 3) It was just created and never had a chance to connect - connection is in process.\n\t\t// We have to differentiate 1 from 2-3 (specifically 1 & 3) in order to be able to reuse socket in #3.\n\t\t// We will use the fact that socket had some activity. I.e. if socket disconnected, or client stopped using\n\t\t// socket, then removeSocketIoReference() will be called for it, and it will be the indiction that it's not #3.\n\t\treturn !this.isPendingInitialConnection;\n\t}\n}\n\n/**\n * Represents a connection to a stream of delta updates\n */\nexport class OdspDocumentDeltaConnection extends DocumentDeltaConnection {\n\t/**\n\t * Create a OdspDocumentDeltaConnection\n\t * If url #1 fails to connect, will try url #2 if applicable.\n\t *\n\t * @param tenantId - the ID of the tenant\n\t * @param documentId - document ID\n\t * @param token - authorization token for storage service\n\t * @param client - information about the client\n\t * @param mode - mode of the client\n\t * @param url - websocket URL\n\t * @param telemetryLogger - optional telemetry logger\n\t * @param timeoutMs - time limit on making the connection\n\t * @param epochTracker - track epoch changes\n\t * @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache\n\t * @param connectionId - (optional) connection ID for the connection\n\t */\n\tpublic static async create(\n\t\ttenantId: string,\n\t\tdocumentId: string,\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\ttoken: string | null,\n\t\tclient: IClient,\n\t\turl: string,\n\t\ttelemetryLogger: ITelemetryLoggerExt,\n\t\ttimeoutMs: number,\n\t\tepochTracker: EpochTracker,\n\t\tsocketReferenceKeyPrefix: string | undefined,\n\t\tconnectionId: string = uuid(),\n\t): Promise<OdspDocumentDeltaConnection> {\n\t\tconst mc = loggerToMonitoringContext(telemetryLogger);\n\n\t\t// enable multiplexing when the websocket url does not include the tenant/document id\n\t\tconst parsedUrl = new URL(url);\n\t\tconst enableMultiplexing =\n\t\t\t!parsedUrl.searchParams.has(\"documentId\") && !parsedUrl.searchParams.has(\"tenantId\");\n\n\t\t// do not include the specific tenant/doc id in the ref key when multiplexing\n\t\t// this will allow multiple documents to share the same websocket connection\n\t\tconst key = socketReferenceKeyPrefix ? `${socketReferenceKeyPrefix},${url}` : url;\n\t\tconst socketReferenceKey = enableMultiplexing ? key : `${key},${tenantId},${documentId}`;\n\n\t\tconst socketReference = OdspDocumentDeltaConnection.getOrCreateSocketIoReference(\n\t\t\ttimeoutMs,\n\t\t\tsocketReferenceKey,\n\t\t\turl,\n\t\t\tenableMultiplexing,\n\t\t\ttenantId,\n\t\t\tdocumentId,\n\t\t\ttelemetryLogger,\n\t\t);\n\n\t\tconst socket = socketReference.socket;\n\t\tconst connectMessage: IConnect = {\n\t\t\tclient,\n\t\t\tid: documentId,\n\t\t\tmode: client.mode,\n\t\t\ttenantId,\n\t\t\ttoken, // Token is going to indicate tenant level information, etc...\n\t\t\tversions: protocolVersions,\n\t\t\tdriverVersion: pkgVersion,\n\t\t\tnonce: connectionId,\n\t\t\tepoch: epochTracker.fluidEpoch,\n\t\t\trelayUserAgent: [client.details.environment, ` driverVersion:${pkgVersion}`].join(\";\"),\n\t\t};\n\n\t\tconnectMessage.supportedFeatures = {};\n\n\t\t// Reference to this client supporting get_ops flow.\n\t\tif (mc.config.getBoolean(\"Fluid.Driver.Odsp.GetOpsEnabled\") !== false) {\n\t\t\tconnectMessage.supportedFeatures[feature_get_ops] = true;\n\t\t}\n\n\t\tconst deltaConnection = new OdspDocumentDeltaConnection(\n\t\t\tsocket,\n\t\t\tdocumentId,\n\t\t\tsocketReference,\n\t\t\ttelemetryLogger,\n\t\t\tenableMultiplexing,\n\t\t\tconnectionId,\n\t\t);\n\n\t\ttry {\n\t\t\tawait deltaConnection.initialize(connectMessage, timeoutMs);\n\t\t\tawait epochTracker.validateEpoch(deltaConnection.details.epoch, \"push\");\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t} catch (error: any) {\n\t\t\tif (error !== null && typeof error === \"object\") {\n\t\t\t\t// We have to special-case error types here in terms of what is re-triable.\n\t\t\t\t// These errors have to re-retried, we just need new joinSession result to connect to right server:\n\t\t\t\t// 400: Invalid tenant or document id. The WebSocket is connected to a different document\n\t\t\t\t// Document is full (with retryAfter)\n\t\t\t\t// 404: Invalid document. The document \\\"local/w1-...\\\" does not exist\n\t\t\t\t// But this has to stay not-retriable:\n\t\t\t\t// 406: Unsupported client protocol. This path is the only gatekeeper, have to fail!\n\t\t\t\t// 409: Epoch Version Mismatch. Client epoch and server epoch does not match, so app needs\n\t\t\t\t// to be refreshed.\n\t\t\t\t// This one is fine either way\n\t\t\t\t// 401/403: Code will retry once with new token either way, then it becomes fatal - on this path\n\t\t\t\t// and on join Session path.\n\t\t\t\t// 501: (Fluid not enabled): this is fine either way, as joinSession is gatekeeper\n\t\t\t\t// eslint-disable-next-line unicorn/no-lonely-if, @typescript-eslint/no-unsafe-member-access\n\t\t\t\tif (error.statusCode === 400 || error.statusCode === 404) {\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\t\terror.canRetry = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn deltaConnection;\n\t}\n\n\tprivate socketReference: SocketReference | undefined;\n\n\tprivate readonly requestOpsNoncePrefix: string;\n\tprivate pushCallCounter = 0;\n\tprivate readonly getOpsMap: Map<string, { start: number; from: number; to: number }> =\n\t\tnew Map();\n\tprivate flushOpNonce: string | undefined;\n\tprivate flushDeferred: Deferred<FlushResult> | undefined;\n\tprivate connectionNotYetDisposedTimeout: ReturnType<typeof setTimeout> | undefined;\n\t// Due to socket reuse(multiplexing), we can get \"disconnect\" event from other clients in the socket reference.\n\t// So, a race condition could happen, where this client is establishing connection and listening for \"connect_document_success\"\n\t// on the socket among other events, but we get \"disconnect\" event on the socket reference from other clients, in which case,\n\t// we dispose connection object and stop listening to further events on the socket. Due to this we get stuck as the connection\n\t// is not yet established and so we don't return any connection object to the client(connection manager). So, we remain stuck.\n\t// In order to handle this, we use this deferred promise to keep track of connection initialization and reject this promise with\n\t// error in the disconnectCore so that the caller can know and handle the error.\n\tprivate connectionInitializeDeferredP: Deferred<void> | undefined;\n\n\t/**\n\t * Error raising for socket.io issues\n\t */\n\tprotected createErrorObject(\n\t\thandler: string,\n\t\t// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\n\t\terror?: any,\n\t\tcanRetry = true,\n\t): IAnyDriverError {\n\t\t// Note: we suspect the incoming error object is either:\n\t\t// - a socketError: add it to the OdspError object for driver to be able to parse it and reason over it.\n\t\t// - anything else: let base class handle it\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\treturn canRetry && Number.isInteger(error?.code) && typeof error?.message === \"string\"\n\t\t\t? errorObjectFromSocketError(error as IOdspSocketError, handler)\n\t\t\t: super.createErrorObject(handler, error, canRetry);\n\t}\n\n\t/**\n\t * Gets or create a socket io connection for the given key\n\t */\n\tprivate static getOrCreateSocketIoReference(\n\t\ttimeoutMs: number,\n\t\tkey: string,\n\t\turl: string,\n\t\tenableMultiplexing: boolean,\n\t\ttenantId: string,\n\t\tdocumentId: string,\n\t\tlogger: ITelemetryLoggerExt,\n\t): SocketReference {\n\t\t// eslint-disable-next-line unicorn/no-array-callback-reference, unicorn/no-array-method-this-argument\n\t\tconst existingSocketReference = SocketReference.find(key, logger);\n\t\tif (existingSocketReference) {\n\t\t\treturn existingSocketReference;\n\t\t}\n\n\t\tconst query = enableMultiplexing ? undefined : { documentId, tenantId };\n\n\t\tconst socket = SocketIOClientStatic(url, {\n\t\t\tmultiplex: false, // Don't rely on socket.io built-in multiplexing\n\t\t\tquery,\n\t\t\treconnection: false,\n\t\t\ttransports: [\"websocket\"],\n\t\t\ttimeout: timeoutMs,\n\t\t});\n\n\t\treturn new SocketReference(key, socket);\n\t}\n\n\t/**\n\t * @param socket - websocket to be used\n\t * @param documentId - ID of the document\n\t * @param details - details of the websocket connection\n\t * @param socketReferenceKey - socket reference key\n\t * @param enableMultiplexing - If the websocket is multiplexing multiple documents\n\t */\n\tprivate constructor(\n\t\tsocket: Socket,\n\t\tdocumentId: string,\n\t\tsocketReference: SocketReference,\n\t\tlogger: ITelemetryLoggerExt,\n\t\tprivate readonly enableMultiplexing?: boolean,\n\t\tconnectionId?: string,\n\t) {\n\t\tsuper(socket, documentId, logger, false, connectionId);\n\t\tthis.socketReference = socketReference;\n\t\tthis.requestOpsNoncePrefix = `${uuid()}-`;\n\t}\n\n\t/**\n\t * Retrieves ops from PUSH\n\t * @param from - inclusive\n\t * @param to - exclusive\n\t * @returns ops retrieved\n\t */\n\tpublic requestOps(from: number, to: number): void {\n\t\tassert(!this.socketReference?.disconnected, 0x413 /* non-active socket */);\n\n\t\t// Given that to is exclusive, we should be asking for at least something!\n\t\tassert(to > from, 0x272 /* \"empty request\" */);\n\n\t\t// PUSH may disable this functionality\n\t\t// back-compat: remove cast to any once latest version of IConnected is consumed\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n\t\tif ((this.details as any).supportedFeatures?.[feature_get_ops] !== true) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.pushCallCounter++;\n\t\tconst nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;\n\t\tconst start = performanceNow();\n\n\t\t// We may keep keep accumulating memory for nothing, if we are not getting responses.\n\t\t// Note that we should not have overlapping requests, as DeltaManager allows only one\n\t\t// outstanding request to storage, and that's the only way to get here.\n\t\t// But requests could be cancelled, and thus overlapping requests might be in the picture\n\t\t// If it happens, we do not care about stale requests.\n\t\t// So track some number of requests, but log if we get too many in flight - that likely\n\t\t// indicates an error somewhere.\n\t\tif (this.getOpsMap.size >= 5) {\n\t\t\tlet time = start;\n\t\t\tlet key: string | undefined;\n\t\t\tfor (const [keyCandidate, value] of this.getOpsMap.entries()) {\n\t\t\t\tif (value.start <= time || key === undefined) {\n\t\t\t\t\ttime = value.start;\n\t\t\t\t\tkey = keyCandidate;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst payloadToDelete = this.getOpsMap.get(key!)!;\n\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\teventName: \"GetOpsTooMany\",\n\t\t\t\tnonce,\n\t\t\t\tfrom: payloadToDelete.from,\n\t\t\t\tto: payloadToDelete.to,\n\t\t\t\tlength: payloadToDelete.to - payloadToDelete.from,\n\t\t\t\tduration: performanceNow() - payloadToDelete.start,\n\t\t\t});\n\t\t\tthis.getOpsMap.delete(key!);\n\t\t}\n\t\tthis.getOpsMap.set(nonce, {\n\t\t\tstart,\n\t\t\tfrom,\n\t\t\tto,\n\t\t});\n\t\tthis.socket.emit(\"get_ops\", this.clientId, {\n\t\t\tnonce,\n\t\t\tfrom,\n\t\t\tto: to - 1,\n\t\t});\n\t}\n\n\tpublic async flush(): Promise<FlushResult> {\n\t\tassert(!this.socketReference?.disconnected, 0x414 /* non-active socket */);\n\n\t\t// back-compat: remove cast to any once latest version of IConnected is consumed\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n\t\tif ((this.details as any).supportedFeatures?.[feature_flush_ops] !== true) {\n\t\t\t// Once single-commit summary is enabled end-to-end, flush support is a must!\n\t\t\t// The only alternative is change in design where SPO fetches ops from PUSH OR\n\t\t\t// summary includes required ops and SPO has some validation mechanism to ensure\n\t\t\t// they are not forged by client.\n\t\t\t// If design changes, we can reconsider it, but right now it's non-recoverable failure.\n\t\t\tthis.logger.sendErrorEvent({ eventName: \"FlushOpsNotSupported\" });\n\t\t\tthrow new Error(\n\t\t\t\t\"flush() API is not supported by PUSH, required for single-commit summaries\",\n\t\t\t);\n\t\t}\n\n\t\tthis.pushCallCounter++;\n\t\tconst nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;\n\t\t// There should be only one flush ops in flight, kicked out by upload summary workflow\n\t\t// That said, it could timeout and request could be repeated, so theoretically we can\n\t\t// get overlapping requests, but it should be very rare\n\t\tif (this.flushDeferred !== undefined) {\n\t\t\tthis.logger.sendErrorEvent({ eventName: \"FlushOpsTooMany\" });\n\t\t\tthis.flushDeferred.reject(\n\t\t\t\t\"process involving flush() was cancelled OR unsupported concurrency\",\n\t\t\t);\n\t\t}\n\t\tthis.socket.emit(\"flush_ops\", this.clientId, { nonce });\n\n\t\tthis.flushOpNonce = nonce;\n\t\tthis.flushDeferred = new Deferred<FlushResult>();\n\t\treturn this.flushDeferred.promise;\n\t}\n\n\tprotected disconnectHandler = (\n\t\terror: IFluidErrorBase & OdspError,\n\t\tclientId?: string,\n\t): void => {\n\t\tif (clientId === undefined || clientId === this.clientId) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: \"ServerDisconnect\",\n\t\t\t\t\tdriverVersion: pkgVersion,\n\t\t\t\t\tdetails: JSON.stringify({\n\t\t\t\t\t\t...this.getConnectionDetailsProps(),\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t\terror,\n\t\t\t);\n\t\t\tthis.disconnect(error);\n\t\t}\n\t};\n\n\tprotected async initialize(connectMessage: IConnect, timeout: number): Promise<void> {\n\t\tassert(!this.socketReference?.disconnected, 0x415 /* non-active socket */);\n\n\t\tif (this.enableMultiplexing) {\n\t\t\t// multiplex compatible early handlers\n\t\t\tthis.earlyOpHandler = (\n\t\t\t\tmessageDocumentId: string,\n\t\t\t\tmsgs: ISequencedDocumentMessage[],\n\t\t\t): void => {\n\t\t\t\tif (this.documentId === messageDocumentId) {\n\t\t\t\t\tthis.queuedMessages.push(...msgs);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.earlySignalHandler = (\n\t\t\t\tmsg: ISignalMessage | ISignalMessage[],\n\t\t\t\tmessageDocumentId?: string,\n\t\t\t): void => {\n\t\t\t\tif (messageDocumentId === undefined || messageDocumentId === this.documentId) {\n\t\t\t\t\tif (Array.isArray(msg)) {\n\t\t\t\t\t\tthis.queuedSignals.push(...msg);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.queuedSignals.push(msg);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tthis.socketReference!.on(\"disconnect\", this.disconnectHandler);\n\n\t\tthis.addTrackedListener(\"get_ops_response\", (result: IGetOpsResponse) => {\n\t\t\tconst messages = result.messages;\n\t\t\tconst data = this.getOpsMap.get(result.nonce);\n\t\t\t// Due to socket multiplexing, this client may not have asked for any data\n\t\t\t// If so, there it most likely does not need these ops (otherwise it already asked for them)\n\t\t\t// Also we may have deleted entry in this.getOpsMap due to too many requests and too slow response.\n\t\t\t// But not processing such result may push us into infinite loop of fast requests and dropping all responses\n\t\t\tif (data !== undefined || result.nonce.startsWith(this.requestOpsNoncePrefix)) {\n\t\t\t\tthis.getOpsMap.delete(result.nonce);\n\t\t\t\tconst common = {\n\t\t\t\t\teventName: \"GetOps\",\n\t\t\t\t\t// We need nonce only to pair with GetOpsTooMany events, i.e. when record was deleted\n\t\t\t\t\tnonce: data === undefined ? result.nonce : undefined,\n\t\t\t\t\tcode: result.code,\n\t\t\t\t\tfrom: data?.from,\n\t\t\t\t\tto: data?.to,\n\t\t\t\t\tduration: data === undefined ? undefined : performanceNow() - data.start,\n\t\t\t\t};\n\t\t\t\tif (messages !== undefined && messages.length > 0) {\n\t\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\t\t...common,\n\t\t\t\t\t\tfirst: messages[0].sequenceNumber,\n\t\t\t\t\t\tlast: messages[messages.length - 1].sequenceNumber,\n\t\t\t\t\t\tlength: messages.length,\n\t\t\t\t\t});\n\t\t\t\t\tthis.emit(\"op\", this.documentId, messages);\n\t\t\t\t} else {\n\t\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\t\t...common,\n\t\t\t\t\t\tlength: 0,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.addTrackedListener(\"flush_ops_response\", (result: IFlushOpsResponse) => {\n\t\t\tif (this.flushOpNonce === result.nonce) {\n\t\t\t\tconst seq = result.lastPersistedSequenceNumber;\n\t\t\t\tlet category: \"generic\" | \"error\" = \"generic\";\n\t\t\t\tif (result.lastPersistedSequenceNumber === undefined || result.code !== 200) {\n\t\t\t\t\tswitch (result.code) {\n\t\t\t\t\t\tcase 409:\n\t\t\t\t\t\tcase 429: {\n\t\t\t\t\t\t\tcategory = \"error\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 204: {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\tcategory = \"error\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"FlushResult\",\n\t\t\t\t\tcode: result.code,\n\t\t\t\t\tsequenceNumber: seq,\n\t\t\t\t\tcategory,\n\t\t\t\t});\n\t\t\t\tthis.flushDeferred!.resolve(result);\n\t\t\t\tthis.flushDeferred = undefined;\n\t\t\t\tthis.flushOpNonce = undefined;\n\t\t\t}\n\t\t});\n\n\t\tthis.connectionInitializeDeferredP = new Deferred<void>();\n\n\t\tsuper\n\t\t\t.initialize(connectMessage, timeout)\n\t\t\t.then(() => this.connectionInitializeDeferredP?.resolve())\n\t\t\t.catch((error) => this.connectionInitializeDeferredP?.reject(error));\n\n\t\tawait this.connectionInitializeDeferredP.promise.finally(() => {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"ConnectionAttemptInfo\",\n\t\t\t\t...this.getConnectionDetailsProps(),\n\t\t\t});\n\t\t});\n\t}\n\n\tprotected addTrackedListener(event: string, listener: (...args: any[]) => void): void {\n\t\t// override some event listeners in order to support multiple documents/clients over the same websocket\n\t\tswitch (event) {\n\t\t\tcase \"op\": {\n\t\t\t\t// per document op handling\n\t\t\t\tsuper.addTrackedListener(\n\t\t\t\t\tevent,\n\t\t\t\t\t(documentId: string, msgs: ISequencedDocumentMessage[]) => {\n\t\t\t\t\t\tif (!this.enableMultiplexing || this.documentId === documentId) {\n\t\t\t\t\t\t\tlistener(documentId, msgs);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"signal\": {\n\t\t\t\t// per document signal handling\n\t\t\t\tsuper.addTrackedListener(\n\t\t\t\t\tevent,\n\t\t\t\t\t(msg: ISignalMessage | ISignalMessage[], documentId?: string) => {\n\t\t\t\t\t\tif (!this.enableMultiplexing) {\n\t\t\t\t\t\t\tlistener(msg, documentId);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\tdocumentId !== undefined,\n\t\t\t\t\t\t\t0xa65 /* documentId is required when multiplexing is enabled. */,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (documentId !== this.documentId) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst msgs = Array.isArray(msg) ? msg : [msg];\n\n\t\t\t\t\t\tconst filteredMsgs = msgs.filter(\n\t\t\t\t\t\t\t(m) => !m.targetClientId || m.targetClientId === this.clientId,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (filteredMsgs.length > 0) {\n\t\t\t\t\t\t\t// This ternary is needed for signal-based layer compat tests to pass,\n\t\t\t\t\t\t\t// specifically the layer version combination where you have an old loader and the most recent driver layer.\n\t\t\t\t\t\t\t// Old loader doesn't send or receive batched signals (ISignalMessage[]),\n\t\t\t\t\t\t\t// so only individual ISignalMessage's should be passed when there's one element for backcompat.\n\t\t\t\t\t\t\tlistener(filteredMsgs.length === 1 ? filteredMsgs[0] : filteredMsgs, documentId);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"nack\": {\n\t\t\t\t// per client / document nack handling\n\t\t\t\tsuper.addTrackedListener(event, (clientIdOrDocumentId: string, nacks: INack[]) => {\n\t\t\t\t\tconst handle =\n\t\t\t\t\t\tclientIdOrDocumentId.length === 0 ||\n\t\t\t\t\t\tclientIdOrDocumentId === this.documentId ||\n\t\t\t\t\t\tclientIdOrDocumentId === this.clientId;\n\t\t\t\t\tconst { code, type, message, retryAfter } = nacks[0]?.content ?? {};\n\t\t\t\t\tconst { clientSequenceNumber, referenceSequenceNumber } = nacks[0]?.operation ?? {};\n\t\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"ServerNack\",\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\tmessage,\n\t\t\t\t\t\tretryAfterSeconds: retryAfter,\n\t\t\t\t\t\tclientId: this.clientId,\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\tclientSequenceNumber,\n\t\t\t\t\t\treferenceSequenceNumber,\n\t\t\t\t\t\topType: nacks[0]?.operation?.type,\n\t\t\t\t\t});\n\t\t\t\t\tif (handle) {\n\t\t\t\t\t\tthis.emit(\"nack\", clientIdOrDocumentId, nacks);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tsuper.addTrackedListener(event, listener);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic get disposed(): boolean {\n\t\tif (!(this._disposed || this.socket.connected)) {\n\t\t\t// Send error event if this connection is not yet disposed after socket is disconnected for 15s.\n\t\t\t// eslint-disable-next-line unicorn/no-lonely-if\n\t\t\tif (this.connectionNotYetDisposedTimeout === undefined) {\n\t\t\t\tthis.connectionNotYetDisposedTimeout = setTimeout(() => {\n\t\t\t\t\tif (!this._disposed) {\n\t\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\t\teventName: \"ConnectionNotYetDisposed\",\n\t\t\t\t\t\t\tdriverVersion: pkgVersion,\n\t\t\t\t\t\t\tdetails: JSON.stringify({\n\t\t\t\t\t\t\t\t...this.getConnectionDetailsProps(),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}, 15000);\n\t\t\t}\n\t\t}\n\t\treturn this._disposed;\n\t}\n\n\t/**\n\t * Returns true in case the connection is not yet disposed and the socket is also connected. The expectation is\n\t * that it will be called only after connection is fully established. i.e. there should no way to submit an op\n\t * while we are connecting, as connection object is not exposed to Loader layer until connection is established.\n\t */\n\tprivate get connected(): boolean {\n\t\treturn !this.disposed && this.socket.connected;\n\t}\n\n\tprotected override emitMessages(type: \"submitOp\", messages: IDocumentMessage[][]): void;\n\tprotected override emitMessages(\n\t\ttype: \"submitSignal\",\n\t\tmessages: string[][] | ISentSignalMessage[],\n\t): void;\n\tprotected override emitMessages(type: string, messages: unknown): void {\n\t\t// Only submit the op/signals if we are connected.\n\t\tif (this.connected) {\n\t\t\tthis.socket.emit(type, this.clientId, messages);\n\t\t}\n\t}\n\n\t/**\n\t * Submits a new delta operation to the server\n\t * @param message - delta operation to submit\n\t */\n\tpublic submit(messages: IDocumentMessage[]): void {\n\t\tthis.emitMessages(\"submitOp\", [messages]);\n\t}\n\n\t/**\n\t * Submits a new signal to the server\n\t *\n\t * @param content - Content of the signal.\n\t * @param targetClientId - When specified, the signal is only sent to the provided client id.\n\t */\n\tpublic submitSignal(content: string, targetClientId?: string): void {\n\t\tconst signal: ISentSignalMessage = {\n\t\t\tcontent,\n\t\t\ttargetClientId,\n\t\t};\n\n\t\tthis.emitMessages(\"submitSignal\", [signal]);\n\t}\n\n\t/**\n\t * Critical path where we need to also close the socket for an error.\n\t * @param error - Error causing the socket to close.\n\t */\n\tprotected closeSocketCore(error: IAnyDriverError): void {\n\t\tconst socket = this.socketReference;\n\t\tassert(socket !== undefined, 0x416 /* reentrancy not supported in close socket */);\n\t\tsocket.closeSocket(error);\n\t\tassert(\n\t\t\tthis.socketReference === undefined,\n\t\t\t0x417 /* disconnect flow did not work correctly */,\n\t\t);\n\t}\n\n\t/**\n\t * Disconnect from the websocket\n\t */\n\tprotected disconnectCore(err: IAnyDriverError): void {\n\t\tconst socket = this.socketReference;\n\t\tassert(socket !== undefined, 0x0a2 /* \"reentrancy not supported!\" */);\n\t\tthis.socketReference = undefined;\n\n\t\tsocket.off(\"disconnect\", this.disconnectHandler);\n\t\tif (this.hasDetails) {\n\t\t\t// tell the server we are disconnecting this client from the document\n\t\t\tthis.socket.emit(\"disconnect_document\", this.clientId, this.documentId);\n\t\t}\n\n\t\tsocket.removeSocketIoReference();\n\t\tif (\n\t\t\tthis.connectionInitializeDeferredP !== undefined &&\n\t\t\t!this.connectionInitializeDeferredP.isCompleted\n\t\t) {\n\t\t\tthis.connectionInitializeDeferredP.reject(err);\n\t\t}\n\t}\n}\n"]}
|
package/lib/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/odsp-driver";
|
|
8
|
-
export declare const pkgVersion = "2.41.0
|
|
8
|
+
export declare const pkgVersion = "2.41.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,gCAAgC,CAAC;AACrD,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,gCAAgC,CAAC;AACrD,eAAO,MAAM,UAAU,WAAW,CAAC"}
|
package/lib/packageVersion.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/odsp-driver\";\nexport const pkgVersion = \"2.41.0\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/odsp-driver",
|
|
3
|
-
"version": "2.41.0
|
|
3
|
+
"version": "2.41.0",
|
|
4
4
|
"description": "Socket storage implementation for SPO and ODC",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -69,26 +69,26 @@
|
|
|
69
69
|
"temp-directory": "nyc/.nyc_output"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@fluid-internal/client-utils": "2.41.0
|
|
73
|
-
"@fluidframework/core-interfaces": "2.41.0
|
|
74
|
-
"@fluidframework/core-utils": "2.41.0
|
|
75
|
-
"@fluidframework/driver-base": "2.41.0
|
|
76
|
-
"@fluidframework/driver-definitions": "2.41.0
|
|
77
|
-
"@fluidframework/driver-utils": "2.41.0
|
|
78
|
-
"@fluidframework/odsp-doclib-utils": "2.41.0
|
|
79
|
-
"@fluidframework/odsp-driver-definitions": "2.41.0
|
|
80
|
-
"@fluidframework/telemetry-utils": "2.41.0
|
|
72
|
+
"@fluid-internal/client-utils": "~2.41.0",
|
|
73
|
+
"@fluidframework/core-interfaces": "~2.41.0",
|
|
74
|
+
"@fluidframework/core-utils": "~2.41.0",
|
|
75
|
+
"@fluidframework/driver-base": "~2.41.0",
|
|
76
|
+
"@fluidframework/driver-definitions": "~2.41.0",
|
|
77
|
+
"@fluidframework/driver-utils": "~2.41.0",
|
|
78
|
+
"@fluidframework/odsp-doclib-utils": "~2.41.0",
|
|
79
|
+
"@fluidframework/odsp-driver-definitions": "~2.41.0",
|
|
80
|
+
"@fluidframework/telemetry-utils": "~2.41.0",
|
|
81
81
|
"socket.io-client": "~4.7.5",
|
|
82
82
|
"uuid": "^9.0.0"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@arethetypeswrong/cli": "^0.17.1",
|
|
86
86
|
"@biomejs/biome": "~1.9.3",
|
|
87
|
-
"@fluid-internal/mocha-test-setup": "2.41.0
|
|
87
|
+
"@fluid-internal/mocha-test-setup": "~2.41.0",
|
|
88
88
|
"@fluid-tools/build-cli": "^0.55.0",
|
|
89
89
|
"@fluidframework/build-common": "^2.0.3",
|
|
90
90
|
"@fluidframework/build-tools": "^0.55.0",
|
|
91
|
-
"@fluidframework/eslint-config-fluid": "^5.7.
|
|
91
|
+
"@fluidframework/eslint-config-fluid": "^5.7.4",
|
|
92
92
|
"@fluidframework/odsp-driver-previous": "npm:@fluidframework/odsp-driver@2.40.0",
|
|
93
93
|
"@microsoft/api-extractor": "7.52.8",
|
|
94
94
|
"@types/mocha": "^10.0.10",
|
|
@@ -20,51 +20,7 @@ import { buildOdspShareLinkReqParams, getContainerPackageName } from "./odspUtil
|
|
|
20
20
|
* @param fileName - name of the new file to be created
|
|
21
21
|
* @param createShareLinkType - type of sharing link you would like to create for this file. ShareLinkTypes
|
|
22
22
|
* will be deprecated soon, so for any new implementation please provide createShareLinkType of type ShareLink
|
|
23
|
-
* @
|
|
24
|
-
* @alpha
|
|
25
|
-
*/
|
|
26
|
-
export function createOdspCreateContainerRequest(
|
|
27
|
-
siteUrl: string,
|
|
28
|
-
driveId: string,
|
|
29
|
-
filePath: string,
|
|
30
|
-
fileName: string,
|
|
31
|
-
createShareLinkType?: ISharingLinkKind,
|
|
32
|
-
): IRequest;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Create the request object with url and headers for creating a new file on OneDrive Sharepoint
|
|
36
|
-
* @param siteUrl - Base url for OneDrive
|
|
37
|
-
* @param driveId - drive identifier
|
|
38
|
-
* @param filePath - path where file needs to be created
|
|
39
|
-
* @param fileName - name of the new file to be created
|
|
40
|
-
* @param createShareLinkType - type of sharing link you would like to create for this file. ShareLinkTypes
|
|
41
|
-
* will be deprecated soon, so for any new implementation please provide createShareLinkType of type ShareLink
|
|
42
|
-
* @param containerPackageInfo - **Deprecated Parameter** - container package information which will be used to extract the container package name.
|
|
43
|
-
* If not given that means that the container package does not have a name.
|
|
44
|
-
* @legacy
|
|
45
|
-
* @alpha
|
|
46
|
-
* @deprecated To be removed in 2.40
|
|
47
|
-
* Add containerPackageInfo to the OdspDriverUrlResolverForShareLink constructor instead; see https://github.com/microsoft/FluidFramework/issues/23882 for more details.
|
|
48
|
-
* Deprecating overloaded function to remove containerPackageInfo
|
|
49
|
-
*/
|
|
50
|
-
export function createOdspCreateContainerRequest(
|
|
51
|
-
siteUrl: string,
|
|
52
|
-
driveId: string,
|
|
53
|
-
filePath: string,
|
|
54
|
-
fileName: string,
|
|
55
|
-
createShareLinkType: ISharingLinkKind | undefined,
|
|
56
|
-
containerPackageInfo: IContainerPackageInfo | undefined,
|
|
57
|
-
): IRequest;
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Create the request object with url and headers for creating a new file on OneDrive Sharepoint
|
|
61
|
-
* @param siteUrl - Base url for OneDrive
|
|
62
|
-
* @param driveId - drive identifier
|
|
63
|
-
* @param filePath - path where file needs to be created
|
|
64
|
-
* @param fileName - name of the new file to be created
|
|
65
|
-
* @param createShareLinkType - type of sharing link you would like to create for this file. ShareLinkTypes
|
|
66
|
-
* will be deprecated soon, so for any new implementation please provide createShareLinkType of type ShareLink
|
|
67
|
-
* @param containerPackageInfo - **Deprecated Parameter** - container package information which will be used to extract the container package name.
|
|
23
|
+
* @param containerPackageInfo - Container package information which will be used to extract the container package name.
|
|
68
24
|
* If not given that means that the container package does not have a name.
|
|
69
25
|
* @legacy
|
|
70
26
|
* @alpha
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
MonitoringContext,
|
|
35
35
|
normalizeError,
|
|
36
36
|
} from "@fluidframework/telemetry-utils/internal";
|
|
37
|
+
import { v4 as uuid } from "uuid";
|
|
37
38
|
|
|
38
39
|
import { policyLabelsUpdatesSignalType } from "./contracts.js";
|
|
39
40
|
import { EpochTracker } from "./epochTracker.js";
|
|
@@ -61,6 +62,8 @@ export class OdspDelayLoadedDeltaStream {
|
|
|
61
62
|
|
|
62
63
|
private _relayServiceTenantAndSessionId: string | undefined;
|
|
63
64
|
|
|
65
|
+
private firstConnectionAttempt = true;
|
|
66
|
+
|
|
64
67
|
// Tracks the time at which the Policy Labels were updated the last time. This is used to resolve race conditions
|
|
65
68
|
// between label updates from the join session and the Fluid signals and they could have same or different timestamps.
|
|
66
69
|
// So this timestamp is updated with timestamp from the service/signals with the most recent timestamp. We could also
|
|
@@ -180,6 +183,19 @@ export class OdspDelayLoadedDeltaStream {
|
|
|
180
183
|
sensitivityLabelsInfo: websocketEndpoint.sensitivityLabelsInfo,
|
|
181
184
|
});
|
|
182
185
|
}
|
|
186
|
+
|
|
187
|
+
const connectionId = uuid();
|
|
188
|
+
if (this.firstConnectionAttempt) {
|
|
189
|
+
this.firstConnectionAttempt = false;
|
|
190
|
+
this.mc.logger.sendTelemetryEvent({
|
|
191
|
+
eventName: "FirstConnectionAttemptDetails",
|
|
192
|
+
details: {
|
|
193
|
+
connectionId,
|
|
194
|
+
tenantId: websocketEndpoint.tenantId,
|
|
195
|
+
documentId: websocketEndpoint.id,
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
}
|
|
183
199
|
try {
|
|
184
200
|
const connection = await this.createDeltaConnection(
|
|
185
201
|
websocketEndpoint.tenantId,
|
|
@@ -187,6 +203,7 @@ export class OdspDelayLoadedDeltaStream {
|
|
|
187
203
|
finalWebsocketToken,
|
|
188
204
|
client,
|
|
189
205
|
websocketEndpoint.deltaStreamSocketUrl,
|
|
206
|
+
connectionId,
|
|
190
207
|
);
|
|
191
208
|
connection.on("op", (documentId, ops: ISequencedDocumentMessage[]) => {
|
|
192
209
|
this.opsReceived(ops);
|
|
@@ -511,6 +528,7 @@ export class OdspDelayLoadedDeltaStream {
|
|
|
511
528
|
* @param token - authorization token for delta service
|
|
512
529
|
* @param client - information about the client
|
|
513
530
|
* @param webSocketUrl - websocket URL
|
|
531
|
+
* @param connectionId - connection ID for the connection
|
|
514
532
|
*/
|
|
515
533
|
private async createDeltaConnection(
|
|
516
534
|
tenantId: string,
|
|
@@ -518,6 +536,7 @@ export class OdspDelayLoadedDeltaStream {
|
|
|
518
536
|
token: string | null,
|
|
519
537
|
client: IClient,
|
|
520
538
|
webSocketUrl: string,
|
|
539
|
+
connectionId: string,
|
|
521
540
|
): Promise<OdspDocumentDeltaConnection> {
|
|
522
541
|
const startTime = performanceNow();
|
|
523
542
|
const connection = await OdspDocumentDeltaConnection.create(
|
|
@@ -530,6 +549,7 @@ export class OdspDelayLoadedDeltaStream {
|
|
|
530
549
|
60000,
|
|
531
550
|
this.epochTracker,
|
|
532
551
|
this.socketReferenceKeyPrefix,
|
|
552
|
+
connectionId,
|
|
533
553
|
);
|
|
534
554
|
const duration = performanceNow() - startTime;
|
|
535
555
|
// This event happens rather often, so it adds up to cost of telemetry.
|
|
@@ -245,6 +245,7 @@ export class OdspDocumentDeltaConnection extends DocumentDeltaConnection {
|
|
|
245
245
|
* @param timeoutMs - time limit on making the connection
|
|
246
246
|
* @param epochTracker - track epoch changes
|
|
247
247
|
* @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache
|
|
248
|
+
* @param connectionId - (optional) connection ID for the connection
|
|
248
249
|
*/
|
|
249
250
|
public static async create(
|
|
250
251
|
tenantId: string,
|
|
@@ -257,6 +258,7 @@ export class OdspDocumentDeltaConnection extends DocumentDeltaConnection {
|
|
|
257
258
|
timeoutMs: number,
|
|
258
259
|
epochTracker: EpochTracker,
|
|
259
260
|
socketReferenceKeyPrefix: string | undefined,
|
|
261
|
+
connectionId: string = uuid(),
|
|
260
262
|
): Promise<OdspDocumentDeltaConnection> {
|
|
261
263
|
const mc = loggerToMonitoringContext(telemetryLogger);
|
|
262
264
|
|
|
@@ -281,7 +283,6 @@ export class OdspDocumentDeltaConnection extends DocumentDeltaConnection {
|
|
|
281
283
|
);
|
|
282
284
|
|
|
283
285
|
const socket = socketReference.socket;
|
|
284
|
-
const connectionId = uuid();
|
|
285
286
|
const connectMessage: IConnect = {
|
|
286
287
|
client,
|
|
287
288
|
id: documentId,
|
package/src/packageVersion.ts
CHANGED