@fluidframework/odsp-driver 2.0.0-internal.4.2.1 → 2.0.0-internal.4.4.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/dist/fetchSnapshot.d.ts +5 -0
- package/dist/fetchSnapshot.d.ts.map +1 -1
- package/dist/fetchSnapshot.js +2 -1
- package/dist/fetchSnapshot.js.map +1 -1
- package/dist/odspDelayLoadedDeltaStream.d.ts +1 -1
- package/dist/odspDelayLoadedDeltaStream.d.ts.map +1 -1
- package/dist/odspDelayLoadedDeltaStream.js +12 -2
- package/dist/odspDelayLoadedDeltaStream.js.map +1 -1
- package/dist/odspDocumentDeltaConnection.d.ts +21 -1
- package/dist/odspDocumentDeltaConnection.d.ts.map +1 -1
- package/dist/odspDocumentDeltaConnection.js +73 -6
- package/dist/odspDocumentDeltaConnection.js.map +1 -1
- package/dist/odspDocumentServiceFactoryCore.d.ts.map +1 -1
- package/dist/odspDocumentServiceFactoryCore.js +6 -6
- package/dist/odspDocumentServiceFactoryCore.js.map +1 -1
- package/dist/odspDocumentStorageManager.d.ts.map +1 -1
- package/dist/odspDocumentStorageManager.js +1 -1
- package/dist/odspDocumentStorageManager.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/fetchSnapshot.d.ts +5 -0
- package/lib/fetchSnapshot.d.ts.map +1 -1
- package/lib/fetchSnapshot.js +1 -1
- package/lib/fetchSnapshot.js.map +1 -1
- package/lib/odspDelayLoadedDeltaStream.d.ts +1 -1
- package/lib/odspDelayLoadedDeltaStream.d.ts.map +1 -1
- package/lib/odspDelayLoadedDeltaStream.js +12 -2
- package/lib/odspDelayLoadedDeltaStream.js.map +1 -1
- package/lib/odspDocumentDeltaConnection.d.ts +21 -1
- package/lib/odspDocumentDeltaConnection.d.ts.map +1 -1
- package/lib/odspDocumentDeltaConnection.js +73 -6
- package/lib/odspDocumentDeltaConnection.js.map +1 -1
- package/lib/odspDocumentServiceFactoryCore.d.ts.map +1 -1
- package/lib/odspDocumentServiceFactoryCore.js +6 -6
- package/lib/odspDocumentServiceFactoryCore.js.map +1 -1
- package/lib/odspDocumentStorageManager.d.ts.map +1 -1
- package/lib/odspDocumentStorageManager.js +2 -2
- package/lib/odspDocumentStorageManager.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +10 -10
- package/src/fetchSnapshot.ts +1 -1
- package/src/odspDelayLoadedDeltaStream.ts +16 -2
- package/src/odspDocumentDeltaConnection.ts +81 -4
- package/src/odspDocumentServiceFactoryCore.ts +6 -7
- package/src/odspDocumentStorageManager.ts +2 -0
- package/src/packageVersion.ts +1 -1
package/CHANGELOG.md
CHANGED
package/dist/fetchSnapshot.d.ts
CHANGED
|
@@ -38,6 +38,11 @@ export interface ISnapshotRequestAndResponseOptions {
|
|
|
38
38
|
[index: string]: any;
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
+
export declare function evalBlobsAndTrees(snapshot: ISnapshotContents): {
|
|
42
|
+
trees: number;
|
|
43
|
+
numBlobs: number;
|
|
44
|
+
encodedBlobsSize: number;
|
|
45
|
+
};
|
|
41
46
|
export declare function validateBlobsAndTrees(snapshot: IOdspSnapshot): void;
|
|
42
47
|
/**
|
|
43
48
|
* This function fetches the snapshot and parse it according to what is mentioned in response headers.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetchSnapshot.d.ts","sourceRoot":"","sources":["../src/fetchSnapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAKtE,OAAO,EACN,gBAAgB,EAChB,gBAAgB,EAEhB,+BAA+B,EAC/B,MAAM,yCAAyC,CAAC;AAOjD,OAAO,EACN,aAAa,EAEb,wBAAwB,EAExB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAKN,aAAa,EAGb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAOtD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C;;GAEG;AACH,oBAAY,yBAAyB;IACpC,IAAI,IAAI;IACR,MAAM,IAAI;IACV,aAAa,IAAI;CACjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAClC,WAAW,EAAE,MAAM,EAEnB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,OAAO,EAC1B,sCAAsC,EAAE,OAAO,EAC/C,MAAM,EAAE,gBAAgB,EACxB,kBAAkB,EAAE,CACnB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE;IAAE,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,KAClC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,GAClC,OAAO,CAAC,iBAAiB,CAAC,CAuB5B;AAED,wBAAsB,uBAAuB,CAC5C,eAAe,EAAE,gBAAgB,EACjC,mBAAmB,EAAE,+BAA+B,EACpD,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,sCAAsC,EAAE,OAAO,EAC/C,MAAM,EAAE,gBAAgB,EACxB,kBAAkB,EAAE,CACnB,oBAAoB,EAAE,gBAAgB,EACtC,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,UAAU,CAAC,EAAE,eAAe,KACxB,OAAO,CAAC,kCAAkC,CAAC,EAChD,UAAU,EAAE,CAAC,cAAc,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,EACvE,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAClC,oBAAoB,CAAC,EAAE,OAAO,GAC5B,OAAO,CAAC,iBAAiB,CAAC,CAwE5B;AA0RD,MAAM,WAAW,kCAAkC;IAClD,YAAY,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE;QAAE,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;CACzC;
|
|
1
|
+
{"version":3,"file":"fetchSnapshot.d.ts","sourceRoot":"","sources":["../src/fetchSnapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAKtE,OAAO,EACN,gBAAgB,EAChB,gBAAgB,EAEhB,+BAA+B,EAC/B,MAAM,yCAAyC,CAAC;AAOjD,OAAO,EACN,aAAa,EAEb,wBAAwB,EAExB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAKN,aAAa,EAGb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAOtD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C;;GAEG;AACH,oBAAY,yBAAyB;IACpC,IAAI,IAAI;IACR,MAAM,IAAI;IACV,aAAa,IAAI;CACjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAClC,WAAW,EAAE,MAAM,EAEnB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,OAAO,EAC1B,sCAAsC,EAAE,OAAO,EAC/C,MAAM,EAAE,gBAAgB,EACxB,kBAAkB,EAAE,CACnB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE;IAAE,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,KAClC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,GAClC,OAAO,CAAC,iBAAiB,CAAC,CAuB5B;AAED,wBAAsB,uBAAuB,CAC5C,eAAe,EAAE,gBAAgB,EACjC,mBAAmB,EAAE,+BAA+B,EACpD,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,sCAAsC,EAAE,OAAO,EAC/C,MAAM,EAAE,gBAAgB,EACxB,kBAAkB,EAAE,CACnB,oBAAoB,EAAE,gBAAgB,EACtC,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,UAAU,CAAC,EAAE,eAAe,KACxB,OAAO,CAAC,kCAAkC,CAAC,EAChD,UAAU,EAAE,CAAC,cAAc,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,EACvE,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAClC,oBAAoB,CAAC,EAAE,OAAO,GAC5B,OAAO,CAAC,iBAAiB,CAAC,CAwE5B;AA0RD,MAAM,WAAW,kCAAkC;IAClD,YAAY,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE;QAAE,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;CACzC;AAuCD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB;;;;EAQ5D;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,QAS5D;AAWD;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACrC,eAAe,EAAE,gBAAgB,EACjC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,gBAAgB,EACxB,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,uBAAuB,CAAC,EAAE,yBAAyB,EACnD,UAAU,CAAC,EAAE,eAAe,EAC5B,YAAY,CAAC,EAAE,YAAY,EAC3B,YAAY,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,kCAAkC,CAAC,CAiD7C"}
|
package/dist/fetchSnapshot.js
CHANGED
|
@@ -7,7 +7,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
7
7
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
8
|
};
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.downloadSnapshot = exports.validateBlobsAndTrees = exports.fetchSnapshotWithRedeem = exports.fetchSnapshot = exports.SnapshotFormatSupportType = void 0;
|
|
10
|
+
exports.downloadSnapshot = exports.validateBlobsAndTrees = exports.evalBlobsAndTrees = exports.fetchSnapshotWithRedeem = exports.fetchSnapshot = exports.SnapshotFormatSupportType = void 0;
|
|
11
11
|
const abort_controller_1 = __importDefault(require("abort-controller"));
|
|
12
12
|
const uuid_1 = require("uuid");
|
|
13
13
|
const common_utils_1 = require("@fluidframework/common-utils");
|
|
@@ -313,6 +313,7 @@ function evalBlobsAndTrees(snapshot) {
|
|
|
313
313
|
}
|
|
314
314
|
return { trees, numBlobs, encodedBlobsSize };
|
|
315
315
|
}
|
|
316
|
+
exports.evalBlobsAndTrees = evalBlobsAndTrees;
|
|
316
317
|
function validateBlobsAndTrees(snapshot) {
|
|
317
318
|
(0, common_utils_1.assert)(snapshot.trees !== undefined, 0x200 /* "Returned odsp snapshot is malformed. No trees!" */);
|
|
318
319
|
(0, common_utils_1.assert)(snapshot.blobs !== undefined, 0x201 /* "Returned odsp snapshot is malformed. No blobs!" */);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetchSnapshot.js","sourceRoot":"","sources":["../src/fetchSnapshot.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 { default as AbortController } from \"abort-controller\";\nimport { v4 as uuid } from \"uuid\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, fromUtf8ToBase64 } from \"@fluidframework/common-utils\";\nimport { getW3CData } from \"@fluidframework/driver-base\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport { isFluidError, PerformanceEvent, wrapError } from \"@fluidframework/telemetry-utils\";\nimport {\n\tIOdspResolvedUrl,\n\tISnapshotOptions,\n\tOdspErrorType,\n\tInstrumentedStorageTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport {\n\tDriverErrorTelemetryProps,\n\tisRuntimeMessage,\n\tNonRetryableError,\n} from \"@fluidframework/driver-utils\";\nimport {\n\tIOdspSnapshot,\n\tISnapshotCachedEntry,\n\tIVersionedValueWithEpoch,\n\tpersistedCacheValueVersion,\n} from \"./contracts\";\nimport { getQueryString } from \"./getQueryString\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport {\n\tfetchAndParseAsJSONHelper,\n\tfetchHelper,\n\tgetWithRetryForTokenRefresh,\n\tgetWithRetryForTokenRefreshRepeat,\n\tIOdspResponse,\n\tmeasure,\n\tmeasureP,\n} from \"./odspUtils\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { convertOdspSnapshotToSnapshotTreeAndBlobs } from \"./odspSnapshotParser\";\nimport {\n\tcurrentReadVersion,\n\tISnapshotContentsWithProps,\n\tparseCompactSnapshotResponse,\n} from \"./compactSnapshotParser\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { pkgVersion } from \"./packageVersion\";\n\n/**\n * Enum to support different types of snapshot formats.\n */\nexport enum SnapshotFormatSupportType {\n\tJson = 0,\n\tBinary = 1,\n\tJsonAndBinary = 2,\n}\n\n/**\n * Fetches a snapshot from the server with a given version id.\n * @param snapshotUrl - snapshot url from where the odsp snapshot will be fetched\n * @param token - token used for authorization in the request\n * @param storageFetchWrapper - Implementation of the get/post methods used to fetch the snapshot\n * @param versionId - id of specific snapshot to be fetched\n * @param fetchFullSnapshot - whether we want to fetch full snapshot(with blobs)\n * @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header\n * @returns A promise of the snapshot and the status code of the response\n */\nexport async function fetchSnapshot(\n\tsnapshotUrl: string,\n\t// eslint-disable-next-line @rushstack/no-new-null\n\ttoken: string | null,\n\tversionId: string,\n\tfetchFullSnapshot: boolean,\n\tforceAccessTokenViaAuthorizationHeader: boolean,\n\tlogger: ITelemetryLogger,\n\tsnapshotDownloader: (\n\t\turl: string,\n\t\tfetchOptions: { [index: string]: any },\n\t) => Promise<IOdspResponse<unknown>>,\n): Promise<ISnapshotContents> {\n\tconst path = `/trees/${versionId}`;\n\tlet queryParams: ISnapshotOptions = {};\n\n\tif (fetchFullSnapshot) {\n\t\tqueryParams = versionId !== \"latest\" ? { blobs: 2 } : { deltas: 1, blobs: 2 };\n\t}\n\n\tconst queryString = getQueryString(queryParams);\n\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t`${snapshotUrl}${path}${queryString}`,\n\t\ttoken,\n\t\tforceAccessTokenViaAuthorizationHeader,\n\t);\n\tconst response = (await PerformanceEvent.timedExecAsync(\n\t\tlogger,\n\t\t{\n\t\t\teventName: \"fetchSnapshot\",\n\t\t\theaders: Object.keys(headers).length !== 0 ? true : undefined,\n\t\t},\n\t\tasync () => snapshotDownloader(url, { headers }),\n\t)) as IOdspResponse<IOdspSnapshot>;\n\treturn convertOdspSnapshotToSnapshotTreeAndBlobs(response.content);\n}\n\nexport async function fetchSnapshotWithRedeem(\n\todspResolvedUrl: IOdspResolvedUrl,\n\tstorageTokenFetcher: InstrumentedStorageTokenFetcher,\n\tsnapshotOptions: ISnapshotOptions | undefined,\n\tforceAccessTokenViaAuthorizationHeader: boolean,\n\tlogger: ITelemetryLogger,\n\tsnapshotDownloader: (\n\t\tfinalOdspResolvedUrl: IOdspResolvedUrl,\n\t\tstorageToken: string,\n\t\tsnapshotOptions: ISnapshotOptions | undefined,\n\t\tcontroller?: AbortController,\n\t) => Promise<ISnapshotRequestAndResponseOptions>,\n\tputInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n\tremoveEntries: () => Promise<void>,\n\tenableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n\t// back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51\n\tconst sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;\n\tif (sharingLinkToRedeem) {\n\t\todspResolvedUrl.shareLinkInfo = { ...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem };\n\t}\n\n\treturn fetchLatestSnapshotCore(\n\t\todspResolvedUrl,\n\t\tstorageTokenFetcher,\n\t\tsnapshotOptions,\n\t\tlogger,\n\t\tsnapshotDownloader,\n\t\tputInCache,\n\t\tenableRedeemFallback,\n\t)\n\t\t.catch(async (error) => {\n\t\t\tif (enableRedeemFallback && isRedeemSharingLinkError(odspResolvedUrl, error)) {\n\t\t\t\t// Execute the redeem fallback\n\n\t\t\t\tawait redeemSharingLink(\n\t\t\t\t\todspResolvedUrl,\n\t\t\t\t\tstorageTokenFetcher,\n\t\t\t\t\tlogger,\n\t\t\t\t\tforceAccessTokenViaAuthorizationHeader,\n\t\t\t\t);\n\t\t\t\tconst odspResolvedUrlWithoutShareLink: IOdspResolvedUrl = {\n\t\t\t\t\t...odspResolvedUrl,\n\t\t\t\t\tshareLinkInfo: {\n\t\t\t\t\t\t...odspResolvedUrl.shareLinkInfo,\n\t\t\t\t\t\tsharingLinkToRedeem: undefined,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\t// Log initial failure only if redeem succeeded - it points out to some bug somewhere\n\t\t\t\t// If redeem failed, that most likely means user has no permissions to access a file,\n\t\t\t\t// and thus it's not worth it logging extra errors - same error will be logged by end-to-end\n\t\t\t\t// flow (container open) based on a failure above.\n\t\t\t\tlogger.sendErrorEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"RedeemFallback\",\n\t\t\t\t\t\terrorType: error.errorType,\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\n\t\t\t\treturn fetchLatestSnapshotCore(\n\t\t\t\t\todspResolvedUrlWithoutShareLink,\n\t\t\t\t\tstorageTokenFetcher,\n\t\t\t\t\tsnapshotOptions,\n\t\t\t\t\tlogger,\n\t\t\t\t\tsnapshotDownloader,\n\t\t\t\t\tputInCache,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t})\n\t\t.catch(async (error) => {\n\t\t\t// Clear the cache on 401/403/404 on snapshot fetch from network because this means either the user doesn't\n\t\t\t// have permissions for the file or it was deleted. So, if we do not clear cache, we will continue fetching\n\t\t\t// snapshot from cache in the future.\n\t\t\tif (\n\t\t\t\t(typeof error === \"object\" &&\n\t\t\t\t\terror !== null &&\n\t\t\t\t\terror.errorType === DriverErrorType.authorizationError) ||\n\t\t\t\terror.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError\n\t\t\t) {\n\t\t\t\tawait removeEntries();\n\t\t\t}\n\t\t\tthrow error;\n\t\t});\n}\n\nasync function redeemSharingLink(\n\todspResolvedUrl: IOdspResolvedUrl,\n\tstorageTokenFetcher: InstrumentedStorageTokenFetcher,\n\tlogger: ITelemetryLogger,\n\tforceAccessTokenViaAuthorizationHeader: boolean,\n) {\n\treturn PerformanceEvent.timedExecAsync(\n\t\tlogger,\n\t\t{\n\t\t\teventName: \"RedeemShareLink\",\n\t\t},\n\t\tasync () =>\n\t\t\tgetWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n\t\t\t\tassert(\n\t\t\t\t\t!!odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem,\n\t\t\t\t\t0x1ed /* \"Share link should be present\" */,\n\t\t\t\t);\n\t\t\t\tconst storageToken = await storageTokenFetcher(\n\t\t\t\t\ttokenFetchOptions,\n\t\t\t\t\t\"RedeemShareLink\",\n\t\t\t\t);\n\t\t\t\tconst encodedShareUrl = getEncodedShareUrl(\n\t\t\t\t\todspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem,\n\t\t\t\t);\n\t\t\t\tconst redeemUrl = `${odspResolvedUrl.siteUrl}/_api/v2.0/shares/${encodedShareUrl}`;\n\t\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\t\tredeemUrl,\n\t\t\t\t\tstorageToken,\n\t\t\t\t\tforceAccessTokenViaAuthorizationHeader,\n\t\t\t\t);\n\t\t\t\theaders.prefer = \"redeemSharingLink\";\n\t\t\t\treturn fetchAndParseAsJSONHelper(url, { headers });\n\t\t\t}),\n\t);\n}\n\nasync function fetchLatestSnapshotCore(\n\todspResolvedUrl: IOdspResolvedUrl,\n\tstorageTokenFetcher: InstrumentedStorageTokenFetcher,\n\tsnapshotOptions: ISnapshotOptions | undefined,\n\tlogger: ITelemetryLogger,\n\tsnapshotDownloader: (\n\t\tfinalOdspResolvedUrl: IOdspResolvedUrl,\n\t\tstorageToken: string,\n\t\tsnapshotOptions: ISnapshotOptions | undefined,\n\t\tcontroller?: AbortController,\n\t) => Promise<ISnapshotRequestAndResponseOptions>,\n\tputInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n\tenableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n\treturn getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n\t\tconst storageToken = await storageTokenFetcher(tokenFetchOptions, \"TreesLatest\", true);\n\t\tassert(storageToken !== null, 0x1e5 /* \"Storage token should not be null\" */);\n\n\t\tconst perfEvent = {\n\t\t\teventName: \"TreesLatest\",\n\t\t\tattempts: tokenFetchOptions.refresh ? 2 : 1,\n\t\t\tshareLinkPresent: odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined,\n\t\t\tisSummarizer: odspResolvedUrl.summarizer,\n\t\t\tredeemFallbackEnabled: enableRedeemFallback,\n\t\t};\n\t\tif (snapshotOptions !== undefined) {\n\t\t\tObject.entries(snapshotOptions).forEach(([key, value]) => {\n\t\t\t\tif (value !== undefined) {\n\t\t\t\t\tperfEvent[`snapshotOption_${key}`] = value;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t// This event measures only successful cases of getLatest call (no tokens, no retries).\n\t\treturn PerformanceEvent.timedExecAsync(logger, perfEvent, async (event) => {\n\t\t\tlet controller: AbortController | undefined;\n\t\t\tlet fetchTimeout: ReturnType<typeof setTimeout> | undefined;\n\t\t\tif (snapshotOptions?.timeout !== undefined) {\n\t\t\t\tcontroller = new AbortController();\n\t\t\t\tfetchTimeout = setTimeout(() => controller!.abort(), snapshotOptions.timeout);\n\t\t\t}\n\n\t\t\tconst [response, fetchTime] = await measureP(async () =>\n\t\t\t\tsnapshotDownloader(odspResolvedUrl, storageToken, snapshotOptions, controller),\n\t\t\t).finally(() => {\n\t\t\t\t// Clear the fetchTimeout once the response is fetched.\n\t\t\t\tif (fetchTimeout !== undefined) {\n\t\t\t\t\tclearTimeout(fetchTimeout);\n\t\t\t\t\tfetchTimeout = undefined;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconst odspResponse = response.odspResponse;\n\t\t\tconst contentType = odspResponse.headers.get(\"content-type\");\n\n\t\t\tconst propsToLog: DriverErrorTelemetryProps = {\n\t\t\t\t...odspResponse.propsToLog,\n\t\t\t\tcontentType,\n\t\t\t\taccept: response.requestHeaders.accept,\n\t\t\t\tdriverVersion: pkgVersion,\n\t\t\t};\n\n\t\t\tlet parsedSnapshotContents: IOdspResponse<ISnapshotContentsWithProps> | undefined;\n\t\t\tlet contentTypeToRead: string | undefined;\n\t\t\tif (contentType?.includes(\"application/ms-fluid\")) {\n\t\t\t\tcontentTypeToRead = \"application/ms-fluid\";\n\t\t\t} else if (contentType?.includes(\"application/json\")) {\n\t\t\t\tcontentTypeToRead = \"application/json\";\n\t\t\t}\n\n\t\t\tlet parseTime: number;\n\t\t\tlet receiveContentTime: number;\n\t\t\ttry {\n\t\t\t\tswitch (contentTypeToRead) {\n\t\t\t\t\tcase \"application/json\": {\n\t\t\t\t\t\tlet text: string;\n\t\t\t\t\t\t[text, receiveContentTime] = await measureP(async () =>\n\t\t\t\t\t\t\todspResponse.content.text(),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tpropsToLog.bodySize = text.length;\n\t\t\t\t\t\tlet content: IOdspSnapshot;\n\t\t\t\t\t\t[content, parseTime] = measure(() => JSON.parse(text) as IOdspSnapshot);\n\t\t\t\t\t\tvalidateBlobsAndTrees(content);\n\t\t\t\t\t\tconst snapshotContents: ISnapshotContents =\n\t\t\t\t\t\t\tconvertOdspSnapshotToSnapshotTreeAndBlobs(content);\n\t\t\t\t\t\tparsedSnapshotContents = {\n\t\t\t\t\t\t\t...odspResponse,\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t...snapshotContents,\n\t\t\t\t\t\t\t\ttelemetryProps: {},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"application/ms-fluid\": {\n\t\t\t\t\t\tlet content: ArrayBuffer;\n\t\t\t\t\t\t[content, receiveContentTime] = await measureP(async () =>\n\t\t\t\t\t\t\todspResponse.content.arrayBuffer(),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tpropsToLog.bodySize = content.byteLength;\n\t\t\t\t\t\tlet snapshotContents: ISnapshotContentsWithProps;\n\t\t\t\t\t\t[snapshotContents, parseTime] = measure(() =>\n\t\t\t\t\t\t\tparseCompactSnapshotResponse(new Uint8Array(content), logger),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tsnapshotContents.snapshotTree.trees === undefined ||\n\t\t\t\t\t\t\tsnapshotContents.snapshotTree.blobs === undefined\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\t\t\t\"Returned odsp snapshot is malformed. No trees or blobs!\",\n\t\t\t\t\t\t\t\tDriverErrorType.incorrectServerResponse,\n\t\t\t\t\t\t\t\tpropsToLog,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst props = snapshotContents.telemetryProps;\n\t\t\t\t\t\tconst slowTreeParseCodePaths = props.slowTreeStructureCount ?? 0;\n\t\t\t\t\t\tconst slowBlobParseCodePaths = props.slowBlobStructureCount ?? 0;\n\t\t\t\t\t\tif (slowTreeParseCodePaths > 10 || slowBlobParseCodePaths > 10) {\n\t\t\t\t\t\t\tlogger.sendErrorEvent({\n\t\t\t\t\t\t\t\teventName: \"SlowSnapshotParseCodePaths\",\n\t\t\t\t\t\t\t\tslowTreeStructureCount: slowTreeParseCodePaths,\n\t\t\t\t\t\t\t\tslowBlobStructureCount: slowBlobParseCodePaths,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tparsedSnapshotContents = { ...odspResponse, content: snapshotContents };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\t\t\"Unknown snapshot content type\",\n\t\t\t\t\t\t\tDriverErrorType.incorrectServerResponse,\n\t\t\t\t\t\t\tpropsToLog,\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (isFluidError(error)) {\n\t\t\t\t\terror.addTelemetryProperties(propsToLog);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tconst enhancedError = wrapError(\n\t\t\t\t\terror,\n\t\t\t\t\t(errorMessage) =>\n\t\t\t\t\t\tnew NonRetryableError(\n\t\t\t\t\t\t\t`Error parsing snapshot response: ${errorMessage}`,\n\t\t\t\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t\t\t\tpropsToLog,\n\t\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tthrow enhancedError;\n\t\t\t}\n\n\t\t\tassert(parsedSnapshotContents !== undefined, 0x312 /* snapshot should be parsed */);\n\t\t\tconst snapshot = parsedSnapshotContents.content;\n\t\t\tconst { trees, numBlobs, encodedBlobsSize } = evalBlobsAndTrees(snapshot);\n\n\t\t\t// There are some scenarios in ODSP where we cannot cache, trees/latest will explicitly tell us when we\n\t\t\t// cannot cache using an HTTP response header.\n\t\t\tconst canCache =\n\t\t\t\todspResponse.headers.get(\"disablebrowsercachingofusercontent\") !== \"true\";\n\t\t\tconst sequenceNumber: number = snapshot.sequenceNumber ?? 0;\n\t\t\tconst seqNumberFromOps =\n\t\t\t\tsnapshot.ops && snapshot.ops.length > 0\n\t\t\t\t\t? snapshot.ops[0].sequenceNumber - 1\n\t\t\t\t\t: undefined;\n\n\t\t\tif (\n\t\t\t\t!Number.isInteger(sequenceNumber) ||\n\t\t\t\t(seqNumberFromOps !== undefined && seqNumberFromOps !== sequenceNumber)\n\t\t\t) {\n\t\t\t\tlogger.sendErrorEvent({\n\t\t\t\t\teventName: \"fetchSnapshotError\",\n\t\t\t\t\tsequenceNumber,\n\t\t\t\t\tseqNumberFromOps,\n\t\t\t\t});\n\t\t\t\tsnapshot.sequenceNumber = undefined;\n\t\t\t} else if (canCache) {\n\t\t\t\tconst fluidEpoch = odspResponse.headers.get(\"x-fluid-epoch\");\n\t\t\t\tassert(\n\t\t\t\t\tfluidEpoch !== undefined,\n\t\t\t\t\t0x1e6 /* \"Epoch should be present in response\" */,\n\t\t\t\t);\n\t\t\t\tconst value: ISnapshotCachedEntry = {\n\t\t\t\t\t...snapshot,\n\t\t\t\t\tcacheEntryTime: Date.now(),\n\t\t\t\t};\n\t\t\t\tconst valueWithEpoch: IVersionedValueWithEpoch = {\n\t\t\t\t\tvalue,\n\t\t\t\t\tfluidEpoch,\n\t\t\t\t\tversion: persistedCacheValueVersion,\n\t\t\t\t};\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-floating-promises\n\t\t\t\tputInCache(valueWithEpoch);\n\t\t\t}\n\n\t\t\tevent.end({\n\t\t\t\ttrees,\n\t\t\t\tblobs: snapshot.blobs?.size ?? 0,\n\t\t\t\tleafNodes: numBlobs,\n\t\t\t\tencodedBlobsSize,\n\t\t\t\tsequenceNumber,\n\t\t\t\tops: snapshot.ops?.length ?? 0,\n\t\t\t\tuserOps: snapshot.ops?.filter((op) => isRuntimeMessage(op)).length ?? 0,\n\t\t\t\theaders: Object.keys(response.requestHeaders).length !== 0 ? true : undefined,\n\t\t\t\t// Measures time to make fetch call. Should be similar to\n\t\t\t\t// fetchStartToResponseEndTime - receiveContentTime, i.e. it looks like it's time till first byte /\n\t\t\t\t// end of response headers\n\t\t\t\tfetchTime,\n\t\t\t\t// time it takes client to parse payload. Same payload as in \"SnapshotParse\" event, here for\n\t\t\t\t// easier analyzes.\n\t\t\t\tparseTime,\n\t\t\t\t// Time it takes to receive content (text of buffer) from Response object.\n\t\t\t\t// This time likely is very closely correlated with networkTime, i.e. time it takes to receive\n\t\t\t\t// actual content (starting measuring from first bite / end of response header)\n\t\t\t\treceiveContentTime,\n\t\t\t\t...getW3CData(response.requestUrl, \"fetch\"),\n\t\t\t\t// Sharing link telemetry regarding sharing link redeem status and performance. Ex: FRL; dur=100,\n\t\t\t\t// Azure Fluid Relay service; desc=S, FRP; desc=False. Here, FRL is the duration taken for redeem,\n\t\t\t\t// Azure Fluid Relay service is the redeem status (S means success), and FRP is a flag to indicate\n\t\t\t\t// if the permission has changed.\n\t\t\t\tsltelemetry: odspResponse.headers.get(\"x-fluid-sltelemetry\"),\n\t\t\t\t// All other props\n\t\t\t\t...propsToLog,\n\t\t\t\t// Various perf counters and measures collected by binary parsing code:\n\t\t\t\t// slowTreeStructureCount, slowBlobStructureCount, durationStructure, durationStrings,\n\t\t\t\t// durationSnapshotTree, durationBlobs, etc.\n\t\t\t\t...parsedSnapshotContents.content.telemetryProps,\n\t\t\t});\n\t\t\treturn snapshot;\n\t\t}).catch((error) => {\n\t\t\t// We hit these errors in stress tests, under load\n\t\t\t// It's useful to try one more time in such case.\n\t\t\tif (\n\t\t\t\ttypeof error === \"object\" &&\n\t\t\t\terror !== null &&\n\t\t\t\t(error.errorType === DriverErrorType.fetchFailure ||\n\t\t\t\t\terror.errorType === OdspErrorType.fetchTimeout)\n\t\t\t) {\n\t\t\t\terror[getWithRetryForTokenRefreshRepeat] = true;\n\t\t\t}\n\t\t\tthrow error;\n\t\t});\n\t});\n}\n\nexport interface ISnapshotRequestAndResponseOptions {\n\todspResponse: IOdspResponse<Response>;\n\trequestUrl: string;\n\trequestHeaders: { [index: string]: any };\n}\n\nfunction getFormBodyAndHeaders(\n\todspResolvedUrl: IOdspResolvedUrl,\n\tstorageToken: string,\n\tsnapshotOptions: ISnapshotOptions | undefined,\n\theaders?: { [index: string]: string },\n) {\n\tconst formBoundary = uuid();\n\tconst formParams: string[] = [];\n\tformParams.push(`--${formBoundary}`);\n\tformParams.push(`Authorization: Bearer ${storageToken}`);\n\tformParams.push(`X-HTTP-Method-Override: GET`);\n\tif (snapshotOptions !== undefined) {\n\t\tObject.entries(snapshotOptions).forEach(([key, value]) => {\n\t\t\tif (value !== undefined) {\n\t\t\t\tformParams.push(`${key}: ${value}`);\n\t\t\t}\n\t\t});\n\t}\n\tif (headers !== undefined) {\n\t\tObject.entries(headers).forEach(([key, value]) => {\n\t\t\tif (value !== undefined) {\n\t\t\t\tformParams.push(`${key}: ${value}`);\n\t\t\t}\n\t\t});\n\t}\n\tif (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem) {\n\t\tformParams.push(`sl: ${odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem}`);\n\t}\n\tformParams.push(`_post: 1`);\n\tformParams.push(`\\r\\n--${formBoundary}--`);\n\tconst postBody = formParams.join(\"\\r\\n\");\n\tconst header: { [index: string]: any } = {\n\t\t\"Content-Type\": `multipart/form-data;boundary=${formBoundary}`,\n\t};\n\treturn { body: postBody, headers: header };\n}\n\nfunction evalBlobsAndTrees(snapshot: ISnapshotContents) {\n\tconst trees = countTreesInSnapshotTree(snapshot.snapshotTree);\n\tconst numBlobs = snapshot.blobs.size;\n\tlet encodedBlobsSize = 0;\n\tfor (const [_, blobContent] of snapshot.blobs) {\n\t\tencodedBlobsSize += blobContent.byteLength;\n\t}\n\treturn { trees, numBlobs, encodedBlobsSize };\n}\n\nexport function validateBlobsAndTrees(snapshot: IOdspSnapshot) {\n\tassert(\n\t\tsnapshot.trees !== undefined,\n\t\t0x200 /* \"Returned odsp snapshot is malformed. No trees!\" */,\n\t);\n\tassert(\n\t\tsnapshot.blobs !== undefined,\n\t\t0x201 /* \"Returned odsp snapshot is malformed. No blobs!\" */,\n\t);\n}\n\nfunction countTreesInSnapshotTree(snapshotTree: ISnapshotTree): number {\n\tlet numTrees = 0;\n\tfor (const [_, tree] of Object.entries(snapshotTree.trees)) {\n\t\tnumTrees += 1;\n\t\tnumTrees += countTreesInSnapshotTree(tree);\n\t}\n\treturn numTrees;\n}\n\n/**\n * This function fetches the snapshot and parse it according to what is mentioned in response headers.\n * @param odspResolvedUrl - resolved odsp url.\n * @param storageToken - token to do the auth for network request.\n * @param snapshotOptions - Options used to specify how and what to fetch in the snapshot.\n * @param logger - logger\n * @param snapshotFormatFetchType - Snapshot format to fetch.\n * @param controller - abort controller if caller needs to abort the network call.\n * @param epochTracker - epoch tracker used to add/validate epoch in the network call.\n * @returns fetched snapshot.\n */\nexport async function downloadSnapshot(\n\todspResolvedUrl: IOdspResolvedUrl,\n\tstorageToken: string,\n\tlogger: ITelemetryLogger,\n\tsnapshotOptions: ISnapshotOptions | undefined,\n\tsnapshotFormatFetchType?: SnapshotFormatSupportType,\n\tcontroller?: AbortController,\n\tepochTracker?: EpochTracker,\n\tscenarioName?: string,\n): Promise<ISnapshotRequestAndResponseOptions> {\n\t// back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51\n\tconst sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;\n\tif (sharingLinkToRedeem) {\n\t\todspResolvedUrl.shareLinkInfo = { ...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem };\n\t}\n\n\tconst snapshotUrl = odspResolvedUrl.endpoints.snapshotStorageUrl;\n\tconst url = `${snapshotUrl}/trees/latest?ump=1`;\n\t// The location of file can move on Spo in which case server returns 308(Permanent Redirect) error.\n\t// Adding below header will make VROOM API return 404 instead of 308 and browser can intercept it.\n\t// This error thrown by server will contain the new redirect location. Look at the 404 error parsing\n\t// for futher reference here: \\packages\\utils\\odsp-doclib-utils\\src\\odspErrorUtils.ts\n\tconst header = { prefer: \"manualredirect\" };\n\tconst { body, headers } = getFormBodyAndHeaders(\n\t\todspResolvedUrl,\n\t\tstorageToken,\n\t\tsnapshotOptions,\n\t\theader,\n\t);\n\tconst fetchOptions = {\n\t\tbody,\n\t\theaders,\n\t\tsignal: controller?.signal,\n\t\tmethod: \"POST\",\n\t};\n\t// Decide what snapshot format to fetch as per the feature gate.\n\tswitch (snapshotFormatFetchType) {\n\t\tcase SnapshotFormatSupportType.Binary:\n\t\t\theaders.accept = `application/ms-fluid; v=${currentReadVersion}`;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t// By default ask both versions and let the server decide the format.\n\t\t\theaders.accept = `application/json, application/ms-fluid; v=${currentReadVersion}`;\n\t}\n\n\tconst odspResponse = await (epochTracker?.fetch(\n\t\turl,\n\t\tfetchOptions,\n\t\t\"treesLatest\",\n\t\ttrue,\n\t\tscenarioName,\n\t) ?? fetchHelper(url, fetchOptions));\n\n\treturn {\n\t\todspResponse,\n\t\trequestHeaders: headers,\n\t\trequestUrl: url,\n\t};\n}\n\nfunction isRedeemSharingLinkError(odspResolvedUrl: IOdspResolvedUrl, error: any) {\n\tif (\n\t\todspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined &&\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t(error.errorType === DriverErrorType.authorizationError ||\n\t\t\terror.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError)\n\t) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nfunction getEncodedShareUrl(url: string): string {\n\t/**\n\t * Encode the url to accepted format by Sharepoint\n\t * https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/shares_get\n\t */\n\tlet encodedUrl = fromUtf8ToBase64(encodeURI(url));\n\tencodedUrl = encodedUrl.replace(/=+$/g, \"\").replace(/\\//g, \"_\").replace(/\\+/g, \"-\");\n\tencodedUrl = \"u!\".concat(encodedUrl);\n\treturn encodedUrl;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"fetchSnapshot.js","sourceRoot":"","sources":["../src/fetchSnapshot.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 { default as AbortController } from \"abort-controller\";\nimport { v4 as uuid } from \"uuid\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, fromUtf8ToBase64 } from \"@fluidframework/common-utils\";\nimport { getW3CData } from \"@fluidframework/driver-base\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport { isFluidError, PerformanceEvent, wrapError } from \"@fluidframework/telemetry-utils\";\nimport {\n\tIOdspResolvedUrl,\n\tISnapshotOptions,\n\tOdspErrorType,\n\tInstrumentedStorageTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport {\n\tDriverErrorTelemetryProps,\n\tisRuntimeMessage,\n\tNonRetryableError,\n} from \"@fluidframework/driver-utils\";\nimport {\n\tIOdspSnapshot,\n\tISnapshotCachedEntry,\n\tIVersionedValueWithEpoch,\n\tpersistedCacheValueVersion,\n} from \"./contracts\";\nimport { getQueryString } from \"./getQueryString\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport {\n\tfetchAndParseAsJSONHelper,\n\tfetchHelper,\n\tgetWithRetryForTokenRefresh,\n\tgetWithRetryForTokenRefreshRepeat,\n\tIOdspResponse,\n\tmeasure,\n\tmeasureP,\n} from \"./odspUtils\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { convertOdspSnapshotToSnapshotTreeAndBlobs } from \"./odspSnapshotParser\";\nimport {\n\tcurrentReadVersion,\n\tISnapshotContentsWithProps,\n\tparseCompactSnapshotResponse,\n} from \"./compactSnapshotParser\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { pkgVersion } from \"./packageVersion\";\n\n/**\n * Enum to support different types of snapshot formats.\n */\nexport enum SnapshotFormatSupportType {\n\tJson = 0,\n\tBinary = 1,\n\tJsonAndBinary = 2,\n}\n\n/**\n * Fetches a snapshot from the server with a given version id.\n * @param snapshotUrl - snapshot url from where the odsp snapshot will be fetched\n * @param token - token used for authorization in the request\n * @param storageFetchWrapper - Implementation of the get/post methods used to fetch the snapshot\n * @param versionId - id of specific snapshot to be fetched\n * @param fetchFullSnapshot - whether we want to fetch full snapshot(with blobs)\n * @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header\n * @returns A promise of the snapshot and the status code of the response\n */\nexport async function fetchSnapshot(\n\tsnapshotUrl: string,\n\t// eslint-disable-next-line @rushstack/no-new-null\n\ttoken: string | null,\n\tversionId: string,\n\tfetchFullSnapshot: boolean,\n\tforceAccessTokenViaAuthorizationHeader: boolean,\n\tlogger: ITelemetryLogger,\n\tsnapshotDownloader: (\n\t\turl: string,\n\t\tfetchOptions: { [index: string]: any },\n\t) => Promise<IOdspResponse<unknown>>,\n): Promise<ISnapshotContents> {\n\tconst path = `/trees/${versionId}`;\n\tlet queryParams: ISnapshotOptions = {};\n\n\tif (fetchFullSnapshot) {\n\t\tqueryParams = versionId !== \"latest\" ? { blobs: 2 } : { deltas: 1, blobs: 2 };\n\t}\n\n\tconst queryString = getQueryString(queryParams);\n\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t`${snapshotUrl}${path}${queryString}`,\n\t\ttoken,\n\t\tforceAccessTokenViaAuthorizationHeader,\n\t);\n\tconst response = (await PerformanceEvent.timedExecAsync(\n\t\tlogger,\n\t\t{\n\t\t\teventName: \"fetchSnapshot\",\n\t\t\theaders: Object.keys(headers).length !== 0 ? true : undefined,\n\t\t},\n\t\tasync () => snapshotDownloader(url, { headers }),\n\t)) as IOdspResponse<IOdspSnapshot>;\n\treturn convertOdspSnapshotToSnapshotTreeAndBlobs(response.content);\n}\n\nexport async function fetchSnapshotWithRedeem(\n\todspResolvedUrl: IOdspResolvedUrl,\n\tstorageTokenFetcher: InstrumentedStorageTokenFetcher,\n\tsnapshotOptions: ISnapshotOptions | undefined,\n\tforceAccessTokenViaAuthorizationHeader: boolean,\n\tlogger: ITelemetryLogger,\n\tsnapshotDownloader: (\n\t\tfinalOdspResolvedUrl: IOdspResolvedUrl,\n\t\tstorageToken: string,\n\t\tsnapshotOptions: ISnapshotOptions | undefined,\n\t\tcontroller?: AbortController,\n\t) => Promise<ISnapshotRequestAndResponseOptions>,\n\tputInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n\tremoveEntries: () => Promise<void>,\n\tenableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n\t// back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51\n\tconst sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;\n\tif (sharingLinkToRedeem) {\n\t\todspResolvedUrl.shareLinkInfo = { ...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem };\n\t}\n\n\treturn fetchLatestSnapshotCore(\n\t\todspResolvedUrl,\n\t\tstorageTokenFetcher,\n\t\tsnapshotOptions,\n\t\tlogger,\n\t\tsnapshotDownloader,\n\t\tputInCache,\n\t\tenableRedeemFallback,\n\t)\n\t\t.catch(async (error) => {\n\t\t\tif (enableRedeemFallback && isRedeemSharingLinkError(odspResolvedUrl, error)) {\n\t\t\t\t// Execute the redeem fallback\n\n\t\t\t\tawait redeemSharingLink(\n\t\t\t\t\todspResolvedUrl,\n\t\t\t\t\tstorageTokenFetcher,\n\t\t\t\t\tlogger,\n\t\t\t\t\tforceAccessTokenViaAuthorizationHeader,\n\t\t\t\t);\n\t\t\t\tconst odspResolvedUrlWithoutShareLink: IOdspResolvedUrl = {\n\t\t\t\t\t...odspResolvedUrl,\n\t\t\t\t\tshareLinkInfo: {\n\t\t\t\t\t\t...odspResolvedUrl.shareLinkInfo,\n\t\t\t\t\t\tsharingLinkToRedeem: undefined,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\t// Log initial failure only if redeem succeeded - it points out to some bug somewhere\n\t\t\t\t// If redeem failed, that most likely means user has no permissions to access a file,\n\t\t\t\t// and thus it's not worth it logging extra errors - same error will be logged by end-to-end\n\t\t\t\t// flow (container open) based on a failure above.\n\t\t\t\tlogger.sendErrorEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"RedeemFallback\",\n\t\t\t\t\t\terrorType: error.errorType,\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\n\t\t\t\treturn fetchLatestSnapshotCore(\n\t\t\t\t\todspResolvedUrlWithoutShareLink,\n\t\t\t\t\tstorageTokenFetcher,\n\t\t\t\t\tsnapshotOptions,\n\t\t\t\t\tlogger,\n\t\t\t\t\tsnapshotDownloader,\n\t\t\t\t\tputInCache,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t})\n\t\t.catch(async (error) => {\n\t\t\t// Clear the cache on 401/403/404 on snapshot fetch from network because this means either the user doesn't\n\t\t\t// have permissions for the file or it was deleted. So, if we do not clear cache, we will continue fetching\n\t\t\t// snapshot from cache in the future.\n\t\t\tif (\n\t\t\t\t(typeof error === \"object\" &&\n\t\t\t\t\terror !== null &&\n\t\t\t\t\terror.errorType === DriverErrorType.authorizationError) ||\n\t\t\t\terror.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError\n\t\t\t) {\n\t\t\t\tawait removeEntries();\n\t\t\t}\n\t\t\tthrow error;\n\t\t});\n}\n\nasync function redeemSharingLink(\n\todspResolvedUrl: IOdspResolvedUrl,\n\tstorageTokenFetcher: InstrumentedStorageTokenFetcher,\n\tlogger: ITelemetryLogger,\n\tforceAccessTokenViaAuthorizationHeader: boolean,\n) {\n\treturn PerformanceEvent.timedExecAsync(\n\t\tlogger,\n\t\t{\n\t\t\teventName: \"RedeemShareLink\",\n\t\t},\n\t\tasync () =>\n\t\t\tgetWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n\t\t\t\tassert(\n\t\t\t\t\t!!odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem,\n\t\t\t\t\t0x1ed /* \"Share link should be present\" */,\n\t\t\t\t);\n\t\t\t\tconst storageToken = await storageTokenFetcher(\n\t\t\t\t\ttokenFetchOptions,\n\t\t\t\t\t\"RedeemShareLink\",\n\t\t\t\t);\n\t\t\t\tconst encodedShareUrl = getEncodedShareUrl(\n\t\t\t\t\todspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem,\n\t\t\t\t);\n\t\t\t\tconst redeemUrl = `${odspResolvedUrl.siteUrl}/_api/v2.0/shares/${encodedShareUrl}`;\n\t\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\t\tredeemUrl,\n\t\t\t\t\tstorageToken,\n\t\t\t\t\tforceAccessTokenViaAuthorizationHeader,\n\t\t\t\t);\n\t\t\t\theaders.prefer = \"redeemSharingLink\";\n\t\t\t\treturn fetchAndParseAsJSONHelper(url, { headers });\n\t\t\t}),\n\t);\n}\n\nasync function fetchLatestSnapshotCore(\n\todspResolvedUrl: IOdspResolvedUrl,\n\tstorageTokenFetcher: InstrumentedStorageTokenFetcher,\n\tsnapshotOptions: ISnapshotOptions | undefined,\n\tlogger: ITelemetryLogger,\n\tsnapshotDownloader: (\n\t\tfinalOdspResolvedUrl: IOdspResolvedUrl,\n\t\tstorageToken: string,\n\t\tsnapshotOptions: ISnapshotOptions | undefined,\n\t\tcontroller?: AbortController,\n\t) => Promise<ISnapshotRequestAndResponseOptions>,\n\tputInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n\tenableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n\treturn getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n\t\tconst storageToken = await storageTokenFetcher(tokenFetchOptions, \"TreesLatest\", true);\n\t\tassert(storageToken !== null, 0x1e5 /* \"Storage token should not be null\" */);\n\n\t\tconst perfEvent = {\n\t\t\teventName: \"TreesLatest\",\n\t\t\tattempts: tokenFetchOptions.refresh ? 2 : 1,\n\t\t\tshareLinkPresent: odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined,\n\t\t\tisSummarizer: odspResolvedUrl.summarizer,\n\t\t\tredeemFallbackEnabled: enableRedeemFallback,\n\t\t};\n\t\tif (snapshotOptions !== undefined) {\n\t\t\tObject.entries(snapshotOptions).forEach(([key, value]) => {\n\t\t\t\tif (value !== undefined) {\n\t\t\t\t\tperfEvent[`snapshotOption_${key}`] = value;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t// This event measures only successful cases of getLatest call (no tokens, no retries).\n\t\treturn PerformanceEvent.timedExecAsync(logger, perfEvent, async (event) => {\n\t\t\tlet controller: AbortController | undefined;\n\t\t\tlet fetchTimeout: ReturnType<typeof setTimeout> | undefined;\n\t\t\tif (snapshotOptions?.timeout !== undefined) {\n\t\t\t\tcontroller = new AbortController();\n\t\t\t\tfetchTimeout = setTimeout(() => controller!.abort(), snapshotOptions.timeout);\n\t\t\t}\n\n\t\t\tconst [response, fetchTime] = await measureP(async () =>\n\t\t\t\tsnapshotDownloader(odspResolvedUrl, storageToken, snapshotOptions, controller),\n\t\t\t).finally(() => {\n\t\t\t\t// Clear the fetchTimeout once the response is fetched.\n\t\t\t\tif (fetchTimeout !== undefined) {\n\t\t\t\t\tclearTimeout(fetchTimeout);\n\t\t\t\t\tfetchTimeout = undefined;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconst odspResponse = response.odspResponse;\n\t\t\tconst contentType = odspResponse.headers.get(\"content-type\");\n\n\t\t\tconst propsToLog: DriverErrorTelemetryProps = {\n\t\t\t\t...odspResponse.propsToLog,\n\t\t\t\tcontentType,\n\t\t\t\taccept: response.requestHeaders.accept,\n\t\t\t\tdriverVersion: pkgVersion,\n\t\t\t};\n\n\t\t\tlet parsedSnapshotContents: IOdspResponse<ISnapshotContentsWithProps> | undefined;\n\t\t\tlet contentTypeToRead: string | undefined;\n\t\t\tif (contentType?.includes(\"application/ms-fluid\")) {\n\t\t\t\tcontentTypeToRead = \"application/ms-fluid\";\n\t\t\t} else if (contentType?.includes(\"application/json\")) {\n\t\t\t\tcontentTypeToRead = \"application/json\";\n\t\t\t}\n\n\t\t\tlet parseTime: number;\n\t\t\tlet receiveContentTime: number;\n\t\t\ttry {\n\t\t\t\tswitch (contentTypeToRead) {\n\t\t\t\t\tcase \"application/json\": {\n\t\t\t\t\t\tlet text: string;\n\t\t\t\t\t\t[text, receiveContentTime] = await measureP(async () =>\n\t\t\t\t\t\t\todspResponse.content.text(),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tpropsToLog.bodySize = text.length;\n\t\t\t\t\t\tlet content: IOdspSnapshot;\n\t\t\t\t\t\t[content, parseTime] = measure(() => JSON.parse(text) as IOdspSnapshot);\n\t\t\t\t\t\tvalidateBlobsAndTrees(content);\n\t\t\t\t\t\tconst snapshotContents: ISnapshotContents =\n\t\t\t\t\t\t\tconvertOdspSnapshotToSnapshotTreeAndBlobs(content);\n\t\t\t\t\t\tparsedSnapshotContents = {\n\t\t\t\t\t\t\t...odspResponse,\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t...snapshotContents,\n\t\t\t\t\t\t\t\ttelemetryProps: {},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"application/ms-fluid\": {\n\t\t\t\t\t\tlet content: ArrayBuffer;\n\t\t\t\t\t\t[content, receiveContentTime] = await measureP(async () =>\n\t\t\t\t\t\t\todspResponse.content.arrayBuffer(),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tpropsToLog.bodySize = content.byteLength;\n\t\t\t\t\t\tlet snapshotContents: ISnapshotContentsWithProps;\n\t\t\t\t\t\t[snapshotContents, parseTime] = measure(() =>\n\t\t\t\t\t\t\tparseCompactSnapshotResponse(new Uint8Array(content), logger),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tsnapshotContents.snapshotTree.trees === undefined ||\n\t\t\t\t\t\t\tsnapshotContents.snapshotTree.blobs === undefined\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\t\t\t\"Returned odsp snapshot is malformed. No trees or blobs!\",\n\t\t\t\t\t\t\t\tDriverErrorType.incorrectServerResponse,\n\t\t\t\t\t\t\t\tpropsToLog,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst props = snapshotContents.telemetryProps;\n\t\t\t\t\t\tconst slowTreeParseCodePaths = props.slowTreeStructureCount ?? 0;\n\t\t\t\t\t\tconst slowBlobParseCodePaths = props.slowBlobStructureCount ?? 0;\n\t\t\t\t\t\tif (slowTreeParseCodePaths > 10 || slowBlobParseCodePaths > 10) {\n\t\t\t\t\t\t\tlogger.sendErrorEvent({\n\t\t\t\t\t\t\t\teventName: \"SlowSnapshotParseCodePaths\",\n\t\t\t\t\t\t\t\tslowTreeStructureCount: slowTreeParseCodePaths,\n\t\t\t\t\t\t\t\tslowBlobStructureCount: slowBlobParseCodePaths,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tparsedSnapshotContents = { ...odspResponse, content: snapshotContents };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\t\t\"Unknown snapshot content type\",\n\t\t\t\t\t\t\tDriverErrorType.incorrectServerResponse,\n\t\t\t\t\t\t\tpropsToLog,\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (isFluidError(error)) {\n\t\t\t\t\terror.addTelemetryProperties(propsToLog);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tconst enhancedError = wrapError(\n\t\t\t\t\terror,\n\t\t\t\t\t(errorMessage) =>\n\t\t\t\t\t\tnew NonRetryableError(\n\t\t\t\t\t\t\t`Error parsing snapshot response: ${errorMessage}`,\n\t\t\t\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t\t\t\tpropsToLog,\n\t\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tthrow enhancedError;\n\t\t\t}\n\n\t\t\tassert(parsedSnapshotContents !== undefined, 0x312 /* snapshot should be parsed */);\n\t\t\tconst snapshot = parsedSnapshotContents.content;\n\t\t\tconst { trees, numBlobs, encodedBlobsSize } = evalBlobsAndTrees(snapshot);\n\n\t\t\t// There are some scenarios in ODSP where we cannot cache, trees/latest will explicitly tell us when we\n\t\t\t// cannot cache using an HTTP response header.\n\t\t\tconst canCache =\n\t\t\t\todspResponse.headers.get(\"disablebrowsercachingofusercontent\") !== \"true\";\n\t\t\tconst sequenceNumber: number = snapshot.sequenceNumber ?? 0;\n\t\t\tconst seqNumberFromOps =\n\t\t\t\tsnapshot.ops && snapshot.ops.length > 0\n\t\t\t\t\t? snapshot.ops[0].sequenceNumber - 1\n\t\t\t\t\t: undefined;\n\n\t\t\tif (\n\t\t\t\t!Number.isInteger(sequenceNumber) ||\n\t\t\t\t(seqNumberFromOps !== undefined && seqNumberFromOps !== sequenceNumber)\n\t\t\t) {\n\t\t\t\tlogger.sendErrorEvent({\n\t\t\t\t\teventName: \"fetchSnapshotError\",\n\t\t\t\t\tsequenceNumber,\n\t\t\t\t\tseqNumberFromOps,\n\t\t\t\t});\n\t\t\t\tsnapshot.sequenceNumber = undefined;\n\t\t\t} else if (canCache) {\n\t\t\t\tconst fluidEpoch = odspResponse.headers.get(\"x-fluid-epoch\");\n\t\t\t\tassert(\n\t\t\t\t\tfluidEpoch !== undefined,\n\t\t\t\t\t0x1e6 /* \"Epoch should be present in response\" */,\n\t\t\t\t);\n\t\t\t\tconst value: ISnapshotCachedEntry = {\n\t\t\t\t\t...snapshot,\n\t\t\t\t\tcacheEntryTime: Date.now(),\n\t\t\t\t};\n\t\t\t\tconst valueWithEpoch: IVersionedValueWithEpoch = {\n\t\t\t\t\tvalue,\n\t\t\t\t\tfluidEpoch,\n\t\t\t\t\tversion: persistedCacheValueVersion,\n\t\t\t\t};\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-floating-promises\n\t\t\t\tputInCache(valueWithEpoch);\n\t\t\t}\n\n\t\t\tevent.end({\n\t\t\t\ttrees,\n\t\t\t\tblobs: snapshot.blobs?.size ?? 0,\n\t\t\t\tleafNodes: numBlobs,\n\t\t\t\tencodedBlobsSize,\n\t\t\t\tsequenceNumber,\n\t\t\t\tops: snapshot.ops?.length ?? 0,\n\t\t\t\tuserOps: snapshot.ops?.filter((op) => isRuntimeMessage(op)).length ?? 0,\n\t\t\t\theaders: Object.keys(response.requestHeaders).length !== 0 ? true : undefined,\n\t\t\t\t// Measures time to make fetch call. Should be similar to\n\t\t\t\t// fetchStartToResponseEndTime - receiveContentTime, i.e. it looks like it's time till first byte /\n\t\t\t\t// end of response headers\n\t\t\t\tfetchTime,\n\t\t\t\t// time it takes client to parse payload. Same payload as in \"SnapshotParse\" event, here for\n\t\t\t\t// easier analyzes.\n\t\t\t\tparseTime,\n\t\t\t\t// Time it takes to receive content (text of buffer) from Response object.\n\t\t\t\t// This time likely is very closely correlated with networkTime, i.e. time it takes to receive\n\t\t\t\t// actual content (starting measuring from first bite / end of response header)\n\t\t\t\treceiveContentTime,\n\t\t\t\t...getW3CData(response.requestUrl, \"fetch\"),\n\t\t\t\t// Sharing link telemetry regarding sharing link redeem status and performance. Ex: FRL; dur=100,\n\t\t\t\t// Azure Fluid Relay service; desc=S, FRP; desc=False. Here, FRL is the duration taken for redeem,\n\t\t\t\t// Azure Fluid Relay service is the redeem status (S means success), and FRP is a flag to indicate\n\t\t\t\t// if the permission has changed.\n\t\t\t\tsltelemetry: odspResponse.headers.get(\"x-fluid-sltelemetry\"),\n\t\t\t\t// All other props\n\t\t\t\t...propsToLog,\n\t\t\t\t// Various perf counters and measures collected by binary parsing code:\n\t\t\t\t// slowTreeStructureCount, slowBlobStructureCount, durationStructure, durationStrings,\n\t\t\t\t// durationSnapshotTree, durationBlobs, etc.\n\t\t\t\t...parsedSnapshotContents.content.telemetryProps,\n\t\t\t});\n\t\t\treturn snapshot;\n\t\t}).catch((error) => {\n\t\t\t// We hit these errors in stress tests, under load\n\t\t\t// It's useful to try one more time in such case.\n\t\t\tif (\n\t\t\t\ttypeof error === \"object\" &&\n\t\t\t\terror !== null &&\n\t\t\t\t(error.errorType === DriverErrorType.fetchFailure ||\n\t\t\t\t\terror.errorType === OdspErrorType.fetchTimeout)\n\t\t\t) {\n\t\t\t\terror[getWithRetryForTokenRefreshRepeat] = true;\n\t\t\t}\n\t\t\tthrow error;\n\t\t});\n\t});\n}\n\nexport interface ISnapshotRequestAndResponseOptions {\n\todspResponse: IOdspResponse<Response>;\n\trequestUrl: string;\n\trequestHeaders: { [index: string]: any };\n}\n\nfunction getFormBodyAndHeaders(\n\todspResolvedUrl: IOdspResolvedUrl,\n\tstorageToken: string,\n\tsnapshotOptions: ISnapshotOptions | undefined,\n\theaders?: { [index: string]: string },\n) {\n\tconst formBoundary = uuid();\n\tconst formParams: string[] = [];\n\tformParams.push(`--${formBoundary}`);\n\tformParams.push(`Authorization: Bearer ${storageToken}`);\n\tformParams.push(`X-HTTP-Method-Override: GET`);\n\tif (snapshotOptions !== undefined) {\n\t\tObject.entries(snapshotOptions).forEach(([key, value]) => {\n\t\t\tif (value !== undefined) {\n\t\t\t\tformParams.push(`${key}: ${value}`);\n\t\t\t}\n\t\t});\n\t}\n\tif (headers !== undefined) {\n\t\tObject.entries(headers).forEach(([key, value]) => {\n\t\t\tif (value !== undefined) {\n\t\t\t\tformParams.push(`${key}: ${value}`);\n\t\t\t}\n\t\t});\n\t}\n\tif (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem) {\n\t\tformParams.push(`sl: ${odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem}`);\n\t}\n\tformParams.push(`_post: 1`);\n\tformParams.push(`\\r\\n--${formBoundary}--`);\n\tconst postBody = formParams.join(\"\\r\\n\");\n\tconst header: { [index: string]: any } = {\n\t\t\"Content-Type\": `multipart/form-data;boundary=${formBoundary}`,\n\t};\n\treturn { body: postBody, headers: header };\n}\n\nexport function evalBlobsAndTrees(snapshot: ISnapshotContents) {\n\tconst trees = countTreesInSnapshotTree(snapshot.snapshotTree);\n\tconst numBlobs = snapshot.blobs.size;\n\tlet encodedBlobsSize = 0;\n\tfor (const [_, blobContent] of snapshot.blobs) {\n\t\tencodedBlobsSize += blobContent.byteLength;\n\t}\n\treturn { trees, numBlobs, encodedBlobsSize };\n}\n\nexport function validateBlobsAndTrees(snapshot: IOdspSnapshot) {\n\tassert(\n\t\tsnapshot.trees !== undefined,\n\t\t0x200 /* \"Returned odsp snapshot is malformed. No trees!\" */,\n\t);\n\tassert(\n\t\tsnapshot.blobs !== undefined,\n\t\t0x201 /* \"Returned odsp snapshot is malformed. No blobs!\" */,\n\t);\n}\n\nfunction countTreesInSnapshotTree(snapshotTree: ISnapshotTree): number {\n\tlet numTrees = 0;\n\tfor (const [_, tree] of Object.entries(snapshotTree.trees)) {\n\t\tnumTrees += 1;\n\t\tnumTrees += countTreesInSnapshotTree(tree);\n\t}\n\treturn numTrees;\n}\n\n/**\n * This function fetches the snapshot and parse it according to what is mentioned in response headers.\n * @param odspResolvedUrl - resolved odsp url.\n * @param storageToken - token to do the auth for network request.\n * @param snapshotOptions - Options used to specify how and what to fetch in the snapshot.\n * @param logger - logger\n * @param snapshotFormatFetchType - Snapshot format to fetch.\n * @param controller - abort controller if caller needs to abort the network call.\n * @param epochTracker - epoch tracker used to add/validate epoch in the network call.\n * @returns fetched snapshot.\n */\nexport async function downloadSnapshot(\n\todspResolvedUrl: IOdspResolvedUrl,\n\tstorageToken: string,\n\tlogger: ITelemetryLogger,\n\tsnapshotOptions: ISnapshotOptions | undefined,\n\tsnapshotFormatFetchType?: SnapshotFormatSupportType,\n\tcontroller?: AbortController,\n\tepochTracker?: EpochTracker,\n\tscenarioName?: string,\n): Promise<ISnapshotRequestAndResponseOptions> {\n\t// back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51\n\tconst sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;\n\tif (sharingLinkToRedeem) {\n\t\todspResolvedUrl.shareLinkInfo = { ...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem };\n\t}\n\n\tconst snapshotUrl = odspResolvedUrl.endpoints.snapshotStorageUrl;\n\tconst url = `${snapshotUrl}/trees/latest?ump=1`;\n\t// The location of file can move on Spo in which case server returns 308(Permanent Redirect) error.\n\t// Adding below header will make VROOM API return 404 instead of 308 and browser can intercept it.\n\t// This error thrown by server will contain the new redirect location. Look at the 404 error parsing\n\t// for futher reference here: \\packages\\utils\\odsp-doclib-utils\\src\\odspErrorUtils.ts\n\tconst header = { prefer: \"manualredirect\" };\n\tconst { body, headers } = getFormBodyAndHeaders(\n\t\todspResolvedUrl,\n\t\tstorageToken,\n\t\tsnapshotOptions,\n\t\theader,\n\t);\n\tconst fetchOptions = {\n\t\tbody,\n\t\theaders,\n\t\tsignal: controller?.signal,\n\t\tmethod: \"POST\",\n\t};\n\t// Decide what snapshot format to fetch as per the feature gate.\n\tswitch (snapshotFormatFetchType) {\n\t\tcase SnapshotFormatSupportType.Binary:\n\t\t\theaders.accept = `application/ms-fluid; v=${currentReadVersion}`;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t// By default ask both versions and let the server decide the format.\n\t\t\theaders.accept = `application/json, application/ms-fluid; v=${currentReadVersion}`;\n\t}\n\n\tconst odspResponse = await (epochTracker?.fetch(\n\t\turl,\n\t\tfetchOptions,\n\t\t\"treesLatest\",\n\t\ttrue,\n\t\tscenarioName,\n\t) ?? fetchHelper(url, fetchOptions));\n\n\treturn {\n\t\todspResponse,\n\t\trequestHeaders: headers,\n\t\trequestUrl: url,\n\t};\n}\n\nfunction isRedeemSharingLinkError(odspResolvedUrl: IOdspResolvedUrl, error: any) {\n\tif (\n\t\todspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined &&\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t(error.errorType === DriverErrorType.authorizationError ||\n\t\t\terror.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError)\n\t) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nfunction getEncodedShareUrl(url: string): string {\n\t/**\n\t * Encode the url to accepted format by Sharepoint\n\t * https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/shares_get\n\t */\n\tlet encodedUrl = fromUtf8ToBase64(encodeURI(url));\n\tencodedUrl = encodedUrl.replace(/=+$/g, \"\").replace(/\\//g, \"_\").replace(/\\+/g, \"-\");\n\tencodedUrl = \"u!\".concat(encodedUrl);\n\treturn encodedUrl;\n}\n"]}
|
|
@@ -61,7 +61,7 @@ export declare class OdspDelayLoadedDeltaStream {
|
|
|
61
61
|
private joinSessionCore;
|
|
62
62
|
private calculateJoinSessionRefreshDelta;
|
|
63
63
|
/**
|
|
64
|
-
*
|
|
64
|
+
* Creates a connection to the given delta stream endpoint
|
|
65
65
|
*
|
|
66
66
|
* @param tenantId - the ID of the tenant
|
|
67
67
|
* @param documentId - document ID
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspDelayLoadedDeltaStream.d.ts","sourceRoot":"","sources":["../src/odspDelayLoadedDeltaStream.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAEN,iBAAiB,EAEjB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACN,wBAAwB,EACxB,YAAY,EACZ,wBAAwB,EAExB,MAAM,oCAAoC,CAAC;AAK5C,OAAO,EAAE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAC1F,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,+BAA+B,EAE/B,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAG5E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C;;;GAGG;AACH,qBAAa,0BAA0B;aA0BrB,eAAe,EAAE,gBAAgB;IAC1C,QAAQ,EAAE,wBAAwB;IACzC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAGlC,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC;IAnC3C,OAAO,CAAC,uBAAuB,CAA4C;IAE3E,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC,OAAO,CAAC,iBAAiB,CAAC,CAA8B;IAExD,OAAO,CAAC,+BAA+B,CAAqB;IAE5D;;;;;;;;;;;;;;OAcG;gBAEc,eAAe,EAAE,gBAAgB,EAC1C,QAAQ,EAAE,wBAAwB,EACxB,eAAe,EAAE,+BAA+B,EAChD,iBAAiB,EAC/B,CAAC,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,GACxD,SAAS,EACK,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,iBAAiB,EAC7B,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,CAAC,GAAG,EAAE,yBAAyB,EAAE,KAAK,IAAI,EACvD,wBAAwB,CAAC,oBAAQ;IAKnD,IAAW,WAAW,IAAI,YAAY,CAErC;IAED,IAAW,sBAAsB,IAAI,2BAA2B,GAAG,SAAS,CAE3E;IAED,IAAW,8BAA8B,IAAI,MAAM,GAAG,SAAS,CAE9D;IAED,uEAAuE;IACvE,OAAO,CAAC,uBAAuB;IAa/B;;;;OAIG;IACU,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"odspDelayLoadedDeltaStream.d.ts","sourceRoot":"","sources":["../src/odspDelayLoadedDeltaStream.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAEN,iBAAiB,EAEjB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACN,wBAAwB,EACxB,YAAY,EACZ,wBAAwB,EAExB,MAAM,oCAAoC,CAAC;AAK5C,OAAO,EAAE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAC1F,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,+BAA+B,EAE/B,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAG5E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C;;;GAGG;AACH,qBAAa,0BAA0B;aA0BrB,eAAe,EAAE,gBAAgB;IAC1C,QAAQ,EAAE,wBAAwB;IACzC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAGlC,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC;IAnC3C,OAAO,CAAC,uBAAuB,CAA4C;IAE3E,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC,OAAO,CAAC,iBAAiB,CAAC,CAA8B;IAExD,OAAO,CAAC,+BAA+B,CAAqB;IAE5D;;;;;;;;;;;;;;OAcG;gBAEc,eAAe,EAAE,gBAAgB,EAC1C,QAAQ,EAAE,wBAAwB,EACxB,eAAe,EAAE,+BAA+B,EAChD,iBAAiB,EAC/B,CAAC,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,GACxD,SAAS,EACK,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,iBAAiB,EAC7B,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,CAAC,GAAG,EAAE,yBAAyB,EAAE,KAAK,IAAI,EACvD,wBAAwB,CAAC,oBAAQ;IAKnD,IAAW,WAAW,IAAI,YAAY,CAErC;IAED,IAAW,sBAAsB,IAAI,2BAA2B,GAAG,SAAS,CAE3E;IAED,IAAW,8BAA8B,IAAI,MAAM,GAAG,SAAS,CAE9D;IAED,uEAAuE;IACvE,OAAO,CAAC,uBAAuB;IAa/B;;;;OAIG;IACU,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,wBAAwB,CAAC;IA6FrF,OAAO,CAAC,qBAAqB;YAOf,0BAA0B;YAmC1B,WAAW;YAuDX,eAAe;IAqF7B,OAAO,CAAC,gCAAgC;IAQxC;;;;;;;;OAQG;YACW,qBAAqB;IAgC5B,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG;CAK1B"}
|
|
@@ -110,7 +110,7 @@ class OdspDelayLoadedDeltaStream {
|
|
|
110
110
|
this.cache.sessionJoinCache.remove(this.joinSessionKey);
|
|
111
111
|
}
|
|
112
112
|
// If we hit this assert, it means that "disconnect" event is emitted before the connection went through
|
|
113
|
-
// dispose flow which is not correct and could lead to a bunch of
|
|
113
|
+
// dispose flow which is not correct and could lead to a bunch of errors.
|
|
114
114
|
(0, common_utils_1.assert)(connection.disposed, 0x4ae /* Connection should be disposed by now */);
|
|
115
115
|
this.currentConnection = undefined;
|
|
116
116
|
});
|
|
@@ -118,6 +118,7 @@ class OdspDelayLoadedDeltaStream {
|
|
|
118
118
|
return connection;
|
|
119
119
|
}
|
|
120
120
|
catch (error) {
|
|
121
|
+
this.clearJoinSessionTimer();
|
|
121
122
|
this.cache.sessionJoinCache.remove(this.joinSessionKey);
|
|
122
123
|
const normalizedError = this.annotateConnectionError(error, "createDeltaConnection", !requestWebsocketTokenFromJoinSession);
|
|
123
124
|
if (typeof error === "object" && error !== null) {
|
|
@@ -136,6 +137,15 @@ class OdspDelayLoadedDeltaStream {
|
|
|
136
137
|
}
|
|
137
138
|
}
|
|
138
139
|
async scheduleJoinSessionRefresh(delta, requestSocketToken, clientId) {
|
|
140
|
+
if (this.joinSessionRefreshTimer !== undefined) {
|
|
141
|
+
this.clearJoinSessionTimer();
|
|
142
|
+
const originalStackTraceLimit = Error.stackTraceLimit;
|
|
143
|
+
Error.stackTraceLimit = 50;
|
|
144
|
+
this.mc.logger.sendTelemetryEvent({
|
|
145
|
+
eventName: "DuplicateJoinSessionRefresh",
|
|
146
|
+
}, new Error("DuplicateJoinSessionRefresh"));
|
|
147
|
+
Error.stackTraceLimit = originalStackTraceLimit;
|
|
148
|
+
}
|
|
139
149
|
await new Promise((resolve, reject) => {
|
|
140
150
|
this.joinSessionRefreshTimer = setTimeout(() => {
|
|
141
151
|
(0, odspUtils_1.getWithRetryForTokenRefresh)(async (options) => {
|
|
@@ -244,7 +254,7 @@ class OdspDelayLoadedDeltaStream {
|
|
|
244
254
|
return responseFetchTime + (refreshSessionDurationSeconds * 1000 - 30000) - Date.now();
|
|
245
255
|
}
|
|
246
256
|
/**
|
|
247
|
-
*
|
|
257
|
+
* Creates a connection to the given delta stream endpoint
|
|
248
258
|
*
|
|
249
259
|
* @param tenantId - the ID of the tenant
|
|
250
260
|
* @param documentId - document ID
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspDelayLoadedDeltaStream.js","sourceRoot":"","sources":["../src/odspDelayLoadedDeltaStream.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, performance } from \"@fluidframework/common-utils\";\nimport {\n\tIFluidErrorBase,\n\tMonitoringContext,\n\tnormalizeError,\n} from \"@fluidframework/telemetry-utils\";\nimport {\n\tIDocumentDeltaConnection,\n\tIResolvedUrl,\n\tIDocumentServicePolicies,\n\tDriverErrorType,\n} from \"@fluidframework/driver-definitions\";\nimport {\n\tDeltaStreamConnectionForbiddenError,\n\tNonRetryableError,\n} from \"@fluidframework/driver-utils\";\nimport { IClient, ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport {\n\tIOdspResolvedUrl,\n\tTokenFetchOptions,\n\tHostStoragePolicy,\n\tInstrumentedStorageTokenFetcher,\n\tOdspErrorType,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { hasFacetCodes } from \"@fluidframework/odsp-doclib-utils\";\nimport { ISocketStorageDiscovery } from \"./contracts\";\nimport { IOdspCache } from \"./odspCache\";\nimport { OdspDocumentDeltaConnection } from \"./odspDocumentDeltaConnection\";\nimport { getWithRetryForTokenRefresh, TokenFetchOptionsEx } from \"./odspUtils\";\nimport { fetchJoinSession } from \"./vroom\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\n\n/**\n * This OdspDelayLoadedDeltaStream is used by OdspDocumentService.ts to delay load the delta connection\n * as they are not on critical path of loading a container.\n */\nexport class OdspDelayLoadedDeltaStream {\n\t// Timer which runs and executes the join session call after intervals.\n\tprivate joinSessionRefreshTimer: ReturnType<typeof setTimeout> | undefined;\n\n\tprivate readonly joinSessionKey: string;\n\n\tprivate currentConnection?: OdspDocumentDeltaConnection;\n\n\tprivate _relayServiceTenantAndSessionId: string | undefined;\n\n\t/**\n\t * @param odspResolvedUrl - resolved url identifying document that will be managed by this service instance.\n\t * @param policies - Document service policies.\n\t * @param getStorageToken - function that can provide the storage token. This is is also referred to as\n\t * the \"Vroom\" token in SPO.\n\t * @param getWebsocketToken - function that can provide a token for accessing the web socket. This is also referred\n\t * to as the \"Push\" token in SPO. If undefined then websocket token is expected to be returned with joinSession\n\t * response payload.\n\t * @param mc - a logger that can capture performance and diagnostic information\n\t * @param cache - This caches response for joinSession.\n\t * @param hostPolicy - host constructed policy which customizes service behavior.\n\t * @param epochTracker - This helper class which adds epoch to backend calls made by this service instance.\n\t * @param opsReceived - To register the ops received through socket.\n\t * @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache\n\t */\n\tpublic constructor(\n\t\tpublic readonly odspResolvedUrl: IOdspResolvedUrl,\n\t\tpublic policies: IDocumentServicePolicies,\n\t\tprivate readonly getStorageToken: InstrumentedStorageTokenFetcher,\n\t\tprivate readonly getWebsocketToken:\n\t\t\t| ((options: TokenFetchOptions) => Promise<string | null>)\n\t\t\t| undefined,\n\t\tprivate readonly mc: MonitoringContext,\n\t\tprivate readonly cache: IOdspCache,\n\t\tprivate readonly hostPolicy: HostStoragePolicy,\n\t\tprivate readonly epochTracker: EpochTracker,\n\t\tprivate readonly opsReceived: (ops: ISequencedDocumentMessage[]) => void,\n\t\tprivate readonly socketReferenceKeyPrefix?: string,\n\t) {\n\t\tthis.joinSessionKey = `${this.odspResolvedUrl.hashedDocumentId}/joinsession`;\n\t}\n\n\tpublic get resolvedUrl(): IResolvedUrl {\n\t\treturn this.odspResolvedUrl;\n\t}\n\n\tpublic get currentDeltaConnection(): OdspDocumentDeltaConnection | undefined {\n\t\treturn this.currentConnection;\n\t}\n\n\tpublic get relayServiceTenantAndSessionId(): string | undefined {\n\t\treturn this._relayServiceTenantAndSessionId;\n\t}\n\n\t/** Annotate the given error indicating which connection step failed */\n\tprivate annotateConnectionError(\n\t\terror: any,\n\t\tfailedConnectionStep: string,\n\t\tseparateTokenRequest: boolean,\n\t): IFluidErrorBase {\n\t\treturn normalizeError(error, {\n\t\t\tprops: {\n\t\t\t\tfailedConnectionStep,\n\t\t\t\tseparateTokenRequest,\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Connects to a delta stream endpoint for emitting ops.\n\t *\n\t * @returns returns the document delta stream service for onedrive/sharepoint driver.\n\t */\n\tpublic async connectToDeltaStream(client: IClient): Promise<IDocumentDeltaConnection> {\n\t\tassert(\n\t\t\tthis.currentConnection === undefined,\n\t\t\t0x4ad /* Should not be called when connection is already present! */,\n\t\t);\n\t\t// Attempt to connect twice, in case we used expired token.\n\t\treturn getWithRetryForTokenRefresh<IDocumentDeltaConnection>(async (options) => {\n\t\t\t// Presence of getWebsocketToken callback dictates whether callback is used for fetching\n\t\t\t// websocket token or whether it is returned with joinSession response payload\n\t\t\tconst requestWebsocketTokenFromJoinSession = this.getWebsocketToken === undefined;\n\t\t\tconst websocketTokenPromise = requestWebsocketTokenFromJoinSession\n\t\t\t\t? Promise.resolve(null)\n\t\t\t\t: this.getWebsocketToken!(options);\n\n\t\t\tconst annotateAndRethrowConnectionError = (step: string) => (error: any) => {\n\t\t\t\tthrow this.annotateConnectionError(\n\t\t\t\t\terror,\n\t\t\t\t\tstep,\n\t\t\t\t\t!requestWebsocketTokenFromJoinSession,\n\t\t\t\t);\n\t\t\t};\n\n\t\t\tconst joinSessionPromise = this.joinSession(\n\t\t\t\trequestWebsocketTokenFromJoinSession,\n\t\t\t\toptions,\n\t\t\t\tfalse /* isRefreshingJoinSession */,\n\t\t\t);\n\t\t\tconst [websocketEndpoint, websocketToken] = await Promise.all([\n\t\t\t\tjoinSessionPromise.catch(annotateAndRethrowConnectionError(\"joinSession\")),\n\t\t\t\twebsocketTokenPromise.catch(annotateAndRethrowConnectionError(\"getWebsocketToken\")),\n\t\t\t]);\n\n\t\t\tconst finalWebsocketToken = websocketToken ?? websocketEndpoint.socketToken ?? null;\n\t\t\tif (finalWebsocketToken === null) {\n\t\t\t\tthrow this.annotateConnectionError(\n\t\t\t\t\tnew NonRetryableError(\n\t\t\t\t\t\t\"Websocket token is null\",\n\t\t\t\t\t\tOdspErrorType.fetchTokenError,\n\t\t\t\t\t\t{ driverVersion },\n\t\t\t\t\t),\n\t\t\t\t\t\"getWebsocketToken\",\n\t\t\t\t\t!requestWebsocketTokenFromJoinSession,\n\t\t\t\t);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst connection = await this.createDeltaConnection(\n\t\t\t\t\twebsocketEndpoint.tenantId,\n\t\t\t\t\twebsocketEndpoint.id,\n\t\t\t\t\tfinalWebsocketToken,\n\t\t\t\t\tclient,\n\t\t\t\t\twebsocketEndpoint.deltaStreamSocketUrl,\n\t\t\t\t);\n\t\t\t\tconnection.on(\"op\", (documentId, ops: ISequencedDocumentMessage[]) => {\n\t\t\t\t\tthis.opsReceived(ops);\n\t\t\t\t});\n\t\t\t\t// On disconnect with 401/403 error code, we can just clear the joinSession cache as we will again\n\t\t\t\t// get the auth error on reconnecting and face latency.\n\t\t\t\tconnection.once(\"disconnect\", (error: any) => {\n\t\t\t\t\t// Clear the join session refresh timer so that it can be restarted on reconnection.\n\t\t\t\t\tthis.clearJoinSessionTimer();\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypeof error === \"object\" &&\n\t\t\t\t\t\terror !== null &&\n\t\t\t\t\t\terror.errorType === DriverErrorType.authorizationError\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.cache.sessionJoinCache.remove(this.joinSessionKey);\n\t\t\t\t\t}\n\t\t\t\t\t// If we hit this assert, it means that \"disconnect\" event is emitted before the connection went through\n\t\t\t\t\t// dispose flow which is not correct and could lead to a bunch of erros.\n\t\t\t\t\tassert(connection.disposed, 0x4ae /* Connection should be disposed by now */);\n\t\t\t\t\tthis.currentConnection = undefined;\n\t\t\t\t});\n\t\t\t\tthis.currentConnection = connection;\n\t\t\t\treturn connection;\n\t\t\t} catch (error) {\n\t\t\t\tthis.cache.sessionJoinCache.remove(this.joinSessionKey);\n\n\t\t\t\tconst normalizedError = this.annotateConnectionError(\n\t\t\t\t\terror,\n\t\t\t\t\t\"createDeltaConnection\",\n\t\t\t\t\t!requestWebsocketTokenFromJoinSession,\n\t\t\t\t);\n\t\t\t\tif (typeof error === \"object\" && error !== null) {\n\t\t\t\t\tnormalizedError.addTelemetryProperties({\n\t\t\t\t\t\tsocketDocumentId: websocketEndpoint.id,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tthrow normalizedError;\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate clearJoinSessionTimer() {\n\t\tif (this.joinSessionRefreshTimer !== undefined) {\n\t\t\tclearTimeout(this.joinSessionRefreshTimer);\n\t\t\tthis.joinSessionRefreshTimer = undefined;\n\t\t}\n\t}\n\n\tprivate async scheduleJoinSessionRefresh(\n\t\tdelta: number,\n\t\trequestSocketToken: boolean,\n\t\tclientId: string | undefined,\n\t) {\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tthis.joinSessionRefreshTimer = setTimeout(() => {\n\t\t\t\tgetWithRetryForTokenRefresh(async (options) => {\n\t\t\t\t\tawait this.joinSession(\n\t\t\t\t\t\trequestSocketToken,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\ttrue /* isRefreshingJoinSession */,\n\t\t\t\t\t\tclientId,\n\t\t\t\t\t);\n\t\t\t\t\tresolve();\n\t\t\t\t}).catch((error) => {\n\t\t\t\t\treject(error);\n\t\t\t\t});\n\t\t\t}, delta);\n\t\t});\n\t}\n\n\tprivate async joinSession(\n\t\trequestSocketToken: boolean,\n\t\toptions: TokenFetchOptionsEx,\n\t\tisRefreshingJoinSession: boolean,\n\t\tclientId?: string,\n\t) {\n\t\t// If this call is to refresh the join session for the current connection but we are already disconnected in\n\t\t// the meantime or disconnected and then reconnected then do not make the call. However, we should not have\n\t\t// come here if that is the case because timer should have been disposed, but due to race condition with the\n\t\t// timer we should not make the call and throw error.\n\t\tif (\n\t\t\tisRefreshingJoinSession &&\n\t\t\t(this.currentConnection === undefined ||\n\t\t\t\t(clientId !== undefined && this.currentConnection.clientId !== clientId))\n\t\t) {\n\t\t\tthis.clearJoinSessionTimer();\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"JoinSessionRefreshTimerNotCancelled\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{\n\t\t\t\t\tdriverVersion,\n\t\t\t\t\tdetails: JSON.stringify({\n\t\t\t\t\t\tschedulerClientId: clientId,\n\t\t\t\t\t\tcurrentClientId: this.currentConnection?.clientId,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t\tconst response = await this.joinSessionCore(\n\t\t\trequestSocketToken,\n\t\t\toptions,\n\t\t\tisRefreshingJoinSession,\n\t\t).catch((e) => {\n\t\t\tif (hasFacetCodes(e) && e.facetCodes !== undefined) {\n\t\t\t\tfor (const code of e.facetCodes) {\n\t\t\t\t\tswitch (code) {\n\t\t\t\t\t\tcase \"sessionForbiddenOnPreservedFiles\":\n\t\t\t\t\t\tcase \"sessionForbiddenOnModerationEnabledLibrary\":\n\t\t\t\t\t\tcase \"sessionForbiddenOnRequireCheckout\":\n\t\t\t\t\t\t\t// This document can only be opened in storage-only mode.\n\t\t\t\t\t\t\t// DeltaManager will recognize this error\n\t\t\t\t\t\t\t// and load without a delta stream connection.\n\t\t\t\t\t\t\tthis.policies = { ...this.policies, storageOnly: true };\n\t\t\t\t\t\t\tthrow new DeltaStreamConnectionForbiddenError(code, { driverVersion });\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow e;\n\t\t});\n\t\tthis._relayServiceTenantAndSessionId = `${response.tenantId}/${response.id}`;\n\t\treturn response;\n\t}\n\n\tprivate async joinSessionCore(\n\t\trequestSocketToken: boolean,\n\t\toptions: TokenFetchOptionsEx,\n\t\tisRefreshingJoinSession: boolean,\n\t): Promise<ISocketStorageDiscovery> {\n\t\tconst disableJoinSessionRefresh = this.mc.config.getBoolean(\n\t\t\t\"Fluid.Driver.Odsp.disableJoinSessionRefresh\",\n\t\t);\n\t\tconst executeFetch = async () => {\n\t\t\tconst joinSessionResponse = await fetchJoinSession(\n\t\t\t\tthis.odspResolvedUrl,\n\t\t\t\t\"opStream/joinSession\",\n\t\t\t\t\"POST\",\n\t\t\t\tthis.mc.logger,\n\t\t\t\tthis.getStorageToken,\n\t\t\t\tthis.epochTracker,\n\t\t\t\trequestSocketToken,\n\t\t\t\toptions,\n\t\t\t\tdisableJoinSessionRefresh,\n\t\t\t\tisRefreshingJoinSession,\n\t\t\t\tthis.hostPolicy.sessionOptions?.unauthenticatedUserDisplayName,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tentryTime: Date.now(),\n\t\t\t\tjoinSessionResponse,\n\t\t\t};\n\t\t};\n\n\t\tconst getResponseAndRefreshAfterDeltaMs = async () => {\n\t\t\tconst _response = await this.cache.sessionJoinCache.addOrGet(\n\t\t\t\tthis.joinSessionKey,\n\t\t\t\texecuteFetch,\n\t\t\t);\n\t\t\t// If the response does not contain refreshSessionDurationSeconds, then treat it as old flow and let the\n\t\t\t// cache entry to be treated as expired after 1 hour.\n\t\t\t_response.joinSessionResponse.refreshSessionDurationSeconds =\n\t\t\t\t_response.joinSessionResponse.refreshSessionDurationSeconds ?? 3600;\n\t\t\treturn {\n\t\t\t\t..._response,\n\t\t\t\trefreshAfterDeltaMs: this.calculateJoinSessionRefreshDelta(\n\t\t\t\t\t_response.entryTime,\n\t\t\t\t\t_response.joinSessionResponse.refreshSessionDurationSeconds,\n\t\t\t\t),\n\t\t\t};\n\t\t};\n\t\tlet response = await getResponseAndRefreshAfterDeltaMs();\n\t\t// This means that the cached entry has expired(This should not be possible if the response is fetched\n\t\t// from the network call). In this case we remove the cached entry and fetch the new response.\n\t\tif (response.refreshAfterDeltaMs <= 0) {\n\t\t\tthis.cache.sessionJoinCache.remove(this.joinSessionKey);\n\t\t\tresponse = await getResponseAndRefreshAfterDeltaMs();\n\t\t}\n\t\tif (!disableJoinSessionRefresh) {\n\t\t\tconst props = {\n\t\t\t\tentryTime: response.entryTime,\n\t\t\t\trefreshSessionDurationSeconds:\n\t\t\t\t\tresponse.joinSessionResponse.refreshSessionDurationSeconds,\n\t\t\t\trefreshAfterDeltaMs: response.refreshAfterDeltaMs,\n\t\t\t};\n\t\t\tif (response.refreshAfterDeltaMs > 0) {\n\t\t\t\tthis.scheduleJoinSessionRefresh(\n\t\t\t\t\tresponse.refreshAfterDeltaMs,\n\t\t\t\t\trequestSocketToken,\n\t\t\t\t\tthis.currentConnection?.clientId,\n\t\t\t\t).catch((error) => {\n\t\t\t\t\t// Log the error and do nothing as the reconnection would fetch the join session.\n\t\t\t\t\tthis.mc.logger.sendTelemetryEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"JoinSessionRefreshError\",\n\t\t\t\t\t\t\tdetails: JSON.stringify(props),\n\t\t\t\t\t\t},\n\t\t\t\t\t\terror,\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Logging just for informational purposes to help with debugging as this is a new feature.\n\t\t\t\tthis.mc.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"JoinSessionRefreshNotScheduled\",\n\t\t\t\t\tdetails: JSON.stringify(props),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn response.joinSessionResponse;\n\t}\n\n\tprivate calculateJoinSessionRefreshDelta(\n\t\tresponseFetchTime: number,\n\t\trefreshSessionDurationSeconds: number,\n\t) {\n\t\t// 30 seconds is buffer time to refresh the session.\n\t\treturn responseFetchTime + (refreshSessionDurationSeconds * 1000 - 30000) - Date.now();\n\t}\n\n\t/**\n\t * Creats a connection to the given delta stream endpoint\n\t *\n\t * @param tenantId - the ID of the tenant\n\t * @param documentId - document ID\n\t * @param token - authorization token for delta service\n\t * @param client - information about the client\n\t * @param webSocketUrl - websocket URL\n\t */\n\tprivate async createDeltaConnection(\n\t\ttenantId: string,\n\t\tdocumentId: string,\n\t\ttoken: string | null,\n\t\tclient: IClient,\n\t\twebSocketUrl: string,\n\t): Promise<OdspDocumentDeltaConnection> {\n\t\tconst startTime = performance.now();\n\t\tconst connection = await OdspDocumentDeltaConnection.create(\n\t\t\ttenantId,\n\t\t\tdocumentId,\n\t\t\ttoken,\n\t\t\tclient,\n\t\t\twebSocketUrl,\n\t\t\tthis.mc.logger,\n\t\t\t60000,\n\t\t\tthis.epochTracker,\n\t\t\tthis.socketReferenceKeyPrefix,\n\t\t);\n\t\tconst duration = performance.now() - startTime;\n\t\t// This event happens rather often, so it adds up to cost of telemetry.\n\t\t// Given that most reconnects result in reusing socket and happen very quickly,\n\t\t// report event only if it took longer than threshold.\n\t\tif (duration >= 2000) {\n\t\t\tthis.mc.logger.sendPerformanceEvent({\n\t\t\t\teventName: \"ConnectionSuccess\",\n\t\t\t\tduration,\n\t\t\t});\n\t\t}\n\t\treturn connection;\n\t}\n\n\tpublic dispose(error?: any) {\n\t\tthis.clearJoinSessionTimer();\n\t\tthis.currentConnection?.dispose();\n\t\tthis.currentConnection = undefined;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"odspDelayLoadedDeltaStream.js","sourceRoot":"","sources":["../src/odspDelayLoadedDeltaStream.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, performance } from \"@fluidframework/common-utils\";\nimport {\n\tIFluidErrorBase,\n\tMonitoringContext,\n\tnormalizeError,\n} from \"@fluidframework/telemetry-utils\";\nimport {\n\tIDocumentDeltaConnection,\n\tIResolvedUrl,\n\tIDocumentServicePolicies,\n\tDriverErrorType,\n} from \"@fluidframework/driver-definitions\";\nimport {\n\tDeltaStreamConnectionForbiddenError,\n\tNonRetryableError,\n} from \"@fluidframework/driver-utils\";\nimport { IClient, ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport {\n\tIOdspResolvedUrl,\n\tTokenFetchOptions,\n\tHostStoragePolicy,\n\tInstrumentedStorageTokenFetcher,\n\tOdspErrorType,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { hasFacetCodes } from \"@fluidframework/odsp-doclib-utils\";\nimport { ISocketStorageDiscovery } from \"./contracts\";\nimport { IOdspCache } from \"./odspCache\";\nimport { OdspDocumentDeltaConnection } from \"./odspDocumentDeltaConnection\";\nimport { getWithRetryForTokenRefresh, TokenFetchOptionsEx } from \"./odspUtils\";\nimport { fetchJoinSession } from \"./vroom\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\n\n/**\n * This OdspDelayLoadedDeltaStream is used by OdspDocumentService.ts to delay load the delta connection\n * as they are not on critical path of loading a container.\n */\nexport class OdspDelayLoadedDeltaStream {\n\t// Timer which runs and executes the join session call after intervals.\n\tprivate joinSessionRefreshTimer: ReturnType<typeof setTimeout> | undefined;\n\n\tprivate readonly joinSessionKey: string;\n\n\tprivate currentConnection?: OdspDocumentDeltaConnection;\n\n\tprivate _relayServiceTenantAndSessionId: string | undefined;\n\n\t/**\n\t * @param odspResolvedUrl - resolved url identifying document that will be managed by this service instance.\n\t * @param policies - Document service policies.\n\t * @param getStorageToken - function that can provide the storage token. This is is also referred to as\n\t * the \"Vroom\" token in SPO.\n\t * @param getWebsocketToken - function that can provide a token for accessing the web socket. This is also referred\n\t * to as the \"Push\" token in SPO. If undefined then websocket token is expected to be returned with joinSession\n\t * response payload.\n\t * @param mc - a logger that can capture performance and diagnostic information\n\t * @param cache - This caches response for joinSession.\n\t * @param hostPolicy - host constructed policy which customizes service behavior.\n\t * @param epochTracker - This helper class which adds epoch to backend calls made by this service instance.\n\t * @param opsReceived - To register the ops received through socket.\n\t * @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache\n\t */\n\tpublic constructor(\n\t\tpublic readonly odspResolvedUrl: IOdspResolvedUrl,\n\t\tpublic policies: IDocumentServicePolicies,\n\t\tprivate readonly getStorageToken: InstrumentedStorageTokenFetcher,\n\t\tprivate readonly getWebsocketToken:\n\t\t\t| ((options: TokenFetchOptions) => Promise<string | null>)\n\t\t\t| undefined,\n\t\tprivate readonly mc: MonitoringContext,\n\t\tprivate readonly cache: IOdspCache,\n\t\tprivate readonly hostPolicy: HostStoragePolicy,\n\t\tprivate readonly epochTracker: EpochTracker,\n\t\tprivate readonly opsReceived: (ops: ISequencedDocumentMessage[]) => void,\n\t\tprivate readonly socketReferenceKeyPrefix?: string,\n\t) {\n\t\tthis.joinSessionKey = `${this.odspResolvedUrl.hashedDocumentId}/joinsession`;\n\t}\n\n\tpublic get resolvedUrl(): IResolvedUrl {\n\t\treturn this.odspResolvedUrl;\n\t}\n\n\tpublic get currentDeltaConnection(): OdspDocumentDeltaConnection | undefined {\n\t\treturn this.currentConnection;\n\t}\n\n\tpublic get relayServiceTenantAndSessionId(): string | undefined {\n\t\treturn this._relayServiceTenantAndSessionId;\n\t}\n\n\t/** Annotate the given error indicating which connection step failed */\n\tprivate annotateConnectionError(\n\t\terror: any,\n\t\tfailedConnectionStep: string,\n\t\tseparateTokenRequest: boolean,\n\t): IFluidErrorBase {\n\t\treturn normalizeError(error, {\n\t\t\tprops: {\n\t\t\t\tfailedConnectionStep,\n\t\t\t\tseparateTokenRequest,\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Connects to a delta stream endpoint for emitting ops.\n\t *\n\t * @returns returns the document delta stream service for onedrive/sharepoint driver.\n\t */\n\tpublic async connectToDeltaStream(client: IClient): Promise<IDocumentDeltaConnection> {\n\t\tassert(\n\t\t\tthis.currentConnection === undefined,\n\t\t\t0x4ad /* Should not be called when connection is already present! */,\n\t\t);\n\t\t// Attempt to connect twice, in case we used expired token.\n\t\treturn getWithRetryForTokenRefresh<IDocumentDeltaConnection>(async (options) => {\n\t\t\t// Presence of getWebsocketToken callback dictates whether callback is used for fetching\n\t\t\t// websocket token or whether it is returned with joinSession response payload\n\t\t\tconst requestWebsocketTokenFromJoinSession = this.getWebsocketToken === undefined;\n\t\t\tconst websocketTokenPromise = requestWebsocketTokenFromJoinSession\n\t\t\t\t? Promise.resolve(null)\n\t\t\t\t: this.getWebsocketToken!(options);\n\n\t\t\tconst annotateAndRethrowConnectionError = (step: string) => (error: any) => {\n\t\t\t\tthrow this.annotateConnectionError(\n\t\t\t\t\terror,\n\t\t\t\t\tstep,\n\t\t\t\t\t!requestWebsocketTokenFromJoinSession,\n\t\t\t\t);\n\t\t\t};\n\n\t\t\tconst joinSessionPromise = this.joinSession(\n\t\t\t\trequestWebsocketTokenFromJoinSession,\n\t\t\t\toptions,\n\t\t\t\tfalse /* isRefreshingJoinSession */,\n\t\t\t);\n\t\t\tconst [websocketEndpoint, websocketToken] = await Promise.all([\n\t\t\t\tjoinSessionPromise.catch(annotateAndRethrowConnectionError(\"joinSession\")),\n\t\t\t\twebsocketTokenPromise.catch(annotateAndRethrowConnectionError(\"getWebsocketToken\")),\n\t\t\t]);\n\n\t\t\tconst finalWebsocketToken = websocketToken ?? websocketEndpoint.socketToken ?? null;\n\t\t\tif (finalWebsocketToken === null) {\n\t\t\t\tthrow this.annotateConnectionError(\n\t\t\t\t\tnew NonRetryableError(\n\t\t\t\t\t\t\"Websocket token is null\",\n\t\t\t\t\t\tOdspErrorType.fetchTokenError,\n\t\t\t\t\t\t{ driverVersion },\n\t\t\t\t\t),\n\t\t\t\t\t\"getWebsocketToken\",\n\t\t\t\t\t!requestWebsocketTokenFromJoinSession,\n\t\t\t\t);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst connection = await this.createDeltaConnection(\n\t\t\t\t\twebsocketEndpoint.tenantId,\n\t\t\t\t\twebsocketEndpoint.id,\n\t\t\t\t\tfinalWebsocketToken,\n\t\t\t\t\tclient,\n\t\t\t\t\twebsocketEndpoint.deltaStreamSocketUrl,\n\t\t\t\t);\n\t\t\t\tconnection.on(\"op\", (documentId, ops: ISequencedDocumentMessage[]) => {\n\t\t\t\t\tthis.opsReceived(ops);\n\t\t\t\t});\n\t\t\t\t// On disconnect with 401/403 error code, we can just clear the joinSession cache as we will again\n\t\t\t\t// get the auth error on reconnecting and face latency.\n\t\t\t\tconnection.once(\"disconnect\", (error: any) => {\n\t\t\t\t\t// Clear the join session refresh timer so that it can be restarted on reconnection.\n\t\t\t\t\tthis.clearJoinSessionTimer();\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypeof error === \"object\" &&\n\t\t\t\t\t\terror !== null &&\n\t\t\t\t\t\terror.errorType === DriverErrorType.authorizationError\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.cache.sessionJoinCache.remove(this.joinSessionKey);\n\t\t\t\t\t}\n\t\t\t\t\t// If we hit this assert, it means that \"disconnect\" event is emitted before the connection went through\n\t\t\t\t\t// dispose flow which is not correct and could lead to a bunch of errors.\n\t\t\t\t\tassert(connection.disposed, 0x4ae /* Connection should be disposed by now */);\n\t\t\t\t\tthis.currentConnection = undefined;\n\t\t\t\t});\n\t\t\t\tthis.currentConnection = connection;\n\t\t\t\treturn connection;\n\t\t\t} catch (error) {\n\t\t\t\tthis.clearJoinSessionTimer();\n\t\t\t\tthis.cache.sessionJoinCache.remove(this.joinSessionKey);\n\n\t\t\t\tconst normalizedError = this.annotateConnectionError(\n\t\t\t\t\terror,\n\t\t\t\t\t\"createDeltaConnection\",\n\t\t\t\t\t!requestWebsocketTokenFromJoinSession,\n\t\t\t\t);\n\t\t\t\tif (typeof error === \"object\" && error !== null) {\n\t\t\t\t\tnormalizedError.addTelemetryProperties({\n\t\t\t\t\t\tsocketDocumentId: websocketEndpoint.id,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tthrow normalizedError;\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate clearJoinSessionTimer() {\n\t\tif (this.joinSessionRefreshTimer !== undefined) {\n\t\t\tclearTimeout(this.joinSessionRefreshTimer);\n\t\t\tthis.joinSessionRefreshTimer = undefined;\n\t\t}\n\t}\n\n\tprivate async scheduleJoinSessionRefresh(\n\t\tdelta: number,\n\t\trequestSocketToken: boolean,\n\t\tclientId: string | undefined,\n\t) {\n\t\tif (this.joinSessionRefreshTimer !== undefined) {\n\t\t\tthis.clearJoinSessionTimer();\n\t\t\tconst originalStackTraceLimit = (Error as any).stackTraceLimit;\n\t\t\t(Error as any).stackTraceLimit = 50;\n\t\t\tthis.mc.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: \"DuplicateJoinSessionRefresh\",\n\t\t\t\t},\n\t\t\t\tnew Error(\"DuplicateJoinSessionRefresh\"),\n\t\t\t);\n\t\t\t(Error as any).stackTraceLimit = originalStackTraceLimit;\n\t\t}\n\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tthis.joinSessionRefreshTimer = setTimeout(() => {\n\t\t\t\tgetWithRetryForTokenRefresh(async (options) => {\n\t\t\t\t\tawait this.joinSession(\n\t\t\t\t\t\trequestSocketToken,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\ttrue /* isRefreshingJoinSession */,\n\t\t\t\t\t\tclientId,\n\t\t\t\t\t);\n\t\t\t\t\tresolve();\n\t\t\t\t}).catch((error) => {\n\t\t\t\t\treject(error);\n\t\t\t\t});\n\t\t\t}, delta);\n\t\t});\n\t}\n\n\tprivate async joinSession(\n\t\trequestSocketToken: boolean,\n\t\toptions: TokenFetchOptionsEx,\n\t\tisRefreshingJoinSession: boolean,\n\t\tclientId?: string,\n\t) {\n\t\t// If this call is to refresh the join session for the current connection but we are already disconnected in\n\t\t// the meantime or disconnected and then reconnected then do not make the call. However, we should not have\n\t\t// come here if that is the case because timer should have been disposed, but due to race condition with the\n\t\t// timer we should not make the call and throw error.\n\t\tif (\n\t\t\tisRefreshingJoinSession &&\n\t\t\t(this.currentConnection === undefined ||\n\t\t\t\t(clientId !== undefined && this.currentConnection.clientId !== clientId))\n\t\t) {\n\t\t\tthis.clearJoinSessionTimer();\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"JoinSessionRefreshTimerNotCancelled\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{\n\t\t\t\t\tdriverVersion,\n\t\t\t\t\tdetails: JSON.stringify({\n\t\t\t\t\t\tschedulerClientId: clientId,\n\t\t\t\t\t\tcurrentClientId: this.currentConnection?.clientId,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t\tconst response = await this.joinSessionCore(\n\t\t\trequestSocketToken,\n\t\t\toptions,\n\t\t\tisRefreshingJoinSession,\n\t\t).catch((e) => {\n\t\t\tif (hasFacetCodes(e) && e.facetCodes !== undefined) {\n\t\t\t\tfor (const code of e.facetCodes) {\n\t\t\t\t\tswitch (code) {\n\t\t\t\t\t\tcase \"sessionForbiddenOnPreservedFiles\":\n\t\t\t\t\t\tcase \"sessionForbiddenOnModerationEnabledLibrary\":\n\t\t\t\t\t\tcase \"sessionForbiddenOnRequireCheckout\":\n\t\t\t\t\t\t\t// This document can only be opened in storage-only mode.\n\t\t\t\t\t\t\t// DeltaManager will recognize this error\n\t\t\t\t\t\t\t// and load without a delta stream connection.\n\t\t\t\t\t\t\tthis.policies = { ...this.policies, storageOnly: true };\n\t\t\t\t\t\t\tthrow new DeltaStreamConnectionForbiddenError(code, { driverVersion });\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow e;\n\t\t});\n\t\tthis._relayServiceTenantAndSessionId = `${response.tenantId}/${response.id}`;\n\t\treturn response;\n\t}\n\n\tprivate async joinSessionCore(\n\t\trequestSocketToken: boolean,\n\t\toptions: TokenFetchOptionsEx,\n\t\tisRefreshingJoinSession: boolean,\n\t): Promise<ISocketStorageDiscovery> {\n\t\tconst disableJoinSessionRefresh = this.mc.config.getBoolean(\n\t\t\t\"Fluid.Driver.Odsp.disableJoinSessionRefresh\",\n\t\t);\n\t\tconst executeFetch = async () => {\n\t\t\tconst joinSessionResponse = await fetchJoinSession(\n\t\t\t\tthis.odspResolvedUrl,\n\t\t\t\t\"opStream/joinSession\",\n\t\t\t\t\"POST\",\n\t\t\t\tthis.mc.logger,\n\t\t\t\tthis.getStorageToken,\n\t\t\t\tthis.epochTracker,\n\t\t\t\trequestSocketToken,\n\t\t\t\toptions,\n\t\t\t\tdisableJoinSessionRefresh,\n\t\t\t\tisRefreshingJoinSession,\n\t\t\t\tthis.hostPolicy.sessionOptions?.unauthenticatedUserDisplayName,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tentryTime: Date.now(),\n\t\t\t\tjoinSessionResponse,\n\t\t\t};\n\t\t};\n\n\t\tconst getResponseAndRefreshAfterDeltaMs = async () => {\n\t\t\tconst _response = await this.cache.sessionJoinCache.addOrGet(\n\t\t\t\tthis.joinSessionKey,\n\t\t\t\texecuteFetch,\n\t\t\t);\n\t\t\t// If the response does not contain refreshSessionDurationSeconds, then treat it as old flow and let the\n\t\t\t// cache entry to be treated as expired after 1 hour.\n\t\t\t_response.joinSessionResponse.refreshSessionDurationSeconds =\n\t\t\t\t_response.joinSessionResponse.refreshSessionDurationSeconds ?? 3600;\n\t\t\treturn {\n\t\t\t\t..._response,\n\t\t\t\trefreshAfterDeltaMs: this.calculateJoinSessionRefreshDelta(\n\t\t\t\t\t_response.entryTime,\n\t\t\t\t\t_response.joinSessionResponse.refreshSessionDurationSeconds,\n\t\t\t\t),\n\t\t\t};\n\t\t};\n\t\tlet response = await getResponseAndRefreshAfterDeltaMs();\n\t\t// This means that the cached entry has expired(This should not be possible if the response is fetched\n\t\t// from the network call). In this case we remove the cached entry and fetch the new response.\n\t\tif (response.refreshAfterDeltaMs <= 0) {\n\t\t\tthis.cache.sessionJoinCache.remove(this.joinSessionKey);\n\t\t\tresponse = await getResponseAndRefreshAfterDeltaMs();\n\t\t}\n\t\tif (!disableJoinSessionRefresh) {\n\t\t\tconst props = {\n\t\t\t\tentryTime: response.entryTime,\n\t\t\t\trefreshSessionDurationSeconds:\n\t\t\t\t\tresponse.joinSessionResponse.refreshSessionDurationSeconds,\n\t\t\t\trefreshAfterDeltaMs: response.refreshAfterDeltaMs,\n\t\t\t};\n\t\t\tif (response.refreshAfterDeltaMs > 0) {\n\t\t\t\tthis.scheduleJoinSessionRefresh(\n\t\t\t\t\tresponse.refreshAfterDeltaMs,\n\t\t\t\t\trequestSocketToken,\n\t\t\t\t\tthis.currentConnection?.clientId,\n\t\t\t\t).catch((error) => {\n\t\t\t\t\t// Log the error and do nothing as the reconnection would fetch the join session.\n\t\t\t\t\tthis.mc.logger.sendTelemetryEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"JoinSessionRefreshError\",\n\t\t\t\t\t\t\tdetails: JSON.stringify(props),\n\t\t\t\t\t\t},\n\t\t\t\t\t\terror,\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Logging just for informational purposes to help with debugging as this is a new feature.\n\t\t\t\tthis.mc.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"JoinSessionRefreshNotScheduled\",\n\t\t\t\t\tdetails: JSON.stringify(props),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn response.joinSessionResponse;\n\t}\n\n\tprivate calculateJoinSessionRefreshDelta(\n\t\tresponseFetchTime: number,\n\t\trefreshSessionDurationSeconds: number,\n\t) {\n\t\t// 30 seconds is buffer time to refresh the session.\n\t\treturn responseFetchTime + (refreshSessionDurationSeconds * 1000 - 30000) - Date.now();\n\t}\n\n\t/**\n\t * Creates a connection to the given delta stream endpoint\n\t *\n\t * @param tenantId - the ID of the tenant\n\t * @param documentId - document ID\n\t * @param token - authorization token for delta service\n\t * @param client - information about the client\n\t * @param webSocketUrl - websocket URL\n\t */\n\tprivate async createDeltaConnection(\n\t\ttenantId: string,\n\t\tdocumentId: string,\n\t\ttoken: string | null,\n\t\tclient: IClient,\n\t\twebSocketUrl: string,\n\t): Promise<OdspDocumentDeltaConnection> {\n\t\tconst startTime = performance.now();\n\t\tconst connection = await OdspDocumentDeltaConnection.create(\n\t\t\ttenantId,\n\t\t\tdocumentId,\n\t\t\ttoken,\n\t\t\tclient,\n\t\t\twebSocketUrl,\n\t\t\tthis.mc.logger,\n\t\t\t60000,\n\t\t\tthis.epochTracker,\n\t\t\tthis.socketReferenceKeyPrefix,\n\t\t);\n\t\tconst duration = performance.now() - startTime;\n\t\t// This event happens rather often, so it adds up to cost of telemetry.\n\t\t// Given that most reconnects result in reusing socket and happen very quickly,\n\t\t// report event only if it took longer than threshold.\n\t\tif (duration >= 2000) {\n\t\t\tthis.mc.logger.sendPerformanceEvent({\n\t\t\t\teventName: \"ConnectionSuccess\",\n\t\t\t\tduration,\n\t\t\t});\n\t\t}\n\t\treturn connection;\n\t}\n\n\tpublic dispose(error?: any) {\n\t\tthis.clearJoinSessionTimer();\n\t\tthis.currentConnection?.dispose();\n\t\tthis.currentConnection = undefined;\n\t}\n}\n"]}
|
|
@@ -7,7 +7,7 @@ import { DocumentDeltaConnection } from "@fluidframework/driver-base";
|
|
|
7
7
|
import { IAnyDriverError } from "@fluidframework/driver-definitions";
|
|
8
8
|
import { OdspError } from "@fluidframework/odsp-driver-definitions";
|
|
9
9
|
import { IFluidErrorBase } from "@fluidframework/telemetry-utils";
|
|
10
|
-
import { IClient, IConnect } from "@fluidframework/protocol-definitions";
|
|
10
|
+
import { IClient, IConnect, IDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
11
11
|
import { EpochTracker } from "./epochTracker";
|
|
12
12
|
export interface FlushResult {
|
|
13
13
|
lastPersistedSequenceNumber?: number;
|
|
@@ -40,6 +40,7 @@ export declare class OdspDocumentDeltaConnection extends DocumentDeltaConnection
|
|
|
40
40
|
private readonly getOpsMap;
|
|
41
41
|
private flushOpNonce;
|
|
42
42
|
private flushDeferred;
|
|
43
|
+
private connectionNotYetDisposedTimeout;
|
|
43
44
|
/**
|
|
44
45
|
* Error raising for socket.io issues
|
|
45
46
|
*/
|
|
@@ -67,6 +68,25 @@ export declare class OdspDocumentDeltaConnection extends DocumentDeltaConnection
|
|
|
67
68
|
protected disconnectHandler: (error: IFluidErrorBase & OdspError, clientId?: string | undefined) => void;
|
|
68
69
|
protected initialize(connectMessage: IConnect, timeout: number): Promise<void>;
|
|
69
70
|
protected addTrackedListener(event: string, listener: (...args: any[]) => void): void;
|
|
71
|
+
get disposed(): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Returns true in case the connection is not yet disposed and the socket is also connected. The expectation is
|
|
74
|
+
* that it will be called only after connection is fully established. i.e. there should no way to submit an op
|
|
75
|
+
* while we are connecting, as connection object is not exposed to Loader layer until connection is established.
|
|
76
|
+
*/
|
|
77
|
+
private get connected();
|
|
78
|
+
protected emitMessages(type: string, messages: IDocumentMessage[][]): void;
|
|
79
|
+
/**
|
|
80
|
+
* Submits a new delta operation to the server
|
|
81
|
+
* @param message - delta operation to submit
|
|
82
|
+
*/
|
|
83
|
+
submit(messages: IDocumentMessage[]): void;
|
|
84
|
+
/**
|
|
85
|
+
* Submits a new signal to the server
|
|
86
|
+
*
|
|
87
|
+
* @param message - signal to submit
|
|
88
|
+
*/
|
|
89
|
+
submitSignal(message: IDocumentMessage): void;
|
|
70
90
|
/**
|
|
71
91
|
* Critical path where we need to also close the socket for an error.
|
|
72
92
|
* @param error - Error causing the socket to close.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspDocumentDeltaConnection.d.ts","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAU,MAAM,oCAAoC,CAAC;AAE9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,eAAe,EAA6B,MAAM,iCAAiC,CAAC;AAC7F,OAAO,EACN,OAAO,EACP,QAAQ,
|
|
1
|
+
{"version":3,"file":"odspDocumentDeltaConnection.d.ts","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAU,MAAM,oCAAoC,CAAC;AAE9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,eAAe,EAA6B,MAAM,iCAAiC,CAAC;AAC7F,OAAO,EACN,OAAO,EACP,QAAQ,EACR,gBAAgB,EAIhB,MAAM,sCAAsC,CAAC;AAK9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAQ9C,MAAM,WAAW,WAAW;IAC3B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAqLD;;GAEG;AACH,qBAAa,2BAA4B,SAAQ,uBAAuB;IA2KtE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IA1KrC;;;;;;;;;;;;;;OAcG;WACiB,MAAM,CACzB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAElB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,gBAAgB,EACjC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,YAAY,EAC1B,wBAAwB,EAAE,MAAM,GAAG,SAAS,GAC1C,OAAO,CAAC,2BAA2B,CAAC;IAgFvC,OAAO,CAAC,eAAe,CAA8B;IAErD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CACf;IACX,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,+BAA+B,CAA4C;IAEnF;;OAEG;IACH,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,QAAQ,UAAO,GAAG,eAAe;IAS3F;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,4BAA4B;IA2B3C;;;;;;OAMG;IACH,OAAO;IAYP;;;;;OAKG;IACI,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAuD7B,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC;IAkC1C,SAAS,CAAC,iBAAiB,UAAW,eAAe,GAAG,SAAS,yCAc/D;cAEc,UAAU,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM;IA0FpE,SAAS,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI;IA0D9E,IAAW,QAAQ,YAkBlB;IAED;;;;OAIG;IACH,OAAO,KAAK,SAAS,GAEpB;IAED,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,EAAE;IAOnE;;;OAGG;IACI,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,IAAI;IAIjD;;;;OAIG;IACI,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAIpD;;;OAGG;IACH,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,eAAe;IAUhD;;OAEG;IACH,SAAS,CAAC,cAAc;CAaxB"}
|
|
@@ -161,10 +161,8 @@ class OdspDocumentDeltaConnection extends driver_base_1.DocumentDeltaConnection
|
|
|
161
161
|
if (clientId === undefined || clientId === this.clientId) {
|
|
162
162
|
this.logger.sendTelemetryEvent({
|
|
163
163
|
eventName: "ServerDisconnect",
|
|
164
|
-
|
|
165
|
-
details: JSON.stringify({
|
|
166
|
-
connection: this.connectionId,
|
|
167
|
-
}),
|
|
164
|
+
driverVersion: packageVersion_1.pkgVersion,
|
|
165
|
+
details: JSON.stringify(Object.assign({}, this.getConnectionDetailsProps())),
|
|
168
166
|
}, error);
|
|
169
167
|
this.disconnect(error);
|
|
170
168
|
}
|
|
@@ -218,8 +216,31 @@ class OdspDocumentDeltaConnection extends driver_base_1.DocumentDeltaConnection
|
|
|
218
216
|
connectMessage.supportedFeatures[feature_get_ops] = true;
|
|
219
217
|
}
|
|
220
218
|
const deltaConnection = new OdspDocumentDeltaConnection(socket, documentId, socketReference, telemetryLogger, enableMultiplexing);
|
|
221
|
-
|
|
222
|
-
|
|
219
|
+
try {
|
|
220
|
+
await deltaConnection.initialize(connectMessage, timeoutMs);
|
|
221
|
+
await epochTracker.validateEpoch(deltaConnection.details.epoch, "push");
|
|
222
|
+
}
|
|
223
|
+
catch (errorObject) {
|
|
224
|
+
if (errorObject !== null && typeof errorObject === "object") {
|
|
225
|
+
// We have to special-case error types here in terms of what is re-triable.
|
|
226
|
+
// These errors have to re-retried, we just need new joinSession result to connect to right server:
|
|
227
|
+
// 400: Invalid tenant or document id. The WebSocket is connected to a different document
|
|
228
|
+
// Document is full (with retryAfter)
|
|
229
|
+
// 404: Invalid document. The document \"local/w1-...\" does not exist
|
|
230
|
+
// But this has to stay not-retriable:
|
|
231
|
+
// 406: Unsupported client protocol. This path is the only gatekeeper, have to fail!
|
|
232
|
+
// 409: Epoch Version Mismatch. Client epoch and server epoch does not match, so app needs
|
|
233
|
+
// to be refreshed.
|
|
234
|
+
// This one is fine either way
|
|
235
|
+
// 401/403: Code will retry once with new token either way, then it becomes fatal - on this path
|
|
236
|
+
// and on join Session path.
|
|
237
|
+
// 501: (Fluid not enabled): this is fine either way, as joinSession is gatekeeper
|
|
238
|
+
if (errorObject.statusCode === 400 || errorObject.statusCode === 404) {
|
|
239
|
+
errorObject.canRetry = true;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
throw errorObject;
|
|
243
|
+
}
|
|
223
244
|
return deltaConnection;
|
|
224
245
|
}
|
|
225
246
|
/**
|
|
@@ -459,6 +480,52 @@ class OdspDocumentDeltaConnection extends driver_base_1.DocumentDeltaConnection
|
|
|
459
480
|
break;
|
|
460
481
|
}
|
|
461
482
|
}
|
|
483
|
+
get disposed() {
|
|
484
|
+
if (!(this._disposed || this.socket.connected)) {
|
|
485
|
+
// Send error event if this connection is not yet disposed after socket is disconnected for 15s.
|
|
486
|
+
if (this.connectionNotYetDisposedTimeout === undefined) {
|
|
487
|
+
this.connectionNotYetDisposedTimeout = setTimeout(() => {
|
|
488
|
+
if (!this._disposed) {
|
|
489
|
+
this.logger.sendErrorEvent({
|
|
490
|
+
eventName: "ConnectionNotYetDisposed",
|
|
491
|
+
driverVersion: packageVersion_1.pkgVersion,
|
|
492
|
+
details: JSON.stringify(Object.assign({}, this.getConnectionDetailsProps())),
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
}, 15000);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
return this._disposed;
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Returns true in case the connection is not yet disposed and the socket is also connected. The expectation is
|
|
502
|
+
* that it will be called only after connection is fully established. i.e. there should no way to submit an op
|
|
503
|
+
* while we are connecting, as connection object is not exposed to Loader layer until connection is established.
|
|
504
|
+
*/
|
|
505
|
+
get connected() {
|
|
506
|
+
return !this.disposed && this.socket.connected;
|
|
507
|
+
}
|
|
508
|
+
emitMessages(type, messages) {
|
|
509
|
+
// Only submit the op/signals if we are connected.
|
|
510
|
+
if (this.connected) {
|
|
511
|
+
this.socket.emit(type, this.clientId, messages);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Submits a new delta operation to the server
|
|
516
|
+
* @param message - delta operation to submit
|
|
517
|
+
*/
|
|
518
|
+
submit(messages) {
|
|
519
|
+
this.emitMessages("submitOp", [messages]);
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Submits a new signal to the server
|
|
523
|
+
*
|
|
524
|
+
* @param message - signal to submit
|
|
525
|
+
*/
|
|
526
|
+
submitSignal(message) {
|
|
527
|
+
this.emitMessages("submitSignal", [[message]]);
|
|
528
|
+
}
|
|
462
529
|
/**
|
|
463
530
|
* Critical path where we need to also close the socket for an error.
|
|
464
531
|
* @param error - Error causing the socket to close.
|