@fluidframework/odsp-driver 2.0.0-internal.4.1.2 → 2.0.0-internal.4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/odspDocumentStorageManager.d.ts.map +1 -1
- package/dist/odspDocumentStorageManager.js +2 -9
- package/dist/odspDocumentStorageManager.js.map +1 -1
- package/dist/odspUtils.d.ts.map +1 -1
- package/dist/odspUtils.js +10 -8
- package/dist/odspUtils.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/odspDocumentStorageManager.d.ts.map +1 -1
- package/lib/odspDocumentStorageManager.js +1 -8
- package/lib/odspDocumentStorageManager.js.map +1 -1
- package/lib/odspUtils.d.ts.map +1 -1
- package/lib/odspUtils.js +10 -8
- package/lib/odspUtils.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 +11 -11
- package/src/odspDocumentStorageManager.ts +1 -11
- package/src/odspUtils.ts +12 -8
- package/src/packageVersion.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspDocumentStorageManager.d.ts","sourceRoot":"","sources":["../src/odspDocumentStorageManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAGtE,OAAO,KAAK,GAAG,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"odspDocumentStorageManager.d.ts","sourceRoot":"","sources":["../src/odspDocumentStorageManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,6 +26,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.OdspDocumentStorageService = exports.defaultSummarizerCacheExpiryTimeout = void 0;
|
|
27
27
|
const common_utils_1 = require("@fluidframework/common-utils");
|
|
28
28
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
29
|
+
const driver_base_1 = require("@fluidframework/driver-base");
|
|
29
30
|
const driver_definitions_1 = require("@fluidframework/driver-definitions");
|
|
30
31
|
const driver_utils_1 = require("@fluidframework/driver-utils");
|
|
31
32
|
const odsp_driver_definitions_1 = require("@fluidframework/odsp-driver-definitions");
|
|
@@ -35,14 +36,6 @@ const odspUtils_1 = require("./odspUtils");
|
|
|
35
36
|
const packageVersion_1 = require("./packageVersion");
|
|
36
37
|
const odspDocumentStorageServiceBase_1 = require("./odspDocumentStorageServiceBase");
|
|
37
38
|
exports.defaultSummarizerCacheExpiryTimeout = 60 * 1000; // 60 seconds.
|
|
38
|
-
// An implementation of Promise.race that gives you the winner of the promise race
|
|
39
|
-
async function promiseRaceWithWinner(promises) {
|
|
40
|
-
return new Promise((resolve, reject) => {
|
|
41
|
-
promises.forEach((p, index) => {
|
|
42
|
-
p.then((v) => resolve({ index, value: v })).catch(reject);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
39
|
class OdspDocumentStorageService extends odspDocumentStorageServiceBase_1.OdspDocumentStorageServiceBase {
|
|
47
40
|
constructor(odspResolvedUrl, getStorageToken, logger, fetchFullSnapshot, cache, hostPolicy, epochTracker, flushCallback, relayServiceTenantAndSessionId, snapshotFormatFetchType) {
|
|
48
41
|
super((0, telemetry_utils_1.loggerToMonitoringContext)(logger).config);
|
|
@@ -205,7 +198,7 @@ class OdspDocumentStorageService extends odspDocumentStorageServiceBase_1.OdspDo
|
|
|
205
198
|
// I.e. if cache fails for some reason, we will proceed with network result.
|
|
206
199
|
// And vice versa - if (for example) client is offline and network request fails first, we
|
|
207
200
|
// do want to attempt to succeed with cached data!
|
|
208
|
-
const promiseRaceWinner = await promiseRaceWithWinner([
|
|
201
|
+
const promiseRaceWinner = await (0, driver_base_1.promiseRaceWithWinner)([
|
|
209
202
|
cachedSnapshotP.catch(() => undefined),
|
|
210
203
|
networkSnapshotP.catch(() => undefined),
|
|
211
204
|
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspDocumentStorageManager.js","sourceRoot":"","sources":["../src/odspDocumentStorageManager.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, delay, performance } from \"@fluidframework/common-utils\";\nimport { loggerToMonitoringContext, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport * as api from \"@fluidframework/protocol-definitions\";\nimport { ISummaryContext, DriverErrorType, FetchSource } from \"@fluidframework/driver-definitions\";\nimport { RateLimiter, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport {\n\tIOdspResolvedUrl,\n\tISnapshotOptions,\n\tOdspErrorType,\n\tInstrumentedStorageTokenFetcher,\n\tgetKeyForCacheEntry,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport {\n\tIDocumentStorageGetVersionsResponse,\n\tHostStoragePolicyInternal,\n\tIVersionedValueWithEpoch,\n\tISnapshotCachedEntry,\n} from \"./contracts\";\nimport {\n\tdownloadSnapshot,\n\tfetchSnapshot,\n\tfetchSnapshotWithRedeem,\n\tSnapshotFormatSupportType,\n} from \"./fetchSnapshot\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport { IOdspCache, IPrefetchSnapshotContents } from \"./odspCache\";\nimport { createCacheSnapshotKey, getWithRetryForTokenRefresh } from \"./odspUtils\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { EpochTracker } from \"./epochTracker\";\nimport type { OdspSummaryUploadManager } from \"./odspSummaryUploadManager\";\nimport { FlushResult } from \"./odspDocumentDeltaConnection\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\nimport { OdspDocumentStorageServiceBase } from \"./odspDocumentStorageServiceBase\";\n\nexport const defaultSummarizerCacheExpiryTimeout: number = 60 * 1000; // 60 seconds.\n\n// An implementation of Promise.race that gives you the winner of the promise race\nasync function promiseRaceWithWinner<T>(\n\tpromises: Promise<T>[],\n): Promise<{ index: number; value: T }> {\n\treturn new Promise((resolve, reject) => {\n\t\tpromises.forEach((p, index) => {\n\t\t\tp.then((v) => resolve({ index, value: v })).catch(reject);\n\t\t});\n\t});\n}\n\ninterface GetVersionsTelemetryProps {\n\tcacheEntryAge?: number;\n\tcacheSummarizerExpired?: boolean;\n}\n\nexport class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {\n\tprivate odspSummaryModuleLoaded: boolean = false;\n\tprivate summaryModuleP: Promise<OdspSummaryUploadManager> | undefined;\n\tprivate odspSummaryUploadManager: OdspSummaryUploadManager | undefined;\n\n\tprivate firstVersionCall = true;\n\n\tprivate readonly documentId: string;\n\tprivate readonly snapshotUrl: string | undefined;\n\tprivate readonly attachmentPOSTUrl: string | undefined;\n\tprivate readonly attachmentGETUrl: string | undefined;\n\t// Driver specified limits for snapshot size and time.\n\t/**\n\t * NOTE: While commit cfff6e3 added restrictions to prevent large payloads, snapshot failures will continue to\n\t * happen until blob request throttling is implemented. Until then, as a temporary fix we set arbitrarily large\n\t * snapshot size and timeout limits so that such failures are unlikely to occur.\n\t */\n\tprivate readonly maxSnapshotSizeLimit = 500000000; // 500 MB\n\tprivate readonly maxSnapshotFetchTimeout = 120000; // 2 min\n\n\t// limits the amount of parallel \"attachment\" blob uploads\n\tprivate readonly createBlobRateLimiter = new RateLimiter(1);\n\n\tconstructor(\n\t\tprivate readonly odspResolvedUrl: IOdspResolvedUrl,\n\t\tprivate readonly getStorageToken: InstrumentedStorageTokenFetcher,\n\t\tprivate readonly logger: ITelemetryLogger,\n\t\tprivate readonly fetchFullSnapshot: boolean,\n\t\tprivate readonly cache: IOdspCache,\n\t\tprivate readonly hostPolicy: HostStoragePolicyInternal,\n\t\tprivate readonly epochTracker: EpochTracker,\n\t\tprivate readonly flushCallback: () => Promise<FlushResult>,\n\t\tprivate readonly relayServiceTenantAndSessionId: () => string | undefined,\n\t\tprivate readonly snapshotFormatFetchType?: SnapshotFormatSupportType,\n\t) {\n\t\tsuper(loggerToMonitoringContext(logger).config);\n\n\t\tthis.documentId = this.odspResolvedUrl.hashedDocumentId;\n\t\tthis.snapshotUrl = this.odspResolvedUrl.endpoints.snapshotStorageUrl;\n\t\tthis.attachmentPOSTUrl = this.odspResolvedUrl.endpoints.attachmentPOSTStorageUrl;\n\t\tthis.attachmentGETUrl = this.odspResolvedUrl.endpoints.attachmentGETStorageUrl;\n\t}\n\n\tpublic async createBlob(file: ArrayBufferLike): Promise<api.ICreateBlobResponse> {\n\t\tthis.checkAttachmentPOSTUrl();\n\n\t\tconst response = await getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"CreateBlob\");\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\t`${this.attachmentPOSTUrl}/content`,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\t\t\theaders[\"Content-Type\"] = \"application/octet-stream\";\n\n\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"createBlob\",\n\t\t\t\t\tsize: file.byteLength,\n\t\t\t\t\twaitQueueLength: this.createBlobRateLimiter.waitQueueLength,\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tconst res = await this.createBlobRateLimiter.schedule(async () =>\n\t\t\t\t\t\tthis.epochTracker.fetchAndParseAsJSON<api.ICreateBlobResponse>(\n\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbody: file,\n\t\t\t\t\t\t\t\theaders,\n\t\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"createBlob\",\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\tblobId: res.content.id,\n\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t});\n\t\t\t\t\treturn res;\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\n\t\treturn response.content;\n\t}\n\n\tprotected async fetchBlobFromStorage(blobId: string, evicted: boolean): Promise<ArrayBuffer> {\n\t\tthis.checkAttachmentGETUrl();\n\n\t\tconst blob = await getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"GetBlob\");\n\t\t\tconst unAuthedUrl = `${this.attachmentGETUrl}/${encodeURIComponent(blobId)}/content`;\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\tunAuthedUrl,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\n\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"readDataBlob\",\n\t\t\t\t\tblobId,\n\t\t\t\t\tevicted,\n\t\t\t\t\theaders: Object.keys(headers).length !== 0 ? true : undefined,\n\t\t\t\t\twaitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tconst res = await this.epochTracker.fetchArray(url, { headers }, \"blob\");\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\twaitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t\tattempts: options.refresh ? 2 : 1,\n\t\t\t\t\t});\n\t\t\t\t\tconst cacheControl = res.headers.get(\"cache-control\");\n\t\t\t\t\tif (\n\t\t\t\t\t\tcacheControl === undefined ||\n\t\t\t\t\t\t!(cacheControl.includes(\"private\") || cacheControl.includes(\"public\"))\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\t\teventName: \"NonCacheableBlob\",\n\t\t\t\t\t\t\tcacheControl,\n\t\t\t\t\t\t\tblobId,\n\t\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn res.content;\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t\tthis.blobCache.setBlob(blobId, blob);\n\t\treturn blob;\n\t}\n\n\tpublic async getSnapshotTree(\n\t\tversion?: api.IVersion,\n\t\tscenarioName?: string,\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t): Promise<api.ISnapshotTree | null> {\n\t\tif (!this.snapshotUrl) {\n\t\t\treturn null;\n\t\t}\n\t\treturn super.getSnapshotTree(version, scenarioName);\n\t}\n\n\tpublic async getVersions(\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tblobid: string | null,\n\t\tcount: number,\n\t\tscenarioName?: string,\n\t\tfetchSource?: FetchSource,\n\t): Promise<api.IVersion[]> {\n\t\t// Regular load workflow uses blobId === documentID to indicate \"latest\".\n\t\tif (blobid !== this.documentId && blobid) {\n\t\t\t// FluidFetch & FluidDebugger tools use empty sting to query for versions\n\t\t\t// In such case we need to make a call against SPO to give full picture to the tool.\n\t\t\t// Otherwise, each commit calls getVersions but odsp doesn't have a history for each commit\n\t\t\t// return the blobid as is\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: blobid,\n\t\t\t\t\ttreeId: undefined!,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\t// Can't really make a call if we do not have URL\n\t\tif (!this.snapshotUrl) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// If count is one, we can use the trees/latest API, which returns the latest version and trees in a single request for better performance\n\t\tif (count === 1 && (blobid === null || blobid === this.documentId)) {\n\t\t\tconst hostSnapshotOptions = this.hostPolicy.snapshotOptions;\n\t\t\tconst odspSnapshotCacheValue: ISnapshotContents = await PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{ eventName: \"ObtainSnapshot\", fetchSource },\n\t\t\t\tasync (event: PerformanceEvent) => {\n\t\t\t\t\tconst props: GetVersionsTelemetryProps = {};\n\t\t\t\t\tlet retrievedSnapshot:\n\t\t\t\t\t\t| ISnapshotContents\n\t\t\t\t\t\t| IPrefetchSnapshotContents\n\t\t\t\t\t\t| undefined;\n\n\t\t\t\t\tlet method: string;\n\t\t\t\t\tlet prefetchWaitStartTime: number = performance.now();\n\t\t\t\t\tif (fetchSource === FetchSource.noCache) {\n\t\t\t\t\t\tretrievedSnapshot = await this.fetchSnapshot(\n\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tmethod = \"networkOnly\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Here's the logic to grab the persistent cache snapshot implemented by the host\n\t\t\t\t\t\t// Epoch tracker is responsible for communicating with the persistent cache, handling epochs and cache versions\n\t\t\t\t\t\tconst cachedSnapshotP: Promise<ISnapshotContents | undefined> =\n\t\t\t\t\t\t\tthis.epochTracker\n\t\t\t\t\t\t\t\t.get(createCacheSnapshotKey(this.odspResolvedUrl))\n\t\t\t\t\t\t\t\t.then(async (snapshotCachedEntry: ISnapshotCachedEntry) => {\n\t\t\t\t\t\t\t\t\tif (snapshotCachedEntry !== undefined) {\n\t\t\t\t\t\t\t\t\t\t// If the cached entry does not contain the entry time, then assign it a default of 30 days old.\n\t\t\t\t\t\t\t\t\t\tconst age =\n\t\t\t\t\t\t\t\t\t\t\tDate.now() -\n\t\t\t\t\t\t\t\t\t\t\t(snapshotCachedEntry.cacheEntryTime ??\n\t\t\t\t\t\t\t\t\t\t\t\tDate.now() - 30 * 24 * 60 * 60 * 1000);\n\n\t\t\t\t\t\t\t\t\t\t// In order to decrease the number of times we have to execute a snapshot refresh,\n\t\t\t\t\t\t\t\t\t\t// if this is the summarizer and we have a cache entry but it is past the defaultSummarizerCacheExpiryTimeout,\n\t\t\t\t\t\t\t\t\t\t// force the network retrieval instead as there might be a more recent snapshot available.\n\t\t\t\t\t\t\t\t\t\t// See: https://github.com/microsoft/FluidFramework/issues/8995 for additional information.\n\t\t\t\t\t\t\t\t\t\tif (this.hostPolicy.summarizerClient) {\n\t\t\t\t\t\t\t\t\t\t\tif (age > defaultSummarizerCacheExpiryTimeout) {\n\t\t\t\t\t\t\t\t\t\t\t\tprops.cacheSummarizerExpired = true;\n\t\t\t\t\t\t\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tprops.cacheSummarizerExpired = false;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Record the cache age\n\t\t\t\t\t\t\t\t\t\tprops.cacheEntryAge = age;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\treturn snapshotCachedEntry;\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// Based on the concurrentSnapshotFetch policy:\n\t\t\t\t\t\t// Either retrieve both the network and cache snapshots concurrently and pick the first to return,\n\t\t\t\t\t\t// or grab the cache value and then the network value if the cache value returns undefined.\n\t\t\t\t\t\t// For summarizer which could call this during refreshing of summary parent, always use the cache\n\t\t\t\t\t\t// first. Also for other clients, if it is not critical path which is determined by firstVersionCall,\n\t\t\t\t\t\t// then also check the cache first.\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tthis.firstVersionCall &&\n\t\t\t\t\t\t\tthis.hostPolicy.concurrentSnapshotFetch &&\n\t\t\t\t\t\t\t!this.hostPolicy.summarizerClient\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tconst networkSnapshotP = this.fetchSnapshot(\n\t\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// Ensure that failures on both paths are ignored initially.\n\t\t\t\t\t\t\t// I.e. if cache fails for some reason, we will proceed with network result.\n\t\t\t\t\t\t\t// And vice versa - if (for example) client is offline and network request fails first, we\n\t\t\t\t\t\t\t// do want to attempt to succeed with cached data!\n\t\t\t\t\t\t\tconst promiseRaceWinner = await promiseRaceWithWinner([\n\t\t\t\t\t\t\t\tcachedSnapshotP.catch(() => undefined),\n\t\t\t\t\t\t\t\tnetworkSnapshotP.catch(() => undefined),\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\tretrievedSnapshot = promiseRaceWinner.value;\n\t\t\t\t\t\t\tmethod = promiseRaceWinner.index === 0 ? \"cache\" : \"network\";\n\n\t\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t\t// if network failed -> wait for cache ( then return network failure)\n\t\t\t\t\t\t\t\t// If cache returned empty or failed -> wait for network (success of failure)\n\t\t\t\t\t\t\t\tif (promiseRaceWinner.index === 1) {\n\t\t\t\t\t\t\t\t\tretrievedSnapshot = await cachedSnapshotP;\n\t\t\t\t\t\t\t\t\tmethod = \"cache\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t\t\tretrievedSnapshot = await networkSnapshotP;\n\t\t\t\t\t\t\t\t\tmethod = \"network\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Note: There's a race condition here - another caller may come past the undefined check\n\t\t\t\t\t\t\t// while the first caller is awaiting later async code in this block.\n\n\t\t\t\t\t\t\tretrievedSnapshot = await cachedSnapshotP;\n\n\t\t\t\t\t\t\tmethod = retrievedSnapshot !== undefined ? \"cache\" : \"network\";\n\n\t\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t\tprefetchWaitStartTime = performance.now();\n\t\t\t\t\t\t\t\tretrievedSnapshot = await this.fetchSnapshot(\n\t\t\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (method === \"network\") {\n\t\t\t\t\t\tprops.cacheEntryAge = undefined;\n\t\t\t\t\t}\n\t\t\t\t\tconst prefetchStartTime: number | undefined = (\n\t\t\t\t\t\tretrievedSnapshot as IPrefetchSnapshotContents\n\t\t\t\t\t).prefetchStartTime;\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tmethod,\n\t\t\t\t\t\tavoidPrefetchSnapshotCache: this.hostPolicy.avoidPrefetchSnapshotCache,\n\t\t\t\t\t\tprefetchSavedDuration:\n\t\t\t\t\t\t\tprefetchStartTime !== undefined && method !== \"cache\"\n\t\t\t\t\t\t\t\t? prefetchWaitStartTime - prefetchStartTime\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t});\n\t\t\t\t\treturn retrievedSnapshot;\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Don't override ops which were fetched during initial load, since we could still need them.\n\t\t\tconst id = this.initializeFromSnapshot(odspSnapshotCacheValue, this.firstVersionCall);\n\t\t\tthis.firstVersionCall = false;\n\n\t\t\treturn id ? [{ id, treeId: undefined! }] : [];\n\t\t}\n\n\t\treturn getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"GetVersions\");\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\t`${this.snapshotUrl}/versions?top=${count}`,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\n\t\t\t// Fetch the latest snapshot versions for the document\n\t\t\tconst response = await PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"getVersions\",\n\t\t\t\t\theaders: Object.keys(headers).length !== 0 ? true : undefined,\n\t\t\t\t},\n\t\t\t\tasync () =>\n\t\t\t\t\tthis.epochTracker.fetchAndParseAsJSON<IDocumentStorageGetVersionsResponse>(\n\t\t\t\t\t\turl,\n\t\t\t\t\t\t{ headers },\n\t\t\t\t\t\t\"versions\",\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tconst versionsResponse = response.content;\n\t\t\tif (!versionsResponse) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\"No response from /versions endpoint\",\n\t\t\t\t\tDriverErrorType.genericNetworkError,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!Array.isArray(versionsResponse.value)) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\"Incorrect response from /versions endpoint, expected an array\",\n\t\t\t\t\tDriverErrorType.genericNetworkError,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn versionsResponse.value.map((version) => {\n\t\t\t\treturn {\n\t\t\t\t\tid: version.id,\n\t\t\t\t\ttreeId: undefined!,\n\t\t\t\t};\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate async fetchSnapshot(\n\t\thostSnapshotOptions: ISnapshotOptions | undefined,\n\t\tscenarioName?: string,\n\t) {\n\t\treturn this.fetchSnapshotCore(hostSnapshotOptions, scenarioName).catch((error) => {\n\t\t\t// Issue #5895:\n\t\t\t// If we are offline, this error is retryable. But that means that RetriableDocumentStorageService\n\t\t\t// will run in circles calling getSnapshotTree, which would result in OdspDocumentStorageService class\n\t\t\t// going getVersions / individual blob download path. This path is very slow, and will not work with\n\t\t\t// delay-loaded data stores and ODSP storage deleting old snapshots and blobs.\n\t\t\tif (typeof error === \"object\" && error !== null) {\n\t\t\t\terror.canRetry = false;\n\t\t\t}\n\t\t\tthrow error;\n\t\t});\n\t}\n\n\tprivate async fetchSnapshotCore(\n\t\thostSnapshotOptions: ISnapshotOptions | undefined,\n\t\tscenarioName?: string,\n\t): Promise<ISnapshotContents | IPrefetchSnapshotContents> {\n\t\t// Don't look into cache, if the host specifically tells us so.\n\t\tif (!this.hostPolicy.avoidPrefetchSnapshotCache) {\n\t\t\tconst prefetchCacheKey = getKeyForCacheEntry(\n\t\t\t\tcreateCacheSnapshotKey(this.odspResolvedUrl),\n\t\t\t);\n\t\t\tconst result = await this.cache.snapshotPrefetchResultCache\n\t\t\t\t?.get(prefetchCacheKey)\n\t\t\t\t?.then(async (response) => {\n\t\t\t\t\t// Validate the epoch from the prefetched snapshot result.\n\t\t\t\t\tawait this.epochTracker.validateEpoch(response.fluidEpoch, \"treesLatest\");\n\t\t\t\t\treturn response;\n\t\t\t\t})\n\t\t\t\t.catch(async (err) => {\n\t\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"PrefetchSnapshotError\",\n\t\t\t\t\t\t\tconcurrentSnapshotFetch: this.hostPolicy.concurrentSnapshotFetch,\n\t\t\t\t\t\t},\n\t\t\t\t\t\terr,\n\t\t\t\t\t);\n\t\t\t\t\treturn undefined;\n\t\t\t\t});\n\t\t\t// If the prefetch call, is successful, then return the contents otherwise as backup for now, just\n\t\t\t// proceed with the old snapshot fetch flow.\n\t\t\tif (result !== undefined) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t\tconst snapshotOptions: ISnapshotOptions = {\n\t\t\tmds: this.maxSnapshotSizeLimit,\n\t\t\t...hostSnapshotOptions,\n\t\t\ttimeout: hostSnapshotOptions?.timeout\n\t\t\t\t? Math.min(hostSnapshotOptions.timeout, this.maxSnapshotFetchTimeout)\n\t\t\t\t: this.maxSnapshotFetchTimeout,\n\t\t};\n\n\t\t// No limit on size of snapshot or time to fetch, as otherwise we fail all clients to summarize\n\t\tif (this.hostPolicy.summarizerClient) {\n\t\t\tsnapshotOptions.mds = undefined;\n\t\t\tsnapshotOptions.timeout = undefined;\n\t\t}\n\n\t\tconst snapshotDownloader = async (\n\t\t\tfinalOdspResolvedUrl: IOdspResolvedUrl,\n\t\t\tstorageToken: string,\n\t\t\toptions: ISnapshotOptions | undefined,\n\t\t\tcontroller?: AbortController,\n\t\t) => {\n\t\t\treturn downloadSnapshot(\n\t\t\t\tfinalOdspResolvedUrl,\n\t\t\t\tstorageToken,\n\t\t\t\tthis.logger,\n\t\t\t\toptions,\n\t\t\t\tthis.snapshotFormatFetchType,\n\t\t\t\tcontroller,\n\t\t\t\tthis.epochTracker,\n\t\t\t\tscenarioName,\n\t\t\t);\n\t\t};\n\t\tconst putInCache = async (valueWithEpoch: IVersionedValueWithEpoch) => {\n\t\t\treturn this.cache.persistedCache.put(\n\t\t\t\tcreateCacheSnapshotKey(this.odspResolvedUrl),\n\t\t\t\t// Epoch tracker will add the epoch and version to the value here. So just send value to cache.\n\t\t\t\tvalueWithEpoch.value,\n\t\t\t);\n\t\t};\n\t\tconst removeEntries = async () => this.cache.persistedCache.removeEntries();\n\t\ttry {\n\t\t\tconst odspSnapshot = await fetchSnapshotWithRedeem(\n\t\t\t\tthis.odspResolvedUrl,\n\t\t\t\tthis.getStorageToken,\n\t\t\t\tsnapshotOptions,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\tthis.logger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t\tputInCache,\n\t\t\t\tremoveEntries,\n\t\t\t\tthis.hostPolicy.enableRedeemFallback,\n\t\t\t);\n\t\t\treturn odspSnapshot;\n\t\t} catch (error: any) {\n\t\t\tconst errorType = error.errorType;\n\t\t\t// If the snapshot size is too big and the host specified the size limitation(specified in hostSnapshotOptions), then don't try to fetch the snapshot again.\n\t\t\tif (\n\t\t\t\terrorType === OdspErrorType.snapshotTooBig &&\n\t\t\t\thostSnapshotOptions?.mds !== undefined &&\n\t\t\t\tthis.hostPolicy.summarizerClient !== true\n\t\t\t) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\t// If the first snapshot request was with blobs and we either timed out or the size was too big, then try to fetch without blobs.\n\t\t\tif (\n\t\t\t\t(errorType === OdspErrorType.snapshotTooBig ||\n\t\t\t\t\terrorType === OdspErrorType.fetchTimeout) &&\n\t\t\t\tsnapshotOptions.blobs\n\t\t\t) {\n\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\teventName: \"TreeLatest_SecondCall\",\n\t\t\t\t\terrorType,\n\t\t\t\t});\n\t\t\t\tconst snapshotOptionsWithoutBlobs: ISnapshotOptions = {\n\t\t\t\t\t...snapshotOptions,\n\t\t\t\t\tblobs: 0,\n\t\t\t\t\tmds: undefined,\n\t\t\t\t\ttimeout: undefined,\n\t\t\t\t};\n\t\t\t\tconst odspSnapshot = await fetchSnapshotWithRedeem(\n\t\t\t\t\tthis.odspResolvedUrl,\n\t\t\t\t\tthis.getStorageToken,\n\t\t\t\t\tsnapshotOptionsWithoutBlobs,\n\t\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tsnapshotDownloader,\n\t\t\t\t\tputInCache,\n\t\t\t\t\tremoveEntries,\n\t\t\t\t\tthis.hostPolicy.enableRedeemFallback,\n\t\t\t\t);\n\t\t\t\treturn odspSnapshot;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic async uploadSummaryWithContext(\n\t\tsummary: api.ISummaryTree,\n\t\tcontext: ISummaryContext,\n\t): Promise<string> {\n\t\tthis.checkSnapshotUrl();\n\n\t\t// Set the module promise right away, so as to not call it twice.\n\t\tif (this.summaryModuleP === undefined) {\n\t\t\tthis.summaryModuleP = this.getDelayLoadedSummaryManager();\n\t\t}\n\n\t\t// Enable flushing only if we have single commit summary and this is not the initial summary for an empty file\n\t\tif (\".protocol\" in summary.tree && context.ackHandle !== undefined) {\n\t\t\tlet retry = 1;\n\t\t\tfor (;;) {\n\t\t\t\tconst result = await this.flushCallback();\n\t\t\t\tconst seq = result.lastPersistedSequenceNumber;\n\t\t\t\tif (seq !== undefined && seq >= context.referenceSequenceNumber) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (retry > 3) {\n\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\teventName: \"FlushFailure\",\n\t\t\t\t\t\t...result,\n\t\t\t\t\t\tretry,\n\t\t\t\t\t\treferenceSequenceNumber: context.referenceSequenceNumber,\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\teventName: \"FlushExtraCall\",\n\t\t\t\t\t...result,\n\t\t\t\t\tretry,\n\t\t\t\t\treferenceSequenceNumber: context.referenceSequenceNumber,\n\t\t\t\t});\n\n\t\t\t\tretry++;\n\t\t\t\tawait delay(1000 * (result.retryAfter ?? 1));\n\t\t\t}\n\t\t}\n\n\t\tif (!this.odspSummaryUploadManager) {\n\t\t\tthis.odspSummaryUploadManager = await this.summaryModuleP\n\t\t\t\t.then(async (m) => {\n\t\t\t\t\tthis.odspSummaryModuleLoaded = true;\n\t\t\t\t\treturn m;\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tthis.odspSummaryModuleLoaded = false;\n\t\t\t\t\tthrow error;\n\t\t\t\t});\n\t\t}\n\n\t\tassert(\n\t\t\tthis.odspSummaryUploadManager !== undefined,\n\t\t\t0x56e /* summary upload manager should have been initialized */,\n\t\t);\n\t\tconst id = await this.odspSummaryUploadManager.writeSummaryTree(summary, context);\n\t\treturn id;\n\t}\n\n\tprivate async getDelayLoadedSummaryManager() {\n\t\tassert(this.odspSummaryModuleLoaded === false, 0x56f /* Should be loaded only once */);\n\t\tconst module = await import(\n\t\t\t/* webpackChunkName: \"summaryModule\" */ \"./odspSummaryUploadManager\"\n\t\t)\n\t\t\t.then((m) => {\n\t\t\t\tthis.logger.sendTelemetryEvent({ eventName: \"SummaryModuleLoaded\" });\n\t\t\t\treturn m;\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.logger.sendErrorEvent({ eventName: \"SummaryModuleLoadFailed\" }, error);\n\t\t\t\tthrow error;\n\t\t\t});\n\t\tthis.odspSummaryUploadManager = new module.OdspSummaryUploadManager(\n\t\t\tthis.odspResolvedUrl.endpoints.snapshotStorageUrl,\n\t\t\tthis.getStorageToken,\n\t\t\tthis.logger,\n\t\t\tthis.epochTracker,\n\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\tthis.relayServiceTenantAndSessionId,\n\t\t);\n\t\treturn this.odspSummaryUploadManager;\n\t}\n\n\tprivate checkSnapshotUrl() {\n\t\tif (!this.snapshotUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no snapshot url was available\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate checkAttachmentPOSTUrl() {\n\t\tif (!this.attachmentPOSTUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no attachment POST url was available\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate checkAttachmentGETUrl() {\n\t\tif (!this.attachmentGETUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no attachment GET url was available\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprotected async fetchTreeFromSnapshot(\n\t\tid: string,\n\t\tscenarioName?: string,\n\t): Promise<api.ISnapshotTree | undefined> {\n\t\treturn getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"ReadCommit\");\n\t\t\tconst snapshotDownloader = async (\n\t\t\t\turl: string,\n\t\t\t\tfetchOptions: { [index: string]: any },\n\t\t\t) => {\n\t\t\t\treturn this.epochTracker.fetchAndParseAsJSON(\n\t\t\t\t\turl,\n\t\t\t\t\tfetchOptions,\n\t\t\t\t\t\"snapshotTree\",\n\t\t\t\t\tundefined,\n\t\t\t\t\tscenarioName,\n\t\t\t\t);\n\t\t\t};\n\t\t\tconst snapshot = await fetchSnapshot(\n\t\t\t\tthis.snapshotUrl!,\n\t\t\t\tstorageToken,\n\t\t\t\tid,\n\t\t\t\tthis.fetchFullSnapshot,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\tthis.logger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t);\n\t\t\tlet treeId = \"\";\n\t\t\tif (snapshot.snapshotTree) {\n\t\t\t\tassert(\n\t\t\t\t\tsnapshot.snapshotTree.id !== undefined,\n\t\t\t\t\t0x222 /* \"Root tree should contain the id!!\" */,\n\t\t\t\t);\n\t\t\t\ttreeId = snapshot.snapshotTree.id;\n\t\t\t\tthis.setRootTree(treeId, snapshot.snapshotTree);\n\t\t\t}\n\t\t\tif (snapshot.blobs) {\n\t\t\t\tthis.initBlobsCache(snapshot.blobs);\n\t\t\t}\n\t\t\t// If the version id doesn't match with the id of the tree, then use the id of first tree which in that case\n\t\t\t// will be the actual id of tree to be fetched.\n\t\t\treturn this.commitCache.get(id) ?? this.commitCache.get(treeId);\n\t\t});\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"odspDocumentStorageManager.js","sourceRoot":"","sources":["../src/odspDocumentStorageManager.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, delay, performance } from \"@fluidframework/common-utils\";\nimport { loggerToMonitoringContext, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport * as api from \"@fluidframework/protocol-definitions\";\nimport { promiseRaceWithWinner } from \"@fluidframework/driver-base\";\nimport { ISummaryContext, DriverErrorType, FetchSource } from \"@fluidframework/driver-definitions\";\nimport { RateLimiter, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport {\n\tIOdspResolvedUrl,\n\tISnapshotOptions,\n\tOdspErrorType,\n\tInstrumentedStorageTokenFetcher,\n\tgetKeyForCacheEntry,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport {\n\tIDocumentStorageGetVersionsResponse,\n\tHostStoragePolicyInternal,\n\tIVersionedValueWithEpoch,\n\tISnapshotCachedEntry,\n} from \"./contracts\";\nimport {\n\tdownloadSnapshot,\n\tfetchSnapshot,\n\tfetchSnapshotWithRedeem,\n\tSnapshotFormatSupportType,\n} from \"./fetchSnapshot\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport { IOdspCache, IPrefetchSnapshotContents } from \"./odspCache\";\nimport { createCacheSnapshotKey, getWithRetryForTokenRefresh } from \"./odspUtils\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { EpochTracker } from \"./epochTracker\";\nimport type { OdspSummaryUploadManager } from \"./odspSummaryUploadManager\";\nimport { FlushResult } from \"./odspDocumentDeltaConnection\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\nimport { OdspDocumentStorageServiceBase } from \"./odspDocumentStorageServiceBase\";\n\nexport const defaultSummarizerCacheExpiryTimeout: number = 60 * 1000; // 60 seconds.\n\ninterface GetVersionsTelemetryProps {\n\tcacheEntryAge?: number;\n\tcacheSummarizerExpired?: boolean;\n}\n\nexport class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {\n\tprivate odspSummaryModuleLoaded: boolean = false;\n\tprivate summaryModuleP: Promise<OdspSummaryUploadManager> | undefined;\n\tprivate odspSummaryUploadManager: OdspSummaryUploadManager | undefined;\n\n\tprivate firstVersionCall = true;\n\n\tprivate readonly documentId: string;\n\tprivate readonly snapshotUrl: string | undefined;\n\tprivate readonly attachmentPOSTUrl: string | undefined;\n\tprivate readonly attachmentGETUrl: string | undefined;\n\t// Driver specified limits for snapshot size and time.\n\t/**\n\t * NOTE: While commit cfff6e3 added restrictions to prevent large payloads, snapshot failures will continue to\n\t * happen until blob request throttling is implemented. Until then, as a temporary fix we set arbitrarily large\n\t * snapshot size and timeout limits so that such failures are unlikely to occur.\n\t */\n\tprivate readonly maxSnapshotSizeLimit = 500000000; // 500 MB\n\tprivate readonly maxSnapshotFetchTimeout = 120000; // 2 min\n\n\t// limits the amount of parallel \"attachment\" blob uploads\n\tprivate readonly createBlobRateLimiter = new RateLimiter(1);\n\n\tconstructor(\n\t\tprivate readonly odspResolvedUrl: IOdspResolvedUrl,\n\t\tprivate readonly getStorageToken: InstrumentedStorageTokenFetcher,\n\t\tprivate readonly logger: ITelemetryLogger,\n\t\tprivate readonly fetchFullSnapshot: boolean,\n\t\tprivate readonly cache: IOdspCache,\n\t\tprivate readonly hostPolicy: HostStoragePolicyInternal,\n\t\tprivate readonly epochTracker: EpochTracker,\n\t\tprivate readonly flushCallback: () => Promise<FlushResult>,\n\t\tprivate readonly relayServiceTenantAndSessionId: () => string | undefined,\n\t\tprivate readonly snapshotFormatFetchType?: SnapshotFormatSupportType,\n\t) {\n\t\tsuper(loggerToMonitoringContext(logger).config);\n\n\t\tthis.documentId = this.odspResolvedUrl.hashedDocumentId;\n\t\tthis.snapshotUrl = this.odspResolvedUrl.endpoints.snapshotStorageUrl;\n\t\tthis.attachmentPOSTUrl = this.odspResolvedUrl.endpoints.attachmentPOSTStorageUrl;\n\t\tthis.attachmentGETUrl = this.odspResolvedUrl.endpoints.attachmentGETStorageUrl;\n\t}\n\n\tpublic async createBlob(file: ArrayBufferLike): Promise<api.ICreateBlobResponse> {\n\t\tthis.checkAttachmentPOSTUrl();\n\n\t\tconst response = await getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"CreateBlob\");\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\t`${this.attachmentPOSTUrl}/content`,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\t\t\theaders[\"Content-Type\"] = \"application/octet-stream\";\n\n\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"createBlob\",\n\t\t\t\t\tsize: file.byteLength,\n\t\t\t\t\twaitQueueLength: this.createBlobRateLimiter.waitQueueLength,\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tconst res = await this.createBlobRateLimiter.schedule(async () =>\n\t\t\t\t\t\tthis.epochTracker.fetchAndParseAsJSON<api.ICreateBlobResponse>(\n\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbody: file,\n\t\t\t\t\t\t\t\theaders,\n\t\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"createBlob\",\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\tblobId: res.content.id,\n\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t});\n\t\t\t\t\treturn res;\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\n\t\treturn response.content;\n\t}\n\n\tprotected async fetchBlobFromStorage(blobId: string, evicted: boolean): Promise<ArrayBuffer> {\n\t\tthis.checkAttachmentGETUrl();\n\n\t\tconst blob = await getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"GetBlob\");\n\t\t\tconst unAuthedUrl = `${this.attachmentGETUrl}/${encodeURIComponent(blobId)}/content`;\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\tunAuthedUrl,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\n\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"readDataBlob\",\n\t\t\t\t\tblobId,\n\t\t\t\t\tevicted,\n\t\t\t\t\theaders: Object.keys(headers).length !== 0 ? true : undefined,\n\t\t\t\t\twaitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tconst res = await this.epochTracker.fetchArray(url, { headers }, \"blob\");\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\twaitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t\tattempts: options.refresh ? 2 : 1,\n\t\t\t\t\t});\n\t\t\t\t\tconst cacheControl = res.headers.get(\"cache-control\");\n\t\t\t\t\tif (\n\t\t\t\t\t\tcacheControl === undefined ||\n\t\t\t\t\t\t!(cacheControl.includes(\"private\") || cacheControl.includes(\"public\"))\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\t\teventName: \"NonCacheableBlob\",\n\t\t\t\t\t\t\tcacheControl,\n\t\t\t\t\t\t\tblobId,\n\t\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn res.content;\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t\tthis.blobCache.setBlob(blobId, blob);\n\t\treturn blob;\n\t}\n\n\tpublic async getSnapshotTree(\n\t\tversion?: api.IVersion,\n\t\tscenarioName?: string,\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t): Promise<api.ISnapshotTree | null> {\n\t\tif (!this.snapshotUrl) {\n\t\t\treturn null;\n\t\t}\n\t\treturn super.getSnapshotTree(version, scenarioName);\n\t}\n\n\tpublic async getVersions(\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tblobid: string | null,\n\t\tcount: number,\n\t\tscenarioName?: string,\n\t\tfetchSource?: FetchSource,\n\t): Promise<api.IVersion[]> {\n\t\t// Regular load workflow uses blobId === documentID to indicate \"latest\".\n\t\tif (blobid !== this.documentId && blobid) {\n\t\t\t// FluidFetch & FluidDebugger tools use empty sting to query for versions\n\t\t\t// In such case we need to make a call against SPO to give full picture to the tool.\n\t\t\t// Otherwise, each commit calls getVersions but odsp doesn't have a history for each commit\n\t\t\t// return the blobid as is\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: blobid,\n\t\t\t\t\ttreeId: undefined!,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\t// Can't really make a call if we do not have URL\n\t\tif (!this.snapshotUrl) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// If count is one, we can use the trees/latest API, which returns the latest version and trees in a single request for better performance\n\t\tif (count === 1 && (blobid === null || blobid === this.documentId)) {\n\t\t\tconst hostSnapshotOptions = this.hostPolicy.snapshotOptions;\n\t\t\tconst odspSnapshotCacheValue: ISnapshotContents = await PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{ eventName: \"ObtainSnapshot\", fetchSource },\n\t\t\t\tasync (event: PerformanceEvent) => {\n\t\t\t\t\tconst props: GetVersionsTelemetryProps = {};\n\t\t\t\t\tlet retrievedSnapshot:\n\t\t\t\t\t\t| ISnapshotContents\n\t\t\t\t\t\t| IPrefetchSnapshotContents\n\t\t\t\t\t\t| undefined;\n\n\t\t\t\t\tlet method: string;\n\t\t\t\t\tlet prefetchWaitStartTime: number = performance.now();\n\t\t\t\t\tif (fetchSource === FetchSource.noCache) {\n\t\t\t\t\t\tretrievedSnapshot = await this.fetchSnapshot(\n\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tmethod = \"networkOnly\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Here's the logic to grab the persistent cache snapshot implemented by the host\n\t\t\t\t\t\t// Epoch tracker is responsible for communicating with the persistent cache, handling epochs and cache versions\n\t\t\t\t\t\tconst cachedSnapshotP: Promise<ISnapshotContents | undefined> =\n\t\t\t\t\t\t\tthis.epochTracker\n\t\t\t\t\t\t\t\t.get(createCacheSnapshotKey(this.odspResolvedUrl))\n\t\t\t\t\t\t\t\t.then(async (snapshotCachedEntry: ISnapshotCachedEntry) => {\n\t\t\t\t\t\t\t\t\tif (snapshotCachedEntry !== undefined) {\n\t\t\t\t\t\t\t\t\t\t// If the cached entry does not contain the entry time, then assign it a default of 30 days old.\n\t\t\t\t\t\t\t\t\t\tconst age =\n\t\t\t\t\t\t\t\t\t\t\tDate.now() -\n\t\t\t\t\t\t\t\t\t\t\t(snapshotCachedEntry.cacheEntryTime ??\n\t\t\t\t\t\t\t\t\t\t\t\tDate.now() - 30 * 24 * 60 * 60 * 1000);\n\n\t\t\t\t\t\t\t\t\t\t// In order to decrease the number of times we have to execute a snapshot refresh,\n\t\t\t\t\t\t\t\t\t\t// if this is the summarizer and we have a cache entry but it is past the defaultSummarizerCacheExpiryTimeout,\n\t\t\t\t\t\t\t\t\t\t// force the network retrieval instead as there might be a more recent snapshot available.\n\t\t\t\t\t\t\t\t\t\t// See: https://github.com/microsoft/FluidFramework/issues/8995 for additional information.\n\t\t\t\t\t\t\t\t\t\tif (this.hostPolicy.summarizerClient) {\n\t\t\t\t\t\t\t\t\t\t\tif (age > defaultSummarizerCacheExpiryTimeout) {\n\t\t\t\t\t\t\t\t\t\t\t\tprops.cacheSummarizerExpired = true;\n\t\t\t\t\t\t\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tprops.cacheSummarizerExpired = false;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Record the cache age\n\t\t\t\t\t\t\t\t\t\tprops.cacheEntryAge = age;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\treturn snapshotCachedEntry;\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// Based on the concurrentSnapshotFetch policy:\n\t\t\t\t\t\t// Either retrieve both the network and cache snapshots concurrently and pick the first to return,\n\t\t\t\t\t\t// or grab the cache value and then the network value if the cache value returns undefined.\n\t\t\t\t\t\t// For summarizer which could call this during refreshing of summary parent, always use the cache\n\t\t\t\t\t\t// first. Also for other clients, if it is not critical path which is determined by firstVersionCall,\n\t\t\t\t\t\t// then also check the cache first.\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tthis.firstVersionCall &&\n\t\t\t\t\t\t\tthis.hostPolicy.concurrentSnapshotFetch &&\n\t\t\t\t\t\t\t!this.hostPolicy.summarizerClient\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tconst networkSnapshotP = this.fetchSnapshot(\n\t\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// Ensure that failures on both paths are ignored initially.\n\t\t\t\t\t\t\t// I.e. if cache fails for some reason, we will proceed with network result.\n\t\t\t\t\t\t\t// And vice versa - if (for example) client is offline and network request fails first, we\n\t\t\t\t\t\t\t// do want to attempt to succeed with cached data!\n\t\t\t\t\t\t\tconst promiseRaceWinner = await promiseRaceWithWinner([\n\t\t\t\t\t\t\t\tcachedSnapshotP.catch(() => undefined),\n\t\t\t\t\t\t\t\tnetworkSnapshotP.catch(() => undefined),\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\tretrievedSnapshot = promiseRaceWinner.value;\n\t\t\t\t\t\t\tmethod = promiseRaceWinner.index === 0 ? \"cache\" : \"network\";\n\n\t\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t\t// if network failed -> wait for cache ( then return network failure)\n\t\t\t\t\t\t\t\t// If cache returned empty or failed -> wait for network (success of failure)\n\t\t\t\t\t\t\t\tif (promiseRaceWinner.index === 1) {\n\t\t\t\t\t\t\t\t\tretrievedSnapshot = await cachedSnapshotP;\n\t\t\t\t\t\t\t\t\tmethod = \"cache\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t\t\tretrievedSnapshot = await networkSnapshotP;\n\t\t\t\t\t\t\t\t\tmethod = \"network\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Note: There's a race condition here - another caller may come past the undefined check\n\t\t\t\t\t\t\t// while the first caller is awaiting later async code in this block.\n\n\t\t\t\t\t\t\tretrievedSnapshot = await cachedSnapshotP;\n\n\t\t\t\t\t\t\tmethod = retrievedSnapshot !== undefined ? \"cache\" : \"network\";\n\n\t\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t\tprefetchWaitStartTime = performance.now();\n\t\t\t\t\t\t\t\tretrievedSnapshot = await this.fetchSnapshot(\n\t\t\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (method === \"network\") {\n\t\t\t\t\t\tprops.cacheEntryAge = undefined;\n\t\t\t\t\t}\n\t\t\t\t\tconst prefetchStartTime: number | undefined = (\n\t\t\t\t\t\tretrievedSnapshot as IPrefetchSnapshotContents\n\t\t\t\t\t).prefetchStartTime;\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tmethod,\n\t\t\t\t\t\tavoidPrefetchSnapshotCache: this.hostPolicy.avoidPrefetchSnapshotCache,\n\t\t\t\t\t\tprefetchSavedDuration:\n\t\t\t\t\t\t\tprefetchStartTime !== undefined && method !== \"cache\"\n\t\t\t\t\t\t\t\t? prefetchWaitStartTime - prefetchStartTime\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t});\n\t\t\t\t\treturn retrievedSnapshot;\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Don't override ops which were fetched during initial load, since we could still need them.\n\t\t\tconst id = this.initializeFromSnapshot(odspSnapshotCacheValue, this.firstVersionCall);\n\t\t\tthis.firstVersionCall = false;\n\n\t\t\treturn id ? [{ id, treeId: undefined! }] : [];\n\t\t}\n\n\t\treturn getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"GetVersions\");\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\t`${this.snapshotUrl}/versions?top=${count}`,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\n\t\t\t// Fetch the latest snapshot versions for the document\n\t\t\tconst response = await PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"getVersions\",\n\t\t\t\t\theaders: Object.keys(headers).length !== 0 ? true : undefined,\n\t\t\t\t},\n\t\t\t\tasync () =>\n\t\t\t\t\tthis.epochTracker.fetchAndParseAsJSON<IDocumentStorageGetVersionsResponse>(\n\t\t\t\t\t\turl,\n\t\t\t\t\t\t{ headers },\n\t\t\t\t\t\t\"versions\",\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tconst versionsResponse = response.content;\n\t\t\tif (!versionsResponse) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\"No response from /versions endpoint\",\n\t\t\t\t\tDriverErrorType.genericNetworkError,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!Array.isArray(versionsResponse.value)) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\"Incorrect response from /versions endpoint, expected an array\",\n\t\t\t\t\tDriverErrorType.genericNetworkError,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn versionsResponse.value.map((version) => {\n\t\t\t\treturn {\n\t\t\t\t\tid: version.id,\n\t\t\t\t\ttreeId: undefined!,\n\t\t\t\t};\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate async fetchSnapshot(\n\t\thostSnapshotOptions: ISnapshotOptions | undefined,\n\t\tscenarioName?: string,\n\t) {\n\t\treturn this.fetchSnapshotCore(hostSnapshotOptions, scenarioName).catch((error) => {\n\t\t\t// Issue #5895:\n\t\t\t// If we are offline, this error is retryable. But that means that RetriableDocumentStorageService\n\t\t\t// will run in circles calling getSnapshotTree, which would result in OdspDocumentStorageService class\n\t\t\t// going getVersions / individual blob download path. This path is very slow, and will not work with\n\t\t\t// delay-loaded data stores and ODSP storage deleting old snapshots and blobs.\n\t\t\tif (typeof error === \"object\" && error !== null) {\n\t\t\t\terror.canRetry = false;\n\t\t\t}\n\t\t\tthrow error;\n\t\t});\n\t}\n\n\tprivate async fetchSnapshotCore(\n\t\thostSnapshotOptions: ISnapshotOptions | undefined,\n\t\tscenarioName?: string,\n\t): Promise<ISnapshotContents | IPrefetchSnapshotContents> {\n\t\t// Don't look into cache, if the host specifically tells us so.\n\t\tif (!this.hostPolicy.avoidPrefetchSnapshotCache) {\n\t\t\tconst prefetchCacheKey = getKeyForCacheEntry(\n\t\t\t\tcreateCacheSnapshotKey(this.odspResolvedUrl),\n\t\t\t);\n\t\t\tconst result = await this.cache.snapshotPrefetchResultCache\n\t\t\t\t?.get(prefetchCacheKey)\n\t\t\t\t?.then(async (response) => {\n\t\t\t\t\t// Validate the epoch from the prefetched snapshot result.\n\t\t\t\t\tawait this.epochTracker.validateEpoch(response.fluidEpoch, \"treesLatest\");\n\t\t\t\t\treturn response;\n\t\t\t\t})\n\t\t\t\t.catch(async (err) => {\n\t\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"PrefetchSnapshotError\",\n\t\t\t\t\t\t\tconcurrentSnapshotFetch: this.hostPolicy.concurrentSnapshotFetch,\n\t\t\t\t\t\t},\n\t\t\t\t\t\terr,\n\t\t\t\t\t);\n\t\t\t\t\treturn undefined;\n\t\t\t\t});\n\t\t\t// If the prefetch call, is successful, then return the contents otherwise as backup for now, just\n\t\t\t// proceed with the old snapshot fetch flow.\n\t\t\tif (result !== undefined) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t\tconst snapshotOptions: ISnapshotOptions = {\n\t\t\tmds: this.maxSnapshotSizeLimit,\n\t\t\t...hostSnapshotOptions,\n\t\t\ttimeout: hostSnapshotOptions?.timeout\n\t\t\t\t? Math.min(hostSnapshotOptions.timeout, this.maxSnapshotFetchTimeout)\n\t\t\t\t: this.maxSnapshotFetchTimeout,\n\t\t};\n\n\t\t// No limit on size of snapshot or time to fetch, as otherwise we fail all clients to summarize\n\t\tif (this.hostPolicy.summarizerClient) {\n\t\t\tsnapshotOptions.mds = undefined;\n\t\t\tsnapshotOptions.timeout = undefined;\n\t\t}\n\n\t\tconst snapshotDownloader = async (\n\t\t\tfinalOdspResolvedUrl: IOdspResolvedUrl,\n\t\t\tstorageToken: string,\n\t\t\toptions: ISnapshotOptions | undefined,\n\t\t\tcontroller?: AbortController,\n\t\t) => {\n\t\t\treturn downloadSnapshot(\n\t\t\t\tfinalOdspResolvedUrl,\n\t\t\t\tstorageToken,\n\t\t\t\tthis.logger,\n\t\t\t\toptions,\n\t\t\t\tthis.snapshotFormatFetchType,\n\t\t\t\tcontroller,\n\t\t\t\tthis.epochTracker,\n\t\t\t\tscenarioName,\n\t\t\t);\n\t\t};\n\t\tconst putInCache = async (valueWithEpoch: IVersionedValueWithEpoch) => {\n\t\t\treturn this.cache.persistedCache.put(\n\t\t\t\tcreateCacheSnapshotKey(this.odspResolvedUrl),\n\t\t\t\t// Epoch tracker will add the epoch and version to the value here. So just send value to cache.\n\t\t\t\tvalueWithEpoch.value,\n\t\t\t);\n\t\t};\n\t\tconst removeEntries = async () => this.cache.persistedCache.removeEntries();\n\t\ttry {\n\t\t\tconst odspSnapshot = await fetchSnapshotWithRedeem(\n\t\t\t\tthis.odspResolvedUrl,\n\t\t\t\tthis.getStorageToken,\n\t\t\t\tsnapshotOptions,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\tthis.logger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t\tputInCache,\n\t\t\t\tremoveEntries,\n\t\t\t\tthis.hostPolicy.enableRedeemFallback,\n\t\t\t);\n\t\t\treturn odspSnapshot;\n\t\t} catch (error: any) {\n\t\t\tconst errorType = error.errorType;\n\t\t\t// If the snapshot size is too big and the host specified the size limitation(specified in hostSnapshotOptions), then don't try to fetch the snapshot again.\n\t\t\tif (\n\t\t\t\terrorType === OdspErrorType.snapshotTooBig &&\n\t\t\t\thostSnapshotOptions?.mds !== undefined &&\n\t\t\t\tthis.hostPolicy.summarizerClient !== true\n\t\t\t) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\t// If the first snapshot request was with blobs and we either timed out or the size was too big, then try to fetch without blobs.\n\t\t\tif (\n\t\t\t\t(errorType === OdspErrorType.snapshotTooBig ||\n\t\t\t\t\terrorType === OdspErrorType.fetchTimeout) &&\n\t\t\t\tsnapshotOptions.blobs\n\t\t\t) {\n\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\teventName: \"TreeLatest_SecondCall\",\n\t\t\t\t\terrorType,\n\t\t\t\t});\n\t\t\t\tconst snapshotOptionsWithoutBlobs: ISnapshotOptions = {\n\t\t\t\t\t...snapshotOptions,\n\t\t\t\t\tblobs: 0,\n\t\t\t\t\tmds: undefined,\n\t\t\t\t\ttimeout: undefined,\n\t\t\t\t};\n\t\t\t\tconst odspSnapshot = await fetchSnapshotWithRedeem(\n\t\t\t\t\tthis.odspResolvedUrl,\n\t\t\t\t\tthis.getStorageToken,\n\t\t\t\t\tsnapshotOptionsWithoutBlobs,\n\t\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tsnapshotDownloader,\n\t\t\t\t\tputInCache,\n\t\t\t\t\tremoveEntries,\n\t\t\t\t\tthis.hostPolicy.enableRedeemFallback,\n\t\t\t\t);\n\t\t\t\treturn odspSnapshot;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic async uploadSummaryWithContext(\n\t\tsummary: api.ISummaryTree,\n\t\tcontext: ISummaryContext,\n\t): Promise<string> {\n\t\tthis.checkSnapshotUrl();\n\n\t\t// Set the module promise right away, so as to not call it twice.\n\t\tif (this.summaryModuleP === undefined) {\n\t\t\tthis.summaryModuleP = this.getDelayLoadedSummaryManager();\n\t\t}\n\n\t\t// Enable flushing only if we have single commit summary and this is not the initial summary for an empty file\n\t\tif (\".protocol\" in summary.tree && context.ackHandle !== undefined) {\n\t\t\tlet retry = 1;\n\t\t\tfor (;;) {\n\t\t\t\tconst result = await this.flushCallback();\n\t\t\t\tconst seq = result.lastPersistedSequenceNumber;\n\t\t\t\tif (seq !== undefined && seq >= context.referenceSequenceNumber) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (retry > 3) {\n\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\teventName: \"FlushFailure\",\n\t\t\t\t\t\t...result,\n\t\t\t\t\t\tretry,\n\t\t\t\t\t\treferenceSequenceNumber: context.referenceSequenceNumber,\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\teventName: \"FlushExtraCall\",\n\t\t\t\t\t...result,\n\t\t\t\t\tretry,\n\t\t\t\t\treferenceSequenceNumber: context.referenceSequenceNumber,\n\t\t\t\t});\n\n\t\t\t\tretry++;\n\t\t\t\tawait delay(1000 * (result.retryAfter ?? 1));\n\t\t\t}\n\t\t}\n\n\t\tif (!this.odspSummaryUploadManager) {\n\t\t\tthis.odspSummaryUploadManager = await this.summaryModuleP\n\t\t\t\t.then(async (m) => {\n\t\t\t\t\tthis.odspSummaryModuleLoaded = true;\n\t\t\t\t\treturn m;\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tthis.odspSummaryModuleLoaded = false;\n\t\t\t\t\tthrow error;\n\t\t\t\t});\n\t\t}\n\n\t\tassert(\n\t\t\tthis.odspSummaryUploadManager !== undefined,\n\t\t\t0x56e /* summary upload manager should have been initialized */,\n\t\t);\n\t\tconst id = await this.odspSummaryUploadManager.writeSummaryTree(summary, context);\n\t\treturn id;\n\t}\n\n\tprivate async getDelayLoadedSummaryManager() {\n\t\tassert(this.odspSummaryModuleLoaded === false, 0x56f /* Should be loaded only once */);\n\t\tconst module = await import(\n\t\t\t/* webpackChunkName: \"summaryModule\" */ \"./odspSummaryUploadManager\"\n\t\t)\n\t\t\t.then((m) => {\n\t\t\t\tthis.logger.sendTelemetryEvent({ eventName: \"SummaryModuleLoaded\" });\n\t\t\t\treturn m;\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.logger.sendErrorEvent({ eventName: \"SummaryModuleLoadFailed\" }, error);\n\t\t\t\tthrow error;\n\t\t\t});\n\t\tthis.odspSummaryUploadManager = new module.OdspSummaryUploadManager(\n\t\t\tthis.odspResolvedUrl.endpoints.snapshotStorageUrl,\n\t\t\tthis.getStorageToken,\n\t\t\tthis.logger,\n\t\t\tthis.epochTracker,\n\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\tthis.relayServiceTenantAndSessionId,\n\t\t);\n\t\treturn this.odspSummaryUploadManager;\n\t}\n\n\tprivate checkSnapshotUrl() {\n\t\tif (!this.snapshotUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no snapshot url was available\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate checkAttachmentPOSTUrl() {\n\t\tif (!this.attachmentPOSTUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no attachment POST url was available\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate checkAttachmentGETUrl() {\n\t\tif (!this.attachmentGETUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no attachment GET url was available\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprotected async fetchTreeFromSnapshot(\n\t\tid: string,\n\t\tscenarioName?: string,\n\t): Promise<api.ISnapshotTree | undefined> {\n\t\treturn getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"ReadCommit\");\n\t\t\tconst snapshotDownloader = async (\n\t\t\t\turl: string,\n\t\t\t\tfetchOptions: { [index: string]: any },\n\t\t\t) => {\n\t\t\t\treturn this.epochTracker.fetchAndParseAsJSON(\n\t\t\t\t\turl,\n\t\t\t\t\tfetchOptions,\n\t\t\t\t\t\"snapshotTree\",\n\t\t\t\t\tundefined,\n\t\t\t\t\tscenarioName,\n\t\t\t\t);\n\t\t\t};\n\t\t\tconst snapshot = await fetchSnapshot(\n\t\t\t\tthis.snapshotUrl!,\n\t\t\t\tstorageToken,\n\t\t\t\tid,\n\t\t\t\tthis.fetchFullSnapshot,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\tthis.logger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t);\n\t\t\tlet treeId = \"\";\n\t\t\tif (snapshot.snapshotTree) {\n\t\t\t\tassert(\n\t\t\t\t\tsnapshot.snapshotTree.id !== undefined,\n\t\t\t\t\t0x222 /* \"Root tree should contain the id!!\" */,\n\t\t\t\t);\n\t\t\t\ttreeId = snapshot.snapshotTree.id;\n\t\t\t\tthis.setRootTree(treeId, snapshot.snapshotTree);\n\t\t\t}\n\t\t\tif (snapshot.blobs) {\n\t\t\t\tthis.initBlobsCache(snapshot.blobs);\n\t\t\t}\n\t\t\t// If the version id doesn't match with the id of the tree, then use the id of first tree which in that case\n\t\t\t// will be the actual id of tree to be fetched.\n\t\t\treturn this.commitCache.get(id) ?? this.commitCache.get(treeId);\n\t\t});\n\t}\n}\n"]}
|
package/dist/odspUtils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspUtils.d.ts","sourceRoot":"","sources":["../src/odspUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAChB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAmB,MAAM,oCAAoC,CAAC;AAoBnF,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EAIjB,6BAA6B,EAC7B,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,WAAW,EAEX,+BAA+B,EAC/B,aAAa,EACb,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAGjF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,eAAO,MAAM,iCAAiC,sCAAsC,CAAC;AAErF,4DAA4D;AAC5D,eAAO,MAAM,SAAS,QAAS,MAAM,WAAwB,CAAC;AAE9D,MAAM,WAAW,aAAa,CAAC,CAAC;IAC/B,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,UAAU,EAAE,oBAAoB,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAoB,SAAQ,iBAAiB;IAC7D,2DAA2D;IAC3D,aAAa,CAAC,EAAE,GAAG,CAAC;CACpB;AAUD;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAAC,CAAC,EAClD,GAAG,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,CAAC,CAAC,cAqBjD;AAED,wBAAsB,WAAW,CAChC,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,GAAG,SAAS,GAClC,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"odspUtils.d.ts","sourceRoot":"","sources":["../src/odspUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAChB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAmB,MAAM,oCAAoC,CAAC;AAoBnF,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EAIjB,6BAA6B,EAC7B,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,WAAW,EAEX,+BAA+B,EAC/B,aAAa,EACb,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAGjF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,eAAO,MAAM,iCAAiC,sCAAsC,CAAC;AAErF,4DAA4D;AAC5D,eAAO,MAAM,SAAS,QAAS,MAAM,WAAwB,CAAC;AAE9D,MAAM,WAAW,aAAa,CAAC,CAAC;IAC/B,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,UAAU,EAAE,oBAAoB,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAoB,SAAQ,iBAAiB;IAC7D,2DAA2D;IAC3D,aAAa,CAAC,EAAE,GAAG,CAAC;CACpB;AAUD;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAAC,CAAC,EAClD,GAAG,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,CAAC,CAAC,cAqBjD;AAED,wBAAsB,WAAW,CAChC,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,GAAG,SAAS,GAClC,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAqFlC;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAC/B,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,GAAG,SAAS,GAClC,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAWrC;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAAC,CAAC,EAChD,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,GAAG,SAAS,GAClC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CA4B3B;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,KAAK,GAAG,UAAU,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAa,SAAQ,aAAa;IAClD,IAAI,EAAE,KAAK,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,cAAc,GAAG,gBAAgB,CAAC;CACnD;AAED,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACvD,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,aAAa,CAC5B,QAAQ,EAAE,YAAY,GAAG,iBAAiB,GACxC,QAAQ,IAAI,YAAY,CAE1B;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,YAAY,GAAG,gBAAgB,CAM9E;AAED,eAAO,MAAM,gBAAgB,0GAK1B,CAAC;AAEJ,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,aAAa;;;;;EAqBxD;AAED,wBAAgB,8BAA8B,CAC7C,MAAM,EAAE,gBAAgB,EACxB,gBAAgB,EAAE,aAAa,EAC/B,YAAY,EAAE,YAAY,CAAC,6BAA6B,CAAC,EACzD,gBAAgB,EAAE,OAAO,GACvB,+BAA+B,CAoEjC;AAED,wBAAgB,sBAAsB,CAAC,eAAe,EAAE,gBAAgB,GAAG,WAAW,CAUrF;AAID,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAExC;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAC1C,aAAa,EAAE,cAAc,GAAG,gBAAgB,GAAG,SAAS,sBAe5D;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAKzD;AAED,wBAAsB,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAKlF;AAED,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,yBAAyB,EAAE,EACrC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,gBAAgB,QA8BxB"}
|
package/dist/odspUtils.js
CHANGED
|
@@ -75,9 +75,14 @@ async function fetchHelper(requestInfo, requestInit) {
|
|
|
75
75
|
};
|
|
76
76
|
}, (error) => {
|
|
77
77
|
const online = (0, driver_utils_1.isOnline)();
|
|
78
|
-
|
|
78
|
+
// The error message may not be suitable to log for privacy reasons, so tag it as such
|
|
79
|
+
const taggedErrorMessage = {
|
|
80
|
+
value: `${error}`,
|
|
81
|
+
tag: telemetry_utils_1.TelemetryDataTag.UserData,
|
|
82
|
+
};
|
|
83
|
+
// After redacting URLs we believe the error message is safe to log
|
|
79
84
|
const urlRegex = /((http|https):\/\/(\S*))/i;
|
|
80
|
-
const redactedErrorText =
|
|
85
|
+
const redactedErrorText = taggedErrorMessage.value.replace(urlRegex, "REDACTED_URL");
|
|
81
86
|
// This error is thrown by fetch() when AbortSignal is provided and it gets cancelled
|
|
82
87
|
if (error.name === "AbortError") {
|
|
83
88
|
throw new driver_utils_1.RetryableError("Fetch Timeout (AbortError)", odsp_driver_definitions_1.OdspErrorType.fetchTimeout, {
|
|
@@ -85,21 +90,18 @@ async function fetchHelper(requestInfo, requestInit) {
|
|
|
85
90
|
});
|
|
86
91
|
}
|
|
87
92
|
// TCP/IP timeout
|
|
88
|
-
if (
|
|
93
|
+
if (redactedErrorText.includes("ETIMEDOUT")) {
|
|
89
94
|
throw new driver_utils_1.RetryableError("Fetch Timeout (ETIMEDOUT)", odsp_driver_definitions_1.OdspErrorType.fetchTimeout, {
|
|
90
95
|
driverVersion: packageVersion_1.pkgVersion,
|
|
91
96
|
});
|
|
92
97
|
}
|
|
93
|
-
// WARNING: Do not log error object itself or any of its properties!
|
|
94
|
-
// It could contain PII, like URI in message itself, or token in properties.
|
|
95
|
-
// It is also non-serializable object due to circular references.
|
|
96
98
|
// eslint-disable-next-line unicorn/prefer-ternary
|
|
97
99
|
if (online === driver_utils_1.OnlineStatus.Offline) {
|
|
98
100
|
throw new driver_utils_1.RetryableError(
|
|
99
101
|
// pre-0.58 error message prefix: Offline
|
|
100
102
|
`ODSP fetch failure (Offline): ${redactedErrorText}`, driver_definitions_1.DriverErrorType.offlineError, {
|
|
101
103
|
driverVersion: packageVersion_1.pkgVersion,
|
|
102
|
-
rawErrorMessage:
|
|
104
|
+
rawErrorMessage: taggedErrorMessage,
|
|
103
105
|
});
|
|
104
106
|
}
|
|
105
107
|
else {
|
|
@@ -109,7 +111,7 @@ async function fetchHelper(requestInfo, requestInit) {
|
|
|
109
111
|
// pre-0.58 error message prefix: Fetch error
|
|
110
112
|
`ODSP fetch failure: ${redactedErrorText}`, driver_definitions_1.DriverErrorType.fetchFailure, {
|
|
111
113
|
driverVersion: packageVersion_1.pkgVersion,
|
|
112
|
-
rawErrorMessage:
|
|
114
|
+
rawErrorMessage: taggedErrorMessage,
|
|
113
115
|
});
|
|
114
116
|
}
|
|
115
117
|
});
|
package/dist/odspUtils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspUtils.js","sourceRoot":"","sources":["../src/odspUtils.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 {\n\tITelemetryProperties,\n\tITelemetryBaseLogger,\n\tITelemetryLogger,\n} from \"@fluidframework/common-definitions\";\nimport { IResolvedUrl, DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport {\n\tisOnline,\n\tOnlineStatus,\n\tRetryableError,\n\tNonRetryableError,\n\tNetworkErrorBasic,\n} from \"@fluidframework/driver-utils\";\nimport { assert, performance } from \"@fluidframework/common-utils\";\nimport {\n\tChildLogger,\n\tPerformanceEvent,\n\tTelemetryDataTag,\n\twrapError,\n} from \"@fluidframework/telemetry-utils\";\nimport {\n\tfetchIncorrectResponse,\n\tthrowOdspNetworkError,\n\tgetSPOAndGraphRequestIdsFromResponse,\n} from \"@fluidframework/odsp-doclib-utils\";\nimport {\n\tIOdspResolvedUrl,\n\tTokenFetchOptions,\n\tOdspErrorType,\n\ttokenFromResponse,\n\tisTokenFromCache,\n\tOdspResourceTokenFetchOptions,\n\tShareLinkTypes,\n\tISharingLinkKind,\n\tTokenFetcher,\n\tICacheEntry,\n\tsnapshotKey,\n\tInstrumentedStorageTokenFetcher,\n\tIOdspUrlParts,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { fetch } from \"./fetch\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\nimport { IOdspSnapshot } from \"./contracts\";\n\nexport const getWithRetryForTokenRefreshRepeat = \"getWithRetryForTokenRefreshRepeat\";\n\n/** Parse the given url and return the origin (host name) */\nexport const getOrigin = (url: string) => new URL(url).origin;\n\nexport interface IOdspResponse<T> {\n\tcontent: T;\n\theaders: Map<string, string>;\n\tpropsToLog: ITelemetryProperties;\n\tduration: number;\n}\n\nexport interface TokenFetchOptionsEx extends TokenFetchOptions {\n\t/** previous error we hit in getWithRetryForTokenRefresh */\n\tpreviousError?: any;\n}\n\nfunction headersToMap(headers: Headers) {\n\tconst newHeaders = new Map<string, string>();\n\tfor (const [key, value] of headers.entries()) {\n\t\tnewHeaders.set(key, value);\n\t}\n\treturn newHeaders;\n}\n\n/**\n * This API should be used with pretty much all network calls (fetch, webSocket connection) in order\n * to correctly handle expired tokens. It relies on callback fetching token, and be able to refetch\n * token on failure. Only specific cases get retry call with refresh = true, all other / unknown errors\n * simply propagate to caller\n */\nexport async function getWithRetryForTokenRefresh<T>(\n\tget: (options: TokenFetchOptionsEx) => Promise<T>,\n) {\n\treturn get({ refresh: false }).catch(async (e) => {\n\t\tconst options: TokenFetchOptionsEx = { refresh: true, previousError: e };\n\t\tswitch (e.errorType) {\n\t\t\t// If the error is 401 or 403 refresh the token and try once more.\n\t\t\tcase DriverErrorType.authorizationError:\n\t\t\t\treturn get({ ...options, claims: e.claims, tenantId: e.tenantId });\n\n\t\t\tcase DriverErrorType.incorrectServerResponse: // some error on the wire, retry once\n\t\t\tcase OdspErrorType.fetchTokenError: // If the token was null, then retry once.\n\t\t\t\treturn get(options);\n\n\t\t\tdefault:\n\t\t\t\t// Caller may determine that it wants one retry\n\t\t\t\tif (e[getWithRetryForTokenRefreshRepeat] === true) {\n\t\t\t\t\treturn get(options);\n\t\t\t\t}\n\t\t\t\tthrow e;\n\t\t}\n\t});\n}\n\nexport async function fetchHelper(\n\trequestInfo: RequestInfo,\n\trequestInit: RequestInit | undefined,\n): Promise<IOdspResponse<Response>> {\n\tconst start = performance.now();\n\n\t// Node-fetch and dom have conflicting typing, force them to work by casting for now\n\treturn fetch(requestInfo, requestInit).then(\n\t\tasync (fetchResponse) => {\n\t\t\tconst response = fetchResponse as any as Response;\n\t\t\t// Let's assume we can retry.\n\t\t\tif (!response) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t// pre-0.58 error message: No response from fetch call\n\t\t\t\t\t\"No response from ODSP fetch call\",\n\t\t\t\t\tDriverErrorType.incorrectServerResponse,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!response.ok || response.status < 200 || response.status >= 300) {\n\t\t\t\tthrowOdspNetworkError(\n\t\t\t\t\t// pre-0.58 error message prefix: odspFetchError\n\t\t\t\t\t`ODSP fetch error [${response.status}]`,\n\t\t\t\t\tresponse.status,\n\t\t\t\t\tresponse,\n\t\t\t\t\tawait response.text(),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst headers = headersToMap(response.headers);\n\t\t\treturn {\n\t\t\t\tcontent: response,\n\t\t\t\theaders,\n\t\t\t\tpropsToLog: getSPOAndGraphRequestIdsFromResponse(headers),\n\t\t\t\tduration: performance.now() - start,\n\t\t\t};\n\t\t},\n\t\t(error) => {\n\t\t\tconst online = isOnline();\n\t\t\tconst errorText = `${error}`;\n\t\t\tconst urlRegex = /((http|https):\\/\\/(\\S*))/i;\n\t\t\tconst redactedErrorText = errorText.replace(urlRegex, \"REDACTED_URL\");\n\t\t\t// This error is thrown by fetch() when AbortSignal is provided and it gets cancelled\n\t\t\tif (error.name === \"AbortError\") {\n\t\t\t\tthrow new RetryableError(\"Fetch Timeout (AbortError)\", OdspErrorType.fetchTimeout, {\n\t\t\t\t\tdriverVersion,\n\t\t\t\t});\n\t\t\t}\n\t\t\t// TCP/IP timeout\n\t\t\tif (errorText.includes(\"ETIMEDOUT\")) {\n\t\t\t\tthrow new RetryableError(\"Fetch Timeout (ETIMEDOUT)\", OdspErrorType.fetchTimeout, {\n\t\t\t\t\tdriverVersion,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// WARNING: Do not log error object itself or any of its properties!\n\t\t\t// It could contain PII, like URI in message itself, or token in properties.\n\t\t\t// It is also non-serializable object due to circular references.\n\t\t\t// eslint-disable-next-line unicorn/prefer-ternary\n\t\t\tif (online === OnlineStatus.Offline) {\n\t\t\t\tthrow new RetryableError(\n\t\t\t\t\t// pre-0.58 error message prefix: Offline\n\t\t\t\t\t`ODSP fetch failure (Offline): ${redactedErrorText}`,\n\t\t\t\t\tDriverErrorType.offlineError,\n\t\t\t\t\t{\n\t\t\t\t\t\tdriverVersion,\n\t\t\t\t\t\trawErrorMessage: { value: errorText, tag: TelemetryDataTag.UserData },\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// It is perhaps still possible that this is due to being offline, the error does not reveal enough\n\t\t\t\t// information to conclude. Could also be DNS errors, malformed fetch request, CSP violation, etc.\n\t\t\t\tthrow new RetryableError(\n\t\t\t\t\t// pre-0.58 error message prefix: Fetch error\n\t\t\t\t\t`ODSP fetch failure: ${redactedErrorText}`,\n\t\t\t\t\tDriverErrorType.fetchFailure,\n\t\t\t\t\t{\n\t\t\t\t\t\tdriverVersion,\n\t\t\t\t\t\trawErrorMessage: { value: errorText, tag: TelemetryDataTag.UserData },\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t);\n}\n\n/**\n * A utility function to fetch and parse as JSON with support for retries\n * @param requestInfo - fetch requestInfo, can be a string\n * @param requestInit - fetch requestInit\n */\nexport async function fetchArray(\n\trequestInfo: RequestInfo,\n\trequestInit: RequestInit | undefined,\n): Promise<IOdspResponse<ArrayBuffer>> {\n\tconst { content, headers, propsToLog, duration } = await fetchHelper(requestInfo, requestInit);\n\n\tconst arrayBuffer = await content.arrayBuffer();\n\tpropsToLog.bodySize = arrayBuffer.byteLength;\n\treturn {\n\t\theaders,\n\t\tcontent: arrayBuffer,\n\t\tpropsToLog,\n\t\tduration,\n\t};\n}\n\n/**\n * A utility function to fetch and parse as JSON with support for retries\n * @param requestInfo - fetch requestInfo, can be a string\n * @param requestInit - fetch requestInit\n */\nexport async function fetchAndParseAsJSONHelper<T>(\n\trequestInfo: RequestInfo,\n\trequestInit: RequestInit | undefined,\n): Promise<IOdspResponse<T>> {\n\tconst { content, headers, propsToLog, duration } = await fetchHelper(requestInfo, requestInit);\n\tlet text: string | undefined;\n\ttry {\n\t\ttext = await content.text();\n\t} catch (e) {\n\t\t// JSON.parse() can fail and message would container full request URI, including\n\t\t// tokens... It fails for me with \"Unexpected end of JSON input\" quite often - an attempt to download big file\n\t\t// (many ops) almost always ends up with this error - I'd guess 1% of op request end up here... It always\n\t\t// succeeds on retry.\n\t\t// So do not log error object itself.\n\t\tthrowOdspNetworkError(\n\t\t\t// pre-0.58 error message: errorWhileParsingFetchResponse\n\t\t\t\"Error while parsing fetch response\",\n\t\t\tfetchIncorrectResponse,\n\t\t\tcontent, // response\n\t\t\ttext,\n\t\t);\n\t}\n\n\tpropsToLog.bodySize = text.length;\n\tconst res = {\n\t\theaders,\n\t\tcontent: JSON.parse(text),\n\t\tpropsToLog,\n\t\tduration,\n\t};\n\treturn res;\n}\n\nexport interface IFileInfoBase {\n\ttype: \"New\" | \"Existing\";\n\tsiteUrl: string;\n\tdriveId: string;\n}\n\nexport interface INewFileInfo extends IFileInfoBase {\n\ttype: \"New\";\n\tfilename: string;\n\tfilePath: string;\n\t/**\n\t * application can request creation of a share link along with the creation of a new file\n\t * by passing in an optional param to specify the kind of sharing link\n\t * (at the time of adding this comment Sept/2021), odsp only supports csl\n\t * ShareLinkTypes will deprecated in future. Use ISharingLinkKind instead which specifies both\n\t * share link type and the role type.\n\t */\n\tcreateLinkType?: ShareLinkTypes | ISharingLinkKind;\n}\n\nexport interface IExistingFileInfo extends IFileInfoBase {\n\ttype: \"Existing\";\n\titemId: string;\n}\n\nexport function isNewFileInfo(\n\tfileInfo: INewFileInfo | IExistingFileInfo,\n): fileInfo is INewFileInfo {\n\treturn fileInfo.type === undefined || fileInfo.type === \"New\";\n}\n\nexport function getOdspResolvedUrl(resolvedUrl: IResolvedUrl): IOdspResolvedUrl {\n\tassert(\n\t\t(resolvedUrl as IOdspResolvedUrl).odspResolvedUrl === true,\n\t\t0x1de /* \"Not an ODSP resolved url\" */,\n\t);\n\treturn resolvedUrl as IOdspResolvedUrl;\n}\n\nexport const createOdspLogger = (logger?: ITelemetryBaseLogger) =>\n\tChildLogger.create(logger, \"OdspDriver\", {\n\t\tall: {\n\t\t\tdriverVersion,\n\t\t},\n\t});\n\nexport function evalBlobsAndTrees(snapshot: IOdspSnapshot) {\n\tlet numTrees = 0;\n\tlet numBlobs = 0;\n\tlet encodedBlobsSize = 0;\n\tlet decodedBlobsSize = 0;\n\tfor (const tree of snapshot.trees) {\n\t\tfor (const treeEntry of tree.entries) {\n\t\t\tif (treeEntry.type === \"blob\") {\n\t\t\t\tnumBlobs++;\n\t\t\t} else if (treeEntry.type === \"tree\") {\n\t\t\t\tnumTrees++;\n\t\t\t}\n\t\t}\n\t}\n\tif (snapshot.blobs !== undefined) {\n\t\tfor (const blob of snapshot.blobs) {\n\t\t\tdecodedBlobsSize += blob.size;\n\t\t\tencodedBlobsSize += blob.content.length;\n\t\t}\n\t}\n\treturn { numTrees, numBlobs, encodedBlobsSize, decodedBlobsSize };\n}\n\nexport function toInstrumentedOdspTokenFetcher(\n\tlogger: ITelemetryLogger,\n\tresolvedUrlParts: IOdspUrlParts,\n\ttokenFetcher: TokenFetcher<OdspResourceTokenFetchOptions>,\n\tthrowOnNullToken: boolean,\n): InstrumentedStorageTokenFetcher {\n\treturn async (\n\t\toptions: TokenFetchOptions,\n\t\tname: string,\n\t\talwaysRecordTokenFetchTelemetry: boolean = false,\n\t) => {\n\t\t// Telemetry note: if options.refresh is true, there is a potential perf issue:\n\t\t// Host should optimize and provide non-expired tokens on all critical paths.\n\t\t// Exceptions: race conditions around expiration, revoked tokens, host that does not care\n\t\t// (fluid-fetcher)\n\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\tlogger,\n\t\t\t{\n\t\t\t\teventName: `${name}_GetToken`,\n\t\t\t\tattempts: options.refresh ? 2 : 1,\n\t\t\t\thasClaims: !!options.claims,\n\t\t\t\thasTenantId: !!options.tenantId,\n\t\t\t},\n\t\t\tasync (event) =>\n\t\t\t\ttokenFetcher({\n\t\t\t\t\t...options,\n\t\t\t\t\t...resolvedUrlParts,\n\t\t\t\t}).then(\n\t\t\t\t\t(tokenResponse) => {\n\t\t\t\t\t\tconst token = tokenFromResponse(tokenResponse);\n\t\t\t\t\t\t// This event alone generates so many events that is materially impacts cost of telemetry\n\t\t\t\t\t\t// Thus do not report end event when it comes back quickly.\n\t\t\t\t\t\t// Note that most of the hosts do not report if result is comming from cache or not,\n\t\t\t\t\t\t// so we can't rely on that here. But always record if specified explicitly for cases such as\n\t\t\t\t\t\t// calling trees/latest during load.\n\t\t\t\t\t\tif (alwaysRecordTokenFetchTelemetry || event.duration >= 32) {\n\t\t\t\t\t\t\tevent.end({\n\t\t\t\t\t\t\t\tfromCache: isTokenFromCache(tokenResponse),\n\t\t\t\t\t\t\t\tisNull: token === null,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (token === null && throwOnNullToken) {\n\t\t\t\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\t\t\t// pre-0.58 error message: Token is null for ${name} call\n\t\t\t\t\t\t\t\t`The Host-provided token fetcher returned null`,\n\t\t\t\t\t\t\t\tOdspErrorType.fetchTokenError,\n\t\t\t\t\t\t\t\t{ method: name, driverVersion },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn token;\n\t\t\t\t\t},\n\t\t\t\t\t(error) => {\n\t\t\t\t\t\t// There is an important but unofficial contract here where token providers can set canRetry: true\n\t\t\t\t\t\t// to hook into the driver's retry logic (e.g. the retry loop when initiating a connection)\n\t\t\t\t\t\tconst rawCanRetry = error?.canRetry;\n\t\t\t\t\t\tconst tokenError = wrapError(\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t\t(errorMessage) =>\n\t\t\t\t\t\t\t\tnew NetworkErrorBasic(\n\t\t\t\t\t\t\t\t\t`The Host-provided token fetcher threw an error`,\n\t\t\t\t\t\t\t\t\tOdspErrorType.fetchTokenError,\n\t\t\t\t\t\t\t\t\ttypeof rawCanRetry === \"boolean\"\n\t\t\t\t\t\t\t\t\t\t? rawCanRetry\n\t\t\t\t\t\t\t\t\t\t: false /* canRetry */,\n\t\t\t\t\t\t\t\t\t{ method: name, errorMessage, driverVersion },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthrow tokenError;\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t{ cancel: \"generic\" },\n\t\t);\n\t};\n}\n\nexport function createCacheSnapshotKey(odspResolvedUrl: IOdspResolvedUrl): ICacheEntry {\n\tconst cacheEntry: ICacheEntry = {\n\t\ttype: snapshotKey,\n\t\tkey: odspResolvedUrl.fileVersion ?? \"\",\n\t\tfile: {\n\t\t\tresolvedUrl: odspResolvedUrl,\n\t\t\tdocId: odspResolvedUrl.hashedDocumentId,\n\t\t},\n\t};\n\treturn cacheEntry;\n}\n\n// 80KB is the max body size that we can put in ump post body for server to be able to accept it.\n// Keeping it 78KB to be a little cautious. As per the telemetry 99p is less than 78KB.\nexport const maxUmpPostBodySize = 79872;\n\n/**\n * Build request parameters to request for the creation of a sharing link along with the creation of the file\n * through the /snapshot api call.\n * @param shareLinkType - Kind of sharing link requested\n * @returns A string of request parameters that can be concatenated with the base URI\n */\nexport function buildOdspShareLinkReqParams(\n\tshareLinkType: ShareLinkTypes | ISharingLinkKind | undefined,\n) {\n\tif (!shareLinkType) {\n\t\treturn;\n\t}\n\tconst scope = (shareLinkType as ISharingLinkKind).scope;\n\tif (!scope) {\n\t\treturn `createLinkType=${shareLinkType}`;\n\t}\n\tlet shareLinkRequestParams = `createLinkScope=${scope}`;\n\tconst role = (shareLinkType as ISharingLinkKind).role;\n\tshareLinkRequestParams = role\n\t\t? `${shareLinkRequestParams}&createLinkRole=${role}`\n\t\t: shareLinkRequestParams;\n\treturn shareLinkRequestParams;\n}\n\nexport function measure<T>(callback: () => T): [T, number] {\n\tconst start = performance.now();\n\tconst result = callback();\n\tconst time = performance.now() - start;\n\treturn [result, time];\n}\n\nexport async function measureP<T>(callback: () => Promise<T>): Promise<[T, number]> {\n\tconst start = performance.now();\n\tconst result = await callback();\n\tconst time = performance.now() - start;\n\treturn [result, time];\n}\n\nexport function validateMessages(\n\treason: string,\n\tmessages: ISequencedDocumentMessage[],\n\tfrom: number,\n\tlogger: ITelemetryLogger,\n) {\n\tif (messages.length !== 0) {\n\t\tconst start = messages[0].sequenceNumber;\n\t\tconst length = messages.length;\n\t\tconst last = messages[length - 1].sequenceNumber;\n\t\tif (start !== from) {\n\t\t\tlogger.sendErrorEvent({\n\t\t\t\teventName: \"OpsFetchViolation\",\n\t\t\t\treason,\n\t\t\t\tfrom,\n\t\t\t\tstart,\n\t\t\t\tlast,\n\t\t\t\tlength,\n\t\t\t});\n\t\t\tmessages.length = 0;\n\t\t}\n\t\tif (last + 1 !== from + length) {\n\t\t\tlogger.sendErrorEvent({\n\t\t\t\teventName: \"OpsFetchViolation\",\n\t\t\t\treason,\n\t\t\t\tfrom,\n\t\t\t\tstart,\n\t\t\t\tlast,\n\t\t\t\tlength,\n\t\t\t});\n\t\t\t// we can do better here by finding consecutive sub-block and return it\n\t\t\tmessages.length = 0;\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"odspUtils.js","sourceRoot":"","sources":["../src/odspUtils.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 {\n\tITelemetryProperties,\n\tITelemetryBaseLogger,\n\tITelemetryLogger,\n} from \"@fluidframework/common-definitions\";\nimport { IResolvedUrl, DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport {\n\tisOnline,\n\tOnlineStatus,\n\tRetryableError,\n\tNonRetryableError,\n\tNetworkErrorBasic,\n} from \"@fluidframework/driver-utils\";\nimport { assert, performance } from \"@fluidframework/common-utils\";\nimport {\n\tChildLogger,\n\tPerformanceEvent,\n\tTelemetryDataTag,\n\twrapError,\n} from \"@fluidframework/telemetry-utils\";\nimport {\n\tfetchIncorrectResponse,\n\tthrowOdspNetworkError,\n\tgetSPOAndGraphRequestIdsFromResponse,\n} from \"@fluidframework/odsp-doclib-utils\";\nimport {\n\tIOdspResolvedUrl,\n\tTokenFetchOptions,\n\tOdspErrorType,\n\ttokenFromResponse,\n\tisTokenFromCache,\n\tOdspResourceTokenFetchOptions,\n\tShareLinkTypes,\n\tISharingLinkKind,\n\tTokenFetcher,\n\tICacheEntry,\n\tsnapshotKey,\n\tInstrumentedStorageTokenFetcher,\n\tIOdspUrlParts,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { fetch } from \"./fetch\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\nimport { IOdspSnapshot } from \"./contracts\";\n\nexport const getWithRetryForTokenRefreshRepeat = \"getWithRetryForTokenRefreshRepeat\";\n\n/** Parse the given url and return the origin (host name) */\nexport const getOrigin = (url: string) => new URL(url).origin;\n\nexport interface IOdspResponse<T> {\n\tcontent: T;\n\theaders: Map<string, string>;\n\tpropsToLog: ITelemetryProperties;\n\tduration: number;\n}\n\nexport interface TokenFetchOptionsEx extends TokenFetchOptions {\n\t/** previous error we hit in getWithRetryForTokenRefresh */\n\tpreviousError?: any;\n}\n\nfunction headersToMap(headers: Headers) {\n\tconst newHeaders = new Map<string, string>();\n\tfor (const [key, value] of headers.entries()) {\n\t\tnewHeaders.set(key, value);\n\t}\n\treturn newHeaders;\n}\n\n/**\n * This API should be used with pretty much all network calls (fetch, webSocket connection) in order\n * to correctly handle expired tokens. It relies on callback fetching token, and be able to refetch\n * token on failure. Only specific cases get retry call with refresh = true, all other / unknown errors\n * simply propagate to caller\n */\nexport async function getWithRetryForTokenRefresh<T>(\n\tget: (options: TokenFetchOptionsEx) => Promise<T>,\n) {\n\treturn get({ refresh: false }).catch(async (e) => {\n\t\tconst options: TokenFetchOptionsEx = { refresh: true, previousError: e };\n\t\tswitch (e.errorType) {\n\t\t\t// If the error is 401 or 403 refresh the token and try once more.\n\t\t\tcase DriverErrorType.authorizationError:\n\t\t\t\treturn get({ ...options, claims: e.claims, tenantId: e.tenantId });\n\n\t\t\tcase DriverErrorType.incorrectServerResponse: // some error on the wire, retry once\n\t\t\tcase OdspErrorType.fetchTokenError: // If the token was null, then retry once.\n\t\t\t\treturn get(options);\n\n\t\t\tdefault:\n\t\t\t\t// Caller may determine that it wants one retry\n\t\t\t\tif (e[getWithRetryForTokenRefreshRepeat] === true) {\n\t\t\t\t\treturn get(options);\n\t\t\t\t}\n\t\t\t\tthrow e;\n\t\t}\n\t});\n}\n\nexport async function fetchHelper(\n\trequestInfo: RequestInfo,\n\trequestInit: RequestInit | undefined,\n): Promise<IOdspResponse<Response>> {\n\tconst start = performance.now();\n\n\t// Node-fetch and dom have conflicting typing, force them to work by casting for now\n\treturn fetch(requestInfo, requestInit).then(\n\t\tasync (fetchResponse) => {\n\t\t\tconst response = fetchResponse as any as Response;\n\t\t\t// Let's assume we can retry.\n\t\t\tif (!response) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t// pre-0.58 error message: No response from fetch call\n\t\t\t\t\t\"No response from ODSP fetch call\",\n\t\t\t\t\tDriverErrorType.incorrectServerResponse,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!response.ok || response.status < 200 || response.status >= 300) {\n\t\t\t\tthrowOdspNetworkError(\n\t\t\t\t\t// pre-0.58 error message prefix: odspFetchError\n\t\t\t\t\t`ODSP fetch error [${response.status}]`,\n\t\t\t\t\tresponse.status,\n\t\t\t\t\tresponse,\n\t\t\t\t\tawait response.text(),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst headers = headersToMap(response.headers);\n\t\t\treturn {\n\t\t\t\tcontent: response,\n\t\t\t\theaders,\n\t\t\t\tpropsToLog: getSPOAndGraphRequestIdsFromResponse(headers),\n\t\t\t\tduration: performance.now() - start,\n\t\t\t};\n\t\t},\n\t\t(error) => {\n\t\t\tconst online = isOnline();\n\n\t\t\t// The error message may not be suitable to log for privacy reasons, so tag it as such\n\t\t\tconst taggedErrorMessage = {\n\t\t\t\tvalue: `${error}`, // This uses toString for objects, which often results in `${error.name}: ${error.message}`\n\t\t\t\ttag: TelemetryDataTag.UserData,\n\t\t\t};\n\t\t\t// After redacting URLs we believe the error message is safe to log\n\t\t\tconst urlRegex = /((http|https):\\/\\/(\\S*))/i;\n\t\t\tconst redactedErrorText = taggedErrorMessage.value.replace(urlRegex, \"REDACTED_URL\");\n\n\t\t\t// This error is thrown by fetch() when AbortSignal is provided and it gets cancelled\n\t\t\tif (error.name === \"AbortError\") {\n\t\t\t\tthrow new RetryableError(\"Fetch Timeout (AbortError)\", OdspErrorType.fetchTimeout, {\n\t\t\t\t\tdriverVersion,\n\t\t\t\t});\n\t\t\t}\n\t\t\t// TCP/IP timeout\n\t\t\tif (redactedErrorText.includes(\"ETIMEDOUT\")) {\n\t\t\t\tthrow new RetryableError(\"Fetch Timeout (ETIMEDOUT)\", OdspErrorType.fetchTimeout, {\n\t\t\t\t\tdriverVersion,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// eslint-disable-next-line unicorn/prefer-ternary\n\t\t\tif (online === OnlineStatus.Offline) {\n\t\t\t\tthrow new RetryableError(\n\t\t\t\t\t// pre-0.58 error message prefix: Offline\n\t\t\t\t\t`ODSP fetch failure (Offline): ${redactedErrorText}`,\n\t\t\t\t\tDriverErrorType.offlineError,\n\t\t\t\t\t{\n\t\t\t\t\t\tdriverVersion,\n\t\t\t\t\t\trawErrorMessage: taggedErrorMessage,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// It is perhaps still possible that this is due to being offline, the error does not reveal enough\n\t\t\t\t// information to conclude. Could also be DNS errors, malformed fetch request, CSP violation, etc.\n\t\t\t\tthrow new RetryableError(\n\t\t\t\t\t// pre-0.58 error message prefix: Fetch error\n\t\t\t\t\t`ODSP fetch failure: ${redactedErrorText}`,\n\t\t\t\t\tDriverErrorType.fetchFailure,\n\t\t\t\t\t{\n\t\t\t\t\t\tdriverVersion,\n\t\t\t\t\t\trawErrorMessage: taggedErrorMessage,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t);\n}\n\n/**\n * A utility function to fetch and parse as JSON with support for retries\n * @param requestInfo - fetch requestInfo, can be a string\n * @param requestInit - fetch requestInit\n */\nexport async function fetchArray(\n\trequestInfo: RequestInfo,\n\trequestInit: RequestInit | undefined,\n): Promise<IOdspResponse<ArrayBuffer>> {\n\tconst { content, headers, propsToLog, duration } = await fetchHelper(requestInfo, requestInit);\n\n\tconst arrayBuffer = await content.arrayBuffer();\n\tpropsToLog.bodySize = arrayBuffer.byteLength;\n\treturn {\n\t\theaders,\n\t\tcontent: arrayBuffer,\n\t\tpropsToLog,\n\t\tduration,\n\t};\n}\n\n/**\n * A utility function to fetch and parse as JSON with support for retries\n * @param requestInfo - fetch requestInfo, can be a string\n * @param requestInit - fetch requestInit\n */\nexport async function fetchAndParseAsJSONHelper<T>(\n\trequestInfo: RequestInfo,\n\trequestInit: RequestInit | undefined,\n): Promise<IOdspResponse<T>> {\n\tconst { content, headers, propsToLog, duration } = await fetchHelper(requestInfo, requestInit);\n\tlet text: string | undefined;\n\ttry {\n\t\ttext = await content.text();\n\t} catch (e) {\n\t\t// JSON.parse() can fail and message would container full request URI, including\n\t\t// tokens... It fails for me with \"Unexpected end of JSON input\" quite often - an attempt to download big file\n\t\t// (many ops) almost always ends up with this error - I'd guess 1% of op request end up here... It always\n\t\t// succeeds on retry.\n\t\t// So do not log error object itself.\n\t\tthrowOdspNetworkError(\n\t\t\t// pre-0.58 error message: errorWhileParsingFetchResponse\n\t\t\t\"Error while parsing fetch response\",\n\t\t\tfetchIncorrectResponse,\n\t\t\tcontent, // response\n\t\t\ttext,\n\t\t);\n\t}\n\n\tpropsToLog.bodySize = text.length;\n\tconst res = {\n\t\theaders,\n\t\tcontent: JSON.parse(text),\n\t\tpropsToLog,\n\t\tduration,\n\t};\n\treturn res;\n}\n\nexport interface IFileInfoBase {\n\ttype: \"New\" | \"Existing\";\n\tsiteUrl: string;\n\tdriveId: string;\n}\n\nexport interface INewFileInfo extends IFileInfoBase {\n\ttype: \"New\";\n\tfilename: string;\n\tfilePath: string;\n\t/**\n\t * application can request creation of a share link along with the creation of a new file\n\t * by passing in an optional param to specify the kind of sharing link\n\t * (at the time of adding this comment Sept/2021), odsp only supports csl\n\t * ShareLinkTypes will deprecated in future. Use ISharingLinkKind instead which specifies both\n\t * share link type and the role type.\n\t */\n\tcreateLinkType?: ShareLinkTypes | ISharingLinkKind;\n}\n\nexport interface IExistingFileInfo extends IFileInfoBase {\n\ttype: \"Existing\";\n\titemId: string;\n}\n\nexport function isNewFileInfo(\n\tfileInfo: INewFileInfo | IExistingFileInfo,\n): fileInfo is INewFileInfo {\n\treturn fileInfo.type === undefined || fileInfo.type === \"New\";\n}\n\nexport function getOdspResolvedUrl(resolvedUrl: IResolvedUrl): IOdspResolvedUrl {\n\tassert(\n\t\t(resolvedUrl as IOdspResolvedUrl).odspResolvedUrl === true,\n\t\t0x1de /* \"Not an ODSP resolved url\" */,\n\t);\n\treturn resolvedUrl as IOdspResolvedUrl;\n}\n\nexport const createOdspLogger = (logger?: ITelemetryBaseLogger) =>\n\tChildLogger.create(logger, \"OdspDriver\", {\n\t\tall: {\n\t\t\tdriverVersion,\n\t\t},\n\t});\n\nexport function evalBlobsAndTrees(snapshot: IOdspSnapshot) {\n\tlet numTrees = 0;\n\tlet numBlobs = 0;\n\tlet encodedBlobsSize = 0;\n\tlet decodedBlobsSize = 0;\n\tfor (const tree of snapshot.trees) {\n\t\tfor (const treeEntry of tree.entries) {\n\t\t\tif (treeEntry.type === \"blob\") {\n\t\t\t\tnumBlobs++;\n\t\t\t} else if (treeEntry.type === \"tree\") {\n\t\t\t\tnumTrees++;\n\t\t\t}\n\t\t}\n\t}\n\tif (snapshot.blobs !== undefined) {\n\t\tfor (const blob of snapshot.blobs) {\n\t\t\tdecodedBlobsSize += blob.size;\n\t\t\tencodedBlobsSize += blob.content.length;\n\t\t}\n\t}\n\treturn { numTrees, numBlobs, encodedBlobsSize, decodedBlobsSize };\n}\n\nexport function toInstrumentedOdspTokenFetcher(\n\tlogger: ITelemetryLogger,\n\tresolvedUrlParts: IOdspUrlParts,\n\ttokenFetcher: TokenFetcher<OdspResourceTokenFetchOptions>,\n\tthrowOnNullToken: boolean,\n): InstrumentedStorageTokenFetcher {\n\treturn async (\n\t\toptions: TokenFetchOptions,\n\t\tname: string,\n\t\talwaysRecordTokenFetchTelemetry: boolean = false,\n\t) => {\n\t\t// Telemetry note: if options.refresh is true, there is a potential perf issue:\n\t\t// Host should optimize and provide non-expired tokens on all critical paths.\n\t\t// Exceptions: race conditions around expiration, revoked tokens, host that does not care\n\t\t// (fluid-fetcher)\n\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\tlogger,\n\t\t\t{\n\t\t\t\teventName: `${name}_GetToken`,\n\t\t\t\tattempts: options.refresh ? 2 : 1,\n\t\t\t\thasClaims: !!options.claims,\n\t\t\t\thasTenantId: !!options.tenantId,\n\t\t\t},\n\t\t\tasync (event) =>\n\t\t\t\ttokenFetcher({\n\t\t\t\t\t...options,\n\t\t\t\t\t...resolvedUrlParts,\n\t\t\t\t}).then(\n\t\t\t\t\t(tokenResponse) => {\n\t\t\t\t\t\tconst token = tokenFromResponse(tokenResponse);\n\t\t\t\t\t\t// This event alone generates so many events that is materially impacts cost of telemetry\n\t\t\t\t\t\t// Thus do not report end event when it comes back quickly.\n\t\t\t\t\t\t// Note that most of the hosts do not report if result is comming from cache or not,\n\t\t\t\t\t\t// so we can't rely on that here. But always record if specified explicitly for cases such as\n\t\t\t\t\t\t// calling trees/latest during load.\n\t\t\t\t\t\tif (alwaysRecordTokenFetchTelemetry || event.duration >= 32) {\n\t\t\t\t\t\t\tevent.end({\n\t\t\t\t\t\t\t\tfromCache: isTokenFromCache(tokenResponse),\n\t\t\t\t\t\t\t\tisNull: token === null,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (token === null && throwOnNullToken) {\n\t\t\t\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\t\t\t// pre-0.58 error message: Token is null for ${name} call\n\t\t\t\t\t\t\t\t`The Host-provided token fetcher returned null`,\n\t\t\t\t\t\t\t\tOdspErrorType.fetchTokenError,\n\t\t\t\t\t\t\t\t{ method: name, driverVersion },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn token;\n\t\t\t\t\t},\n\t\t\t\t\t(error) => {\n\t\t\t\t\t\t// There is an important but unofficial contract here where token providers can set canRetry: true\n\t\t\t\t\t\t// to hook into the driver's retry logic (e.g. the retry loop when initiating a connection)\n\t\t\t\t\t\tconst rawCanRetry = error?.canRetry;\n\t\t\t\t\t\tconst tokenError = wrapError(\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t\t(errorMessage) =>\n\t\t\t\t\t\t\t\tnew NetworkErrorBasic(\n\t\t\t\t\t\t\t\t\t`The Host-provided token fetcher threw an error`,\n\t\t\t\t\t\t\t\t\tOdspErrorType.fetchTokenError,\n\t\t\t\t\t\t\t\t\ttypeof rawCanRetry === \"boolean\"\n\t\t\t\t\t\t\t\t\t\t? rawCanRetry\n\t\t\t\t\t\t\t\t\t\t: false /* canRetry */,\n\t\t\t\t\t\t\t\t\t{ method: name, errorMessage, driverVersion },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthrow tokenError;\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t{ cancel: \"generic\" },\n\t\t);\n\t};\n}\n\nexport function createCacheSnapshotKey(odspResolvedUrl: IOdspResolvedUrl): ICacheEntry {\n\tconst cacheEntry: ICacheEntry = {\n\t\ttype: snapshotKey,\n\t\tkey: odspResolvedUrl.fileVersion ?? \"\",\n\t\tfile: {\n\t\t\tresolvedUrl: odspResolvedUrl,\n\t\t\tdocId: odspResolvedUrl.hashedDocumentId,\n\t\t},\n\t};\n\treturn cacheEntry;\n}\n\n// 80KB is the max body size that we can put in ump post body for server to be able to accept it.\n// Keeping it 78KB to be a little cautious. As per the telemetry 99p is less than 78KB.\nexport const maxUmpPostBodySize = 79872;\n\n/**\n * Build request parameters to request for the creation of a sharing link along with the creation of the file\n * through the /snapshot api call.\n * @param shareLinkType - Kind of sharing link requested\n * @returns A string of request parameters that can be concatenated with the base URI\n */\nexport function buildOdspShareLinkReqParams(\n\tshareLinkType: ShareLinkTypes | ISharingLinkKind | undefined,\n) {\n\tif (!shareLinkType) {\n\t\treturn;\n\t}\n\tconst scope = (shareLinkType as ISharingLinkKind).scope;\n\tif (!scope) {\n\t\treturn `createLinkType=${shareLinkType}`;\n\t}\n\tlet shareLinkRequestParams = `createLinkScope=${scope}`;\n\tconst role = (shareLinkType as ISharingLinkKind).role;\n\tshareLinkRequestParams = role\n\t\t? `${shareLinkRequestParams}&createLinkRole=${role}`\n\t\t: shareLinkRequestParams;\n\treturn shareLinkRequestParams;\n}\n\nexport function measure<T>(callback: () => T): [T, number] {\n\tconst start = performance.now();\n\tconst result = callback();\n\tconst time = performance.now() - start;\n\treturn [result, time];\n}\n\nexport async function measureP<T>(callback: () => Promise<T>): Promise<[T, number]> {\n\tconst start = performance.now();\n\tconst result = await callback();\n\tconst time = performance.now() - start;\n\treturn [result, time];\n}\n\nexport function validateMessages(\n\treason: string,\n\tmessages: ISequencedDocumentMessage[],\n\tfrom: number,\n\tlogger: ITelemetryLogger,\n) {\n\tif (messages.length !== 0) {\n\t\tconst start = messages[0].sequenceNumber;\n\t\tconst length = messages.length;\n\t\tconst last = messages[length - 1].sequenceNumber;\n\t\tif (start !== from) {\n\t\t\tlogger.sendErrorEvent({\n\t\t\t\teventName: \"OpsFetchViolation\",\n\t\t\t\treason,\n\t\t\t\tfrom,\n\t\t\t\tstart,\n\t\t\t\tlast,\n\t\t\t\tlength,\n\t\t\t});\n\t\t\tmessages.length = 0;\n\t\t}\n\t\tif (last + 1 !== from + length) {\n\t\t\tlogger.sendErrorEvent({\n\t\t\t\teventName: \"OpsFetchViolation\",\n\t\t\t\treason,\n\t\t\t\tfrom,\n\t\t\t\tstart,\n\t\t\t\tlast,\n\t\t\t\tlength,\n\t\t\t});\n\t\t\t// we can do better here by finding consecutive sub-block and return it\n\t\t\tmessages.length = 0;\n\t\t}\n\t}\n}\n"]}
|
package/dist/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/odsp-driver";
|
|
8
|
-
export declare const pkgVersion = "2.0.0-internal.4.1
|
|
8
|
+
export declare const pkgVersion = "2.0.0-internal.4.2.1";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/dist/packageVersion.js
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.pkgVersion = exports.pkgName = void 0;
|
|
10
10
|
exports.pkgName = "@fluidframework/odsp-driver";
|
|
11
|
-
exports.pkgVersion = "2.0.0-internal.4.1
|
|
11
|
+
exports.pkgVersion = "2.0.0-internal.4.2.1";
|
|
12
12
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,6BAA6B,CAAC;AACxC,QAAA,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/odsp-driver\";\nexport const pkgVersion = \"2.0.0-internal.4.1
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,6BAA6B,CAAC;AACxC,QAAA,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/odsp-driver\";\nexport const pkgVersion = \"2.0.0-internal.4.2.1\";\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspDocumentStorageManager.d.ts","sourceRoot":"","sources":["../src/odspDocumentStorageManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAGtE,OAAO,KAAK,GAAG,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"odspDocumentStorageManager.d.ts","sourceRoot":"","sources":["../src/odspDocumentStorageManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { assert, delay, performance } from "@fluidframework/common-utils";
|
|
6
6
|
import { loggerToMonitoringContext, PerformanceEvent } from "@fluidframework/telemetry-utils";
|
|
7
|
+
import { promiseRaceWithWinner } from "@fluidframework/driver-base";
|
|
7
8
|
import { DriverErrorType, FetchSource } from "@fluidframework/driver-definitions";
|
|
8
9
|
import { RateLimiter, NonRetryableError } from "@fluidframework/driver-utils";
|
|
9
10
|
import { OdspErrorType, getKeyForCacheEntry, } from "@fluidframework/odsp-driver-definitions";
|
|
@@ -13,14 +14,6 @@ import { createCacheSnapshotKey, getWithRetryForTokenRefresh } from "./odspUtils
|
|
|
13
14
|
import { pkgVersion as driverVersion } from "./packageVersion";
|
|
14
15
|
import { OdspDocumentStorageServiceBase } from "./odspDocumentStorageServiceBase";
|
|
15
16
|
export const defaultSummarizerCacheExpiryTimeout = 60 * 1000; // 60 seconds.
|
|
16
|
-
// An implementation of Promise.race that gives you the winner of the promise race
|
|
17
|
-
async function promiseRaceWithWinner(promises) {
|
|
18
|
-
return new Promise((resolve, reject) => {
|
|
19
|
-
promises.forEach((p, index) => {
|
|
20
|
-
p.then((v) => resolve({ index, value: v })).catch(reject);
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
17
|
export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
25
18
|
constructor(odspResolvedUrl, getStorageToken, logger, fetchFullSnapshot, cache, hostPolicy, epochTracker, flushCallback, relayServiceTenantAndSessionId, snapshotFormatFetchType) {
|
|
26
19
|
super(loggerToMonitoringContext(logger).config);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspDocumentStorageManager.js","sourceRoot":"","sources":["../src/odspDocumentStorageManager.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, delay, performance } from \"@fluidframework/common-utils\";\nimport { loggerToMonitoringContext, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport * as api from \"@fluidframework/protocol-definitions\";\nimport { ISummaryContext, DriverErrorType, FetchSource } from \"@fluidframework/driver-definitions\";\nimport { RateLimiter, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport {\n\tIOdspResolvedUrl,\n\tISnapshotOptions,\n\tOdspErrorType,\n\tInstrumentedStorageTokenFetcher,\n\tgetKeyForCacheEntry,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport {\n\tIDocumentStorageGetVersionsResponse,\n\tHostStoragePolicyInternal,\n\tIVersionedValueWithEpoch,\n\tISnapshotCachedEntry,\n} from \"./contracts\";\nimport {\n\tdownloadSnapshot,\n\tfetchSnapshot,\n\tfetchSnapshotWithRedeem,\n\tSnapshotFormatSupportType,\n} from \"./fetchSnapshot\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport { IOdspCache, IPrefetchSnapshotContents } from \"./odspCache\";\nimport { createCacheSnapshotKey, getWithRetryForTokenRefresh } from \"./odspUtils\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { EpochTracker } from \"./epochTracker\";\nimport type { OdspSummaryUploadManager } from \"./odspSummaryUploadManager\";\nimport { FlushResult } from \"./odspDocumentDeltaConnection\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\nimport { OdspDocumentStorageServiceBase } from \"./odspDocumentStorageServiceBase\";\n\nexport const defaultSummarizerCacheExpiryTimeout: number = 60 * 1000; // 60 seconds.\n\n// An implementation of Promise.race that gives you the winner of the promise race\nasync function promiseRaceWithWinner<T>(\n\tpromises: Promise<T>[],\n): Promise<{ index: number; value: T }> {\n\treturn new Promise((resolve, reject) => {\n\t\tpromises.forEach((p, index) => {\n\t\t\tp.then((v) => resolve({ index, value: v })).catch(reject);\n\t\t});\n\t});\n}\n\ninterface GetVersionsTelemetryProps {\n\tcacheEntryAge?: number;\n\tcacheSummarizerExpired?: boolean;\n}\n\nexport class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {\n\tprivate odspSummaryModuleLoaded: boolean = false;\n\tprivate summaryModuleP: Promise<OdspSummaryUploadManager> | undefined;\n\tprivate odspSummaryUploadManager: OdspSummaryUploadManager | undefined;\n\n\tprivate firstVersionCall = true;\n\n\tprivate readonly documentId: string;\n\tprivate readonly snapshotUrl: string | undefined;\n\tprivate readonly attachmentPOSTUrl: string | undefined;\n\tprivate readonly attachmentGETUrl: string | undefined;\n\t// Driver specified limits for snapshot size and time.\n\t/**\n\t * NOTE: While commit cfff6e3 added restrictions to prevent large payloads, snapshot failures will continue to\n\t * happen until blob request throttling is implemented. Until then, as a temporary fix we set arbitrarily large\n\t * snapshot size and timeout limits so that such failures are unlikely to occur.\n\t */\n\tprivate readonly maxSnapshotSizeLimit = 500000000; // 500 MB\n\tprivate readonly maxSnapshotFetchTimeout = 120000; // 2 min\n\n\t// limits the amount of parallel \"attachment\" blob uploads\n\tprivate readonly createBlobRateLimiter = new RateLimiter(1);\n\n\tconstructor(\n\t\tprivate readonly odspResolvedUrl: IOdspResolvedUrl,\n\t\tprivate readonly getStorageToken: InstrumentedStorageTokenFetcher,\n\t\tprivate readonly logger: ITelemetryLogger,\n\t\tprivate readonly fetchFullSnapshot: boolean,\n\t\tprivate readonly cache: IOdspCache,\n\t\tprivate readonly hostPolicy: HostStoragePolicyInternal,\n\t\tprivate readonly epochTracker: EpochTracker,\n\t\tprivate readonly flushCallback: () => Promise<FlushResult>,\n\t\tprivate readonly relayServiceTenantAndSessionId: () => string | undefined,\n\t\tprivate readonly snapshotFormatFetchType?: SnapshotFormatSupportType,\n\t) {\n\t\tsuper(loggerToMonitoringContext(logger).config);\n\n\t\tthis.documentId = this.odspResolvedUrl.hashedDocumentId;\n\t\tthis.snapshotUrl = this.odspResolvedUrl.endpoints.snapshotStorageUrl;\n\t\tthis.attachmentPOSTUrl = this.odspResolvedUrl.endpoints.attachmentPOSTStorageUrl;\n\t\tthis.attachmentGETUrl = this.odspResolvedUrl.endpoints.attachmentGETStorageUrl;\n\t}\n\n\tpublic async createBlob(file: ArrayBufferLike): Promise<api.ICreateBlobResponse> {\n\t\tthis.checkAttachmentPOSTUrl();\n\n\t\tconst response = await getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"CreateBlob\");\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\t`${this.attachmentPOSTUrl}/content`,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\t\t\theaders[\"Content-Type\"] = \"application/octet-stream\";\n\n\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"createBlob\",\n\t\t\t\t\tsize: file.byteLength,\n\t\t\t\t\twaitQueueLength: this.createBlobRateLimiter.waitQueueLength,\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tconst res = await this.createBlobRateLimiter.schedule(async () =>\n\t\t\t\t\t\tthis.epochTracker.fetchAndParseAsJSON<api.ICreateBlobResponse>(\n\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbody: file,\n\t\t\t\t\t\t\t\theaders,\n\t\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"createBlob\",\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\tblobId: res.content.id,\n\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t});\n\t\t\t\t\treturn res;\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\n\t\treturn response.content;\n\t}\n\n\tprotected async fetchBlobFromStorage(blobId: string, evicted: boolean): Promise<ArrayBuffer> {\n\t\tthis.checkAttachmentGETUrl();\n\n\t\tconst blob = await getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"GetBlob\");\n\t\t\tconst unAuthedUrl = `${this.attachmentGETUrl}/${encodeURIComponent(blobId)}/content`;\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\tunAuthedUrl,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\n\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"readDataBlob\",\n\t\t\t\t\tblobId,\n\t\t\t\t\tevicted,\n\t\t\t\t\theaders: Object.keys(headers).length !== 0 ? true : undefined,\n\t\t\t\t\twaitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tconst res = await this.epochTracker.fetchArray(url, { headers }, \"blob\");\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\twaitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t\tattempts: options.refresh ? 2 : 1,\n\t\t\t\t\t});\n\t\t\t\t\tconst cacheControl = res.headers.get(\"cache-control\");\n\t\t\t\t\tif (\n\t\t\t\t\t\tcacheControl === undefined ||\n\t\t\t\t\t\t!(cacheControl.includes(\"private\") || cacheControl.includes(\"public\"))\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\t\teventName: \"NonCacheableBlob\",\n\t\t\t\t\t\t\tcacheControl,\n\t\t\t\t\t\t\tblobId,\n\t\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn res.content;\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t\tthis.blobCache.setBlob(blobId, blob);\n\t\treturn blob;\n\t}\n\n\tpublic async getSnapshotTree(\n\t\tversion?: api.IVersion,\n\t\tscenarioName?: string,\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t): Promise<api.ISnapshotTree | null> {\n\t\tif (!this.snapshotUrl) {\n\t\t\treturn null;\n\t\t}\n\t\treturn super.getSnapshotTree(version, scenarioName);\n\t}\n\n\tpublic async getVersions(\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tblobid: string | null,\n\t\tcount: number,\n\t\tscenarioName?: string,\n\t\tfetchSource?: FetchSource,\n\t): Promise<api.IVersion[]> {\n\t\t// Regular load workflow uses blobId === documentID to indicate \"latest\".\n\t\tif (blobid !== this.documentId && blobid) {\n\t\t\t// FluidFetch & FluidDebugger tools use empty sting to query for versions\n\t\t\t// In such case we need to make a call against SPO to give full picture to the tool.\n\t\t\t// Otherwise, each commit calls getVersions but odsp doesn't have a history for each commit\n\t\t\t// return the blobid as is\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: blobid,\n\t\t\t\t\ttreeId: undefined!,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\t// Can't really make a call if we do not have URL\n\t\tif (!this.snapshotUrl) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// If count is one, we can use the trees/latest API, which returns the latest version and trees in a single request for better performance\n\t\tif (count === 1 && (blobid === null || blobid === this.documentId)) {\n\t\t\tconst hostSnapshotOptions = this.hostPolicy.snapshotOptions;\n\t\t\tconst odspSnapshotCacheValue: ISnapshotContents = await PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{ eventName: \"ObtainSnapshot\", fetchSource },\n\t\t\t\tasync (event: PerformanceEvent) => {\n\t\t\t\t\tconst props: GetVersionsTelemetryProps = {};\n\t\t\t\t\tlet retrievedSnapshot:\n\t\t\t\t\t\t| ISnapshotContents\n\t\t\t\t\t\t| IPrefetchSnapshotContents\n\t\t\t\t\t\t| undefined;\n\n\t\t\t\t\tlet method: string;\n\t\t\t\t\tlet prefetchWaitStartTime: number = performance.now();\n\t\t\t\t\tif (fetchSource === FetchSource.noCache) {\n\t\t\t\t\t\tretrievedSnapshot = await this.fetchSnapshot(\n\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tmethod = \"networkOnly\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Here's the logic to grab the persistent cache snapshot implemented by the host\n\t\t\t\t\t\t// Epoch tracker is responsible for communicating with the persistent cache, handling epochs and cache versions\n\t\t\t\t\t\tconst cachedSnapshotP: Promise<ISnapshotContents | undefined> =\n\t\t\t\t\t\t\tthis.epochTracker\n\t\t\t\t\t\t\t\t.get(createCacheSnapshotKey(this.odspResolvedUrl))\n\t\t\t\t\t\t\t\t.then(async (snapshotCachedEntry: ISnapshotCachedEntry) => {\n\t\t\t\t\t\t\t\t\tif (snapshotCachedEntry !== undefined) {\n\t\t\t\t\t\t\t\t\t\t// If the cached entry does not contain the entry time, then assign it a default of 30 days old.\n\t\t\t\t\t\t\t\t\t\tconst age =\n\t\t\t\t\t\t\t\t\t\t\tDate.now() -\n\t\t\t\t\t\t\t\t\t\t\t(snapshotCachedEntry.cacheEntryTime ??\n\t\t\t\t\t\t\t\t\t\t\t\tDate.now() - 30 * 24 * 60 * 60 * 1000);\n\n\t\t\t\t\t\t\t\t\t\t// In order to decrease the number of times we have to execute a snapshot refresh,\n\t\t\t\t\t\t\t\t\t\t// if this is the summarizer and we have a cache entry but it is past the defaultSummarizerCacheExpiryTimeout,\n\t\t\t\t\t\t\t\t\t\t// force the network retrieval instead as there might be a more recent snapshot available.\n\t\t\t\t\t\t\t\t\t\t// See: https://github.com/microsoft/FluidFramework/issues/8995 for additional information.\n\t\t\t\t\t\t\t\t\t\tif (this.hostPolicy.summarizerClient) {\n\t\t\t\t\t\t\t\t\t\t\tif (age > defaultSummarizerCacheExpiryTimeout) {\n\t\t\t\t\t\t\t\t\t\t\t\tprops.cacheSummarizerExpired = true;\n\t\t\t\t\t\t\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tprops.cacheSummarizerExpired = false;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Record the cache age\n\t\t\t\t\t\t\t\t\t\tprops.cacheEntryAge = age;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\treturn snapshotCachedEntry;\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// Based on the concurrentSnapshotFetch policy:\n\t\t\t\t\t\t// Either retrieve both the network and cache snapshots concurrently and pick the first to return,\n\t\t\t\t\t\t// or grab the cache value and then the network value if the cache value returns undefined.\n\t\t\t\t\t\t// For summarizer which could call this during refreshing of summary parent, always use the cache\n\t\t\t\t\t\t// first. Also for other clients, if it is not critical path which is determined by firstVersionCall,\n\t\t\t\t\t\t// then also check the cache first.\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tthis.firstVersionCall &&\n\t\t\t\t\t\t\tthis.hostPolicy.concurrentSnapshotFetch &&\n\t\t\t\t\t\t\t!this.hostPolicy.summarizerClient\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tconst networkSnapshotP = this.fetchSnapshot(\n\t\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// Ensure that failures on both paths are ignored initially.\n\t\t\t\t\t\t\t// I.e. if cache fails for some reason, we will proceed with network result.\n\t\t\t\t\t\t\t// And vice versa - if (for example) client is offline and network request fails first, we\n\t\t\t\t\t\t\t// do want to attempt to succeed with cached data!\n\t\t\t\t\t\t\tconst promiseRaceWinner = await promiseRaceWithWinner([\n\t\t\t\t\t\t\t\tcachedSnapshotP.catch(() => undefined),\n\t\t\t\t\t\t\t\tnetworkSnapshotP.catch(() => undefined),\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\tretrievedSnapshot = promiseRaceWinner.value;\n\t\t\t\t\t\t\tmethod = promiseRaceWinner.index === 0 ? \"cache\" : \"network\";\n\n\t\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t\t// if network failed -> wait for cache ( then return network failure)\n\t\t\t\t\t\t\t\t// If cache returned empty or failed -> wait for network (success of failure)\n\t\t\t\t\t\t\t\tif (promiseRaceWinner.index === 1) {\n\t\t\t\t\t\t\t\t\tretrievedSnapshot = await cachedSnapshotP;\n\t\t\t\t\t\t\t\t\tmethod = \"cache\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t\t\tretrievedSnapshot = await networkSnapshotP;\n\t\t\t\t\t\t\t\t\tmethod = \"network\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Note: There's a race condition here - another caller may come past the undefined check\n\t\t\t\t\t\t\t// while the first caller is awaiting later async code in this block.\n\n\t\t\t\t\t\t\tretrievedSnapshot = await cachedSnapshotP;\n\n\t\t\t\t\t\t\tmethod = retrievedSnapshot !== undefined ? \"cache\" : \"network\";\n\n\t\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t\tprefetchWaitStartTime = performance.now();\n\t\t\t\t\t\t\t\tretrievedSnapshot = await this.fetchSnapshot(\n\t\t\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (method === \"network\") {\n\t\t\t\t\t\tprops.cacheEntryAge = undefined;\n\t\t\t\t\t}\n\t\t\t\t\tconst prefetchStartTime: number | undefined = (\n\t\t\t\t\t\tretrievedSnapshot as IPrefetchSnapshotContents\n\t\t\t\t\t).prefetchStartTime;\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tmethod,\n\t\t\t\t\t\tavoidPrefetchSnapshotCache: this.hostPolicy.avoidPrefetchSnapshotCache,\n\t\t\t\t\t\tprefetchSavedDuration:\n\t\t\t\t\t\t\tprefetchStartTime !== undefined && method !== \"cache\"\n\t\t\t\t\t\t\t\t? prefetchWaitStartTime - prefetchStartTime\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t});\n\t\t\t\t\treturn retrievedSnapshot;\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Don't override ops which were fetched during initial load, since we could still need them.\n\t\t\tconst id = this.initializeFromSnapshot(odspSnapshotCacheValue, this.firstVersionCall);\n\t\t\tthis.firstVersionCall = false;\n\n\t\t\treturn id ? [{ id, treeId: undefined! }] : [];\n\t\t}\n\n\t\treturn getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"GetVersions\");\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\t`${this.snapshotUrl}/versions?top=${count}`,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\n\t\t\t// Fetch the latest snapshot versions for the document\n\t\t\tconst response = await PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"getVersions\",\n\t\t\t\t\theaders: Object.keys(headers).length !== 0 ? true : undefined,\n\t\t\t\t},\n\t\t\t\tasync () =>\n\t\t\t\t\tthis.epochTracker.fetchAndParseAsJSON<IDocumentStorageGetVersionsResponse>(\n\t\t\t\t\t\turl,\n\t\t\t\t\t\t{ headers },\n\t\t\t\t\t\t\"versions\",\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tconst versionsResponse = response.content;\n\t\t\tif (!versionsResponse) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\"No response from /versions endpoint\",\n\t\t\t\t\tDriverErrorType.genericNetworkError,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!Array.isArray(versionsResponse.value)) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\"Incorrect response from /versions endpoint, expected an array\",\n\t\t\t\t\tDriverErrorType.genericNetworkError,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn versionsResponse.value.map((version) => {\n\t\t\t\treturn {\n\t\t\t\t\tid: version.id,\n\t\t\t\t\ttreeId: undefined!,\n\t\t\t\t};\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate async fetchSnapshot(\n\t\thostSnapshotOptions: ISnapshotOptions | undefined,\n\t\tscenarioName?: string,\n\t) {\n\t\treturn this.fetchSnapshotCore(hostSnapshotOptions, scenarioName).catch((error) => {\n\t\t\t// Issue #5895:\n\t\t\t// If we are offline, this error is retryable. But that means that RetriableDocumentStorageService\n\t\t\t// will run in circles calling getSnapshotTree, which would result in OdspDocumentStorageService class\n\t\t\t// going getVersions / individual blob download path. This path is very slow, and will not work with\n\t\t\t// delay-loaded data stores and ODSP storage deleting old snapshots and blobs.\n\t\t\tif (typeof error === \"object\" && error !== null) {\n\t\t\t\terror.canRetry = false;\n\t\t\t}\n\t\t\tthrow error;\n\t\t});\n\t}\n\n\tprivate async fetchSnapshotCore(\n\t\thostSnapshotOptions: ISnapshotOptions | undefined,\n\t\tscenarioName?: string,\n\t): Promise<ISnapshotContents | IPrefetchSnapshotContents> {\n\t\t// Don't look into cache, if the host specifically tells us so.\n\t\tif (!this.hostPolicy.avoidPrefetchSnapshotCache) {\n\t\t\tconst prefetchCacheKey = getKeyForCacheEntry(\n\t\t\t\tcreateCacheSnapshotKey(this.odspResolvedUrl),\n\t\t\t);\n\t\t\tconst result = await this.cache.snapshotPrefetchResultCache\n\t\t\t\t?.get(prefetchCacheKey)\n\t\t\t\t?.then(async (response) => {\n\t\t\t\t\t// Validate the epoch from the prefetched snapshot result.\n\t\t\t\t\tawait this.epochTracker.validateEpoch(response.fluidEpoch, \"treesLatest\");\n\t\t\t\t\treturn response;\n\t\t\t\t})\n\t\t\t\t.catch(async (err) => {\n\t\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"PrefetchSnapshotError\",\n\t\t\t\t\t\t\tconcurrentSnapshotFetch: this.hostPolicy.concurrentSnapshotFetch,\n\t\t\t\t\t\t},\n\t\t\t\t\t\terr,\n\t\t\t\t\t);\n\t\t\t\t\treturn undefined;\n\t\t\t\t});\n\t\t\t// If the prefetch call, is successful, then return the contents otherwise as backup for now, just\n\t\t\t// proceed with the old snapshot fetch flow.\n\t\t\tif (result !== undefined) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t\tconst snapshotOptions: ISnapshotOptions = {\n\t\t\tmds: this.maxSnapshotSizeLimit,\n\t\t\t...hostSnapshotOptions,\n\t\t\ttimeout: hostSnapshotOptions?.timeout\n\t\t\t\t? Math.min(hostSnapshotOptions.timeout, this.maxSnapshotFetchTimeout)\n\t\t\t\t: this.maxSnapshotFetchTimeout,\n\t\t};\n\n\t\t// No limit on size of snapshot or time to fetch, as otherwise we fail all clients to summarize\n\t\tif (this.hostPolicy.summarizerClient) {\n\t\t\tsnapshotOptions.mds = undefined;\n\t\t\tsnapshotOptions.timeout = undefined;\n\t\t}\n\n\t\tconst snapshotDownloader = async (\n\t\t\tfinalOdspResolvedUrl: IOdspResolvedUrl,\n\t\t\tstorageToken: string,\n\t\t\toptions: ISnapshotOptions | undefined,\n\t\t\tcontroller?: AbortController,\n\t\t) => {\n\t\t\treturn downloadSnapshot(\n\t\t\t\tfinalOdspResolvedUrl,\n\t\t\t\tstorageToken,\n\t\t\t\tthis.logger,\n\t\t\t\toptions,\n\t\t\t\tthis.snapshotFormatFetchType,\n\t\t\t\tcontroller,\n\t\t\t\tthis.epochTracker,\n\t\t\t\tscenarioName,\n\t\t\t);\n\t\t};\n\t\tconst putInCache = async (valueWithEpoch: IVersionedValueWithEpoch) => {\n\t\t\treturn this.cache.persistedCache.put(\n\t\t\t\tcreateCacheSnapshotKey(this.odspResolvedUrl),\n\t\t\t\t// Epoch tracker will add the epoch and version to the value here. So just send value to cache.\n\t\t\t\tvalueWithEpoch.value,\n\t\t\t);\n\t\t};\n\t\tconst removeEntries = async () => this.cache.persistedCache.removeEntries();\n\t\ttry {\n\t\t\tconst odspSnapshot = await fetchSnapshotWithRedeem(\n\t\t\t\tthis.odspResolvedUrl,\n\t\t\t\tthis.getStorageToken,\n\t\t\t\tsnapshotOptions,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\tthis.logger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t\tputInCache,\n\t\t\t\tremoveEntries,\n\t\t\t\tthis.hostPolicy.enableRedeemFallback,\n\t\t\t);\n\t\t\treturn odspSnapshot;\n\t\t} catch (error: any) {\n\t\t\tconst errorType = error.errorType;\n\t\t\t// If the snapshot size is too big and the host specified the size limitation(specified in hostSnapshotOptions), then don't try to fetch the snapshot again.\n\t\t\tif (\n\t\t\t\terrorType === OdspErrorType.snapshotTooBig &&\n\t\t\t\thostSnapshotOptions?.mds !== undefined &&\n\t\t\t\tthis.hostPolicy.summarizerClient !== true\n\t\t\t) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\t// If the first snapshot request was with blobs and we either timed out or the size was too big, then try to fetch without blobs.\n\t\t\tif (\n\t\t\t\t(errorType === OdspErrorType.snapshotTooBig ||\n\t\t\t\t\terrorType === OdspErrorType.fetchTimeout) &&\n\t\t\t\tsnapshotOptions.blobs\n\t\t\t) {\n\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\teventName: \"TreeLatest_SecondCall\",\n\t\t\t\t\terrorType,\n\t\t\t\t});\n\t\t\t\tconst snapshotOptionsWithoutBlobs: ISnapshotOptions = {\n\t\t\t\t\t...snapshotOptions,\n\t\t\t\t\tblobs: 0,\n\t\t\t\t\tmds: undefined,\n\t\t\t\t\ttimeout: undefined,\n\t\t\t\t};\n\t\t\t\tconst odspSnapshot = await fetchSnapshotWithRedeem(\n\t\t\t\t\tthis.odspResolvedUrl,\n\t\t\t\t\tthis.getStorageToken,\n\t\t\t\t\tsnapshotOptionsWithoutBlobs,\n\t\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tsnapshotDownloader,\n\t\t\t\t\tputInCache,\n\t\t\t\t\tremoveEntries,\n\t\t\t\t\tthis.hostPolicy.enableRedeemFallback,\n\t\t\t\t);\n\t\t\t\treturn odspSnapshot;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic async uploadSummaryWithContext(\n\t\tsummary: api.ISummaryTree,\n\t\tcontext: ISummaryContext,\n\t): Promise<string> {\n\t\tthis.checkSnapshotUrl();\n\n\t\t// Set the module promise right away, so as to not call it twice.\n\t\tif (this.summaryModuleP === undefined) {\n\t\t\tthis.summaryModuleP = this.getDelayLoadedSummaryManager();\n\t\t}\n\n\t\t// Enable flushing only if we have single commit summary and this is not the initial summary for an empty file\n\t\tif (\".protocol\" in summary.tree && context.ackHandle !== undefined) {\n\t\t\tlet retry = 1;\n\t\t\tfor (;;) {\n\t\t\t\tconst result = await this.flushCallback();\n\t\t\t\tconst seq = result.lastPersistedSequenceNumber;\n\t\t\t\tif (seq !== undefined && seq >= context.referenceSequenceNumber) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (retry > 3) {\n\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\teventName: \"FlushFailure\",\n\t\t\t\t\t\t...result,\n\t\t\t\t\t\tretry,\n\t\t\t\t\t\treferenceSequenceNumber: context.referenceSequenceNumber,\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\teventName: \"FlushExtraCall\",\n\t\t\t\t\t...result,\n\t\t\t\t\tretry,\n\t\t\t\t\treferenceSequenceNumber: context.referenceSequenceNumber,\n\t\t\t\t});\n\n\t\t\t\tretry++;\n\t\t\t\tawait delay(1000 * (result.retryAfter ?? 1));\n\t\t\t}\n\t\t}\n\n\t\tif (!this.odspSummaryUploadManager) {\n\t\t\tthis.odspSummaryUploadManager = await this.summaryModuleP\n\t\t\t\t.then(async (m) => {\n\t\t\t\t\tthis.odspSummaryModuleLoaded = true;\n\t\t\t\t\treturn m;\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tthis.odspSummaryModuleLoaded = false;\n\t\t\t\t\tthrow error;\n\t\t\t\t});\n\t\t}\n\n\t\tassert(\n\t\t\tthis.odspSummaryUploadManager !== undefined,\n\t\t\t0x56e /* summary upload manager should have been initialized */,\n\t\t);\n\t\tconst id = await this.odspSummaryUploadManager.writeSummaryTree(summary, context);\n\t\treturn id;\n\t}\n\n\tprivate async getDelayLoadedSummaryManager() {\n\t\tassert(this.odspSummaryModuleLoaded === false, 0x56f /* Should be loaded only once */);\n\t\tconst module = await import(\n\t\t\t/* webpackChunkName: \"summaryModule\" */ \"./odspSummaryUploadManager\"\n\t\t)\n\t\t\t.then((m) => {\n\t\t\t\tthis.logger.sendTelemetryEvent({ eventName: \"SummaryModuleLoaded\" });\n\t\t\t\treturn m;\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.logger.sendErrorEvent({ eventName: \"SummaryModuleLoadFailed\" }, error);\n\t\t\t\tthrow error;\n\t\t\t});\n\t\tthis.odspSummaryUploadManager = new module.OdspSummaryUploadManager(\n\t\t\tthis.odspResolvedUrl.endpoints.snapshotStorageUrl,\n\t\t\tthis.getStorageToken,\n\t\t\tthis.logger,\n\t\t\tthis.epochTracker,\n\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\tthis.relayServiceTenantAndSessionId,\n\t\t);\n\t\treturn this.odspSummaryUploadManager;\n\t}\n\n\tprivate checkSnapshotUrl() {\n\t\tif (!this.snapshotUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no snapshot url was available\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate checkAttachmentPOSTUrl() {\n\t\tif (!this.attachmentPOSTUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no attachment POST url was available\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate checkAttachmentGETUrl() {\n\t\tif (!this.attachmentGETUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no attachment GET url was available\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprotected async fetchTreeFromSnapshot(\n\t\tid: string,\n\t\tscenarioName?: string,\n\t): Promise<api.ISnapshotTree | undefined> {\n\t\treturn getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"ReadCommit\");\n\t\t\tconst snapshotDownloader = async (\n\t\t\t\turl: string,\n\t\t\t\tfetchOptions: { [index: string]: any },\n\t\t\t) => {\n\t\t\t\treturn this.epochTracker.fetchAndParseAsJSON(\n\t\t\t\t\turl,\n\t\t\t\t\tfetchOptions,\n\t\t\t\t\t\"snapshotTree\",\n\t\t\t\t\tundefined,\n\t\t\t\t\tscenarioName,\n\t\t\t\t);\n\t\t\t};\n\t\t\tconst snapshot = await fetchSnapshot(\n\t\t\t\tthis.snapshotUrl!,\n\t\t\t\tstorageToken,\n\t\t\t\tid,\n\t\t\t\tthis.fetchFullSnapshot,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\tthis.logger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t);\n\t\t\tlet treeId = \"\";\n\t\t\tif (snapshot.snapshotTree) {\n\t\t\t\tassert(\n\t\t\t\t\tsnapshot.snapshotTree.id !== undefined,\n\t\t\t\t\t0x222 /* \"Root tree should contain the id!!\" */,\n\t\t\t\t);\n\t\t\t\ttreeId = snapshot.snapshotTree.id;\n\t\t\t\tthis.setRootTree(treeId, snapshot.snapshotTree);\n\t\t\t}\n\t\t\tif (snapshot.blobs) {\n\t\t\t\tthis.initBlobsCache(snapshot.blobs);\n\t\t\t}\n\t\t\t// If the version id doesn't match with the id of the tree, then use the id of first tree which in that case\n\t\t\t// will be the actual id of tree to be fetched.\n\t\t\treturn this.commitCache.get(id) ?? this.commitCache.get(treeId);\n\t\t});\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"odspDocumentStorageManager.js","sourceRoot":"","sources":["../src/odspDocumentStorageManager.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, delay, performance } from \"@fluidframework/common-utils\";\nimport { loggerToMonitoringContext, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport * as api from \"@fluidframework/protocol-definitions\";\nimport { promiseRaceWithWinner } from \"@fluidframework/driver-base\";\nimport { ISummaryContext, DriverErrorType, FetchSource } from \"@fluidframework/driver-definitions\";\nimport { RateLimiter, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport {\n\tIOdspResolvedUrl,\n\tISnapshotOptions,\n\tOdspErrorType,\n\tInstrumentedStorageTokenFetcher,\n\tgetKeyForCacheEntry,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport {\n\tIDocumentStorageGetVersionsResponse,\n\tHostStoragePolicyInternal,\n\tIVersionedValueWithEpoch,\n\tISnapshotCachedEntry,\n} from \"./contracts\";\nimport {\n\tdownloadSnapshot,\n\tfetchSnapshot,\n\tfetchSnapshotWithRedeem,\n\tSnapshotFormatSupportType,\n} from \"./fetchSnapshot\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport { IOdspCache, IPrefetchSnapshotContents } from \"./odspCache\";\nimport { createCacheSnapshotKey, getWithRetryForTokenRefresh } from \"./odspUtils\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { EpochTracker } from \"./epochTracker\";\nimport type { OdspSummaryUploadManager } from \"./odspSummaryUploadManager\";\nimport { FlushResult } from \"./odspDocumentDeltaConnection\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\nimport { OdspDocumentStorageServiceBase } from \"./odspDocumentStorageServiceBase\";\n\nexport const defaultSummarizerCacheExpiryTimeout: number = 60 * 1000; // 60 seconds.\n\ninterface GetVersionsTelemetryProps {\n\tcacheEntryAge?: number;\n\tcacheSummarizerExpired?: boolean;\n}\n\nexport class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {\n\tprivate odspSummaryModuleLoaded: boolean = false;\n\tprivate summaryModuleP: Promise<OdspSummaryUploadManager> | undefined;\n\tprivate odspSummaryUploadManager: OdspSummaryUploadManager | undefined;\n\n\tprivate firstVersionCall = true;\n\n\tprivate readonly documentId: string;\n\tprivate readonly snapshotUrl: string | undefined;\n\tprivate readonly attachmentPOSTUrl: string | undefined;\n\tprivate readonly attachmentGETUrl: string | undefined;\n\t// Driver specified limits for snapshot size and time.\n\t/**\n\t * NOTE: While commit cfff6e3 added restrictions to prevent large payloads, snapshot failures will continue to\n\t * happen until blob request throttling is implemented. Until then, as a temporary fix we set arbitrarily large\n\t * snapshot size and timeout limits so that such failures are unlikely to occur.\n\t */\n\tprivate readonly maxSnapshotSizeLimit = 500000000; // 500 MB\n\tprivate readonly maxSnapshotFetchTimeout = 120000; // 2 min\n\n\t// limits the amount of parallel \"attachment\" blob uploads\n\tprivate readonly createBlobRateLimiter = new RateLimiter(1);\n\n\tconstructor(\n\t\tprivate readonly odspResolvedUrl: IOdspResolvedUrl,\n\t\tprivate readonly getStorageToken: InstrumentedStorageTokenFetcher,\n\t\tprivate readonly logger: ITelemetryLogger,\n\t\tprivate readonly fetchFullSnapshot: boolean,\n\t\tprivate readonly cache: IOdspCache,\n\t\tprivate readonly hostPolicy: HostStoragePolicyInternal,\n\t\tprivate readonly epochTracker: EpochTracker,\n\t\tprivate readonly flushCallback: () => Promise<FlushResult>,\n\t\tprivate readonly relayServiceTenantAndSessionId: () => string | undefined,\n\t\tprivate readonly snapshotFormatFetchType?: SnapshotFormatSupportType,\n\t) {\n\t\tsuper(loggerToMonitoringContext(logger).config);\n\n\t\tthis.documentId = this.odspResolvedUrl.hashedDocumentId;\n\t\tthis.snapshotUrl = this.odspResolvedUrl.endpoints.snapshotStorageUrl;\n\t\tthis.attachmentPOSTUrl = this.odspResolvedUrl.endpoints.attachmentPOSTStorageUrl;\n\t\tthis.attachmentGETUrl = this.odspResolvedUrl.endpoints.attachmentGETStorageUrl;\n\t}\n\n\tpublic async createBlob(file: ArrayBufferLike): Promise<api.ICreateBlobResponse> {\n\t\tthis.checkAttachmentPOSTUrl();\n\n\t\tconst response = await getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"CreateBlob\");\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\t`${this.attachmentPOSTUrl}/content`,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\t\t\theaders[\"Content-Type\"] = \"application/octet-stream\";\n\n\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"createBlob\",\n\t\t\t\t\tsize: file.byteLength,\n\t\t\t\t\twaitQueueLength: this.createBlobRateLimiter.waitQueueLength,\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tconst res = await this.createBlobRateLimiter.schedule(async () =>\n\t\t\t\t\t\tthis.epochTracker.fetchAndParseAsJSON<api.ICreateBlobResponse>(\n\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbody: file,\n\t\t\t\t\t\t\t\theaders,\n\t\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"createBlob\",\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\tblobId: res.content.id,\n\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t});\n\t\t\t\t\treturn res;\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\n\t\treturn response.content;\n\t}\n\n\tprotected async fetchBlobFromStorage(blobId: string, evicted: boolean): Promise<ArrayBuffer> {\n\t\tthis.checkAttachmentGETUrl();\n\n\t\tconst blob = await getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"GetBlob\");\n\t\t\tconst unAuthedUrl = `${this.attachmentGETUrl}/${encodeURIComponent(blobId)}/content`;\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\tunAuthedUrl,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\n\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"readDataBlob\",\n\t\t\t\t\tblobId,\n\t\t\t\t\tevicted,\n\t\t\t\t\theaders: Object.keys(headers).length !== 0 ? true : undefined,\n\t\t\t\t\twaitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tconst res = await this.epochTracker.fetchArray(url, { headers }, \"blob\");\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\twaitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t\tattempts: options.refresh ? 2 : 1,\n\t\t\t\t\t});\n\t\t\t\t\tconst cacheControl = res.headers.get(\"cache-control\");\n\t\t\t\t\tif (\n\t\t\t\t\t\tcacheControl === undefined ||\n\t\t\t\t\t\t!(cacheControl.includes(\"private\") || cacheControl.includes(\"public\"))\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\t\teventName: \"NonCacheableBlob\",\n\t\t\t\t\t\t\tcacheControl,\n\t\t\t\t\t\t\tblobId,\n\t\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn res.content;\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t\tthis.blobCache.setBlob(blobId, blob);\n\t\treturn blob;\n\t}\n\n\tpublic async getSnapshotTree(\n\t\tversion?: api.IVersion,\n\t\tscenarioName?: string,\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t): Promise<api.ISnapshotTree | null> {\n\t\tif (!this.snapshotUrl) {\n\t\t\treturn null;\n\t\t}\n\t\treturn super.getSnapshotTree(version, scenarioName);\n\t}\n\n\tpublic async getVersions(\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tblobid: string | null,\n\t\tcount: number,\n\t\tscenarioName?: string,\n\t\tfetchSource?: FetchSource,\n\t): Promise<api.IVersion[]> {\n\t\t// Regular load workflow uses blobId === documentID to indicate \"latest\".\n\t\tif (blobid !== this.documentId && blobid) {\n\t\t\t// FluidFetch & FluidDebugger tools use empty sting to query for versions\n\t\t\t// In such case we need to make a call against SPO to give full picture to the tool.\n\t\t\t// Otherwise, each commit calls getVersions but odsp doesn't have a history for each commit\n\t\t\t// return the blobid as is\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: blobid,\n\t\t\t\t\ttreeId: undefined!,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\t// Can't really make a call if we do not have URL\n\t\tif (!this.snapshotUrl) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// If count is one, we can use the trees/latest API, which returns the latest version and trees in a single request for better performance\n\t\tif (count === 1 && (blobid === null || blobid === this.documentId)) {\n\t\t\tconst hostSnapshotOptions = this.hostPolicy.snapshotOptions;\n\t\t\tconst odspSnapshotCacheValue: ISnapshotContents = await PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{ eventName: \"ObtainSnapshot\", fetchSource },\n\t\t\t\tasync (event: PerformanceEvent) => {\n\t\t\t\t\tconst props: GetVersionsTelemetryProps = {};\n\t\t\t\t\tlet retrievedSnapshot:\n\t\t\t\t\t\t| ISnapshotContents\n\t\t\t\t\t\t| IPrefetchSnapshotContents\n\t\t\t\t\t\t| undefined;\n\n\t\t\t\t\tlet method: string;\n\t\t\t\t\tlet prefetchWaitStartTime: number = performance.now();\n\t\t\t\t\tif (fetchSource === FetchSource.noCache) {\n\t\t\t\t\t\tretrievedSnapshot = await this.fetchSnapshot(\n\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tmethod = \"networkOnly\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Here's the logic to grab the persistent cache snapshot implemented by the host\n\t\t\t\t\t\t// Epoch tracker is responsible for communicating with the persistent cache, handling epochs and cache versions\n\t\t\t\t\t\tconst cachedSnapshotP: Promise<ISnapshotContents | undefined> =\n\t\t\t\t\t\t\tthis.epochTracker\n\t\t\t\t\t\t\t\t.get(createCacheSnapshotKey(this.odspResolvedUrl))\n\t\t\t\t\t\t\t\t.then(async (snapshotCachedEntry: ISnapshotCachedEntry) => {\n\t\t\t\t\t\t\t\t\tif (snapshotCachedEntry !== undefined) {\n\t\t\t\t\t\t\t\t\t\t// If the cached entry does not contain the entry time, then assign it a default of 30 days old.\n\t\t\t\t\t\t\t\t\t\tconst age =\n\t\t\t\t\t\t\t\t\t\t\tDate.now() -\n\t\t\t\t\t\t\t\t\t\t\t(snapshotCachedEntry.cacheEntryTime ??\n\t\t\t\t\t\t\t\t\t\t\t\tDate.now() - 30 * 24 * 60 * 60 * 1000);\n\n\t\t\t\t\t\t\t\t\t\t// In order to decrease the number of times we have to execute a snapshot refresh,\n\t\t\t\t\t\t\t\t\t\t// if this is the summarizer and we have a cache entry but it is past the defaultSummarizerCacheExpiryTimeout,\n\t\t\t\t\t\t\t\t\t\t// force the network retrieval instead as there might be a more recent snapshot available.\n\t\t\t\t\t\t\t\t\t\t// See: https://github.com/microsoft/FluidFramework/issues/8995 for additional information.\n\t\t\t\t\t\t\t\t\t\tif (this.hostPolicy.summarizerClient) {\n\t\t\t\t\t\t\t\t\t\t\tif (age > defaultSummarizerCacheExpiryTimeout) {\n\t\t\t\t\t\t\t\t\t\t\t\tprops.cacheSummarizerExpired = true;\n\t\t\t\t\t\t\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tprops.cacheSummarizerExpired = false;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Record the cache age\n\t\t\t\t\t\t\t\t\t\tprops.cacheEntryAge = age;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\treturn snapshotCachedEntry;\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// Based on the concurrentSnapshotFetch policy:\n\t\t\t\t\t\t// Either retrieve both the network and cache snapshots concurrently and pick the first to return,\n\t\t\t\t\t\t// or grab the cache value and then the network value if the cache value returns undefined.\n\t\t\t\t\t\t// For summarizer which could call this during refreshing of summary parent, always use the cache\n\t\t\t\t\t\t// first. Also for other clients, if it is not critical path which is determined by firstVersionCall,\n\t\t\t\t\t\t// then also check the cache first.\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tthis.firstVersionCall &&\n\t\t\t\t\t\t\tthis.hostPolicy.concurrentSnapshotFetch &&\n\t\t\t\t\t\t\t!this.hostPolicy.summarizerClient\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tconst networkSnapshotP = this.fetchSnapshot(\n\t\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// Ensure that failures on both paths are ignored initially.\n\t\t\t\t\t\t\t// I.e. if cache fails for some reason, we will proceed with network result.\n\t\t\t\t\t\t\t// And vice versa - if (for example) client is offline and network request fails first, we\n\t\t\t\t\t\t\t// do want to attempt to succeed with cached data!\n\t\t\t\t\t\t\tconst promiseRaceWinner = await promiseRaceWithWinner([\n\t\t\t\t\t\t\t\tcachedSnapshotP.catch(() => undefined),\n\t\t\t\t\t\t\t\tnetworkSnapshotP.catch(() => undefined),\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\tretrievedSnapshot = promiseRaceWinner.value;\n\t\t\t\t\t\t\tmethod = promiseRaceWinner.index === 0 ? \"cache\" : \"network\";\n\n\t\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t\t// if network failed -> wait for cache ( then return network failure)\n\t\t\t\t\t\t\t\t// If cache returned empty or failed -> wait for network (success of failure)\n\t\t\t\t\t\t\t\tif (promiseRaceWinner.index === 1) {\n\t\t\t\t\t\t\t\t\tretrievedSnapshot = await cachedSnapshotP;\n\t\t\t\t\t\t\t\t\tmethod = \"cache\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t\t\tretrievedSnapshot = await networkSnapshotP;\n\t\t\t\t\t\t\t\t\tmethod = \"network\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Note: There's a race condition here - another caller may come past the undefined check\n\t\t\t\t\t\t\t// while the first caller is awaiting later async code in this block.\n\n\t\t\t\t\t\t\tretrievedSnapshot = await cachedSnapshotP;\n\n\t\t\t\t\t\t\tmethod = retrievedSnapshot !== undefined ? \"cache\" : \"network\";\n\n\t\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t\tprefetchWaitStartTime = performance.now();\n\t\t\t\t\t\t\t\tretrievedSnapshot = await this.fetchSnapshot(\n\t\t\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (method === \"network\") {\n\t\t\t\t\t\tprops.cacheEntryAge = undefined;\n\t\t\t\t\t}\n\t\t\t\t\tconst prefetchStartTime: number | undefined = (\n\t\t\t\t\t\tretrievedSnapshot as IPrefetchSnapshotContents\n\t\t\t\t\t).prefetchStartTime;\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tmethod,\n\t\t\t\t\t\tavoidPrefetchSnapshotCache: this.hostPolicy.avoidPrefetchSnapshotCache,\n\t\t\t\t\t\tprefetchSavedDuration:\n\t\t\t\t\t\t\tprefetchStartTime !== undefined && method !== \"cache\"\n\t\t\t\t\t\t\t\t? prefetchWaitStartTime - prefetchStartTime\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t});\n\t\t\t\t\treturn retrievedSnapshot;\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Don't override ops which were fetched during initial load, since we could still need them.\n\t\t\tconst id = this.initializeFromSnapshot(odspSnapshotCacheValue, this.firstVersionCall);\n\t\t\tthis.firstVersionCall = false;\n\n\t\t\treturn id ? [{ id, treeId: undefined! }] : [];\n\t\t}\n\n\t\treturn getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"GetVersions\");\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\t`${this.snapshotUrl}/versions?top=${count}`,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\n\t\t\t// Fetch the latest snapshot versions for the document\n\t\t\tconst response = await PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"getVersions\",\n\t\t\t\t\theaders: Object.keys(headers).length !== 0 ? true : undefined,\n\t\t\t\t},\n\t\t\t\tasync () =>\n\t\t\t\t\tthis.epochTracker.fetchAndParseAsJSON<IDocumentStorageGetVersionsResponse>(\n\t\t\t\t\t\turl,\n\t\t\t\t\t\t{ headers },\n\t\t\t\t\t\t\"versions\",\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tconst versionsResponse = response.content;\n\t\t\tif (!versionsResponse) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\"No response from /versions endpoint\",\n\t\t\t\t\tDriverErrorType.genericNetworkError,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!Array.isArray(versionsResponse.value)) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\"Incorrect response from /versions endpoint, expected an array\",\n\t\t\t\t\tDriverErrorType.genericNetworkError,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn versionsResponse.value.map((version) => {\n\t\t\t\treturn {\n\t\t\t\t\tid: version.id,\n\t\t\t\t\ttreeId: undefined!,\n\t\t\t\t};\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate async fetchSnapshot(\n\t\thostSnapshotOptions: ISnapshotOptions | undefined,\n\t\tscenarioName?: string,\n\t) {\n\t\treturn this.fetchSnapshotCore(hostSnapshotOptions, scenarioName).catch((error) => {\n\t\t\t// Issue #5895:\n\t\t\t// If we are offline, this error is retryable. But that means that RetriableDocumentStorageService\n\t\t\t// will run in circles calling getSnapshotTree, which would result in OdspDocumentStorageService class\n\t\t\t// going getVersions / individual blob download path. This path is very slow, and will not work with\n\t\t\t// delay-loaded data stores and ODSP storage deleting old snapshots and blobs.\n\t\t\tif (typeof error === \"object\" && error !== null) {\n\t\t\t\terror.canRetry = false;\n\t\t\t}\n\t\t\tthrow error;\n\t\t});\n\t}\n\n\tprivate async fetchSnapshotCore(\n\t\thostSnapshotOptions: ISnapshotOptions | undefined,\n\t\tscenarioName?: string,\n\t): Promise<ISnapshotContents | IPrefetchSnapshotContents> {\n\t\t// Don't look into cache, if the host specifically tells us so.\n\t\tif (!this.hostPolicy.avoidPrefetchSnapshotCache) {\n\t\t\tconst prefetchCacheKey = getKeyForCacheEntry(\n\t\t\t\tcreateCacheSnapshotKey(this.odspResolvedUrl),\n\t\t\t);\n\t\t\tconst result = await this.cache.snapshotPrefetchResultCache\n\t\t\t\t?.get(prefetchCacheKey)\n\t\t\t\t?.then(async (response) => {\n\t\t\t\t\t// Validate the epoch from the prefetched snapshot result.\n\t\t\t\t\tawait this.epochTracker.validateEpoch(response.fluidEpoch, \"treesLatest\");\n\t\t\t\t\treturn response;\n\t\t\t\t})\n\t\t\t\t.catch(async (err) => {\n\t\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"PrefetchSnapshotError\",\n\t\t\t\t\t\t\tconcurrentSnapshotFetch: this.hostPolicy.concurrentSnapshotFetch,\n\t\t\t\t\t\t},\n\t\t\t\t\t\terr,\n\t\t\t\t\t);\n\t\t\t\t\treturn undefined;\n\t\t\t\t});\n\t\t\t// If the prefetch call, is successful, then return the contents otherwise as backup for now, just\n\t\t\t// proceed with the old snapshot fetch flow.\n\t\t\tif (result !== undefined) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t\tconst snapshotOptions: ISnapshotOptions = {\n\t\t\tmds: this.maxSnapshotSizeLimit,\n\t\t\t...hostSnapshotOptions,\n\t\t\ttimeout: hostSnapshotOptions?.timeout\n\t\t\t\t? Math.min(hostSnapshotOptions.timeout, this.maxSnapshotFetchTimeout)\n\t\t\t\t: this.maxSnapshotFetchTimeout,\n\t\t};\n\n\t\t// No limit on size of snapshot or time to fetch, as otherwise we fail all clients to summarize\n\t\tif (this.hostPolicy.summarizerClient) {\n\t\t\tsnapshotOptions.mds = undefined;\n\t\t\tsnapshotOptions.timeout = undefined;\n\t\t}\n\n\t\tconst snapshotDownloader = async (\n\t\t\tfinalOdspResolvedUrl: IOdspResolvedUrl,\n\t\t\tstorageToken: string,\n\t\t\toptions: ISnapshotOptions | undefined,\n\t\t\tcontroller?: AbortController,\n\t\t) => {\n\t\t\treturn downloadSnapshot(\n\t\t\t\tfinalOdspResolvedUrl,\n\t\t\t\tstorageToken,\n\t\t\t\tthis.logger,\n\t\t\t\toptions,\n\t\t\t\tthis.snapshotFormatFetchType,\n\t\t\t\tcontroller,\n\t\t\t\tthis.epochTracker,\n\t\t\t\tscenarioName,\n\t\t\t);\n\t\t};\n\t\tconst putInCache = async (valueWithEpoch: IVersionedValueWithEpoch) => {\n\t\t\treturn this.cache.persistedCache.put(\n\t\t\t\tcreateCacheSnapshotKey(this.odspResolvedUrl),\n\t\t\t\t// Epoch tracker will add the epoch and version to the value here. So just send value to cache.\n\t\t\t\tvalueWithEpoch.value,\n\t\t\t);\n\t\t};\n\t\tconst removeEntries = async () => this.cache.persistedCache.removeEntries();\n\t\ttry {\n\t\t\tconst odspSnapshot = await fetchSnapshotWithRedeem(\n\t\t\t\tthis.odspResolvedUrl,\n\t\t\t\tthis.getStorageToken,\n\t\t\t\tsnapshotOptions,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\tthis.logger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t\tputInCache,\n\t\t\t\tremoveEntries,\n\t\t\t\tthis.hostPolicy.enableRedeemFallback,\n\t\t\t);\n\t\t\treturn odspSnapshot;\n\t\t} catch (error: any) {\n\t\t\tconst errorType = error.errorType;\n\t\t\t// If the snapshot size is too big and the host specified the size limitation(specified in hostSnapshotOptions), then don't try to fetch the snapshot again.\n\t\t\tif (\n\t\t\t\terrorType === OdspErrorType.snapshotTooBig &&\n\t\t\t\thostSnapshotOptions?.mds !== undefined &&\n\t\t\t\tthis.hostPolicy.summarizerClient !== true\n\t\t\t) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\t// If the first snapshot request was with blobs and we either timed out or the size was too big, then try to fetch without blobs.\n\t\t\tif (\n\t\t\t\t(errorType === OdspErrorType.snapshotTooBig ||\n\t\t\t\t\terrorType === OdspErrorType.fetchTimeout) &&\n\t\t\t\tsnapshotOptions.blobs\n\t\t\t) {\n\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\teventName: \"TreeLatest_SecondCall\",\n\t\t\t\t\terrorType,\n\t\t\t\t});\n\t\t\t\tconst snapshotOptionsWithoutBlobs: ISnapshotOptions = {\n\t\t\t\t\t...snapshotOptions,\n\t\t\t\t\tblobs: 0,\n\t\t\t\t\tmds: undefined,\n\t\t\t\t\ttimeout: undefined,\n\t\t\t\t};\n\t\t\t\tconst odspSnapshot = await fetchSnapshotWithRedeem(\n\t\t\t\t\tthis.odspResolvedUrl,\n\t\t\t\t\tthis.getStorageToken,\n\t\t\t\t\tsnapshotOptionsWithoutBlobs,\n\t\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tsnapshotDownloader,\n\t\t\t\t\tputInCache,\n\t\t\t\t\tremoveEntries,\n\t\t\t\t\tthis.hostPolicy.enableRedeemFallback,\n\t\t\t\t);\n\t\t\t\treturn odspSnapshot;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic async uploadSummaryWithContext(\n\t\tsummary: api.ISummaryTree,\n\t\tcontext: ISummaryContext,\n\t): Promise<string> {\n\t\tthis.checkSnapshotUrl();\n\n\t\t// Set the module promise right away, so as to not call it twice.\n\t\tif (this.summaryModuleP === undefined) {\n\t\t\tthis.summaryModuleP = this.getDelayLoadedSummaryManager();\n\t\t}\n\n\t\t// Enable flushing only if we have single commit summary and this is not the initial summary for an empty file\n\t\tif (\".protocol\" in summary.tree && context.ackHandle !== undefined) {\n\t\t\tlet retry = 1;\n\t\t\tfor (;;) {\n\t\t\t\tconst result = await this.flushCallback();\n\t\t\t\tconst seq = result.lastPersistedSequenceNumber;\n\t\t\t\tif (seq !== undefined && seq >= context.referenceSequenceNumber) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (retry > 3) {\n\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\teventName: \"FlushFailure\",\n\t\t\t\t\t\t...result,\n\t\t\t\t\t\tretry,\n\t\t\t\t\t\treferenceSequenceNumber: context.referenceSequenceNumber,\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\teventName: \"FlushExtraCall\",\n\t\t\t\t\t...result,\n\t\t\t\t\tretry,\n\t\t\t\t\treferenceSequenceNumber: context.referenceSequenceNumber,\n\t\t\t\t});\n\n\t\t\t\tretry++;\n\t\t\t\tawait delay(1000 * (result.retryAfter ?? 1));\n\t\t\t}\n\t\t}\n\n\t\tif (!this.odspSummaryUploadManager) {\n\t\t\tthis.odspSummaryUploadManager = await this.summaryModuleP\n\t\t\t\t.then(async (m) => {\n\t\t\t\t\tthis.odspSummaryModuleLoaded = true;\n\t\t\t\t\treturn m;\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tthis.odspSummaryModuleLoaded = false;\n\t\t\t\t\tthrow error;\n\t\t\t\t});\n\t\t}\n\n\t\tassert(\n\t\t\tthis.odspSummaryUploadManager !== undefined,\n\t\t\t0x56e /* summary upload manager should have been initialized */,\n\t\t);\n\t\tconst id = await this.odspSummaryUploadManager.writeSummaryTree(summary, context);\n\t\treturn id;\n\t}\n\n\tprivate async getDelayLoadedSummaryManager() {\n\t\tassert(this.odspSummaryModuleLoaded === false, 0x56f /* Should be loaded only once */);\n\t\tconst module = await import(\n\t\t\t/* webpackChunkName: \"summaryModule\" */ \"./odspSummaryUploadManager\"\n\t\t)\n\t\t\t.then((m) => {\n\t\t\t\tthis.logger.sendTelemetryEvent({ eventName: \"SummaryModuleLoaded\" });\n\t\t\t\treturn m;\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.logger.sendErrorEvent({ eventName: \"SummaryModuleLoadFailed\" }, error);\n\t\t\t\tthrow error;\n\t\t\t});\n\t\tthis.odspSummaryUploadManager = new module.OdspSummaryUploadManager(\n\t\t\tthis.odspResolvedUrl.endpoints.snapshotStorageUrl,\n\t\t\tthis.getStorageToken,\n\t\t\tthis.logger,\n\t\t\tthis.epochTracker,\n\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\tthis.relayServiceTenantAndSessionId,\n\t\t);\n\t\treturn this.odspSummaryUploadManager;\n\t}\n\n\tprivate checkSnapshotUrl() {\n\t\tif (!this.snapshotUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no snapshot url was available\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate checkAttachmentPOSTUrl() {\n\t\tif (!this.attachmentPOSTUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no attachment POST url was available\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate checkAttachmentGETUrl() {\n\t\tif (!this.attachmentGETUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no attachment GET url was available\",\n\t\t\t\tDriverErrorType.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprotected async fetchTreeFromSnapshot(\n\t\tid: string,\n\t\tscenarioName?: string,\n\t): Promise<api.ISnapshotTree | undefined> {\n\t\treturn getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"ReadCommit\");\n\t\t\tconst snapshotDownloader = async (\n\t\t\t\turl: string,\n\t\t\t\tfetchOptions: { [index: string]: any },\n\t\t\t) => {\n\t\t\t\treturn this.epochTracker.fetchAndParseAsJSON(\n\t\t\t\t\turl,\n\t\t\t\t\tfetchOptions,\n\t\t\t\t\t\"snapshotTree\",\n\t\t\t\t\tundefined,\n\t\t\t\t\tscenarioName,\n\t\t\t\t);\n\t\t\t};\n\t\t\tconst snapshot = await fetchSnapshot(\n\t\t\t\tthis.snapshotUrl!,\n\t\t\t\tstorageToken,\n\t\t\t\tid,\n\t\t\t\tthis.fetchFullSnapshot,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\tthis.logger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t);\n\t\t\tlet treeId = \"\";\n\t\t\tif (snapshot.snapshotTree) {\n\t\t\t\tassert(\n\t\t\t\t\tsnapshot.snapshotTree.id !== undefined,\n\t\t\t\t\t0x222 /* \"Root tree should contain the id!!\" */,\n\t\t\t\t);\n\t\t\t\ttreeId = snapshot.snapshotTree.id;\n\t\t\t\tthis.setRootTree(treeId, snapshot.snapshotTree);\n\t\t\t}\n\t\t\tif (snapshot.blobs) {\n\t\t\t\tthis.initBlobsCache(snapshot.blobs);\n\t\t\t}\n\t\t\t// If the version id doesn't match with the id of the tree, then use the id of first tree which in that case\n\t\t\t// will be the actual id of tree to be fetched.\n\t\t\treturn this.commitCache.get(id) ?? this.commitCache.get(treeId);\n\t\t});\n\t}\n}\n"]}
|
package/lib/odspUtils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspUtils.d.ts","sourceRoot":"","sources":["../src/odspUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAChB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAmB,MAAM,oCAAoC,CAAC;AAoBnF,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EAIjB,6BAA6B,EAC7B,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,WAAW,EAEX,+BAA+B,EAC/B,aAAa,EACb,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAGjF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,eAAO,MAAM,iCAAiC,sCAAsC,CAAC;AAErF,4DAA4D;AAC5D,eAAO,MAAM,SAAS,QAAS,MAAM,WAAwB,CAAC;AAE9D,MAAM,WAAW,aAAa,CAAC,CAAC;IAC/B,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,UAAU,EAAE,oBAAoB,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAoB,SAAQ,iBAAiB;IAC7D,2DAA2D;IAC3D,aAAa,CAAC,EAAE,GAAG,CAAC;CACpB;AAUD;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAAC,CAAC,EAClD,GAAG,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,CAAC,CAAC,cAqBjD;AAED,wBAAsB,WAAW,CAChC,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,GAAG,SAAS,GAClC,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"odspUtils.d.ts","sourceRoot":"","sources":["../src/odspUtils.ts"],"names":[],"mappings":"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"}
|
package/lib/odspUtils.js
CHANGED
|
@@ -70,9 +70,14 @@ export async function fetchHelper(requestInfo, requestInit) {
|
|
|
70
70
|
};
|
|
71
71
|
}, (error) => {
|
|
72
72
|
const online = isOnline();
|
|
73
|
-
|
|
73
|
+
// The error message may not be suitable to log for privacy reasons, so tag it as such
|
|
74
|
+
const taggedErrorMessage = {
|
|
75
|
+
value: `${error}`,
|
|
76
|
+
tag: TelemetryDataTag.UserData,
|
|
77
|
+
};
|
|
78
|
+
// After redacting URLs we believe the error message is safe to log
|
|
74
79
|
const urlRegex = /((http|https):\/\/(\S*))/i;
|
|
75
|
-
const redactedErrorText =
|
|
80
|
+
const redactedErrorText = taggedErrorMessage.value.replace(urlRegex, "REDACTED_URL");
|
|
76
81
|
// This error is thrown by fetch() when AbortSignal is provided and it gets cancelled
|
|
77
82
|
if (error.name === "AbortError") {
|
|
78
83
|
throw new RetryableError("Fetch Timeout (AbortError)", OdspErrorType.fetchTimeout, {
|
|
@@ -80,21 +85,18 @@ export async function fetchHelper(requestInfo, requestInit) {
|
|
|
80
85
|
});
|
|
81
86
|
}
|
|
82
87
|
// TCP/IP timeout
|
|
83
|
-
if (
|
|
88
|
+
if (redactedErrorText.includes("ETIMEDOUT")) {
|
|
84
89
|
throw new RetryableError("Fetch Timeout (ETIMEDOUT)", OdspErrorType.fetchTimeout, {
|
|
85
90
|
driverVersion,
|
|
86
91
|
});
|
|
87
92
|
}
|
|
88
|
-
// WARNING: Do not log error object itself or any of its properties!
|
|
89
|
-
// It could contain PII, like URI in message itself, or token in properties.
|
|
90
|
-
// It is also non-serializable object due to circular references.
|
|
91
93
|
// eslint-disable-next-line unicorn/prefer-ternary
|
|
92
94
|
if (online === OnlineStatus.Offline) {
|
|
93
95
|
throw new RetryableError(
|
|
94
96
|
// pre-0.58 error message prefix: Offline
|
|
95
97
|
`ODSP fetch failure (Offline): ${redactedErrorText}`, DriverErrorType.offlineError, {
|
|
96
98
|
driverVersion,
|
|
97
|
-
rawErrorMessage:
|
|
99
|
+
rawErrorMessage: taggedErrorMessage,
|
|
98
100
|
});
|
|
99
101
|
}
|
|
100
102
|
else {
|
|
@@ -104,7 +106,7 @@ export async function fetchHelper(requestInfo, requestInit) {
|
|
|
104
106
|
// pre-0.58 error message prefix: Fetch error
|
|
105
107
|
`ODSP fetch failure: ${redactedErrorText}`, DriverErrorType.fetchFailure, {
|
|
106
108
|
driverVersion,
|
|
107
|
-
rawErrorMessage:
|
|
109
|
+
rawErrorMessage: taggedErrorMessage,
|
|
108
110
|
});
|
|
109
111
|
}
|
|
110
112
|
});
|
package/lib/odspUtils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspUtils.js","sourceRoot":"","sources":["../src/odspUtils.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 {\n\tITelemetryProperties,\n\tITelemetryBaseLogger,\n\tITelemetryLogger,\n} from \"@fluidframework/common-definitions\";\nimport { IResolvedUrl, DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport {\n\tisOnline,\n\tOnlineStatus,\n\tRetryableError,\n\tNonRetryableError,\n\tNetworkErrorBasic,\n} from \"@fluidframework/driver-utils\";\nimport { assert, performance } from \"@fluidframework/common-utils\";\nimport {\n\tChildLogger,\n\tPerformanceEvent,\n\tTelemetryDataTag,\n\twrapError,\n} from \"@fluidframework/telemetry-utils\";\nimport {\n\tfetchIncorrectResponse,\n\tthrowOdspNetworkError,\n\tgetSPOAndGraphRequestIdsFromResponse,\n} from \"@fluidframework/odsp-doclib-utils\";\nimport {\n\tIOdspResolvedUrl,\n\tTokenFetchOptions,\n\tOdspErrorType,\n\ttokenFromResponse,\n\tisTokenFromCache,\n\tOdspResourceTokenFetchOptions,\n\tShareLinkTypes,\n\tISharingLinkKind,\n\tTokenFetcher,\n\tICacheEntry,\n\tsnapshotKey,\n\tInstrumentedStorageTokenFetcher,\n\tIOdspUrlParts,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { fetch } from \"./fetch\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\nimport { IOdspSnapshot } from \"./contracts\";\n\nexport const getWithRetryForTokenRefreshRepeat = \"getWithRetryForTokenRefreshRepeat\";\n\n/** Parse the given url and return the origin (host name) */\nexport const getOrigin = (url: string) => new URL(url).origin;\n\nexport interface IOdspResponse<T> {\n\tcontent: T;\n\theaders: Map<string, string>;\n\tpropsToLog: ITelemetryProperties;\n\tduration: number;\n}\n\nexport interface TokenFetchOptionsEx extends TokenFetchOptions {\n\t/** previous error we hit in getWithRetryForTokenRefresh */\n\tpreviousError?: any;\n}\n\nfunction headersToMap(headers: Headers) {\n\tconst newHeaders = new Map<string, string>();\n\tfor (const [key, value] of headers.entries()) {\n\t\tnewHeaders.set(key, value);\n\t}\n\treturn newHeaders;\n}\n\n/**\n * This API should be used with pretty much all network calls (fetch, webSocket connection) in order\n * to correctly handle expired tokens. It relies on callback fetching token, and be able to refetch\n * token on failure. Only specific cases get retry call with refresh = true, all other / unknown errors\n * simply propagate to caller\n */\nexport async function getWithRetryForTokenRefresh<T>(\n\tget: (options: TokenFetchOptionsEx) => Promise<T>,\n) {\n\treturn get({ refresh: false }).catch(async (e) => {\n\t\tconst options: TokenFetchOptionsEx = { refresh: true, previousError: e };\n\t\tswitch (e.errorType) {\n\t\t\t// If the error is 401 or 403 refresh the token and try once more.\n\t\t\tcase DriverErrorType.authorizationError:\n\t\t\t\treturn get({ ...options, claims: e.claims, tenantId: e.tenantId });\n\n\t\t\tcase DriverErrorType.incorrectServerResponse: // some error on the wire, retry once\n\t\t\tcase OdspErrorType.fetchTokenError: // If the token was null, then retry once.\n\t\t\t\treturn get(options);\n\n\t\t\tdefault:\n\t\t\t\t// Caller may determine that it wants one retry\n\t\t\t\tif (e[getWithRetryForTokenRefreshRepeat] === true) {\n\t\t\t\t\treturn get(options);\n\t\t\t\t}\n\t\t\t\tthrow e;\n\t\t}\n\t});\n}\n\nexport async function fetchHelper(\n\trequestInfo: RequestInfo,\n\trequestInit: RequestInit | undefined,\n): Promise<IOdspResponse<Response>> {\n\tconst start = performance.now();\n\n\t// Node-fetch and dom have conflicting typing, force them to work by casting for now\n\treturn fetch(requestInfo, requestInit).then(\n\t\tasync (fetchResponse) => {\n\t\t\tconst response = fetchResponse as any as Response;\n\t\t\t// Let's assume we can retry.\n\t\t\tif (!response) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t// pre-0.58 error message: No response from fetch call\n\t\t\t\t\t\"No response from ODSP fetch call\",\n\t\t\t\t\tDriverErrorType.incorrectServerResponse,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!response.ok || response.status < 200 || response.status >= 300) {\n\t\t\t\tthrowOdspNetworkError(\n\t\t\t\t\t// pre-0.58 error message prefix: odspFetchError\n\t\t\t\t\t`ODSP fetch error [${response.status}]`,\n\t\t\t\t\tresponse.status,\n\t\t\t\t\tresponse,\n\t\t\t\t\tawait response.text(),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst headers = headersToMap(response.headers);\n\t\t\treturn {\n\t\t\t\tcontent: response,\n\t\t\t\theaders,\n\t\t\t\tpropsToLog: getSPOAndGraphRequestIdsFromResponse(headers),\n\t\t\t\tduration: performance.now() - start,\n\t\t\t};\n\t\t},\n\t\t(error) => {\n\t\t\tconst online = isOnline();\n\t\t\tconst errorText = `${error}`;\n\t\t\tconst urlRegex = /((http|https):\\/\\/(\\S*))/i;\n\t\t\tconst redactedErrorText = errorText.replace(urlRegex, \"REDACTED_URL\");\n\t\t\t// This error is thrown by fetch() when AbortSignal is provided and it gets cancelled\n\t\t\tif (error.name === \"AbortError\") {\n\t\t\t\tthrow new RetryableError(\"Fetch Timeout (AbortError)\", OdspErrorType.fetchTimeout, {\n\t\t\t\t\tdriverVersion,\n\t\t\t\t});\n\t\t\t}\n\t\t\t// TCP/IP timeout\n\t\t\tif (errorText.includes(\"ETIMEDOUT\")) {\n\t\t\t\tthrow new RetryableError(\"Fetch Timeout (ETIMEDOUT)\", OdspErrorType.fetchTimeout, {\n\t\t\t\t\tdriverVersion,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// WARNING: Do not log error object itself or any of its properties!\n\t\t\t// It could contain PII, like URI in message itself, or token in properties.\n\t\t\t// It is also non-serializable object due to circular references.\n\t\t\t// eslint-disable-next-line unicorn/prefer-ternary\n\t\t\tif (online === OnlineStatus.Offline) {\n\t\t\t\tthrow new RetryableError(\n\t\t\t\t\t// pre-0.58 error message prefix: Offline\n\t\t\t\t\t`ODSP fetch failure (Offline): ${redactedErrorText}`,\n\t\t\t\t\tDriverErrorType.offlineError,\n\t\t\t\t\t{\n\t\t\t\t\t\tdriverVersion,\n\t\t\t\t\t\trawErrorMessage: { value: errorText, tag: TelemetryDataTag.UserData },\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// It is perhaps still possible that this is due to being offline, the error does not reveal enough\n\t\t\t\t// information to conclude. Could also be DNS errors, malformed fetch request, CSP violation, etc.\n\t\t\t\tthrow new RetryableError(\n\t\t\t\t\t// pre-0.58 error message prefix: Fetch error\n\t\t\t\t\t`ODSP fetch failure: ${redactedErrorText}`,\n\t\t\t\t\tDriverErrorType.fetchFailure,\n\t\t\t\t\t{\n\t\t\t\t\t\tdriverVersion,\n\t\t\t\t\t\trawErrorMessage: { value: errorText, tag: TelemetryDataTag.UserData },\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t);\n}\n\n/**\n * A utility function to fetch and parse as JSON with support for retries\n * @param requestInfo - fetch requestInfo, can be a string\n * @param requestInit - fetch requestInit\n */\nexport async function fetchArray(\n\trequestInfo: RequestInfo,\n\trequestInit: RequestInit | undefined,\n): Promise<IOdspResponse<ArrayBuffer>> {\n\tconst { content, headers, propsToLog, duration } = await fetchHelper(requestInfo, requestInit);\n\n\tconst arrayBuffer = await content.arrayBuffer();\n\tpropsToLog.bodySize = arrayBuffer.byteLength;\n\treturn {\n\t\theaders,\n\t\tcontent: arrayBuffer,\n\t\tpropsToLog,\n\t\tduration,\n\t};\n}\n\n/**\n * A utility function to fetch and parse as JSON with support for retries\n * @param requestInfo - fetch requestInfo, can be a string\n * @param requestInit - fetch requestInit\n */\nexport async function fetchAndParseAsJSONHelper<T>(\n\trequestInfo: RequestInfo,\n\trequestInit: RequestInit | undefined,\n): Promise<IOdspResponse<T>> {\n\tconst { content, headers, propsToLog, duration } = await fetchHelper(requestInfo, requestInit);\n\tlet text: string | undefined;\n\ttry {\n\t\ttext = await content.text();\n\t} catch (e) {\n\t\t// JSON.parse() can fail and message would container full request URI, including\n\t\t// tokens... It fails for me with \"Unexpected end of JSON input\" quite often - an attempt to download big file\n\t\t// (many ops) almost always ends up with this error - I'd guess 1% of op request end up here... It always\n\t\t// succeeds on retry.\n\t\t// So do not log error object itself.\n\t\tthrowOdspNetworkError(\n\t\t\t// pre-0.58 error message: errorWhileParsingFetchResponse\n\t\t\t\"Error while parsing fetch response\",\n\t\t\tfetchIncorrectResponse,\n\t\t\tcontent, // response\n\t\t\ttext,\n\t\t);\n\t}\n\n\tpropsToLog.bodySize = text.length;\n\tconst res = {\n\t\theaders,\n\t\tcontent: JSON.parse(text),\n\t\tpropsToLog,\n\t\tduration,\n\t};\n\treturn res;\n}\n\nexport interface IFileInfoBase {\n\ttype: \"New\" | \"Existing\";\n\tsiteUrl: string;\n\tdriveId: string;\n}\n\nexport interface INewFileInfo extends IFileInfoBase {\n\ttype: \"New\";\n\tfilename: string;\n\tfilePath: string;\n\t/**\n\t * application can request creation of a share link along with the creation of a new file\n\t * by passing in an optional param to specify the kind of sharing link\n\t * (at the time of adding this comment Sept/2021), odsp only supports csl\n\t * ShareLinkTypes will deprecated in future. Use ISharingLinkKind instead which specifies both\n\t * share link type and the role type.\n\t */\n\tcreateLinkType?: ShareLinkTypes | ISharingLinkKind;\n}\n\nexport interface IExistingFileInfo extends IFileInfoBase {\n\ttype: \"Existing\";\n\titemId: string;\n}\n\nexport function isNewFileInfo(\n\tfileInfo: INewFileInfo | IExistingFileInfo,\n): fileInfo is INewFileInfo {\n\treturn fileInfo.type === undefined || fileInfo.type === \"New\";\n}\n\nexport function getOdspResolvedUrl(resolvedUrl: IResolvedUrl): IOdspResolvedUrl {\n\tassert(\n\t\t(resolvedUrl as IOdspResolvedUrl).odspResolvedUrl === true,\n\t\t0x1de /* \"Not an ODSP resolved url\" */,\n\t);\n\treturn resolvedUrl as IOdspResolvedUrl;\n}\n\nexport const createOdspLogger = (logger?: ITelemetryBaseLogger) =>\n\tChildLogger.create(logger, \"OdspDriver\", {\n\t\tall: {\n\t\t\tdriverVersion,\n\t\t},\n\t});\n\nexport function evalBlobsAndTrees(snapshot: IOdspSnapshot) {\n\tlet numTrees = 0;\n\tlet numBlobs = 0;\n\tlet encodedBlobsSize = 0;\n\tlet decodedBlobsSize = 0;\n\tfor (const tree of snapshot.trees) {\n\t\tfor (const treeEntry of tree.entries) {\n\t\t\tif (treeEntry.type === \"blob\") {\n\t\t\t\tnumBlobs++;\n\t\t\t} else if (treeEntry.type === \"tree\") {\n\t\t\t\tnumTrees++;\n\t\t\t}\n\t\t}\n\t}\n\tif (snapshot.blobs !== undefined) {\n\t\tfor (const blob of snapshot.blobs) {\n\t\t\tdecodedBlobsSize += blob.size;\n\t\t\tencodedBlobsSize += blob.content.length;\n\t\t}\n\t}\n\treturn { numTrees, numBlobs, encodedBlobsSize, decodedBlobsSize };\n}\n\nexport function toInstrumentedOdspTokenFetcher(\n\tlogger: ITelemetryLogger,\n\tresolvedUrlParts: IOdspUrlParts,\n\ttokenFetcher: TokenFetcher<OdspResourceTokenFetchOptions>,\n\tthrowOnNullToken: boolean,\n): InstrumentedStorageTokenFetcher {\n\treturn async (\n\t\toptions: TokenFetchOptions,\n\t\tname: string,\n\t\talwaysRecordTokenFetchTelemetry: boolean = false,\n\t) => {\n\t\t// Telemetry note: if options.refresh is true, there is a potential perf issue:\n\t\t// Host should optimize and provide non-expired tokens on all critical paths.\n\t\t// Exceptions: race conditions around expiration, revoked tokens, host that does not care\n\t\t// (fluid-fetcher)\n\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\tlogger,\n\t\t\t{\n\t\t\t\teventName: `${name}_GetToken`,\n\t\t\t\tattempts: options.refresh ? 2 : 1,\n\t\t\t\thasClaims: !!options.claims,\n\t\t\t\thasTenantId: !!options.tenantId,\n\t\t\t},\n\t\t\tasync (event) =>\n\t\t\t\ttokenFetcher({\n\t\t\t\t\t...options,\n\t\t\t\t\t...resolvedUrlParts,\n\t\t\t\t}).then(\n\t\t\t\t\t(tokenResponse) => {\n\t\t\t\t\t\tconst token = tokenFromResponse(tokenResponse);\n\t\t\t\t\t\t// This event alone generates so many events that is materially impacts cost of telemetry\n\t\t\t\t\t\t// Thus do not report end event when it comes back quickly.\n\t\t\t\t\t\t// Note that most of the hosts do not report if result is comming from cache or not,\n\t\t\t\t\t\t// so we can't rely on that here. But always record if specified explicitly for cases such as\n\t\t\t\t\t\t// calling trees/latest during load.\n\t\t\t\t\t\tif (alwaysRecordTokenFetchTelemetry || event.duration >= 32) {\n\t\t\t\t\t\t\tevent.end({\n\t\t\t\t\t\t\t\tfromCache: isTokenFromCache(tokenResponse),\n\t\t\t\t\t\t\t\tisNull: token === null,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (token === null && throwOnNullToken) {\n\t\t\t\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\t\t\t// pre-0.58 error message: Token is null for ${name} call\n\t\t\t\t\t\t\t\t`The Host-provided token fetcher returned null`,\n\t\t\t\t\t\t\t\tOdspErrorType.fetchTokenError,\n\t\t\t\t\t\t\t\t{ method: name, driverVersion },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn token;\n\t\t\t\t\t},\n\t\t\t\t\t(error) => {\n\t\t\t\t\t\t// There is an important but unofficial contract here where token providers can set canRetry: true\n\t\t\t\t\t\t// to hook into the driver's retry logic (e.g. the retry loop when initiating a connection)\n\t\t\t\t\t\tconst rawCanRetry = error?.canRetry;\n\t\t\t\t\t\tconst tokenError = wrapError(\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t\t(errorMessage) =>\n\t\t\t\t\t\t\t\tnew NetworkErrorBasic(\n\t\t\t\t\t\t\t\t\t`The Host-provided token fetcher threw an error`,\n\t\t\t\t\t\t\t\t\tOdspErrorType.fetchTokenError,\n\t\t\t\t\t\t\t\t\ttypeof rawCanRetry === \"boolean\"\n\t\t\t\t\t\t\t\t\t\t? rawCanRetry\n\t\t\t\t\t\t\t\t\t\t: false /* canRetry */,\n\t\t\t\t\t\t\t\t\t{ method: name, errorMessage, driverVersion },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthrow tokenError;\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t{ cancel: \"generic\" },\n\t\t);\n\t};\n}\n\nexport function createCacheSnapshotKey(odspResolvedUrl: IOdspResolvedUrl): ICacheEntry {\n\tconst cacheEntry: ICacheEntry = {\n\t\ttype: snapshotKey,\n\t\tkey: odspResolvedUrl.fileVersion ?? \"\",\n\t\tfile: {\n\t\t\tresolvedUrl: odspResolvedUrl,\n\t\t\tdocId: odspResolvedUrl.hashedDocumentId,\n\t\t},\n\t};\n\treturn cacheEntry;\n}\n\n// 80KB is the max body size that we can put in ump post body for server to be able to accept it.\n// Keeping it 78KB to be a little cautious. As per the telemetry 99p is less than 78KB.\nexport const maxUmpPostBodySize = 79872;\n\n/**\n * Build request parameters to request for the creation of a sharing link along with the creation of the file\n * through the /snapshot api call.\n * @param shareLinkType - Kind of sharing link requested\n * @returns A string of request parameters that can be concatenated with the base URI\n */\nexport function buildOdspShareLinkReqParams(\n\tshareLinkType: ShareLinkTypes | ISharingLinkKind | undefined,\n) {\n\tif (!shareLinkType) {\n\t\treturn;\n\t}\n\tconst scope = (shareLinkType as ISharingLinkKind).scope;\n\tif (!scope) {\n\t\treturn `createLinkType=${shareLinkType}`;\n\t}\n\tlet shareLinkRequestParams = `createLinkScope=${scope}`;\n\tconst role = (shareLinkType as ISharingLinkKind).role;\n\tshareLinkRequestParams = role\n\t\t? `${shareLinkRequestParams}&createLinkRole=${role}`\n\t\t: shareLinkRequestParams;\n\treturn shareLinkRequestParams;\n}\n\nexport function measure<T>(callback: () => T): [T, number] {\n\tconst start = performance.now();\n\tconst result = callback();\n\tconst time = performance.now() - start;\n\treturn [result, time];\n}\n\nexport async function measureP<T>(callback: () => Promise<T>): Promise<[T, number]> {\n\tconst start = performance.now();\n\tconst result = await callback();\n\tconst time = performance.now() - start;\n\treturn [result, time];\n}\n\nexport function validateMessages(\n\treason: string,\n\tmessages: ISequencedDocumentMessage[],\n\tfrom: number,\n\tlogger: ITelemetryLogger,\n) {\n\tif (messages.length !== 0) {\n\t\tconst start = messages[0].sequenceNumber;\n\t\tconst length = messages.length;\n\t\tconst last = messages[length - 1].sequenceNumber;\n\t\tif (start !== from) {\n\t\t\tlogger.sendErrorEvent({\n\t\t\t\teventName: \"OpsFetchViolation\",\n\t\t\t\treason,\n\t\t\t\tfrom,\n\t\t\t\tstart,\n\t\t\t\tlast,\n\t\t\t\tlength,\n\t\t\t});\n\t\t\tmessages.length = 0;\n\t\t}\n\t\tif (last + 1 !== from + length) {\n\t\t\tlogger.sendErrorEvent({\n\t\t\t\teventName: \"OpsFetchViolation\",\n\t\t\t\treason,\n\t\t\t\tfrom,\n\t\t\t\tstart,\n\t\t\t\tlast,\n\t\t\t\tlength,\n\t\t\t});\n\t\t\t// we can do better here by finding consecutive sub-block and return it\n\t\t\tmessages.length = 0;\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"odspUtils.js","sourceRoot":"","sources":["../src/odspUtils.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 {\n\tITelemetryProperties,\n\tITelemetryBaseLogger,\n\tITelemetryLogger,\n} from \"@fluidframework/common-definitions\";\nimport { IResolvedUrl, DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport {\n\tisOnline,\n\tOnlineStatus,\n\tRetryableError,\n\tNonRetryableError,\n\tNetworkErrorBasic,\n} from \"@fluidframework/driver-utils\";\nimport { assert, performance } from \"@fluidframework/common-utils\";\nimport {\n\tChildLogger,\n\tPerformanceEvent,\n\tTelemetryDataTag,\n\twrapError,\n} from \"@fluidframework/telemetry-utils\";\nimport {\n\tfetchIncorrectResponse,\n\tthrowOdspNetworkError,\n\tgetSPOAndGraphRequestIdsFromResponse,\n} from \"@fluidframework/odsp-doclib-utils\";\nimport {\n\tIOdspResolvedUrl,\n\tTokenFetchOptions,\n\tOdspErrorType,\n\ttokenFromResponse,\n\tisTokenFromCache,\n\tOdspResourceTokenFetchOptions,\n\tShareLinkTypes,\n\tISharingLinkKind,\n\tTokenFetcher,\n\tICacheEntry,\n\tsnapshotKey,\n\tInstrumentedStorageTokenFetcher,\n\tIOdspUrlParts,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { fetch } from \"./fetch\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\nimport { IOdspSnapshot } from \"./contracts\";\n\nexport const getWithRetryForTokenRefreshRepeat = \"getWithRetryForTokenRefreshRepeat\";\n\n/** Parse the given url and return the origin (host name) */\nexport const getOrigin = (url: string) => new URL(url).origin;\n\nexport interface IOdspResponse<T> {\n\tcontent: T;\n\theaders: Map<string, string>;\n\tpropsToLog: ITelemetryProperties;\n\tduration: number;\n}\n\nexport interface TokenFetchOptionsEx extends TokenFetchOptions {\n\t/** previous error we hit in getWithRetryForTokenRefresh */\n\tpreviousError?: any;\n}\n\nfunction headersToMap(headers: Headers) {\n\tconst newHeaders = new Map<string, string>();\n\tfor (const [key, value] of headers.entries()) {\n\t\tnewHeaders.set(key, value);\n\t}\n\treturn newHeaders;\n}\n\n/**\n * This API should be used with pretty much all network calls (fetch, webSocket connection) in order\n * to correctly handle expired tokens. It relies on callback fetching token, and be able to refetch\n * token on failure. Only specific cases get retry call with refresh = true, all other / unknown errors\n * simply propagate to caller\n */\nexport async function getWithRetryForTokenRefresh<T>(\n\tget: (options: TokenFetchOptionsEx) => Promise<T>,\n) {\n\treturn get({ refresh: false }).catch(async (e) => {\n\t\tconst options: TokenFetchOptionsEx = { refresh: true, previousError: e };\n\t\tswitch (e.errorType) {\n\t\t\t// If the error is 401 or 403 refresh the token and try once more.\n\t\t\tcase DriverErrorType.authorizationError:\n\t\t\t\treturn get({ ...options, claims: e.claims, tenantId: e.tenantId });\n\n\t\t\tcase DriverErrorType.incorrectServerResponse: // some error on the wire, retry once\n\t\t\tcase OdspErrorType.fetchTokenError: // If the token was null, then retry once.\n\t\t\t\treturn get(options);\n\n\t\t\tdefault:\n\t\t\t\t// Caller may determine that it wants one retry\n\t\t\t\tif (e[getWithRetryForTokenRefreshRepeat] === true) {\n\t\t\t\t\treturn get(options);\n\t\t\t\t}\n\t\t\t\tthrow e;\n\t\t}\n\t});\n}\n\nexport async function fetchHelper(\n\trequestInfo: RequestInfo,\n\trequestInit: RequestInit | undefined,\n): Promise<IOdspResponse<Response>> {\n\tconst start = performance.now();\n\n\t// Node-fetch and dom have conflicting typing, force them to work by casting for now\n\treturn fetch(requestInfo, requestInit).then(\n\t\tasync (fetchResponse) => {\n\t\t\tconst response = fetchResponse as any as Response;\n\t\t\t// Let's assume we can retry.\n\t\t\tif (!response) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t// pre-0.58 error message: No response from fetch call\n\t\t\t\t\t\"No response from ODSP fetch call\",\n\t\t\t\t\tDriverErrorType.incorrectServerResponse,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!response.ok || response.status < 200 || response.status >= 300) {\n\t\t\t\tthrowOdspNetworkError(\n\t\t\t\t\t// pre-0.58 error message prefix: odspFetchError\n\t\t\t\t\t`ODSP fetch error [${response.status}]`,\n\t\t\t\t\tresponse.status,\n\t\t\t\t\tresponse,\n\t\t\t\t\tawait response.text(),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst headers = headersToMap(response.headers);\n\t\t\treturn {\n\t\t\t\tcontent: response,\n\t\t\t\theaders,\n\t\t\t\tpropsToLog: getSPOAndGraphRequestIdsFromResponse(headers),\n\t\t\t\tduration: performance.now() - start,\n\t\t\t};\n\t\t},\n\t\t(error) => {\n\t\t\tconst online = isOnline();\n\n\t\t\t// The error message may not be suitable to log for privacy reasons, so tag it as such\n\t\t\tconst taggedErrorMessage = {\n\t\t\t\tvalue: `${error}`, // This uses toString for objects, which often results in `${error.name}: ${error.message}`\n\t\t\t\ttag: TelemetryDataTag.UserData,\n\t\t\t};\n\t\t\t// After redacting URLs we believe the error message is safe to log\n\t\t\tconst urlRegex = /((http|https):\\/\\/(\\S*))/i;\n\t\t\tconst redactedErrorText = taggedErrorMessage.value.replace(urlRegex, \"REDACTED_URL\");\n\n\t\t\t// This error is thrown by fetch() when AbortSignal is provided and it gets cancelled\n\t\t\tif (error.name === \"AbortError\") {\n\t\t\t\tthrow new RetryableError(\"Fetch Timeout (AbortError)\", OdspErrorType.fetchTimeout, {\n\t\t\t\t\tdriverVersion,\n\t\t\t\t});\n\t\t\t}\n\t\t\t// TCP/IP timeout\n\t\t\tif (redactedErrorText.includes(\"ETIMEDOUT\")) {\n\t\t\t\tthrow new RetryableError(\"Fetch Timeout (ETIMEDOUT)\", OdspErrorType.fetchTimeout, {\n\t\t\t\t\tdriverVersion,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// eslint-disable-next-line unicorn/prefer-ternary\n\t\t\tif (online === OnlineStatus.Offline) {\n\t\t\t\tthrow new RetryableError(\n\t\t\t\t\t// pre-0.58 error message prefix: Offline\n\t\t\t\t\t`ODSP fetch failure (Offline): ${redactedErrorText}`,\n\t\t\t\t\tDriverErrorType.offlineError,\n\t\t\t\t\t{\n\t\t\t\t\t\tdriverVersion,\n\t\t\t\t\t\trawErrorMessage: taggedErrorMessage,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// It is perhaps still possible that this is due to being offline, the error does not reveal enough\n\t\t\t\t// information to conclude. Could also be DNS errors, malformed fetch request, CSP violation, etc.\n\t\t\t\tthrow new RetryableError(\n\t\t\t\t\t// pre-0.58 error message prefix: Fetch error\n\t\t\t\t\t`ODSP fetch failure: ${redactedErrorText}`,\n\t\t\t\t\tDriverErrorType.fetchFailure,\n\t\t\t\t\t{\n\t\t\t\t\t\tdriverVersion,\n\t\t\t\t\t\trawErrorMessage: taggedErrorMessage,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t);\n}\n\n/**\n * A utility function to fetch and parse as JSON with support for retries\n * @param requestInfo - fetch requestInfo, can be a string\n * @param requestInit - fetch requestInit\n */\nexport async function fetchArray(\n\trequestInfo: RequestInfo,\n\trequestInit: RequestInit | undefined,\n): Promise<IOdspResponse<ArrayBuffer>> {\n\tconst { content, headers, propsToLog, duration } = await fetchHelper(requestInfo, requestInit);\n\n\tconst arrayBuffer = await content.arrayBuffer();\n\tpropsToLog.bodySize = arrayBuffer.byteLength;\n\treturn {\n\t\theaders,\n\t\tcontent: arrayBuffer,\n\t\tpropsToLog,\n\t\tduration,\n\t};\n}\n\n/**\n * A utility function to fetch and parse as JSON with support for retries\n * @param requestInfo - fetch requestInfo, can be a string\n * @param requestInit - fetch requestInit\n */\nexport async function fetchAndParseAsJSONHelper<T>(\n\trequestInfo: RequestInfo,\n\trequestInit: RequestInit | undefined,\n): Promise<IOdspResponse<T>> {\n\tconst { content, headers, propsToLog, duration } = await fetchHelper(requestInfo, requestInit);\n\tlet text: string | undefined;\n\ttry {\n\t\ttext = await content.text();\n\t} catch (e) {\n\t\t// JSON.parse() can fail and message would container full request URI, including\n\t\t// tokens... It fails for me with \"Unexpected end of JSON input\" quite often - an attempt to download big file\n\t\t// (many ops) almost always ends up with this error - I'd guess 1% of op request end up here... It always\n\t\t// succeeds on retry.\n\t\t// So do not log error object itself.\n\t\tthrowOdspNetworkError(\n\t\t\t// pre-0.58 error message: errorWhileParsingFetchResponse\n\t\t\t\"Error while parsing fetch response\",\n\t\t\tfetchIncorrectResponse,\n\t\t\tcontent, // response\n\t\t\ttext,\n\t\t);\n\t}\n\n\tpropsToLog.bodySize = text.length;\n\tconst res = {\n\t\theaders,\n\t\tcontent: JSON.parse(text),\n\t\tpropsToLog,\n\t\tduration,\n\t};\n\treturn res;\n}\n\nexport interface IFileInfoBase {\n\ttype: \"New\" | \"Existing\";\n\tsiteUrl: string;\n\tdriveId: string;\n}\n\nexport interface INewFileInfo extends IFileInfoBase {\n\ttype: \"New\";\n\tfilename: string;\n\tfilePath: string;\n\t/**\n\t * application can request creation of a share link along with the creation of a new file\n\t * by passing in an optional param to specify the kind of sharing link\n\t * (at the time of adding this comment Sept/2021), odsp only supports csl\n\t * ShareLinkTypes will deprecated in future. Use ISharingLinkKind instead which specifies both\n\t * share link type and the role type.\n\t */\n\tcreateLinkType?: ShareLinkTypes | ISharingLinkKind;\n}\n\nexport interface IExistingFileInfo extends IFileInfoBase {\n\ttype: \"Existing\";\n\titemId: string;\n}\n\nexport function isNewFileInfo(\n\tfileInfo: INewFileInfo | IExistingFileInfo,\n): fileInfo is INewFileInfo {\n\treturn fileInfo.type === undefined || fileInfo.type === \"New\";\n}\n\nexport function getOdspResolvedUrl(resolvedUrl: IResolvedUrl): IOdspResolvedUrl {\n\tassert(\n\t\t(resolvedUrl as IOdspResolvedUrl).odspResolvedUrl === true,\n\t\t0x1de /* \"Not an ODSP resolved url\" */,\n\t);\n\treturn resolvedUrl as IOdspResolvedUrl;\n}\n\nexport const createOdspLogger = (logger?: ITelemetryBaseLogger) =>\n\tChildLogger.create(logger, \"OdspDriver\", {\n\t\tall: {\n\t\t\tdriverVersion,\n\t\t},\n\t});\n\nexport function evalBlobsAndTrees(snapshot: IOdspSnapshot) {\n\tlet numTrees = 0;\n\tlet numBlobs = 0;\n\tlet encodedBlobsSize = 0;\n\tlet decodedBlobsSize = 0;\n\tfor (const tree of snapshot.trees) {\n\t\tfor (const treeEntry of tree.entries) {\n\t\t\tif (treeEntry.type === \"blob\") {\n\t\t\t\tnumBlobs++;\n\t\t\t} else if (treeEntry.type === \"tree\") {\n\t\t\t\tnumTrees++;\n\t\t\t}\n\t\t}\n\t}\n\tif (snapshot.blobs !== undefined) {\n\t\tfor (const blob of snapshot.blobs) {\n\t\t\tdecodedBlobsSize += blob.size;\n\t\t\tencodedBlobsSize += blob.content.length;\n\t\t}\n\t}\n\treturn { numTrees, numBlobs, encodedBlobsSize, decodedBlobsSize };\n}\n\nexport function toInstrumentedOdspTokenFetcher(\n\tlogger: ITelemetryLogger,\n\tresolvedUrlParts: IOdspUrlParts,\n\ttokenFetcher: TokenFetcher<OdspResourceTokenFetchOptions>,\n\tthrowOnNullToken: boolean,\n): InstrumentedStorageTokenFetcher {\n\treturn async (\n\t\toptions: TokenFetchOptions,\n\t\tname: string,\n\t\talwaysRecordTokenFetchTelemetry: boolean = false,\n\t) => {\n\t\t// Telemetry note: if options.refresh is true, there is a potential perf issue:\n\t\t// Host should optimize and provide non-expired tokens on all critical paths.\n\t\t// Exceptions: race conditions around expiration, revoked tokens, host that does not care\n\t\t// (fluid-fetcher)\n\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\tlogger,\n\t\t\t{\n\t\t\t\teventName: `${name}_GetToken`,\n\t\t\t\tattempts: options.refresh ? 2 : 1,\n\t\t\t\thasClaims: !!options.claims,\n\t\t\t\thasTenantId: !!options.tenantId,\n\t\t\t},\n\t\t\tasync (event) =>\n\t\t\t\ttokenFetcher({\n\t\t\t\t\t...options,\n\t\t\t\t\t...resolvedUrlParts,\n\t\t\t\t}).then(\n\t\t\t\t\t(tokenResponse) => {\n\t\t\t\t\t\tconst token = tokenFromResponse(tokenResponse);\n\t\t\t\t\t\t// This event alone generates so many events that is materially impacts cost of telemetry\n\t\t\t\t\t\t// Thus do not report end event when it comes back quickly.\n\t\t\t\t\t\t// Note that most of the hosts do not report if result is comming from cache or not,\n\t\t\t\t\t\t// so we can't rely on that here. But always record if specified explicitly for cases such as\n\t\t\t\t\t\t// calling trees/latest during load.\n\t\t\t\t\t\tif (alwaysRecordTokenFetchTelemetry || event.duration >= 32) {\n\t\t\t\t\t\t\tevent.end({\n\t\t\t\t\t\t\t\tfromCache: isTokenFromCache(tokenResponse),\n\t\t\t\t\t\t\t\tisNull: token === null,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (token === null && throwOnNullToken) {\n\t\t\t\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\t\t\t// pre-0.58 error message: Token is null for ${name} call\n\t\t\t\t\t\t\t\t`The Host-provided token fetcher returned null`,\n\t\t\t\t\t\t\t\tOdspErrorType.fetchTokenError,\n\t\t\t\t\t\t\t\t{ method: name, driverVersion },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn token;\n\t\t\t\t\t},\n\t\t\t\t\t(error) => {\n\t\t\t\t\t\t// There is an important but unofficial contract here where token providers can set canRetry: true\n\t\t\t\t\t\t// to hook into the driver's retry logic (e.g. the retry loop when initiating a connection)\n\t\t\t\t\t\tconst rawCanRetry = error?.canRetry;\n\t\t\t\t\t\tconst tokenError = wrapError(\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t\t(errorMessage) =>\n\t\t\t\t\t\t\t\tnew NetworkErrorBasic(\n\t\t\t\t\t\t\t\t\t`The Host-provided token fetcher threw an error`,\n\t\t\t\t\t\t\t\t\tOdspErrorType.fetchTokenError,\n\t\t\t\t\t\t\t\t\ttypeof rawCanRetry === \"boolean\"\n\t\t\t\t\t\t\t\t\t\t? rawCanRetry\n\t\t\t\t\t\t\t\t\t\t: false /* canRetry */,\n\t\t\t\t\t\t\t\t\t{ method: name, errorMessage, driverVersion },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthrow tokenError;\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t{ cancel: \"generic\" },\n\t\t);\n\t};\n}\n\nexport function createCacheSnapshotKey(odspResolvedUrl: IOdspResolvedUrl): ICacheEntry {\n\tconst cacheEntry: ICacheEntry = {\n\t\ttype: snapshotKey,\n\t\tkey: odspResolvedUrl.fileVersion ?? \"\",\n\t\tfile: {\n\t\t\tresolvedUrl: odspResolvedUrl,\n\t\t\tdocId: odspResolvedUrl.hashedDocumentId,\n\t\t},\n\t};\n\treturn cacheEntry;\n}\n\n// 80KB is the max body size that we can put in ump post body for server to be able to accept it.\n// Keeping it 78KB to be a little cautious. As per the telemetry 99p is less than 78KB.\nexport const maxUmpPostBodySize = 79872;\n\n/**\n * Build request parameters to request for the creation of a sharing link along with the creation of the file\n * through the /snapshot api call.\n * @param shareLinkType - Kind of sharing link requested\n * @returns A string of request parameters that can be concatenated with the base URI\n */\nexport function buildOdspShareLinkReqParams(\n\tshareLinkType: ShareLinkTypes | ISharingLinkKind | undefined,\n) {\n\tif (!shareLinkType) {\n\t\treturn;\n\t}\n\tconst scope = (shareLinkType as ISharingLinkKind).scope;\n\tif (!scope) {\n\t\treturn `createLinkType=${shareLinkType}`;\n\t}\n\tlet shareLinkRequestParams = `createLinkScope=${scope}`;\n\tconst role = (shareLinkType as ISharingLinkKind).role;\n\tshareLinkRequestParams = role\n\t\t? `${shareLinkRequestParams}&createLinkRole=${role}`\n\t\t: shareLinkRequestParams;\n\treturn shareLinkRequestParams;\n}\n\nexport function measure<T>(callback: () => T): [T, number] {\n\tconst start = performance.now();\n\tconst result = callback();\n\tconst time = performance.now() - start;\n\treturn [result, time];\n}\n\nexport async function measureP<T>(callback: () => Promise<T>): Promise<[T, number]> {\n\tconst start = performance.now();\n\tconst result = await callback();\n\tconst time = performance.now() - start;\n\treturn [result, time];\n}\n\nexport function validateMessages(\n\treason: string,\n\tmessages: ISequencedDocumentMessage[],\n\tfrom: number,\n\tlogger: ITelemetryLogger,\n) {\n\tif (messages.length !== 0) {\n\t\tconst start = messages[0].sequenceNumber;\n\t\tconst length = messages.length;\n\t\tconst last = messages[length - 1].sequenceNumber;\n\t\tif (start !== from) {\n\t\t\tlogger.sendErrorEvent({\n\t\t\t\teventName: \"OpsFetchViolation\",\n\t\t\t\treason,\n\t\t\t\tfrom,\n\t\t\t\tstart,\n\t\t\t\tlast,\n\t\t\t\tlength,\n\t\t\t});\n\t\t\tmessages.length = 0;\n\t\t}\n\t\tif (last + 1 !== from + length) {\n\t\t\tlogger.sendErrorEvent({\n\t\t\t\teventName: \"OpsFetchViolation\",\n\t\t\t\treason,\n\t\t\t\tfrom,\n\t\t\t\tstart,\n\t\t\t\tlast,\n\t\t\t\tlength,\n\t\t\t});\n\t\t\t// we can do better here by finding consecutive sub-block and return it\n\t\t\tmessages.length = 0;\n\t\t}\n\t}\n}\n"]}
|
package/lib/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/odsp-driver";
|
|
8
|
-
export declare const pkgVersion = "2.0.0-internal.4.1
|
|
8
|
+
export declare const pkgVersion = "2.0.0-internal.4.2.1";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/lib/packageVersion.js
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export const pkgName = "@fluidframework/odsp-driver";
|
|
8
|
-
export const pkgVersion = "2.0.0-internal.4.1
|
|
8
|
+
export const pkgVersion = "2.0.0-internal.4.2.1";
|
|
9
9
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/odsp-driver\";\nexport const pkgVersion = \"2.0.0-internal.4.1
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/odsp-driver\";\nexport const pkgVersion = \"2.0.0-internal.4.2.1\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/odsp-driver",
|
|
3
|
-
"version": "2.0.0-internal.4.1
|
|
3
|
+
"version": "2.0.0-internal.4.2.1",
|
|
4
4
|
"description": "Socket storage implementation for SPO and ODC",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -37,27 +37,27 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
39
39
|
"@fluidframework/common-utils": "^1.1.1",
|
|
40
|
-
"@fluidframework/core-interfaces": ">=2.0.0-internal.4.1
|
|
41
|
-
"@fluidframework/driver-base": ">=2.0.0-internal.4.1
|
|
42
|
-
"@fluidframework/driver-definitions": ">=2.0.0-internal.4.1
|
|
43
|
-
"@fluidframework/driver-utils": ">=2.0.0-internal.4.1
|
|
40
|
+
"@fluidframework/core-interfaces": ">=2.0.0-internal.4.2.1 <2.0.0-internal.4.3.0",
|
|
41
|
+
"@fluidframework/driver-base": ">=2.0.0-internal.4.2.1 <2.0.0-internal.4.3.0",
|
|
42
|
+
"@fluidframework/driver-definitions": ">=2.0.0-internal.4.2.1 <2.0.0-internal.4.3.0",
|
|
43
|
+
"@fluidframework/driver-utils": ">=2.0.0-internal.4.2.1 <2.0.0-internal.4.3.0",
|
|
44
44
|
"@fluidframework/gitresources": "^0.1039.1000",
|
|
45
|
-
"@fluidframework/odsp-doclib-utils": ">=2.0.0-internal.4.1
|
|
46
|
-
"@fluidframework/odsp-driver-definitions": ">=2.0.0-internal.4.1
|
|
45
|
+
"@fluidframework/odsp-doclib-utils": ">=2.0.0-internal.4.2.1 <2.0.0-internal.4.3.0",
|
|
46
|
+
"@fluidframework/odsp-driver-definitions": ">=2.0.0-internal.4.2.1 <2.0.0-internal.4.3.0",
|
|
47
47
|
"@fluidframework/protocol-base": "^0.1039.1000",
|
|
48
48
|
"@fluidframework/protocol-definitions": "^1.1.0",
|
|
49
|
-
"@fluidframework/telemetry-utils": ">=2.0.0-internal.4.1
|
|
49
|
+
"@fluidframework/telemetry-utils": ">=2.0.0-internal.4.2.1 <2.0.0-internal.4.3.0",
|
|
50
50
|
"abort-controller": "^3.0.0",
|
|
51
51
|
"node-fetch": "^2.6.9",
|
|
52
52
|
"socket.io-client": "^4.4.1",
|
|
53
53
|
"uuid": "^8.3.1"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@fluid-tools/build-cli": "^0.
|
|
56
|
+
"@fluid-tools/build-cli": "^0.17.0",
|
|
57
57
|
"@fluidframework/build-common": "^1.1.0",
|
|
58
|
-
"@fluidframework/build-tools": "^0.
|
|
58
|
+
"@fluidframework/build-tools": "^0.17.0",
|
|
59
59
|
"@fluidframework/eslint-config-fluid": "^2.0.0",
|
|
60
|
-
"@fluidframework/mocha-test-setup": ">=2.0.0-internal.4.1
|
|
60
|
+
"@fluidframework/mocha-test-setup": ">=2.0.0-internal.4.2.1 <2.0.0-internal.4.3.0",
|
|
61
61
|
"@fluidframework/odsp-driver-previous": "npm:@fluidframework/odsp-driver@2.0.0-internal.4.1.0",
|
|
62
62
|
"@microsoft/api-extractor": "^7.34.4",
|
|
63
63
|
"@types/mocha": "^9.1.1",
|
|
@@ -8,6 +8,7 @@ import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
|
8
8
|
import { assert, delay, performance } from "@fluidframework/common-utils";
|
|
9
9
|
import { loggerToMonitoringContext, PerformanceEvent } from "@fluidframework/telemetry-utils";
|
|
10
10
|
import * as api from "@fluidframework/protocol-definitions";
|
|
11
|
+
import { promiseRaceWithWinner } from "@fluidframework/driver-base";
|
|
11
12
|
import { ISummaryContext, DriverErrorType, FetchSource } from "@fluidframework/driver-definitions";
|
|
12
13
|
import { RateLimiter, NonRetryableError } from "@fluidframework/driver-utils";
|
|
13
14
|
import {
|
|
@@ -41,17 +42,6 @@ import { OdspDocumentStorageServiceBase } from "./odspDocumentStorageServiceBase
|
|
|
41
42
|
|
|
42
43
|
export const defaultSummarizerCacheExpiryTimeout: number = 60 * 1000; // 60 seconds.
|
|
43
44
|
|
|
44
|
-
// An implementation of Promise.race that gives you the winner of the promise race
|
|
45
|
-
async function promiseRaceWithWinner<T>(
|
|
46
|
-
promises: Promise<T>[],
|
|
47
|
-
): Promise<{ index: number; value: T }> {
|
|
48
|
-
return new Promise((resolve, reject) => {
|
|
49
|
-
promises.forEach((p, index) => {
|
|
50
|
-
p.then((v) => resolve({ index, value: v })).catch(reject);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
45
|
interface GetVersionsTelemetryProps {
|
|
56
46
|
cacheEntryAge?: number;
|
|
57
47
|
cacheSummarizerExpired?: boolean;
|
package/src/odspUtils.ts
CHANGED
|
@@ -142,9 +142,16 @@ export async function fetchHelper(
|
|
|
142
142
|
},
|
|
143
143
|
(error) => {
|
|
144
144
|
const online = isOnline();
|
|
145
|
-
|
|
145
|
+
|
|
146
|
+
// The error message may not be suitable to log for privacy reasons, so tag it as such
|
|
147
|
+
const taggedErrorMessage = {
|
|
148
|
+
value: `${error}`, // This uses toString for objects, which often results in `${error.name}: ${error.message}`
|
|
149
|
+
tag: TelemetryDataTag.UserData,
|
|
150
|
+
};
|
|
151
|
+
// After redacting URLs we believe the error message is safe to log
|
|
146
152
|
const urlRegex = /((http|https):\/\/(\S*))/i;
|
|
147
|
-
const redactedErrorText =
|
|
153
|
+
const redactedErrorText = taggedErrorMessage.value.replace(urlRegex, "REDACTED_URL");
|
|
154
|
+
|
|
148
155
|
// This error is thrown by fetch() when AbortSignal is provided and it gets cancelled
|
|
149
156
|
if (error.name === "AbortError") {
|
|
150
157
|
throw new RetryableError("Fetch Timeout (AbortError)", OdspErrorType.fetchTimeout, {
|
|
@@ -152,15 +159,12 @@ export async function fetchHelper(
|
|
|
152
159
|
});
|
|
153
160
|
}
|
|
154
161
|
// TCP/IP timeout
|
|
155
|
-
if (
|
|
162
|
+
if (redactedErrorText.includes("ETIMEDOUT")) {
|
|
156
163
|
throw new RetryableError("Fetch Timeout (ETIMEDOUT)", OdspErrorType.fetchTimeout, {
|
|
157
164
|
driverVersion,
|
|
158
165
|
});
|
|
159
166
|
}
|
|
160
167
|
|
|
161
|
-
// WARNING: Do not log error object itself or any of its properties!
|
|
162
|
-
// It could contain PII, like URI in message itself, or token in properties.
|
|
163
|
-
// It is also non-serializable object due to circular references.
|
|
164
168
|
// eslint-disable-next-line unicorn/prefer-ternary
|
|
165
169
|
if (online === OnlineStatus.Offline) {
|
|
166
170
|
throw new RetryableError(
|
|
@@ -169,7 +173,7 @@ export async function fetchHelper(
|
|
|
169
173
|
DriverErrorType.offlineError,
|
|
170
174
|
{
|
|
171
175
|
driverVersion,
|
|
172
|
-
rawErrorMessage:
|
|
176
|
+
rawErrorMessage: taggedErrorMessage,
|
|
173
177
|
},
|
|
174
178
|
);
|
|
175
179
|
} else {
|
|
@@ -181,7 +185,7 @@ export async function fetchHelper(
|
|
|
181
185
|
DriverErrorType.fetchFailure,
|
|
182
186
|
{
|
|
183
187
|
driverVersion,
|
|
184
|
-
rawErrorMessage:
|
|
188
|
+
rawErrorMessage: taggedErrorMessage,
|
|
185
189
|
},
|
|
186
190
|
);
|
|
187
191
|
}
|
package/src/packageVersion.ts
CHANGED