@fluidframework/odsp-driver 1.0.1 → 1.1.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/compactSnapshotParser.d.ts +1 -1
- package/dist/compactSnapshotParser.d.ts.map +1 -1
- package/dist/compactSnapshotParser.js +7 -4
- package/dist/compactSnapshotParser.js.map +1 -1
- package/dist/compactSnapshotWriter.d.ts +1 -1
- package/dist/compactSnapshotWriter.d.ts.map +1 -1
- package/dist/compactSnapshotWriter.js +4 -3
- package/dist/compactSnapshotWriter.js.map +1 -1
- package/dist/contracts.d.ts +1 -1
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/createFile.d.ts.map +1 -1
- package/dist/createFile.js.map +1 -1
- package/dist/createNewUtils.d.ts +1 -1
- package/dist/createNewUtils.d.ts.map +1 -1
- package/dist/createNewUtils.js +1 -0
- package/dist/createNewUtils.js.map +1 -1
- package/dist/fetchSnapshot.d.ts +7 -6
- package/dist/fetchSnapshot.d.ts.map +1 -1
- package/dist/fetchSnapshot.js +57 -31
- package/dist/fetchSnapshot.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/odspDocumentDeltaConnection.d.ts.map +1 -1
- package/dist/odspDocumentDeltaConnection.js +17 -17
- package/dist/odspDocumentDeltaConnection.js.map +1 -1
- package/dist/odspDocumentService.d.ts.map +1 -1
- package/dist/odspDocumentService.js +8 -4
- package/dist/odspDocumentService.js.map +1 -1
- package/dist/odspDocumentStorageManager.d.ts +2 -2
- package/dist/odspDocumentStorageManager.d.ts.map +1 -1
- package/dist/odspDocumentStorageManager.js +13 -13
- package/dist/odspDocumentStorageManager.js.map +1 -1
- package/dist/odspError.d.ts +3 -1
- package/dist/odspError.d.ts.map +1 -1
- package/dist/odspError.js +14 -5
- package/dist/odspError.js.map +1 -1
- package/dist/odspPublicUtils.d.ts +14 -0
- package/dist/odspPublicUtils.d.ts.map +1 -1
- package/dist/odspPublicUtils.js.map +1 -1
- package/dist/odspSnapshotParser.d.ts +2 -2
- package/dist/odspSnapshotParser.d.ts.map +1 -1
- package/dist/odspSnapshotParser.js +7 -4
- package/dist/odspSnapshotParser.js.map +1 -1
- package/dist/odspUtils.d.ts +0 -7
- package/dist/odspUtils.d.ts.map +1 -1
- package/dist/odspUtils.js +4 -3
- package/dist/odspUtils.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/compactSnapshotParser.d.ts +1 -1
- package/lib/compactSnapshotParser.d.ts.map +1 -1
- package/lib/compactSnapshotParser.js +7 -4
- package/lib/compactSnapshotParser.js.map +1 -1
- package/lib/compactSnapshotWriter.d.ts +1 -1
- package/lib/compactSnapshotWriter.d.ts.map +1 -1
- package/lib/compactSnapshotWriter.js +4 -3
- package/lib/compactSnapshotWriter.js.map +1 -1
- package/lib/contracts.d.ts +1 -1
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/createFile.d.ts.map +1 -1
- package/lib/createFile.js.map +1 -1
- package/lib/createNewUtils.d.ts +1 -1
- package/lib/createNewUtils.d.ts.map +1 -1
- package/lib/createNewUtils.js +1 -0
- package/lib/createNewUtils.js.map +1 -1
- package/lib/fetchSnapshot.d.ts +7 -6
- package/lib/fetchSnapshot.d.ts.map +1 -1
- package/lib/fetchSnapshot.js +58 -33
- package/lib/fetchSnapshot.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -1
- package/lib/odspDocumentDeltaConnection.d.ts.map +1 -1
- package/lib/odspDocumentDeltaConnection.js +17 -17
- package/lib/odspDocumentDeltaConnection.js.map +1 -1
- package/lib/odspDocumentService.d.ts.map +1 -1
- package/lib/odspDocumentService.js +9 -5
- package/lib/odspDocumentService.js.map +1 -1
- package/lib/odspDocumentStorageManager.d.ts +2 -2
- package/lib/odspDocumentStorageManager.d.ts.map +1 -1
- package/lib/odspDocumentStorageManager.js +13 -13
- package/lib/odspDocumentStorageManager.js.map +1 -1
- package/lib/odspError.d.ts +3 -1
- package/lib/odspError.d.ts.map +1 -1
- package/lib/odspError.js +14 -5
- package/lib/odspError.js.map +1 -1
- package/lib/odspPublicUtils.d.ts +14 -0
- package/lib/odspPublicUtils.d.ts.map +1 -1
- package/lib/odspPublicUtils.js.map +1 -1
- package/lib/odspSnapshotParser.d.ts +2 -2
- package/lib/odspSnapshotParser.d.ts.map +1 -1
- package/lib/odspSnapshotParser.js +5 -2
- package/lib/odspSnapshotParser.js.map +1 -1
- package/lib/odspUtils.d.ts +0 -7
- package/lib/odspUtils.d.ts.map +1 -1
- package/lib/odspUtils.js +4 -3
- package/lib/odspUtils.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +15 -15
- package/src/compactSnapshotParser.ts +10 -4
- package/src/compactSnapshotWriter.ts +7 -4
- package/src/contracts.ts +1 -1
- package/src/createFile.ts +2 -2
- package/src/createNewUtils.ts +2 -1
- package/src/fetchSnapshot.ts +113 -67
- package/src/index.ts +4 -0
- package/src/odspDocumentDeltaConnection.ts +17 -18
- package/src/odspDocumentService.ts +7 -3
- package/src/odspDocumentStorageManager.ts +18 -15
- package/src/odspError.ts +23 -10
- package/src/odspPublicUtils.ts +17 -0
- package/src/odspSnapshotParser.ts +8 -3
- package/src/odspUtils.ts +4 -11
- package/src/packageVersion.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 {\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 IOdspUrlParts,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { fetch } from \"./fetch\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\nimport { IOdspSnapshot } from \"./contracts\";\n\nexport const getWithRetryForTokenRefreshRepeat = \"getWithRetryForTokenRefreshRepeat\";\n\n/** Parse the given url and return the origin (host name) */\nexport const getOrigin = (url: string) => new URL(url).origin;\n\nexport interface 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 // pre-0.58 error message: No response from fetch call\n \"No response from ODSP fetch call\",\n DriverErrorType.incorrectServerResponse,\n { driverVersion });\n }\n if (!response.ok || response.status < 200 || response.status >= 300) {\n throwOdspNetworkError(\n // pre-0.58 error message prefix: odspFetchError\n `ODSP fetch error [${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 const online = isOnline();\n const errorText = `${error}`;\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(\n \"Fetch Timeout (AbortError)\", OdspErrorType.fetchTimeout, { driverVersion });\n }\n // TCP/IP timeout\n if (errorText.includes(\"ETIMEDOUT\")) {\n throw new RetryableError(\n \"Fetch Timeout (ETIMEDOUT)\", OdspErrorType.fetchTimeout, { driverVersion });\n }\n\n //\n // WARNING: Do not log error object itself or any of its properties!\n // It could contain 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(\n // pre-0.58 error message prefix: Offline\n `ODSP fetch failure (Offline): ${errorText}`, DriverErrorType.offlineError, { driverVersion });\n } else {\n // It is perhaps still possible that this is due to being offline, the error does not reveal enough\n // information to conclude. Could also be DNS errors, malformed fetch request, CSP violation, etc.\n throw new RetryableError(\n // pre-0.58 error message prefix: Fetch error\n `ODSP fetch failure: ${errorText}`, DriverErrorType.fetchFailure, { driverVersion });\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 // pre-0.58 error message: errorWhileParsingFetchResponse\n \"Error while parsing fetch response\",\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,\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 resolvedUrlParts: IOdspUrlParts,\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 ...resolvedUrlParts,\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 // pre-0.58 error message: Token is null for ${name} call\n `The Host-provided token fetcher for ${name} call returned null`,\n OdspErrorType.fetchTokenError,\n { method: name, driverVersion });\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 `The Host-provided token fetcher for ${name} call threw an error: ${errorMessage}`,\n OdspErrorType.fetchTokenError,\n typeof rawCanRetry === \"boolean\" ? rawCanRetry : false /* canRetry */,\n { method: name, driverVersion }));\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\n// 80KB is the max body size that we can put in ump post body for server to be able to accept it.\n// Keeping it 78KB to be a little cautious. As per the telemetry 99p is less than 78KB.\nexport const maxUmpPostBodySize = 79872;\n"]}
|
|
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 { 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 IOdspUrlParts,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { fetch } from \"./fetch\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\nimport { IOdspSnapshot } from \"./contracts\";\n\nexport const getWithRetryForTokenRefreshRepeat = \"getWithRetryForTokenRefreshRepeat\";\n\n/** Parse the given url and return the origin (host name) */\nexport const getOrigin = (url: string) => new URL(url).origin;\n\nexport interface IOdspResponse<T> {\n 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 // pre-0.58 error message: No response from fetch call\n \"No response from ODSP fetch call\",\n DriverErrorType.incorrectServerResponse,\n { driverVersion });\n }\n if (!response.ok || response.status < 200 || response.status >= 300) {\n throwOdspNetworkError(\n // pre-0.58 error message prefix: odspFetchError\n `ODSP fetch error [${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 const online = isOnline();\n const errorText = `${error}`;\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(\n \"Fetch Timeout (AbortError)\", OdspErrorType.fetchTimeout, { driverVersion });\n }\n // TCP/IP timeout\n if (errorText.includes(\"ETIMEDOUT\")) {\n throw new RetryableError(\n \"Fetch Timeout (ETIMEDOUT)\", OdspErrorType.fetchTimeout, { driverVersion });\n }\n\n //\n // WARNING: Do not log error object itself or any of its properties!\n // It could contain 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(\n // pre-0.58 error message prefix: Offline\n `ODSP fetch failure (Offline): ${errorText}`, DriverErrorType.offlineError, { driverVersion });\n } else {\n // It is perhaps still possible that this is due to being offline, the error does not reveal enough\n // information to conclude. Could also be DNS errors, malformed fetch request, CSP violation, etc.\n throw new RetryableError(\n // pre-0.58 error message prefix: Fetch error\n `ODSP fetch failure: ${errorText}`, DriverErrorType.fetchFailure, { driverVersion });\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 // pre-0.58 error message: errorWhileParsingFetchResponse\n \"Error while parsing fetch response\",\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 {\n all:\n {\n driverVersion,\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 resolvedUrlParts: IOdspUrlParts,\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 ...resolvedUrlParts,\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 // pre-0.58 error message: Token is null for ${name} call\n `The Host-provided token fetcher returned null`,\n OdspErrorType.fetchTokenError,\n { method: name, driverVersion });\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 `The Host-provided token fetcher threw an error: ${errorMessage}`,\n OdspErrorType.fetchTokenError,\n typeof rawCanRetry === \"boolean\" ? rawCanRetry : false /* canRetry */,\n { method: name, driverVersion }));\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\n// 80KB is the max body size that we can put in ump post body for server to be able to accept it.\n// Keeping it 78KB to be a little cautious. As per the telemetry 99p is less than 78KB.\nexport const maxUmpPostBodySize = 79872;\n"]}
|
package/lib/packageVersion.d.ts
CHANGED
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,OAAO,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 = \"1.0
|
|
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,OAAO,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 = \"1.1.0\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/odsp-driver",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Socket storage implementation for SPO and ODC",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -62,27 +62,27 @@
|
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
64
64
|
"@fluidframework/common-utils": "^0.32.1",
|
|
65
|
-
"@fluidframework/core-interfaces": "^1.0
|
|
66
|
-
"@fluidframework/driver-base": "^1.0
|
|
67
|
-
"@fluidframework/driver-definitions": "^1.0
|
|
68
|
-
"@fluidframework/driver-utils": "^1.0
|
|
69
|
-
"@fluidframework/gitresources": "^0.1036.
|
|
70
|
-
"@fluidframework/odsp-doclib-utils": "^1.0
|
|
71
|
-
"@fluidframework/odsp-driver-definitions": "^1.0
|
|
72
|
-
"@fluidframework/protocol-base": "^0.1036.
|
|
65
|
+
"@fluidframework/core-interfaces": "^1.1.0",
|
|
66
|
+
"@fluidframework/driver-base": "^1.1.0",
|
|
67
|
+
"@fluidframework/driver-definitions": "^1.1.0",
|
|
68
|
+
"@fluidframework/driver-utils": "^1.1.0",
|
|
69
|
+
"@fluidframework/gitresources": "^0.1036.5000",
|
|
70
|
+
"@fluidframework/odsp-doclib-utils": "^1.1.0",
|
|
71
|
+
"@fluidframework/odsp-driver-definitions": "^1.1.0",
|
|
72
|
+
"@fluidframework/protocol-base": "^0.1036.5000",
|
|
73
73
|
"@fluidframework/protocol-definitions": "^0.1028.2000",
|
|
74
|
-
"@fluidframework/telemetry-utils": "^1.0
|
|
74
|
+
"@fluidframework/telemetry-utils": "^1.1.0",
|
|
75
75
|
"abort-controller": "^3.0.0",
|
|
76
76
|
"node-fetch": "^2.6.1",
|
|
77
77
|
"socket.io-client": "^4.4.1",
|
|
78
78
|
"uuid": "^8.3.1"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@fluidframework/build-common": "^0.
|
|
82
|
-
"@fluidframework/build-tools": "^0.2.
|
|
81
|
+
"@fluidframework/build-common": "^0.24.0",
|
|
82
|
+
"@fluidframework/build-tools": "^0.2.74327",
|
|
83
83
|
"@fluidframework/eslint-config-fluid": "^0.28.2000",
|
|
84
|
-
"@fluidframework/mocha-test-setup": "^1.0
|
|
85
|
-
"@fluidframework/odsp-driver-previous": "npm:@fluidframework/odsp-driver@^0.
|
|
84
|
+
"@fluidframework/mocha-test-setup": "^1.1.0",
|
|
85
|
+
"@fluidframework/odsp-driver-previous": "npm:@fluidframework/odsp-driver@^1.0.0",
|
|
86
86
|
"@microsoft/api-extractor": "^7.22.2",
|
|
87
87
|
"@rushstack/eslint-config": "^2.5.1",
|
|
88
88
|
"@types/mocha": "^9.1.1",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"typescript-formatter": "7.1.0"
|
|
101
101
|
},
|
|
102
102
|
"typeValidation": {
|
|
103
|
-
"version": "1.
|
|
103
|
+
"version": "1.1.0",
|
|
104
104
|
"broken": {}
|
|
105
105
|
}
|
|
106
106
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { assert } from "@fluidframework/common-utils";
|
|
7
7
|
import { ISequencedDocumentMessage, ISnapshotTree } from "@fluidframework/protocol-definitions";
|
|
8
|
-
import { ISnapshotContents } from "./
|
|
8
|
+
import { ISnapshotContents } from "./odspPublicUtils";
|
|
9
9
|
import { ReadBuffer } from "./ReadBufferUtils";
|
|
10
10
|
import { ISnapshotTreeEx } from "./contracts";
|
|
11
11
|
import {
|
|
@@ -127,19 +127,25 @@ export function parseCompactSnapshotResponse(buffer: ReadBuffer): ISnapshotConte
|
|
|
127
127
|
const root = builder.getNode(0);
|
|
128
128
|
|
|
129
129
|
const records = getAndValidateNodeProps(root,
|
|
130
|
-
["mrv", "cv", "snapshot", "blobs", "deltas"], false);
|
|
130
|
+
["mrv", "cv", "lsn", "snapshot", "blobs", "deltas"], false);
|
|
131
131
|
|
|
132
132
|
assertBlobCoreInstance(records.mrv, "minReadVersion should be of BlobCore type");
|
|
133
133
|
assertBlobCoreInstance(records.cv, "createVersion should be of BlobCore type");
|
|
134
|
-
|
|
134
|
+
if (records.lsn !== undefined) {
|
|
135
|
+
assertNumberInstance(records.lsn, "lsn should be a number");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
assert(parseFloat(snapshotMinReadVersion) >= parseFloat(records.mrv.toString()),
|
|
135
139
|
0x20f /* "Driver min read version should >= to server minReadVersion" */);
|
|
136
|
-
assert(records.cv.toString() >= snapshotMinReadVersion,
|
|
140
|
+
assert(parseFloat(records.cv.toString()) >= parseFloat(snapshotMinReadVersion),
|
|
137
141
|
0x210 /* "Snapshot should be created with minReadVersion or above" */);
|
|
138
142
|
assert(currentReadVersion === records.cv.toString(),
|
|
139
143
|
0x2c2 /* "Create Version should be equal to currentReadVersion" */);
|
|
144
|
+
|
|
140
145
|
return {
|
|
141
146
|
...readSnapshotSection(records.snapshot),
|
|
142
147
|
blobs: readBlobSection(records.blobs),
|
|
143
148
|
ops: records.deltas !== undefined ? readOpsSection(records.deltas) : [],
|
|
149
|
+
latestSequenceNumber: records.lsn,
|
|
144
150
|
};
|
|
145
151
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { assert, stringToBuffer } from "@fluidframework/common-utils";
|
|
7
7
|
import { IBlob, ISequencedDocumentMessage, ISnapshotTree } from "@fluidframework/protocol-definitions";
|
|
8
8
|
import { snapshotMinReadVersion } from "./compactSnapshotParser";
|
|
9
|
-
import { ISnapshotContents } from "./
|
|
9
|
+
import { ISnapshotContents } from "./odspPublicUtils";
|
|
10
10
|
import { ReadBuffer } from "./ReadBufferUtils";
|
|
11
11
|
import { TreeBuilderSerializer } from "./WriteBufferUtils";
|
|
12
12
|
import { addBoolProperty, addNumberProperty, addStringProperty, NodeCore } from "./zipItDataRepresentationUtils";
|
|
@@ -131,8 +131,11 @@ export function convertToCompactSnapshot(snapshotContents: ISnapshotContents): R
|
|
|
131
131
|
// Create the root node.
|
|
132
132
|
const rootNode = builder.addNode();
|
|
133
133
|
assert(snapshotContents.sequenceNumber !== undefined, 0x21c /* "Seq number should be provided" */);
|
|
134
|
-
|
|
135
|
-
const latestSequenceNumber =
|
|
134
|
+
|
|
135
|
+
const latestSequenceNumber = snapshotContents.latestSequenceNumber ??
|
|
136
|
+
snapshotContents.ops.length > 0 ?
|
|
137
|
+
snapshotContents.ops[snapshotContents.ops.length - 1].sequenceNumber : snapshotContents.sequenceNumber;
|
|
138
|
+
|
|
136
139
|
writeSnapshotProps(rootNode, latestSequenceNumber);
|
|
137
140
|
|
|
138
141
|
writeSnapshotSection(
|
|
@@ -145,7 +148,7 @@ export function convertToCompactSnapshot(snapshotContents: ISnapshotContents): R
|
|
|
145
148
|
writeBlobsSection(rootNode, snapshotContents.blobs);
|
|
146
149
|
|
|
147
150
|
// Then write the ops node.
|
|
148
|
-
writeOpsSection(rootNode, ops);
|
|
151
|
+
writeOpsSection(rootNode, snapshotContents.ops);
|
|
149
152
|
|
|
150
153
|
return builder.serialize();
|
|
151
154
|
}
|
package/src/contracts.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import * as api from "@fluidframework/protocol-definitions";
|
|
7
7
|
import { HostStoragePolicy } from "@fluidframework/odsp-driver-definitions";
|
|
8
|
-
import { ISnapshotContents } from "./
|
|
8
|
+
import { ISnapshotContents } from "./odspPublicUtils";
|
|
9
9
|
|
|
10
10
|
/** https://portal.microsofticm.com/imp/v3/incidents/details/308931013/home
|
|
11
11
|
* The commits property was removed from protocol-definitions but in order to support back compat, we will
|
package/src/createFile.ts
CHANGED
|
@@ -30,9 +30,9 @@ import {
|
|
|
30
30
|
getWithRetryForTokenRefresh,
|
|
31
31
|
INewFileInfo,
|
|
32
32
|
getOrigin,
|
|
33
|
-
ISnapshotContents,
|
|
34
33
|
maxUmpPostBodySize,
|
|
35
34
|
} from "./odspUtils";
|
|
35
|
+
import { ISnapshotContents } from "./odspPublicUtils";
|
|
36
36
|
import { createOdspUrl } from "./createOdspUrl";
|
|
37
37
|
import { getApiRoot } from "./odspUrlHelper";
|
|
38
38
|
import { EpochTracker } from "./epochTracker";
|
|
@@ -91,7 +91,7 @@ export async function createNewFluidFile(
|
|
|
91
91
|
sharingLinkErrorReason = content.sharingLinkErrorReason;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
const odspUrl = createOdspUrl({ ...
|
|
94
|
+
const odspUrl = createOdspUrl({ ...newFileInfo, itemId, dataStorePath: "/" });
|
|
95
95
|
const resolver = new OdspDriverUrlResolver();
|
|
96
96
|
const odspResolvedUrl = await resolver.resolve({
|
|
97
97
|
url: odspUrl,
|
package/src/createNewUtils.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { v4 as uuid } from "uuid";
|
|
|
7
7
|
import { ISummaryTree, SummaryType } from "@fluidframework/protocol-definitions";
|
|
8
8
|
import { getDocAttributesFromProtocolSummary } from "@fluidframework/driver-utils";
|
|
9
9
|
import { stringToBuffer, unreachableCase } from "@fluidframework/common-utils";
|
|
10
|
-
import { ISnapshotContents } from "./
|
|
10
|
+
import { ISnapshotContents } from "./odspPublicUtils";
|
|
11
11
|
import { ISnapshotTreeEx } from "./contracts";
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -25,6 +25,7 @@ export function convertCreateNewSummaryTreeToTreeAndBlobs(summary: ISummaryTree,
|
|
|
25
25
|
blobs,
|
|
26
26
|
ops: [],
|
|
27
27
|
sequenceNumber,
|
|
28
|
+
latestSequenceNumber: sequenceNumber,
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
return snapshotTreeValue;
|
package/src/fetchSnapshot.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { v4 as uuid } from "uuid";
|
|
|
8
8
|
import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
9
9
|
import { assert, fromUtf8ToBase64, performance } from "@fluidframework/common-utils";
|
|
10
10
|
import { DriverErrorType } from "@fluidframework/driver-definitions";
|
|
11
|
-
import { PerformanceEvent } from "@fluidframework/telemetry-utils";
|
|
11
|
+
import { isFluidError, PerformanceEvent, wrapError } from "@fluidframework/telemetry-utils";
|
|
12
12
|
import {
|
|
13
13
|
IOdspResolvedUrl,
|
|
14
14
|
ISnapshotOptions,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
InstrumentedStorageTokenFetcher,
|
|
17
17
|
} from "@fluidframework/odsp-driver-definitions";
|
|
18
18
|
import { ISnapshotTree } from "@fluidframework/protocol-definitions";
|
|
19
|
-
import { isRuntimeMessage } from "@fluidframework/driver-utils";
|
|
19
|
+
import { isRuntimeMessage, NonRetryableError } from "@fluidframework/driver-utils";
|
|
20
20
|
import { IOdspSnapshot, ISnapshotCachedEntry, IVersionedValueWithEpoch, persistedCacheValueVersion } from "./contracts";
|
|
21
21
|
import { getQueryString } from "./getQueryString";
|
|
22
22
|
import { getUrlAndHeadersWithAuth } from "./getUrlAndHeadersWithAuth";
|
|
@@ -26,12 +26,13 @@ import {
|
|
|
26
26
|
getWithRetryForTokenRefresh,
|
|
27
27
|
getWithRetryForTokenRefreshRepeat,
|
|
28
28
|
IOdspResponse,
|
|
29
|
-
ISnapshotContents,
|
|
30
29
|
} from "./odspUtils";
|
|
31
|
-
import {
|
|
30
|
+
import { ISnapshotContents } from "./odspPublicUtils";
|
|
31
|
+
import { convertOdspSnapshotToSnapshotTreeAndBlobs } from "./odspSnapshotParser";
|
|
32
32
|
import { currentReadVersion, parseCompactSnapshotResponse } from "./compactSnapshotParser";
|
|
33
33
|
import { ReadBuffer } from "./ReadBufferUtils";
|
|
34
34
|
import { EpochTracker } from "./epochTracker";
|
|
35
|
+
import { pkgVersion } from "./packageVersion";
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
38
|
* Enum to support different types of snapshot formats.
|
|
@@ -83,7 +84,7 @@ export async function fetchSnapshot(
|
|
|
83
84
|
},
|
|
84
85
|
async () => snapshotDownloader(url, { headers }),
|
|
85
86
|
) as IOdspResponse<IOdspSnapshot>;
|
|
86
|
-
return
|
|
87
|
+
return convertOdspSnapshotToSnapshotTreeAndBlobs(response.content);
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
export async function fetchSnapshotWithRedeem(
|
|
@@ -93,11 +94,11 @@ export async function fetchSnapshotWithRedeem(
|
|
|
93
94
|
forceAccessTokenViaAuthorizationHeader: boolean,
|
|
94
95
|
logger: ITelemetryLogger,
|
|
95
96
|
snapshotDownloader: (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
finalOdspResolvedUrl: IOdspResolvedUrl,
|
|
98
|
+
storageToken: string,
|
|
99
|
+
snapshotOptions: ISnapshotOptions | undefined,
|
|
100
|
+
controller?: AbortController,
|
|
101
|
+
) => Promise<ISnapshotRequestAndResponseOptions>,
|
|
101
102
|
putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,
|
|
102
103
|
removeEntries: () => Promise<void>,
|
|
103
104
|
enableRedeemFallback?: boolean,
|
|
@@ -126,12 +127,13 @@ export async function fetchSnapshotWithRedeem(
|
|
|
126
127
|
await redeemSharingLink(
|
|
127
128
|
odspResolvedUrl, storageTokenFetcher, logger, forceAccessTokenViaAuthorizationHeader);
|
|
128
129
|
const odspResolvedUrlWithoutShareLink: IOdspResolvedUrl =
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
130
|
+
{
|
|
131
|
+
...odspResolvedUrl,
|
|
132
|
+
shareLinkInfo: {
|
|
133
|
+
...odspResolvedUrl.shareLinkInfo,
|
|
134
|
+
sharingLinkToRedeem: undefined,
|
|
135
|
+
},
|
|
136
|
+
};
|
|
135
137
|
|
|
136
138
|
return fetchLatestSnapshotCore(
|
|
137
139
|
odspResolvedUrlWithoutShareLink,
|
|
@@ -168,15 +170,15 @@ async function redeemSharingLink(
|
|
|
168
170
|
eventName: "RedeemShareLink",
|
|
169
171
|
},
|
|
170
172
|
async () => getWithRetryForTokenRefresh(async (tokenFetchOptions) => {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
173
|
+
assert(!!odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem,
|
|
174
|
+
0x1ed /* "Share link should be present" */);
|
|
175
|
+
const storageToken = await storageTokenFetcher(tokenFetchOptions, "RedeemShareLink");
|
|
176
|
+
const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem);
|
|
177
|
+
const redeemUrl = `${odspResolvedUrl.siteUrl}/_api/v2.0/shares/${encodedShareUrl}`;
|
|
178
|
+
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
179
|
+
redeemUrl, storageToken, forceAccessTokenViaAuthorizationHeader);
|
|
180
|
+
headers.prefer = "redeemSharingLink";
|
|
181
|
+
return fetchAndParseAsJSONHelper(url, { headers });
|
|
180
182
|
}),
|
|
181
183
|
);
|
|
182
184
|
}
|
|
@@ -187,11 +189,11 @@ async function fetchLatestSnapshotCore(
|
|
|
187
189
|
snapshotOptions: ISnapshotOptions | undefined,
|
|
188
190
|
logger: ITelemetryLogger,
|
|
189
191
|
snapshotDownloader: (
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
192
|
+
finalOdspResolvedUrl: IOdspResolvedUrl,
|
|
193
|
+
storageToken: string,
|
|
194
|
+
snapshotOptions: ISnapshotOptions | undefined,
|
|
195
|
+
controller?: AbortController,
|
|
196
|
+
) => Promise<ISnapshotRequestAndResponseOptions>,
|
|
195
197
|
putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,
|
|
196
198
|
enableRedeemFallback?: boolean,
|
|
197
199
|
): Promise<ISnapshotContents> {
|
|
@@ -232,7 +234,64 @@ async function fetchLatestSnapshotCore(
|
|
|
232
234
|
snapshotOptions,
|
|
233
235
|
controller,
|
|
234
236
|
);
|
|
235
|
-
const
|
|
237
|
+
const odspResponse = response.odspResponse;
|
|
238
|
+
const contentType = odspResponse.headers.get("content-type");
|
|
239
|
+
odspResponse.propsToLog = {
|
|
240
|
+
...odspResponse.propsToLog,
|
|
241
|
+
contentType,
|
|
242
|
+
accept: response.requestHeaders.accept,
|
|
243
|
+
};
|
|
244
|
+
let parsedSnapshotContents: IOdspResponse<ISnapshotContents> | undefined;
|
|
245
|
+
try {
|
|
246
|
+
switch (contentType) {
|
|
247
|
+
case "application/json": {
|
|
248
|
+
const text = await odspResponse.content.text();
|
|
249
|
+
odspResponse.propsToLog.bodySize = text.length;
|
|
250
|
+
const content: IOdspSnapshot = JSON.parse(text);
|
|
251
|
+
validateBlobsAndTrees(content);
|
|
252
|
+
const snapshotContents: ISnapshotContents =
|
|
253
|
+
convertOdspSnapshotToSnapshotTreeAndBlobs(content);
|
|
254
|
+
parsedSnapshotContents = { ...odspResponse, content: snapshotContents };
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
case "application/ms-fluid": {
|
|
258
|
+
const content = await odspResponse.content.arrayBuffer();
|
|
259
|
+
odspResponse.propsToLog.bodySize = content.byteLength;
|
|
260
|
+
const snapshotContents: ISnapshotContents = parseCompactSnapshotResponse(
|
|
261
|
+
new ReadBuffer(new Uint8Array(content)));
|
|
262
|
+
if (snapshotContents.snapshotTree.trees === undefined ||
|
|
263
|
+
snapshotContents.snapshotTree.blobs === undefined) {
|
|
264
|
+
throw new NonRetryableError(
|
|
265
|
+
"Returned odsp snapshot is malformed. No trees or blobs!",
|
|
266
|
+
DriverErrorType.incorrectServerResponse,
|
|
267
|
+
{ driverVersion: pkgVersion, ...odspResponse.propsToLog },
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
parsedSnapshotContents = { ...odspResponse, content: snapshotContents };
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
default:
|
|
274
|
+
throw new NonRetryableError(
|
|
275
|
+
"Unknown snapshot content type",
|
|
276
|
+
DriverErrorType.incorrectServerResponse,
|
|
277
|
+
{ driverVersion: pkgVersion, ...odspResponse.propsToLog },
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
} catch (error) {
|
|
281
|
+
if (isFluidError(error)) {
|
|
282
|
+
error.addTelemetryProperties({ driverVersion: pkgVersion, ...odspResponse.propsToLog });
|
|
283
|
+
throw error;
|
|
284
|
+
}
|
|
285
|
+
const enhancedError = wrapError(
|
|
286
|
+
error,
|
|
287
|
+
(errorMessage) => new NonRetryableError(
|
|
288
|
+
`Error parsing snapshot response: ${errorMessage}`,
|
|
289
|
+
DriverErrorType.genericError,
|
|
290
|
+
{ driverVersion: pkgVersion, ...odspResponse.propsToLog }));
|
|
291
|
+
throw enhancedError;
|
|
292
|
+
}
|
|
293
|
+
assert(parsedSnapshotContents !== undefined, 0x312 /* snapshot should be parsed */);
|
|
294
|
+
const snapshot = parsedSnapshotContents.content;
|
|
236
295
|
// From: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming
|
|
237
296
|
// fetchStart: immediately before the browser starts to fetch the resource.
|
|
238
297
|
// requestStart: immediately before the browser starts requesting the resource from the server
|
|
@@ -254,7 +313,7 @@ async function fetchLatestSnapshotCore(
|
|
|
254
313
|
let fetchStartToResponseEndTime: number | undefined; // responseEnd - fetchStart
|
|
255
314
|
let reqStartToResponseEndTime: number | undefined; // responseEnd - requestStart
|
|
256
315
|
let networkTime: number | undefined; // responseEnd - startTime
|
|
257
|
-
const spReqDuration =
|
|
316
|
+
const spReqDuration = odspResponse.headers.get("sprequestduration");
|
|
258
317
|
|
|
259
318
|
// getEntriesByType is only available in browser performance object
|
|
260
319
|
const resources1 = performance.getEntriesByType?.("resource") ?? [];
|
|
@@ -286,12 +345,12 @@ async function fetchLatestSnapshotCore(
|
|
|
286
345
|
}
|
|
287
346
|
|
|
288
347
|
const { numTrees, numBlobs, encodedBlobsSize } =
|
|
289
|
-
|
|
348
|
+
evalBlobsAndTrees(parsedSnapshotContents.content);
|
|
290
349
|
|
|
291
350
|
// There are some scenarios in ODSP where we cannot cache, trees/latest will explicitly tell us when we
|
|
292
351
|
// cannot cache using an HTTP response header.
|
|
293
352
|
const canCache =
|
|
294
|
-
|
|
353
|
+
odspResponse.headers.get("disablebrowsercachingofusercontent") !== "true";
|
|
295
354
|
const sequenceNumber: number = snapshot.sequenceNumber ?? 0;
|
|
296
355
|
const seqNumberFromOps = snapshot.ops && snapshot.ops.length > 0 ?
|
|
297
356
|
snapshot.ops[0].sequenceNumber - 1 :
|
|
@@ -302,7 +361,7 @@ async function fetchLatestSnapshotCore(
|
|
|
302
361
|
logger.sendErrorEvent({ eventName: "fetchSnapshotError", sequenceNumber, seqNumberFromOps });
|
|
303
362
|
snapshot.sequenceNumber = undefined;
|
|
304
363
|
} else if (canCache) {
|
|
305
|
-
const fluidEpoch =
|
|
364
|
+
const fluidEpoch = odspResponse.headers.get("x-fluid-epoch");
|
|
306
365
|
assert(fluidEpoch !== undefined, 0x1e6 /* "Epoch should be present in response" */);
|
|
307
366
|
const value: ISnapshotCachedEntry = {
|
|
308
367
|
...snapshot,
|
|
@@ -346,8 +405,8 @@ async function fetchLatestSnapshotCore(
|
|
|
346
405
|
// Azure Fluid Relay service; desc=S, FRP; desc=False. Here, FRL is the duration taken for redeem,
|
|
347
406
|
// Azure Fluid Relay service is the redeem status (S means success), and FRP is a flag to indicate
|
|
348
407
|
// if the permission has changed.
|
|
349
|
-
sltelemetry:
|
|
350
|
-
...
|
|
408
|
+
sltelemetry: odspResponse.headers.get("x-fluid-sltelemetry"),
|
|
409
|
+
...odspResponse.propsToLog,
|
|
351
410
|
});
|
|
352
411
|
return snapshot;
|
|
353
412
|
},
|
|
@@ -363,8 +422,8 @@ async function fetchLatestSnapshotCore(
|
|
|
363
422
|
});
|
|
364
423
|
}
|
|
365
424
|
|
|
366
|
-
interface ISnapshotRequestAndResponseOptions {
|
|
367
|
-
|
|
425
|
+
export interface ISnapshotRequestAndResponseOptions {
|
|
426
|
+
odspResponse: IOdspResponse<Response>;
|
|
368
427
|
requestUrl: string;
|
|
369
428
|
requestHeaders: { [index: string]: any; };
|
|
370
429
|
}
|
|
@@ -406,11 +465,7 @@ function getFormBodyAndHeaders(
|
|
|
406
465
|
return { body: postBody, headers: header };
|
|
407
466
|
}
|
|
408
467
|
|
|
409
|
-
function
|
|
410
|
-
assert(snapshot.snapshotTree !== undefined,
|
|
411
|
-
0x200 /* "Returned odsp snapshot is malformed. No trees!" */);
|
|
412
|
-
assert(snapshot.blobs !== undefined,
|
|
413
|
-
0x201 /* "Returned odsp snapshot is malformed. No blobs!" */);
|
|
468
|
+
function evalBlobsAndTrees(snapshot: ISnapshotContents) {
|
|
414
469
|
const numTrees = countTreesInSnapshotTree(snapshot.snapshotTree);
|
|
415
470
|
const numBlobs = snapshot.blobs.size;
|
|
416
471
|
let encodedBlobsSize = 0;
|
|
@@ -420,6 +475,13 @@ function validateAndEvalBlobsAndTrees(snapshot: ISnapshotContents) {
|
|
|
420
475
|
return { numTrees, numBlobs, encodedBlobsSize };
|
|
421
476
|
}
|
|
422
477
|
|
|
478
|
+
export function validateBlobsAndTrees(snapshot: IOdspSnapshot) {
|
|
479
|
+
assert(snapshot.trees !== undefined,
|
|
480
|
+
0x200 /* "Returned odsp snapshot is malformed. No trees!" */);
|
|
481
|
+
assert(snapshot.blobs !== undefined,
|
|
482
|
+
0x201 /* "Returned odsp snapshot is malformed. No blobs!" */);
|
|
483
|
+
}
|
|
484
|
+
|
|
423
485
|
function countTreesInSnapshotTree(snapshotTree: ISnapshotTree): number {
|
|
424
486
|
let numTrees = 0;
|
|
425
487
|
for (const [_, tree] of Object.entries(snapshotTree.trees)) {
|
|
@@ -448,6 +510,7 @@ export async function downloadSnapshot(
|
|
|
448
510
|
snapshotFormatFetchType?: SnapshotFormatSupportType,
|
|
449
511
|
controller?: AbortController,
|
|
450
512
|
epochTracker?: EpochTracker,
|
|
513
|
+
scenarioName?: string,
|
|
451
514
|
): Promise<ISnapshotRequestAndResponseOptions> {
|
|
452
515
|
// back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51
|
|
453
516
|
const sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;
|
|
@@ -482,28 +545,11 @@ export async function downloadSnapshot(
|
|
|
482
545
|
headers.accept = "application/json";
|
|
483
546
|
}
|
|
484
547
|
|
|
485
|
-
const
|
|
548
|
+
const odspResponse = await (epochTracker?.fetch(url, fetchOptions, "treesLatest", true, scenarioName) ??
|
|
486
549
|
fetchHelper(url, fetchOptions));
|
|
487
550
|
|
|
488
|
-
let finalSnapshotContents: IOdspResponse<ISnapshotContents>;
|
|
489
|
-
const contentType = response.headers.get("content-type");
|
|
490
|
-
if (contentType === "application/json") {
|
|
491
|
-
const text = await response.content.text();
|
|
492
|
-
const content: IOdspSnapshot = JSON.parse(text);
|
|
493
|
-
response.propsToLog.bodySize = text.length;
|
|
494
|
-
const snapshotContents: ISnapshotContents = convertOdspSnapshotToSnapsohtTreeAndBlobs(content);
|
|
495
|
-
finalSnapshotContents = { ...response, content: snapshotContents };
|
|
496
|
-
} else {
|
|
497
|
-
assert(contentType === "application/ms-fluid", 0x2c3 /* "Content type should be application/ms-fluid" */);
|
|
498
|
-
const content = await response.content.arrayBuffer();
|
|
499
|
-
response.propsToLog.bodySize = content.byteLength;
|
|
500
|
-
const snapshotContents: ISnapshotContents = parseCompactSnapshotResponse(
|
|
501
|
-
new ReadBuffer(new Uint8Array(content)));
|
|
502
|
-
finalSnapshotContents = { ...response, content: snapshotContents };
|
|
503
|
-
}
|
|
504
|
-
response.propsToLog.contentType = contentType;
|
|
505
551
|
return {
|
|
506
|
-
|
|
552
|
+
odspResponse,
|
|
507
553
|
requestHeaders: headers,
|
|
508
554
|
requestUrl: url,
|
|
509
555
|
};
|
|
@@ -513,7 +559,7 @@ function isRedeemSharingLinkError(odspResolvedUrl: IOdspResolvedUrl, error: any)
|
|
|
513
559
|
if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined
|
|
514
560
|
&& (typeof error === "object" && error !== null)
|
|
515
561
|
&& (error.errorType === DriverErrorType.authorizationError
|
|
516
|
-
|
|
562
|
+
|| error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError)) {
|
|
517
563
|
return true;
|
|
518
564
|
}
|
|
519
565
|
return false;
|
|
@@ -526,9 +572,9 @@ function getEncodedShareUrl(url: string): string {
|
|
|
526
572
|
*/
|
|
527
573
|
let encodedUrl = fromUtf8ToBase64(encodeURI(url));
|
|
528
574
|
encodedUrl = encodedUrl
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
575
|
+
.replace(/=+$/g, "")
|
|
576
|
+
.replace(/\//g, "_")
|
|
577
|
+
.replace(/\+/g, "-");
|
|
532
578
|
encodedUrl = "u!".concat(encodedUrl);
|
|
533
579
|
return encodedUrl;
|
|
534
580
|
}
|
package/src/index.ts
CHANGED
|
@@ -31,3 +31,7 @@ export * from "./odspDriverUrlResolver";
|
|
|
31
31
|
|
|
32
32
|
// It's used by URL resolve code, but also has some public functions
|
|
33
33
|
export * from "./odspFluidFileLink";
|
|
34
|
+
|
|
35
|
+
// Wire format related
|
|
36
|
+
export * from "./compactSnapshotParser";
|
|
37
|
+
export * from "./ReadBufferUtils";
|