@fluidframework/odsp-driver 0.52.1 → 0.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/createFile.d.ts.map +1 -1
- package/dist/createFile.js +5 -4
- package/dist/createFile.js.map +1 -1
- package/dist/epochTracker.d.ts +2 -1
- package/dist/epochTracker.d.ts.map +1 -1
- package/dist/epochTracker.js +50 -21
- package/dist/epochTracker.js.map +1 -1
- package/dist/fetchSnapshot.d.ts.map +1 -1
- package/dist/fetchSnapshot.js +15 -14
- package/dist/fetchSnapshot.js.map +1 -1
- package/dist/getFileLink.js +3 -3
- package/dist/getFileLink.js.map +1 -1
- package/dist/odspDeltaStorageService.d.ts +3 -3
- package/dist/odspDeltaStorageService.d.ts.map +1 -1
- package/dist/odspDeltaStorageService.js +7 -4
- package/dist/odspDeltaStorageService.js.map +1 -1
- package/dist/odspDocumentDeltaConnection.d.ts.map +1 -1
- package/dist/odspDocumentDeltaConnection.js +2 -0
- package/dist/odspDocumentDeltaConnection.js.map +1 -1
- package/dist/odspDocumentService.d.ts +1 -1
- package/dist/odspDocumentService.d.ts.map +1 -1
- package/dist/odspDocumentService.js +13 -25
- package/dist/odspDocumentService.js.map +1 -1
- package/dist/odspDocumentStorageManager.d.ts.map +1 -1
- package/dist/odspDocumentStorageManager.js +29 -26
- package/dist/odspDocumentStorageManager.js.map +1 -1
- package/dist/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
- package/dist/odspDriverUrlResolverForShareLink.js +4 -3
- package/dist/odspDriverUrlResolverForShareLink.js.map +1 -1
- package/dist/odspError.d.ts.map +1 -1
- package/dist/odspError.js +3 -1
- package/dist/odspError.js.map +1 -1
- package/dist/odspSummaryUploadManager.d.ts +1 -1
- package/dist/odspSummaryUploadManager.d.ts.map +1 -1
- package/dist/odspSummaryUploadManager.js +7 -20
- package/dist/odspSummaryUploadManager.js.map +1 -1
- package/dist/odspUtils.d.ts.map +1 -1
- package/dist/odspUtils.js +31 -22
- 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/dist/vroom.d.ts.map +1 -1
- package/dist/vroom.js +4 -1
- package/dist/vroom.js.map +1 -1
- package/dist/zipItDataRepresentationUtils.d.ts.map +1 -1
- package/dist/zipItDataRepresentationUtils.js +3 -3
- package/dist/zipItDataRepresentationUtils.js.map +1 -1
- package/lib/createFile.d.ts.map +1 -1
- package/lib/createFile.js +6 -5
- package/lib/createFile.js.map +1 -1
- package/lib/epochTracker.d.ts +2 -1
- package/lib/epochTracker.d.ts.map +1 -1
- package/lib/epochTracker.js +50 -21
- package/lib/epochTracker.js.map +1 -1
- package/lib/fetchSnapshot.d.ts.map +1 -1
- package/lib/fetchSnapshot.js +15 -14
- package/lib/fetchSnapshot.js.map +1 -1
- package/lib/getFileLink.js +4 -4
- package/lib/getFileLink.js.map +1 -1
- package/lib/odspDeltaStorageService.d.ts +3 -3
- package/lib/odspDeltaStorageService.d.ts.map +1 -1
- package/lib/odspDeltaStorageService.js +7 -4
- package/lib/odspDeltaStorageService.js.map +1 -1
- package/lib/odspDocumentDeltaConnection.d.ts.map +1 -1
- package/lib/odspDocumentDeltaConnection.js +2 -0
- package/lib/odspDocumentDeltaConnection.js.map +1 -1
- package/lib/odspDocumentService.d.ts +1 -1
- package/lib/odspDocumentService.d.ts.map +1 -1
- package/lib/odspDocumentService.js +15 -27
- package/lib/odspDocumentService.js.map +1 -1
- package/lib/odspDocumentStorageManager.d.ts.map +1 -1
- package/lib/odspDocumentStorageManager.js +31 -28
- package/lib/odspDocumentStorageManager.js.map +1 -1
- package/lib/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
- package/lib/odspDriverUrlResolverForShareLink.js +5 -4
- package/lib/odspDriverUrlResolverForShareLink.js.map +1 -1
- package/lib/odspError.d.ts.map +1 -1
- package/lib/odspError.js +3 -1
- package/lib/odspError.js.map +1 -1
- package/lib/odspSummaryUploadManager.d.ts +1 -1
- package/lib/odspSummaryUploadManager.d.ts.map +1 -1
- package/lib/odspSummaryUploadManager.js +8 -21
- package/lib/odspSummaryUploadManager.js.map +1 -1
- package/lib/odspUtils.d.ts.map +1 -1
- package/lib/odspUtils.js +33 -24
- 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/lib/vroom.d.ts.map +1 -1
- package/lib/vroom.js +4 -1
- package/lib/vroom.js.map +1 -1
- package/lib/zipItDataRepresentationUtils.d.ts.map +1 -1
- package/lib/zipItDataRepresentationUtils.js +3 -3
- package/lib/zipItDataRepresentationUtils.js.map +1 -1
- package/package.json +8 -8
- package/src/createFile.ts +13 -9
- package/src/epochTracker.ts +50 -20
- package/src/fetchSnapshot.ts +15 -8
- package/src/getFileLink.ts +10 -4
- package/src/odspDeltaStorageService.ts +10 -3
- package/src/odspDocumentDeltaConnection.ts +2 -0
- package/src/odspDocumentService.ts +27 -29
- package/src/odspDocumentStorageManager.ts +48 -28
- package/src/odspDriverUrlResolverForShareLink.ts +8 -3
- package/src/odspError.ts +5 -1
- package/src/odspSummaryUploadManager.ts +7 -22
- package/src/odspUtils.ts +43 -34
- package/src/packageVersion.ts +1 -1
- package/src/vroom.ts +6 -1
- package/src/zipItDataRepresentationUtils.ts +4 -7
package/lib/epochTracker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"epochTracker.js","sourceRoot":"","sources":["../src/epochTracker.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 { v4 as uuid } from \"uuid\";\nimport { assert, Deferred } from \"@fluidframework/common-utils\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { fluidEpochMismatchError, throwOdspNetworkError } from \"@fluidframework/odsp-doclib-utils\";\nimport { ThrottlingError, RateLimiter } from \"@fluidframework/driver-utils\";\nimport { IConnected } from \"@fluidframework/protocol-definitions\";\nimport {\n snapshotKey,\n ICacheEntry,\n IEntry,\n IFileEntry,\n IPersistedCache,\n IOdspError,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport { PerformanceEvent, isFluidError, normalizeError } from \"@fluidframework/telemetry-utils\";\nimport { fetchAndParseAsJSONHelper, fetchArray, IOdspResponse } from \"./odspUtils\";\nimport {\n IOdspCache,\n INonPersistentCache,\n IPersistedFileCache,\n } from \"./odspCache\";\nimport { IVersionedValueWithEpoch, persistedCacheValueVersion } from \"./contracts\";\n\nexport type FetchType = \"blob\" | \"createBlob\" | \"createFile\" | \"joinSession\" | \"ops\" | \"test\" | \"snapshotTree\" |\n \"treesLatest\" | \"uploadSummary\" | \"push\" | \"versions\";\n\nexport type FetchTypeInternal = FetchType | \"cache\";\n\nexport const Odsp409Error = \"Odsp409Error\";\n\n/**\n * This class is a wrapper around fetch calls. It adds epoch to the request made so that the\n * server can match it with its epoch value in order to match the version.\n * It also validates the epoch value received in response of fetch calls. If the epoch does not match,\n * then it also clears all the cached entries for the given container.\n */\nexport class EpochTracker implements IPersistedFileCache {\n private _fluidEpoch: string | undefined;\n\n public readonly rateLimiter: RateLimiter;\n private readonly driverId = uuid();\n // This tracks the request number made by the driver instance.\n private networkCallNumber = 1;\n constructor(\n protected readonly cache: IPersistedCache,\n protected readonly fileEntry: IFileEntry,\n protected readonly logger: ITelemetryLogger,\n ) {\n // Limits the max number of concurrent requests to 24.\n this.rateLimiter = new RateLimiter(24);\n }\n\n // public for UT purposes only!\n public setEpoch(epoch: string, fromCache: boolean, fetchType: FetchTypeInternal) {\n assert(this._fluidEpoch === undefined, 0x1db /* \"epoch exists\" */);\n this._fluidEpoch = epoch;\n\n this.logger.sendTelemetryEvent(\n {\n eventName: \"EpochLearnedFirstTime\",\n epoch,\n fetchType,\n fromCache,\n },\n );\n }\n\n public async get(\n entry: IEntry,\n ): Promise<any> {\n try {\n const value: IVersionedValueWithEpoch = await this.cache.get(this.fileEntryFromEntry(entry));\n if (value === undefined || value.version !== persistedCacheValueVersion) {\n return undefined;\n }\n assert(value.fluidEpoch !== undefined, 0x1dc /* \"all entries have to have epoch\" */);\n if (this._fluidEpoch === undefined) {\n this.setEpoch(value.fluidEpoch, true, \"cache\");\n } else if (this._fluidEpoch !== value.fluidEpoch) {\n return undefined;\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return value.value;\n } catch (error) {\n this.logger.sendErrorEvent({ eventName: \"cacheFetchError\", type: entry.type }, error);\n return undefined;\n }\n }\n\n public async put(entry: IEntry, value: any) {\n assert(this._fluidEpoch !== undefined, 0x1dd /* \"no epoch\" */);\n const data: IVersionedValueWithEpoch = {\n value,\n version: persistedCacheValueVersion,\n fluidEpoch: this._fluidEpoch,\n };\n return this.cache.put(this.fileEntryFromEntry(entry), data)\n .catch((error) => {\n this.logger.sendErrorEvent({ eventName: \"cachePutError\", type: entry.type }, error);\n throw error;\n });\n }\n\n public async removeEntries(): Promise<void> {\n try {\n return await this.cache.removeEntries(this.fileEntry);\n } catch (error) {\n this.logger.sendErrorEvent({ eventName: \"removeCacheEntries\" }, error);\n }\n }\n\n public get fluidEpoch() {\n return this._fluidEpoch;\n }\n\n public async validateEpochFromPush(details: IConnected) {\n const epoch = details.epoch;\n assert(epoch !== undefined, 0x09d /* \"Connection details should contain epoch\" */);\n try {\n this.validateEpochFromResponse(epoch, \"push\");\n } catch (error) {\n await this.checkForEpochError(error, epoch, \"push\");\n throw error;\n }\n }\n\n /**\n * Api to fetch the response for given request and parse it as json.\n * @param url - url of the request\n * @param fetchOptions - fetch options for request containing body, headers etc.\n * @param fetchType - method for which fetch is called.\n * @param addInBody - Pass True if caller wants to add epoch in post body.\n */\n public async fetchAndParseAsJSON<T>(\n url: string,\n fetchOptions: RequestInit,\n fetchType: FetchType,\n addInBody: boolean = false,\n ): Promise<IOdspResponse<T>> {\n const clientCorelationId = this.formatClientCorelationId();\n // Add epoch in fetch request.\n this.addEpochInRequest(fetchOptions, addInBody, clientCorelationId);\n let epochFromResponse: string | undefined;\n return this.rateLimiter.schedule(\n async () => fetchAndParseAsJSONHelper<T>(url, fetchOptions),\n ).then((response) => {\n epochFromResponse = response.headers.get(\"x-fluid-epoch\");\n this.validateEpochFromResponse(epochFromResponse, fetchType);\n response.commonSpoHeaders = {\n ...response.commonSpoHeaders,\n \"X-RequestStats\": clientCorelationId,\n };\n return response;\n }).catch(async (error) => {\n // Get the server epoch from error in case we don't have it as if undefined we won't be able\n // to mark it as epoch error.\n if (epochFromResponse === undefined) {\n epochFromResponse = (error as IOdspError).serverEpoch;\n }\n await this.checkForEpochError(error, epochFromResponse, fetchType);\n throw error;\n }).catch((error) => {\n const fluidError = normalizeError(error, {props: {\"X-RequestStats\": clientCorelationId}});\n throw fluidError;\n });\n }\n\n /**\n * Api to fetch the response as it is for given request.\n * @param url - url of the request\n * @param fetchOptions - fetch options for request containing body, headers etc.\n * @param fetchType - method for which fetch is called.\n * @param addInBody - Pass True if caller wants to add epoch in post body.\n */\n public async fetchArray(\n url: string,\n fetchOptions: {[index: string]: any},\n fetchType: FetchType,\n addInBody: boolean = false,\n ) {\n const clientCorelationId = this.formatClientCorelationId();\n // Add epoch in fetch request.\n this.addEpochInRequest(fetchOptions, addInBody, clientCorelationId);\n let epochFromResponse: string | undefined;\n return this.rateLimiter.schedule(\n async () => fetchArray(url, fetchOptions),\n ).then((response) => {\n epochFromResponse = response.headers.get(\"x-fluid-epoch\");\n this.validateEpochFromResponse(epochFromResponse, fetchType);\n response.commonSpoHeaders = {\n ...response.commonSpoHeaders,\n \"X-RequestStats\": clientCorelationId,\n };\n return response;\n }).catch(async (error) => {\n // Get the server epoch from error in case we don't have it as if undefined we won't be able\n // to mark it as epoch error.\n if (epochFromResponse === undefined) {\n epochFromResponse = (error as IOdspError).serverEpoch;\n }\n await this.checkForEpochError(error, epochFromResponse, fetchType);\n throw error;\n }).catch((error) => {\n const fluidError = normalizeError(error, {props: {\"X-RequestStats\": clientCorelationId}});\n throw fluidError;\n });\n }\n\n private addEpochInRequest(\n fetchOptions: RequestInit,\n addInBody: boolean,\n clientCorelationId: string,\n ) {\n if (addInBody) {\n const headers: {[key: string]: string} = {};\n headers[\"X-RequestStats\"] = clientCorelationId;\n if (this.fluidEpoch !== undefined) {\n headers[\"x-fluid-epoch\"] = this.fluidEpoch;\n }\n this.addParamInBody(fetchOptions, headers);\n } else {\n const addHeader = (key: string, val: string) => {\n fetchOptions.headers = {\n ...fetchOptions.headers,\n };\n assert(fetchOptions.headers !== undefined, 0x282 /* \"Headers should be present now\" */);\n fetchOptions.headers[key] = val;\n };\n addHeader(\"X-RequestStats\", clientCorelationId);\n if (this.fluidEpoch !== undefined) {\n addHeader(\"x-fluid-epoch\", this.fluidEpoch);\n }\n }\n }\n\n private addParamInBody(fetchOptions: RequestInit, headers: {[key: string]: string}) {\n // We use multi part form request for post body where we want to use this.\n // So extract the form boundary to mark the end of form.\n const body = fetchOptions.body;\n assert(typeof body === \"string\", 0x21d /* \"body is not string\" */);\n const splitBody = body.split(\"\\r\\n\");\n const firstLine = splitBody.shift();\n assert(firstLine !== undefined && firstLine.startsWith(\"--\"), 0x21e /* \"improper boundary format\" */);\n const formParams = [firstLine];\n Object.entries(headers).forEach(([key, value]) => {\n formParams.push(`${key}: ${value}`);\n });\n splitBody.forEach((value: string) => {\n formParams.push(value);\n });\n fetchOptions.body = formParams.join(\"\\r\\n\");\n }\n\n private formatClientCorelationId() {\n return `driverId=${this.driverId}, RequestNumber=${this.networkCallNumber++}`;\n }\n\n protected validateEpochFromResponse(\n epochFromResponse: string | undefined,\n fetchType: FetchTypeInternal,\n fromCache: boolean = false,\n ) {\n this.checkForEpochErrorCore(epochFromResponse);\n if (epochFromResponse !== undefined) {\n if (this._fluidEpoch === undefined) {\n this.setEpoch(epochFromResponse, fromCache, fetchType);\n }\n }\n }\n\n private async checkForEpochError(\n error: unknown,\n epochFromResponse: string | null | undefined,\n fetchType: FetchTypeInternal,\n fromCache: boolean = false,\n ) {\n if (isFluidError(error) && error.errorType === DriverErrorType.fileOverwrittenInStorage) {\n try {\n // This will only throw if it is an epoch error.\n this.checkForEpochErrorCore(epochFromResponse);\n } catch (epochError) {\n assert(isFluidError(epochError),\n 0x21f /* \"epochError expected to be thrown by throwOdspNetworkError and of known type\" */);\n epochError.addTelemetryProperties({\n fromCache,\n clientEpoch: this.fluidEpoch,\n fetchType,\n });\n this.logger.sendErrorEvent({ eventName: \"fileOverwrittenInStorage\" }, epochError);\n // If the epoch mismatches, then clear all entries for such file entry from cache.\n await this.removeEntries();\n throw epochError;\n }\n // If it was categorized as epoch error but the epoch returned in response matches with the client epoch\n // then it was coherency 409, so rethrow it as throttling error so that it can retried. Default throttling\n // time is 1s.\n throw new ThrottlingError(\"coherency409\", error.message, 1, { [Odsp409Error]: true });\n }\n }\n\n private checkForEpochErrorCore(epochFromResponse: string | null | undefined) {\n // If epoch is undefined, then don't compare it because initially for createNew or TreesLatest\n // initializes this value. Sometimes response does not contain epoch as it is still in\n // implementation phase at server side. In that case also, don't compare it with our epoch value.\n if (this.fluidEpoch && epochFromResponse && (this.fluidEpoch !== epochFromResponse)) {\n throwOdspNetworkError(\"epochMismatch\", fluidEpochMismatchError);\n }\n }\n\n private fileEntryFromEntry(entry: IEntry): ICacheEntry {\n return { ...entry, file: this.fileEntry };\n }\n}\n\nexport class EpochTrackerWithRedemption extends EpochTracker {\n private readonly treesLatestDeferral = new Deferred<void>();\n\n protected validateEpochFromResponse(\n epochFromResponse: string | undefined,\n fetchType: FetchType,\n fromCache: boolean = false,\n ) {\n super.validateEpochFromResponse(epochFromResponse, fetchType, fromCache);\n\n // Any successful call means we have access to a file, i.e. any redemption that was required already happened.\n // That covers cases of \"treesLatest\" as well as \"getVersions\" or \"createFile\" - all the ways we can start\n // exploring a file.\n this.treesLatestDeferral.resolve();\n }\n\n public async get(\n entry: IEntry,\n ): Promise<any> {\n let result = super.get(entry);\n\n // equivalence of what happens in fetchAndParseAsJSON()\n if (entry.type === snapshotKey) {\n result = result\n .then((value) => {\n // If there is nothing in cache, we need to wait for network call to complete (and do redemption)\n // Otherwise file was redeemed in prior session, so if joinSession failed, we should not retry\n if (value !== undefined) {\n this.treesLatestDeferral.resolve();\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return value;\n })\n .catch((error) => {\n this.treesLatestDeferral.reject(error);\n throw error;\n });\n }\n return result;\n }\n\n public async fetchAndParseAsJSON<T>(\n url: string,\n fetchOptions: {[index: string]: any},\n fetchType: FetchType,\n addInBody: boolean = false,\n ): Promise<IOdspResponse<T>> {\n // Optimize the flow if we know that treesLatestDeferral was already completed by the timer we started\n // joinSession call. If we did - there is no reason to repeat the call as it will fail with same error.\n const completed = this.treesLatestDeferral.isCompleted;\n\n try {\n return await super.fetchAndParseAsJSON<T>(url, fetchOptions, fetchType, addInBody);\n } catch (error) {\n // Only handling here treesLatest. If createFile failed, we should never try to do joinSession.\n // Similar, if getVersions failed, we should not do any further storage calls.\n // So treesLatest is the only call that can have parallel joinSession request.\n if (fetchType === \"treesLatest\") {\n this.treesLatestDeferral.reject(error);\n }\n if (fetchType !== \"joinSession\" || error.statusCode < 401 || error.statusCode > 404 || completed) {\n throw error;\n }\n }\n\n // It is joinSession failing with 401..404 error\n // Repeat after waiting for treeLatest succeeding (or fail if it failed).\n // No special handling after first call - if file has been deleted, then it's game over.\n\n // Ensure we have some safety here - we do not want to deadlock if we got logic somewhere wrong.\n // If we waited too long, we will log error event and proceed with call.\n // It may result in failure for user, but refreshing document would address it.\n // Thus we use rather long timeout (not to get these failures as much as possible), but not large enough\n // to unblock the process.\n await PerformanceEvent.timedExecAsync(\n this.logger,\n { eventName: \"JoinSessionSyncWait\" },\n async (event) => {\n const timeoutRes = 51; // anything will work here\n let timer: ReturnType<typeof setTimeout>;\n const timeoutP = new Promise<number>((accept) => {\n timer = setTimeout(() => { accept(timeoutRes); }, 15000);\n });\n const res = await Promise.race([\n timeoutP,\n // cancel timeout to unblock UTs (otherwise Node process does not exit for 15 sec)\n this.treesLatestDeferral.promise.finally(() => clearTimeout(timer))]);\n if (res === timeoutRes) {\n event.cancel();\n }\n },\n { start: true, end: true, cancel: \"generic\" });\n return super.fetchAndParseAsJSON<T>(url, fetchOptions, fetchType, addInBody);\n }\n}\n\nexport interface ICacheAndTracker {\n cache: IOdspCache;\n epochTracker: EpochTracker;\n}\n\nexport function createOdspCacheAndTracker(\n persistedCacheArg: IPersistedCache,\n nonpersistentCache: INonPersistentCache,\n fileEntry: IFileEntry,\n logger: ITelemetryLogger): ICacheAndTracker\n{\n const epochTracker = new EpochTrackerWithRedemption(persistedCacheArg, fileEntry, logger);\n return {\n cache: {\n ...nonpersistentCache,\n persistedCache: epochTracker,\n },\n epochTracker,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"epochTracker.js","sourceRoot":"","sources":["../src/epochTracker.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 { v4 as uuid } from \"uuid\";\nimport { assert, Deferred } from \"@fluidframework/common-utils\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { ThrottlingError, RateLimiter, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport { IConnected } from \"@fluidframework/protocol-definitions\";\nimport {\n snapshotKey,\n ICacheEntry,\n IEntry,\n IFileEntry,\n IPersistedCache,\n IOdspError,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport { PerformanceEvent, isFluidError, normalizeError } from \"@fluidframework/telemetry-utils\";\nimport { fetchAndParseAsJSONHelper, fetchArray, IOdspResponse } from \"./odspUtils\";\nimport {\n IOdspCache,\n INonPersistentCache,\n IPersistedFileCache,\n } from \"./odspCache\";\nimport { IVersionedValueWithEpoch, persistedCacheValueVersion } from \"./contracts\";\n\nexport type FetchType = \"blob\" | \"createBlob\" | \"createFile\" | \"joinSession\" | \"ops\" | \"test\" | \"snapshotTree\" |\n \"treesLatest\" | \"uploadSummary\" | \"push\" | \"versions\";\n\nexport type FetchTypeInternal = FetchType | \"cache\";\n\nexport const Odsp409Error = \"Odsp409Error\";\n\nexport const defaultCacheExpiryTimeoutMs: number = 2 * 24 * 60 * 60 * 1000;\n\n/**\n * This class is a wrapper around fetch calls. It adds epoch to the request made so that the\n * server can match it with its epoch value in order to match the version.\n * It also validates the epoch value received in response of fetch calls. If the epoch does not match,\n * then it also clears all the cached entries for the given container.\n */\nexport class EpochTracker implements IPersistedFileCache {\n private _fluidEpoch: string | undefined;\n\n public readonly rateLimiter: RateLimiter;\n private readonly driverId = uuid();\n // This tracks the request number made by the driver instance.\n private networkCallNumber = 1;\n constructor(\n protected readonly cache: IPersistedCache,\n protected readonly fileEntry: IFileEntry,\n protected readonly logger: ITelemetryLogger,\n ) {\n // Limits the max number of concurrent requests to 24.\n this.rateLimiter = new RateLimiter(24);\n }\n\n // public for UT purposes only!\n public setEpoch(epoch: string, fromCache: boolean, fetchType: FetchTypeInternal) {\n assert(this._fluidEpoch === undefined, 0x1db /* \"epoch exists\" */);\n this._fluidEpoch = epoch;\n\n this.logger.sendTelemetryEvent(\n {\n eventName: \"EpochLearnedFirstTime\",\n epoch,\n fetchType,\n fromCache,\n },\n );\n }\n\n public async get(\n entry: IEntry,\n ): Promise<any> {\n try {\n // Return undefined so that the ops/snapshots are grabbed from the server instead of the cache\n const value: IVersionedValueWithEpoch = await this.cache.get(this.fileEntryFromEntry(entry));\n // Version mismatch between what the runtime expects and what it recieved.\n // The cached value should not be used\n if (value === undefined || value.version !== persistedCacheValueVersion) {\n return undefined;\n }\n assert(value.fluidEpoch !== undefined, 0x1dc /* \"all entries have to have epoch\" */);\n if (this._fluidEpoch === undefined) {\n this.setEpoch(value.fluidEpoch, true, \"cache\");\n // Epoch mismatch, the cached value is considerably different from what the current state of\n // the runtime and should not be used\n } else if (this._fluidEpoch !== value.fluidEpoch) {\n return undefined;\n }\n // Expire the cached snapshot if it's older than the defaultCacheExpiryTimeoutMs and immediately\n // expire all old caches that do not have cacheEntryTime\n if (entry.type === snapshotKey) {\n const cacheTime = value.value?.cacheEntryTime;\n const currentTime = Date.now();\n if (cacheTime === undefined || currentTime - cacheTime >= defaultCacheExpiryTimeoutMs) {\n this.logger.sendTelemetryEvent(\n {\n eventName: \"odspVersionsCacheExpired\",\n duration: currentTime - cacheTime,\n maxCacheAgeMs: defaultCacheExpiryTimeoutMs,\n });\n await this.removeEntries();\n return undefined;\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return value.value;\n } catch (error) {\n this.logger.sendErrorEvent({ eventName: \"cacheFetchError\", type: entry.type }, error);\n return undefined;\n }\n }\n\n public async put(entry: IEntry, value: any) {\n assert(this._fluidEpoch !== undefined, 0x1dd /* \"no epoch\" */);\n // For snapshots, the value should have the cacheEntryTime. This will be used to expire snapshots older\n // than the defaultCacheExpiryTimeoutMs.\n if (entry.type === snapshotKey) {\n value.cacheEntryTime = value.cacheEntryTime ?? Date.now();\n }\n const data: IVersionedValueWithEpoch = {\n value,\n version: persistedCacheValueVersion,\n fluidEpoch: this._fluidEpoch,\n };\n return this.cache.put(this.fileEntryFromEntry(entry), data)\n .catch((error) => {\n this.logger.sendErrorEvent({ eventName: \"cachePutError\", type: entry.type }, error);\n throw error;\n });\n }\n\n public async removeEntries(): Promise<void> {\n try {\n return await this.cache.removeEntries(this.fileEntry);\n } catch (error) {\n this.logger.sendErrorEvent({ eventName: \"removeCacheEntries\" }, error);\n }\n }\n\n public get fluidEpoch() {\n return this._fluidEpoch;\n }\n\n public async validateEpochFromPush(details: IConnected) {\n const epoch = details.epoch;\n assert(epoch !== undefined, 0x09d /* \"Connection details should contain epoch\" */);\n try {\n this.validateEpochFromResponse(epoch, \"push\");\n } catch (error) {\n await this.checkForEpochError(error, epoch, \"push\");\n throw error;\n }\n }\n\n /**\n * Api to fetch the response for given request and parse it as json.\n * @param url - url of the request\n * @param fetchOptions - fetch options for request containing body, headers etc.\n * @param fetchType - method for which fetch is called.\n * @param addInBody - Pass True if caller wants to add epoch in post body.\n */\n public async fetchAndParseAsJSON<T>(\n url: string,\n fetchOptions: RequestInit,\n fetchType: FetchType,\n addInBody: boolean = false,\n ): Promise<IOdspResponse<T>> {\n const clientCorrelationId = this.formatClientCorrelationId();\n // Add epoch in fetch request.\n this.addEpochInRequest(fetchOptions, addInBody, clientCorrelationId);\n let epochFromResponse: string | undefined;\n return this.rateLimiter.schedule(\n async () => fetchAndParseAsJSONHelper<T>(url, fetchOptions),\n ).then((response) => {\n epochFromResponse = response.headers.get(\"x-fluid-epoch\");\n this.validateEpochFromResponse(epochFromResponse, fetchType);\n response.commonSpoHeaders = {\n ...response.commonSpoHeaders,\n \"X-RequestStats\": clientCorrelationId,\n };\n return response;\n }).catch(async (error) => {\n // Get the server epoch from error in case we don't have it as if undefined we won't be able\n // to mark it as epoch error.\n if (epochFromResponse === undefined) {\n epochFromResponse = (error as IOdspError).serverEpoch;\n }\n await this.checkForEpochError(error, epochFromResponse, fetchType);\n throw error;\n }).catch((error) => {\n const fluidError = normalizeError(error, { props: { XRequestStatsHeader: clientCorrelationId }});\n throw fluidError;\n });\n }\n\n /**\n * Api to fetch the response as it is for given request.\n * @param url - url of the request\n * @param fetchOptions - fetch options for request containing body, headers etc.\n * @param fetchType - method for which fetch is called.\n * @param addInBody - Pass True if caller wants to add epoch in post body.\n */\n public async fetchArray(\n url: string,\n fetchOptions: {[index: string]: any},\n fetchType: FetchType,\n addInBody: boolean = false,\n ) {\n const clientCorrelationId = this.formatClientCorrelationId();\n // Add epoch in fetch request.\n this.addEpochInRequest(fetchOptions, addInBody, clientCorrelationId);\n let epochFromResponse: string | undefined;\n return this.rateLimiter.schedule(\n async () => fetchArray(url, fetchOptions),\n ).then((response) => {\n epochFromResponse = response.headers.get(\"x-fluid-epoch\");\n this.validateEpochFromResponse(epochFromResponse, fetchType);\n response.commonSpoHeaders = {\n ...response.commonSpoHeaders,\n \"X-RequestStats\": clientCorrelationId,\n };\n return response;\n }).catch(async (error) => {\n // Get the server epoch from error in case we don't have it as if undefined we won't be able\n // to mark it as epoch error.\n if (epochFromResponse === undefined) {\n epochFromResponse = (error as IOdspError).serverEpoch;\n }\n await this.checkForEpochError(error, epochFromResponse, fetchType);\n throw error;\n }).catch((error) => {\n const fluidError = normalizeError(error, { props: { XRequestStatsHeader: clientCorrelationId }});\n throw fluidError;\n });\n }\n\n private addEpochInRequest(\n fetchOptions: RequestInit,\n addInBody: boolean,\n clientCorrelationId: string,\n ) {\n if (addInBody) {\n const headers: {[key: string]: string} = {};\n headers[\"X-RequestStats\"] = clientCorrelationId;\n if (this.fluidEpoch !== undefined) {\n headers[\"x-fluid-epoch\"] = this.fluidEpoch;\n }\n this.addParamInBody(fetchOptions, headers);\n } else {\n const addHeader = (key: string, val: string) => {\n fetchOptions.headers = {\n ...fetchOptions.headers,\n };\n assert(fetchOptions.headers !== undefined, 0x282 /* \"Headers should be present now\" */);\n fetchOptions.headers[key] = val;\n };\n addHeader(\"X-RequestStats\", clientCorrelationId);\n if (this.fluidEpoch !== undefined) {\n addHeader(\"x-fluid-epoch\", this.fluidEpoch);\n }\n }\n }\n\n private addParamInBody(fetchOptions: RequestInit, headers: {[key: string]: string}) {\n // We use multi part form request for post body where we want to use this.\n // So extract the form boundary to mark the end of form.\n const body = fetchOptions.body;\n assert(typeof body === \"string\", 0x21d /* \"body is not string\" */);\n const splitBody = body.split(\"\\r\\n\");\n const firstLine = splitBody.shift();\n assert(firstLine !== undefined && firstLine.startsWith(\"--\"), 0x21e /* \"improper boundary format\" */);\n const formParams = [firstLine];\n Object.entries(headers).forEach(([key, value]) => {\n formParams.push(`${key}: ${value}`);\n });\n splitBody.forEach((value: string) => {\n formParams.push(value);\n });\n fetchOptions.body = formParams.join(\"\\r\\n\");\n }\n\n private formatClientCorrelationId() {\n return `driverId=${this.driverId}, RequestNumber=${this.networkCallNumber++}`;\n }\n\n protected validateEpochFromResponse(\n epochFromResponse: string | undefined,\n fetchType: FetchTypeInternal,\n fromCache: boolean = false,\n ) {\n const error = this.checkForEpochErrorCore(epochFromResponse);\n if (error !== undefined) {\n throw error;\n }\n if (epochFromResponse !== undefined) {\n if (this._fluidEpoch === undefined) {\n this.setEpoch(epochFromResponse, fromCache, fetchType);\n }\n }\n }\n\n private async checkForEpochError(\n error: unknown,\n epochFromResponse: string | null | undefined,\n fetchType: FetchTypeInternal,\n fromCache: boolean = false,\n ) {\n if (isFluidError(error) && error.errorType === DriverErrorType.fileOverwrittenInStorage) {\n const epochError = this.checkForEpochErrorCore(epochFromResponse);\n if (epochError !== undefined) {\n assert(isFluidError(epochError),\n 0x21f /* \"epochError expected to be thrown by throwOdspNetworkError and of known type\" */);\n epochError.addTelemetryProperties({\n fromCache,\n clientEpoch: this.fluidEpoch,\n fetchType,\n });\n this.logger.sendErrorEvent({ eventName: \"fileOverwrittenInStorage\" }, epochError);\n // If the epoch mismatches, then clear all entries for such file entry from cache.\n await this.removeEntries();\n throw epochError;\n }\n // If it was categorized as epoch error but the epoch returned in response matches with the client epoch\n // then it was coherency 409, so rethrow it as throttling error so that it can retried. Default throttling\n // time is 1s.\n throw new ThrottlingError(\"coherency409\", error.message, 1, { [Odsp409Error]: true });\n }\n }\n\n private checkForEpochErrorCore(epochFromResponse: string | null | undefined) {\n // If epoch is undefined, then don't compare it because initially for createNew or TreesLatest\n // initializes this value. Sometimes response does not contain epoch as it is still in\n // implementation phase at server side. In that case also, don't compare it with our epoch value.\n if (this.fluidEpoch && epochFromResponse && (this.fluidEpoch !== epochFromResponse)) {\n // This is similar in nature to how fluidEpochMismatchError (409) is handled.\n // Difference - client detected mismatch, instead of server detecting it.\n return new NonRetryableError(\"epochMismatch\", \"Epoch mismatch\", DriverErrorType.fileOverwrittenInStorage);\n }\n }\n\n private fileEntryFromEntry(entry: IEntry): ICacheEntry {\n return { ...entry, file: this.fileEntry };\n }\n}\n\nexport class EpochTrackerWithRedemption extends EpochTracker {\n private readonly treesLatestDeferral = new Deferred<void>();\n\n protected validateEpochFromResponse(\n epochFromResponse: string | undefined,\n fetchType: FetchType,\n fromCache: boolean = false,\n ) {\n super.validateEpochFromResponse(epochFromResponse, fetchType, fromCache);\n\n // Any successful call means we have access to a file, i.e. any redemption that was required already happened.\n // That covers cases of \"treesLatest\" as well as \"getVersions\" or \"createFile\" - all the ways we can start\n // exploring a file.\n this.treesLatestDeferral.resolve();\n }\n\n public async get(\n entry: IEntry,\n ): Promise<any> {\n let result = super.get(entry);\n\n // equivalence of what happens in fetchAndParseAsJSON()\n if (entry.type === snapshotKey) {\n result = result\n .then((value) => {\n // If there is nothing in cache, we need to wait for network call to complete (and do redemption)\n // Otherwise file was redeemed in prior session, so if joinSession failed, we should not retry\n if (value !== undefined) {\n this.treesLatestDeferral.resolve();\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return value;\n })\n .catch((error) => {\n this.treesLatestDeferral.reject(error);\n throw error;\n });\n }\n return result;\n }\n\n public async fetchAndParseAsJSON<T>(\n url: string,\n fetchOptions: {[index: string]: any},\n fetchType: FetchType,\n addInBody: boolean = false,\n ): Promise<IOdspResponse<T>> {\n // Optimize the flow if we know that treesLatestDeferral was already completed by the timer we started\n // joinSession call. If we did - there is no reason to repeat the call as it will fail with same error.\n const completed = this.treesLatestDeferral.isCompleted;\n\n try {\n return await super.fetchAndParseAsJSON<T>(url, fetchOptions, fetchType, addInBody);\n } catch (error) {\n // Only handling here treesLatest. If createFile failed, we should never try to do joinSession.\n // Similar, if getVersions failed, we should not do any further storage calls.\n // So treesLatest is the only call that can have parallel joinSession request.\n if (fetchType === \"treesLatest\") {\n this.treesLatestDeferral.reject(error);\n }\n if (fetchType !== \"joinSession\" || error.statusCode < 401 || error.statusCode > 404 || completed) {\n throw error;\n }\n }\n\n // It is joinSession failing with 401..404 error\n // Repeat after waiting for treeLatest succeeding (or fail if it failed).\n // No special handling after first call - if file has been deleted, then it's game over.\n\n // Ensure we have some safety here - we do not want to deadlock if we got logic somewhere wrong.\n // If we waited too long, we will log error event and proceed with call.\n // It may result in failure for user, but refreshing document would address it.\n // Thus we use rather long timeout (not to get these failures as much as possible), but not large enough\n // to unblock the process.\n await PerformanceEvent.timedExecAsync(\n this.logger,\n { eventName: \"JoinSessionSyncWait\" },\n async (event) => {\n const timeoutRes = 51; // anything will work here\n let timer: ReturnType<typeof setTimeout>;\n const timeoutP = new Promise<number>((accept) => {\n timer = setTimeout(() => { accept(timeoutRes); }, 15000);\n });\n const res = await Promise.race([\n timeoutP,\n // cancel timeout to unblock UTs (otherwise Node process does not exit for 15 sec)\n this.treesLatestDeferral.promise.finally(() => clearTimeout(timer))]);\n if (res === timeoutRes) {\n event.cancel();\n }\n },\n { start: true, end: true, cancel: \"generic\" });\n return super.fetchAndParseAsJSON<T>(url, fetchOptions, fetchType, addInBody);\n }\n}\n\nexport interface ICacheAndTracker {\n cache: IOdspCache;\n epochTracker: EpochTracker;\n}\n\nexport function createOdspCacheAndTracker(\n persistedCacheArg: IPersistedCache,\n nonpersistentCache: INonPersistentCache,\n fileEntry: IFileEntry,\n logger: ITelemetryLogger): ICacheAndTracker\n{\n const epochTracker = new EpochTrackerWithRedemption(persistedCacheArg, fileEntry, logger);\n return {\n cache: {\n ...nonpersistentCache,\n persistedCache: epochTracker,\n },\n epochTracker,\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetchSnapshot.d.ts","sourceRoot":"","sources":["../src/fetchSnapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAItE,OAAO,EACH,gBAAgB,EAChB,gBAAgB,EAEhB,+BAA+B,EAClC,MAAM,yCAAyC,CAAC;AAEjD,OAAO,EAAuC,wBAAwB,EAA8B,MAAM,aAAa,CAAC;AAGxH,OAAO,EAKH,aAAa,EACb,iBAAiB,EACpB,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAC/B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,OAAO,EAC1B,MAAM,EAAE,gBAAgB,EACxB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE;IAAC,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAA;CAAC,KAAK,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,GAC3G,OAAO,CAAC,iBAAiB,CAAC,CAuB5B;AAED,wBAAsB,uBAAuB,CACzC,eAAe,EAAE,gBAAgB,EACjC,mBAAmB,EAAE,+BAA+B,EACpD,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,MAAM,EAAE,gBAAgB,EACxB,kBAAkB,EAAE,CACZ,oBAAoB,EAAE,gBAAgB,EACtC,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,UAAU,CAAC,EAAE,eAAe,KAC3B,OAAO,CAAC,kCAAkC,CAAC,EACpD,UAAU,EAAE,CAAC,cAAc,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,EACvE,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAClC,oBAAoB,CAAC,EAAE,OAAO,GAC/B,OAAO,CAAC,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"fetchSnapshot.d.ts","sourceRoot":"","sources":["../src/fetchSnapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAItE,OAAO,EACH,gBAAgB,EAChB,gBAAgB,EAEhB,+BAA+B,EAClC,MAAM,yCAAyC,CAAC;AAEjD,OAAO,EAAuC,wBAAwB,EAA8B,MAAM,aAAa,CAAC;AAGxH,OAAO,EAKH,aAAa,EACb,iBAAiB,EACpB,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAC/B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,OAAO,EAC1B,MAAM,EAAE,gBAAgB,EACxB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE;IAAC,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAA;CAAC,KAAK,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,GAC3G,OAAO,CAAC,iBAAiB,CAAC,CAuB5B;AAED,wBAAsB,uBAAuB,CACzC,eAAe,EAAE,gBAAgB,EACjC,mBAAmB,EAAE,+BAA+B,EACpD,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,MAAM,EAAE,gBAAgB,EACxB,kBAAkB,EAAE,CACZ,oBAAoB,EAAE,gBAAgB,EACtC,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,UAAU,CAAC,EAAE,eAAe,KAC3B,OAAO,CAAC,kCAAkC,CAAC,EACpD,UAAU,EAAE,CAAC,cAAc,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,EACvE,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAClC,oBAAoB,CAAC,EAAE,OAAO,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CA+C5B;AA0LD,UAAU,kCAAkC;IACxC,oBAAoB,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE;QAAC,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,CAAC;CAC1C;AA4HD,wBAAsB,gBAAgB,CAClC,eAAe,EAAE,gBAAgB,EACjC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,gBAAgB,EACxB,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,yBAAyB,CAAC,EAAE,OAAO,EACnC,UAAU,CAAC,EAAE,eAAe,EAC5B,YAAY,CAAC,EAAE,YAAY,GAC5B,OAAO,CAAC,kCAAkC,CAAC,CAQ7C"}
|
package/lib/fetchSnapshot.js
CHANGED
|
@@ -52,7 +52,10 @@ export async function fetchSnapshotWithRedeem(odspResolvedUrl, storageTokenFetch
|
|
|
52
52
|
errorType: error.errorType,
|
|
53
53
|
}, error);
|
|
54
54
|
await redeemSharingLink(odspResolvedUrl, storageTokenFetcher, logger);
|
|
55
|
-
const odspResolvedUrlWithoutShareLink = Object.assign(Object.assign({}, odspResolvedUrl), {
|
|
55
|
+
const odspResolvedUrlWithoutShareLink = Object.assign(Object.assign({}, odspResolvedUrl), { sharingLinkToRedeem: undefined });
|
|
56
|
+
if (odspResolvedUrlWithoutShareLink.shareLinkInfo) {
|
|
57
|
+
odspResolvedUrlWithoutShareLink.shareLinkInfo = Object.assign(Object.assign({}, odspResolvedUrlWithoutShareLink.shareLinkInfo), { sharingLinkToRedeem: undefined });
|
|
58
|
+
}
|
|
56
59
|
return fetchLatestSnapshotCore(odspResolvedUrlWithoutShareLink, storageTokenFetcher, snapshotOptions, logger, snapshotDownloader, putInCache);
|
|
57
60
|
}
|
|
58
61
|
else {
|
|
@@ -73,10 +76,9 @@ async function redeemSharingLink(odspResolvedUrl, storageTokenFetcher, logger) {
|
|
|
73
76
|
return PerformanceEvent.timedExecAsync(logger, {
|
|
74
77
|
eventName: "RedeemShareLink",
|
|
75
78
|
}, async () => getWithRetryForTokenRefresh(async (tokenFetchOptions) => {
|
|
76
|
-
|
|
77
|
-
assert(!!((_a = odspResolvedUrl.shareLinkInfo) === null || _a === void 0 ? void 0 : _a.sharingLinkToRedeem), 0x1ed /* "Share link should be present" */);
|
|
79
|
+
assert(!!odspResolvedUrl.sharingLinkToRedeem, 0x1ed /* "Share link should be present" */);
|
|
78
80
|
const storageToken = await storageTokenFetcher(tokenFetchOptions, "RedeemShareLink");
|
|
79
|
-
const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.
|
|
81
|
+
const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.sharingLinkToRedeem);
|
|
80
82
|
const redeemUrl = `${odspResolvedUrl.siteUrl}/_api/v2.0/shares/${encodedShareUrl}`;
|
|
81
83
|
const { url, headers } = getUrlAndHeadersWithAuth(redeemUrl, storageToken);
|
|
82
84
|
headers.prefer = "redeemSharingLink";
|
|
@@ -203,7 +205,7 @@ async function fetchLatestSnapshotCore(odspResolvedUrl, storageTokenFetcher, sna
|
|
|
203
205
|
* @returns fetched snapshot.
|
|
204
206
|
*/
|
|
205
207
|
async function fetchSnapshotContentsCoreV1(odspResolvedUrl, storageToken, snapshotOptions, controller, epochTracker) {
|
|
206
|
-
var _a
|
|
208
|
+
var _a;
|
|
207
209
|
const snapshotUrl = odspResolvedUrl.endpoints.snapshotStorageUrl;
|
|
208
210
|
const url = `${snapshotUrl}/trees/latest?ump=1`;
|
|
209
211
|
const formBoundary = uuid();
|
|
@@ -218,8 +220,8 @@ async function fetchSnapshotContentsCoreV1(odspResolvedUrl, storageToken, snapsh
|
|
|
218
220
|
}
|
|
219
221
|
});
|
|
220
222
|
}
|
|
221
|
-
if (
|
|
222
|
-
formParams.push(`sl: ${odspResolvedUrl.
|
|
223
|
+
if (odspResolvedUrl.sharingLinkToRedeem) {
|
|
224
|
+
formParams.push(`sl: ${odspResolvedUrl.sharingLinkToRedeem}`);
|
|
223
225
|
}
|
|
224
226
|
formParams.push(`_post: 1`);
|
|
225
227
|
formParams.push(`\r\n--${formBoundary}--`);
|
|
@@ -233,7 +235,7 @@ async function fetchSnapshotContentsCoreV1(odspResolvedUrl, storageToken, snapsh
|
|
|
233
235
|
signal: controller === null || controller === void 0 ? void 0 : controller.signal,
|
|
234
236
|
method: "POST",
|
|
235
237
|
};
|
|
236
|
-
const response = await ((
|
|
238
|
+
const response = await ((_a = epochTracker === null || epochTracker === void 0 ? void 0 : epochTracker.fetchAndParseAsJSON(url, fetchOptions, "treesLatest", true)) !== null && _a !== void 0 ? _a : fetchAndParseAsJSONHelper(url, fetchOptions));
|
|
237
239
|
const snapshotContents = convertOdspSnapshotToSnapsohtTreeAndBlobs(response.content);
|
|
238
240
|
const finalSnapshotContents = Object.assign(Object.assign({}, response), { content: snapshotContents });
|
|
239
241
|
return {
|
|
@@ -253,12 +255,12 @@ async function fetchSnapshotContentsCoreV1(odspResolvedUrl, storageToken, snapsh
|
|
|
253
255
|
* @returns fetched snapshot.
|
|
254
256
|
*/
|
|
255
257
|
async function fetchSnapshotContentsCoreV2(odspResolvedUrl, storageToken, snapshotOptions, controller, epochTracker) {
|
|
256
|
-
var _a
|
|
258
|
+
var _a;
|
|
257
259
|
const fullUrl = `${odspResolvedUrl.siteUrl}/_api/v2.1/drives/${odspResolvedUrl.driveId}/items/${odspResolvedUrl.itemId}/opStream/attachments/latest/content`;
|
|
258
260
|
const queryParams = Object.assign({}, snapshotOptions);
|
|
259
|
-
if (
|
|
261
|
+
if (odspResolvedUrl.sharingLinkToRedeem) {
|
|
260
262
|
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
261
|
-
queryParams["sl"] = odspResolvedUrl.
|
|
263
|
+
queryParams["sl"] = odspResolvedUrl.sharingLinkToRedeem;
|
|
262
264
|
}
|
|
263
265
|
const queryString = getQueryString(queryParams);
|
|
264
266
|
const { url, headers } = getUrlAndHeadersWithAuth(`${fullUrl}${queryString}`, storageToken);
|
|
@@ -266,7 +268,7 @@ async function fetchSnapshotContentsCoreV2(odspResolvedUrl, storageToken, snapsh
|
|
|
266
268
|
headers,
|
|
267
269
|
signal: controller === null || controller === void 0 ? void 0 : controller.signal,
|
|
268
270
|
};
|
|
269
|
-
const response = await ((
|
|
271
|
+
const response = await ((_a = epochTracker === null || epochTracker === void 0 ? void 0 : epochTracker.fetchArray(url, fetchOptions, "treesLatest")) !== null && _a !== void 0 ? _a : fetchArray(url, fetchOptions));
|
|
270
272
|
const snapshotContents = parseCompactSnapshotResponse(new ReadBuffer(new Uint8Array(response.content)));
|
|
271
273
|
const finalSnapshotContents = Object.assign(Object.assign({}, response), { content: snapshotContents });
|
|
272
274
|
return {
|
|
@@ -305,8 +307,7 @@ export async function downloadSnapshot(odspResolvedUrl, storageToken, logger, sn
|
|
|
305
307
|
}
|
|
306
308
|
}
|
|
307
309
|
function isRedeemSharingLinkError(odspResolvedUrl, error) {
|
|
308
|
-
|
|
309
|
-
if (((_a = odspResolvedUrl.shareLinkInfo) === null || _a === void 0 ? void 0 : _a.sharingLinkToRedeem) !== undefined
|
|
310
|
+
if (odspResolvedUrl.sharingLinkToRedeem !== undefined
|
|
310
311
|
&& (typeof error === "object" && error !== null)
|
|
311
312
|
&& (error.errorType === DriverErrorType.authorizationError
|
|
312
313
|
|| error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError)) {
|
package/lib/fetchSnapshot.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetchSnapshot.js","sourceRoot":"","sources":["../src/fetchSnapshot.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { default as AbortController } from \"abort-controller\";\nimport { v4 as uuid } from \"uuid\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, fromUtf8ToBase64, performance } from \"@fluidframework/common-utils\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport {\n IOdspResolvedUrl,\n ISnapshotOptions,\n OdspErrorType,\n InstrumentedStorageTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { IOdspSnapshot, ISnapshotCachedEntry, IVersionedValueWithEpoch, persistedCacheValueVersion } from \"./contracts\";\nimport { getQueryString } from \"./getQueryString\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport {\n fetchAndParseAsJSONHelper,\n fetchArray,\n getWithRetryForTokenRefresh,\n getWithRetryForTokenRefreshRepeat,\n IOdspResponse,\n ISnapshotContents,\n} from \"./odspUtils\";\nimport { convertOdspSnapshotToSnapsohtTreeAndBlobs } from \"./odspSnapshotParser\";\nimport { parseCompactSnapshotResponse } from \"./compactSnapshotParser\";\nimport { ReadBuffer } from \"./ReadBufferUtils\";\nimport { EpochTracker } from \"./epochTracker\";\n\n/**\n * Fetches a snapshot from the server with a given version id.\n * @param snapshotUrl - snapshot url from where the odsp snapshot will be fetched\n * @param token - token used for authorization in the request\n * @param storageFetchWrapper - Implementation of the get/post methods used to fetch the snapshot\n * @param versionId - id of specific snapshot to be fetched\n * @param fetchFullSnapshot - whether we want to fetch full snapshot(with blobs)\n * @returns A promise of the snapshot and the status code of the response\n */\nexport async function fetchSnapshot(\n snapshotUrl: string,\n token: string | null,\n versionId: string,\n fetchFullSnapshot: boolean,\n logger: ITelemetryLogger,\n snapshotDownloader: (url: string, fetchOptions: {[index: string]: any}) => Promise<IOdspResponse<unknown>>,\n): Promise<ISnapshotContents> {\n const path = `/trees/${versionId}`;\n let queryParams: ISnapshotOptions = {};\n\n if (fetchFullSnapshot) {\n if (versionId !== \"latest\") {\n queryParams = { channels: 1, blobs: 2 };\n } else {\n queryParams = { deltas: 1, channels: 1, blobs: 2 };\n }\n }\n\n const queryString = getQueryString(queryParams);\n const { url, headers } = getUrlAndHeadersWithAuth(`${snapshotUrl}${path}${queryString}`, token);\n const response = await PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: \"fetchSnapshot\",\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n },\n async () => snapshotDownloader(url, { headers }),\n ) as IOdspResponse<IOdspSnapshot>;\n return convertOdspSnapshotToSnapsohtTreeAndBlobs(response.content);\n}\n\nexport async function fetchSnapshotWithRedeem(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n snapshotOptions: ISnapshotOptions | undefined,\n logger: ITelemetryLogger,\n snapshotDownloader: (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => Promise<ISnapshotRequestAndResponseOptions>,\n putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n removeEntries: () => Promise<void>,\n enableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n return fetchLatestSnapshotCore(\n odspResolvedUrl,\n storageTokenFetcher,\n snapshotOptions,\n logger,\n snapshotDownloader,\n putInCache,\n ).catch(async (error) => {\n if (enableRedeemFallback && isRedeemSharingLinkError(odspResolvedUrl, error)) {\n // Execute the redeem fallback\n logger.sendErrorEvent({\n eventName: \"RedeemFallback\",\n errorType: error.errorType,\n }, error);\n await redeemSharingLink(odspResolvedUrl, storageTokenFetcher, logger);\n const odspResolvedUrlWithoutShareLink: IOdspResolvedUrl =\n { ...odspResolvedUrl, shareLinkInfo: { ...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem: undefined } };\n\n return fetchLatestSnapshotCore(\n odspResolvedUrlWithoutShareLink,\n storageTokenFetcher,\n snapshotOptions,\n logger,\n snapshotDownloader,\n putInCache,\n );\n } else {\n throw error;\n }\n }).catch(async (error) => {\n // Clear the cache on 401/403/404 on snapshot fetch from network because this means either the user doesn't\n // have permissions for the file or it was deleted. So, if we do not clear cache, we will continue fetching\n // snapshot from cache in the future.\n if (typeof error === \"object\" && error !== null && error.errorType === DriverErrorType.authorizationError\n || error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError) {\n await removeEntries();\n }\n throw error;\n });\n}\n\nasync function redeemSharingLink(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n logger: ITelemetryLogger,\n) {\n return PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: \"RedeemShareLink\",\n },\n async () => getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n assert(!!odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem,\n 0x1ed /* \"Share link should be present\" */);\n const storageToken = await storageTokenFetcher(tokenFetchOptions, \"RedeemShareLink\");\n const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.shareLinkInfo.sharingLinkToRedeem);\n const redeemUrl = `${odspResolvedUrl.siteUrl}/_api/v2.0/shares/${encodedShareUrl}`;\n const { url, headers } = getUrlAndHeadersWithAuth(redeemUrl, storageToken);\n headers.prefer = \"redeemSharingLink\";\n return fetchAndParseAsJSONHelper(url, { headers });\n }),\n );\n}\n\nasync function fetchLatestSnapshotCore(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n snapshotOptions: ISnapshotOptions | undefined,\n logger: ITelemetryLogger,\n snapshotDownloader: (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => Promise<ISnapshotRequestAndResponseOptions>,\n putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n): Promise<ISnapshotContents> {\n return getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n const storageToken = await storageTokenFetcher(tokenFetchOptions, \"TreesLatest\", true);\n assert(storageToken !== null, 0x1e5 /* \"Storage token should not be null\" */);\n\n let controller: AbortController | undefined;\n if (snapshotOptions?.timeout !== undefined) {\n controller = new AbortController();\n setTimeout(\n () => controller!.abort(),\n snapshotOptions.timeout,\n );\n }\n const perfEvent = {\n eventName: \"TreesLatest\",\n attempts: tokenFetchOptions.refresh ? 2 : 1,\n };\n if (snapshotOptions !== undefined) {\n Object.entries(snapshotOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n perfEvent[`snapshotOption_${key}`] = value;\n }\n });\n }\n // This event measures only successful cases of getLatest call (no tokens, no retries).\n return PerformanceEvent.timedExecAsync(\n logger,\n perfEvent,\n async (event) => {\n const startTime = performance.now();\n const response = await snapshotDownloader(\n odspResolvedUrl,\n storageToken,\n snapshotOptions,\n controller,\n );\n const endTime = performance.now();\n const overallTime = endTime - startTime;\n const snapshot = response.odspSnapshotResponse.content;\n let dnstime: number | undefined; // domainLookupEnd - domainLookupStart\n let redirectTime: number | undefined; // redirectEnd -redirectStart\n let tcpHandshakeTime: number | undefined; // connectEnd - connectStart\n let secureConntime: number | undefined; // connectEnd - secureConnectionStart\n let responseTime: number | undefined; // responsEnd - responseStart\n let fetchStToRespEndTime: number | undefined; // responseEnd - fetchStart\n let reqStToRespEndTime: number | undefined; // responseEnd - requestStart\n let networkTime: number | undefined; // responseEnd - startTime\n const spReqDuration = response.odspSnapshotResponse.headers.get(\"sprequestduration\");\n\n // getEntriesByType is only available in browser performance object\n const resources1 = performance.getEntriesByType?.(\"resource\") ?? [];\n // Usually the latest fetch call is to the end of resources, so we start from the end.\n for (let i = resources1.length - 1; i > 0; i--) {\n const indResTime = resources1[i] as PerformanceResourceTiming;\n const resource_name = indResTime.name;\n const resource_initiatortype = indResTime.initiatorType;\n if ((resource_initiatortype.localeCompare(\"fetch\") === 0)\n && (resource_name.localeCompare(response.requestUrl) === 0)) {\n redirectTime = indResTime.redirectEnd - indResTime.redirectStart;\n dnstime = indResTime.domainLookupEnd - indResTime.domainLookupStart;\n tcpHandshakeTime = indResTime.connectEnd - indResTime.connectStart;\n secureConntime = (indResTime.secureConnectionStart > 0) ?\n (indResTime.connectEnd - indResTime.secureConnectionStart) : 0;\n responseTime = indResTime.responseEnd - indResTime.responseStart;\n fetchStToRespEndTime = (indResTime.fetchStart > 0) ?\n (indResTime.responseEnd - indResTime.fetchStart) : 0;\n reqStToRespEndTime = (indResTime.requestStart > 0) ?\n (indResTime.responseEnd - indResTime.requestStart) : 0;\n networkTime = (indResTime.startTime > 0) ? (indResTime.responseEnd - indResTime.startTime) : 0;\n if (spReqDuration) {\n networkTime = networkTime - parseInt(spReqDuration, 10);\n }\n break;\n }\n }\n\n const { numTrees, numBlobs, encodedBlobsSize } =\n validateAndEvalBlobsAndTrees(response.odspSnapshotResponse.content);\n const clientTime = networkTime ? overallTime - networkTime : undefined;\n\n // There are some scenarios in ODSP where we cannot cache, trees/latest will explicitly tell us when we\n // cannot cache using an HTTP response header.\n const canCache =\n response.odspSnapshotResponse.headers.get(\"disablebrowsercachingofusercontent\") !== \"true\";\n const sequenceNumber: number = snapshot.sequenceNumber ?? 0;\n const seqNumberFromOps = snapshot.ops && snapshot.ops.length > 0 ?\n snapshot.ops[0].sequenceNumber - 1 :\n undefined;\n\n if (!Number.isInteger(sequenceNumber)\n || seqNumberFromOps !== undefined && seqNumberFromOps !== sequenceNumber) {\n logger.sendErrorEvent({ eventName: \"fetchSnapshotError\", sequenceNumber, seqNumberFromOps });\n snapshot.sequenceNumber = undefined;\n } else if (canCache) {\n const fluidEpoch = response.odspSnapshotResponse.headers.get(\"x-fluid-epoch\");\n assert(fluidEpoch !== undefined, 0x1e6 /* \"Epoch should be present in response\" */);\n const value: ISnapshotCachedEntry = {\n ...snapshot,\n cacheEntryTime: Date.now(),\n };\n const valueWithEpoch: IVersionedValueWithEpoch = {\n value,\n fluidEpoch,\n version: persistedCacheValueVersion,\n };\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n putInCache(valueWithEpoch);\n }\n event.end({\n trees: numTrees,\n blobs: snapshot.blobs?.size ?? 0,\n leafNodes: numBlobs,\n encodedBlobsSize,\n sequenceNumber,\n ops: snapshot.ops?.length ?? 0,\n headers: Object.keys(response.requestHeaders).length !== 0 ? true : undefined,\n redirecttime: redirectTime,\n dnsLookuptime: dnstime,\n responsenetworkTime: responseTime,\n tcphandshakeTime: tcpHandshakeTime,\n secureconnectiontime: secureConntime,\n fetchstarttorespendtime: fetchStToRespEndTime,\n reqstarttorespendtime: reqStToRespEndTime,\n overalltime: overallTime,\n networktime: networkTime,\n clienttime: clientTime,\n // Sharing link telemetry regarding sharing link redeem status and performance. Ex: FRL; dur=100,\n // Azure Fluid Relay service; desc=S, FRP; desc=False. Here, FRL is the duration taken for redeem,\n // Azure Fluid Relay service is the redeem status (S means success), and FRP is a flag to indicate\n // if the permission has changed.\n sltelemetry: response.odspSnapshotResponse.headers.get(\"x-fluid-sltelemetry\"),\n ...response.odspSnapshotResponse.commonSpoHeaders,\n });\n return snapshot;\n },\n ).catch((error) => {\n // We hit these errors in stress tests, under load\n // It's useful to try one more time in such case.\n // We might want to add DriverErrorType.offlineError in the future if we see evidence it happens\n // (not in \"real\" offline) and it actually helps.\n if (typeof error === \"object\" && error !== null && (error.errorType === DriverErrorType.fetchFailure ||\n error.errorType === OdspErrorType.fetchTimeout)) {\n error[getWithRetryForTokenRefreshRepeat] = true;\n }\n throw error;\n });\n });\n}\n\ninterface ISnapshotRequestAndResponseOptions {\n odspSnapshotResponse: IOdspResponse<ISnapshotContents>,\n requestUrl: string,\n requestHeaders: {[index: string]: any},\n}\n\n/**\n * This function fetches the older snapshot format which is the json format(IOdspSnapshot).\n * @param odspResolvedUrl - resolved odsp url.\n * @param storageToken - token to do the auth for network request.\n * @param snapshotOptions - Options used to specify how and what to fetch in the snapshot.\n * @param controller - abort controller if caller needs to abort the network call.\n * @param epochTracker - epoch tracker used to add/validate epoch in the network call.\n * @returns fetched snapshot.\n */\nasync function fetchSnapshotContentsCoreV1(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n): Promise<ISnapshotRequestAndResponseOptions> {\n const snapshotUrl = odspResolvedUrl.endpoints.snapshotStorageUrl;\n const url = `${snapshotUrl}/trees/latest?ump=1`;\n const formBoundary = uuid();\n const formParams: string[] = [];\n formParams.push(`--${formBoundary}`);\n formParams.push(`Authorization: Bearer ${storageToken}`);\n formParams.push(`X-HTTP-Method-Override: GET`);\n if (snapshotOptions !== undefined) {\n Object.entries(snapshotOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n formParams.push(`${key}: ${value}`);\n }\n });\n }\n if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem) {\n formParams.push(`sl: ${odspResolvedUrl.shareLinkInfo.sharingLinkToRedeem}`);\n }\n formParams.push(`_post: 1`);\n formParams.push(`\\r\\n--${formBoundary}--`);\n const postBody = formParams.join(\"\\r\\n\");\n const headers: {[index: string]: any} = {\n \"Content-Type\": `multipart/form-data;boundary=${formBoundary}`,\n };\n\n const fetchOptions = {\n body: postBody,\n headers,\n signal: controller?.signal,\n method: \"POST\",\n };\n const response = await (epochTracker?.fetchAndParseAsJSON<IOdspSnapshot>(url, fetchOptions, \"treesLatest\", true) ??\n fetchAndParseAsJSONHelper<IOdspSnapshot>(url, fetchOptions));\n const snapshotContents: ISnapshotContents = convertOdspSnapshotToSnapsohtTreeAndBlobs(response.content);\n const finalSnapshotContents: IOdspResponse<ISnapshotContents> = { ...response, content: snapshotContents };\n return {\n odspSnapshotResponse: finalSnapshotContents,\n requestHeaders: headers,\n requestUrl: url,\n };\n}\n\n/**\n * This function fetches the binary compact snapshot format. This is an experimental feature\n * and is behind a feature flag.\n * @param odspResolvedUrl - resolved odsp url.\n * @param storageToken - token to do the auth for network request.\n * @param snapshotOptions - Options used to specify how and what to fetch in the snapshot.\n * @param controller - abort controller if caller needs to abort the network call.\n * @param epochTracker - epoch tracker used to add/validate epoch in the network call.\n * @returns fetched snapshot.\n */\nasync function fetchSnapshotContentsCoreV2(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n): Promise<ISnapshotRequestAndResponseOptions> {\n const fullUrl = `${odspResolvedUrl.siteUrl}/_api/v2.1/drives/${odspResolvedUrl.driveId}/items/${\n odspResolvedUrl.itemId}/opStream/attachments/latest/content`;\n const queryParams = { ...snapshotOptions };\n if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem) {\n // eslint-disable-next-line @typescript-eslint/dot-notation\n queryParams[\"sl\"] = odspResolvedUrl.shareLinkInfo.sharingLinkToRedeem;\n }\n const queryString = getQueryString(queryParams);\n const { url, headers } = getUrlAndHeadersWithAuth(`${fullUrl}${queryString}`, storageToken);\n const fetchOptions = {\n headers,\n signal: controller?.signal,\n };\n const response = await (epochTracker?.fetchArray(url, fetchOptions, \"treesLatest\") ??\n fetchArray(url, fetchOptions));\n const snapshotContents: ISnapshotContents = parseCompactSnapshotResponse(\n new ReadBuffer(new Uint8Array(response.content)));\n const finalSnapshotContents: IOdspResponse<ISnapshotContents> = { ...response, content: snapshotContents };\n return {\n odspSnapshotResponse: finalSnapshotContents,\n requestHeaders: headers,\n requestUrl: url,\n };\n}\n\nfunction validateAndEvalBlobsAndTrees(snapshot: ISnapshotContents) {\n assert(snapshot.snapshotTree !== undefined,\n 0x200 /* \"Returned odsp snapshot is malformed. No trees!\" */);\n assert(snapshot.blobs !== undefined,\n 0x201 /* \"Returned odsp snapshot is malformed. No blobs!\" */);\n const numTrees = countTreesInSnapshotTree(snapshot.snapshotTree);\n const numBlobs = snapshot.blobs.size;\n let encodedBlobsSize = 0;\n for (const [_, blobContent] of snapshot.blobs) {\n encodedBlobsSize += blobContent.byteLength;\n }\n return { numTrees, numBlobs, encodedBlobsSize };\n}\n\nfunction countTreesInSnapshotTree(snapshotTree: ISnapshotTree): number {\n let numTrees = 0;\n for (const [_, tree] of Object.entries(snapshotTree.trees)) {\n numTrees += 1;\n numTrees += countTreesInSnapshotTree(tree);\n }\n return numTrees;\n}\n\nexport async function downloadSnapshot(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n logger: ITelemetryLogger,\n snapshotOptions: ISnapshotOptions | undefined,\n fetchBinarySnapshotFormat?: boolean,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n): Promise<ISnapshotRequestAndResponseOptions> {\n if (fetchBinarySnapshotFormat) {\n // Logging an event here as it is not supposed to be used in production yet and only in experimental mode.\n logger.sendTelemetryEvent({ eventName: \"BinarySnapshotFetched\" });\n return fetchSnapshotContentsCoreV2(odspResolvedUrl, storageToken, snapshotOptions, controller, epochTracker);\n } else {\n return fetchSnapshotContentsCoreV1(odspResolvedUrl, storageToken, snapshotOptions, controller, epochTracker);\n }\n}\n\nfunction isRedeemSharingLinkError(odspResolvedUrl: IOdspResolvedUrl, error: any) {\n if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined\n && (typeof error === \"object\" && error !== null)\n && (error.errorType === DriverErrorType.authorizationError\n || error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError)) {\n return true;\n }\n return false;\n}\n\nfunction getEncodedShareUrl(url: string): string {\n /**\n * Encode the url to accepted format by Sharepoint\n * https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/shares_get\n */\n let encodedUrl = fromUtf8ToBase64(encodeURI(url));\n encodedUrl = encodedUrl\n .replace(/=+$/g, \"\")\n .replace(/\\//g, \"_\")\n .replace(/\\+/g, \"-\");\n encodedUrl = \"u!\".concat(encodedUrl);\n return encodedUrl;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"fetchSnapshot.js","sourceRoot":"","sources":["../src/fetchSnapshot.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { default as AbortController } from \"abort-controller\";\nimport { v4 as uuid } from \"uuid\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, fromUtf8ToBase64, performance } from \"@fluidframework/common-utils\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport {\n IOdspResolvedUrl,\n ISnapshotOptions,\n OdspErrorType,\n InstrumentedStorageTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { IOdspSnapshot, ISnapshotCachedEntry, IVersionedValueWithEpoch, persistedCacheValueVersion } from \"./contracts\";\nimport { getQueryString } from \"./getQueryString\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport {\n fetchAndParseAsJSONHelper,\n fetchArray,\n getWithRetryForTokenRefresh,\n getWithRetryForTokenRefreshRepeat,\n IOdspResponse,\n ISnapshotContents,\n} from \"./odspUtils\";\nimport { convertOdspSnapshotToSnapsohtTreeAndBlobs } from \"./odspSnapshotParser\";\nimport { parseCompactSnapshotResponse } from \"./compactSnapshotParser\";\nimport { ReadBuffer } from \"./ReadBufferUtils\";\nimport { EpochTracker } from \"./epochTracker\";\n\n/**\n * Fetches a snapshot from the server with a given version id.\n * @param snapshotUrl - snapshot url from where the odsp snapshot will be fetched\n * @param token - token used for authorization in the request\n * @param storageFetchWrapper - Implementation of the get/post methods used to fetch the snapshot\n * @param versionId - id of specific snapshot to be fetched\n * @param fetchFullSnapshot - whether we want to fetch full snapshot(with blobs)\n * @returns A promise of the snapshot and the status code of the response\n */\nexport async function fetchSnapshot(\n snapshotUrl: string,\n token: string | null,\n versionId: string,\n fetchFullSnapshot: boolean,\n logger: ITelemetryLogger,\n snapshotDownloader: (url: string, fetchOptions: {[index: string]: any}) => Promise<IOdspResponse<unknown>>,\n): Promise<ISnapshotContents> {\n const path = `/trees/${versionId}`;\n let queryParams: ISnapshotOptions = {};\n\n if (fetchFullSnapshot) {\n if (versionId !== \"latest\") {\n queryParams = { channels: 1, blobs: 2 };\n } else {\n queryParams = { deltas: 1, channels: 1, blobs: 2 };\n }\n }\n\n const queryString = getQueryString(queryParams);\n const { url, headers } = getUrlAndHeadersWithAuth(`${snapshotUrl}${path}${queryString}`, token);\n const response = await PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: \"fetchSnapshot\",\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n },\n async () => snapshotDownloader(url, { headers }),\n ) as IOdspResponse<IOdspSnapshot>;\n return convertOdspSnapshotToSnapsohtTreeAndBlobs(response.content);\n}\n\nexport async function fetchSnapshotWithRedeem(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n snapshotOptions: ISnapshotOptions | undefined,\n logger: ITelemetryLogger,\n snapshotDownloader: (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => Promise<ISnapshotRequestAndResponseOptions>,\n putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n removeEntries: () => Promise<void>,\n enableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n return fetchLatestSnapshotCore(\n odspResolvedUrl,\n storageTokenFetcher,\n snapshotOptions,\n logger,\n snapshotDownloader,\n putInCache,\n ).catch(async (error) => {\n if (enableRedeemFallback && isRedeemSharingLinkError(odspResolvedUrl, error)) {\n // Execute the redeem fallback\n logger.sendErrorEvent({\n eventName: \"RedeemFallback\",\n errorType: error.errorType,\n }, error);\n await redeemSharingLink(odspResolvedUrl, storageTokenFetcher, logger);\n const odspResolvedUrlWithoutShareLink: IOdspResolvedUrl =\n { ...odspResolvedUrl, sharingLinkToRedeem: undefined };\n\n if(odspResolvedUrlWithoutShareLink.shareLinkInfo) {\n odspResolvedUrlWithoutShareLink.shareLinkInfo = {\n ...odspResolvedUrlWithoutShareLink.shareLinkInfo,\n sharingLinkToRedeem: undefined,\n };\n }\n\n return fetchLatestSnapshotCore(\n odspResolvedUrlWithoutShareLink,\n storageTokenFetcher,\n snapshotOptions,\n logger,\n snapshotDownloader,\n putInCache,\n );\n } else {\n throw error;\n }\n }).catch(async (error) => {\n // Clear the cache on 401/403/404 on snapshot fetch from network because this means either the user doesn't\n // have permissions for the file or it was deleted. So, if we do not clear cache, we will continue fetching\n // snapshot from cache in the future.\n if (typeof error === \"object\" && error !== null && error.errorType === DriverErrorType.authorizationError\n || error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError) {\n await removeEntries();\n }\n throw error;\n });\n}\n\nasync function redeemSharingLink(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n logger: ITelemetryLogger,\n) {\n return PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: \"RedeemShareLink\",\n },\n async () => getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n assert(!!odspResolvedUrl.sharingLinkToRedeem,\n 0x1ed /* \"Share link should be present\" */);\n const storageToken = await storageTokenFetcher(tokenFetchOptions, \"RedeemShareLink\");\n const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.sharingLinkToRedeem);\n const redeemUrl = `${odspResolvedUrl.siteUrl}/_api/v2.0/shares/${encodedShareUrl}`;\n const { url, headers } = getUrlAndHeadersWithAuth(redeemUrl, storageToken);\n headers.prefer = \"redeemSharingLink\";\n return fetchAndParseAsJSONHelper(url, { headers });\n }),\n );\n}\n\nasync function fetchLatestSnapshotCore(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n snapshotOptions: ISnapshotOptions | undefined,\n logger: ITelemetryLogger,\n snapshotDownloader: (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => Promise<ISnapshotRequestAndResponseOptions>,\n putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n): Promise<ISnapshotContents> {\n return getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n const storageToken = await storageTokenFetcher(tokenFetchOptions, \"TreesLatest\", true);\n assert(storageToken !== null, 0x1e5 /* \"Storage token should not be null\" */);\n\n let controller: AbortController | undefined;\n if (snapshotOptions?.timeout !== undefined) {\n controller = new AbortController();\n setTimeout(\n () => controller!.abort(),\n snapshotOptions.timeout,\n );\n }\n const perfEvent = {\n eventName: \"TreesLatest\",\n attempts: tokenFetchOptions.refresh ? 2 : 1,\n };\n if (snapshotOptions !== undefined) {\n Object.entries(snapshotOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n perfEvent[`snapshotOption_${key}`] = value;\n }\n });\n }\n // This event measures only successful cases of getLatest call (no tokens, no retries).\n return PerformanceEvent.timedExecAsync(\n logger,\n perfEvent,\n async (event) => {\n const startTime = performance.now();\n const response = await snapshotDownloader(\n odspResolvedUrl,\n storageToken,\n snapshotOptions,\n controller,\n );\n const endTime = performance.now();\n const overallTime = endTime - startTime;\n const snapshot = response.odspSnapshotResponse.content;\n let dnstime: number | undefined; // domainLookupEnd - domainLookupStart\n let redirectTime: number | undefined; // redirectEnd -redirectStart\n let tcpHandshakeTime: number | undefined; // connectEnd - connectStart\n let secureConntime: number | undefined; // connectEnd - secureConnectionStart\n let responseTime: number | undefined; // responsEnd - responseStart\n let fetchStToRespEndTime: number | undefined; // responseEnd - fetchStart\n let reqStToRespEndTime: number | undefined; // responseEnd - requestStart\n let networkTime: number | undefined; // responseEnd - startTime\n const spReqDuration = response.odspSnapshotResponse.headers.get(\"sprequestduration\");\n\n // getEntriesByType is only available in browser performance object\n const resources1 = performance.getEntriesByType?.(\"resource\") ?? [];\n // Usually the latest fetch call is to the end of resources, so we start from the end.\n for (let i = resources1.length - 1; i > 0; i--) {\n const indResTime = resources1[i] as PerformanceResourceTiming;\n const resource_name = indResTime.name;\n const resource_initiatortype = indResTime.initiatorType;\n if ((resource_initiatortype.localeCompare(\"fetch\") === 0)\n && (resource_name.localeCompare(response.requestUrl) === 0)) {\n redirectTime = indResTime.redirectEnd - indResTime.redirectStart;\n dnstime = indResTime.domainLookupEnd - indResTime.domainLookupStart;\n tcpHandshakeTime = indResTime.connectEnd - indResTime.connectStart;\n secureConntime = (indResTime.secureConnectionStart > 0) ?\n (indResTime.connectEnd - indResTime.secureConnectionStart) : 0;\n responseTime = indResTime.responseEnd - indResTime.responseStart;\n fetchStToRespEndTime = (indResTime.fetchStart > 0) ?\n (indResTime.responseEnd - indResTime.fetchStart) : 0;\n reqStToRespEndTime = (indResTime.requestStart > 0) ?\n (indResTime.responseEnd - indResTime.requestStart) : 0;\n networkTime = (indResTime.startTime > 0) ? (indResTime.responseEnd - indResTime.startTime) : 0;\n if (spReqDuration) {\n networkTime = networkTime - parseInt(spReqDuration, 10);\n }\n break;\n }\n }\n\n const { numTrees, numBlobs, encodedBlobsSize } =\n validateAndEvalBlobsAndTrees(response.odspSnapshotResponse.content);\n const clientTime = networkTime ? overallTime - networkTime : undefined;\n\n // There are some scenarios in ODSP where we cannot cache, trees/latest will explicitly tell us when we\n // cannot cache using an HTTP response header.\n const canCache =\n response.odspSnapshotResponse.headers.get(\"disablebrowsercachingofusercontent\") !== \"true\";\n const sequenceNumber: number = snapshot.sequenceNumber ?? 0;\n const seqNumberFromOps = snapshot.ops && snapshot.ops.length > 0 ?\n snapshot.ops[0].sequenceNumber - 1 :\n undefined;\n\n if (!Number.isInteger(sequenceNumber)\n || seqNumberFromOps !== undefined && seqNumberFromOps !== sequenceNumber) {\n logger.sendErrorEvent({ eventName: \"fetchSnapshotError\", sequenceNumber, seqNumberFromOps });\n snapshot.sequenceNumber = undefined;\n } else if (canCache) {\n const fluidEpoch = response.odspSnapshotResponse.headers.get(\"x-fluid-epoch\");\n assert(fluidEpoch !== undefined, 0x1e6 /* \"Epoch should be present in response\" */);\n const value: ISnapshotCachedEntry = {\n ...snapshot,\n cacheEntryTime: Date.now(),\n };\n const valueWithEpoch: IVersionedValueWithEpoch = {\n value,\n fluidEpoch,\n version: persistedCacheValueVersion,\n };\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n putInCache(valueWithEpoch);\n }\n event.end({\n trees: numTrees,\n blobs: snapshot.blobs?.size ?? 0,\n leafNodes: numBlobs,\n encodedBlobsSize,\n sequenceNumber,\n ops: snapshot.ops?.length ?? 0,\n headers: Object.keys(response.requestHeaders).length !== 0 ? true : undefined,\n redirecttime: redirectTime,\n dnsLookuptime: dnstime,\n responsenetworkTime: responseTime,\n tcphandshakeTime: tcpHandshakeTime,\n secureconnectiontime: secureConntime,\n fetchstarttorespendtime: fetchStToRespEndTime,\n reqstarttorespendtime: reqStToRespEndTime,\n overalltime: overallTime,\n networktime: networkTime,\n clienttime: clientTime,\n // Sharing link telemetry regarding sharing link redeem status and performance. Ex: FRL; dur=100,\n // Azure Fluid Relay service; desc=S, FRP; desc=False. Here, FRL is the duration taken for redeem,\n // Azure Fluid Relay service is the redeem status (S means success), and FRP is a flag to indicate\n // if the permission has changed.\n sltelemetry: response.odspSnapshotResponse.headers.get(\"x-fluid-sltelemetry\"),\n ...response.odspSnapshotResponse.commonSpoHeaders,\n });\n return snapshot;\n },\n ).catch((error) => {\n // We hit these errors in stress tests, under load\n // It's useful to try one more time in such case.\n // We might want to add DriverErrorType.offlineError in the future if we see evidence it happens\n // (not in \"real\" offline) and it actually helps.\n if (typeof error === \"object\" && error !== null && (error.errorType === DriverErrorType.fetchFailure ||\n error.errorType === OdspErrorType.fetchTimeout)) {\n error[getWithRetryForTokenRefreshRepeat] = true;\n }\n throw error;\n });\n });\n}\n\ninterface ISnapshotRequestAndResponseOptions {\n odspSnapshotResponse: IOdspResponse<ISnapshotContents>,\n requestUrl: string,\n requestHeaders: {[index: string]: any},\n}\n\n/**\n * This function fetches the older snapshot format which is the json format(IOdspSnapshot).\n * @param odspResolvedUrl - resolved odsp url.\n * @param storageToken - token to do the auth for network request.\n * @param snapshotOptions - Options used to specify how and what to fetch in the snapshot.\n * @param controller - abort controller if caller needs to abort the network call.\n * @param epochTracker - epoch tracker used to add/validate epoch in the network call.\n * @returns fetched snapshot.\n */\nasync function fetchSnapshotContentsCoreV1(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n): Promise<ISnapshotRequestAndResponseOptions> {\n const snapshotUrl = odspResolvedUrl.endpoints.snapshotStorageUrl;\n const url = `${snapshotUrl}/trees/latest?ump=1`;\n const formBoundary = uuid();\n const formParams: string[] = [];\n formParams.push(`--${formBoundary}`);\n formParams.push(`Authorization: Bearer ${storageToken}`);\n formParams.push(`X-HTTP-Method-Override: GET`);\n if (snapshotOptions !== undefined) {\n Object.entries(snapshotOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n formParams.push(`${key}: ${value}`);\n }\n });\n }\n if (odspResolvedUrl.sharingLinkToRedeem) {\n formParams.push(`sl: ${odspResolvedUrl.sharingLinkToRedeem}`);\n }\n formParams.push(`_post: 1`);\n formParams.push(`\\r\\n--${formBoundary}--`);\n const postBody = formParams.join(\"\\r\\n\");\n const headers: {[index: string]: any} = {\n \"Content-Type\": `multipart/form-data;boundary=${formBoundary}`,\n };\n\n const fetchOptions = {\n body: postBody,\n headers,\n signal: controller?.signal,\n method: \"POST\",\n };\n const response = await (epochTracker?.fetchAndParseAsJSON<IOdspSnapshot>(url, fetchOptions, \"treesLatest\", true) ??\n fetchAndParseAsJSONHelper<IOdspSnapshot>(url, fetchOptions));\n const snapshotContents: ISnapshotContents = convertOdspSnapshotToSnapsohtTreeAndBlobs(response.content);\n const finalSnapshotContents: IOdspResponse<ISnapshotContents> = { ...response, content: snapshotContents };\n return {\n odspSnapshotResponse: finalSnapshotContents,\n requestHeaders: headers,\n requestUrl: url,\n };\n}\n\n/**\n * This function fetches the binary compact snapshot format. This is an experimental feature\n * and is behind a feature flag.\n * @param odspResolvedUrl - resolved odsp url.\n * @param storageToken - token to do the auth for network request.\n * @param snapshotOptions - Options used to specify how and what to fetch in the snapshot.\n * @param controller - abort controller if caller needs to abort the network call.\n * @param epochTracker - epoch tracker used to add/validate epoch in the network call.\n * @returns fetched snapshot.\n */\nasync function fetchSnapshotContentsCoreV2(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n): Promise<ISnapshotRequestAndResponseOptions> {\n const fullUrl = `${odspResolvedUrl.siteUrl}/_api/v2.1/drives/${odspResolvedUrl.driveId}/items/${\n odspResolvedUrl.itemId}/opStream/attachments/latest/content`;\n const queryParams = { ...snapshotOptions };\n if (odspResolvedUrl.sharingLinkToRedeem) {\n // eslint-disable-next-line @typescript-eslint/dot-notation\n queryParams[\"sl\"] = odspResolvedUrl.sharingLinkToRedeem;\n }\n const queryString = getQueryString(queryParams);\n const { url, headers } = getUrlAndHeadersWithAuth(`${fullUrl}${queryString}`, storageToken);\n const fetchOptions = {\n headers,\n signal: controller?.signal,\n };\n const response = await (epochTracker?.fetchArray(url, fetchOptions, \"treesLatest\") ??\n fetchArray(url, fetchOptions));\n const snapshotContents: ISnapshotContents = parseCompactSnapshotResponse(\n new ReadBuffer(new Uint8Array(response.content)));\n const finalSnapshotContents: IOdspResponse<ISnapshotContents> = { ...response, content: snapshotContents };\n return {\n odspSnapshotResponse: finalSnapshotContents,\n requestHeaders: headers,\n requestUrl: url,\n };\n}\n\nfunction validateAndEvalBlobsAndTrees(snapshot: ISnapshotContents) {\n assert(snapshot.snapshotTree !== undefined,\n 0x200 /* \"Returned odsp snapshot is malformed. No trees!\" */);\n assert(snapshot.blobs !== undefined,\n 0x201 /* \"Returned odsp snapshot is malformed. No blobs!\" */);\n const numTrees = countTreesInSnapshotTree(snapshot.snapshotTree);\n const numBlobs = snapshot.blobs.size;\n let encodedBlobsSize = 0;\n for (const [_, blobContent] of snapshot.blobs) {\n encodedBlobsSize += blobContent.byteLength;\n }\n return { numTrees, numBlobs, encodedBlobsSize };\n}\n\nfunction countTreesInSnapshotTree(snapshotTree: ISnapshotTree): number {\n let numTrees = 0;\n for (const [_, tree] of Object.entries(snapshotTree.trees)) {\n numTrees += 1;\n numTrees += countTreesInSnapshotTree(tree);\n }\n return numTrees;\n}\n\nexport async function downloadSnapshot(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n logger: ITelemetryLogger,\n snapshotOptions: ISnapshotOptions | undefined,\n fetchBinarySnapshotFormat?: boolean,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n): Promise<ISnapshotRequestAndResponseOptions> {\n if (fetchBinarySnapshotFormat) {\n // Logging an event here as it is not supposed to be used in production yet and only in experimental mode.\n logger.sendTelemetryEvent({ eventName: \"BinarySnapshotFetched\" });\n return fetchSnapshotContentsCoreV2(odspResolvedUrl, storageToken, snapshotOptions, controller, epochTracker);\n } else {\n return fetchSnapshotContentsCoreV1(odspResolvedUrl, storageToken, snapshotOptions, controller, epochTracker);\n }\n}\n\nfunction isRedeemSharingLinkError(odspResolvedUrl: IOdspResolvedUrl, error: any) {\n if (odspResolvedUrl.sharingLinkToRedeem !== undefined\n && (typeof error === \"object\" && error !== null)\n && (error.errorType === DriverErrorType.authorizationError\n || error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError)) {\n return true;\n }\n return false;\n}\n\nfunction getEncodedShareUrl(url: string): string {\n /**\n * Encode the url to accepted format by Sharepoint\n * https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/shares_get\n */\n let encodedUrl = fromUtf8ToBase64(encodeURI(url));\n encodedUrl = encodedUrl\n .replace(/=+$/g, \"\")\n .replace(/\\//g, \"_\")\n .replace(/\\+/g, \"-\");\n encodedUrl = \"u!\".concat(encodedUrl);\n return encodedUrl;\n}\n"]}
|
package/lib/getFileLink.js
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { assert, delay } from "@fluidframework/common-utils";
|
|
6
|
-
import { canRetryOnError, getRetryDelayFromError } from "@fluidframework/driver-utils";
|
|
6
|
+
import { canRetryOnError, getRetryDelayFromError, NonRetryableError } from "@fluidframework/driver-utils";
|
|
7
7
|
import { PerformanceEvent } from "@fluidframework/telemetry-utils";
|
|
8
|
-
import {
|
|
8
|
+
import { DriverErrorType } from "@fluidframework/driver-definitions";
|
|
9
9
|
import { tokenFromResponse, } from "@fluidframework/odsp-driver-definitions";
|
|
10
10
|
import { getUrlAndHeadersWithAuth } from "./getUrlAndHeadersWithAuth";
|
|
11
11
|
import { fetchHelper, getWithRetryForTokenRefresh } from "./odspUtils";
|
|
@@ -87,7 +87,7 @@ async function getFileLinkCore(getToken, odspUrlParts, identityType, logger) {
|
|
|
87
87
|
const directUrl = (_a = sharingInfo === null || sharingInfo === void 0 ? void 0 : sharingInfo.d) === null || _a === void 0 ? void 0 : _a.directUrl;
|
|
88
88
|
if (typeof directUrl !== "string") {
|
|
89
89
|
// This will retry once in getWithRetryForTokenRefresh
|
|
90
|
-
|
|
90
|
+
throw new NonRetryableError("getFileLinkCoreMalformedResponse", "Malformed GetSharingInformation response", DriverErrorType.incorrectServerResponse);
|
|
91
91
|
}
|
|
92
92
|
return directUrl;
|
|
93
93
|
});
|
|
@@ -116,7 +116,7 @@ async function getFileItemLite(getToken, odspUrlParts, logger) {
|
|
|
116
116
|
const responseJson = await response.content.json();
|
|
117
117
|
if (!isFileItemLite(responseJson)) {
|
|
118
118
|
// This will retry once in getWithRetryForTokenRefresh
|
|
119
|
-
|
|
119
|
+
throw new NonRetryableError("getFileItemLiteMalformedResponse", "Malformed getFileItemLite response", DriverErrorType.incorrectServerResponse);
|
|
120
120
|
}
|
|
121
121
|
return responseJson;
|
|
122
122
|
});
|
package/lib/getFileLink.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getFileLink.js","sourceRoot":"","sources":["../src/getFileLink.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, delay } from \"@fluidframework/common-utils\";\nimport { canRetryOnError, getRetryDelayFromError } from \"@fluidframework/driver-utils\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { fetchIncorrectResponse, throwOdspNetworkError } from \"@fluidframework/odsp-doclib-utils\";\nimport {\n IOdspUrlParts,\n OdspResourceTokenFetchOptions,\n IdentityType,\n TokenFetcher,\n tokenFromResponse,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport { fetchHelper, getWithRetryForTokenRefresh } from \"./odspUtils\";\n\n// Store cached responses for the lifetime of web session as file link remains the same for given file item\nconst fileLinkCache = new Map<string, Promise<string>>();\n\n/**\n * Returns file link for a file with given drive and item ids.\n * Scope needed: files.readwrite.all.\n * This function keeps retrying if it gets a retriable error or wait for some delay if it gets a\n * throttling error. In future, we are thinking of app allowing to pass some cancel token, with which\n * we would be able to stop retrying.\n * @param getToken - used to fetch access tokens needed to execute operation\n * @param siteUrl - url of the site that contains the file\n * @param driveId - drive where file is stored\n * @param itemId - file id\n * @param identityType - type of client account\n * @param logger - used to log results of operation, including any error\n * @returns Promise which resolves to file link url when successful; otherwise, undefined.\n */\nexport async function getFileLink(\n getToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n odspUrlParts: IOdspUrlParts,\n identityType: IdentityType,\n logger: ITelemetryLogger,\n): Promise<string> {\n const cacheKey = `${odspUrlParts.siteUrl}_${odspUrlParts.driveId}_${odspUrlParts.itemId}`;\n const maybeFileLinkCacheEntry = fileLinkCache.get(cacheKey);\n if (maybeFileLinkCacheEntry !== undefined) {\n return maybeFileLinkCacheEntry;\n }\n\n const valueGenerator = async function() {\n let result: string | undefined;\n let success = false;\n let retryAfterMs = 1000;\n do {\n try {\n result = await getFileLinkCore(getToken, odspUrlParts, identityType, logger);\n success = true;\n } catch (err) {\n // If it is not retriable, then just throw\n if (!canRetryOnError(err)) {\n // Delete from the cache to permit retrying later.\n fileLinkCache.delete(cacheKey);\n throw err;\n }\n // If the error is throttling error, then wait for the specified time before retrying.\n // If the waitTime is not specified, then we start with retrying immediately to max of 8s.\n retryAfterMs = getRetryDelayFromError(err) ?? Math.min(retryAfterMs * 2, 8000);\n await delay(retryAfterMs);\n }\n } while (!success);\n\n // We are guaranteed to run the getFileLinkCore at least once with successful result (which must be a string)\n assert(result !== undefined, 0x292 /* \"Unexpected undefined result from getFileLinkCore\" */);\n return result;\n };\n const fileLink = valueGenerator();\n fileLinkCache.set(cacheKey, fileLink);\n return fileLink;\n}\n\nasync function getFileLinkCore(\n getToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n odspUrlParts: IOdspUrlParts,\n identityType: IdentityType,\n logger: ITelemetryLogger,\n): Promise<string> {\n const fileItem = await getFileItemLite(getToken, odspUrlParts, logger);\n\n // ODC canonical link does not require any additional processing\n if (identityType === \"Consumer\") {\n return fileItem.webUrl;\n }\n\n // ODSP link requires extra call to return link that is resistant to file being renamed or moved to different folder\n return PerformanceEvent.timedExecAsync(\n logger,\n { eventName: \"odspFileLink\", requestName: \"getSharingInformation\" },\n async (event) => {\n let attempts = 0;\n let additionalProps;\n const fileLink = await getWithRetryForTokenRefresh(async (options) => {\n attempts++;\n const token = await getToken({ ...options, ... odspUrlParts });\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${odspUrlParts.siteUrl}/_api/web/GetFileByUrl(@a1)/ListItemAllFields/GetSharingInformation?@a1=${\n encodeURIComponent(`'${fileItem.webDavUrl}'`)\n }`, tokenFromResponse(token));\n const requestInit = {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json;odata=verbose\",\n \"Accept\": \"application/json;odata=verbose\",\n ...headers,\n },\n };\n const response = await fetchHelper(url, requestInit);\n additionalProps = response.commonSpoHeaders;\n\n const sharingInfo = await response.content.json();\n const directUrl = sharingInfo?.d?.directUrl;\n if (typeof directUrl !== \"string\") {\n // This will retry once in getWithRetryForTokenRefresh\n throwOdspNetworkError(\"malformedGetSharingInformationResponse\", fetchIncorrectResponse);\n }\n return directUrl;\n });\n event.end({ ...additionalProps, attempts });\n return fileLink;\n },\n );\n}\n\n/**\n * This represents a lite version of file item containing only the webUrl and webDavUrl properties\n */\ninterface FileItemLite {\n webUrl: string;\n webDavUrl: string;\n}\n\nconst isFileItemLite = (maybeFileItemLite: any): maybeFileItemLite is FileItemLite => {\n if (typeof maybeFileItemLite.webUrl !== \"string\" || typeof maybeFileItemLite.webDavUrl !== \"string\") {\n return false;\n }\n return true;\n};\n\nasync function getFileItemLite(\n getToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n odspUrlParts: IOdspUrlParts,\n logger: ITelemetryLogger,\n): Promise<FileItemLite> {\n return PerformanceEvent.timedExecAsync(\n logger,\n { eventName: \"odspFileLink\", requestName: \"getFileItemLite\" },\n async (event) => {\n let attempts = 0;\n let additionalProps;\n const fileItem = await getWithRetryForTokenRefresh(async (options) => {\n attempts++;\n const {siteUrl, driveId, itemId} = odspUrlParts;\n const token = await getToken({ ...options, siteUrl, driveId, itemId});\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${siteUrl}/_api/v2.0/drives/${driveId}/items/${itemId}?select=webUrl,webDavUrl`,\n tokenFromResponse(token),\n );\n const requestInit = { method: \"GET\", headers };\n const response = await fetchHelper(url, requestInit);\n additionalProps = response.commonSpoHeaders;\n\n const responseJson = await response.content.json();\n if (!isFileItemLite(responseJson)) {\n // This will retry once in getWithRetryForTokenRefresh\n throwOdspNetworkError(\"malformedGetFileItemLiteResponse\", fetchIncorrectResponse);\n }\n return responseJson;\n });\n event.end({ ...additionalProps, attempts });\n return fileItem;\n },\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"getFileLink.js","sourceRoot":"","sources":["../src/getFileLink.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, delay } from \"@fluidframework/common-utils\";\nimport { canRetryOnError, getRetryDelayFromError, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport {\n IOdspUrlParts,\n OdspResourceTokenFetchOptions,\n IdentityType,\n TokenFetcher,\n tokenFromResponse,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport { fetchHelper, getWithRetryForTokenRefresh } from \"./odspUtils\";\n\n// Store cached responses for the lifetime of web session as file link remains the same for given file item\nconst fileLinkCache = new Map<string, Promise<string>>();\n\n/**\n * Returns file link for a file with given drive and item ids.\n * Scope needed: files.readwrite.all.\n * This function keeps retrying if it gets a retriable error or wait for some delay if it gets a\n * throttling error. In future, we are thinking of app allowing to pass some cancel token, with which\n * we would be able to stop retrying.\n * @param getToken - used to fetch access tokens needed to execute operation\n * @param siteUrl - url of the site that contains the file\n * @param driveId - drive where file is stored\n * @param itemId - file id\n * @param identityType - type of client account\n * @param logger - used to log results of operation, including any error\n * @returns Promise which resolves to file link url when successful; otherwise, undefined.\n */\nexport async function getFileLink(\n getToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n odspUrlParts: IOdspUrlParts,\n identityType: IdentityType,\n logger: ITelemetryLogger,\n): Promise<string> {\n const cacheKey = `${odspUrlParts.siteUrl}_${odspUrlParts.driveId}_${odspUrlParts.itemId}`;\n const maybeFileLinkCacheEntry = fileLinkCache.get(cacheKey);\n if (maybeFileLinkCacheEntry !== undefined) {\n return maybeFileLinkCacheEntry;\n }\n\n const valueGenerator = async function() {\n let result: string | undefined;\n let success = false;\n let retryAfterMs = 1000;\n do {\n try {\n result = await getFileLinkCore(getToken, odspUrlParts, identityType, logger);\n success = true;\n } catch (err) {\n // If it is not retriable, then just throw\n if (!canRetryOnError(err)) {\n // Delete from the cache to permit retrying later.\n fileLinkCache.delete(cacheKey);\n throw err;\n }\n // If the error is throttling error, then wait for the specified time before retrying.\n // If the waitTime is not specified, then we start with retrying immediately to max of 8s.\n retryAfterMs = getRetryDelayFromError(err) ?? Math.min(retryAfterMs * 2, 8000);\n await delay(retryAfterMs);\n }\n } while (!success);\n\n // We are guaranteed to run the getFileLinkCore at least once with successful result (which must be a string)\n assert(result !== undefined, 0x292 /* \"Unexpected undefined result from getFileLinkCore\" */);\n return result;\n };\n const fileLink = valueGenerator();\n fileLinkCache.set(cacheKey, fileLink);\n return fileLink;\n}\n\nasync function getFileLinkCore(\n getToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n odspUrlParts: IOdspUrlParts,\n identityType: IdentityType,\n logger: ITelemetryLogger,\n): Promise<string> {\n const fileItem = await getFileItemLite(getToken, odspUrlParts, logger);\n\n // ODC canonical link does not require any additional processing\n if (identityType === \"Consumer\") {\n return fileItem.webUrl;\n }\n\n // ODSP link requires extra call to return link that is resistant to file being renamed or moved to different folder\n return PerformanceEvent.timedExecAsync(\n logger,\n { eventName: \"odspFileLink\", requestName: \"getSharingInformation\" },\n async (event) => {\n let attempts = 0;\n let additionalProps;\n const fileLink = await getWithRetryForTokenRefresh(async (options) => {\n attempts++;\n const token = await getToken({ ...options, ... odspUrlParts });\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${odspUrlParts.siteUrl}/_api/web/GetFileByUrl(@a1)/ListItemAllFields/GetSharingInformation?@a1=${\n encodeURIComponent(`'${fileItem.webDavUrl}'`)\n }`, tokenFromResponse(token));\n const requestInit = {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json;odata=verbose\",\n \"Accept\": \"application/json;odata=verbose\",\n ...headers,\n },\n };\n const response = await fetchHelper(url, requestInit);\n additionalProps = response.commonSpoHeaders;\n\n const sharingInfo = await response.content.json();\n const directUrl = sharingInfo?.d?.directUrl;\n if (typeof directUrl !== \"string\") {\n // This will retry once in getWithRetryForTokenRefresh\n throw new NonRetryableError(\n \"getFileLinkCoreMalformedResponse\",\n \"Malformed GetSharingInformation response\",\n DriverErrorType.incorrectServerResponse);\n }\n return directUrl;\n });\n event.end({ ...additionalProps, attempts });\n return fileLink;\n },\n );\n}\n\n/**\n * This represents a lite version of file item containing only the webUrl and webDavUrl properties\n */\ninterface FileItemLite {\n webUrl: string;\n webDavUrl: string;\n}\n\nconst isFileItemLite = (maybeFileItemLite: any): maybeFileItemLite is FileItemLite => {\n if (typeof maybeFileItemLite.webUrl !== \"string\" || typeof maybeFileItemLite.webDavUrl !== \"string\") {\n return false;\n }\n return true;\n};\n\nasync function getFileItemLite(\n getToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n odspUrlParts: IOdspUrlParts,\n logger: ITelemetryLogger,\n): Promise<FileItemLite> {\n return PerformanceEvent.timedExecAsync(\n logger,\n { eventName: \"odspFileLink\", requestName: \"getFileItemLite\" },\n async (event) => {\n let attempts = 0;\n let additionalProps;\n const fileItem = await getWithRetryForTokenRefresh(async (options) => {\n attempts++;\n const {siteUrl, driveId, itemId} = odspUrlParts;\n const token = await getToken({ ...options, siteUrl, driveId, itemId});\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${siteUrl}/_api/v2.0/drives/${driveId}/items/${itemId}?select=webUrl,webDavUrl`,\n tokenFromResponse(token),\n );\n const requestInit = { method: \"GET\", headers };\n const response = await fetchHelper(url, requestInit);\n additionalProps = response.commonSpoHeaders;\n\n const responseJson = await response.content.json();\n if (!isFileItemLite(responseJson)) {\n // This will retry once in getWithRetryForTokenRefresh\n throw new NonRetryableError(\n \"getFileItemLiteMalformedResponse\",\n \"Malformed getFileItemLite response\",\n DriverErrorType.incorrectServerResponse);\n }\n return responseJson;\n });\n event.end({ ...additionalProps, attempts });\n return fileItem;\n },\n );\n}\n"]}
|
|
@@ -23,7 +23,7 @@ export declare class OdspDeltaStorageService {
|
|
|
23
23
|
* @param telemetryProps - properties to add when issuing telemetry events
|
|
24
24
|
* @returns ops retrieved & info if result was partial (i.e. more is available)
|
|
25
25
|
*/
|
|
26
|
-
get(from: number, to: number, telemetryProps: ITelemetryProperties): Promise<IDeltasFetchResult>;
|
|
26
|
+
get(from: number, to: number, telemetryProps: ITelemetryProperties, fetchReason?: string): Promise<IDeltasFetchResult>;
|
|
27
27
|
buildUrl(from: number, to: number): string;
|
|
28
28
|
}
|
|
29
29
|
export declare class OdspDeltaStorageWithCache implements IDocumentDeltaStorageService {
|
|
@@ -36,8 +36,8 @@ export declare class OdspDeltaStorageWithCache implements IDocumentDeltaStorageS
|
|
|
36
36
|
private readonly requestFromSocket;
|
|
37
37
|
private readonly opsReceived;
|
|
38
38
|
private firstCacheMiss;
|
|
39
|
-
constructor(snapshotOps: ISequencedDocumentMessage[] | undefined, logger: ITelemetryLogger, batchSize: number, concurrency: number, getFromStorage: (from: number, to: number, telemetryProps: ITelemetryProperties) => Promise<IDeltasFetchResult>, getCached: (from: number, to: number) => Promise<ISequencedDocumentMessage[]>, requestFromSocket: (from: number, to: number) => void, opsReceived: (ops: ISequencedDocumentMessage[]) => void);
|
|
39
|
+
constructor(snapshotOps: ISequencedDocumentMessage[] | undefined, logger: ITelemetryLogger, batchSize: number, concurrency: number, getFromStorage: (from: number, to: number, telemetryProps: ITelemetryProperties, fetchReason?: string) => Promise<IDeltasFetchResult>, getCached: (from: number, to: number) => Promise<ISequencedDocumentMessage[]>, requestFromSocket: (from: number, to: number) => void, opsReceived: (ops: ISequencedDocumentMessage[]) => void);
|
|
40
40
|
protected validateMessages(reason: string, messages: ISequencedDocumentMessage[], from: number): void;
|
|
41
|
-
fetchMessages(fromTotal: number, toTotal: number | undefined, abortSignal?: AbortSignal, cachedOnly?: boolean): import("@fluidframework/driver-definitions").IStream<ISequencedDocumentMessage[]>;
|
|
41
|
+
fetchMessages(fromTotal: number, toTotal: number | undefined, abortSignal?: AbortSignal, cachedOnly?: boolean, fetchReason?: string): import("@fluidframework/driver-definitions").IStream<ISequencedDocumentMessage[]>;
|
|
42
42
|
}
|
|
43
43
|
//# sourceMappingURL=odspDeltaStorageService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspDeltaStorageService.d.ts","sourceRoot":"","sources":["../src/odspDeltaStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAE5F,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,+BAA+B,EAAE,MAAM,yCAAyC,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAMtG,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C;;GAEG;AACH,qBAAa,uBAAuB;IAE5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAHN,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,+BAA+B,EAChD,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,gBAAgB;IAI7C;;;;;;OAMG;IACW,GAAG,CACb,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"odspDeltaStorageService.d.ts","sourceRoot":"","sources":["../src/odspDeltaStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAE5F,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,+BAA+B,EAAE,MAAM,yCAAyC,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAMtG,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C;;GAEG;AACH,qBAAa,uBAAuB;IAE5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAHN,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,+BAA+B,EAChD,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,gBAAgB;IAI7C;;;;;;OAMG;IACW,GAAG,CACb,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,oBAAoB,EACpC,WAAW,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,kBAAkB,CAAC;IAmEvB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;CAK3C;AAED,qBAAa,yBAA0B,YAAW,4BAA4B;IAItE,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAK/B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW;IAdhC,OAAO,CAAC,cAAc,CAA2B;gBAGrC,WAAW,EAAE,yBAAyB,EAAE,GAAG,SAAS,EAC3C,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,CAC7B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,oBAAoB,EACpC,WAAW,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,EACvC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,yBAAyB,EAAE,CAAC,EAC7E,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,EACrD,WAAW,EAAE,CAAC,GAAG,EAAE,yBAAyB,EAAE,KAAK,IAAI;IAI5E,SAAS,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,yBAAyB,EAAE,EAAE,IAAI,EAAE,MAAM;IAiBvF,aAAa,CAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,UAAU,CAAC,EAAE,OAAO,EACpB,WAAW,CAAC,EAAE,MAAM;CAmF3B"}
|
|
@@ -24,7 +24,7 @@ export class OdspDeltaStorageService {
|
|
|
24
24
|
* @param telemetryProps - properties to add when issuing telemetry events
|
|
25
25
|
* @returns ops retrieved & info if result was partial (i.e. more is available)
|
|
26
26
|
*/
|
|
27
|
-
async get(from, to, telemetryProps) {
|
|
27
|
+
async get(from, to, telemetryProps, fetchReason) {
|
|
28
28
|
return getWithRetryForTokenRefresh(async (options) => {
|
|
29
29
|
// Note - this call ends up in getSocketStorageDiscovery() and can refresh token
|
|
30
30
|
// Thus it needs to be done before we call getStorageToken() to reduce extra calls
|
|
@@ -34,6 +34,9 @@ export class OdspDeltaStorageService {
|
|
|
34
34
|
let postBody = `--${formBoundary}\r\n`;
|
|
35
35
|
postBody += `Authorization: Bearer ${storageToken}\r\n`;
|
|
36
36
|
postBody += `X-HTTP-Method-Override: GET\r\n`;
|
|
37
|
+
if (fetchReason !== undefined) {
|
|
38
|
+
postBody += `fetchReason: ${fetchReason}\r\n`;
|
|
39
|
+
}
|
|
37
40
|
postBody += `_post: 1\r\n`;
|
|
38
41
|
postBody += `\r\n--${formBoundary}--`;
|
|
39
42
|
const headers = {
|
|
@@ -102,7 +105,7 @@ export class OdspDeltaStorageWithCache {
|
|
|
102
105
|
}
|
|
103
106
|
}
|
|
104
107
|
}
|
|
105
|
-
fetchMessages(fromTotal, toTotal, abortSignal, cachedOnly) {
|
|
108
|
+
fetchMessages(fromTotal, toTotal, abortSignal, cachedOnly, fetchReason) {
|
|
106
109
|
// We do not control what's in the cache. Current API assumes that fetchMessages() keeps banging on
|
|
107
110
|
// storage / cache until it gets ops it needs. This would result in deadlock if fixed range is asked from
|
|
108
111
|
// cache and it's not there.
|
|
@@ -141,7 +144,7 @@ export class OdspDeltaStorageWithCache {
|
|
|
141
144
|
if (cachedOnly) {
|
|
142
145
|
return { messages: [], partialResult: false };
|
|
143
146
|
}
|
|
144
|
-
const ops = await this.getFromStorage(from, to, telemetryProps);
|
|
147
|
+
const ops = await this.getFromStorage(from, to, telemetryProps, fetchReason);
|
|
145
148
|
this.validateMessages("storage", ops.messages, from);
|
|
146
149
|
opsFromStorage += ops.messages.length;
|
|
147
150
|
this.opsReceived(ops.messages);
|
|
@@ -157,7 +160,7 @@ export class OdspDeltaStorageWithCache {
|
|
|
157
160
|
// In future releases we will switch to actual concurrency
|
|
158
161
|
this.concurrency, fromTotal, // inclusive
|
|
159
162
|
toTotal, // exclusive
|
|
160
|
-
this.batchSize, this.logger, abortSignal);
|
|
163
|
+
this.batchSize, this.logger, abortSignal, fetchReason);
|
|
161
164
|
return streamObserver(stream, (result) => {
|
|
162
165
|
if (result.done && opsFromSnapshot + opsFromCache + opsFromStorage !== 0) {
|
|
163
166
|
this.logger.sendPerformanceEvent({
|