@fluidframework/odsp-driver 2.0.0-internal.2.1.2 → 2.0.0-internal.2.2.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/.eslintrc.js +1 -1
- package/dist/compactSnapshotParser.d.ts +1 -2
- package/dist/compactSnapshotParser.d.ts.map +1 -1
- package/dist/compactSnapshotParser.js +6 -2
- package/dist/compactSnapshotParser.js.map +1 -1
- package/dist/fetchSnapshot.d.ts.map +1 -1
- package/dist/fetchSnapshot.js +13 -18
- package/dist/fetchSnapshot.js.map +1 -1
- package/dist/localOdspDriver/localOdspDeltaStorageService.d.ts +17 -0
- package/dist/localOdspDriver/localOdspDeltaStorageService.d.ts.map +1 -0
- package/dist/localOdspDriver/localOdspDeltaStorageService.js +35 -0
- package/dist/localOdspDriver/localOdspDeltaStorageService.js.map +1 -0
- package/dist/localOdspDriver/localOdspDocumentService.d.ts +1 -0
- package/dist/localOdspDriver/localOdspDocumentService.d.ts.map +1 -1
- package/dist/localOdspDriver/localOdspDocumentService.js +5 -2
- package/dist/localOdspDriver/localOdspDocumentService.js.map +1 -1
- package/dist/odspDeltaStorageService.d.ts +0 -1
- package/dist/odspDeltaStorageService.d.ts.map +1 -1
- package/dist/odspDeltaStorageService.js +4 -20
- package/dist/odspDeltaStorageService.js.map +1 -1
- package/dist/odspDocumentDeltaConnection.js +1 -1
- package/dist/odspDocumentDeltaConnection.js.map +1 -1
- package/dist/odspDocumentService.d.ts.map +1 -1
- package/dist/odspDocumentService.js +9 -2
- package/dist/odspDocumentService.js.map +1 -1
- package/dist/odspUtils.d.ts +4 -0
- package/dist/odspUtils.d.ts.map +1 -1
- package/dist/odspUtils.js +32 -1
- 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/zipItDataRepresentationUtils.d.ts +17 -2
- package/dist/zipItDataRepresentationUtils.d.ts.map +1 -1
- package/dist/zipItDataRepresentationUtils.js +15 -2
- package/dist/zipItDataRepresentationUtils.js.map +1 -1
- package/lib/compactSnapshotParser.d.ts +1 -2
- package/lib/compactSnapshotParser.d.ts.map +1 -1
- package/lib/compactSnapshotParser.js +6 -2
- package/lib/compactSnapshotParser.js.map +1 -1
- package/lib/fetchSnapshot.d.ts.map +1 -1
- package/lib/fetchSnapshot.js +14 -19
- package/lib/fetchSnapshot.js.map +1 -1
- package/lib/localOdspDriver/localOdspDeltaStorageService.d.ts +17 -0
- package/lib/localOdspDriver/localOdspDeltaStorageService.d.ts.map +1 -0
- package/lib/localOdspDriver/localOdspDeltaStorageService.js +31 -0
- package/lib/localOdspDriver/localOdspDeltaStorageService.js.map +1 -0
- package/lib/localOdspDriver/localOdspDocumentService.d.ts +1 -0
- package/lib/localOdspDriver/localOdspDocumentService.d.ts.map +1 -1
- package/lib/localOdspDriver/localOdspDocumentService.js +6 -3
- package/lib/localOdspDriver/localOdspDocumentService.js.map +1 -1
- package/lib/odspDeltaStorageService.d.ts +0 -1
- package/lib/odspDeltaStorageService.d.ts.map +1 -1
- package/lib/odspDeltaStorageService.js +5 -21
- package/lib/odspDeltaStorageService.js.map +1 -1
- package/lib/odspDocumentDeltaConnection.js +1 -1
- package/lib/odspDocumentDeltaConnection.js.map +1 -1
- package/lib/odspDocumentService.d.ts.map +1 -1
- package/lib/odspDocumentService.js +10 -3
- package/lib/odspDocumentService.js.map +1 -1
- package/lib/odspUtils.d.ts +4 -0
- package/lib/odspUtils.d.ts.map +1 -1
- package/lib/odspUtils.js +28 -0
- 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/zipItDataRepresentationUtils.d.ts +17 -2
- package/lib/zipItDataRepresentationUtils.d.ts.map +1 -1
- package/lib/zipItDataRepresentationUtils.js +15 -2
- package/lib/zipItDataRepresentationUtils.js.map +1 -1
- package/package.json +19 -14
- package/prettier.config.cjs +8 -0
- package/src/compactSnapshotParser.ts +16 -12
- package/src/fetchSnapshot.ts +29 -24
- package/src/localOdspDriver/localOdspDeltaStorageService.ts +46 -0
- package/src/localOdspDriver/localOdspDocumentService.ts +9 -3
- package/src/odspDeltaStorageService.ts +5 -22
- package/src/odspDocumentDeltaConnection.ts +1 -1
- package/src/odspDocumentService.ts +9 -2
- package/src/odspUtils.ts +37 -0
- package/src/packageVersion.ts +1 -1
- package/src/zipItDataRepresentationUtils.ts +18 -3
package/.eslintrc.js
CHANGED
|
@@ -11,8 +11,7 @@ export declare const currentReadVersion = "1.0";
|
|
|
11
11
|
* represents how many times slower parsing path is executed. This will be then logged into telemetry.
|
|
12
12
|
*/
|
|
13
13
|
export interface ISnapshotContentsWithProps extends ISnapshotContents {
|
|
14
|
-
|
|
15
|
-
slowTreeStructureCount?: number;
|
|
14
|
+
telemetryProps: Record<string, number>;
|
|
16
15
|
}
|
|
17
16
|
/**
|
|
18
17
|
* Converts snapshot from binary compact representation to tree/blobs/ops.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compactSnapshotParser.d.ts","sourceRoot":"","sources":["../src/compactSnapshotParser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"compactSnapshotParser.d.ts","sourceRoot":"","sources":["../src/compactSnapshotParser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAetD,eAAO,MAAM,sBAAsB,QAAQ,CAAC;AAC5C,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAExC;;;GAGG;AACH,MAAM,WAAW,0BAA2B,SAAQ,iBAAiB;IACjE,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAsKD;;;;GAIG;AACH,wBAAgB,4BAA4B,CACxC,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,gBAAgB,GACzB,0BAA0B,CAoC5B"}
|
|
@@ -8,6 +8,7 @@ exports.parseCompactSnapshotResponse = exports.currentReadVersion = exports.snap
|
|
|
8
8
|
const common_utils_1 = require("@fluidframework/common-utils");
|
|
9
9
|
const ReadBufferUtils_1 = require("./ReadBufferUtils");
|
|
10
10
|
const zipItDataRepresentationUtils_1 = require("./zipItDataRepresentationUtils");
|
|
11
|
+
const odspUtils_1 = require("./odspUtils");
|
|
11
12
|
exports.snapshotMinReadVersion = "1.0";
|
|
12
13
|
exports.currentReadVersion = "1.0";
|
|
13
14
|
/**
|
|
@@ -168,7 +169,7 @@ function readSnapshotSection(node) {
|
|
|
168
169
|
* @returns - tree, blobs and ops from the snapshot.
|
|
169
170
|
*/
|
|
170
171
|
function parseCompactSnapshotResponse(buffer, logger) {
|
|
171
|
-
const builder = zipItDataRepresentationUtils_1.TreeBuilder.load(new ReadBufferUtils_1.ReadBuffer(buffer), logger);
|
|
172
|
+
const { builder, telemetryProps } = zipItDataRepresentationUtils_1.TreeBuilder.load(new ReadBufferUtils_1.ReadBuffer(buffer), logger);
|
|
172
173
|
(0, common_utils_1.assert)(builder.length === 1, 0x219 /* "1 root should be there" */);
|
|
173
174
|
const root = builder.getNode(0);
|
|
174
175
|
const records = (0, zipItDataRepresentationUtils_1.getNodeProps)(root);
|
|
@@ -180,7 +181,10 @@ function parseCompactSnapshotResponse(buffer, logger) {
|
|
|
180
181
|
(0, common_utils_1.assert)(parseFloat(exports.snapshotMinReadVersion) >= parseFloat(mrv), 0x20f /* "Driver min read version should >= to server minReadVersion" */);
|
|
181
182
|
(0, common_utils_1.assert)(parseFloat(cv) >= parseFloat(exports.snapshotMinReadVersion), 0x210 /* "Snapshot should be created with minReadVersion or above" */);
|
|
182
183
|
(0, common_utils_1.assert)(exports.currentReadVersion === cv, 0x2c2 /* "Create Version should be equal to currentReadVersion" */);
|
|
183
|
-
|
|
184
|
+
const [snapshot, durationSnapshotTree] = (0, odspUtils_1.measure)(() => readSnapshotSection(records.snapshot));
|
|
185
|
+
const [blobs, durationBlobs] = (0, odspUtils_1.measure)(() => readBlobSection(records.blobs));
|
|
186
|
+
return Object.assign(Object.assign(Object.assign({}, snapshot), blobs), { ops: records.deltas !== undefined ? readOpsSection(records.deltas) : [], latestSequenceNumber: records.lsn, telemetryProps: Object.assign(Object.assign({}, telemetryProps), { durationSnapshotTree,
|
|
187
|
+
durationBlobs, slowTreeStructureCount: snapshot.slowTreeStructureCount, slowBlobStructureCount: blobs.slowBlobStructureCount }) });
|
|
184
188
|
}
|
|
185
189
|
exports.parseCompactSnapshotResponse = parseCompactSnapshotResponse;
|
|
186
190
|
//# sourceMappingURL=compactSnapshotParser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compactSnapshotParser.js","sourceRoot":"","sources":["../src/compactSnapshotParser.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/common-utils\";\nimport { ISequencedDocumentMessage, ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { ReadBuffer } from \"./ReadBufferUtils\";\nimport {\n assertBlobCoreInstance,\n getStringInstance,\n assertBoolInstance,\n assertNodeCoreInstance,\n assertNumberInstance,\n getNodeProps,\n NodeCore,\n NodeTypes,\n TreeBuilder,\n} from \"./zipItDataRepresentationUtils\";\n\nexport const snapshotMinReadVersion = \"1.0\";\nexport const currentReadVersion = \"1.0\";\n\ninterface ISnapshotSection {\n snapshotTree: ISnapshotTree;\n sequenceNumber: number;\n slowTreeStructureCount: number;\n}\n\n/**\n * The parsing is significantly faster if the position of props is well known instead of dynamic. So these variables\n * represents how many times slower parsing path is executed. This will be then logged into telemetry.\n */\nexport interface ISnapshotContentsWithProps extends ISnapshotContents {\n slowBlobStructureCount?: number;\n slowTreeStructureCount?: number;\n}\n\n/**\n * Recreates blobs section of the tree.\n * @param node - tree node to read blob section from\n */\nfunction readBlobSection(node: NodeTypes) {\n assertNodeCoreInstance(node, \"TreeBlobs should be of type NodeCore\");\n let slowBlobStructureCount = 0;\n const blobs: Map<string, ArrayBuffer> = new Map();\n for (const blob of node) {\n assertNodeCoreInstance(blob, \"blob should be node\");\n\n /**\n * Perf optimization - the most common cases!\n * This is essentially unrolling code below for faster processing\n * It speeds up tree parsing by 2-3x times!\n */\n if (blob.length === 4 && blob.getMaybeString(0) === \"id\" && blob.getMaybeString(2) === \"data\") {\n // \"id\": <node name>\n // \"data\": <blob>\n blobs.set(blob.getString(1), blob.getBlob(3).arrayBuffer);\n continue;\n }\n\n /**\n * More generalized workflow\n */\n slowBlobStructureCount += 1;\n const records = getNodeProps(blob);\n assertBlobCoreInstance(records.data, \"data should be of BlobCore type\");\n const id = getStringInstance(records.id, \"blob id should be string\");\n blobs.set(id, records.data.arrayBuffer);\n }\n return { blobs, slowBlobStructureCount };\n}\n\n/**\n * Recreates ops section of the tree.\n * @param node - tree node to read ops section from\n */\nfunction readOpsSection(node: NodeTypes) {\n assertNodeCoreInstance(node, \"Deltas should be of type NodeCore\");\n const ops: ISequencedDocumentMessage[] = [];\n const records = getNodeProps(node);\n assertNumberInstance(records.firstSequenceNumber, \"Seq number should be a number\");\n assertNodeCoreInstance(records.deltas, \"Deltas should be a Node\");\n for (let i = 0; i < records.deltas.length; ++i) {\n ops.push(JSON.parse(records.deltas.getString(i)));\n }\n assert(records.firstSequenceNumber.valueOf() === ops[0].sequenceNumber,\n 0x280 /* \"Validate first op seq number\" */);\n return ops;\n}\n\n/**\n * Recreates snapshot tree out of tree representation.\n * @param node - tree node to de-serialize from\n */\nfunction readTreeSection(node: NodeCore) {\n let slowTreeStructureCount = 0;\n const trees = {};\n const snapshotTree: ISnapshotTree = {\n blobs: {},\n trees,\n };\n for (const treeNode of node) {\n assertNodeCoreInstance(treeNode, \"tree nodes should be nodes\");\n\n /**\n * Perf optimization - the most common cases!\n * This is essentially unrolling code below for faster processing\n * It speeds up tree parsing by 2-3x times!\n */\n const length = treeNode.length;\n if (length > 0 && treeNode.getMaybeString(0) === \"name\") {\n if (length === 4) {\n const content = treeNode.getMaybeString(2);\n // \"name\": <node name>\n // \"children\": <blob id>\n if (content === \"children\") {\n const result = readTreeSection(treeNode.getNode(3));\n trees[treeNode.getString(1)] = result.snapshotTree;\n slowTreeStructureCount += result.slowTreeStructureCount;\n continue;\n }\n // \"name\": <node name>\n // \"value\": <blob id>\n if (content === \"value\") {\n snapshotTree.blobs[treeNode.getString(1)] = treeNode.getString(3);\n continue;\n }\n }\n\n // \"name\": <node name>\n // \"nodeType\": 3\n // \"value\": <blob id>\n if (length === 6 &&\n treeNode.getMaybeString(2) === \"nodeType\" &&\n treeNode.getMaybeString(4) === \"value\") {\n snapshotTree.blobs[treeNode.getString(1)] = treeNode.getString(5);\n continue;\n }\n\n // \"name\": <node name>\n // \"unreferenced\": true\n // \"children\": <blob id>\n if (length === 6 &&\n treeNode.getMaybeString(2) === \"unreferenced\" &&\n treeNode.getMaybeString(4) === \"children\") {\n const result = readTreeSection(treeNode.getNode(5));\n trees[treeNode.getString(1)] = result.snapshotTree;\n slowTreeStructureCount += result.slowTreeStructureCount;\n assert(treeNode.getBool(3), 0x3db /* Unreferenced if present should be true */);\n snapshotTree.unreferenced = true;\n continue;\n }\n }\n\n /**\n * More generalized workflow\n */\n slowTreeStructureCount += 1;\n const records = getNodeProps(treeNode);\n\n if (records.unreferenced !== undefined) {\n assertBoolInstance(records.unreferenced, \"Unreferenced flag should be bool\");\n assert(records.unreferenced, 0x281 /* \"Unreferenced if present should be true\" */);\n snapshotTree.unreferenced = true;\n }\n\n const path = getStringInstance(records.name, \"Path name should be string\");\n if (records.value !== undefined) {\n snapshotTree.blobs[path] = getStringInstance(records.value, \"Blob value should be string\");\n } else if (records.children !== undefined) {\n assertNodeCoreInstance(records.children, \"Trees should be of type NodeCore\");\n const result = readTreeSection(records.children);\n trees[path] = result.snapshotTree;\n slowTreeStructureCount += result.slowTreeStructureCount;\n } else {\n trees[path] = { blobs: {}, trees: {} };\n }\n }\n return { snapshotTree, slowTreeStructureCount };\n}\n\n/**\n * Recreates snapshot tree out of tree representation.\n * @param node - tree node to de-serialize from\n */\nfunction readSnapshotSection(node: NodeTypes): ISnapshotSection {\n assertNodeCoreInstance(node, \"Snapshot should be of type NodeCore\");\n const records = getNodeProps(node);\n\n assertNodeCoreInstance(records.treeNodes, \"TreeNodes should be of type NodeCore\");\n assertNumberInstance(records.sequenceNumber, \"sequenceNumber should be of type number\");\n const { snapshotTree, slowTreeStructureCount } = readTreeSection(records.treeNodes);\n snapshotTree.id = getStringInstance(records.id, \"snapshotId should be string\");\n const sequenceNumber = records.sequenceNumber.valueOf();\n return {\n sequenceNumber,\n snapshotTree,\n slowTreeStructureCount,\n };\n}\n\n/**\n * Converts snapshot from binary compact representation to tree/blobs/ops.\n * @param buffer - Compact snapshot to be parsed into tree/blobs/ops.\n * @returns - tree, blobs and ops from the snapshot.\n */\nexport function parseCompactSnapshotResponse(\n buffer: Uint8Array,\n logger: ITelemetryLogger,\n): ISnapshotContentsWithProps {\n const builder = TreeBuilder.load(new ReadBuffer(buffer), logger);\n assert(builder.length === 1, 0x219 /* \"1 root should be there\" */);\n const root = builder.getNode(0);\n\n const records = getNodeProps(root);\n\n const mrv = getStringInstance(records.mrv, \"minReadVersion should be string\");\n const cv = getStringInstance(records.cv, \"createVersion should be string\");\n if (records.lsn !== undefined) {\n assertNumberInstance(records.lsn, \"lsn should be a number\");\n }\n\n assert(parseFloat(snapshotMinReadVersion) >= parseFloat(mrv),\n 0x20f /* \"Driver min read version should >= to server minReadVersion\" */);\n assert(parseFloat(cv) >= parseFloat(snapshotMinReadVersion),\n 0x210 /* \"Snapshot should be created with minReadVersion or above\" */);\n assert(currentReadVersion === cv,\n 0x2c2 /* \"Create Version should be equal to currentReadVersion\" */);\n\n return {\n ...readSnapshotSection(records.snapshot),\n ...readBlobSection(records.blobs),\n ops: records.deltas !== undefined ? readOpsSection(records.deltas) : [],\n latestSequenceNumber: records.lsn,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"compactSnapshotParser.js","sourceRoot":"","sources":["../src/compactSnapshotParser.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/common-utils\";\nimport { ISequencedDocumentMessage, ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { ReadBuffer } from \"./ReadBufferUtils\";\nimport {\n assertBlobCoreInstance,\n getStringInstance,\n assertBoolInstance,\n assertNodeCoreInstance,\n assertNumberInstance,\n getNodeProps,\n NodeCore,\n NodeTypes,\n TreeBuilder,\n} from \"./zipItDataRepresentationUtils\";\nimport { measure } from \"./odspUtils\";\n\nexport const snapshotMinReadVersion = \"1.0\";\nexport const currentReadVersion = \"1.0\";\n\n/**\n * The parsing is significantly faster if the position of props is well known instead of dynamic. So these variables\n * represents how many times slower parsing path is executed. This will be then logged into telemetry.\n */\nexport interface ISnapshotContentsWithProps extends ISnapshotContents {\n telemetryProps: Record<string, number>;\n}\n\n/**\n * Recreates blobs section of the tree.\n * @param node - tree node to read blob section from\n */\nfunction readBlobSection(node: NodeTypes) {\n assertNodeCoreInstance(node, \"TreeBlobs should be of type NodeCore\");\n let slowBlobStructureCount = 0;\n const blobs: Map<string, ArrayBuffer> = new Map();\n for (const blob of node) {\n assertNodeCoreInstance(blob, \"blob should be node\");\n\n /**\n * Perf optimization - the most common cases!\n * This is essentially unrolling code below for faster processing\n * It speeds up tree parsing by 2-3x times!\n */\n if (blob.length === 4 && blob.getMaybeString(0) === \"id\" && blob.getMaybeString(2) === \"data\") {\n // \"id\": <node name>\n // \"data\": <blob>\n blobs.set(blob.getString(1), blob.getBlob(3).arrayBuffer);\n continue;\n }\n\n /**\n * More generalized workflow\n */\n slowBlobStructureCount += 1;\n const records = getNodeProps(blob);\n assertBlobCoreInstance(records.data, \"data should be of BlobCore type\");\n const id = getStringInstance(records.id, \"blob id should be string\");\n blobs.set(id, records.data.arrayBuffer);\n }\n return { blobs, slowBlobStructureCount };\n}\n\n/**\n * Recreates ops section of the tree.\n * @param node - tree node to read ops section from\n */\nfunction readOpsSection(node: NodeTypes) {\n assertNodeCoreInstance(node, \"Deltas should be of type NodeCore\");\n const ops: ISequencedDocumentMessage[] = [];\n const records = getNodeProps(node);\n assertNumberInstance(records.firstSequenceNumber, \"Seq number should be a number\");\n assertNodeCoreInstance(records.deltas, \"Deltas should be a Node\");\n for (let i = 0; i < records.deltas.length; ++i) {\n ops.push(JSON.parse(records.deltas.getString(i)));\n }\n assert(records.firstSequenceNumber.valueOf() === ops[0].sequenceNumber,\n 0x280 /* \"Validate first op seq number\" */);\n return ops;\n}\n\n/**\n * Recreates snapshot tree out of tree representation.\n * @param node - tree node to de-serialize from\n */\nfunction readTreeSection(node: NodeCore) {\n let slowTreeStructureCount = 0;\n const trees = {};\n const snapshotTree: ISnapshotTree = {\n blobs: {},\n trees,\n };\n for (const treeNode of node) {\n assertNodeCoreInstance(treeNode, \"tree nodes should be nodes\");\n\n /**\n * Perf optimization - the most common cases!\n * This is essentially unrolling code below for faster processing\n * It speeds up tree parsing by 2-3x times!\n */\n const length = treeNode.length;\n if (length > 0 && treeNode.getMaybeString(0) === \"name\") {\n if (length === 4) {\n const content = treeNode.getMaybeString(2);\n // \"name\": <node name>\n // \"children\": <blob id>\n if (content === \"children\") {\n const result = readTreeSection(treeNode.getNode(3));\n trees[treeNode.getString(1)] = result.snapshotTree;\n slowTreeStructureCount += result.slowTreeStructureCount;\n continue;\n }\n // \"name\": <node name>\n // \"value\": <blob id>\n if (content === \"value\") {\n snapshotTree.blobs[treeNode.getString(1)] = treeNode.getString(3);\n continue;\n }\n }\n\n // \"name\": <node name>\n // \"nodeType\": 3\n // \"value\": <blob id>\n if (length === 6 &&\n treeNode.getMaybeString(2) === \"nodeType\" &&\n treeNode.getMaybeString(4) === \"value\") {\n snapshotTree.blobs[treeNode.getString(1)] = treeNode.getString(5);\n continue;\n }\n\n // \"name\": <node name>\n // \"unreferenced\": true\n // \"children\": <blob id>\n if (length === 6 &&\n treeNode.getMaybeString(2) === \"unreferenced\" &&\n treeNode.getMaybeString(4) === \"children\") {\n const result = readTreeSection(treeNode.getNode(5));\n trees[treeNode.getString(1)] = result.snapshotTree;\n slowTreeStructureCount += result.slowTreeStructureCount;\n assert(treeNode.getBool(3), 0x3db /* Unreferenced if present should be true */);\n snapshotTree.unreferenced = true;\n continue;\n }\n }\n\n /**\n * More generalized workflow\n */\n slowTreeStructureCount += 1;\n const records = getNodeProps(treeNode);\n\n if (records.unreferenced !== undefined) {\n assertBoolInstance(records.unreferenced, \"Unreferenced flag should be bool\");\n assert(records.unreferenced, 0x281 /* \"Unreferenced if present should be true\" */);\n snapshotTree.unreferenced = true;\n }\n\n const path = getStringInstance(records.name, \"Path name should be string\");\n if (records.value !== undefined) {\n snapshotTree.blobs[path] = getStringInstance(records.value, \"Blob value should be string\");\n } else if (records.children !== undefined) {\n assertNodeCoreInstance(records.children, \"Trees should be of type NodeCore\");\n const result = readTreeSection(records.children);\n trees[path] = result.snapshotTree;\n slowTreeStructureCount += result.slowTreeStructureCount;\n } else {\n trees[path] = { blobs: {}, trees: {} };\n }\n }\n return { snapshotTree, slowTreeStructureCount };\n}\n\n/**\n * Recreates snapshot tree out of tree representation.\n * @param node - tree node to de-serialize from\n */\nfunction readSnapshotSection(node: NodeTypes) {\n assertNodeCoreInstance(node, \"Snapshot should be of type NodeCore\");\n const records = getNodeProps(node);\n\n assertNodeCoreInstance(records.treeNodes, \"TreeNodes should be of type NodeCore\");\n assertNumberInstance(records.sequenceNumber, \"sequenceNumber should be of type number\");\n const { snapshotTree, slowTreeStructureCount } = readTreeSection(records.treeNodes);\n snapshotTree.id = getStringInstance(records.id, \"snapshotId should be string\");\n const sequenceNumber = records.sequenceNumber.valueOf();\n return {\n sequenceNumber,\n snapshotTree,\n slowTreeStructureCount,\n };\n}\n\n/**\n * Converts snapshot from binary compact representation to tree/blobs/ops.\n * @param buffer - Compact snapshot to be parsed into tree/blobs/ops.\n * @returns - tree, blobs and ops from the snapshot.\n */\nexport function parseCompactSnapshotResponse(\n buffer: Uint8Array,\n logger: ITelemetryLogger,\n): ISnapshotContentsWithProps {\n const { builder, telemetryProps } = TreeBuilder.load(new ReadBuffer(buffer), logger);\n assert(builder.length === 1, 0x219 /* \"1 root should be there\" */);\n const root = builder.getNode(0);\n\n const records = getNodeProps(root);\n\n const mrv = getStringInstance(records.mrv, \"minReadVersion should be string\");\n const cv = getStringInstance(records.cv, \"createVersion should be string\");\n if (records.lsn !== undefined) {\n assertNumberInstance(records.lsn, \"lsn should be a number\");\n }\n\n assert(parseFloat(snapshotMinReadVersion) >= parseFloat(mrv),\n 0x20f /* \"Driver min read version should >= to server minReadVersion\" */);\n assert(parseFloat(cv) >= parseFloat(snapshotMinReadVersion),\n 0x210 /* \"Snapshot should be created with minReadVersion or above\" */);\n assert(currentReadVersion === cv,\n 0x2c2 /* \"Create Version should be equal to currentReadVersion\" */);\n\n const [snapshot, durationSnapshotTree] = measure(() => readSnapshotSection(records.snapshot));\n const [blobs, durationBlobs] = measure(() => readBlobSection(records.blobs));\n\n return {\n ...snapshot,\n ...blobs,\n ops: records.deltas !== undefined ? readOpsSection(records.deltas) : [],\n latestSequenceNumber: records.lsn,\n telemetryProps: {\n ...telemetryProps,\n durationSnapshotTree,\n durationBlobs,\n slowTreeStructureCount: snapshot.slowTreeStructureCount,\n slowBlobStructureCount: blobs.slowBlobStructureCount,\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetchSnapshot.d.ts","sourceRoot":"","sources":["../src/fetchSnapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAItE,OAAO,EACH,gBAAgB,EAChB,gBAAgB,EAEhB,+BAA+B,EAClC,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EAAE,aAAa,EAAwB,wBAAwB,EAA8B,MAAM,aAAa,CAAC;AAGxH,OAAO,EAKH,aAAa,
|
|
1
|
+
{"version":3,"file":"fetchSnapshot.d.ts","sourceRoot":"","sources":["../src/fetchSnapshot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAItE,OAAO,EACH,gBAAgB,EAChB,gBAAgB,EAEhB,+BAA+B,EAClC,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EAAE,aAAa,EAAwB,wBAAwB,EAA8B,MAAM,aAAa,CAAC;AAGxH,OAAO,EAKH,aAAa,EAGhB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C;;GAEG;AACH,oBAAY,yBAAyB;IACjC,IAAI,IAAI;IACR,MAAM,IAAI;IACV,aAAa,IAAI;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAC/B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,OAAO,EAC1B,sCAAsC,EAAE,OAAO,EAC/C,MAAM,EAAE,gBAAgB,EACxB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE;IAAE,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC;CAAE,KAAK,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,GAC9G,OAAO,CAAC,iBAAiB,CAAC,CAoB5B;AAED,wBAAsB,uBAAuB,CACzC,eAAe,EAAE,gBAAgB,EACjC,mBAAmB,EAAE,+BAA+B,EACpD,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,sCAAsC,EAAE,OAAO,EAC/C,MAAM,EAAE,gBAAgB,EACxB,kBAAkB,EAAE,CAChB,oBAAoB,EAAE,gBAAgB,EACtC,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,UAAU,CAAC,EAAE,eAAe,KAC3B,OAAO,CAAC,kCAAkC,CAAC,EAChD,UAAU,EAAE,CAAC,cAAc,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,EACvE,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAClC,oBAAoB,CAAC,EAAE,OAAO,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CA4D5B;AAyUD,MAAM,WAAW,kCAAkC;IAC/C,YAAY,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE;QAAE,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC;KAAE,CAAC;CAC7C;AAiDD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,QAK5D;AAWD;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAClC,eAAe,EAAE,gBAAgB,EACjC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,gBAAgB,EACxB,eAAe,EAAE,gBAAgB,GAAG,SAAS,EAC7C,uBAAuB,CAAC,EAAE,yBAAyB,EACnD,UAAU,CAAC,EAAE,eAAe,EAC5B,YAAY,CAAC,EAAE,YAAY,EAC3B,YAAY,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,kCAAkC,CAAC,CAwC7C"}
|
package/dist/fetchSnapshot.js
CHANGED
|
@@ -22,12 +22,6 @@ const odspUtils_1 = require("./odspUtils");
|
|
|
22
22
|
const odspSnapshotParser_1 = require("./odspSnapshotParser");
|
|
23
23
|
const compactSnapshotParser_1 = require("./compactSnapshotParser");
|
|
24
24
|
const packageVersion_1 = require("./packageVersion");
|
|
25
|
-
async function measure(callback) {
|
|
26
|
-
const start = common_utils_1.performance.now();
|
|
27
|
-
const result = await callback();
|
|
28
|
-
const time = common_utils_1.performance.now() - start;
|
|
29
|
-
return [result, time];
|
|
30
|
-
}
|
|
31
25
|
/**
|
|
32
26
|
* Enum to support different types of snapshot formats.
|
|
33
27
|
*/
|
|
@@ -133,14 +127,14 @@ async function fetchLatestSnapshotCore(odspResolvedUrl, storageTokenFetcher, sna
|
|
|
133
127
|
}
|
|
134
128
|
// This event measures only successful cases of getLatest call (no tokens, no retries).
|
|
135
129
|
return telemetry_utils_1.PerformanceEvent.timedExecAsync(logger, perfEvent, async (event) => {
|
|
136
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l
|
|
130
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
137
131
|
let controller;
|
|
138
132
|
let fetchTimeout;
|
|
139
133
|
if ((snapshotOptions === null || snapshotOptions === void 0 ? void 0 : snapshotOptions.timeout) !== undefined) {
|
|
140
134
|
controller = new abort_controller_1.default();
|
|
141
135
|
fetchTimeout = setTimeout(() => controller.abort(), snapshotOptions.timeout);
|
|
142
136
|
}
|
|
143
|
-
const [response, fetchTime] = await
|
|
137
|
+
const [response, fetchTime] = await (0, odspUtils_1.measureP)(async () => snapshotDownloader(odspResolvedUrl, storageToken, snapshotOptions, controller)).finally(() => {
|
|
144
138
|
// Clear the fetchTimeout once the response is fetched.
|
|
145
139
|
if (fetchTimeout !== undefined) {
|
|
146
140
|
clearTimeout(fetchTimeout);
|
|
@@ -164,28 +158,29 @@ async function fetchLatestSnapshotCore(odspResolvedUrl, storageTokenFetcher, sna
|
|
|
164
158
|
switch (contentTypeToRead) {
|
|
165
159
|
case "application/json": {
|
|
166
160
|
let text;
|
|
167
|
-
[text, receiveContentTime] = await
|
|
161
|
+
[text, receiveContentTime] = await (0, odspUtils_1.measureP)(async () => odspResponse.content.text());
|
|
168
162
|
propsToLog.bodySize = text.length;
|
|
169
163
|
let content;
|
|
170
|
-
[content, parseTime] =
|
|
164
|
+
[content, parseTime] = (0, odspUtils_1.measure)(() => JSON.parse(text));
|
|
171
165
|
validateBlobsAndTrees(content);
|
|
172
166
|
const snapshotContents = (0, odspSnapshotParser_1.convertOdspSnapshotToSnapshotTreeAndBlobs)(content);
|
|
173
|
-
parsedSnapshotContents = Object.assign(Object.assign({}, odspResponse), { content: snapshotContents });
|
|
167
|
+
parsedSnapshotContents = Object.assign(Object.assign({}, odspResponse), { content: Object.assign(Object.assign({}, snapshotContents), { telemetryProps: {} }) });
|
|
174
168
|
break;
|
|
175
169
|
}
|
|
176
170
|
case "application/ms-fluid": {
|
|
177
171
|
let content;
|
|
178
172
|
[content, receiveContentTime] =
|
|
179
|
-
await
|
|
173
|
+
await (0, odspUtils_1.measureP)(async () => odspResponse.content.arrayBuffer());
|
|
180
174
|
propsToLog.bodySize = content.byteLength;
|
|
181
175
|
let snapshotContents;
|
|
182
|
-
[snapshotContents, parseTime] =
|
|
176
|
+
[snapshotContents, parseTime] = (0, odspUtils_1.measure)(() => (0, compactSnapshotParser_1.parseCompactSnapshotResponse)(new Uint8Array(content), logger));
|
|
183
177
|
if (snapshotContents.snapshotTree.trees === undefined ||
|
|
184
178
|
snapshotContents.snapshotTree.blobs === undefined) {
|
|
185
179
|
throw new driver_utils_1.NonRetryableError("Returned odsp snapshot is malformed. No trees or blobs!", driver_definitions_1.DriverErrorType.incorrectServerResponse, propsToLog);
|
|
186
180
|
}
|
|
187
|
-
const
|
|
188
|
-
const
|
|
181
|
+
const props = snapshotContents.telemetryProps;
|
|
182
|
+
const slowTreeParseCodePaths = (_a = props.slowTreeStructureCount) !== null && _a !== void 0 ? _a : 0;
|
|
183
|
+
const slowBlobParseCodePaths = (_b = props.slowBlobStructureCount) !== null && _b !== void 0 ? _b : 0;
|
|
189
184
|
if (slowTreeParseCodePaths > 10 || slowBlobParseCodePaths > 10) {
|
|
190
185
|
logger.sendErrorEvent({
|
|
191
186
|
eventName: "SlowSnapshotParseCodePaths",
|
|
@@ -284,8 +279,8 @@ async function fetchLatestSnapshotCore(odspResolvedUrl, storageTokenFetcher, sna
|
|
|
284
279
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
285
280
|
putInCache(valueWithEpoch);
|
|
286
281
|
}
|
|
287
|
-
event.end(Object.assign({ trees, blobs: (_g = (_f = snapshot.blobs) === null || _f === void 0 ? void 0 : _f.size) !== null && _g !== void 0 ? _g : 0, leafNodes: numBlobs, encodedBlobsSize,
|
|
288
|
-
sequenceNumber, ops: (_j = (_h = snapshot.ops) === null || _h === void 0 ? void 0 : _h.length) !== null && _j !== void 0 ? _j : 0,
|
|
282
|
+
event.end(Object.assign(Object.assign({ trees, blobs: (_g = (_f = snapshot.blobs) === null || _f === void 0 ? void 0 : _f.size) !== null && _g !== void 0 ? _g : 0, leafNodes: numBlobs, encodedBlobsSize,
|
|
283
|
+
sequenceNumber, ops: (_j = (_h = snapshot.ops) === null || _h === void 0 ? void 0 : _h.length) !== null && _j !== void 0 ? _j : 0, userOps: (_l = (_k = snapshot.ops) === null || _k === void 0 ? void 0 : _k.filter((op) => (0, driver_utils_1.isRuntimeMessage)(op)).length) !== null && _l !== void 0 ? _l : 0, headers: Object.keys(response.requestHeaders).length !== 0 ? true : undefined,
|
|
289
284
|
// Interval between the first fetch until the last byte of the last redirect.
|
|
290
285
|
redirectTime,
|
|
291
286
|
// Interval between start and finish of the domain name lookup for the resource.
|
|
@@ -321,7 +316,7 @@ async function fetchLatestSnapshotCore(odspResolvedUrl, storageTokenFetcher, sna
|
|
|
321
316
|
// Azure Fluid Relay service; desc=S, FRP; desc=False. Here, FRL is the duration taken for redeem,
|
|
322
317
|
// Azure Fluid Relay service is the redeem status (S means success), and FRP is a flag to indicate
|
|
323
318
|
// if the permission has changed.
|
|
324
|
-
sltelemetry: odspResponse.headers.get("x-fluid-sltelemetry") }, propsToLog));
|
|
319
|
+
sltelemetry: odspResponse.headers.get("x-fluid-sltelemetry") }, propsToLog), parsedSnapshotContents.content.telemetryProps));
|
|
325
320
|
return snapshot;
|
|
326
321
|
}).catch((error) => {
|
|
327
322
|
// We hit these errors in stress tests, under load
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetchSnapshot.js","sourceRoot":"","sources":["../src/fetchSnapshot.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { default as AbortController } from \"abort-controller\";\nimport { v4 as uuid } from \"uuid\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, fromUtf8ToBase64, performance } from \"@fluidframework/common-utils\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport { isFluidError, PerformanceEvent, wrapError } from \"@fluidframework/telemetry-utils\";\nimport {\n IOdspResolvedUrl,\n ISnapshotOptions,\n OdspErrorType,\n InstrumentedStorageTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { DriverErrorTelemetryProps, isRuntimeMessage, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport { IOdspSnapshot, ISnapshotCachedEntry, IVersionedValueWithEpoch, persistedCacheValueVersion } from \"./contracts\";\nimport { getQueryString } from \"./getQueryString\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport {\n fetchAndParseAsJSONHelper,\n fetchHelper,\n getWithRetryForTokenRefresh,\n getWithRetryForTokenRefreshRepeat,\n IOdspResponse,\n} from \"./odspUtils\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { convertOdspSnapshotToSnapshotTreeAndBlobs } from \"./odspSnapshotParser\";\nimport { currentReadVersion, ISnapshotContentsWithProps, parseCompactSnapshotResponse } from \"./compactSnapshotParser\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { pkgVersion } from \"./packageVersion\";\n\nasync function measure<T>(callback: () => T | Promise<T>): Promise<[T, number]> {\n const start = performance.now();\n const result = await callback();\n const time = performance.now() - start;\n return [result, time];\n}\n\n/**\n * Enum to support different types of snapshot formats.\n */\nexport enum SnapshotFormatSupportType {\n Json = 0,\n Binary = 1,\n JsonAndBinary = 2,\n}\n\n/**\n * Fetches a snapshot from the server with a given version id.\n * @param snapshotUrl - snapshot url from where the odsp snapshot will be fetched\n * @param token - token used for authorization in the request\n * @param storageFetchWrapper - Implementation of the get/post methods used to fetch the snapshot\n * @param versionId - id of specific snapshot to be fetched\n * @param fetchFullSnapshot - whether we want to fetch full snapshot(with blobs)\n * @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header\n * @returns A promise of the snapshot and the status code of the response\n */\nexport async function fetchSnapshot(\n snapshotUrl: string,\n token: string | null,\n versionId: string,\n fetchFullSnapshot: boolean,\n forceAccessTokenViaAuthorizationHeader: boolean,\n logger: ITelemetryLogger,\n snapshotDownloader: (url: string, fetchOptions: { [index: string]: any; }) => Promise<IOdspResponse<unknown>>,\n): Promise<ISnapshotContents> {\n const path = `/trees/${versionId}`;\n let queryParams: ISnapshotOptions = {};\n\n if (fetchFullSnapshot) {\n queryParams = versionId !== \"latest\" ? { blobs: 2 } : { deltas: 1, blobs: 2 };\n }\n\n const queryString = getQueryString(queryParams);\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${snapshotUrl}${path}${queryString}`, token, forceAccessTokenViaAuthorizationHeader);\n const response = await PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: \"fetchSnapshot\",\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n },\n async () => snapshotDownloader(url, { headers }),\n ) as IOdspResponse<IOdspSnapshot>;\n return convertOdspSnapshotToSnapshotTreeAndBlobs(response.content);\n}\n\nexport async function fetchSnapshotWithRedeem(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n snapshotOptions: ISnapshotOptions | undefined,\n forceAccessTokenViaAuthorizationHeader: boolean,\n logger: ITelemetryLogger,\n snapshotDownloader: (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => Promise<ISnapshotRequestAndResponseOptions>,\n putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n removeEntries: () => Promise<void>,\n enableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n // back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51\n const sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;\n if (sharingLinkToRedeem) {\n odspResolvedUrl.shareLinkInfo = { ...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem };\n }\n\n return fetchLatestSnapshotCore(\n odspResolvedUrl,\n storageTokenFetcher,\n snapshotOptions,\n logger,\n snapshotDownloader,\n putInCache,\n enableRedeemFallback,\n ).catch(async (error) => {\n if (enableRedeemFallback && isRedeemSharingLinkError(odspResolvedUrl, error)) {\n // Execute the redeem fallback\n\n await redeemSharingLink(\n odspResolvedUrl, storageTokenFetcher, logger, forceAccessTokenViaAuthorizationHeader);\n const odspResolvedUrlWithoutShareLink: IOdspResolvedUrl =\n {\n ...odspResolvedUrl,\n shareLinkInfo: {\n ...odspResolvedUrl.shareLinkInfo,\n sharingLinkToRedeem: undefined,\n },\n };\n\n // Log initial failure only if redeem succeeded - it points out to some bug somewhere\n // If redeem failed, that most likely means user has no permissions to access a file,\n // and thus it's not worth it logging extra errors - same error will be logged by end-to-end\n // flow (container open) based on a failure above.\n logger.sendErrorEvent({\n eventName: \"RedeemFallback\",\n errorType: error.errorType,\n }, error);\n\n return fetchLatestSnapshotCore(\n odspResolvedUrlWithoutShareLink,\n storageTokenFetcher,\n snapshotOptions,\n logger,\n snapshotDownloader,\n putInCache,\n );\n } else {\n throw error;\n }\n }).catch(async (error) => {\n // Clear the cache on 401/403/404 on snapshot fetch from network because this means either the user doesn't\n // have permissions for the file or it was deleted. So, if we do not clear cache, we will continue fetching\n // snapshot from cache in the future.\n if (typeof error === \"object\" && error !== null && error.errorType === DriverErrorType.authorizationError\n || error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError) {\n await removeEntries();\n }\n throw error;\n });\n}\n\nasync function redeemSharingLink(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n logger: ITelemetryLogger,\n forceAccessTokenViaAuthorizationHeader: boolean,\n) {\n return PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: \"RedeemShareLink\",\n },\n async () => getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n assert(!!odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem,\n 0x1ed /* \"Share link should be present\" */);\n const storageToken = await storageTokenFetcher(tokenFetchOptions, \"RedeemShareLink\");\n const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem);\n const redeemUrl = `${odspResolvedUrl.siteUrl}/_api/v2.0/shares/${encodedShareUrl}`;\n const { url, headers } = getUrlAndHeadersWithAuth(\n redeemUrl, storageToken, forceAccessTokenViaAuthorizationHeader);\n headers.prefer = \"redeemSharingLink\";\n return fetchAndParseAsJSONHelper(url, { headers });\n }),\n );\n}\n\nasync function fetchLatestSnapshotCore(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n snapshotOptions: ISnapshotOptions | undefined,\n logger: ITelemetryLogger,\n snapshotDownloader: (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => Promise<ISnapshotRequestAndResponseOptions>,\n putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n enableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n return getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n const storageToken = await storageTokenFetcher(tokenFetchOptions, \"TreesLatest\", true);\n assert(storageToken !== null, 0x1e5 /* \"Storage token should not be null\" */);\n\n const perfEvent = {\n eventName: \"TreesLatest\",\n attempts: tokenFetchOptions.refresh ? 2 : 1,\n shareLinkPresent: odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined,\n isSummarizer: odspResolvedUrl.summarizer,\n redeemFallbackEnabled: enableRedeemFallback,\n };\n if (snapshotOptions !== undefined) {\n Object.entries(snapshotOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n perfEvent[`snapshotOption_${key}`] = value;\n }\n });\n }\n // This event measures only successful cases of getLatest call (no tokens, no retries).\n return PerformanceEvent.timedExecAsync(\n logger,\n perfEvent,\n async (event) => {\n let controller: AbortController | undefined;\n let fetchTimeout: ReturnType<typeof setTimeout> | undefined;\n if (snapshotOptions?.timeout !== undefined) {\n controller = new AbortController();\n fetchTimeout = setTimeout(\n () => controller!.abort(),\n snapshotOptions.timeout,\n );\n }\n\n const [response, fetchTime] = await measure(async () => snapshotDownloader(\n odspResolvedUrl,\n storageToken,\n snapshotOptions,\n controller,\n )).finally(() => {\n // Clear the fetchTimeout once the response is fetched.\n if (fetchTimeout !== undefined) {\n clearTimeout(fetchTimeout);\n fetchTimeout = undefined;\n }\n });\n\n const odspResponse = response.odspResponse;\n const contentType = odspResponse.headers.get(\"content-type\");\n\n const propsToLog: DriverErrorTelemetryProps = {\n ...odspResponse.propsToLog,\n contentType,\n accept: response.requestHeaders.accept,\n driverVersion: pkgVersion,\n };\n\n let parsedSnapshotContents: IOdspResponse<ISnapshotContentsWithProps> | undefined;\n let contentTypeToRead: string | undefined;\n if (contentType?.includes(\"application/ms-fluid\")) {\n contentTypeToRead = \"application/ms-fluid\";\n } else if (contentType?.includes(\"application/json\")) {\n contentTypeToRead = \"application/json\";\n }\n\n let parseTime: number;\n let receiveContentTime: number;\n try {\n switch (contentTypeToRead) {\n case \"application/json\": {\n let text: string;\n [text, receiveContentTime] = await measure(async () => odspResponse.content.text());\n propsToLog.bodySize = text.length;\n let content: IOdspSnapshot;\n [content, parseTime] = await measure( () => JSON.parse(text) as IOdspSnapshot);\n validateBlobsAndTrees(content);\n const snapshotContents: ISnapshotContents =\n convertOdspSnapshotToSnapshotTreeAndBlobs(content);\n parsedSnapshotContents = { ...odspResponse, content: snapshotContents };\n break;\n }\n case \"application/ms-fluid\": {\n let content: ArrayBuffer;\n [content, receiveContentTime] =\n await measure(async () => odspResponse.content.arrayBuffer());\n propsToLog.bodySize = content.byteLength;\n let snapshotContents: ISnapshotContentsWithProps;\n [snapshotContents, parseTime] = await measure(() => parseCompactSnapshotResponse(\n new Uint8Array(content),\n logger));\n if (snapshotContents.snapshotTree.trees === undefined ||\n snapshotContents.snapshotTree.blobs === undefined) {\n throw new NonRetryableError(\n \"Returned odsp snapshot is malformed. No trees or blobs!\",\n DriverErrorType.incorrectServerResponse,\n propsToLog,\n );\n }\n const slowTreeParseCodePaths = snapshotContents.slowTreeStructureCount ?? 0;\n const slowBlobParseCodePaths = snapshotContents.slowBlobStructureCount ?? 0;\n if (slowTreeParseCodePaths > 10 || slowBlobParseCodePaths > 10) {\n logger.sendErrorEvent({\n eventName: \"SlowSnapshotParseCodePaths\",\n slowTreeStructureCount: slowTreeParseCodePaths,\n slowBlobStructureCount: slowBlobParseCodePaths,\n });\n }\n parsedSnapshotContents = { ...odspResponse, content: snapshotContents };\n break;\n }\n default:\n throw new NonRetryableError(\n \"Unknown snapshot content type\",\n DriverErrorType.incorrectServerResponse,\n propsToLog,\n );\n }\n } catch (error) {\n if (isFluidError(error)) {\n error.addTelemetryProperties(propsToLog);\n throw error;\n }\n const enhancedError = wrapError(\n error,\n (errorMessage) => new NonRetryableError(\n `Error parsing snapshot response: ${errorMessage}`,\n DriverErrorType.genericError,\n propsToLog));\n throw enhancedError;\n }\n\n assert(parsedSnapshotContents !== undefined, 0x312 /* snapshot should be parsed */);\n const snapshot = parsedSnapshotContents.content;\n const { trees, numBlobs, encodedBlobsSize } = evalBlobsAndTrees(snapshot);\n\n // From: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming\n // fetchStart: immediately before the browser starts to fetch the resource.\n // requestStart: immediately before the browser starts requesting the resource from the server\n // responseStart: immediately after the browser receives the first byte of the response from the server.\n // responseEnd: immediately after the browser receives the last byte of the resource\n // or immediately before the transport connection is closed, whichever comes first.\n // secureConnectionStart: immediately before the browser starts the handshake process to secure the\n // current connection. If a secure connection is not used, this property returns zero.\n // startTime: Time when the resource fetch started. This value is equivalent to fetchStart.\n // domainLookupStart: immediately before the browser starts the domain name lookup for the resource.\n // domainLookupEnd: immediately after the browser finishes the domain name lookup for the resource.\n // redirectStart: start time of the fetch which that initiates the redirect.\n // redirectEnd: immediately after receiving the last byte of the response of the last redirect.\n let dnsLookupTime: number | undefined; // domainLookupEnd - domainLookupStart\n let redirectTime: number | undefined; // redirectEnd - redirectStart\n let tcpHandshakeTime: number | undefined; // connectEnd - connectStart\n let secureConnectionTime: number | undefined; // connectEnd - secureConnectionStart\n let responseNetworkTime: number | undefined; // responsEnd - responseStart\n let fetchStartToResponseEndTime: number | undefined; // responseEnd - fetchStart\n let reqStartToResponseEndTime: number | undefined; // responseEnd - requestStart\n let networkTime: number | undefined; // responseEnd - startTime\n const spReqDuration = odspResponse.headers.get(\"sprequestduration\");\n\n // getEntriesByType is only available in browser performance object\n const resources1 = performance.getEntriesByType?.(\"resource\") ?? [];\n // Usually the latest fetch call is to the end of resources, so we start from the end.\n for (let i = resources1.length - 1; i > 0; i--) {\n const indResTime = resources1[i] as PerformanceResourceTiming;\n const resource_name = indResTime.name;\n const resource_initiatortype = indResTime.initiatorType;\n if ((resource_initiatortype.localeCompare(\"fetch\") === 0)\n && (resource_name.localeCompare(response.requestUrl) === 0)) {\n redirectTime = indResTime.redirectEnd - indResTime.redirectStart;\n dnsLookupTime = indResTime.domainLookupEnd - indResTime.domainLookupStart;\n tcpHandshakeTime = indResTime.connectEnd - indResTime.connectStart;\n secureConnectionTime = (indResTime.secureConnectionStart > 0) ?\n (indResTime.connectEnd - indResTime.secureConnectionStart) : undefined;\n responseNetworkTime = (indResTime.responseStart > 0) ?\n (indResTime.responseEnd - indResTime.responseStart) : undefined;\n fetchStartToResponseEndTime = (indResTime.fetchStart > 0) ?\n (indResTime.responseEnd - indResTime.fetchStart) : undefined;\n reqStartToResponseEndTime = (indResTime.requestStart > 0) ?\n (indResTime.responseEnd - indResTime.requestStart) : undefined;\n networkTime = fetchStartToResponseEndTime;\n if (spReqDuration !== undefined && networkTime !== undefined) {\n networkTime = networkTime - parseInt(spReqDuration, 10);\n }\n break;\n }\n }\n\n // There are some scenarios in ODSP where we cannot cache, trees/latest will explicitly tell us when we\n // cannot cache using an HTTP response header.\n const canCache =\n odspResponse.headers.get(\"disablebrowsercachingofusercontent\") !== \"true\";\n const sequenceNumber: number = snapshot.sequenceNumber ?? 0;\n const seqNumberFromOps = snapshot.ops && snapshot.ops.length > 0 ?\n snapshot.ops[0].sequenceNumber - 1 :\n undefined;\n\n if (!Number.isInteger(sequenceNumber)\n || seqNumberFromOps !== undefined && seqNumberFromOps !== sequenceNumber) {\n logger.sendErrorEvent({ eventName: \"fetchSnapshotError\", sequenceNumber, seqNumberFromOps });\n snapshot.sequenceNumber = undefined;\n } else if (canCache) {\n const fluidEpoch = odspResponse.headers.get(\"x-fluid-epoch\");\n assert(fluidEpoch !== undefined, 0x1e6 /* \"Epoch should be present in response\" */);\n const value: ISnapshotCachedEntry = {\n ...snapshot,\n cacheEntryTime: Date.now(),\n };\n const valueWithEpoch: IVersionedValueWithEpoch = {\n value,\n fluidEpoch,\n version: persistedCacheValueVersion,\n };\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n putInCache(valueWithEpoch);\n }\n\n event.end({\n trees,\n blobs: snapshot.blobs?.size ?? 0,\n leafNodes: numBlobs,\n encodedBlobsSize,\n sequenceNumber,\n ops: snapshot.ops?.length ?? 0,\n slowTreeStructureCount: snapshot.slowTreeStructureCount ?? 0,\n slowBlobStructureCount: snapshot.slowBlobStructureCount ?? 0,\n userOps: snapshot.ops?.filter((op) => isRuntimeMessage(op)).length ?? 0,\n headers: Object.keys(response.requestHeaders).length !== 0 ? true : undefined,\n // Interval between the first fetch until the last byte of the last redirect.\n redirectTime,\n // Interval between start and finish of the domain name lookup for the resource.\n dnsLookupTime,\n // Interval to receive all (first to last) bytes form the server.\n responseNetworkTime,\n // Time to establish the connection to the server to retrieve the resource.\n tcpHandshakeTime,\n // Time from the end of the connection until the inital handshake process to secure the connection.\n secureConnectionTime,\n // Interval between the initial fetch until the last byte is received.\n // Likely same as fetchTime + receiveContentTime.\n fetchStartToResponseEndTime,\n // reqStartToResponseEndTime = fetchStartToResponseEndTime - <initial TCP handshake>\n // Interval between starting the request for the resource until receiving the last byte.\n reqStartToResponseEndTime,\n // networkTime = fetchStartToResponseEndTime - sprequestduration\n // Interval between starting the request for the resource until receiving the last byte but\n // excluding the snaphot request duration indicated on the snapshot response header.\n networkTime,\n // Measures time to make fetch call. Should be similar to\n // fetchStartToResponseEndTime - receiveContentTime, i.e. it looks like it's time till first byte /\n // end of response headers\n fetchTime,\n // time it takes client to parse payload. Same payload as in \"SnapshotParse\" event, here for\n // easier analyzes.\n parseTime,\n // Time it takes to receive content (text of buffer) from Response object.\n // This time likely is very closely correlated with networkTime, i.e. time it takes to receive\n // actual content (starting measuring from first bite / end of response header)\n receiveContentTime,\n // Sharing link telemetry regarding sharing link redeem status and performance. Ex: FRL; dur=100,\n // Azure Fluid Relay service; desc=S, FRP; desc=False. Here, FRL is the duration taken for redeem,\n // Azure Fluid Relay service is the redeem status (S means success), and FRP is a flag to indicate\n // if the permission has changed.\n sltelemetry: odspResponse.headers.get(\"x-fluid-sltelemetry\"),\n // All other props\n ...propsToLog,\n });\n return snapshot;\n },\n ).catch((error) => {\n // We hit these errors in stress tests, under load\n // It's useful to try one more time in such case.\n if (typeof error === \"object\" && error !== null && (error.errorType === DriverErrorType.fetchFailure ||\n error.errorType === OdspErrorType.fetchTimeout)) {\n error[getWithRetryForTokenRefreshRepeat] = true;\n }\n throw error;\n });\n });\n}\n\nexport interface ISnapshotRequestAndResponseOptions {\n odspResponse: IOdspResponse<Response>;\n requestUrl: string;\n requestHeaders: { [index: string]: any; };\n}\n\nfunction getFormBodyAndHeaders(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n headers?: { [index: string]: string; },\n) {\n const formBoundary = uuid();\n const formParams: string[] = [];\n formParams.push(`--${formBoundary}`);\n formParams.push(`Authorization: Bearer ${storageToken}`);\n formParams.push(`X-HTTP-Method-Override: GET`);\n if (snapshotOptions !== undefined) {\n Object.entries(snapshotOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n formParams.push(`${key}: ${value}`);\n }\n });\n }\n if (headers !== undefined) {\n Object.entries(headers).forEach(([key, value]) => {\n if (value !== undefined) {\n formParams.push(`${key}: ${value}`);\n }\n });\n }\n if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem) {\n formParams.push(`sl: ${odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem}`);\n }\n formParams.push(`_post: 1`);\n formParams.push(`\\r\\n--${formBoundary}--`);\n const postBody = formParams.join(\"\\r\\n\");\n const header: { [index: string]: any; } = {\n \"Content-Type\": `multipart/form-data;boundary=${formBoundary}`,\n };\n return { body: postBody, headers: header };\n}\n\nfunction evalBlobsAndTrees(snapshot: ISnapshotContents) {\n const trees = countTreesInSnapshotTree(snapshot.snapshotTree);\n const numBlobs = snapshot.blobs.size;\n let encodedBlobsSize = 0;\n for (const [_, blobContent] of snapshot.blobs) {\n encodedBlobsSize += blobContent.byteLength;\n }\n return { trees, numBlobs, encodedBlobsSize };\n}\n\nexport function validateBlobsAndTrees(snapshot: IOdspSnapshot) {\n assert(snapshot.trees !== undefined,\n 0x200 /* \"Returned odsp snapshot is malformed. No trees!\" */);\n assert(snapshot.blobs !== undefined,\n 0x201 /* \"Returned odsp snapshot is malformed. No blobs!\" */);\n}\n\nfunction countTreesInSnapshotTree(snapshotTree: ISnapshotTree): number {\n let numTrees = 0;\n for (const [_, tree] of Object.entries(snapshotTree.trees)) {\n numTrees += 1;\n numTrees += countTreesInSnapshotTree(tree);\n }\n return numTrees;\n}\n\n/**\n * This function fetches the snapshot and parse it according to what is mentioned in response headers.\n * @param odspResolvedUrl - resolved odsp url.\n * @param storageToken - token to do the auth for network request.\n * @param snapshotOptions - Options used to specify how and what to fetch in the snapshot.\n * @param logger - logger\n * @param snapshotFormatFetchType - Snapshot format to fetch.\n * @param controller - abort controller if caller needs to abort the network call.\n * @param epochTracker - epoch tracker used to add/validate epoch in the network call.\n * @returns fetched snapshot.\n */\nexport async function downloadSnapshot(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n logger: ITelemetryLogger,\n snapshotOptions: ISnapshotOptions | undefined,\n snapshotFormatFetchType?: SnapshotFormatSupportType,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n scenarioName?: string,\n): Promise<ISnapshotRequestAndResponseOptions> {\n // back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51\n const sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;\n if (sharingLinkToRedeem) {\n odspResolvedUrl.shareLinkInfo = { ...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem };\n }\n\n const snapshotUrl = odspResolvedUrl.endpoints.snapshotStorageUrl;\n const url = `${snapshotUrl}/trees/latest?ump=1`;\n // The location of file can move on Spo in which case server returns 308(Permanent Redirect) error.\n // Adding below header will make VROOM API return 404 instead of 308 and browser can intercept it.\n // This error thrown by server will contain the new redirect location. Look at the 404 error parsing\n // for futher reference here: \\packages\\utils\\odsp-doclib-utils\\src\\odspErrorUtils.ts\n const header = { prefer: \"manualredirect\" };\n const { body, headers } = getFormBodyAndHeaders(\n odspResolvedUrl, storageToken, snapshotOptions, header);\n const fetchOptions = {\n body,\n headers,\n signal: controller?.signal,\n method: \"POST\",\n };\n // Decide what snapshot format to fetch as per the feature gate.\n switch (snapshotFormatFetchType) {\n case SnapshotFormatSupportType.Binary:\n headers.accept = `application/ms-fluid; v=${currentReadVersion}`;\n break;\n default:\n // By default ask both versions and let the server decide the format.\n headers.accept = `application/json, application/ms-fluid; v=${currentReadVersion}`;\n }\n\n const odspResponse = await (epochTracker?.fetch(url, fetchOptions, \"treesLatest\", true, scenarioName) ??\n fetchHelper(url, fetchOptions));\n\n return {\n odspResponse,\n requestHeaders: headers,\n requestUrl: url,\n };\n}\n\nfunction isRedeemSharingLinkError(odspResolvedUrl: IOdspResolvedUrl, error: any) {\n if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined\n && (typeof error === \"object\" && error !== null)\n && (error.errorType === DriverErrorType.authorizationError\n || error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError)) {\n return true;\n }\n return false;\n}\n\nfunction getEncodedShareUrl(url: string): string {\n /**\n * Encode the url to accepted format by Sharepoint\n * https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/shares_get\n */\n let encodedUrl = fromUtf8ToBase64(encodeURI(url));\n encodedUrl = encodedUrl\n .replace(/=+$/g, \"\")\n .replace(/\\//g, \"_\")\n .replace(/\\+/g, \"-\");\n encodedUrl = \"u!\".concat(encodedUrl);\n return encodedUrl;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"fetchSnapshot.js","sourceRoot":"","sources":["../src/fetchSnapshot.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { default as AbortController } from \"abort-controller\";\nimport { v4 as uuid } from \"uuid\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, fromUtf8ToBase64, performance } from \"@fluidframework/common-utils\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport { isFluidError, PerformanceEvent, wrapError } from \"@fluidframework/telemetry-utils\";\nimport {\n IOdspResolvedUrl,\n ISnapshotOptions,\n OdspErrorType,\n InstrumentedStorageTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { DriverErrorTelemetryProps, isRuntimeMessage, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport { IOdspSnapshot, ISnapshotCachedEntry, IVersionedValueWithEpoch, persistedCacheValueVersion } from \"./contracts\";\nimport { getQueryString } from \"./getQueryString\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport {\n fetchAndParseAsJSONHelper,\n fetchHelper,\n getWithRetryForTokenRefresh,\n getWithRetryForTokenRefreshRepeat,\n IOdspResponse,\n measure,\n measureP,\n} from \"./odspUtils\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { convertOdspSnapshotToSnapshotTreeAndBlobs } from \"./odspSnapshotParser\";\nimport { currentReadVersion, ISnapshotContentsWithProps, parseCompactSnapshotResponse } from \"./compactSnapshotParser\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { pkgVersion } from \"./packageVersion\";\n\n/**\n * Enum to support different types of snapshot formats.\n */\nexport enum SnapshotFormatSupportType {\n Json = 0,\n Binary = 1,\n JsonAndBinary = 2,\n}\n\n/**\n * Fetches a snapshot from the server with a given version id.\n * @param snapshotUrl - snapshot url from where the odsp snapshot will be fetched\n * @param token - token used for authorization in the request\n * @param storageFetchWrapper - Implementation of the get/post methods used to fetch the snapshot\n * @param versionId - id of specific snapshot to be fetched\n * @param fetchFullSnapshot - whether we want to fetch full snapshot(with blobs)\n * @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header\n * @returns A promise of the snapshot and the status code of the response\n */\nexport async function fetchSnapshot(\n snapshotUrl: string,\n token: string | null,\n versionId: string,\n fetchFullSnapshot: boolean,\n forceAccessTokenViaAuthorizationHeader: boolean,\n logger: ITelemetryLogger,\n snapshotDownloader: (url: string, fetchOptions: { [index: string]: any; }) => Promise<IOdspResponse<unknown>>,\n): Promise<ISnapshotContents> {\n const path = `/trees/${versionId}`;\n let queryParams: ISnapshotOptions = {};\n\n if (fetchFullSnapshot) {\n queryParams = versionId !== \"latest\" ? { blobs: 2 } : { deltas: 1, blobs: 2 };\n }\n\n const queryString = getQueryString(queryParams);\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${snapshotUrl}${path}${queryString}`, token, forceAccessTokenViaAuthorizationHeader);\n const response = await PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: \"fetchSnapshot\",\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n },\n async () => snapshotDownloader(url, { headers }),\n ) as IOdspResponse<IOdspSnapshot>;\n return convertOdspSnapshotToSnapshotTreeAndBlobs(response.content);\n}\n\nexport async function fetchSnapshotWithRedeem(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n snapshotOptions: ISnapshotOptions | undefined,\n forceAccessTokenViaAuthorizationHeader: boolean,\n logger: ITelemetryLogger,\n snapshotDownloader: (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => Promise<ISnapshotRequestAndResponseOptions>,\n putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n removeEntries: () => Promise<void>,\n enableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n // back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51\n const sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;\n if (sharingLinkToRedeem) {\n odspResolvedUrl.shareLinkInfo = { ...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem };\n }\n\n return fetchLatestSnapshotCore(\n odspResolvedUrl,\n storageTokenFetcher,\n snapshotOptions,\n logger,\n snapshotDownloader,\n putInCache,\n enableRedeemFallback,\n ).catch(async (error) => {\n if (enableRedeemFallback && isRedeemSharingLinkError(odspResolvedUrl, error)) {\n // Execute the redeem fallback\n\n await redeemSharingLink(\n odspResolvedUrl, storageTokenFetcher, logger, forceAccessTokenViaAuthorizationHeader);\n const odspResolvedUrlWithoutShareLink: IOdspResolvedUrl =\n {\n ...odspResolvedUrl,\n shareLinkInfo: {\n ...odspResolvedUrl.shareLinkInfo,\n sharingLinkToRedeem: undefined,\n },\n };\n\n // Log initial failure only if redeem succeeded - it points out to some bug somewhere\n // If redeem failed, that most likely means user has no permissions to access a file,\n // and thus it's not worth it logging extra errors - same error will be logged by end-to-end\n // flow (container open) based on a failure above.\n logger.sendErrorEvent({\n eventName: \"RedeemFallback\",\n errorType: error.errorType,\n }, error);\n\n return fetchLatestSnapshotCore(\n odspResolvedUrlWithoutShareLink,\n storageTokenFetcher,\n snapshotOptions,\n logger,\n snapshotDownloader,\n putInCache,\n );\n } else {\n throw error;\n }\n }).catch(async (error) => {\n // Clear the cache on 401/403/404 on snapshot fetch from network because this means either the user doesn't\n // have permissions for the file or it was deleted. So, if we do not clear cache, we will continue fetching\n // snapshot from cache in the future.\n if (typeof error === \"object\" && error !== null && error.errorType === DriverErrorType.authorizationError\n || error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError) {\n await removeEntries();\n }\n throw error;\n });\n}\n\nasync function redeemSharingLink(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n logger: ITelemetryLogger,\n forceAccessTokenViaAuthorizationHeader: boolean,\n) {\n return PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: \"RedeemShareLink\",\n },\n async () => getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n assert(!!odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem,\n 0x1ed /* \"Share link should be present\" */);\n const storageToken = await storageTokenFetcher(tokenFetchOptions, \"RedeemShareLink\");\n const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem);\n const redeemUrl = `${odspResolvedUrl.siteUrl}/_api/v2.0/shares/${encodedShareUrl}`;\n const { url, headers } = getUrlAndHeadersWithAuth(\n redeemUrl, storageToken, forceAccessTokenViaAuthorizationHeader);\n headers.prefer = \"redeemSharingLink\";\n return fetchAndParseAsJSONHelper(url, { headers });\n }),\n );\n}\n\nasync function fetchLatestSnapshotCore(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n snapshotOptions: ISnapshotOptions | undefined,\n logger: ITelemetryLogger,\n snapshotDownloader: (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => Promise<ISnapshotRequestAndResponseOptions>,\n putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n enableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n return getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n const storageToken = await storageTokenFetcher(tokenFetchOptions, \"TreesLatest\", true);\n assert(storageToken !== null, 0x1e5 /* \"Storage token should not be null\" */);\n\n const perfEvent = {\n eventName: \"TreesLatest\",\n attempts: tokenFetchOptions.refresh ? 2 : 1,\n shareLinkPresent: odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined,\n isSummarizer: odspResolvedUrl.summarizer,\n redeemFallbackEnabled: enableRedeemFallback,\n };\n if (snapshotOptions !== undefined) {\n Object.entries(snapshotOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n perfEvent[`snapshotOption_${key}`] = value;\n }\n });\n }\n // This event measures only successful cases of getLatest call (no tokens, no retries).\n return PerformanceEvent.timedExecAsync(\n logger,\n perfEvent,\n async (event) => {\n let controller: AbortController | undefined;\n let fetchTimeout: ReturnType<typeof setTimeout> | undefined;\n if (snapshotOptions?.timeout !== undefined) {\n controller = new AbortController();\n fetchTimeout = setTimeout(\n () => controller!.abort(),\n snapshotOptions.timeout,\n );\n }\n\n const [response, fetchTime] = await measureP(async () => snapshotDownloader(\n odspResolvedUrl,\n storageToken,\n snapshotOptions,\n controller,\n )).finally(() => {\n // Clear the fetchTimeout once the response is fetched.\n if (fetchTimeout !== undefined) {\n clearTimeout(fetchTimeout);\n fetchTimeout = undefined;\n }\n });\n\n const odspResponse = response.odspResponse;\n const contentType = odspResponse.headers.get(\"content-type\");\n\n const propsToLog: DriverErrorTelemetryProps = {\n ...odspResponse.propsToLog,\n contentType,\n accept: response.requestHeaders.accept,\n driverVersion: pkgVersion,\n };\n\n let parsedSnapshotContents: IOdspResponse<ISnapshotContentsWithProps> | undefined;\n let contentTypeToRead: string | undefined;\n if (contentType?.includes(\"application/ms-fluid\")) {\n contentTypeToRead = \"application/ms-fluid\";\n } else if (contentType?.includes(\"application/json\")) {\n contentTypeToRead = \"application/json\";\n }\n\n let parseTime: number;\n let receiveContentTime: number;\n try {\n switch (contentTypeToRead) {\n case \"application/json\": {\n let text: string;\n [text, receiveContentTime] = await measureP(async () => odspResponse.content.text());\n propsToLog.bodySize = text.length;\n let content: IOdspSnapshot;\n [content, parseTime] = measure( () => JSON.parse(text) as IOdspSnapshot);\n validateBlobsAndTrees(content);\n const snapshotContents: ISnapshotContents =\n convertOdspSnapshotToSnapshotTreeAndBlobs(content);\n parsedSnapshotContents = {\n ...odspResponse,\n content: {\n ...snapshotContents,\n telemetryProps: {},\n },\n };\n break;\n }\n case \"application/ms-fluid\": {\n let content: ArrayBuffer;\n [content, receiveContentTime] =\n await measureP(async () => odspResponse.content.arrayBuffer());\n propsToLog.bodySize = content.byteLength;\n let snapshotContents: ISnapshotContentsWithProps;\n [snapshotContents, parseTime] = measure(() => parseCompactSnapshotResponse(\n new Uint8Array(content),\n logger));\n if (snapshotContents.snapshotTree.trees === undefined ||\n snapshotContents.snapshotTree.blobs === undefined) {\n throw new NonRetryableError(\n \"Returned odsp snapshot is malformed. No trees or blobs!\",\n DriverErrorType.incorrectServerResponse,\n propsToLog,\n );\n }\n\n const props = snapshotContents.telemetryProps;\n const slowTreeParseCodePaths = props.slowTreeStructureCount ?? 0;\n const slowBlobParseCodePaths = props.slowBlobStructureCount ?? 0;\n if (slowTreeParseCodePaths > 10 || slowBlobParseCodePaths > 10) {\n logger.sendErrorEvent({\n eventName: \"SlowSnapshotParseCodePaths\",\n slowTreeStructureCount: slowTreeParseCodePaths,\n slowBlobStructureCount: slowBlobParseCodePaths,\n });\n }\n parsedSnapshotContents = { ...odspResponse, content: snapshotContents };\n break;\n }\n default:\n throw new NonRetryableError(\n \"Unknown snapshot content type\",\n DriverErrorType.incorrectServerResponse,\n propsToLog,\n );\n }\n } catch (error) {\n if (isFluidError(error)) {\n error.addTelemetryProperties(propsToLog);\n throw error;\n }\n const enhancedError = wrapError(\n error,\n (errorMessage) => new NonRetryableError(\n `Error parsing snapshot response: ${errorMessage}`,\n DriverErrorType.genericError,\n propsToLog));\n throw enhancedError;\n }\n\n assert(parsedSnapshotContents !== undefined, 0x312 /* snapshot should be parsed */);\n const snapshot = parsedSnapshotContents.content;\n const { trees, numBlobs, encodedBlobsSize } = evalBlobsAndTrees(snapshot);\n\n // From: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming\n // fetchStart: immediately before the browser starts to fetch the resource.\n // requestStart: immediately before the browser starts requesting the resource from the server\n // responseStart: immediately after the browser receives the first byte of the response from the server.\n // responseEnd: immediately after the browser receives the last byte of the resource\n // or immediately before the transport connection is closed, whichever comes first.\n // secureConnectionStart: immediately before the browser starts the handshake process to secure the\n // current connection. If a secure connection is not used, this property returns zero.\n // startTime: Time when the resource fetch started. This value is equivalent to fetchStart.\n // domainLookupStart: immediately before the browser starts the domain name lookup for the resource.\n // domainLookupEnd: immediately after the browser finishes the domain name lookup for the resource.\n // redirectStart: start time of the fetch which that initiates the redirect.\n // redirectEnd: immediately after receiving the last byte of the response of the last redirect.\n let dnsLookupTime: number | undefined; // domainLookupEnd - domainLookupStart\n let redirectTime: number | undefined; // redirectEnd - redirectStart\n let tcpHandshakeTime: number | undefined; // connectEnd - connectStart\n let secureConnectionTime: number | undefined; // connectEnd - secureConnectionStart\n let responseNetworkTime: number | undefined; // responsEnd - responseStart\n let fetchStartToResponseEndTime: number | undefined; // responseEnd - fetchStart\n let reqStartToResponseEndTime: number | undefined; // responseEnd - requestStart\n let networkTime: number | undefined; // responseEnd - startTime\n const spReqDuration = odspResponse.headers.get(\"sprequestduration\");\n\n // getEntriesByType is only available in browser performance object\n const resources1 = performance.getEntriesByType?.(\"resource\") ?? [];\n // Usually the latest fetch call is to the end of resources, so we start from the end.\n for (let i = resources1.length - 1; i > 0; i--) {\n const indResTime = resources1[i] as PerformanceResourceTiming;\n const resource_name = indResTime.name;\n const resource_initiatortype = indResTime.initiatorType;\n if ((resource_initiatortype.localeCompare(\"fetch\") === 0)\n && (resource_name.localeCompare(response.requestUrl) === 0)) {\n redirectTime = indResTime.redirectEnd - indResTime.redirectStart;\n dnsLookupTime = indResTime.domainLookupEnd - indResTime.domainLookupStart;\n tcpHandshakeTime = indResTime.connectEnd - indResTime.connectStart;\n secureConnectionTime = (indResTime.secureConnectionStart > 0) ?\n (indResTime.connectEnd - indResTime.secureConnectionStart) : undefined;\n responseNetworkTime = (indResTime.responseStart > 0) ?\n (indResTime.responseEnd - indResTime.responseStart) : undefined;\n fetchStartToResponseEndTime = (indResTime.fetchStart > 0) ?\n (indResTime.responseEnd - indResTime.fetchStart) : undefined;\n reqStartToResponseEndTime = (indResTime.requestStart > 0) ?\n (indResTime.responseEnd - indResTime.requestStart) : undefined;\n networkTime = fetchStartToResponseEndTime;\n if (spReqDuration !== undefined && networkTime !== undefined) {\n networkTime = networkTime - parseInt(spReqDuration, 10);\n }\n break;\n }\n }\n\n // There are some scenarios in ODSP where we cannot cache, trees/latest will explicitly tell us when we\n // cannot cache using an HTTP response header.\n const canCache =\n odspResponse.headers.get(\"disablebrowsercachingofusercontent\") !== \"true\";\n const sequenceNumber: number = snapshot.sequenceNumber ?? 0;\n const seqNumberFromOps = snapshot.ops && snapshot.ops.length > 0 ?\n snapshot.ops[0].sequenceNumber - 1 :\n undefined;\n\n if (!Number.isInteger(sequenceNumber)\n || seqNumberFromOps !== undefined && seqNumberFromOps !== sequenceNumber) {\n logger.sendErrorEvent({ eventName: \"fetchSnapshotError\", sequenceNumber, seqNumberFromOps });\n snapshot.sequenceNumber = undefined;\n } else if (canCache) {\n const fluidEpoch = odspResponse.headers.get(\"x-fluid-epoch\");\n assert(fluidEpoch !== undefined, 0x1e6 /* \"Epoch should be present in response\" */);\n const value: ISnapshotCachedEntry = {\n ...snapshot,\n cacheEntryTime: Date.now(),\n };\n const valueWithEpoch: IVersionedValueWithEpoch = {\n value,\n fluidEpoch,\n version: persistedCacheValueVersion,\n };\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n putInCache(valueWithEpoch);\n }\n\n event.end({\n trees,\n blobs: snapshot.blobs?.size ?? 0,\n leafNodes: numBlobs,\n encodedBlobsSize,\n sequenceNumber,\n ops: snapshot.ops?.length ?? 0,\n userOps: snapshot.ops?.filter((op) => isRuntimeMessage(op)).length ?? 0,\n headers: Object.keys(response.requestHeaders).length !== 0 ? true : undefined,\n // Interval between the first fetch until the last byte of the last redirect.\n redirectTime,\n // Interval between start and finish of the domain name lookup for the resource.\n dnsLookupTime,\n // Interval to receive all (first to last) bytes form the server.\n responseNetworkTime,\n // Time to establish the connection to the server to retrieve the resource.\n tcpHandshakeTime,\n // Time from the end of the connection until the inital handshake process to secure the connection.\n secureConnectionTime,\n // Interval between the initial fetch until the last byte is received.\n // Likely same as fetchTime + receiveContentTime.\n fetchStartToResponseEndTime,\n // reqStartToResponseEndTime = fetchStartToResponseEndTime - <initial TCP handshake>\n // Interval between starting the request for the resource until receiving the last byte.\n reqStartToResponseEndTime,\n // networkTime = fetchStartToResponseEndTime - sprequestduration\n // Interval between starting the request for the resource until receiving the last byte but\n // excluding the snaphot request duration indicated on the snapshot response header.\n networkTime,\n // Measures time to make fetch call. Should be similar to\n // fetchStartToResponseEndTime - receiveContentTime, i.e. it looks like it's time till first byte /\n // end of response headers\n fetchTime,\n // time it takes client to parse payload. Same payload as in \"SnapshotParse\" event, here for\n // easier analyzes.\n parseTime,\n // Time it takes to receive content (text of buffer) from Response object.\n // This time likely is very closely correlated with networkTime, i.e. time it takes to receive\n // actual content (starting measuring from first bite / end of response header)\n receiveContentTime,\n // Sharing link telemetry regarding sharing link redeem status and performance. Ex: FRL; dur=100,\n // Azure Fluid Relay service; desc=S, FRP; desc=False. Here, FRL is the duration taken for redeem,\n // Azure Fluid Relay service is the redeem status (S means success), and FRP is a flag to indicate\n // if the permission has changed.\n sltelemetry: odspResponse.headers.get(\"x-fluid-sltelemetry\"),\n // All other props\n ...propsToLog,\n // Various perf counters and measures collected by binary parsing code:\n // slowTreeStructureCount, slowBlobStructureCount, durationStructure, durationStrings,\n // durationSnapshotTree, durationBlobs, etc.\n ...parsedSnapshotContents.content.telemetryProps,\n });\n return snapshot;\n },\n ).catch((error) => {\n // We hit these errors in stress tests, under load\n // It's useful to try one more time in such case.\n if (typeof error === \"object\" && error !== null && (error.errorType === DriverErrorType.fetchFailure ||\n error.errorType === OdspErrorType.fetchTimeout)) {\n error[getWithRetryForTokenRefreshRepeat] = true;\n }\n throw error;\n });\n });\n}\n\nexport interface ISnapshotRequestAndResponseOptions {\n odspResponse: IOdspResponse<Response>;\n requestUrl: string;\n requestHeaders: { [index: string]: any; };\n}\n\nfunction getFormBodyAndHeaders(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n headers?: { [index: string]: string; },\n) {\n const formBoundary = uuid();\n const formParams: string[] = [];\n formParams.push(`--${formBoundary}`);\n formParams.push(`Authorization: Bearer ${storageToken}`);\n formParams.push(`X-HTTP-Method-Override: GET`);\n if (snapshotOptions !== undefined) {\n Object.entries(snapshotOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n formParams.push(`${key}: ${value}`);\n }\n });\n }\n if (headers !== undefined) {\n Object.entries(headers).forEach(([key, value]) => {\n if (value !== undefined) {\n formParams.push(`${key}: ${value}`);\n }\n });\n }\n if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem) {\n formParams.push(`sl: ${odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem}`);\n }\n formParams.push(`_post: 1`);\n formParams.push(`\\r\\n--${formBoundary}--`);\n const postBody = formParams.join(\"\\r\\n\");\n const header: { [index: string]: any; } = {\n \"Content-Type\": `multipart/form-data;boundary=${formBoundary}`,\n };\n return { body: postBody, headers: header };\n}\n\nfunction evalBlobsAndTrees(snapshot: ISnapshotContents) {\n const trees = countTreesInSnapshotTree(snapshot.snapshotTree);\n const numBlobs = snapshot.blobs.size;\n let encodedBlobsSize = 0;\n for (const [_, blobContent] of snapshot.blobs) {\n encodedBlobsSize += blobContent.byteLength;\n }\n return { trees, numBlobs, encodedBlobsSize };\n}\n\nexport function validateBlobsAndTrees(snapshot: IOdspSnapshot) {\n assert(snapshot.trees !== undefined,\n 0x200 /* \"Returned odsp snapshot is malformed. No trees!\" */);\n assert(snapshot.blobs !== undefined,\n 0x201 /* \"Returned odsp snapshot is malformed. No blobs!\" */);\n}\n\nfunction countTreesInSnapshotTree(snapshotTree: ISnapshotTree): number {\n let numTrees = 0;\n for (const [_, tree] of Object.entries(snapshotTree.trees)) {\n numTrees += 1;\n numTrees += countTreesInSnapshotTree(tree);\n }\n return numTrees;\n}\n\n/**\n * This function fetches the snapshot and parse it according to what is mentioned in response headers.\n * @param odspResolvedUrl - resolved odsp url.\n * @param storageToken - token to do the auth for network request.\n * @param snapshotOptions - Options used to specify how and what to fetch in the snapshot.\n * @param logger - logger\n * @param snapshotFormatFetchType - Snapshot format to fetch.\n * @param controller - abort controller if caller needs to abort the network call.\n * @param epochTracker - epoch tracker used to add/validate epoch in the network call.\n * @returns fetched snapshot.\n */\nexport async function downloadSnapshot(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n logger: ITelemetryLogger,\n snapshotOptions: ISnapshotOptions | undefined,\n snapshotFormatFetchType?: SnapshotFormatSupportType,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n scenarioName?: string,\n): Promise<ISnapshotRequestAndResponseOptions> {\n // back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51\n const sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;\n if (sharingLinkToRedeem) {\n odspResolvedUrl.shareLinkInfo = { ...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem };\n }\n\n const snapshotUrl = odspResolvedUrl.endpoints.snapshotStorageUrl;\n const url = `${snapshotUrl}/trees/latest?ump=1`;\n // The location of file can move on Spo in which case server returns 308(Permanent Redirect) error.\n // Adding below header will make VROOM API return 404 instead of 308 and browser can intercept it.\n // This error thrown by server will contain the new redirect location. Look at the 404 error parsing\n // for futher reference here: \\packages\\utils\\odsp-doclib-utils\\src\\odspErrorUtils.ts\n const header = { prefer: \"manualredirect\" };\n const { body, headers } = getFormBodyAndHeaders(\n odspResolvedUrl, storageToken, snapshotOptions, header);\n const fetchOptions = {\n body,\n headers,\n signal: controller?.signal,\n method: \"POST\",\n };\n // Decide what snapshot format to fetch as per the feature gate.\n switch (snapshotFormatFetchType) {\n case SnapshotFormatSupportType.Binary:\n headers.accept = `application/ms-fluid; v=${currentReadVersion}`;\n break;\n default:\n // By default ask both versions and let the server decide the format.\n headers.accept = `application/json, application/ms-fluid; v=${currentReadVersion}`;\n }\n\n const odspResponse = await (epochTracker?.fetch(url, fetchOptions, \"treesLatest\", true, scenarioName) ??\n fetchHelper(url, fetchOptions));\n\n return {\n odspResponse,\n requestHeaders: headers,\n requestUrl: url,\n };\n}\n\nfunction isRedeemSharingLinkError(odspResolvedUrl: IOdspResolvedUrl, error: any) {\n if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined\n && (typeof error === \"object\" && error !== null)\n && (error.errorType === DriverErrorType.authorizationError\n || error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError)) {\n return true;\n }\n return false;\n}\n\nfunction getEncodedShareUrl(url: string): string {\n /**\n * Encode the url to accepted format by Sharepoint\n * https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/shares_get\n */\n let encodedUrl = fromUtf8ToBase64(encodeURI(url));\n encodedUrl = encodedUrl\n .replace(/=+$/g, \"\")\n .replace(/\\//g, \"_\")\n .replace(/\\+/g, \"-\");\n encodedUrl = \"u!\".concat(encodedUrl);\n return encodedUrl;\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
6
|
+
import { IDocumentDeltaStorageService, IStream } from "@fluidframework/driver-definitions";
|
|
7
|
+
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
8
|
+
/**
|
|
9
|
+
* Implementation of IDocumentDeltaStorageService that will return snapshot ops when fetching messages
|
|
10
|
+
*/
|
|
11
|
+
export declare class LocalOdspDeltaStorageService implements IDocumentDeltaStorageService {
|
|
12
|
+
private readonly logger;
|
|
13
|
+
private snapshotOps;
|
|
14
|
+
constructor(logger: ITelemetryLogger, snapshotOps: ISequencedDocumentMessage[]);
|
|
15
|
+
fetchMessages(from: number, to: number | undefined, _abortSignal?: AbortSignal, _cachedOnly?: boolean, _fetchReason?: string): IStream<ISequencedDocumentMessage[]>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=localOdspDeltaStorageService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localOdspDeltaStorageService.d.ts","sourceRoot":"","sources":["../../src/localOdspDriver/localOdspDeltaStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,4BAA4B,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAE3F,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAGjF;;GAEG;AACH,qBAAa,4BAA6B,YAAW,4BAA4B;IAEzE,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,WAAW;gBADF,MAAM,EAAE,gBAAgB,EACjC,WAAW,EAAE,yBAAyB,EAAE;IAG7C,aAAa,CAChB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GAAG,SAAS,EACtB,YAAY,CAAC,EAAE,WAAW,EAC1B,WAAW,CAAC,EAAE,OAAO,EACrB,YAAY,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,yBAAyB,EAAE,CAAC;CAmB1C"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.LocalOdspDeltaStorageService = void 0;
|
|
8
|
+
const driver_utils_1 = require("@fluidframework/driver-utils");
|
|
9
|
+
const odspUtils_1 = require("../odspUtils");
|
|
10
|
+
/**
|
|
11
|
+
* Implementation of IDocumentDeltaStorageService that will return snapshot ops when fetching messages
|
|
12
|
+
*/
|
|
13
|
+
class LocalOdspDeltaStorageService {
|
|
14
|
+
constructor(logger, snapshotOps) {
|
|
15
|
+
this.logger = logger;
|
|
16
|
+
this.snapshotOps = snapshotOps;
|
|
17
|
+
}
|
|
18
|
+
fetchMessages(from, to, _abortSignal, _cachedOnly, _fetchReason) {
|
|
19
|
+
if (this.snapshotOps.length === 0) {
|
|
20
|
+
return driver_utils_1.emptyMessageStream;
|
|
21
|
+
}
|
|
22
|
+
const queue = new driver_utils_1.Queue();
|
|
23
|
+
const messages = this.snapshotOps.filter((op) => op.sequenceNumber >= from && (to === undefined || op.sequenceNumber < to));
|
|
24
|
+
(0, odspUtils_1.validateMessages)("cached", messages, from, this.logger);
|
|
25
|
+
if (messages.length === 0 || messages[0].sequenceNumber !== from) {
|
|
26
|
+
this.snapshotOps = [];
|
|
27
|
+
}
|
|
28
|
+
this.snapshotOps = this.snapshotOps.filter((op) => to !== undefined && op.sequenceNumber >= to);
|
|
29
|
+
queue.pushValue(messages);
|
|
30
|
+
queue.pushDone();
|
|
31
|
+
return queue;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.LocalOdspDeltaStorageService = LocalOdspDeltaStorageService;
|
|
35
|
+
//# sourceMappingURL=localOdspDeltaStorageService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localOdspDeltaStorageService.js","sourceRoot":"","sources":["../../src/localOdspDriver/localOdspDeltaStorageService.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH,+DAAyE;AAEzE,4CAAgD;AAEhD;;GAEG;AACH,MAAa,4BAA4B;IACrC,YACqB,MAAwB,EACjC,WAAwC;QAD/B,WAAM,GAAN,MAAM,CAAkB;QACjC,gBAAW,GAAX,WAAW,CAA6B;IAChD,CAAC;IAEE,aAAa,CAChB,IAAY,EACZ,EAAsB,EACtB,YAA0B,EAC1B,WAAqB,EACrB,YAAqB;QAErB,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE;YAC/B,OAAO,iCAAkB,CAAC;SAC7B;QAED,MAAM,KAAK,GAAG,IAAI,oBAAK,EAA+B,CAAC;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAC5C,EAAE,CAAC,cAAc,IAAI,IAAI,IAAI,CAAC,EAAE,KAAK,SAAS,IAAI,EAAE,CAAC,cAAc,GAAG,EAAE,CAAC,CAAC,CAAC;QAC/E,IAAA,4BAAgB,EAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAExD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,IAAI,EAAE;YAC9D,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;SACzB;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,SAAS,IAAI,EAAE,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;QAEhG,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC1B,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC;IACjB,CAAC;CACJ;AA/BD,oEA+BC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { IDocumentDeltaStorageService, IStream } from \"@fluidframework/driver-definitions\";\nimport { Queue, emptyMessageStream } from \"@fluidframework/driver-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { validateMessages } from \"../odspUtils\";\n\n/**\n * Implementation of IDocumentDeltaStorageService that will return snapshot ops when fetching messages\n */\nexport class LocalOdspDeltaStorageService implements IDocumentDeltaStorageService {\n constructor(\n private readonly logger: ITelemetryLogger,\n private snapshotOps: ISequencedDocumentMessage[],\n ) { }\n\n public fetchMessages(\n from: number,\n to: number | undefined,\n _abortSignal?: AbortSignal,\n _cachedOnly?: boolean,\n _fetchReason?: string,\n ): IStream<ISequencedDocumentMessage[]> {\n if (this.snapshotOps.length === 0) {\n return emptyMessageStream;\n }\n\n const queue = new Queue<ISequencedDocumentMessage[]>();\n const messages = this.snapshotOps.filter((op) =>\n op.sequenceNumber >= from && (to === undefined || op.sequenceNumber < to));\n validateMessages(\"cached\", messages, from, this.logger);\n\n if (messages.length === 0 || messages[0].sequenceNumber !== from) {\n this.snapshotOps = [];\n }\n this.snapshotOps = this.snapshotOps.filter((op) => to !== undefined && op.sequenceNumber >= to);\n\n queue.pushValue(messages);\n queue.pushDone();\n return queue;\n }\n}\n"]}
|
|
@@ -16,6 +16,7 @@ export declare class LocalOdspDocumentService implements IDocumentService {
|
|
|
16
16
|
policies: {
|
|
17
17
|
storageOnly: boolean;
|
|
18
18
|
};
|
|
19
|
+
private storageManager?;
|
|
19
20
|
constructor(odspResolvedUrl: IOdspResolvedUrl, logger: ITelemetryLogger, localSnapshot: Uint8Array | string);
|
|
20
21
|
get resolvedUrl(): IResolvedUrl;
|
|
21
22
|
connectToStorage(): Promise<IDocumentStorageService>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localOdspDocumentService.d.ts","sourceRoot":"","sources":["../../src/localOdspDriver/localOdspDocumentService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EACH,4BAA4B,EAC5B,gBAAgB,EAChB,uBAAuB,EACvB,YAAY,EACf,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"localOdspDocumentService.d.ts","sourceRoot":"","sources":["../../src/localOdspDriver/localOdspDocumentService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EACH,4BAA4B,EAC5B,gBAAgB,EAChB,uBAAuB,EACvB,YAAY,EACf,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAI/D;;GAEG;AACH,qBAAa,wBAAyB,YAAW,gBAAgB;IAKzD,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAN3B,QAAQ;;MAAyB;IACxC,OAAO,CAAC,cAAc,CAAC,CAAkC;gBAGpC,eAAe,EAAE,gBAAgB,EACjC,MAAM,EAAE,gBAAgB,EACxB,aAAa,EAAE,UAAU,GAAG,MAAM;IAGvD,IAAW,WAAW,IAAI,YAAY,CAErC;IAEY,gBAAgB,IAAI,OAAO,CAAC,uBAAuB,CAAC;IAQpD,qBAAqB,IAAI,OAAO,CAAC,4BAA4B,CAAC;IAOpE,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,KAAK;IAM7C,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,IAAI;CAGrC"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.LocalOdspDocumentService = void 0;
|
|
8
8
|
const driver_utils_1 = require("@fluidframework/driver-utils");
|
|
9
|
+
const localOdspDeltaStorageService_1 = require("./localOdspDeltaStorageService");
|
|
9
10
|
const localOdspDocumentStorageManager_1 = require("./localOdspDocumentStorageManager");
|
|
10
11
|
/**
|
|
11
12
|
* IDocumentService implementation that provides explicit snapshot to the document storage service.
|
|
@@ -21,10 +22,12 @@ class LocalOdspDocumentService {
|
|
|
21
22
|
return this.odspResolvedUrl;
|
|
22
23
|
}
|
|
23
24
|
async connectToStorage() {
|
|
24
|
-
|
|
25
|
+
this.storageManager = new localOdspDocumentStorageManager_1.LocalOdspDocumentStorageService(this.logger, this.localSnapshot);
|
|
26
|
+
return this.storageManager;
|
|
25
27
|
}
|
|
26
28
|
async connectToDeltaStorage() {
|
|
27
|
-
|
|
29
|
+
var _a, _b;
|
|
30
|
+
return new localOdspDeltaStorageService_1.LocalOdspDeltaStorageService(this.logger, (_b = (_a = this.storageManager) === null || _a === void 0 ? void 0 : _a.ops) !== null && _b !== void 0 ? _b : []);
|
|
28
31
|
}
|
|
29
32
|
connectToDeltaStream(_client) {
|
|
30
33
|
const toThrow = new driver_utils_1.UsageError("\"connectToDeltaStream\" is not supported by LocalOdspDocumentService");
|