@fluidframework/odsp-driver 0.55.0 → 0.55.4
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.js +2 -2
- package/dist/createFile.js.map +1 -1
- package/dist/epochTracker.d.ts.map +1 -1
- package/dist/epochTracker.js +2 -2
- package/dist/epochTracker.js.map +1 -1
- package/dist/fetchSnapshot.js +1 -1
- package/dist/fetchSnapshot.js.map +1 -1
- package/dist/getFileLink.js +2 -2
- package/dist/getFileLink.js.map +1 -1
- package/dist/odspDeltaStorageService.js +1 -1
- package/dist/odspDeltaStorageService.js.map +1 -1
- package/dist/odspDocumentStorageManager.js +3 -3
- package/dist/odspDocumentStorageManager.js.map +1 -1
- package/dist/odspUtils.d.ts +1 -1
- package/dist/odspUtils.d.ts.map +1 -1
- package/dist/odspUtils.js +11 -8
- package/dist/odspUtils.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/vroom.js +1 -1
- package/dist/vroom.js.map +1 -1
- package/lib/createFile.js +2 -2
- package/lib/createFile.js.map +1 -1
- package/lib/epochTracker.d.ts.map +1 -1
- package/lib/epochTracker.js +2 -2
- package/lib/epochTracker.js.map +1 -1
- package/lib/fetchSnapshot.js +1 -1
- package/lib/fetchSnapshot.js.map +1 -1
- package/lib/getFileLink.js +2 -2
- package/lib/getFileLink.js.map +1 -1
- package/lib/odspDeltaStorageService.js +1 -1
- package/lib/odspDeltaStorageService.js.map +1 -1
- package/lib/odspDocumentStorageManager.js +3 -3
- package/lib/odspDocumentStorageManager.js.map +1 -1
- package/lib/odspUtils.d.ts +1 -1
- package/lib/odspUtils.d.ts.map +1 -1
- package/lib/odspUtils.js +12 -9
- 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.js +1 -1
- package/lib/vroom.js.map +1 -1
- package/package.json +7 -7
- package/src/createFile.ts +2 -2
- package/src/epochTracker.ts +2 -8
- package/src/fetchSnapshot.ts +1 -1
- package/src/getFileLink.ts +2 -2
- package/src/odspDeltaStorageService.ts +1 -1
- package/src/odspDocumentStorageManager.ts +3 -3
- package/src/odspUtils.ts +21 -11
- package/src/packageVersion.ts +1 -1
- package/src/vroom.ts +1 -1
package/lib/odspUtils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspUtils.js","sourceRoot":"","sources":["../src/odspUtils.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryProperties, ITelemetryBaseLogger, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { IResolvedUrl, DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport { isOnline, OnlineStatus, RetryableError, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport { assert, performance } from \"@fluidframework/common-utils\";\nimport { ISequencedDocumentMessage, ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { ChildLogger, PerformanceEvent, wrapError } from \"@fluidframework/telemetry-utils\";\nimport {\n fetchIncorrectResponse,\n throwOdspNetworkError,\n getSPOAndGraphRequestIdsFromResponse,\n} from \"@fluidframework/odsp-doclib-utils\";\nimport {\n IOdspResolvedUrl,\n TokenFetchOptions,\n OdspErrorType,\n tokenFromResponse,\n isTokenFromCache,\n OdspResourceTokenFetchOptions,\n ShareLinkTypes,\n TokenFetcher,\n ICacheEntry,\n snapshotKey,\n InstrumentedStorageTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { fetch } from \"./fetch\";\nimport { pkgVersion } from \"./packageVersion\";\nimport { IOdspSnapshot } from \"./contracts\";\n\nexport const getWithRetryForTokenRefreshRepeat = \"getWithRetryForTokenRefreshRepeat\";\n\n/** Parse the given url and return the origin (host name) */\nexport const getOrigin = (url: string) => new URL(url).origin;\n\nexport interface ISnapshotContents {\n snapshotTree: ISnapshotTree,\n blobs: Map<string, ArrayBuffer>,\n ops: ISequencedDocumentMessage[],\n sequenceNumber: number | undefined,\n}\n\nexport interface IOdspResponse<T> {\n content: T;\n headers: Map<string, string>;\n commonSpoHeaders: ITelemetryProperties;\n duration: number,\n}\n\nexport interface TokenFetchOptionsEx extends TokenFetchOptions {\n /** previous error we hit in getWithRetryForTokenRefresh */\n previousError?: any;\n}\n\nfunction headersToMap(headers: Headers) {\n const newHeaders = new Map<string, string>();\n for (const [key, value] of headers.entries()) {\n newHeaders.set(key, value);\n }\n return newHeaders;\n}\n\n/**\n * This API should be used with pretty much all network calls (fetch, webSocket connection) in order\n * to correctly handle expired tokens. It relies on callback fetching token, and be able to refetch\n * token on failure. Only specific cases get retry call with refresh = true, all other / unknown errors\n * simply propagate to caller\n */\nexport async function getWithRetryForTokenRefresh<T>(get: (options: TokenFetchOptionsEx) => Promise<T>) {\n return get({ refresh: false }).catch(async (e) => {\n const options: TokenFetchOptionsEx = { refresh: true, previousError: e };\n switch (e.errorType) {\n // If the error is 401 or 403 refresh the token and try once more.\n case DriverErrorType.authorizationError:\n return get({ ...options, claims: e.claims, tenantId: e.tenantId });\n\n case DriverErrorType.incorrectServerResponse: // some error on the wire, retry once\n case OdspErrorType.fetchTokenError: // If the token was null, then retry once.\n return get(options);\n\n default:\n // Caller may determine that it wants one retry\n if (e[getWithRetryForTokenRefreshRepeat] === true) {\n return get(options);\n }\n throw e;\n }\n });\n}\n\nexport async function fetchHelper(\n requestInfo: RequestInfo,\n requestInit: RequestInit | undefined,\n): Promise<IOdspResponse<Response>> {\n const start = performance.now();\n\n // Node-fetch and dom have conflicting typing, force them to work by casting for now\n return fetch(requestInfo, requestInit).then(async (fetchResponse) => {\n const response = fetchResponse as any as Response;\n // Let's assume we can retry.\n if (!response) {\n throw new NonRetryableError(\n \"odspFetchErrorNoResponse\",\n \"No response from fetch call\",\n DriverErrorType.incorrectServerResponse);\n }\n if (!response.ok || response.status < 200 || response.status >= 300) {\n throwOdspNetworkError(\n `odspFetchError [${response.status}]`, response.status, response, await response.text());\n }\n\n const headers = headersToMap(response.headers);\n return {\n content: response,\n headers,\n commonSpoHeaders: getSPOAndGraphRequestIdsFromResponse(headers),\n duration: performance.now() - start,\n };\n }, (error) => {\n // While we do not know for sure whether computer is offline, this error is not actionable and\n // is pretty good indicator we are offline. Treating it as offline scenario will make it\n // easier to see other errors in telemetry.\n let online = isOnline();\n const errorText = `${error}`;\n if (errorText === \"TypeError: Failed to fetch\") {\n online = OnlineStatus.Offline;\n }\n // This error is thrown by fetch() when AbortSignal is provided and it gets cancelled\n if (error.name === \"AbortError\") {\n throw new RetryableError(\"fetchAbort\", \"Fetch Timeout (AbortError)\", OdspErrorType.fetchTimeout);\n }\n // TCP/IP timeout\n if (errorText.indexOf(\"ETIMEDOUT\") !== -1) {\n throw new RetryableError(\"fetchETimedout\", \"Fetch Timeout (ETIMEDOUT)\", OdspErrorType.fetchTimeout);\n }\n\n //\n // WARNING: Do not log error object itself or any of its properties!\n // It could container PII, like URI in message itself, or token in properties.\n // It is also non-serializable object due to circular references.\n //\n if (online === OnlineStatus.Offline) {\n throw new RetryableError(\"OdspFetchOffline\", `Offline: ${errorText}`, DriverErrorType.offlineError);\n } else {\n throw new RetryableError(\"OdspFetchError\", `Fetch error: ${errorText}`, DriverErrorType.fetchFailure);\n }\n });\n}\n\n/**\n * A utility function to fetch and parse as JSON with support for retries\n * @param requestInfo - fetch requestInfo, can be a string\n * @param requestInit - fetch requestInit\n */\nexport async function fetchArray(\n requestInfo: RequestInfo,\n requestInit: RequestInit | undefined,\n): Promise<IOdspResponse<ArrayBuffer>> {\n const { content, headers, commonSpoHeaders, duration } = await fetchHelper(requestInfo, requestInit);\n\n const arrayBuffer = await content.arrayBuffer();\n commonSpoHeaders.bodySize = arrayBuffer.byteLength;\n return {\n headers,\n content: arrayBuffer,\n commonSpoHeaders,\n duration,\n };\n}\n\n/**\n * A utility function to fetch and parse as JSON with support for retries\n * @param requestInfo - fetch requestInfo, can be a string\n * @param requestInit - fetch requestInit\n */\nexport async function fetchAndParseAsJSONHelper<T>(\n requestInfo: RequestInfo,\n requestInit: RequestInit | undefined,\n): Promise<IOdspResponse<T>> {\n const { content, headers, commonSpoHeaders, duration } = await fetchHelper(requestInfo, requestInit);\n let text: string | undefined;\n try {\n text = await content.text();\n } catch (e) {\n // JSON.parse() can fail and message would container full request URI, including\n // tokens... It fails for me with \"Unexpected end of JSON input\" quite often - an attempt to download big file\n // (many ops) almost always ends up with this error - I'd guess 1% of op request end up here... It always\n // succeeds on retry.\n // So do not log error object itself.\n throwOdspNetworkError(\n \"errorWhileParsingFetchResponse\",\n fetchIncorrectResponse,\n content, // response\n text,\n );\n }\n\n commonSpoHeaders.bodySize = text.length;\n const res = {\n headers,\n content: JSON.parse(text),\n commonSpoHeaders,\n duration,\n };\n return res;\n}\n\nexport interface INewFileInfo {\n siteUrl: string;\n driveId: string;\n filename: string;\n filePath: string;\n /**\n * application can request creation of a share link along with the creation of a new file\n * by passing in an optional param to specify the kind of sharing link\n * (at the time of adding this comment Sept/2021), odsp only supports csl\n */\n createLinkType?: ShareLinkTypes;\n}\n\nexport function getOdspResolvedUrl(resolvedUrl: IResolvedUrl): IOdspResolvedUrl {\n assert((resolvedUrl as IOdspResolvedUrl).odspResolvedUrl === true, 0x1de /* \"Not an ODSP resolved url\" */);\n return resolvedUrl as IOdspResolvedUrl;\n}\n\nexport const createOdspLogger = (logger?: ITelemetryBaseLogger) =>\n ChildLogger.create(\n logger,\n \"OdspDriver\",\n { all :\n {\n driverVersion: pkgVersion,\n },\n });\n\nexport function evalBlobsAndTrees(snapshot: IOdspSnapshot) {\n let numTrees = 0;\n let numBlobs = 0;\n let encodedBlobsSize = 0;\n let decodedBlobsSize = 0;\n for (const tree of snapshot.trees) {\n for (const treeEntry of tree.entries) {\n if (treeEntry.type === \"blob\") {\n numBlobs++;\n } else if (treeEntry.type === \"tree\") {\n numTrees++;\n }\n }\n }\n if (snapshot.blobs !== undefined) {\n for (const blob of snapshot.blobs) {\n decodedBlobsSize += blob.size;\n encodedBlobsSize += blob.content.length;\n }\n }\n return { numTrees, numBlobs, encodedBlobsSize, decodedBlobsSize };\n}\n\nexport function toInstrumentedOdspTokenFetcher(\n logger: ITelemetryLogger,\n resolvedUrl: IOdspResolvedUrl,\n tokenFetcher: TokenFetcher<OdspResourceTokenFetchOptions>,\n throwOnNullToken: boolean,\n): InstrumentedStorageTokenFetcher {\n return async (options: TokenFetchOptions, name: string, alwaysRecordTokenFetchTelemetry: boolean = false) => {\n // Telemetry note: if options.refresh is true, there is a potential perf issue:\n // Host should optimize and provide non-expired tokens on all critical paths.\n // Exceptions: race conditions around expiration, revoked tokens, host that does not care\n // (fluid-fetcher)\n return PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: `${name}_GetToken`,\n attempts: options.refresh ? 2 : 1,\n hasClaims: !!options.claims,\n hasTenantId: !!options.tenantId,\n },\n async (event) => tokenFetcher({\n ...options,\n siteUrl: resolvedUrl.siteUrl,\n driveId: resolvedUrl.driveId,\n itemId: resolvedUrl.itemId,\n }).then((tokenResponse) => {\n const token = tokenFromResponse(tokenResponse);\n // This event alone generates so many events that is materially impacts cost of telemetry\n // Thus do not report end event when it comes back quickly.\n // Note that most of the hosts do not report if result is comming from cache or not,\n // so we can't rely on that here. But always record if specified explicitly for cases such as\n // calling trees/latest during load.\n if (alwaysRecordTokenFetchTelemetry || event.duration >= 32) {\n event.end({ fromCache: isTokenFromCache(tokenResponse), isNull: token === null });\n }\n if (token === null && throwOnNullToken) {\n throw new NonRetryableError(\n \"storageTokenIsNull\",\n `Token is null for ${name} call`,\n OdspErrorType.fetchTokenError,\n { method: name });\n }\n return token;\n }, (error) => {\n const tokenError = wrapError(\n error,\n (errorMessage) => new NonRetryableError(\n \"tokenFetcherFailed\",\n errorMessage,\n OdspErrorType.fetchTokenError,\n { method: name }));\n throw tokenError;\n }),\n { cancel: \"generic\" });\n };\n}\n\nexport function createCacheSnapshotKey(odspResolvedUrl: IOdspResolvedUrl): ICacheEntry {\n const cacheEntry: ICacheEntry = {\n type: snapshotKey,\n key: \"\",\n file: {\n resolvedUrl: odspResolvedUrl,\n docId: odspResolvedUrl.hashedDocumentId,\n },\n };\n return cacheEntry;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"odspUtils.js","sourceRoot":"","sources":["../src/odspUtils.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryProperties, ITelemetryBaseLogger, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { IResolvedUrl, DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport {\n isOnline,\n OnlineStatus,\n RetryableError,\n NonRetryableError,\n NetworkErrorBasic,\n} from \"@fluidframework/driver-utils\";\nimport { assert, performance } from \"@fluidframework/common-utils\";\nimport { ISequencedDocumentMessage, ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { ChildLogger, PerformanceEvent, wrapError } from \"@fluidframework/telemetry-utils\";\nimport {\n fetchIncorrectResponse,\n throwOdspNetworkError,\n getSPOAndGraphRequestIdsFromResponse,\n} from \"@fluidframework/odsp-doclib-utils\";\nimport {\n IOdspResolvedUrl,\n TokenFetchOptions,\n OdspErrorType,\n tokenFromResponse,\n isTokenFromCache,\n OdspResourceTokenFetchOptions,\n ShareLinkTypes,\n TokenFetcher,\n ICacheEntry,\n snapshotKey,\n InstrumentedStorageTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { fetch } from \"./fetch\";\nimport { pkgVersion } from \"./packageVersion\";\nimport { IOdspSnapshot } from \"./contracts\";\n\nexport const getWithRetryForTokenRefreshRepeat = \"getWithRetryForTokenRefreshRepeat\";\n\n/** Parse the given url and return the origin (host name) */\nexport const getOrigin = (url: string) => new URL(url).origin;\n\nexport interface ISnapshotContents {\n snapshotTree: ISnapshotTree,\n blobs: Map<string, ArrayBuffer>,\n ops: ISequencedDocumentMessage[],\n sequenceNumber: number | undefined,\n}\n\nexport interface IOdspResponse<T> {\n content: T;\n headers: Map<string, string>;\n propsToLog: ITelemetryProperties;\n duration: number,\n}\n\nexport interface TokenFetchOptionsEx extends TokenFetchOptions {\n /** previous error we hit in getWithRetryForTokenRefresh */\n previousError?: any;\n}\n\nfunction headersToMap(headers: Headers) {\n const newHeaders = new Map<string, string>();\n for (const [key, value] of headers.entries()) {\n newHeaders.set(key, value);\n }\n return newHeaders;\n}\n\n/**\n * This API should be used with pretty much all network calls (fetch, webSocket connection) in order\n * to correctly handle expired tokens. It relies on callback fetching token, and be able to refetch\n * token on failure. Only specific cases get retry call with refresh = true, all other / unknown errors\n * simply propagate to caller\n */\nexport async function getWithRetryForTokenRefresh<T>(get: (options: TokenFetchOptionsEx) => Promise<T>) {\n return get({ refresh: false }).catch(async (e) => {\n const options: TokenFetchOptionsEx = { refresh: true, previousError: e };\n switch (e.errorType) {\n // If the error is 401 or 403 refresh the token and try once more.\n case DriverErrorType.authorizationError:\n return get({ ...options, claims: e.claims, tenantId: e.tenantId });\n\n case DriverErrorType.incorrectServerResponse: // some error on the wire, retry once\n case OdspErrorType.fetchTokenError: // If the token was null, then retry once.\n return get(options);\n\n default:\n // Caller may determine that it wants one retry\n if (e[getWithRetryForTokenRefreshRepeat] === true) {\n return get(options);\n }\n throw e;\n }\n });\n}\n\nexport async function fetchHelper(\n requestInfo: RequestInfo,\n requestInit: RequestInit | undefined,\n): Promise<IOdspResponse<Response>> {\n const start = performance.now();\n\n // Node-fetch and dom have conflicting typing, force them to work by casting for now\n return fetch(requestInfo, requestInit).then(async (fetchResponse) => {\n const response = fetchResponse as any as Response;\n // Let's assume we can retry.\n if (!response) {\n throw new NonRetryableError(\n \"odspFetchErrorNoResponse\",\n \"No response from fetch call\",\n DriverErrorType.incorrectServerResponse);\n }\n if (!response.ok || response.status < 200 || response.status >= 300) {\n throwOdspNetworkError(\n `odspFetchError [${response.status}]`, response.status, response, await response.text());\n }\n\n const headers = headersToMap(response.headers);\n return {\n content: response,\n headers,\n propsToLog: getSPOAndGraphRequestIdsFromResponse(headers),\n duration: performance.now() - start,\n };\n }, (error) => {\n // While we do not know for sure whether computer is offline, this error is not actionable and\n // is pretty good indicator we are offline. Treating it as offline scenario will make it\n // easier to see other errors in telemetry.\n let online = isOnline();\n const errorText = `${error}`;\n if (errorText === \"TypeError: Failed to fetch\") {\n online = OnlineStatus.Offline;\n }\n // This error is thrown by fetch() when AbortSignal is provided and it gets cancelled\n if (error.name === \"AbortError\") {\n throw new RetryableError(\"fetchAbort\", \"Fetch Timeout (AbortError)\", OdspErrorType.fetchTimeout);\n }\n // TCP/IP timeout\n if (errorText.indexOf(\"ETIMEDOUT\") !== -1) {\n throw new RetryableError(\"fetchETimedout\", \"Fetch Timeout (ETIMEDOUT)\", OdspErrorType.fetchTimeout);\n }\n\n //\n // WARNING: Do not log error object itself or any of its properties!\n // It could container PII, like URI in message itself, or token in properties.\n // It is also non-serializable object due to circular references.\n //\n if (online === OnlineStatus.Offline) {\n throw new RetryableError(\"OdspFetchOffline\", `Offline: ${errorText}`, DriverErrorType.offlineError);\n } else {\n throw new RetryableError(\"OdspFetchError\", `Fetch error: ${errorText}`, DriverErrorType.fetchFailure);\n }\n });\n}\n\n/**\n * A utility function to fetch and parse as JSON with support for retries\n * @param requestInfo - fetch requestInfo, can be a string\n * @param requestInit - fetch requestInit\n */\nexport async function fetchArray(\n requestInfo: RequestInfo,\n requestInit: RequestInit | undefined,\n): Promise<IOdspResponse<ArrayBuffer>> {\n const { content, headers, propsToLog, duration } = await fetchHelper(requestInfo, requestInit);\n\n const arrayBuffer = await content.arrayBuffer();\n propsToLog.bodySize = arrayBuffer.byteLength;\n return {\n headers,\n content: arrayBuffer,\n propsToLog,\n duration,\n };\n}\n\n/**\n * A utility function to fetch and parse as JSON with support for retries\n * @param requestInfo - fetch requestInfo, can be a string\n * @param requestInit - fetch requestInit\n */\nexport async function fetchAndParseAsJSONHelper<T>(\n requestInfo: RequestInfo,\n requestInit: RequestInit | undefined,\n): Promise<IOdspResponse<T>> {\n const { content, headers, propsToLog, duration } = await fetchHelper(requestInfo, requestInit);\n let text: string | undefined;\n try {\n text = await content.text();\n } catch (e) {\n // JSON.parse() can fail and message would container full request URI, including\n // tokens... It fails for me with \"Unexpected end of JSON input\" quite often - an attempt to download big file\n // (many ops) almost always ends up with this error - I'd guess 1% of op request end up here... It always\n // succeeds on retry.\n // So do not log error object itself.\n throwOdspNetworkError(\n \"errorWhileParsingFetchResponse\",\n fetchIncorrectResponse,\n content, // response\n text,\n );\n }\n\n propsToLog.bodySize = text.length;\n const res = {\n headers,\n content: JSON.parse(text),\n propsToLog,\n duration,\n };\n return res;\n}\n\nexport interface INewFileInfo {\n siteUrl: string;\n driveId: string;\n filename: string;\n filePath: string;\n /**\n * application can request creation of a share link along with the creation of a new file\n * by passing in an optional param to specify the kind of sharing link\n * (at the time of adding this comment Sept/2021), odsp only supports csl\n */\n createLinkType?: ShareLinkTypes;\n}\n\nexport function getOdspResolvedUrl(resolvedUrl: IResolvedUrl): IOdspResolvedUrl {\n assert((resolvedUrl as IOdspResolvedUrl).odspResolvedUrl === true, 0x1de /* \"Not an ODSP resolved url\" */);\n return resolvedUrl as IOdspResolvedUrl;\n}\n\nexport const createOdspLogger = (logger?: ITelemetryBaseLogger) =>\n ChildLogger.create(\n logger,\n \"OdspDriver\",\n { all :\n {\n driverVersion: pkgVersion,\n },\n });\n\nexport function evalBlobsAndTrees(snapshot: IOdspSnapshot) {\n let numTrees = 0;\n let numBlobs = 0;\n let encodedBlobsSize = 0;\n let decodedBlobsSize = 0;\n for (const tree of snapshot.trees) {\n for (const treeEntry of tree.entries) {\n if (treeEntry.type === \"blob\") {\n numBlobs++;\n } else if (treeEntry.type === \"tree\") {\n numTrees++;\n }\n }\n }\n if (snapshot.blobs !== undefined) {\n for (const blob of snapshot.blobs) {\n decodedBlobsSize += blob.size;\n encodedBlobsSize += blob.content.length;\n }\n }\n return { numTrees, numBlobs, encodedBlobsSize, decodedBlobsSize };\n}\n\nexport function toInstrumentedOdspTokenFetcher(\n logger: ITelemetryLogger,\n resolvedUrl: IOdspResolvedUrl,\n tokenFetcher: TokenFetcher<OdspResourceTokenFetchOptions>,\n throwOnNullToken: boolean,\n): InstrumentedStorageTokenFetcher {\n return async (options: TokenFetchOptions, name: string, alwaysRecordTokenFetchTelemetry: boolean = false) => {\n // Telemetry note: if options.refresh is true, there is a potential perf issue:\n // Host should optimize and provide non-expired tokens on all critical paths.\n // Exceptions: race conditions around expiration, revoked tokens, host that does not care\n // (fluid-fetcher)\n return PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: `${name}_GetToken`,\n attempts: options.refresh ? 2 : 1,\n hasClaims: !!options.claims,\n hasTenantId: !!options.tenantId,\n },\n async (event) => tokenFetcher({\n ...options,\n siteUrl: resolvedUrl.siteUrl,\n driveId: resolvedUrl.driveId,\n itemId: resolvedUrl.itemId,\n }).then((tokenResponse) => {\n const token = tokenFromResponse(tokenResponse);\n // This event alone generates so many events that is materially impacts cost of telemetry\n // Thus do not report end event when it comes back quickly.\n // Note that most of the hosts do not report if result is comming from cache or not,\n // so we can't rely on that here. But always record if specified explicitly for cases such as\n // calling trees/latest during load.\n if (alwaysRecordTokenFetchTelemetry || event.duration >= 32) {\n event.end({ fromCache: isTokenFromCache(tokenResponse), isNull: token === null });\n }\n if (token === null && throwOnNullToken) {\n throw new NonRetryableError(\n \"storageTokenIsNull\",\n `Token is null for ${name} call`,\n OdspErrorType.fetchTokenError,\n { method: name });\n }\n return token;\n }, (error) => {\n // There is an important but unofficial contract here where token providers can set canRetry: true\n // to hook into the driver's retry logic (e.g. the retry loop when initiating a connection)\n const rawCanRetry = error?.canRetry;\n const tokenError = wrapError(\n error,\n (errorMessage) => new NetworkErrorBasic(\n \"tokenFetcherFailed\",\n errorMessage,\n OdspErrorType.fetchTokenError,\n typeof rawCanRetry === \"boolean\" ? rawCanRetry : false /* canRetry */,\n { method: name, driverVersion: pkgVersion }));\n throw tokenError;\n }),\n { cancel: \"generic\" });\n };\n}\n\nexport function createCacheSnapshotKey(odspResolvedUrl: IOdspResolvedUrl): ICacheEntry {\n const cacheEntry: ICacheEntry = {\n type: snapshotKey,\n key: \"\",\n file: {\n resolvedUrl: odspResolvedUrl,\n docId: odspResolvedUrl.hashedDocumentId,\n },\n };\n return cacheEntry;\n}\n"]}
|
package/lib/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/odsp-driver";
|
|
8
|
-
export declare const pkgVersion = "0.55.
|
|
8
|
+
export declare const pkgVersion = "0.55.4";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/lib/packageVersion.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/odsp-driver\";\nexport const pkgVersion = \"0.55.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/odsp-driver\";\nexport const pkgVersion = \"0.55.4\";\n"]}
|
package/lib/vroom.js
CHANGED
|
@@ -51,7 +51,7 @@ export async function fetchJoinSession(urlParts, path, method, logger, getStorag
|
|
|
51
51
|
// expecting socketUrl to be something like https://{hostName}/...
|
|
52
52
|
const webSocketHostName = socketUrl.split("/")[2];
|
|
53
53
|
// TODO SPO-specific telemetry
|
|
54
|
-
event.end(Object.assign(Object.assign({}, response.
|
|
54
|
+
event.end(Object.assign(Object.assign({}, response.propsToLog), {
|
|
55
55
|
// pushV2 websocket urls will contain pushf
|
|
56
56
|
pushv2: socketUrl.includes("pushf"), webSocketHostName }));
|
|
57
57
|
if (response.content.runtimeTenantId && !response.content.tenantId) {
|
package/lib/vroom.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vroom.js","sourceRoot":"","sources":["../src/vroom.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAElC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAGnE,OAAO,EAAE,SAAS,EAAuB,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAO5C;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAClC,QAAuB,EACvB,IAAY,EACZ,MAAc,EACd,MAAwB,EACxB,eAAgD,EAChD,YAA0B,EAC1B,kBAA2B,EAC3B,OAA4B,EAC5B,gBAAyB;IAEzB,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAE5D,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO;QAC9B,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;QAClE,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,gBAAgB,CAAC,cAAc,CAClC,MAAM,kBACF,SAAS,EAAE,aAAa,EACxB,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAC9B,UAAU,GAEjB,KAAK,EAAE,KAAK,EAAE,EAAE;QACZ,MAAM,UAAU,GAAG,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,YAAY,GAAG,IAAI,EAAE,CAAC;QAC5B,IAAI,QAAQ,GAAG,KAAK,YAAY,MAAM,CAAC;QACvC,QAAQ,IAAI,yBAAyB,KAAK,MAAM,CAAC;QACjD,QAAQ,IAAI,kCAAkC,CAAC;QAC/C,QAAQ,IAAI,oCAAoC,CAAC;QACjD,QAAQ,IAAI,cAAc,CAAC;QAC3B,sEAAsE;QACtE,IAAI,kBAAkB,IAAI,gBAAgB,KAAK,SAAS,EAAE;YACtD,MAAM,IAAI,GAAqB;gBAC3B,kBAAkB,EAAE,IAAI;gBACxB,gBAAgB;aACnB,CAAC;YACF,QAAQ,IAAI,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;SACjD;QACD,QAAQ,IAAI,SAAS,YAAY,IAAI,CAAC;QACtC,MAAM,OAAO,GAA8B;YACvC,cAAc,EAAE,gCAAgC,YAAY,EAAE;SACjE,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,YAAY,CAC/B,KAAK,IAAI,EAAE,CAAC,YAAY,CAAC,mBAAmB,CACxC,GAAG,UAAU,CAAC,UAAU,CAAC,WACrB,QAAQ,CAAC,OACb,UAAU,QAAQ,CAAC,MAAM,IAAI,IAAI,QAAQ,EACzC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EACnC,aAAa,EACb,IAAI,CACP,EACD,aAAa,EACb,MAAM,CACT,CAAC;QAEF,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC;QACxD,kEAAkE;QAClE,MAAM,iBAAiB,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAElD,8BAA8B;QAC9B,KAAK,CAAC,GAAG,iCACF,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"vroom.js","sourceRoot":"","sources":["../src/vroom.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { InstrumentedStorageTokenFetcher, IOdspUrlParts } from \"@fluidframework/odsp-driver-definitions\";\nimport { ISocketStorageDiscovery } from \"./contracts\";\nimport { getOrigin, TokenFetchOptionsEx } from \"./odspUtils\";\nimport { getApiRoot } from \"./odspUrlHelper\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { runWithRetry } from \"./retryUtils\";\n\ninterface IJoinSessionBody {\n requestSocketToken: boolean;\n guestDisplayName: string;\n}\n\n/**\n * Makes join session call on SPO to get information about the web socket for a document\n * @param urlParts - The SPO drive id, itemId, siteUrl that this request should be made against\n * @param path - The API path that is relevant to this request\n * @param method - The type of request, such as GET or POST\n * @param logger - A logger to use for this request\n * @param getStorageToken - A function that is able to provide the access token for this request\n * @param epochTracker - fetch wrapper which incorporates epoch logic around joinSession call\n * @param requestSocketToken - flag indicating whether joinSession is expected to return access token\n * which is used when establishing websocket connection with collab session backend service.\n * @param options - Options to fetch the token.\n * @param guestDisplayName - display name used to identify guest user joining a session.\n * This is optional and used only when collab session is being joined via invite.\n */\nexport async function fetchJoinSession(\n urlParts: IOdspUrlParts,\n path: string,\n method: string,\n logger: ITelemetryLogger,\n getStorageToken: InstrumentedStorageTokenFetcher,\n epochTracker: EpochTracker,\n requestSocketToken: boolean,\n options: TokenFetchOptionsEx,\n guestDisplayName?: string,\n): Promise<ISocketStorageDiscovery> {\n const token = await getStorageToken(options, \"JoinSession\");\n\n const extraProps = options.refresh\n ? { hasClaims: !!options.claims, hasTenantId: !!options.tenantId }\n : {};\n return PerformanceEvent.timedExecAsync(\n logger, {\n eventName: \"JoinSession\",\n attempts: options.refresh ? 2 : 1,\n ...extraProps,\n },\n async (event) => {\n const siteOrigin = getOrigin(urlParts.siteUrl);\n const formBoundary = uuid();\n let postBody = `--${formBoundary}\\r\\n`;\n postBody += `Authorization: Bearer ${token}\\r\\n`;\n postBody += `X-HTTP-Method-Override: POST\\r\\n`;\n postBody += `Content-Type: application/json\\r\\n`;\n postBody += `_post: 1\\r\\n`;\n // Name should be there when socket token is requested and vice-versa.\n if (requestSocketToken && guestDisplayName !== undefined) {\n const body: IJoinSessionBody = {\n requestSocketToken: true,\n guestDisplayName,\n };\n postBody += `\\r\\n${JSON.stringify(body)}\\r\\n`;\n }\n postBody += `\\r\\n--${formBoundary}--`;\n const headers: {[index: string]: string} = {\n \"Content-Type\": `multipart/form-data;boundary=${formBoundary}`,\n };\n\n const response = await runWithRetry(\n async () => epochTracker.fetchAndParseAsJSON<ISocketStorageDiscovery>(\n `${getApiRoot(siteOrigin)}/drives/${\n urlParts.driveId\n }/items/${urlParts.itemId}/${path}?ump=1`,\n { method, headers, body: postBody },\n \"joinSession\",\n true,\n ),\n \"joinSession\",\n logger,\n );\n\n const socketUrl = response.content.deltaStreamSocketUrl;\n // expecting socketUrl to be something like https://{hostName}/...\n const webSocketHostName = socketUrl.split(\"/\")[2];\n\n // TODO SPO-specific telemetry\n event.end({\n ...response.propsToLog,\n // pushV2 websocket urls will contain pushf\n pushv2: socketUrl.includes(\"pushf\"),\n webSocketHostName,\n });\n\n if (response.content.runtimeTenantId && !response.content.tenantId) {\n response.content.tenantId = response.content.runtimeTenantId;\n }\n\n return response.content;\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/odsp-driver",
|
|
3
|
-
"version": "0.55.
|
|
3
|
+
"version": "0.55.4",
|
|
4
4
|
"description": "Socket storage implementation for SPO and ODC",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": "https://github.com/microsoft/FluidFramework",
|
|
@@ -58,15 +58,15 @@
|
|
|
58
58
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
59
59
|
"@fluidframework/common-utils": "^0.32.1",
|
|
60
60
|
"@fluidframework/core-interfaces": "^0.41.0",
|
|
61
|
-
"@fluidframework/driver-base": "^0.55.
|
|
61
|
+
"@fluidframework/driver-base": "^0.55.4",
|
|
62
62
|
"@fluidframework/driver-definitions": "^0.43.0",
|
|
63
|
-
"@fluidframework/driver-utils": "^0.55.
|
|
63
|
+
"@fluidframework/driver-utils": "^0.55.4",
|
|
64
64
|
"@fluidframework/gitresources": "^0.1034.0",
|
|
65
|
-
"@fluidframework/odsp-doclib-utils": "^0.55.
|
|
66
|
-
"@fluidframework/odsp-driver-definitions": "^0.55.
|
|
65
|
+
"@fluidframework/odsp-doclib-utils": "^0.55.4",
|
|
66
|
+
"@fluidframework/odsp-driver-definitions": "^0.55.4",
|
|
67
67
|
"@fluidframework/protocol-base": "^0.1034.0",
|
|
68
68
|
"@fluidframework/protocol-definitions": "^0.1026.0",
|
|
69
|
-
"@fluidframework/telemetry-utils": "^0.55.
|
|
69
|
+
"@fluidframework/telemetry-utils": "^0.55.4",
|
|
70
70
|
"abort-controller": "^3.0.0",
|
|
71
71
|
"node-fetch": "^2.6.1",
|
|
72
72
|
"socket.io-client": "^2.4.0",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"@fluidframework/build-common": "^0.23.0",
|
|
77
77
|
"@fluidframework/eslint-config-fluid": "^0.25.0",
|
|
78
|
-
"@fluidframework/mocha-test-setup": "^0.55.
|
|
78
|
+
"@fluidframework/mocha-test-setup": "^0.55.4",
|
|
79
79
|
"@microsoft/api-extractor": "^7.16.1",
|
|
80
80
|
"@rushstack/eslint-config": "^2.5.1",
|
|
81
81
|
"@types/mocha": "^8.2.2",
|
package/src/createFile.ts
CHANGED
|
@@ -149,7 +149,7 @@ export async function createNewEmptyFluidFile(
|
|
|
149
149
|
}
|
|
150
150
|
event.end({
|
|
151
151
|
headers: Object.keys(headers).length !== 0 ? true : undefined,
|
|
152
|
-
...fetchResponse.
|
|
152
|
+
...fetchResponse.propsToLog,
|
|
153
153
|
});
|
|
154
154
|
return content.id;
|
|
155
155
|
},
|
|
@@ -208,7 +208,7 @@ export async function createNewFluidFileFromSummary(
|
|
|
208
208
|
event.end({
|
|
209
209
|
headers: Object.keys(headers).length !== 0 ? true : undefined,
|
|
210
210
|
attempts: options.refresh ? 2 : 1,
|
|
211
|
-
...fetchResponse.
|
|
211
|
+
...fetchResponse.propsToLog,
|
|
212
212
|
});
|
|
213
213
|
return content;
|
|
214
214
|
},
|
package/src/epochTracker.ts
CHANGED
|
@@ -180,10 +180,7 @@ export class EpochTracker implements IPersistedFileCache {
|
|
|
180
180
|
).then((response) => {
|
|
181
181
|
epochFromResponse = response.headers.get("x-fluid-epoch");
|
|
182
182
|
this.validateEpochFromResponse(epochFromResponse, fetchType);
|
|
183
|
-
response.
|
|
184
|
-
...response.commonSpoHeaders,
|
|
185
|
-
"X-RequestStats": clientCorrelationId,
|
|
186
|
-
};
|
|
183
|
+
response.propsToLog.XRequestStatsHeader = clientCorrelationId;
|
|
187
184
|
return response;
|
|
188
185
|
}).catch(async (error) => {
|
|
189
186
|
// Get the server epoch from error in case we don't have it as if undefined we won't be able
|
|
@@ -221,10 +218,7 @@ export class EpochTracker implements IPersistedFileCache {
|
|
|
221
218
|
).then((response) => {
|
|
222
219
|
epochFromResponse = response.headers.get("x-fluid-epoch");
|
|
223
220
|
this.validateEpochFromResponse(epochFromResponse, fetchType);
|
|
224
|
-
response.
|
|
225
|
-
...response.commonSpoHeaders,
|
|
226
|
-
"X-RequestStats": clientCorrelationId,
|
|
227
|
-
};
|
|
221
|
+
response.propsToLog.XRequestStatsHeader = clientCorrelationId;
|
|
228
222
|
return response;
|
|
229
223
|
}).catch(async (error) => {
|
|
230
224
|
// Get the server epoch from error in case we don't have it as if undefined we won't be able
|
package/src/fetchSnapshot.ts
CHANGED
|
@@ -306,7 +306,7 @@ async function fetchLatestSnapshotCore(
|
|
|
306
306
|
// Azure Fluid Relay service is the redeem status (S means success), and FRP is a flag to indicate
|
|
307
307
|
// if the permission has changed.
|
|
308
308
|
sltelemetry: response.odspSnapshotResponse.headers.get("x-fluid-sltelemetry"),
|
|
309
|
-
...response.odspSnapshotResponse.
|
|
309
|
+
...response.odspSnapshotResponse.propsToLog,
|
|
310
310
|
});
|
|
311
311
|
return snapshot;
|
|
312
312
|
},
|
package/src/getFileLink.ts
CHANGED
|
@@ -114,7 +114,7 @@ async function getFileLinkCore(
|
|
|
114
114
|
},
|
|
115
115
|
};
|
|
116
116
|
const response = await fetchHelper(url, requestInit);
|
|
117
|
-
additionalProps = response.
|
|
117
|
+
additionalProps = response.propsToLog;
|
|
118
118
|
|
|
119
119
|
const sharingInfo = await response.content.json();
|
|
120
120
|
const directUrl = sharingInfo?.d?.directUrl;
|
|
@@ -169,7 +169,7 @@ async function getFileItemLite(
|
|
|
169
169
|
);
|
|
170
170
|
const requestInit = { method: "GET", headers };
|
|
171
171
|
const response = await fetchHelper(url, requestInit);
|
|
172
|
-
additionalProps = response.
|
|
172
|
+
additionalProps = response.propsToLog;
|
|
173
173
|
|
|
174
174
|
const responseJson = await response.content.json();
|
|
175
175
|
if (!isFileItemLite(responseJson)) {
|
|
@@ -96,7 +96,7 @@ export class OdspDeltaStorageService {
|
|
|
96
96
|
headers: Object.keys(headers).length !== 0 ? true : undefined,
|
|
97
97
|
length: messages.length,
|
|
98
98
|
duration: response.duration, // this duration for single attempt!
|
|
99
|
-
...response.
|
|
99
|
+
...response.propsToLog,
|
|
100
100
|
attempts: options.refresh ? 2 : 1,
|
|
101
101
|
from,
|
|
102
102
|
to,
|
|
@@ -259,7 +259,7 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
|
|
|
259
259
|
));
|
|
260
260
|
event.end({
|
|
261
261
|
blobId: res.content.id,
|
|
262
|
-
...res.
|
|
262
|
+
...res.propsToLog,
|
|
263
263
|
});
|
|
264
264
|
return res;
|
|
265
265
|
},
|
|
@@ -294,7 +294,7 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
|
|
|
294
294
|
const res = await this.epochTracker.fetchArray(url, { headers }, "blob");
|
|
295
295
|
event.end({
|
|
296
296
|
waitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,
|
|
297
|
-
...res.
|
|
297
|
+
...res.propsToLog,
|
|
298
298
|
attempts: options.refresh ? 2 : 1,
|
|
299
299
|
});
|
|
300
300
|
const cacheControl = res.headers.get("cache-control");
|
|
@@ -303,7 +303,7 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
|
|
|
303
303
|
eventName: "NonCacheableBlob",
|
|
304
304
|
cacheControl,
|
|
305
305
|
blobId,
|
|
306
|
-
...res.
|
|
306
|
+
...res.propsToLog,
|
|
307
307
|
});
|
|
308
308
|
}
|
|
309
309
|
return res.content;
|
package/src/odspUtils.ts
CHANGED
|
@@ -5,7 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
import { ITelemetryProperties, ITelemetryBaseLogger, ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
7
7
|
import { IResolvedUrl, DriverErrorType } from "@fluidframework/driver-definitions";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
isOnline,
|
|
10
|
+
OnlineStatus,
|
|
11
|
+
RetryableError,
|
|
12
|
+
NonRetryableError,
|
|
13
|
+
NetworkErrorBasic,
|
|
14
|
+
} from "@fluidframework/driver-utils";
|
|
9
15
|
import { assert, performance } from "@fluidframework/common-utils";
|
|
10
16
|
import { ISequencedDocumentMessage, ISnapshotTree } from "@fluidframework/protocol-definitions";
|
|
11
17
|
import { ChildLogger, PerformanceEvent, wrapError } from "@fluidframework/telemetry-utils";
|
|
@@ -46,7 +52,7 @@ export interface ISnapshotContents {
|
|
|
46
52
|
export interface IOdspResponse<T> {
|
|
47
53
|
content: T;
|
|
48
54
|
headers: Map<string, string>;
|
|
49
|
-
|
|
55
|
+
propsToLog: ITelemetryProperties;
|
|
50
56
|
duration: number,
|
|
51
57
|
}
|
|
52
58
|
|
|
@@ -116,7 +122,7 @@ export async function fetchHelper(
|
|
|
116
122
|
return {
|
|
117
123
|
content: response,
|
|
118
124
|
headers,
|
|
119
|
-
|
|
125
|
+
propsToLog: getSPOAndGraphRequestIdsFromResponse(headers),
|
|
120
126
|
duration: performance.now() - start,
|
|
121
127
|
};
|
|
122
128
|
}, (error) => {
|
|
@@ -159,14 +165,14 @@ export async function fetchArray(
|
|
|
159
165
|
requestInfo: RequestInfo,
|
|
160
166
|
requestInit: RequestInit | undefined,
|
|
161
167
|
): Promise<IOdspResponse<ArrayBuffer>> {
|
|
162
|
-
const { content, headers,
|
|
168
|
+
const { content, headers, propsToLog, duration } = await fetchHelper(requestInfo, requestInit);
|
|
163
169
|
|
|
164
170
|
const arrayBuffer = await content.arrayBuffer();
|
|
165
|
-
|
|
171
|
+
propsToLog.bodySize = arrayBuffer.byteLength;
|
|
166
172
|
return {
|
|
167
173
|
headers,
|
|
168
174
|
content: arrayBuffer,
|
|
169
|
-
|
|
175
|
+
propsToLog,
|
|
170
176
|
duration,
|
|
171
177
|
};
|
|
172
178
|
}
|
|
@@ -180,7 +186,7 @@ export async function fetchAndParseAsJSONHelper<T>(
|
|
|
180
186
|
requestInfo: RequestInfo,
|
|
181
187
|
requestInit: RequestInit | undefined,
|
|
182
188
|
): Promise<IOdspResponse<T>> {
|
|
183
|
-
const { content, headers,
|
|
189
|
+
const { content, headers, propsToLog, duration } = await fetchHelper(requestInfo, requestInit);
|
|
184
190
|
let text: string | undefined;
|
|
185
191
|
try {
|
|
186
192
|
text = await content.text();
|
|
@@ -198,11 +204,11 @@ export async function fetchAndParseAsJSONHelper<T>(
|
|
|
198
204
|
);
|
|
199
205
|
}
|
|
200
206
|
|
|
201
|
-
|
|
207
|
+
propsToLog.bodySize = text.length;
|
|
202
208
|
const res = {
|
|
203
209
|
headers,
|
|
204
210
|
content: JSON.parse(text),
|
|
205
|
-
|
|
211
|
+
propsToLog,
|
|
206
212
|
duration,
|
|
207
213
|
};
|
|
208
214
|
return res;
|
|
@@ -302,13 +308,17 @@ export function toInstrumentedOdspTokenFetcher(
|
|
|
302
308
|
}
|
|
303
309
|
return token;
|
|
304
310
|
}, (error) => {
|
|
311
|
+
// There is an important but unofficial contract here where token providers can set canRetry: true
|
|
312
|
+
// to hook into the driver's retry logic (e.g. the retry loop when initiating a connection)
|
|
313
|
+
const rawCanRetry = error?.canRetry;
|
|
305
314
|
const tokenError = wrapError(
|
|
306
315
|
error,
|
|
307
|
-
(errorMessage) => new
|
|
316
|
+
(errorMessage) => new NetworkErrorBasic(
|
|
308
317
|
"tokenFetcherFailed",
|
|
309
318
|
errorMessage,
|
|
310
319
|
OdspErrorType.fetchTokenError,
|
|
311
|
-
|
|
320
|
+
typeof rawCanRetry === "boolean" ? rawCanRetry : false /* canRetry */,
|
|
321
|
+
{ method: name, driverVersion: pkgVersion }));
|
|
312
322
|
throw tokenError;
|
|
313
323
|
}),
|
|
314
324
|
{ cancel: "generic" });
|
package/src/packageVersion.ts
CHANGED
package/src/vroom.ts
CHANGED
|
@@ -94,7 +94,7 @@ export async function fetchJoinSession(
|
|
|
94
94
|
|
|
95
95
|
// TODO SPO-specific telemetry
|
|
96
96
|
event.end({
|
|
97
|
-
...response.
|
|
97
|
+
...response.propsToLog,
|
|
98
98
|
// pushV2 websocket urls will contain pushf
|
|
99
99
|
pushv2: socketUrl.includes("pushf"),
|
|
100
100
|
webSocketHostName,
|