@fluidframework/odsp-driver 2.0.0-internal.6.3.2 → 2.0.0-internal.6.4.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.
Files changed (115) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/compactSnapshotParser.d.ts +1 -1
  3. package/dist/compactSnapshotParser.js +1 -1
  4. package/dist/compactSnapshotParser.js.map +1 -1
  5. package/dist/compactSnapshotWriter.d.ts +1 -1
  6. package/dist/compactSnapshotWriter.js +1 -1
  7. package/dist/compactSnapshotWriter.js.map +1 -1
  8. package/dist/createNewContainerOnExistingFile.d.ts +8 -4
  9. package/dist/createNewContainerOnExistingFile.d.ts.map +1 -1
  10. package/dist/createNewContainerOnExistingFile.js +8 -4
  11. package/dist/createNewContainerOnExistingFile.js.map +1 -1
  12. package/dist/odspDocumentDeltaConnection.d.ts.map +1 -1
  13. package/dist/odspDocumentDeltaConnection.js +15 -13
  14. package/dist/odspDocumentDeltaConnection.js.map +1 -1
  15. package/dist/odspDocumentService.d.ts +1 -1
  16. package/dist/odspDocumentService.js +1 -1
  17. package/dist/odspDocumentService.js.map +1 -1
  18. package/dist/odspDocumentServiceFactoryCore.d.ts +1 -1
  19. package/dist/odspDocumentServiceFactoryCore.js +1 -1
  20. package/dist/odspDocumentServiceFactoryCore.js.map +1 -1
  21. package/dist/odspDocumentStorageManager.d.ts.map +1 -1
  22. package/dist/odspDocumentStorageManager.js +23 -6
  23. package/dist/odspDocumentStorageManager.js.map +1 -1
  24. package/dist/odspDocumentStorageServiceBase.d.ts +1 -1
  25. package/dist/odspDocumentStorageServiceBase.d.ts.map +1 -1
  26. package/dist/odspDocumentStorageServiceBase.js +1 -3
  27. package/dist/odspDocumentStorageServiceBase.js.map +1 -1
  28. package/dist/odspDriverUrlResolver.d.ts.map +1 -1
  29. package/dist/odspDriverUrlResolver.js +2 -0
  30. package/dist/odspDriverUrlResolver.js.map +1 -1
  31. package/dist/odspFluidFileLink.d.ts +2 -1
  32. package/dist/odspFluidFileLink.d.ts.map +1 -1
  33. package/dist/odspFluidFileLink.js +6 -4
  34. package/dist/odspFluidFileLink.js.map +1 -1
  35. package/dist/odspLocationRedirection.d.ts +1 -1
  36. package/dist/odspLocationRedirection.js +1 -1
  37. package/dist/odspLocationRedirection.js.map +1 -1
  38. package/dist/odspUtils.d.ts.map +1 -1
  39. package/dist/odspUtils.js +1 -0
  40. package/dist/odspUtils.js.map +1 -1
  41. package/dist/packageVersion.d.ts +1 -1
  42. package/dist/packageVersion.js +1 -1
  43. package/dist/packageVersion.js.map +1 -1
  44. package/dist/prefetchLatestSnapshot.d.ts +1 -1
  45. package/dist/prefetchLatestSnapshot.js +1 -1
  46. package/dist/prefetchLatestSnapshot.js.map +1 -1
  47. package/dist/socketModule.d.ts +7 -0
  48. package/dist/socketModule.d.ts.map +1 -0
  49. package/dist/socketModule.js +10 -0
  50. package/dist/socketModule.js.map +1 -0
  51. package/lib/compactSnapshotParser.d.ts +1 -1
  52. package/lib/compactSnapshotParser.js +1 -1
  53. package/lib/compactSnapshotParser.js.map +1 -1
  54. package/lib/compactSnapshotWriter.d.ts +1 -1
  55. package/lib/compactSnapshotWriter.js +1 -1
  56. package/lib/compactSnapshotWriter.js.map +1 -1
  57. package/lib/createNewContainerOnExistingFile.d.ts +8 -4
  58. package/lib/createNewContainerOnExistingFile.d.ts.map +1 -1
  59. package/lib/createNewContainerOnExistingFile.js +8 -4
  60. package/lib/createNewContainerOnExistingFile.js.map +1 -1
  61. package/lib/odspDocumentDeltaConnection.d.ts.map +1 -1
  62. package/lib/odspDocumentDeltaConnection.js +14 -12
  63. package/lib/odspDocumentDeltaConnection.js.map +1 -1
  64. package/lib/odspDocumentService.d.ts +1 -1
  65. package/lib/odspDocumentService.js +1 -1
  66. package/lib/odspDocumentService.js.map +1 -1
  67. package/lib/odspDocumentServiceFactoryCore.d.ts +1 -1
  68. package/lib/odspDocumentServiceFactoryCore.js +1 -1
  69. package/lib/odspDocumentServiceFactoryCore.js.map +1 -1
  70. package/lib/odspDocumentStorageManager.d.ts.map +1 -1
  71. package/lib/odspDocumentStorageManager.js +24 -7
  72. package/lib/odspDocumentStorageManager.js.map +1 -1
  73. package/lib/odspDocumentStorageServiceBase.d.ts +1 -1
  74. package/lib/odspDocumentStorageServiceBase.d.ts.map +1 -1
  75. package/lib/odspDocumentStorageServiceBase.js +1 -3
  76. package/lib/odspDocumentStorageServiceBase.js.map +1 -1
  77. package/lib/odspDriverUrlResolver.d.ts.map +1 -1
  78. package/lib/odspDriverUrlResolver.js +2 -0
  79. package/lib/odspDriverUrlResolver.js.map +1 -1
  80. package/lib/odspFluidFileLink.d.ts +2 -1
  81. package/lib/odspFluidFileLink.d.ts.map +1 -1
  82. package/lib/odspFluidFileLink.js +6 -4
  83. package/lib/odspFluidFileLink.js.map +1 -1
  84. package/lib/odspLocationRedirection.d.ts +1 -1
  85. package/lib/odspLocationRedirection.js +1 -1
  86. package/lib/odspLocationRedirection.js.map +1 -1
  87. package/lib/odspUtils.d.ts.map +1 -1
  88. package/lib/odspUtils.js +1 -0
  89. package/lib/odspUtils.js.map +1 -1
  90. package/lib/packageVersion.d.ts +1 -1
  91. package/lib/packageVersion.js +1 -1
  92. package/lib/packageVersion.js.map +1 -1
  93. package/lib/prefetchLatestSnapshot.d.ts +1 -1
  94. package/lib/prefetchLatestSnapshot.js +1 -1
  95. package/lib/prefetchLatestSnapshot.js.map +1 -1
  96. package/lib/socketModule.d.ts +7 -0
  97. package/lib/socketModule.d.ts.map +1 -0
  98. package/lib/socketModule.js +7 -0
  99. package/lib/socketModule.js.map +1 -0
  100. package/package.json +12 -13
  101. package/src/compactSnapshotParser.ts +1 -1
  102. package/src/compactSnapshotWriter.ts +1 -1
  103. package/src/createNewContainerOnExistingFile.ts +8 -4
  104. package/src/odspDocumentDeltaConnection.ts +31 -24
  105. package/src/odspDocumentService.ts +1 -1
  106. package/src/odspDocumentServiceFactoryCore.ts +1 -1
  107. package/src/odspDocumentStorageManager.ts +28 -7
  108. package/src/odspDocumentStorageServiceBase.ts +1 -3
  109. package/src/odspDriverUrlResolver.ts +2 -0
  110. package/src/odspFluidFileLink.ts +13 -3
  111. package/src/odspLocationRedirection.ts +1 -1
  112. package/src/odspUtils.ts +1 -0
  113. package/src/packageVersion.ts +1 -1
  114. package/src/prefetchLatestSnapshot.ts +1 -1
  115. package/src/socketModule.ts +8 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @fluidframework/odsp-driver
2
2
 
3
+ ## 2.0.0-internal.6.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Upcoming: The type of the logger property/param in various APIs will be changing ([#17350](https://github.com/microsoft/FluidFramework/issues/17350)) [27284bcda3](https://github.com/microsoft/FluidFramework/commits/27284bcda3d63cc4306cf76806f8a075db0db60f)
8
+
9
+ - @fluidframework/runtime-definitions
10
+ - `IFluidDataStoreRuntime.logger` will be re-typed as `ITelemetryBaseLogger`
11
+ - @fluidframework/odsp-driver
12
+ - `protected OdspDocumentServiceFactoryCore.createDocumentServiceCore`'s parameter `odspLogger` will be re-typed as `ITelemetryLoggerExt`
13
+ - `protected LocalOdspDocumentServiceFactory.createDocumentServiceCore`'s parameter `odspLogger` will be re-typed as `ITelemetryLoggerExt`
14
+
15
+ Additionally, several of @fluidframework/telemetry-utils's exports are being marked as internal and should not be consumed outside of other FF packages.
16
+
3
17
  ## 2.0.0-internal.6.3.0
4
18
 
5
19
  Dependency updates only.
@@ -16,7 +16,7 @@ export interface ISnapshotContentsWithProps extends ISnapshotContents {
16
16
  /**
17
17
  * Converts snapshot from binary compact representation to tree/blobs/ops.
18
18
  * @param buffer - Compact snapshot to be parsed into tree/blobs/ops.
19
- * @returns - tree, blobs and ops from the snapshot.
19
+ * @returns Tree, blobs and ops from the snapshot.
20
20
  */
21
21
  export declare function parseCompactSnapshotResponse(buffer: Uint8Array, logger: ITelemetryLoggerExt): ISnapshotContentsWithProps;
22
22
  //# sourceMappingURL=compactSnapshotParser.d.ts.map
@@ -171,7 +171,7 @@ function readSnapshotSection(node) {
171
171
  /**
172
172
  * Converts snapshot from binary compact representation to tree/blobs/ops.
173
173
  * @param buffer - Compact snapshot to be parsed into tree/blobs/ops.
174
- * @returns - tree, blobs and ops from the snapshot.
174
+ * @returns Tree, blobs and ops from the snapshot.
175
175
  */
176
176
  function parseCompactSnapshotResponse(buffer, logger) {
177
177
  const { builder, telemetryProps } = zipItDataRepresentationUtils_1.TreeBuilder.load(new ReadBufferUtils_1.ReadBuffer(buffer), logger);
@@ -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/core-utils\";\nimport { ISequencedDocumentMessage, ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { ReadBuffer } from \"./ReadBufferUtils\";\nimport {\n\tassertBlobCoreInstance,\n\tgetStringInstance,\n\tassertBoolInstance,\n\tassertNodeCoreInstance,\n\tassertNumberInstance,\n\tgetNodeProps,\n\tNodeCore,\n\tNodeTypes,\n\tTreeBuilder,\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\ttelemetryProps: 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\tassertNodeCoreInstance(node, \"TreeBlobs should be of type NodeCore\");\n\tlet slowBlobStructureCount = 0;\n\tconst blobs: Map<string, ArrayBuffer> = new Map();\n\tfor (const blob of node) {\n\t\tassertNodeCoreInstance(blob, \"blob should be node\");\n\n\t\t/**\n\t\t * Perf optimization - the most common cases!\n\t\t * This is essentially unrolling code below for faster processing\n\t\t * It speeds up tree parsing by 2-3x times!\n\t\t */\n\t\tif (\n\t\t\tblob.length === 4 &&\n\t\t\tblob.getMaybeString(0) === \"id\" &&\n\t\t\tblob.getMaybeString(2) === \"data\"\n\t\t) {\n\t\t\t// \"id\": <node name>\n\t\t\t// \"data\": <blob>\n\t\t\tblobs.set(blob.getString(1), blob.getBlob(3).arrayBuffer);\n\t\t\tcontinue;\n\t\t}\n\n\t\t/**\n\t\t * More generalized workflow\n\t\t */\n\t\tslowBlobStructureCount += 1;\n\t\tconst records = getNodeProps(blob);\n\t\tassertBlobCoreInstance(records.data, \"data should be of BlobCore type\");\n\t\tconst id = getStringInstance(records.id, \"blob id should be string\");\n\t\tblobs.set(id, records.data.arrayBuffer);\n\t}\n\treturn { 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\tassertNodeCoreInstance(node, \"Deltas should be of type NodeCore\");\n\tconst ops: ISequencedDocumentMessage[] = [];\n\tconst records = getNodeProps(node);\n\tassertNumberInstance(records.firstSequenceNumber, \"Seq number should be a number\");\n\tassertNodeCoreInstance(records.deltas, \"Deltas should be a Node\");\n\tfor (let i = 0; i < records.deltas.length; ++i) {\n\t\tops.push(JSON.parse(records.deltas.getString(i)));\n\t}\n\t// Due to a bug at service side, in an edge case service was serializing deltas even\n\t// when there are no ops. So just make the code resilient to that bug. Service has also\n\t// fixed that bug.\n\tassert(\n\t\tops.length === 0 || records.firstSequenceNumber.valueOf() === ops[0].sequenceNumber,\n\t\t0x280 /* \"Validate first op seq number\" */,\n\t);\n\treturn 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\tlet slowTreeStructureCount = 0;\n\tconst trees = {};\n\tconst snapshotTree: ISnapshotTree = {\n\t\tblobs: {},\n\t\ttrees,\n\t};\n\tfor (const treeNode of node) {\n\t\tassertNodeCoreInstance(treeNode, \"tree nodes should be nodes\");\n\n\t\t/**\n\t\t * Perf optimization - the most common cases!\n\t\t * This is essentially unrolling code below for faster processing\n\t\t * It speeds up tree parsing by 2-3x times!\n\t\t */\n\t\tconst length = treeNode.length;\n\t\tif (length > 0 && treeNode.getMaybeString(0) === \"name\") {\n\t\t\tif (length === 4) {\n\t\t\t\tconst content = treeNode.getMaybeString(2);\n\t\t\t\t// \"name\": <node name>\n\t\t\t\t// \"children\": <blob id>\n\t\t\t\tif (content === \"children\") {\n\t\t\t\t\tconst result = readTreeSection(treeNode.getNode(3));\n\t\t\t\t\ttrees[treeNode.getString(1)] = result.snapshotTree;\n\t\t\t\t\tslowTreeStructureCount += result.slowTreeStructureCount;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// \"name\": <node name>\n\t\t\t\t// \"value\": <blob id>\n\t\t\t\tif (content === \"value\") {\n\t\t\t\t\tsnapshotTree.blobs[treeNode.getString(1)] = treeNode.getString(3);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// \"name\": <node name>\n\t\t\t// \"nodeType\": 3\n\t\t\t// \"value\": <blob id>\n\t\t\tif (\n\t\t\t\tlength === 6 &&\n\t\t\t\ttreeNode.getMaybeString(2) === \"nodeType\" &&\n\t\t\t\ttreeNode.getMaybeString(4) === \"value\"\n\t\t\t) {\n\t\t\t\tsnapshotTree.blobs[treeNode.getString(1)] = treeNode.getString(5);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// \"name\": <node name>\n\t\t\t// \"unreferenced\": true\n\t\t\t// \"children\": <blob id>\n\t\t\tif (\n\t\t\t\tlength === 6 &&\n\t\t\t\ttreeNode.getMaybeString(2) === \"unreferenced\" &&\n\t\t\t\ttreeNode.getMaybeString(4) === \"children\"\n\t\t\t) {\n\t\t\t\tconst result = readTreeSection(treeNode.getNode(5));\n\t\t\t\ttrees[treeNode.getString(1)] = result.snapshotTree;\n\t\t\t\tslowTreeStructureCount += result.slowTreeStructureCount;\n\t\t\t\tassert(treeNode.getBool(3), 0x3db /* Unreferenced if present should be true */);\n\t\t\t\tsnapshotTree.unreferenced = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * More generalized workflow\n\t\t */\n\t\tslowTreeStructureCount += 1;\n\t\tconst records = getNodeProps(treeNode);\n\n\t\tif (records.unreferenced !== undefined) {\n\t\t\tassertBoolInstance(records.unreferenced, \"Unreferenced flag should be bool\");\n\t\t\tassert(records.unreferenced, 0x281 /* \"Unreferenced if present should be true\" */);\n\t\t\tsnapshotTree.unreferenced = true;\n\t\t}\n\n\t\tconst path = getStringInstance(records.name, \"Path name should be string\");\n\t\tif (records.value !== undefined) {\n\t\t\tsnapshotTree.blobs[path] = getStringInstance(\n\t\t\t\trecords.value,\n\t\t\t\t\"Blob value should be string\",\n\t\t\t);\n\t\t} else if (records.children !== undefined) {\n\t\t\tassertNodeCoreInstance(records.children, \"Trees should be of type NodeCore\");\n\t\t\tconst result = readTreeSection(records.children);\n\t\t\ttrees[path] = result.snapshotTree;\n\t\t\tslowTreeStructureCount += result.slowTreeStructureCount;\n\t\t} else {\n\t\t\ttrees[path] = { blobs: {}, trees: {} };\n\t\t}\n\t}\n\treturn { 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\tassertNodeCoreInstance(node, \"Snapshot should be of type NodeCore\");\n\tconst records = getNodeProps(node);\n\n\tassertNodeCoreInstance(records.treeNodes, \"TreeNodes should be of type NodeCore\");\n\tassertNumberInstance(records.sequenceNumber, \"sequenceNumber should be of type number\");\n\tconst { snapshotTree, slowTreeStructureCount } = readTreeSection(records.treeNodes);\n\tsnapshotTree.id = getStringInstance(records.id, \"snapshotId should be string\");\n\tconst sequenceNumber = records.sequenceNumber.valueOf();\n\treturn {\n\t\tsequenceNumber,\n\t\tsnapshotTree,\n\t\tslowTreeStructureCount,\n\t};\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\tbuffer: Uint8Array,\n\tlogger: ITelemetryLoggerExt,\n): ISnapshotContentsWithProps {\n\tconst { builder, telemetryProps } = TreeBuilder.load(new ReadBuffer(buffer), logger);\n\tassert(builder.length === 1, 0x219 /* \"1 root should be there\" */);\n\tconst root = builder.getNode(0);\n\n\tconst records = getNodeProps(root);\n\n\tconst mrv = getStringInstance(records.mrv, \"minReadVersion should be string\");\n\tconst cv = getStringInstance(records.cv, \"createVersion should be string\");\n\tif (records.lsn !== undefined) {\n\t\tassertNumberInstance(records.lsn, \"lsn should be a number\");\n\t}\n\n\tassert(\n\t\tparseFloat(snapshotMinReadVersion) >= parseFloat(mrv),\n\t\t0x20f /* \"Driver min read version should >= to server minReadVersion\" */,\n\t);\n\tassert(\n\t\tparseFloat(cv) >= parseFloat(snapshotMinReadVersion),\n\t\t0x210 /* \"Snapshot should be created with minReadVersion or above\" */,\n\t);\n\tassert(\n\t\tcurrentReadVersion === cv,\n\t\t0x2c2 /* \"Create Version should be equal to currentReadVersion\" */,\n\t);\n\n\tconst [snapshot, durationSnapshotTree] = measure(() => readSnapshotSection(records.snapshot));\n\tconst [blobs, durationBlobs] = measure(() => readBlobSection(records.blobs));\n\n\treturn {\n\t\t...snapshot,\n\t\t...blobs,\n\t\tops: records.deltas !== undefined ? readOpsSection(records.deltas) : [],\n\t\tlatestSequenceNumber: records.lsn,\n\t\ttelemetryProps: {\n\t\t\t...telemetryProps,\n\t\t\tdurationSnapshotTree,\n\t\t\tdurationBlobs,\n\t\t\tslowTreeStructureCount: snapshot.slowTreeStructureCount,\n\t\t\tslowBlobStructureCount: blobs.slowBlobStructureCount,\n\t\t},\n\t};\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/core-utils\";\nimport { ISequencedDocumentMessage, ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { ReadBuffer } from \"./ReadBufferUtils\";\nimport {\n\tassertBlobCoreInstance,\n\tgetStringInstance,\n\tassertBoolInstance,\n\tassertNodeCoreInstance,\n\tassertNumberInstance,\n\tgetNodeProps,\n\tNodeCore,\n\tNodeTypes,\n\tTreeBuilder,\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\ttelemetryProps: 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\tassertNodeCoreInstance(node, \"TreeBlobs should be of type NodeCore\");\n\tlet slowBlobStructureCount = 0;\n\tconst blobs: Map<string, ArrayBuffer> = new Map();\n\tfor (const blob of node) {\n\t\tassertNodeCoreInstance(blob, \"blob should be node\");\n\n\t\t/**\n\t\t * Perf optimization - the most common cases!\n\t\t * This is essentially unrolling code below for faster processing\n\t\t * It speeds up tree parsing by 2-3x times!\n\t\t */\n\t\tif (\n\t\t\tblob.length === 4 &&\n\t\t\tblob.getMaybeString(0) === \"id\" &&\n\t\t\tblob.getMaybeString(2) === \"data\"\n\t\t) {\n\t\t\t// \"id\": <node name>\n\t\t\t// \"data\": <blob>\n\t\t\tblobs.set(blob.getString(1), blob.getBlob(3).arrayBuffer);\n\t\t\tcontinue;\n\t\t}\n\n\t\t/**\n\t\t * More generalized workflow\n\t\t */\n\t\tslowBlobStructureCount += 1;\n\t\tconst records = getNodeProps(blob);\n\t\tassertBlobCoreInstance(records.data, \"data should be of BlobCore type\");\n\t\tconst id = getStringInstance(records.id, \"blob id should be string\");\n\t\tblobs.set(id, records.data.arrayBuffer);\n\t}\n\treturn { 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\tassertNodeCoreInstance(node, \"Deltas should be of type NodeCore\");\n\tconst ops: ISequencedDocumentMessage[] = [];\n\tconst records = getNodeProps(node);\n\tassertNumberInstance(records.firstSequenceNumber, \"Seq number should be a number\");\n\tassertNodeCoreInstance(records.deltas, \"Deltas should be a Node\");\n\tfor (let i = 0; i < records.deltas.length; ++i) {\n\t\tops.push(JSON.parse(records.deltas.getString(i)));\n\t}\n\t// Due to a bug at service side, in an edge case service was serializing deltas even\n\t// when there are no ops. So just make the code resilient to that bug. Service has also\n\t// fixed that bug.\n\tassert(\n\t\tops.length === 0 || records.firstSequenceNumber.valueOf() === ops[0].sequenceNumber,\n\t\t0x280 /* \"Validate first op seq number\" */,\n\t);\n\treturn 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\tlet slowTreeStructureCount = 0;\n\tconst trees = {};\n\tconst snapshotTree: ISnapshotTree = {\n\t\tblobs: {},\n\t\ttrees,\n\t};\n\tfor (const treeNode of node) {\n\t\tassertNodeCoreInstance(treeNode, \"tree nodes should be nodes\");\n\n\t\t/**\n\t\t * Perf optimization - the most common cases!\n\t\t * This is essentially unrolling code below for faster processing\n\t\t * It speeds up tree parsing by 2-3x times!\n\t\t */\n\t\tconst length = treeNode.length;\n\t\tif (length > 0 && treeNode.getMaybeString(0) === \"name\") {\n\t\t\tif (length === 4) {\n\t\t\t\tconst content = treeNode.getMaybeString(2);\n\t\t\t\t// \"name\": <node name>\n\t\t\t\t// \"children\": <blob id>\n\t\t\t\tif (content === \"children\") {\n\t\t\t\t\tconst result = readTreeSection(treeNode.getNode(3));\n\t\t\t\t\ttrees[treeNode.getString(1)] = result.snapshotTree;\n\t\t\t\t\tslowTreeStructureCount += result.slowTreeStructureCount;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// \"name\": <node name>\n\t\t\t\t// \"value\": <blob id>\n\t\t\t\tif (content === \"value\") {\n\t\t\t\t\tsnapshotTree.blobs[treeNode.getString(1)] = treeNode.getString(3);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// \"name\": <node name>\n\t\t\t// \"nodeType\": 3\n\t\t\t// \"value\": <blob id>\n\t\t\tif (\n\t\t\t\tlength === 6 &&\n\t\t\t\ttreeNode.getMaybeString(2) === \"nodeType\" &&\n\t\t\t\ttreeNode.getMaybeString(4) === \"value\"\n\t\t\t) {\n\t\t\t\tsnapshotTree.blobs[treeNode.getString(1)] = treeNode.getString(5);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// \"name\": <node name>\n\t\t\t// \"unreferenced\": true\n\t\t\t// \"children\": <blob id>\n\t\t\tif (\n\t\t\t\tlength === 6 &&\n\t\t\t\ttreeNode.getMaybeString(2) === \"unreferenced\" &&\n\t\t\t\ttreeNode.getMaybeString(4) === \"children\"\n\t\t\t) {\n\t\t\t\tconst result = readTreeSection(treeNode.getNode(5));\n\t\t\t\ttrees[treeNode.getString(1)] = result.snapshotTree;\n\t\t\t\tslowTreeStructureCount += result.slowTreeStructureCount;\n\t\t\t\tassert(treeNode.getBool(3), 0x3db /* Unreferenced if present should be true */);\n\t\t\t\tsnapshotTree.unreferenced = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * More generalized workflow\n\t\t */\n\t\tslowTreeStructureCount += 1;\n\t\tconst records = getNodeProps(treeNode);\n\n\t\tif (records.unreferenced !== undefined) {\n\t\t\tassertBoolInstance(records.unreferenced, \"Unreferenced flag should be bool\");\n\t\t\tassert(records.unreferenced, 0x281 /* \"Unreferenced if present should be true\" */);\n\t\t\tsnapshotTree.unreferenced = true;\n\t\t}\n\n\t\tconst path = getStringInstance(records.name, \"Path name should be string\");\n\t\tif (records.value !== undefined) {\n\t\t\tsnapshotTree.blobs[path] = getStringInstance(\n\t\t\t\trecords.value,\n\t\t\t\t\"Blob value should be string\",\n\t\t\t);\n\t\t} else if (records.children !== undefined) {\n\t\t\tassertNodeCoreInstance(records.children, \"Trees should be of type NodeCore\");\n\t\t\tconst result = readTreeSection(records.children);\n\t\t\ttrees[path] = result.snapshotTree;\n\t\t\tslowTreeStructureCount += result.slowTreeStructureCount;\n\t\t} else {\n\t\t\ttrees[path] = { blobs: {}, trees: {} };\n\t\t}\n\t}\n\treturn { 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\tassertNodeCoreInstance(node, \"Snapshot should be of type NodeCore\");\n\tconst records = getNodeProps(node);\n\n\tassertNodeCoreInstance(records.treeNodes, \"TreeNodes should be of type NodeCore\");\n\tassertNumberInstance(records.sequenceNumber, \"sequenceNumber should be of type number\");\n\tconst { snapshotTree, slowTreeStructureCount } = readTreeSection(records.treeNodes);\n\tsnapshotTree.id = getStringInstance(records.id, \"snapshotId should be string\");\n\tconst sequenceNumber = records.sequenceNumber.valueOf();\n\treturn {\n\t\tsequenceNumber,\n\t\tsnapshotTree,\n\t\tslowTreeStructureCount,\n\t};\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\tbuffer: Uint8Array,\n\tlogger: ITelemetryLoggerExt,\n): ISnapshotContentsWithProps {\n\tconst { builder, telemetryProps } = TreeBuilder.load(new ReadBuffer(buffer), logger);\n\tassert(builder.length === 1, 0x219 /* \"1 root should be there\" */);\n\tconst root = builder.getNode(0);\n\n\tconst records = getNodeProps(root);\n\n\tconst mrv = getStringInstance(records.mrv, \"minReadVersion should be string\");\n\tconst cv = getStringInstance(records.cv, \"createVersion should be string\");\n\tif (records.lsn !== undefined) {\n\t\tassertNumberInstance(records.lsn, \"lsn should be a number\");\n\t}\n\n\tassert(\n\t\tparseFloat(snapshotMinReadVersion) >= parseFloat(mrv),\n\t\t0x20f /* \"Driver min read version should >= to server minReadVersion\" */,\n\t);\n\tassert(\n\t\tparseFloat(cv) >= parseFloat(snapshotMinReadVersion),\n\t\t0x210 /* \"Snapshot should be created with minReadVersion or above\" */,\n\t);\n\tassert(\n\t\tcurrentReadVersion === cv,\n\t\t0x2c2 /* \"Create Version should be equal to currentReadVersion\" */,\n\t);\n\n\tconst [snapshot, durationSnapshotTree] = measure(() => readSnapshotSection(records.snapshot));\n\tconst [blobs, durationBlobs] = measure(() => readBlobSection(records.blobs));\n\n\treturn {\n\t\t...snapshot,\n\t\t...blobs,\n\t\tops: records.deltas !== undefined ? readOpsSection(records.deltas) : [],\n\t\tlatestSequenceNumber: records.lsn,\n\t\ttelemetryProps: {\n\t\t\t...telemetryProps,\n\t\t\tdurationSnapshotTree,\n\t\t\tdurationBlobs,\n\t\t\tslowTreeStructureCount: snapshot.slowTreeStructureCount,\n\t\t\tslowBlobStructureCount: blobs.slowBlobStructureCount,\n\t\t},\n\t};\n}\n"]}
@@ -6,7 +6,7 @@ import { ISnapshotContents } from "./odspPublicUtils";
6
6
  /**
7
7
  * Converts trees/blobs/ops to binary compact representation.
8
8
  * @param snapshotContents - snapshot tree contents to serialize
9
- * @returns - ReadBuffer - binary representation of the data.
9
+ * @returns ReadBuffer - binary representation of the data.
10
10
  */
11
11
  export declare function convertToCompactSnapshot(snapshotContents: ISnapshotContents): Uint8Array;
12
12
  //# sourceMappingURL=compactSnapshotWriter.d.ts.map
@@ -117,7 +117,7 @@ function writeOpsSection(rootNode, ops) {
117
117
  /**
118
118
  * Converts trees/blobs/ops to binary compact representation.
119
119
  * @param snapshotContents - snapshot tree contents to serialize
120
- * @returns - ReadBuffer - binary representation of the data.
120
+ * @returns ReadBuffer - binary representation of the data.
121
121
  */
122
122
  function convertToCompactSnapshot(snapshotContents) {
123
123
  const builder = new WriteBufferUtils_1.TreeBuilderSerializer();
@@ -1 +1 @@
1
- {"version":3,"file":"compactSnapshotWriter.js","sourceRoot":"","sources":["../src/compactSnapshotWriter.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 { stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { assert } from \"@fluidframework/core-utils\";\nimport {\n\tIBlob,\n\tISequencedDocumentMessage,\n\tISnapshotTree,\n} from \"@fluidframework/protocol-definitions\";\nimport { snapshotMinReadVersion } from \"./compactSnapshotParser\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { TreeBuilderSerializer } from \"./WriteBufferUtils\";\nimport {\n\taddBoolProperty,\n\taddNumberProperty,\n\taddStringProperty,\n\taddDictionaryStringProperty,\n\tNodeCore,\n} from \"./zipItDataRepresentationUtils\";\n\n/**\n * Writes header section of the snapshot.\n * @param node - snapshot node to serialize to\n * @param latestSequenceNumber - latest seq number of the container.\n */\nfunction writeSnapshotProps(node: NodeCore, latestSequenceNumber: number) {\n\taddStringProperty(node, \"mrv\", snapshotMinReadVersion);\n\taddStringProperty(node, \"cv\", snapshotMinReadVersion);\n\taddNumberProperty(node, \"lsn\", latestSequenceNumber);\n}\n\n/**\n * Represents blobs in the tree.\n * @param snapshotNode - node to serialize to.\n * @param blobs - blobs that is being serialized\n */\nfunction writeBlobsSection(snapshotNode: NodeCore, blobs: Map<string, IBlob | ArrayBuffer>) {\n\tsnapshotNode.addDictionaryString(\"blobs\");\n\tconst blobsNode = snapshotNode.addNode(\"list\");\n\tfor (const [storageBlobId, blob] of blobs) {\n\t\tconst blobNode = blobsNode.addNode();\n\t\taddDictionaryStringProperty(blobNode, \"id\", storageBlobId);\n\t\tblobNode.addString(\"data\");\n\t\tif (blob instanceof ArrayBuffer) {\n\t\t\tblobNode.addBlob(new Uint8Array(blob));\n\t\t} else {\n\t\t\tblobNode.addBlob(\n\t\t\t\tnew Uint8Array(stringToBuffer(blob.contents, blob.encoding ?? \"utf-8\")),\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Represents and serializes tree part of the snapshot\n * @param snapshotNode - tree node to serialize to\n * @param snapshotTree - snapshot tree that is being serialized\n */\nfunction writeTreeSection(snapshotNode: NodeCore, snapshotTree: ISnapshotTree) {\n\tsnapshotNode.addDictionaryString(\"treeNodes\");\n\tconst treesNode = snapshotNode.addNode(\"list\");\n\twriteTreeSectionCore(treesNode, snapshotTree);\n}\n\nfunction writeTreeSectionCore(treesNode: NodeCore, snapshotTree: ISnapshotTree) {\n\tfor (const [path, value] of Object.entries(snapshotTree.trees)) {\n\t\tconst treeNode = treesNode.addNode();\n\t\t// Many leaf nodes in the tree have same names like \"content\", \"body\", \"header\"\n\t\t// We could be smarter here and not use dictionary where we are sure reuse is unlikely, but\n\t\t// it does not feel like it's worth it.\n\t\taddDictionaryStringProperty(treeNode, \"name\", path);\n\t\tif (snapshotTree.unreferenced) {\n\t\t\taddBoolProperty(treeNode, \"unreferenced\", snapshotTree.unreferenced);\n\t\t}\n\t\t// Only write children prop if either blobs or trees are present.\n\t\tif (Object.keys(value.blobs).length > 0 || Object.keys(value.trees).length > 0) {\n\t\t\ttreeNode.addDictionaryString(\"children\");\n\t\t\tconst childNode = treeNode.addNode(\"list\");\n\t\t\twriteTreeSectionCore(childNode, value);\n\t\t}\n\t}\n\n\tif (snapshotTree.blobs) {\n\t\tfor (const [path, id] of Object.entries(snapshotTree.blobs)) {\n\t\t\tconst blobNode = treesNode.addNode();\n\t\t\taddDictionaryStringProperty(blobNode, \"name\", path);\n\t\t\taddDictionaryStringProperty(blobNode, \"value\", id);\n\t\t}\n\t}\n}\n\n/**\n * Represents (serializes) snapshot tree as generalizes tree\n * @param rootNode - tree node to serialize to\n * @param snapshotTree - snapshot tree that is being serialized\n * @param blobs - blobs mapping of the snapshot\n * @param snapshotSequenceNumber - seq number at which snapshot is taken\n */\nfunction writeSnapshotSection(\n\trootNode: NodeCore,\n\tsnapshotTree: ISnapshotTree,\n\tsnapshotSequenceNumber: number,\n) {\n\trootNode.addDictionaryString(\"snapshot\");\n\tconst snapshotNode = rootNode.addNode();\n\n\tconst snapshotId = snapshotTree.id;\n\tassert(snapshotId !== undefined, 0x21b /* \"Snapshot id should be provided\" */);\n\taddStringProperty(snapshotNode, \"id\", snapshotId);\n\taddStringProperty(snapshotNode, \"message\", `Snapshot@${snapshotSequenceNumber}`);\n\taddNumberProperty(snapshotNode, \"sequenceNumber\", snapshotSequenceNumber);\n\n\t// Add Trees\n\twriteTreeSection(snapshotNode, snapshotTree);\n}\n\n/**\n * Represents ops in the tree.\n * @param rootNode - node to serialize to.\n * @param ops - ops that is being serialized\n */\nfunction writeOpsSection(rootNode: NodeCore, ops: ISequencedDocumentMessage[]) {\n\tlet firstSequenceNumber: number | undefined;\n\tif (ops.length > 0) {\n\t\tfirstSequenceNumber = ops[0].sequenceNumber;\n\t}\n\tif (firstSequenceNumber !== undefined) {\n\t\trootNode.addDictionaryString(\"deltas\");\n\t\tconst opsNode = rootNode.addNode();\n\t\taddNumberProperty(opsNode, \"firstSequenceNumber\", firstSequenceNumber);\n\t\topsNode.addDictionaryString(\"deltas\");\n\t\tconst deltaNode = opsNode.addNode(\"list\");\n\t\tops.forEach((op) => {\n\t\t\tdeltaNode.addString(JSON.stringify(op));\n\t\t});\n\t}\n}\n\n/**\n * Converts trees/blobs/ops to binary compact representation.\n * @param snapshotContents - snapshot tree contents to serialize\n * @returns - ReadBuffer - binary representation of the data.\n */\nexport function convertToCompactSnapshot(snapshotContents: ISnapshotContents): Uint8Array {\n\tconst builder = new TreeBuilderSerializer();\n\t// Create the root node.\n\tconst rootNode = builder.addNode();\n\tassert(\n\t\tsnapshotContents.sequenceNumber !== undefined,\n\t\t0x21c /* \"Seq number should be provided\" */,\n\t);\n\n\tlet latestSequenceNumber = snapshotContents.latestSequenceNumber;\n\tif (latestSequenceNumber === undefined) {\n\t\tlatestSequenceNumber =\n\t\t\tsnapshotContents.ops.length > 0\n\t\t\t\t? snapshotContents.ops[snapshotContents.ops.length - 1].sequenceNumber\n\t\t\t\t: snapshotContents.sequenceNumber;\n\t}\n\n\twriteSnapshotProps(rootNode, latestSequenceNumber);\n\n\twriteSnapshotSection(rootNode, snapshotContents.snapshotTree, snapshotContents.sequenceNumber);\n\n\t// Add Blobs\n\twriteBlobsSection(rootNode, snapshotContents.blobs);\n\n\t// Then write the ops node.\n\twriteOpsSection(rootNode, snapshotContents.ops);\n\n\treturn builder.serialize();\n}\n"]}
1
+ {"version":3,"file":"compactSnapshotWriter.js","sourceRoot":"","sources":["../src/compactSnapshotWriter.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 { stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { assert } from \"@fluidframework/core-utils\";\nimport {\n\tIBlob,\n\tISequencedDocumentMessage,\n\tISnapshotTree,\n} from \"@fluidframework/protocol-definitions\";\nimport { snapshotMinReadVersion } from \"./compactSnapshotParser\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { TreeBuilderSerializer } from \"./WriteBufferUtils\";\nimport {\n\taddBoolProperty,\n\taddNumberProperty,\n\taddStringProperty,\n\taddDictionaryStringProperty,\n\tNodeCore,\n} from \"./zipItDataRepresentationUtils\";\n\n/**\n * Writes header section of the snapshot.\n * @param node - snapshot node to serialize to\n * @param latestSequenceNumber - latest seq number of the container.\n */\nfunction writeSnapshotProps(node: NodeCore, latestSequenceNumber: number) {\n\taddStringProperty(node, \"mrv\", snapshotMinReadVersion);\n\taddStringProperty(node, \"cv\", snapshotMinReadVersion);\n\taddNumberProperty(node, \"lsn\", latestSequenceNumber);\n}\n\n/**\n * Represents blobs in the tree.\n * @param snapshotNode - node to serialize to.\n * @param blobs - blobs that is being serialized\n */\nfunction writeBlobsSection(snapshotNode: NodeCore, blobs: Map<string, IBlob | ArrayBuffer>) {\n\tsnapshotNode.addDictionaryString(\"blobs\");\n\tconst blobsNode = snapshotNode.addNode(\"list\");\n\tfor (const [storageBlobId, blob] of blobs) {\n\t\tconst blobNode = blobsNode.addNode();\n\t\taddDictionaryStringProperty(blobNode, \"id\", storageBlobId);\n\t\tblobNode.addString(\"data\");\n\t\tif (blob instanceof ArrayBuffer) {\n\t\t\tblobNode.addBlob(new Uint8Array(blob));\n\t\t} else {\n\t\t\tblobNode.addBlob(\n\t\t\t\tnew Uint8Array(stringToBuffer(blob.contents, blob.encoding ?? \"utf-8\")),\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Represents and serializes tree part of the snapshot\n * @param snapshotNode - tree node to serialize to\n * @param snapshotTree - snapshot tree that is being serialized\n */\nfunction writeTreeSection(snapshotNode: NodeCore, snapshotTree: ISnapshotTree) {\n\tsnapshotNode.addDictionaryString(\"treeNodes\");\n\tconst treesNode = snapshotNode.addNode(\"list\");\n\twriteTreeSectionCore(treesNode, snapshotTree);\n}\n\nfunction writeTreeSectionCore(treesNode: NodeCore, snapshotTree: ISnapshotTree) {\n\tfor (const [path, value] of Object.entries(snapshotTree.trees)) {\n\t\tconst treeNode = treesNode.addNode();\n\t\t// Many leaf nodes in the tree have same names like \"content\", \"body\", \"header\"\n\t\t// We could be smarter here and not use dictionary where we are sure reuse is unlikely, but\n\t\t// it does not feel like it's worth it.\n\t\taddDictionaryStringProperty(treeNode, \"name\", path);\n\t\tif (snapshotTree.unreferenced) {\n\t\t\taddBoolProperty(treeNode, \"unreferenced\", snapshotTree.unreferenced);\n\t\t}\n\t\t// Only write children prop if either blobs or trees are present.\n\t\tif (Object.keys(value.blobs).length > 0 || Object.keys(value.trees).length > 0) {\n\t\t\ttreeNode.addDictionaryString(\"children\");\n\t\t\tconst childNode = treeNode.addNode(\"list\");\n\t\t\twriteTreeSectionCore(childNode, value);\n\t\t}\n\t}\n\n\tif (snapshotTree.blobs) {\n\t\tfor (const [path, id] of Object.entries(snapshotTree.blobs)) {\n\t\t\tconst blobNode = treesNode.addNode();\n\t\t\taddDictionaryStringProperty(blobNode, \"name\", path);\n\t\t\taddDictionaryStringProperty(blobNode, \"value\", id);\n\t\t}\n\t}\n}\n\n/**\n * Represents (serializes) snapshot tree as generalizes tree\n * @param rootNode - tree node to serialize to\n * @param snapshotTree - snapshot tree that is being serialized\n * @param blobs - blobs mapping of the snapshot\n * @param snapshotSequenceNumber - seq number at which snapshot is taken\n */\nfunction writeSnapshotSection(\n\trootNode: NodeCore,\n\tsnapshotTree: ISnapshotTree,\n\tsnapshotSequenceNumber: number,\n) {\n\trootNode.addDictionaryString(\"snapshot\");\n\tconst snapshotNode = rootNode.addNode();\n\n\tconst snapshotId = snapshotTree.id;\n\tassert(snapshotId !== undefined, 0x21b /* \"Snapshot id should be provided\" */);\n\taddStringProperty(snapshotNode, \"id\", snapshotId);\n\taddStringProperty(snapshotNode, \"message\", `Snapshot@${snapshotSequenceNumber}`);\n\taddNumberProperty(snapshotNode, \"sequenceNumber\", snapshotSequenceNumber);\n\n\t// Add Trees\n\twriteTreeSection(snapshotNode, snapshotTree);\n}\n\n/**\n * Represents ops in the tree.\n * @param rootNode - node to serialize to.\n * @param ops - ops that is being serialized\n */\nfunction writeOpsSection(rootNode: NodeCore, ops: ISequencedDocumentMessage[]) {\n\tlet firstSequenceNumber: number | undefined;\n\tif (ops.length > 0) {\n\t\tfirstSequenceNumber = ops[0].sequenceNumber;\n\t}\n\tif (firstSequenceNumber !== undefined) {\n\t\trootNode.addDictionaryString(\"deltas\");\n\t\tconst opsNode = rootNode.addNode();\n\t\taddNumberProperty(opsNode, \"firstSequenceNumber\", firstSequenceNumber);\n\t\topsNode.addDictionaryString(\"deltas\");\n\t\tconst deltaNode = opsNode.addNode(\"list\");\n\t\tops.forEach((op) => {\n\t\t\tdeltaNode.addString(JSON.stringify(op));\n\t\t});\n\t}\n}\n\n/**\n * Converts trees/blobs/ops to binary compact representation.\n * @param snapshotContents - snapshot tree contents to serialize\n * @returns ReadBuffer - binary representation of the data.\n */\nexport function convertToCompactSnapshot(snapshotContents: ISnapshotContents): Uint8Array {\n\tconst builder = new TreeBuilderSerializer();\n\t// Create the root node.\n\tconst rootNode = builder.addNode();\n\tassert(\n\t\tsnapshotContents.sequenceNumber !== undefined,\n\t\t0x21c /* \"Seq number should be provided\" */,\n\t);\n\n\tlet latestSequenceNumber = snapshotContents.latestSequenceNumber;\n\tif (latestSequenceNumber === undefined) {\n\t\tlatestSequenceNumber =\n\t\t\tsnapshotContents.ops.length > 0\n\t\t\t\t? snapshotContents.ops[snapshotContents.ops.length - 1].sequenceNumber\n\t\t\t\t: snapshotContents.sequenceNumber;\n\t}\n\n\twriteSnapshotProps(rootNode, latestSequenceNumber);\n\n\twriteSnapshotSection(rootNode, snapshotContents.snapshotTree, snapshotContents.sequenceNumber);\n\n\t// Add Blobs\n\twriteBlobsSection(rootNode, snapshotContents.blobs);\n\n\t// Then write the ops node.\n\twriteOpsSection(rootNode, snapshotContents.ops);\n\n\treturn builder.serialize();\n}\n"]}
@@ -9,10 +9,14 @@ import { IExistingFileInfo } from "./odspUtils";
9
9
  import { EpochTracker } from "./epochTracker";
10
10
  /**
11
11
  * Creates a new Fluid container on an existing file.
12
- * This requires service's capability to manage Fluid container inside an existing file.
13
- * @example - This enables a scenario where Fluid data is not stored as a standalone file but in a way that is managed
14
- * by an existing file. For example, SharePoint Pages is able to store Fluid container in an
15
- * "alternative file partition" where the main File stub is an ASPX page.
12
+ *
13
+ * @remarks This requires service's capability to manage Fluid container inside an existing file.
14
+ *
15
+ * @example
16
+ *
17
+ * This enables a scenario where Fluid data is not stored as a standalone file but in a way that is managed
18
+ * by an existing file. For example, SharePoint Pages is able to store Fluid container in an
19
+ * "alternative file partition" where the main File stub is an ASPX page.
16
20
  */
17
21
  export declare function createNewContainerOnExistingFile(getStorageToken: InstrumentedStorageTokenFetcher, fileInfo: IExistingFileInfo, logger: ITelemetryLoggerExt, createNewSummary: ISummaryTree | undefined, epochTracker: EpochTracker, fileEntry: IFileEntry, createNewCaching: boolean, forceAccessTokenViaAuthorizationHeader: boolean, isClpCompliantApp?: boolean): Promise<IOdspResolvedUrl>;
18
22
  //# sourceMappingURL=createNewContainerOnExistingFile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createNewContainerOnExistingFile.d.ts","sourceRoot":"","sources":["../src/createNewContainerOnExistingFile.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEtE,OAAO,EACN,UAAU,EACV,+BAA+B,EAC/B,gBAAgB,EAChB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,EAAqC,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAInF,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAS9C;;;;;;GAMG;AACH,wBAAsB,gCAAgC,CACrD,eAAe,EAAE,+BAA+B,EAChD,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,mBAAmB,EAC3B,gBAAgB,EAAE,YAAY,GAAG,SAAS,EAC1C,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,UAAU,EACrB,gBAAgB,EAAE,OAAO,EACzB,sCAAsC,EAAE,OAAO,EAC/C,iBAAiB,CAAC,EAAE,OAAO,GACzB,OAAO,CAAC,gBAAgB,CAAC,CA4C3B"}
1
+ {"version":3,"file":"createNewContainerOnExistingFile.d.ts","sourceRoot":"","sources":["../src/createNewContainerOnExistingFile.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEtE,OAAO,EACN,UAAU,EACV,+BAA+B,EAC/B,gBAAgB,EAChB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,EAAqC,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAInF,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAS9C;;;;;;;;;;GAUG;AACH,wBAAsB,gCAAgC,CACrD,eAAe,EAAE,+BAA+B,EAChD,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,mBAAmB,EAC3B,gBAAgB,EAAE,YAAY,GAAG,SAAS,EAC1C,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,UAAU,EACrB,gBAAgB,EAAE,OAAO,EACzB,sCAAsC,EAAE,OAAO,EAC/C,iBAAiB,CAAC,EAAE,OAAO,GACzB,OAAO,CAAC,gBAAgB,CAAC,CA4C3B"}
@@ -14,10 +14,14 @@ const createNewUtils_1 = require("./createNewUtils");
14
14
  const contractsPublic_1 = require("./contractsPublic");
15
15
  /**
16
16
  * Creates a new Fluid container on an existing file.
17
- * This requires service's capability to manage Fluid container inside an existing file.
18
- * @example - This enables a scenario where Fluid data is not stored as a standalone file but in a way that is managed
19
- * by an existing file. For example, SharePoint Pages is able to store Fluid container in an
20
- * "alternative file partition" where the main File stub is an ASPX page.
17
+ *
18
+ * @remarks This requires service's capability to manage Fluid container inside an existing file.
19
+ *
20
+ * @example
21
+ *
22
+ * This enables a scenario where Fluid data is not stored as a standalone file but in a way that is managed
23
+ * by an existing file. For example, SharePoint Pages is able to store Fluid container in an
24
+ * "alternative file partition" where the main File stub is an ASPX page.
21
25
  */
22
26
  async function createNewContainerOnExistingFile(getStorageToken, fileInfo, logger, createNewSummary, epochTracker, fileEntry, createNewCaching, forceAccessTokenViaAuthorizationHeader, isClpCompliantApp) {
23
27
  if (createNewSummary === undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"createNewContainerOnExistingFile.js","sourceRoot":"","sources":["../src/createNewContainerOnExistingFile.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH,+DAA0D;AAO1D,2CAAmF;AAEnF,mDAAgD;AAChD,mDAA6C;AAE7C,mEAAgE;AAChE,qDAI0B;AAC1B,uDAA0D;AAE1D;;;;;;GAMG;AACI,KAAK,UAAU,gCAAgC,CACrD,eAAgD,EAChD,QAA2B,EAC3B,MAA2B,EAC3B,gBAA0C,EAC1C,YAA0B,EAC1B,SAAqB,EACrB,gBAAyB,EACzB,sCAA+C,EAC/C,iBAA2B;IAE3B,IAAI,gBAAgB,KAAK,SAAS,EAAE;QACnC,MAAM,IAAI,yBAAU,CAAC,uDAAuD,CAAC,CAAC;KAC9E;IAED,MAAM,OAAO,GAAG,GAAG,IAAA,0BAAU,EAAC,IAAA,qBAAS,EAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,WAAW,QAAQ,CAAC,OAAO,UACpF,QAAQ,CAAC,MACV,EAAE,CAAC;IAEH,MAAM,iBAAiB,GAAG,IAAA,oDAAmC,EAAC,gBAAgB,CAAC,CAAC;IAEhF,MAAM,UAAU,GAAG,GAAG,OAAO,8BAA8B,CAAC;IAE5D,MAAM,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,MAAM,IAAA,4CAA2B,EAAwB;QACtF,iBAAiB;QACjB,eAAe;QACf,MAAM;QACN,UAAU;QACV,sCAAsC;QACtC,YAAY;QACZ,aAAa,EAAE,kCAAkC;QACjD,SAAS,EAAE,eAAe;KAC1B,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,IAAA,6BAAa,EAAC,EAAE,GAAG,QAAQ,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,IAAI,6CAAqB,EAAE,CAAC;IAC7C,MAAM,eAAe,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC;QAC9C,GAAG,EAAE,OAAO;QACZ,OAAO,EAAE,EAAE,CAAC,uCAAqB,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,EAAE;KACzE,CAAC,CAAC;IACH,SAAS,CAAC,KAAK,GAAG,eAAe,CAAC,gBAAgB,CAAC;IACnD,SAAS,CAAC,WAAW,GAAG,eAAe,CAAC;IAExC,IAAI,gBAAgB,EAAE;QACrB,iDAAiD;QACjD,MAAM,QAAQ,GAAsB,IAAA,0DAAyC,EAC5E,gBAAgB,EAChB,aAAa,CACb,CAAC;QACF,gCAAgC;QAChC,MAAM,YAAY,CAAC,GAAG,CAAC,IAAA,kCAAsB,EAAC,eAAe,CAAC,EAAE,QAAQ,CAAC,CAAC;KAC1E;IAED,OAAO,eAAe,CAAC;AACxB,CAAC;AAtDD,4EAsDC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ISummaryTree } from \"@fluidframework/protocol-definitions\";\nimport { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport { UsageError } from \"@fluidframework/driver-utils\";\nimport {\n\tIFileEntry,\n\tInstrumentedStorageTokenFetcher,\n\tIOdspResolvedUrl,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { IWriteSummaryResponse } from \"./contracts\";\nimport { createCacheSnapshotKey, getOrigin, IExistingFileInfo } from \"./odspUtils\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { createOdspUrl } from \"./createOdspUrl\";\nimport { getApiRoot } from \"./odspUrlHelper\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { OdspDriverUrlResolver } from \"./odspDriverUrlResolver\";\nimport {\n\tconvertCreateNewSummaryTreeToTreeAndBlobs,\n\tconvertSummaryIntoContainerSnapshot,\n\tcreateNewFluidContainerCore,\n} from \"./createNewUtils\";\nimport { ClpCompliantAppHeader } from \"./contractsPublic\";\n\n/**\n * Creates a new Fluid container on an existing file.\n * This requires service's capability to manage Fluid container inside an existing file.\n * @example - This enables a scenario where Fluid data is not stored as a standalone file but in a way that is managed\n * by an existing file. For example, SharePoint Pages is able to store Fluid container in an\n * \"alternative file partition\" where the main File stub is an ASPX page.\n */\nexport async function createNewContainerOnExistingFile(\n\tgetStorageToken: InstrumentedStorageTokenFetcher,\n\tfileInfo: IExistingFileInfo,\n\tlogger: ITelemetryLoggerExt,\n\tcreateNewSummary: ISummaryTree | undefined,\n\tepochTracker: EpochTracker,\n\tfileEntry: IFileEntry,\n\tcreateNewCaching: boolean,\n\tforceAccessTokenViaAuthorizationHeader: boolean,\n\tisClpCompliantApp?: boolean,\n): Promise<IOdspResolvedUrl> {\n\tif (createNewSummary === undefined) {\n\t\tthrow new UsageError(\"createNewSummary must exist to create a new container\");\n\t}\n\n\tconst baseUrl = `${getApiRoot(getOrigin(fileInfo.siteUrl))}/drives/${fileInfo.driveId}/items/${\n\t\tfileInfo.itemId\n\t}`;\n\n\tconst containerSnapshot = convertSummaryIntoContainerSnapshot(createNewSummary);\n\n\tconst initialUrl = `${baseUrl}/opStream/snapshots/snapshot`;\n\n\tconst { id: summaryHandle } = await createNewFluidContainerCore<IWriteSummaryResponse>({\n\t\tcontainerSnapshot,\n\t\tgetStorageToken,\n\t\tlogger,\n\t\tinitialUrl,\n\t\tforceAccessTokenViaAuthorizationHeader,\n\t\tepochTracker,\n\t\ttelemetryName: \"CreateNewContainerOnExistingFile\",\n\t\tfetchType: \"uploadSummary\",\n\t});\n\n\tconst odspUrl = createOdspUrl({ ...fileInfo, dataStorePath: \"/\" });\n\tconst resolver = new OdspDriverUrlResolver();\n\tconst odspResolvedUrl = await resolver.resolve({\n\t\turl: odspUrl,\n\t\theaders: { [ClpCompliantAppHeader.isClpCompliantApp]: isClpCompliantApp },\n\t});\n\tfileEntry.docId = odspResolvedUrl.hashedDocumentId;\n\tfileEntry.resolvedUrl = odspResolvedUrl;\n\n\tif (createNewCaching) {\n\t\t// converting summary and getting sequence number\n\t\tconst snapshot: ISnapshotContents = convertCreateNewSummaryTreeToTreeAndBlobs(\n\t\t\tcreateNewSummary,\n\t\t\tsummaryHandle,\n\t\t);\n\t\t// caching the converted summary\n\t\tawait epochTracker.put(createCacheSnapshotKey(odspResolvedUrl), snapshot);\n\t}\n\n\treturn odspResolvedUrl;\n}\n"]}
1
+ {"version":3,"file":"createNewContainerOnExistingFile.js","sourceRoot":"","sources":["../src/createNewContainerOnExistingFile.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH,+DAA0D;AAO1D,2CAAmF;AAEnF,mDAAgD;AAChD,mDAA6C;AAE7C,mEAAgE;AAChE,qDAI0B;AAC1B,uDAA0D;AAE1D;;;;;;;;;;GAUG;AACI,KAAK,UAAU,gCAAgC,CACrD,eAAgD,EAChD,QAA2B,EAC3B,MAA2B,EAC3B,gBAA0C,EAC1C,YAA0B,EAC1B,SAAqB,EACrB,gBAAyB,EACzB,sCAA+C,EAC/C,iBAA2B;IAE3B,IAAI,gBAAgB,KAAK,SAAS,EAAE;QACnC,MAAM,IAAI,yBAAU,CAAC,uDAAuD,CAAC,CAAC;KAC9E;IAED,MAAM,OAAO,GAAG,GAAG,IAAA,0BAAU,EAAC,IAAA,qBAAS,EAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,WAAW,QAAQ,CAAC,OAAO,UACpF,QAAQ,CAAC,MACV,EAAE,CAAC;IAEH,MAAM,iBAAiB,GAAG,IAAA,oDAAmC,EAAC,gBAAgB,CAAC,CAAC;IAEhF,MAAM,UAAU,GAAG,GAAG,OAAO,8BAA8B,CAAC;IAE5D,MAAM,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,MAAM,IAAA,4CAA2B,EAAwB;QACtF,iBAAiB;QACjB,eAAe;QACf,MAAM;QACN,UAAU;QACV,sCAAsC;QACtC,YAAY;QACZ,aAAa,EAAE,kCAAkC;QACjD,SAAS,EAAE,eAAe;KAC1B,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,IAAA,6BAAa,EAAC,EAAE,GAAG,QAAQ,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,IAAI,6CAAqB,EAAE,CAAC;IAC7C,MAAM,eAAe,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC;QAC9C,GAAG,EAAE,OAAO;QACZ,OAAO,EAAE,EAAE,CAAC,uCAAqB,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,EAAE;KACzE,CAAC,CAAC;IACH,SAAS,CAAC,KAAK,GAAG,eAAe,CAAC,gBAAgB,CAAC;IACnD,SAAS,CAAC,WAAW,GAAG,eAAe,CAAC;IAExC,IAAI,gBAAgB,EAAE;QACrB,iDAAiD;QACjD,MAAM,QAAQ,GAAsB,IAAA,0DAAyC,EAC5E,gBAAgB,EAChB,aAAa,CACb,CAAC;QACF,gCAAgC;QAChC,MAAM,YAAY,CAAC,GAAG,CAAC,IAAA,kCAAsB,EAAC,eAAe,CAAC,EAAE,QAAQ,CAAC,CAAC;KAC1E;IAED,OAAO,eAAe,CAAC;AACxB,CAAC;AAtDD,4EAsDC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ISummaryTree } from \"@fluidframework/protocol-definitions\";\nimport { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport { UsageError } from \"@fluidframework/driver-utils\";\nimport {\n\tIFileEntry,\n\tInstrumentedStorageTokenFetcher,\n\tIOdspResolvedUrl,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { IWriteSummaryResponse } from \"./contracts\";\nimport { createCacheSnapshotKey, getOrigin, IExistingFileInfo } from \"./odspUtils\";\nimport { ISnapshotContents } from \"./odspPublicUtils\";\nimport { createOdspUrl } from \"./createOdspUrl\";\nimport { getApiRoot } from \"./odspUrlHelper\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { OdspDriverUrlResolver } from \"./odspDriverUrlResolver\";\nimport {\n\tconvertCreateNewSummaryTreeToTreeAndBlobs,\n\tconvertSummaryIntoContainerSnapshot,\n\tcreateNewFluidContainerCore,\n} from \"./createNewUtils\";\nimport { ClpCompliantAppHeader } from \"./contractsPublic\";\n\n/**\n * Creates a new Fluid container on an existing file.\n *\n * @remarks This requires service's capability to manage Fluid container inside an existing file.\n *\n * @example\n *\n * This enables a scenario where Fluid data is not stored as a standalone file but in a way that is managed\n * by an existing file. For example, SharePoint Pages is able to store Fluid container in an\n * \"alternative file partition\" where the main File stub is an ASPX page.\n */\nexport async function createNewContainerOnExistingFile(\n\tgetStorageToken: InstrumentedStorageTokenFetcher,\n\tfileInfo: IExistingFileInfo,\n\tlogger: ITelemetryLoggerExt,\n\tcreateNewSummary: ISummaryTree | undefined,\n\tepochTracker: EpochTracker,\n\tfileEntry: IFileEntry,\n\tcreateNewCaching: boolean,\n\tforceAccessTokenViaAuthorizationHeader: boolean,\n\tisClpCompliantApp?: boolean,\n): Promise<IOdspResolvedUrl> {\n\tif (createNewSummary === undefined) {\n\t\tthrow new UsageError(\"createNewSummary must exist to create a new container\");\n\t}\n\n\tconst baseUrl = `${getApiRoot(getOrigin(fileInfo.siteUrl))}/drives/${fileInfo.driveId}/items/${\n\t\tfileInfo.itemId\n\t}`;\n\n\tconst containerSnapshot = convertSummaryIntoContainerSnapshot(createNewSummary);\n\n\tconst initialUrl = `${baseUrl}/opStream/snapshots/snapshot`;\n\n\tconst { id: summaryHandle } = await createNewFluidContainerCore<IWriteSummaryResponse>({\n\t\tcontainerSnapshot,\n\t\tgetStorageToken,\n\t\tlogger,\n\t\tinitialUrl,\n\t\tforceAccessTokenViaAuthorizationHeader,\n\t\tepochTracker,\n\t\ttelemetryName: \"CreateNewContainerOnExistingFile\",\n\t\tfetchType: \"uploadSummary\",\n\t});\n\n\tconst odspUrl = createOdspUrl({ ...fileInfo, dataStorePath: \"/\" });\n\tconst resolver = new OdspDriverUrlResolver();\n\tconst odspResolvedUrl = await resolver.resolve({\n\t\turl: odspUrl,\n\t\theaders: { [ClpCompliantAppHeader.isClpCompliantApp]: isClpCompliantApp },\n\t});\n\tfileEntry.docId = odspResolvedUrl.hashedDocumentId;\n\tfileEntry.resolvedUrl = odspResolvedUrl;\n\n\tif (createNewCaching) {\n\t\t// converting summary and getting sequence number\n\t\tconst snapshot: ISnapshotContents = convertCreateNewSummaryTreeToTreeAndBlobs(\n\t\t\tcreateNewSummary,\n\t\t\tsummaryHandle,\n\t\t);\n\t\t// caching the converted summary\n\t\tawait epochTracker.put(createCacheSnapshotKey(odspResolvedUrl), snapshot);\n\t}\n\n\treturn odspResolvedUrl;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"odspDocumentDeltaConnection.d.ts","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,mBAAmB,EACnB,eAAe,EAEf,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EACN,OAAO,EACP,QAAQ,EACR,gBAAgB,EAIhB,MAAM,sCAAsC,CAAC;AAK9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAQ9C,MAAM,WAAW,WAAW;IAC3B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAqLD;;GAEG;AACH,qBAAa,2BAA4B,SAAQ,uBAAuB;IA4KtE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IA3KrC;;;;;;;;;;;;;;OAcG;WACiB,MAAM,CACzB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAElB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,mBAAmB,EACpC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,YAAY,EAC1B,wBAAwB,EAAE,MAAM,GAAG,SAAS,GAC1C,OAAO,CAAC,2BAA2B,CAAC;IAiFvC,OAAO,CAAC,eAAe,CAA8B;IAErD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CACf;IACX,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,+BAA+B,CAA4C;IAEnF;;OAEG;IACH,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,QAAQ,UAAO,GAAG,eAAe;IAS3F;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,4BAA4B;IA2B3C;;;;;;OAMG;IACH,OAAO;IAaP;;;;;OAKG;IACI,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAuD7B,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC;IAkC1C,SAAS,CAAC,iBAAiB,UAAW,eAAe,GAAG,SAAS,yCAc/D;cAEc,UAAU,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM;IA+FpE,SAAS,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI;IA0D9E,IAAW,QAAQ,YAkBlB;IAED;;;;OAIG;IACH,OAAO,KAAK,SAAS,GAEpB;IAED,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,EAAE;IAOnE;;;OAGG;IACI,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,IAAI;IAIjD;;;;OAIG;IACI,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAIpD;;;OAGG;IACH,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,eAAe;IAUhD;;OAEG;IACH,SAAS,CAAC,cAAc;CAaxB"}
1
+ {"version":3,"file":"odspDocumentDeltaConnection.d.ts","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,mBAAmB,EACnB,eAAe,EAEf,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EACN,OAAO,EACP,QAAQ,EACR,gBAAgB,EAIhB,MAAM,sCAAsC,CAAC;AAK9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAS9C,MAAM,WAAW,WAAW;IAC3B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AA2LD;;GAEG;AACH,qBAAa,2BAA4B,SAAQ,uBAAuB;IA4KtE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IA3KrC;;;;;;;;;;;;;;OAcG;WACiB,MAAM,CACzB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAElB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,mBAAmB,EACpC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,YAAY,EAC1B,wBAAwB,EAAE,MAAM,GAAG,SAAS,GAC1C,OAAO,CAAC,2BAA2B,CAAC;IAiFvC,OAAO,CAAC,eAAe,CAA8B;IAErD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CACf;IACX,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,+BAA+B,CAA4C;IAEnF;;OAEG;IACH,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,QAAQ,UAAO,GAAG,eAAe;IAS3F;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,4BAA4B;IA2B3C;;;;;;OAMG;IACH,OAAO;IAaP;;;;;OAKG;IACI,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAuD7B,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC;IAkC1C,SAAS,CAAC,iBAAiB,UAAW,eAAe,GAAG,SAAS,yCAc/D;cAEc,UAAU,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM;IA+FpE,SAAS,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI;IA0D9E,IAAW,QAAQ,YAkBlB;IAED;;;;OAIG;IACH,OAAO,KAAK,SAAS,GAEpB;IAED,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,EAAE;IAOnE;;;OAGG;IACI,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,IAAI;IAIjD;;;;OAIG;IACI,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAIpD;;;OAGG;IACH,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,eAAe;IAUhD;;OAEG;IACH,SAAS,CAAC,cAAc;CAaxB"}
@@ -9,10 +9,10 @@ const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
9
9
  const client_utils_1 = require("@fluid-internal/client-utils");
10
10
  const core_utils_1 = require("@fluidframework/core-utils");
11
11
  const driver_base_1 = require("@fluidframework/driver-base");
12
- const socket_io_client_1 = require("socket.io-client");
13
12
  const uuid_1 = require("uuid");
14
13
  const driver_utils_1 = require("@fluidframework/driver-utils");
15
14
  const odspError_1 = require("./odspError");
15
+ const socketModule_1 = require("./socketModule");
16
16
  const packageVersion_1 = require("./packageVersion");
17
17
  const protocolVersions = ["^0.4.0", "^0.3.0", "^0.2.0", "^0.1.0"];
18
18
  const feature_get_ops = "api_get_ops";
@@ -30,13 +30,7 @@ class SocketReference extends client_utils_1.TypedEventEmitter {
30
30
  // Socket that never connected and never failed, it's in "attempting to connect" mode
31
31
  // such sockets should be reused, despite socket.disconnected === true
32
32
  this.isPendingInitialConnection = true;
33
- this._socket = socket;
34
- (0, core_utils_1.assert)(!SocketReference.socketIoSockets.has(key), 0x220 /* "socket key collision" */);
35
- SocketReference.socketIoSockets.set(key, this);
36
- // Server sends this event when it wants to disconnect a particular client in which case the client id would
37
- // be present or if it wants to disconnect all the clients. The server always closes the socket in case all
38
- // clients needs to be disconnected. So fully remove the socket reference in this case.
39
- socket.on("server_disconnect", (socketError, clientId) => {
33
+ this.serverDisconnectEventHandler = (socketError, clientId) => {
40
34
  // Treat all errors as recoverable, and rely on joinSession / reconnection flow to
41
35
  // filter out retryable vs. non-retryable cases.
42
36
  const error = (0, odspError_1.errorObjectFromSocketError)(socketError, "server_disconnect");
@@ -54,7 +48,14 @@ class SocketReference extends client_utils_1.TypedEventEmitter {
54
48
  else {
55
49
  this.emit("disconnect", error, clientId);
56
50
  }
57
- });
51
+ };
52
+ this._socket = socket;
53
+ (0, core_utils_1.assert)(!SocketReference.socketIoSockets.has(key), 0x220 /* "socket key collision" */);
54
+ SocketReference.socketIoSockets.set(key, this);
55
+ // Server sends this event when it wants to disconnect a particular client in which case the client id would
56
+ // be present or if it wants to disconnect all the clients. The server always closes the socket in case all
57
+ // clients needs to be disconnected. So fully remove the socket reference in this case.
58
+ socket.on("server_disconnect", this.serverDisconnectEventHandler);
58
59
  }
59
60
  static find(key, logger) {
60
61
  const socketReference = SocketReference.socketIoSockets.get(key);
@@ -108,6 +109,7 @@ class SocketReference extends client_utils_1.TypedEventEmitter {
108
109
  if (!this._socket) {
109
110
  return;
110
111
  }
112
+ this._socket.off("server_disconnect", this.serverDisconnectEventHandler);
111
113
  this.clearTimer();
112
114
  (0, core_utils_1.assert)(SocketReference.socketIoSockets.get(this.key) === this, 0x0a1 /* "Socket reference set unexpectedly does not point to this socket!" */);
113
115
  // First, remove socket to ensure no socket reuse is possible.
@@ -268,7 +270,7 @@ class OdspDocumentDeltaConnection extends driver_base_1.DocumentDeltaConnection
268
270
  return existingSocketReference;
269
271
  }
270
272
  const query = enableMultiplexing ? undefined : { documentId, tenantId };
271
- const socket = (0, socket_io_client_1.io)(url, {
273
+ const socket = (0, socketModule_1.SocketIOClientStatic)(url, {
272
274
  multiplex: false,
273
275
  query,
274
276
  reconnection: false,
@@ -375,14 +377,14 @@ class OdspDocumentDeltaConnection extends driver_base_1.DocumentDeltaConnection
375
377
  };
376
378
  }
377
379
  this.socketReference.on("disconnect", this.disconnectHandler);
378
- this.socket.on("get_ops_response", (result) => {
380
+ this.addTrackedListener("get_ops_response", (result) => {
379
381
  const messages = result.messages;
380
382
  const data = this.getOpsMap.get(result.nonce);
381
383
  // Due to socket multiplexing, this client may not have asked for any data
382
384
  // If so, there it most likely does not need these ops (otherwise it already asked for them)
383
385
  // Also we may have deleted entry in this.getOpsMap due to too many requests and too slow response.
384
386
  // But not processing such result may push us into infinite loop of fast requests and dropping all responses
385
- if (data !== undefined || result.nonce.indexOf(this.requestOpsNoncePrefix) === 0) {
387
+ if (data !== undefined || result.nonce.startsWith(this.requestOpsNoncePrefix)) {
386
388
  this.getOpsMap.delete(result.nonce);
387
389
  const common = {
388
390
  eventName: "GetOps",
@@ -410,7 +412,7 @@ class OdspDocumentDeltaConnection extends driver_base_1.DocumentDeltaConnection
410
412
  }
411
413
  }
412
414
  });
413
- this.socket.on("flush_ops_response", (result) => {
415
+ this.addTrackedListener("flush_ops_response", (result) => {
414
416
  if (this.flushOpNonce === result.nonce) {
415
417
  const seq = result.lastPersistedSequenceNumber;
416
418
  let category = "generic";
@@ -1 +1 @@
1
- {"version":3,"file":"odspDocumentDeltaConnection.js","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.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 { IEvent } from \"@fluidframework/core-interfaces\";\nimport {\n\tITelemetryLoggerExt,\n\tIFluidErrorBase,\n\tloggerToMonitoringContext,\n} from \"@fluidframework/telemetry-utils\";\nimport { performance, TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { assert, Deferred } from \"@fluidframework/core-utils\";\nimport { DocumentDeltaConnection } from \"@fluidframework/driver-base\";\nimport { IAnyDriverError } from \"@fluidframework/driver-definitions\";\nimport { OdspError } from \"@fluidframework/odsp-driver-definitions\";\nimport {\n\tIClient,\n\tIConnect,\n\tIDocumentMessage,\n\tINack,\n\tISequencedDocumentMessage,\n\tISignalMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport { Socket, io as SocketIOClientStatic } from \"socket.io-client\";\nimport { v4 as uuid } from \"uuid\";\nimport { createGenericNetworkError } from \"@fluidframework/driver-utils\";\nimport { IOdspSocketError, IGetOpsResponse, IFlushOpsResponse } from \"./contracts\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { errorObjectFromSocketError } from \"./odspError\";\nimport { pkgVersion } from \"./packageVersion\";\n\nconst protocolVersions = [\"^0.4.0\", \"^0.3.0\", \"^0.2.0\", \"^0.1.0\"];\nconst feature_get_ops = \"api_get_ops\";\nconst feature_flush_ops = \"api_flush_ops\";\n\nexport interface FlushResult {\n\tlastPersistedSequenceNumber?: number;\n\tretryAfter?: number;\n}\n\n// How long to wait before disconnecting the socket after the last reference is removed\n// This allows reconnection after receiving a nack to be smooth\nconst socketReferenceBufferTime = 2000;\n\ninterface ISocketEvents extends IEvent {\n\t(\n\t\tevent: \"disconnect\",\n\t\tlistener: (error: IFluidErrorBase & OdspError, clientId?: string) => void,\n\t);\n}\n\nclass SocketReference extends TypedEventEmitter<ISocketEvents> {\n\tprivate references: number = 1;\n\tprivate delayDeleteTimeout: ReturnType<typeof setTimeout> | undefined;\n\tprivate _socket: Socket | undefined;\n\n\t// When making decisions about socket reuse, we do not reuse disconnected socket.\n\t// But we want to differentiate the following case from disconnected case:\n\t// Socket that never connected and never failed, it's in \"attempting to connect\" mode\n\t// such sockets should be reused, despite socket.disconnected === true\n\tprivate isPendingInitialConnection = true;\n\n\t// Map of all existing socket io sockets. [url, tenantId, documentId] -> socket\n\tprivate static readonly socketIoSockets: Map<string, SocketReference> = new Map();\n\n\tpublic static find(key: string, logger: ITelemetryLoggerExt) {\n\t\tconst socketReference = SocketReference.socketIoSockets.get(key);\n\n\t\t// Verify the socket is healthy before reusing it\n\t\tif (socketReference?.disconnected) {\n\t\t\t// The socket is in a bad state. fully remove the reference\n\t\t\tsocketReference.closeSocket();\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (socketReference) {\n\t\t\t// Clear the pending deletion if there is one\n\t\t\tsocketReference.clearTimer();\n\t\t\tsocketReference.references++;\n\t\t}\n\n\t\treturn socketReference;\n\t}\n\n\t/**\n\t * Removes a reference for the given key\n\t * Once the ref count hits 0, the socket is disconnected and removed\n\t */\n\tpublic removeSocketIoReference() {\n\t\tassert(this.references > 0, 0x09f /* \"No more socketIO refs to remove!\" */);\n\t\tthis.references--;\n\n\t\t// see comment in disconnected() getter\n\t\tthis.isPendingInitialConnection = false;\n\n\t\tif (this.disconnected) {\n\t\t\tthis.closeSocket();\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.references === 0 && this.delayDeleteTimeout === undefined) {\n\t\t\tthis.delayDeleteTimeout = setTimeout(() => {\n\t\t\t\t// We should not get here with active users.\n\t\t\t\tassert(\n\t\t\t\t\tthis.references === 0,\n\t\t\t\t\t0x0a0 /* \"Unexpected socketIO references on timeout\" */,\n\t\t\t\t);\n\t\t\t\tthis.closeSocket();\n\t\t\t}, socketReferenceBufferTime);\n\t\t}\n\t}\n\n\tpublic get socket() {\n\t\tif (!this._socket) {\n\t\t\tthrow new Error(`Invalid socket for key \"${this.key}`);\n\t\t}\n\t\treturn this._socket;\n\t}\n\n\tpublic constructor(public readonly key: string, socket: Socket) {\n\t\tsuper();\n\n\t\tthis._socket = socket;\n\t\tassert(!SocketReference.socketIoSockets.has(key), 0x220 /* \"socket key collision\" */);\n\t\tSocketReference.socketIoSockets.set(key, this);\n\n\t\t// Server sends this event when it wants to disconnect a particular client in which case the client id would\n\t\t// be present or if it wants to disconnect all the clients. The server always closes the socket in case all\n\t\t// clients needs to be disconnected. So fully remove the socket reference in this case.\n\t\tsocket.on(\"server_disconnect\", (socketError: IOdspSocketError, clientId?: string) => {\n\t\t\t// Treat all errors as recoverable, and rely on joinSession / reconnection flow to\n\t\t\t// filter out retryable vs. non-retryable cases.\n\t\t\tconst error = errorObjectFromSocketError(socketError, \"server_disconnect\");\n\t\t\terror.addTelemetryProperties({ disconnectClientId: clientId });\n\t\t\terror.canRetry = true;\n\n\t\t\t// see comment in disconnected() getter\n\t\t\t// Setting it here to ensure socket reuse does not happen if new request to connect\n\t\t\t// comes in from \"disconnect\" listener below, before we close socket.\n\t\t\tthis.isPendingInitialConnection = false;\n\n\t\t\tif (clientId === undefined) {\n\t\t\t\t// We could first raise \"disconnect\" event, but that may result in socket reuse due to\n\t\t\t\t// new connection comming in. So, it's better to have more explicit flow to make it impossible.\n\t\t\t\tthis.closeSocket(error);\n\t\t\t} else {\n\t\t\t\tthis.emit(\"disconnect\", error, clientId);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate clearTimer() {\n\t\tif (this.delayDeleteTimeout !== undefined) {\n\t\t\tclearTimeout(this.delayDeleteTimeout);\n\t\t\tthis.delayDeleteTimeout = undefined;\n\t\t}\n\t}\n\n\tpublic closeSocket(error?: IAnyDriverError) {\n\t\tif (!this._socket) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.clearTimer();\n\n\t\tassert(\n\t\t\tSocketReference.socketIoSockets.get(this.key) === this,\n\t\t\t0x0a1 /* \"Socket reference set unexpectedly does not point to this socket!\" */,\n\t\t);\n\n\t\t// First, remove socket to ensure no socket reuse is possible.\n\t\tSocketReference.socketIoSockets.delete(this.key);\n\n\t\t// Block access to socket. From now on, calls like flush() or requestOps()\n\t\t// Disconnect flow should be synchronous and result in system fully forgetting about this connection / socket.\n\t\tconst socket = this._socket;\n\t\tthis._socket = undefined;\n\n\t\t// Let all connections know they need to go through disconnect flow.\n\t\tthis.emit(\n\t\t\t\"disconnect\",\n\t\t\terror ??\n\t\t\t\tcreateGenericNetworkError(\n\t\t\t\t\t\"Socket closed without error\",\n\t\t\t\t\t{ canRetry: true },\n\t\t\t\t\t{ driverVersion: pkgVersion },\n\t\t\t\t),\n\t\t\tundefined /* clientId */,\n\t\t);\n\n\t\t// We should not have any users now, assuming synchronous disconnect flow in response to\n\t\t// \"disconnect\" event\n\t\tassert(\n\t\t\tthis.references === 0,\n\t\t\t0x412 /* Nobody should be connected to this socket at this point! */,\n\t\t);\n\n\t\tsocket.disconnect();\n\t}\n\n\tpublic get disconnected() {\n\t\tif (this._socket === undefined) {\n\t\t\treturn true;\n\t\t}\n\t\tif (this.socket.connected) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We have a socket that is not connected. Possible cases:\n\t\t// 1) It was connected some time ago and lost connection. We do not want to reuse it.\n\t\t// 2) It failed to connect (was never connected).\n\t\t// 3) It was just created and never had a chance to connect - connection is in process.\n\t\t// We have to differentiate 1 from 2-3 (specifically 1 & 3) in order to be able to reuse socket in #3.\n\t\t// We will use the fact that socket had some activity. I.e. if socket disconnected, or client stopped using\n\t\t// socket, then removeSocketIoReference() will be called for it, and it will be the indiction that it's not #3.\n\t\treturn !this.isPendingInitialConnection;\n\t}\n}\n\n/**\n * Represents a connection to a stream of delta updates\n */\nexport class OdspDocumentDeltaConnection extends DocumentDeltaConnection {\n\t/**\n\t * Create a OdspDocumentDeltaConnection\n\t * If url #1 fails to connect, will try url #2 if applicable.\n\t *\n\t * @param tenantId - the ID of the tenant\n\t * @param documentId - document ID\n\t * @param token - authorization token for storage service\n\t * @param client - information about the client\n\t * @param mode - mode of the client\n\t * @param url - websocket URL\n\t * @param telemetryLogger - optional telemetry logger\n\t * @param timeoutMs - time limit on making the connection\n\t * @param epochTracker - track epoch changes\n\t * @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache\n\t */\n\tpublic static async create(\n\t\ttenantId: string,\n\t\tdocumentId: string,\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\ttoken: string | null,\n\t\tclient: IClient,\n\t\turl: string,\n\t\ttelemetryLogger: ITelemetryLoggerExt,\n\t\ttimeoutMs: number,\n\t\tepochTracker: EpochTracker,\n\t\tsocketReferenceKeyPrefix: string | undefined,\n\t): Promise<OdspDocumentDeltaConnection> {\n\t\tconst mc = loggerToMonitoringContext(telemetryLogger);\n\n\t\t// enable multiplexing when the websocket url does not include the tenant/document id\n\t\tconst parsedUrl = new URL(url);\n\t\tconst enableMultiplexing =\n\t\t\t!parsedUrl.searchParams.has(\"documentId\") && !parsedUrl.searchParams.has(\"tenantId\");\n\n\t\t// do not include the specific tenant/doc id in the ref key when multiplexing\n\t\t// this will allow multiple documents to share the same websocket connection\n\t\tconst key = socketReferenceKeyPrefix ? `${socketReferenceKeyPrefix},${url}` : url;\n\t\tconst socketReferenceKey = enableMultiplexing ? key : `${key},${tenantId},${documentId}`;\n\n\t\tconst socketReference = OdspDocumentDeltaConnection.getOrCreateSocketIoReference(\n\t\t\ttimeoutMs,\n\t\t\tsocketReferenceKey,\n\t\t\turl,\n\t\t\tenableMultiplexing,\n\t\t\ttenantId,\n\t\t\tdocumentId,\n\t\t\ttelemetryLogger,\n\t\t);\n\n\t\tconst socket = socketReference.socket;\n\t\tconst connectionId = uuid();\n\t\tconst connectMessage: IConnect = {\n\t\t\tclient,\n\t\t\tid: documentId,\n\t\t\tmode: client.mode,\n\t\t\ttenantId,\n\t\t\ttoken, // Token is going to indicate tenant level information, etc...\n\t\t\tversions: protocolVersions,\n\t\t\tdriverVersion: pkgVersion,\n\t\t\tnonce: connectionId,\n\t\t\tepoch: epochTracker.fluidEpoch,\n\t\t\trelayUserAgent: [client.details.environment, ` driverVersion:${pkgVersion}`].join(\";\"),\n\t\t};\n\n\t\t// Reference to this client supporting get_ops flow.\n\t\tconnectMessage.supportedFeatures = {};\n\t\tif (mc.config.getBoolean(\"Fluid.Driver.Odsp.GetOpsEnabled\") !== false) {\n\t\t\tconnectMessage.supportedFeatures[feature_get_ops] = true;\n\t\t}\n\n\t\tconst deltaConnection = new OdspDocumentDeltaConnection(\n\t\t\tsocket,\n\t\t\tdocumentId,\n\t\t\tsocketReference,\n\t\t\ttelemetryLogger,\n\t\t\tenableMultiplexing,\n\t\t\tconnectionId,\n\t\t);\n\n\t\ttry {\n\t\t\tawait deltaConnection.initialize(connectMessage, timeoutMs);\n\t\t\tawait epochTracker.validateEpoch(deltaConnection.details.epoch, \"push\");\n\t\t} catch (errorObject: any) {\n\t\t\tif (errorObject !== null && typeof errorObject === \"object\") {\n\t\t\t\t// We have to special-case error types here in terms of what is re-triable.\n\t\t\t\t// These errors have to re-retried, we just need new joinSession result to connect to right server:\n\t\t\t\t// 400: Invalid tenant or document id. The WebSocket is connected to a different document\n\t\t\t\t// Document is full (with retryAfter)\n\t\t\t\t// 404: Invalid document. The document \\\"local/w1-...\\\" does not exist\n\t\t\t\t// But this has to stay not-retriable:\n\t\t\t\t// 406: Unsupported client protocol. This path is the only gatekeeper, have to fail!\n\t\t\t\t// 409: Epoch Version Mismatch. Client epoch and server epoch does not match, so app needs\n\t\t\t\t// to be refreshed.\n\t\t\t\t// This one is fine either way\n\t\t\t\t// 401/403: Code will retry once with new token either way, then it becomes fatal - on this path\n\t\t\t\t// and on join Session path.\n\t\t\t\t// 501: (Fluid not enabled): this is fine either way, as joinSession is gatekeeper\n\t\t\t\tif (errorObject.statusCode === 400 || errorObject.statusCode === 404) {\n\t\t\t\t\terrorObject.canRetry = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow errorObject;\n\t\t}\n\n\t\treturn deltaConnection;\n\t}\n\n\tprivate socketReference: SocketReference | undefined;\n\n\tprivate readonly requestOpsNoncePrefix: string;\n\tprivate pushCallCounter = 0;\n\tprivate readonly getOpsMap: Map<string, { start: number; from: number; to: number }> =\n\t\tnew Map();\n\tprivate flushOpNonce: string | undefined;\n\tprivate flushDeferred: Deferred<FlushResult> | undefined;\n\tprivate connectionNotYetDisposedTimeout: ReturnType<typeof setTimeout> | undefined;\n\n\t/**\n\t * Error raising for socket.io issues\n\t */\n\tprotected createErrorObject(handler: string, error?: any, canRetry = true): IAnyDriverError {\n\t\t// Note: we suspect the incoming error object is either:\n\t\t// - a socketError: add it to the OdspError object for driver to be able to parse it and reason over it.\n\t\t// - anything else: let base class handle it\n\t\treturn canRetry && Number.isInteger(error?.code) && typeof error?.message === \"string\"\n\t\t\t? errorObjectFromSocketError(error as IOdspSocketError, handler)\n\t\t\t: super.createErrorObject(handler, error, canRetry);\n\t}\n\n\t/**\n\t * Gets or create a socket io connection for the given key\n\t */\n\tprivate static getOrCreateSocketIoReference(\n\t\ttimeoutMs: number,\n\t\tkey: string,\n\t\turl: string,\n\t\tenableMultiplexing: boolean,\n\t\ttenantId: string,\n\t\tdocumentId: string,\n\t\tlogger: ITelemetryLoggerExt,\n\t): SocketReference {\n\t\tconst existingSocketReference = SocketReference.find(key, logger);\n\t\tif (existingSocketReference) {\n\t\t\treturn existingSocketReference;\n\t\t}\n\n\t\tconst query = enableMultiplexing ? undefined : { documentId, tenantId };\n\n\t\tconst socket = SocketIOClientStatic(url, {\n\t\t\tmultiplex: false, // Don't rely on socket.io built-in multiplexing\n\t\t\tquery,\n\t\t\treconnection: false,\n\t\t\ttransports: [\"websocket\"],\n\t\t\ttimeout: timeoutMs,\n\t\t});\n\n\t\treturn new SocketReference(key, socket);\n\t}\n\n\t/**\n\t * @param socket - websocket to be used\n\t * @param documentId - ID of the document\n\t * @param details - details of the websocket connection\n\t * @param socketReferenceKey - socket reference key\n\t * @param enableMultiplexing - If the websocket is multiplexing multiple documents\n\t */\n\tprivate constructor(\n\t\tsocket: Socket,\n\t\tdocumentId: string,\n\t\tsocketReference: SocketReference,\n\t\tlogger: ITelemetryLoggerExt,\n\t\tprivate readonly enableMultiplexing?: boolean,\n\t\tconnectionId?: string,\n\t) {\n\t\tsuper(socket, documentId, logger, false, connectionId);\n\t\tthis.socketReference = socketReference;\n\t\tthis.requestOpsNoncePrefix = `${uuid()}-`;\n\t}\n\n\t/**\n\t * Retrieves ops from PUSH\n\t * @param from - inclusive\n\t * @param to - exclusive\n\t * @returns ops retrieved\n\t */\n\tpublic requestOps(from: number, to: number) {\n\t\tassert(!this.socketReference?.disconnected, 0x413 /* non-active socket */);\n\n\t\t// Given that to is exclusive, we should be asking for at least something!\n\t\tassert(to > from, 0x272 /* \"empty request\" */);\n\n\t\t// PUSH may disable this functionality\n\t\t// back-compat: remove cast to any once latest version of IConnected is consumed\n\t\tif ((this.details as any).supportedFeatures?.[feature_get_ops] !== true) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.pushCallCounter++;\n\t\tconst nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;\n\t\tconst start = performance.now();\n\n\t\t// We may keep keep accumulating memory for nothing, if we are not getting responses.\n\t\t// Note that we should not have overlapping requests, as DeltaManager allows only one\n\t\t// outstanding request to storage, and that's the only way to get here.\n\t\t// But requests could be cancelled, and thus overlapping requests might be in the picture\n\t\t// If it happens, we do not care about stale requests.\n\t\t// So track some number of requests, but log if we get too many in flight - that likely\n\t\t// indicates an error somewhere.\n\t\tif (this.getOpsMap.size >= 5) {\n\t\t\tlet time = start;\n\t\t\tlet key: string | undefined;\n\t\t\tfor (const [keyCandidate, value] of this.getOpsMap.entries()) {\n\t\t\t\tif (value.start <= time || key === undefined) {\n\t\t\t\t\ttime = value.start;\n\t\t\t\t\tkey = keyCandidate;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst payloadToDelete = this.getOpsMap.get(key!)!;\n\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\teventName: \"GetOpsTooMany\",\n\t\t\t\tnonce,\n\t\t\t\tfrom: payloadToDelete.from,\n\t\t\t\tto: payloadToDelete.to,\n\t\t\t\tlength: payloadToDelete.to - payloadToDelete.from,\n\t\t\t\tduration: performance.now() - payloadToDelete.start,\n\t\t\t});\n\t\t\tthis.getOpsMap.delete(key!);\n\t\t}\n\t\tthis.getOpsMap.set(nonce, {\n\t\t\tstart,\n\t\t\tfrom,\n\t\t\tto,\n\t\t});\n\t\tthis.socket.emit(\"get_ops\", this.clientId, {\n\t\t\tnonce,\n\t\t\tfrom,\n\t\t\tto: to - 1,\n\t\t});\n\t}\n\n\tpublic async flush(): Promise<FlushResult> {\n\t\tassert(!this.socketReference?.disconnected, 0x414 /* non-active socket */);\n\n\t\t// back-compat: remove cast to any once latest version of IConnected is consumed\n\t\tif ((this.details as any).supportedFeatures?.[feature_flush_ops] !== true) {\n\t\t\t// Once single-commit summary is enabled end-to-end, flush support is a must!\n\t\t\t// The only alternative is change in design where SPO fetches ops from PUSH OR\n\t\t\t// summary includes required ops and SPO has some validation mechanism to ensure\n\t\t\t// they are not forged by client.\n\t\t\t// If design changes, we can reconsider it, but right now it's non-recoverable failure.\n\t\t\tthis.logger.sendErrorEvent({ eventName: \"FlushOpsNotSupported\" });\n\t\t\tthrow new Error(\n\t\t\t\t\"flush() API is not supported by PUSH, required for single-commit summaries\",\n\t\t\t);\n\t\t}\n\n\t\tthis.pushCallCounter++;\n\t\tconst nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;\n\t\t// There should be only one flush ops in flight, kicked out by upload summary workflow\n\t\t// That said, it could timeout and request could be repeated, so theoretically we can\n\t\t// get overlapping requests, but it should be very rare\n\t\tif (this.flushDeferred !== undefined) {\n\t\t\tthis.logger.sendErrorEvent({ eventName: \"FlushOpsTooMany\" });\n\t\t\tthis.flushDeferred.reject(\n\t\t\t\t\"process involving flush() was cancelled OR unsupported concurrency\",\n\t\t\t);\n\t\t}\n\t\tthis.socket.emit(\"flush_ops\", this.clientId, { nonce });\n\n\t\tthis.flushOpNonce = nonce;\n\t\tthis.flushDeferred = new Deferred<FlushResult>();\n\t\treturn this.flushDeferred.promise;\n\t}\n\n\tprotected disconnectHandler = (error: IFluidErrorBase & OdspError, clientId?: string) => {\n\t\tif (clientId === undefined || clientId === this.clientId) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: \"ServerDisconnect\",\n\t\t\t\t\tdriverVersion: pkgVersion,\n\t\t\t\t\tdetails: JSON.stringify({\n\t\t\t\t\t\t...this.getConnectionDetailsProps(),\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t\terror,\n\t\t\t);\n\t\t\tthis.disconnect(error);\n\t\t}\n\t};\n\n\tprotected async initialize(connectMessage: IConnect, timeout: number) {\n\t\tassert(!this.socketReference?.disconnected, 0x415 /* non-active socket */);\n\n\t\tif (this.enableMultiplexing) {\n\t\t\t// multiplex compatible early handlers\n\t\t\tthis.earlyOpHandler = (\n\t\t\t\tmessageDocumentId: string,\n\t\t\t\tmsgs: ISequencedDocumentMessage[],\n\t\t\t) => {\n\t\t\t\tif (this.documentId === messageDocumentId) {\n\t\t\t\t\tthis.queuedMessages.push(...msgs);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.earlySignalHandler = (msg: ISignalMessage, messageDocumentId?: string) => {\n\t\t\t\tif (messageDocumentId === undefined || messageDocumentId === this.documentId) {\n\t\t\t\t\tthis.queuedSignals.push(msg);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tthis.socketReference!.on(\"disconnect\", this.disconnectHandler);\n\n\t\tthis.socket.on(\"get_ops_response\", (result: IGetOpsResponse) => {\n\t\t\tconst messages = result.messages;\n\t\t\tconst data = this.getOpsMap.get(result.nonce);\n\t\t\t// Due to socket multiplexing, this client may not have asked for any data\n\t\t\t// If so, there it most likely does not need these ops (otherwise it already asked for them)\n\t\t\t// Also we may have deleted entry in this.getOpsMap due to too many requests and too slow response.\n\t\t\t// But not processing such result may push us into infinite loop of fast requests and dropping all responses\n\t\t\tif (data !== undefined || result.nonce.indexOf(this.requestOpsNoncePrefix) === 0) {\n\t\t\t\tthis.getOpsMap.delete(result.nonce);\n\t\t\t\tconst common = {\n\t\t\t\t\teventName: \"GetOps\",\n\t\t\t\t\t// We need nonce only to pair with GetOpsTooMany events, i.e. when record was deleted\n\t\t\t\t\tnonce: data === undefined ? result.nonce : undefined,\n\t\t\t\t\tcode: result.code,\n\t\t\t\t\tfrom: data?.from,\n\t\t\t\t\tto: data?.to,\n\t\t\t\t\tduration: data === undefined ? undefined : performance.now() - data.start,\n\t\t\t\t};\n\t\t\t\tif (messages !== undefined && messages.length > 0) {\n\t\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\t\t...common,\n\t\t\t\t\t\tfirst: messages[0].sequenceNumber,\n\t\t\t\t\t\tlast: messages[messages.length - 1].sequenceNumber,\n\t\t\t\t\t\tlength: messages.length,\n\t\t\t\t\t});\n\t\t\t\t\tthis.emit(\"op\", this.documentId, messages);\n\t\t\t\t} else {\n\t\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\t\t...common,\n\t\t\t\t\t\tlength: 0,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.socket.on(\"flush_ops_response\", (result: IFlushOpsResponse) => {\n\t\t\tif (this.flushOpNonce === result.nonce) {\n\t\t\t\tconst seq = result.lastPersistedSequenceNumber;\n\t\t\t\tlet category: \"generic\" | \"error\" = \"generic\";\n\t\t\t\tif (result.lastPersistedSequenceNumber === undefined || result.code !== 200) {\n\t\t\t\t\tswitch (result.code) {\n\t\t\t\t\t\tcase 409:\n\t\t\t\t\t\tcase 429:\n\t\t\t\t\t\t\tcategory = \"error\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 204:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tcategory = \"error\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"FlushResult\",\n\t\t\t\t\tcode: result.code,\n\t\t\t\t\tsequenceNumber: seq,\n\t\t\t\t\tcategory,\n\t\t\t\t});\n\t\t\t\tthis.flushDeferred!.resolve(result);\n\t\t\t\tthis.flushDeferred = undefined;\n\t\t\t\tthis.flushOpNonce = undefined;\n\t\t\t}\n\t\t});\n\n\t\tawait super.initialize(connectMessage, timeout).finally(() => {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"ConnectionAttemptInfo\",\n\t\t\t\t...this.getConnectionDetailsProps(),\n\t\t\t});\n\t\t});\n\t}\n\n\tprotected addTrackedListener(event: string, listener: (...args: any[]) => void) {\n\t\t// override some event listeners in order to support multiple documents/clients over the same websocket\n\t\tswitch (event) {\n\t\t\tcase \"op\":\n\t\t\t\t// per document op handling\n\t\t\t\tsuper.addTrackedListener(\n\t\t\t\t\tevent,\n\t\t\t\t\t(documentId: string, msgs: ISequencedDocumentMessage[]) => {\n\t\t\t\t\t\tif (!this.enableMultiplexing || this.documentId === documentId) {\n\t\t\t\t\t\t\tlistener(documentId, msgs);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase \"signal\":\n\t\t\t\t// per document signal handling\n\t\t\t\tsuper.addTrackedListener(event, (msg: ISignalMessage, documentId?: string) => {\n\t\t\t\t\tif (!this.enableMultiplexing || !documentId || documentId === this.documentId) {\n\t\t\t\t\t\tlistener(msg, documentId);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase \"nack\":\n\t\t\t\t// per client / document nack handling\n\t\t\t\tsuper.addTrackedListener(event, (clientIdOrDocumentId: string, nacks: INack[]) => {\n\t\t\t\t\tconst handle =\n\t\t\t\t\t\tclientIdOrDocumentId.length === 0 ||\n\t\t\t\t\t\tclientIdOrDocumentId === this.documentId ||\n\t\t\t\t\t\tclientIdOrDocumentId === this.clientId;\n\t\t\t\t\tconst { code, type, message, retryAfter } = nacks[0]?.content ?? {};\n\t\t\t\t\tconst { clientSequenceNumber, referenceSequenceNumber } =\n\t\t\t\t\t\tnacks[0]?.operation ?? {};\n\t\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"ServerNack\",\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\tmessage,\n\t\t\t\t\t\tretryAfterSeconds: retryAfter,\n\t\t\t\t\t\tclientId: this.clientId,\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\tclientSequenceNumber,\n\t\t\t\t\t\treferenceSequenceNumber,\n\t\t\t\t\t\topType: nacks[0]?.operation?.type,\n\t\t\t\t\t});\n\t\t\t\t\tif (handle) {\n\t\t\t\t\t\tthis.emit(\"nack\", clientIdOrDocumentId, nacks);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tsuper.addTrackedListener(event, listener);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tpublic get disposed() {\n\t\tif (!(this._disposed || this.socket.connected)) {\n\t\t\t// Send error event if this connection is not yet disposed after socket is disconnected for 15s.\n\t\t\tif (this.connectionNotYetDisposedTimeout === undefined) {\n\t\t\t\tthis.connectionNotYetDisposedTimeout = setTimeout(() => {\n\t\t\t\t\tif (!this._disposed) {\n\t\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\t\teventName: \"ConnectionNotYetDisposed\",\n\t\t\t\t\t\t\tdriverVersion: pkgVersion,\n\t\t\t\t\t\t\tdetails: JSON.stringify({\n\t\t\t\t\t\t\t\t...this.getConnectionDetailsProps(),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}, 15000);\n\t\t\t}\n\t\t}\n\t\treturn this._disposed;\n\t}\n\n\t/**\n\t * Returns true in case the connection is not yet disposed and the socket is also connected. The expectation is\n\t * that it will be called only after connection is fully established. i.e. there should no way to submit an op\n\t * while we are connecting, as connection object is not exposed to Loader layer until connection is established.\n\t */\n\tprivate get connected(): boolean {\n\t\treturn !this.disposed && this.socket.connected;\n\t}\n\n\tprotected emitMessages(type: string, messages: IDocumentMessage[][]) {\n\t\t// Only submit the op/signals if we are connected.\n\t\tif (this.connected) {\n\t\t\tthis.socket.emit(type, this.clientId, messages);\n\t\t}\n\t}\n\n\t/**\n\t * Submits a new delta operation to the server\n\t * @param message - delta operation to submit\n\t */\n\tpublic submit(messages: IDocumentMessage[]): void {\n\t\tthis.emitMessages(\"submitOp\", [messages]);\n\t}\n\n\t/**\n\t * Submits a new signal to the server\n\t *\n\t * @param message - signal to submit\n\t */\n\tpublic submitSignal(message: IDocumentMessage): void {\n\t\tthis.emitMessages(\"submitSignal\", [[message]]);\n\t}\n\n\t/**\n\t * Critical path where we need to also close the socket for an error.\n\t * @param error - Error causing the socket to close.\n\t */\n\tprotected closeSocketCore(error: IAnyDriverError) {\n\t\tconst socket = this.socketReference;\n\t\tassert(socket !== undefined, 0x416 /* reentrancy not supported in close socket */);\n\t\tsocket.closeSocket(error);\n\t\tassert(\n\t\t\tthis.socketReference === undefined,\n\t\t\t0x417 /* disconnect flow did not work correctly */,\n\t\t);\n\t}\n\n\t/**\n\t * Disconnect from the websocket\n\t */\n\tprotected disconnectCore() {\n\t\tconst socket = this.socketReference;\n\t\tassert(socket !== undefined, 0x0a2 /* \"reentrancy not supported!\" */);\n\t\tthis.socketReference = undefined;\n\n\t\tsocket.off(\"disconnect\", this.disconnectHandler);\n\t\tif (this.hasDetails) {\n\t\t\t// tell the server we are disconnecting this client from the document\n\t\t\tthis.socket.emit(\"disconnect_document\", this.clientId, this.documentId);\n\t\t}\n\n\t\tsocket.removeSocketIoReference();\n\t}\n}\n"]}
1
+ {"version":3,"file":"odspDocumentDeltaConnection.js","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.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 { IEvent } from \"@fluidframework/core-interfaces\";\nimport {\n\tITelemetryLoggerExt,\n\tIFluidErrorBase,\n\tloggerToMonitoringContext,\n} from \"@fluidframework/telemetry-utils\";\nimport { performance, TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { assert, Deferred } from \"@fluidframework/core-utils\";\nimport { DocumentDeltaConnection } from \"@fluidframework/driver-base\";\nimport { IAnyDriverError } from \"@fluidframework/driver-definitions\";\nimport { OdspError } from \"@fluidframework/odsp-driver-definitions\";\nimport {\n\tIClient,\n\tIConnect,\n\tIDocumentMessage,\n\tINack,\n\tISequencedDocumentMessage,\n\tISignalMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport { Socket } from \"socket.io-client\";\nimport { v4 as uuid } from \"uuid\";\nimport { createGenericNetworkError } from \"@fluidframework/driver-utils\";\nimport { IOdspSocketError, IGetOpsResponse, IFlushOpsResponse } from \"./contracts\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { errorObjectFromSocketError } from \"./odspError\";\nimport { SocketIOClientStatic } from \"./socketModule\";\nimport { pkgVersion } from \"./packageVersion\";\n\nconst protocolVersions = [\"^0.4.0\", \"^0.3.0\", \"^0.2.0\", \"^0.1.0\"];\nconst feature_get_ops = \"api_get_ops\";\nconst feature_flush_ops = \"api_flush_ops\";\n\nexport interface FlushResult {\n\tlastPersistedSequenceNumber?: number;\n\tretryAfter?: number;\n}\n\n// How long to wait before disconnecting the socket after the last reference is removed\n// This allows reconnection after receiving a nack to be smooth\nconst socketReferenceBufferTime = 2000;\n\ninterface ISocketEvents extends IEvent {\n\t(\n\t\tevent: \"disconnect\",\n\t\tlistener: (error: IFluidErrorBase & OdspError, clientId?: string) => void,\n\t);\n}\n\nclass SocketReference extends TypedEventEmitter<ISocketEvents> {\n\tprivate references: number = 1;\n\tprivate delayDeleteTimeout: ReturnType<typeof setTimeout> | undefined;\n\tprivate _socket: Socket | undefined;\n\n\t// When making decisions about socket reuse, we do not reuse disconnected socket.\n\t// But we want to differentiate the following case from disconnected case:\n\t// Socket that never connected and never failed, it's in \"attempting to connect\" mode\n\t// such sockets should be reused, despite socket.disconnected === true\n\tprivate isPendingInitialConnection = true;\n\n\t// Map of all existing socket io sockets. [url, tenantId, documentId] -> socket\n\tprivate static readonly socketIoSockets: Map<string, SocketReference> = new Map();\n\n\tpublic static find(key: string, logger: ITelemetryLoggerExt) {\n\t\tconst socketReference = SocketReference.socketIoSockets.get(key);\n\n\t\t// Verify the socket is healthy before reusing it\n\t\tif (socketReference?.disconnected) {\n\t\t\t// The socket is in a bad state. fully remove the reference\n\t\t\tsocketReference.closeSocket();\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (socketReference) {\n\t\t\t// Clear the pending deletion if there is one\n\t\t\tsocketReference.clearTimer();\n\t\t\tsocketReference.references++;\n\t\t}\n\n\t\treturn socketReference;\n\t}\n\n\t/**\n\t * Removes a reference for the given key\n\t * Once the ref count hits 0, the socket is disconnected and removed\n\t */\n\tpublic removeSocketIoReference() {\n\t\tassert(this.references > 0, 0x09f /* \"No more socketIO refs to remove!\" */);\n\t\tthis.references--;\n\n\t\t// see comment in disconnected() getter\n\t\tthis.isPendingInitialConnection = false;\n\n\t\tif (this.disconnected) {\n\t\t\tthis.closeSocket();\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.references === 0 && this.delayDeleteTimeout === undefined) {\n\t\t\tthis.delayDeleteTimeout = setTimeout(() => {\n\t\t\t\t// We should not get here with active users.\n\t\t\t\tassert(\n\t\t\t\t\tthis.references === 0,\n\t\t\t\t\t0x0a0 /* \"Unexpected socketIO references on timeout\" */,\n\t\t\t\t);\n\t\t\t\tthis.closeSocket();\n\t\t\t}, socketReferenceBufferTime);\n\t\t}\n\t}\n\n\tpublic get socket() {\n\t\tif (!this._socket) {\n\t\t\tthrow new Error(`Invalid socket for key \"${this.key}`);\n\t\t}\n\t\treturn this._socket;\n\t}\n\n\tpublic constructor(public readonly key: string, socket: Socket) {\n\t\tsuper();\n\n\t\tthis._socket = socket;\n\t\tassert(!SocketReference.socketIoSockets.has(key), 0x220 /* \"socket key collision\" */);\n\t\tSocketReference.socketIoSockets.set(key, this);\n\n\t\t// Server sends this event when it wants to disconnect a particular client in which case the client id would\n\t\t// be present or if it wants to disconnect all the clients. The server always closes the socket in case all\n\t\t// clients needs to be disconnected. So fully remove the socket reference in this case.\n\t\tsocket.on(\"server_disconnect\", this.serverDisconnectEventHandler);\n\t}\n\n\tprivate readonly serverDisconnectEventHandler = (\n\t\tsocketError: IOdspSocketError,\n\t\tclientId?: string,\n\t) => {\n\t\t// Treat all errors as recoverable, and rely on joinSession / reconnection flow to\n\t\t// filter out retryable vs. non-retryable cases.\n\t\tconst error = errorObjectFromSocketError(socketError, \"server_disconnect\");\n\t\terror.addTelemetryProperties({ disconnectClientId: clientId });\n\t\terror.canRetry = true;\n\n\t\t// see comment in disconnected() getter\n\t\t// Setting it here to ensure socket reuse does not happen if new request to connect\n\t\t// comes in from \"disconnect\" listener below, before we close socket.\n\t\tthis.isPendingInitialConnection = false;\n\n\t\tif (clientId === undefined) {\n\t\t\t// We could first raise \"disconnect\" event, but that may result in socket reuse due to\n\t\t\t// new connection comming in. So, it's better to have more explicit flow to make it impossible.\n\t\t\tthis.closeSocket(error);\n\t\t} else {\n\t\t\tthis.emit(\"disconnect\", error, clientId);\n\t\t}\n\t};\n\n\tprivate clearTimer() {\n\t\tif (this.delayDeleteTimeout !== undefined) {\n\t\t\tclearTimeout(this.delayDeleteTimeout);\n\t\t\tthis.delayDeleteTimeout = undefined;\n\t\t}\n\t}\n\n\tpublic closeSocket(error?: IAnyDriverError) {\n\t\tif (!this._socket) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._socket.off(\"server_disconnect\", this.serverDisconnectEventHandler);\n\t\tthis.clearTimer();\n\n\t\tassert(\n\t\t\tSocketReference.socketIoSockets.get(this.key) === this,\n\t\t\t0x0a1 /* \"Socket reference set unexpectedly does not point to this socket!\" */,\n\t\t);\n\n\t\t// First, remove socket to ensure no socket reuse is possible.\n\t\tSocketReference.socketIoSockets.delete(this.key);\n\n\t\t// Block access to socket. From now on, calls like flush() or requestOps()\n\t\t// Disconnect flow should be synchronous and result in system fully forgetting about this connection / socket.\n\t\tconst socket = this._socket;\n\t\tthis._socket = undefined;\n\n\t\t// Let all connections know they need to go through disconnect flow.\n\t\tthis.emit(\n\t\t\t\"disconnect\",\n\t\t\terror ??\n\t\t\t\tcreateGenericNetworkError(\n\t\t\t\t\t\"Socket closed without error\",\n\t\t\t\t\t{ canRetry: true },\n\t\t\t\t\t{ driverVersion: pkgVersion },\n\t\t\t\t),\n\t\t\tundefined /* clientId */,\n\t\t);\n\n\t\t// We should not have any users now, assuming synchronous disconnect flow in response to\n\t\t// \"disconnect\" event\n\t\tassert(\n\t\t\tthis.references === 0,\n\t\t\t0x412 /* Nobody should be connected to this socket at this point! */,\n\t\t);\n\n\t\tsocket.disconnect();\n\t}\n\n\tpublic get disconnected() {\n\t\tif (this._socket === undefined) {\n\t\t\treturn true;\n\t\t}\n\t\tif (this.socket.connected) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We have a socket that is not connected. Possible cases:\n\t\t// 1) It was connected some time ago and lost connection. We do not want to reuse it.\n\t\t// 2) It failed to connect (was never connected).\n\t\t// 3) It was just created and never had a chance to connect - connection is in process.\n\t\t// We have to differentiate 1 from 2-3 (specifically 1 & 3) in order to be able to reuse socket in #3.\n\t\t// We will use the fact that socket had some activity. I.e. if socket disconnected, or client stopped using\n\t\t// socket, then removeSocketIoReference() will be called for it, and it will be the indiction that it's not #3.\n\t\treturn !this.isPendingInitialConnection;\n\t}\n}\n\n/**\n * Represents a connection to a stream of delta updates\n */\nexport class OdspDocumentDeltaConnection extends DocumentDeltaConnection {\n\t/**\n\t * Create a OdspDocumentDeltaConnection\n\t * If url #1 fails to connect, will try url #2 if applicable.\n\t *\n\t * @param tenantId - the ID of the tenant\n\t * @param documentId - document ID\n\t * @param token - authorization token for storage service\n\t * @param client - information about the client\n\t * @param mode - mode of the client\n\t * @param url - websocket URL\n\t * @param telemetryLogger - optional telemetry logger\n\t * @param timeoutMs - time limit on making the connection\n\t * @param epochTracker - track epoch changes\n\t * @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache\n\t */\n\tpublic static async create(\n\t\ttenantId: string,\n\t\tdocumentId: string,\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\ttoken: string | null,\n\t\tclient: IClient,\n\t\turl: string,\n\t\ttelemetryLogger: ITelemetryLoggerExt,\n\t\ttimeoutMs: number,\n\t\tepochTracker: EpochTracker,\n\t\tsocketReferenceKeyPrefix: string | undefined,\n\t): Promise<OdspDocumentDeltaConnection> {\n\t\tconst mc = loggerToMonitoringContext(telemetryLogger);\n\n\t\t// enable multiplexing when the websocket url does not include the tenant/document id\n\t\tconst parsedUrl = new URL(url);\n\t\tconst enableMultiplexing =\n\t\t\t!parsedUrl.searchParams.has(\"documentId\") && !parsedUrl.searchParams.has(\"tenantId\");\n\n\t\t// do not include the specific tenant/doc id in the ref key when multiplexing\n\t\t// this will allow multiple documents to share the same websocket connection\n\t\tconst key = socketReferenceKeyPrefix ? `${socketReferenceKeyPrefix},${url}` : url;\n\t\tconst socketReferenceKey = enableMultiplexing ? key : `${key},${tenantId},${documentId}`;\n\n\t\tconst socketReference = OdspDocumentDeltaConnection.getOrCreateSocketIoReference(\n\t\t\ttimeoutMs,\n\t\t\tsocketReferenceKey,\n\t\t\turl,\n\t\t\tenableMultiplexing,\n\t\t\ttenantId,\n\t\t\tdocumentId,\n\t\t\ttelemetryLogger,\n\t\t);\n\n\t\tconst socket = socketReference.socket;\n\t\tconst connectionId = uuid();\n\t\tconst connectMessage: IConnect = {\n\t\t\tclient,\n\t\t\tid: documentId,\n\t\t\tmode: client.mode,\n\t\t\ttenantId,\n\t\t\ttoken, // Token is going to indicate tenant level information, etc...\n\t\t\tversions: protocolVersions,\n\t\t\tdriverVersion: pkgVersion,\n\t\t\tnonce: connectionId,\n\t\t\tepoch: epochTracker.fluidEpoch,\n\t\t\trelayUserAgent: [client.details.environment, ` driverVersion:${pkgVersion}`].join(\";\"),\n\t\t};\n\n\t\t// Reference to this client supporting get_ops flow.\n\t\tconnectMessage.supportedFeatures = {};\n\t\tif (mc.config.getBoolean(\"Fluid.Driver.Odsp.GetOpsEnabled\") !== false) {\n\t\t\tconnectMessage.supportedFeatures[feature_get_ops] = true;\n\t\t}\n\n\t\tconst deltaConnection = new OdspDocumentDeltaConnection(\n\t\t\tsocket,\n\t\t\tdocumentId,\n\t\t\tsocketReference,\n\t\t\ttelemetryLogger,\n\t\t\tenableMultiplexing,\n\t\t\tconnectionId,\n\t\t);\n\n\t\ttry {\n\t\t\tawait deltaConnection.initialize(connectMessage, timeoutMs);\n\t\t\tawait epochTracker.validateEpoch(deltaConnection.details.epoch, \"push\");\n\t\t} catch (errorObject: any) {\n\t\t\tif (errorObject !== null && typeof errorObject === \"object\") {\n\t\t\t\t// We have to special-case error types here in terms of what is re-triable.\n\t\t\t\t// These errors have to re-retried, we just need new joinSession result to connect to right server:\n\t\t\t\t// 400: Invalid tenant or document id. The WebSocket is connected to a different document\n\t\t\t\t// Document is full (with retryAfter)\n\t\t\t\t// 404: Invalid document. The document \\\"local/w1-...\\\" does not exist\n\t\t\t\t// But this has to stay not-retriable:\n\t\t\t\t// 406: Unsupported client protocol. This path is the only gatekeeper, have to fail!\n\t\t\t\t// 409: Epoch Version Mismatch. Client epoch and server epoch does not match, so app needs\n\t\t\t\t// to be refreshed.\n\t\t\t\t// This one is fine either way\n\t\t\t\t// 401/403: Code will retry once with new token either way, then it becomes fatal - on this path\n\t\t\t\t// and on join Session path.\n\t\t\t\t// 501: (Fluid not enabled): this is fine either way, as joinSession is gatekeeper\n\t\t\t\tif (errorObject.statusCode === 400 || errorObject.statusCode === 404) {\n\t\t\t\t\terrorObject.canRetry = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow errorObject;\n\t\t}\n\n\t\treturn deltaConnection;\n\t}\n\n\tprivate socketReference: SocketReference | undefined;\n\n\tprivate readonly requestOpsNoncePrefix: string;\n\tprivate pushCallCounter = 0;\n\tprivate readonly getOpsMap: Map<string, { start: number; from: number; to: number }> =\n\t\tnew Map();\n\tprivate flushOpNonce: string | undefined;\n\tprivate flushDeferred: Deferred<FlushResult> | undefined;\n\tprivate connectionNotYetDisposedTimeout: ReturnType<typeof setTimeout> | undefined;\n\n\t/**\n\t * Error raising for socket.io issues\n\t */\n\tprotected createErrorObject(handler: string, error?: any, canRetry = true): IAnyDriverError {\n\t\t// Note: we suspect the incoming error object is either:\n\t\t// - a socketError: add it to the OdspError object for driver to be able to parse it and reason over it.\n\t\t// - anything else: let base class handle it\n\t\treturn canRetry && Number.isInteger(error?.code) && typeof error?.message === \"string\"\n\t\t\t? errorObjectFromSocketError(error as IOdspSocketError, handler)\n\t\t\t: super.createErrorObject(handler, error, canRetry);\n\t}\n\n\t/**\n\t * Gets or create a socket io connection for the given key\n\t */\n\tprivate static getOrCreateSocketIoReference(\n\t\ttimeoutMs: number,\n\t\tkey: string,\n\t\turl: string,\n\t\tenableMultiplexing: boolean,\n\t\ttenantId: string,\n\t\tdocumentId: string,\n\t\tlogger: ITelemetryLoggerExt,\n\t): SocketReference {\n\t\tconst existingSocketReference = SocketReference.find(key, logger);\n\t\tif (existingSocketReference) {\n\t\t\treturn existingSocketReference;\n\t\t}\n\n\t\tconst query = enableMultiplexing ? undefined : { documentId, tenantId };\n\n\t\tconst socket = SocketIOClientStatic(url, {\n\t\t\tmultiplex: false, // Don't rely on socket.io built-in multiplexing\n\t\t\tquery,\n\t\t\treconnection: false,\n\t\t\ttransports: [\"websocket\"],\n\t\t\ttimeout: timeoutMs,\n\t\t});\n\n\t\treturn new SocketReference(key, socket);\n\t}\n\n\t/**\n\t * @param socket - websocket to be used\n\t * @param documentId - ID of the document\n\t * @param details - details of the websocket connection\n\t * @param socketReferenceKey - socket reference key\n\t * @param enableMultiplexing - If the websocket is multiplexing multiple documents\n\t */\n\tprivate constructor(\n\t\tsocket: Socket,\n\t\tdocumentId: string,\n\t\tsocketReference: SocketReference,\n\t\tlogger: ITelemetryLoggerExt,\n\t\tprivate readonly enableMultiplexing?: boolean,\n\t\tconnectionId?: string,\n\t) {\n\t\tsuper(socket, documentId, logger, false, connectionId);\n\t\tthis.socketReference = socketReference;\n\t\tthis.requestOpsNoncePrefix = `${uuid()}-`;\n\t}\n\n\t/**\n\t * Retrieves ops from PUSH\n\t * @param from - inclusive\n\t * @param to - exclusive\n\t * @returns ops retrieved\n\t */\n\tpublic requestOps(from: number, to: number) {\n\t\tassert(!this.socketReference?.disconnected, 0x413 /* non-active socket */);\n\n\t\t// Given that to is exclusive, we should be asking for at least something!\n\t\tassert(to > from, 0x272 /* \"empty request\" */);\n\n\t\t// PUSH may disable this functionality\n\t\t// back-compat: remove cast to any once latest version of IConnected is consumed\n\t\tif ((this.details as any).supportedFeatures?.[feature_get_ops] !== true) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.pushCallCounter++;\n\t\tconst nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;\n\t\tconst start = performance.now();\n\n\t\t// We may keep keep accumulating memory for nothing, if we are not getting responses.\n\t\t// Note that we should not have overlapping requests, as DeltaManager allows only one\n\t\t// outstanding request to storage, and that's the only way to get here.\n\t\t// But requests could be cancelled, and thus overlapping requests might be in the picture\n\t\t// If it happens, we do not care about stale requests.\n\t\t// So track some number of requests, but log if we get too many in flight - that likely\n\t\t// indicates an error somewhere.\n\t\tif (this.getOpsMap.size >= 5) {\n\t\t\tlet time = start;\n\t\t\tlet key: string | undefined;\n\t\t\tfor (const [keyCandidate, value] of this.getOpsMap.entries()) {\n\t\t\t\tif (value.start <= time || key === undefined) {\n\t\t\t\t\ttime = value.start;\n\t\t\t\t\tkey = keyCandidate;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst payloadToDelete = this.getOpsMap.get(key!)!;\n\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\teventName: \"GetOpsTooMany\",\n\t\t\t\tnonce,\n\t\t\t\tfrom: payloadToDelete.from,\n\t\t\t\tto: payloadToDelete.to,\n\t\t\t\tlength: payloadToDelete.to - payloadToDelete.from,\n\t\t\t\tduration: performance.now() - payloadToDelete.start,\n\t\t\t});\n\t\t\tthis.getOpsMap.delete(key!);\n\t\t}\n\t\tthis.getOpsMap.set(nonce, {\n\t\t\tstart,\n\t\t\tfrom,\n\t\t\tto,\n\t\t});\n\t\tthis.socket.emit(\"get_ops\", this.clientId, {\n\t\t\tnonce,\n\t\t\tfrom,\n\t\t\tto: to - 1,\n\t\t});\n\t}\n\n\tpublic async flush(): Promise<FlushResult> {\n\t\tassert(!this.socketReference?.disconnected, 0x414 /* non-active socket */);\n\n\t\t// back-compat: remove cast to any once latest version of IConnected is consumed\n\t\tif ((this.details as any).supportedFeatures?.[feature_flush_ops] !== true) {\n\t\t\t// Once single-commit summary is enabled end-to-end, flush support is a must!\n\t\t\t// The only alternative is change in design where SPO fetches ops from PUSH OR\n\t\t\t// summary includes required ops and SPO has some validation mechanism to ensure\n\t\t\t// they are not forged by client.\n\t\t\t// If design changes, we can reconsider it, but right now it's non-recoverable failure.\n\t\t\tthis.logger.sendErrorEvent({ eventName: \"FlushOpsNotSupported\" });\n\t\t\tthrow new Error(\n\t\t\t\t\"flush() API is not supported by PUSH, required for single-commit summaries\",\n\t\t\t);\n\t\t}\n\n\t\tthis.pushCallCounter++;\n\t\tconst nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;\n\t\t// There should be only one flush ops in flight, kicked out by upload summary workflow\n\t\t// That said, it could timeout and request could be repeated, so theoretically we can\n\t\t// get overlapping requests, but it should be very rare\n\t\tif (this.flushDeferred !== undefined) {\n\t\t\tthis.logger.sendErrorEvent({ eventName: \"FlushOpsTooMany\" });\n\t\t\tthis.flushDeferred.reject(\n\t\t\t\t\"process involving flush() was cancelled OR unsupported concurrency\",\n\t\t\t);\n\t\t}\n\t\tthis.socket.emit(\"flush_ops\", this.clientId, { nonce });\n\n\t\tthis.flushOpNonce = nonce;\n\t\tthis.flushDeferred = new Deferred<FlushResult>();\n\t\treturn this.flushDeferred.promise;\n\t}\n\n\tprotected disconnectHandler = (error: IFluidErrorBase & OdspError, clientId?: string) => {\n\t\tif (clientId === undefined || clientId === this.clientId) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: \"ServerDisconnect\",\n\t\t\t\t\tdriverVersion: pkgVersion,\n\t\t\t\t\tdetails: JSON.stringify({\n\t\t\t\t\t\t...this.getConnectionDetailsProps(),\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t\terror,\n\t\t\t);\n\t\t\tthis.disconnect(error);\n\t\t}\n\t};\n\n\tprotected async initialize(connectMessage: IConnect, timeout: number) {\n\t\tassert(!this.socketReference?.disconnected, 0x415 /* non-active socket */);\n\n\t\tif (this.enableMultiplexing) {\n\t\t\t// multiplex compatible early handlers\n\t\t\tthis.earlyOpHandler = (\n\t\t\t\tmessageDocumentId: string,\n\t\t\t\tmsgs: ISequencedDocumentMessage[],\n\t\t\t) => {\n\t\t\t\tif (this.documentId === messageDocumentId) {\n\t\t\t\t\tthis.queuedMessages.push(...msgs);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.earlySignalHandler = (msg: ISignalMessage, messageDocumentId?: string) => {\n\t\t\t\tif (messageDocumentId === undefined || messageDocumentId === this.documentId) {\n\t\t\t\t\tthis.queuedSignals.push(msg);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tthis.socketReference!.on(\"disconnect\", this.disconnectHandler);\n\n\t\tthis.addTrackedListener(\"get_ops_response\", (result: IGetOpsResponse) => {\n\t\t\tconst messages = result.messages;\n\t\t\tconst data = this.getOpsMap.get(result.nonce);\n\t\t\t// Due to socket multiplexing, this client may not have asked for any data\n\t\t\t// If so, there it most likely does not need these ops (otherwise it already asked for them)\n\t\t\t// Also we may have deleted entry in this.getOpsMap due to too many requests and too slow response.\n\t\t\t// But not processing such result may push us into infinite loop of fast requests and dropping all responses\n\t\t\tif (data !== undefined || result.nonce.startsWith(this.requestOpsNoncePrefix)) {\n\t\t\t\tthis.getOpsMap.delete(result.nonce);\n\t\t\t\tconst common = {\n\t\t\t\t\teventName: \"GetOps\",\n\t\t\t\t\t// We need nonce only to pair with GetOpsTooMany events, i.e. when record was deleted\n\t\t\t\t\tnonce: data === undefined ? result.nonce : undefined,\n\t\t\t\t\tcode: result.code,\n\t\t\t\t\tfrom: data?.from,\n\t\t\t\t\tto: data?.to,\n\t\t\t\t\tduration: data === undefined ? undefined : performance.now() - data.start,\n\t\t\t\t};\n\t\t\t\tif (messages !== undefined && messages.length > 0) {\n\t\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\t\t...common,\n\t\t\t\t\t\tfirst: messages[0].sequenceNumber,\n\t\t\t\t\t\tlast: messages[messages.length - 1].sequenceNumber,\n\t\t\t\t\t\tlength: messages.length,\n\t\t\t\t\t});\n\t\t\t\t\tthis.emit(\"op\", this.documentId, messages);\n\t\t\t\t} else {\n\t\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\t\t...common,\n\t\t\t\t\t\tlength: 0,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.addTrackedListener(\"flush_ops_response\", (result: IFlushOpsResponse) => {\n\t\t\tif (this.flushOpNonce === result.nonce) {\n\t\t\t\tconst seq = result.lastPersistedSequenceNumber;\n\t\t\t\tlet category: \"generic\" | \"error\" = \"generic\";\n\t\t\t\tif (result.lastPersistedSequenceNumber === undefined || result.code !== 200) {\n\t\t\t\t\tswitch (result.code) {\n\t\t\t\t\t\tcase 409:\n\t\t\t\t\t\tcase 429:\n\t\t\t\t\t\t\tcategory = \"error\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 204:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tcategory = \"error\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"FlushResult\",\n\t\t\t\t\tcode: result.code,\n\t\t\t\t\tsequenceNumber: seq,\n\t\t\t\t\tcategory,\n\t\t\t\t});\n\t\t\t\tthis.flushDeferred!.resolve(result);\n\t\t\t\tthis.flushDeferred = undefined;\n\t\t\t\tthis.flushOpNonce = undefined;\n\t\t\t}\n\t\t});\n\n\t\tawait super.initialize(connectMessage, timeout).finally(() => {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"ConnectionAttemptInfo\",\n\t\t\t\t...this.getConnectionDetailsProps(),\n\t\t\t});\n\t\t});\n\t}\n\n\tprotected addTrackedListener(event: string, listener: (...args: any[]) => void) {\n\t\t// override some event listeners in order to support multiple documents/clients over the same websocket\n\t\tswitch (event) {\n\t\t\tcase \"op\":\n\t\t\t\t// per document op handling\n\t\t\t\tsuper.addTrackedListener(\n\t\t\t\t\tevent,\n\t\t\t\t\t(documentId: string, msgs: ISequencedDocumentMessage[]) => {\n\t\t\t\t\t\tif (!this.enableMultiplexing || this.documentId === documentId) {\n\t\t\t\t\t\t\tlistener(documentId, msgs);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase \"signal\":\n\t\t\t\t// per document signal handling\n\t\t\t\tsuper.addTrackedListener(event, (msg: ISignalMessage, documentId?: string) => {\n\t\t\t\t\tif (!this.enableMultiplexing || !documentId || documentId === this.documentId) {\n\t\t\t\t\t\tlistener(msg, documentId);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase \"nack\":\n\t\t\t\t// per client / document nack handling\n\t\t\t\tsuper.addTrackedListener(event, (clientIdOrDocumentId: string, nacks: INack[]) => {\n\t\t\t\t\tconst handle =\n\t\t\t\t\t\tclientIdOrDocumentId.length === 0 ||\n\t\t\t\t\t\tclientIdOrDocumentId === this.documentId ||\n\t\t\t\t\t\tclientIdOrDocumentId === this.clientId;\n\t\t\t\t\tconst { code, type, message, retryAfter } = nacks[0]?.content ?? {};\n\t\t\t\t\tconst { clientSequenceNumber, referenceSequenceNumber } =\n\t\t\t\t\t\tnacks[0]?.operation ?? {};\n\t\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"ServerNack\",\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\tmessage,\n\t\t\t\t\t\tretryAfterSeconds: retryAfter,\n\t\t\t\t\t\tclientId: this.clientId,\n\t\t\t\t\t\thandle,\n\t\t\t\t\t\tclientSequenceNumber,\n\t\t\t\t\t\treferenceSequenceNumber,\n\t\t\t\t\t\topType: nacks[0]?.operation?.type,\n\t\t\t\t\t});\n\t\t\t\t\tif (handle) {\n\t\t\t\t\t\tthis.emit(\"nack\", clientIdOrDocumentId, nacks);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tsuper.addTrackedListener(event, listener);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tpublic get disposed() {\n\t\tif (!(this._disposed || this.socket.connected)) {\n\t\t\t// Send error event if this connection is not yet disposed after socket is disconnected for 15s.\n\t\t\tif (this.connectionNotYetDisposedTimeout === undefined) {\n\t\t\t\tthis.connectionNotYetDisposedTimeout = setTimeout(() => {\n\t\t\t\t\tif (!this._disposed) {\n\t\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\t\teventName: \"ConnectionNotYetDisposed\",\n\t\t\t\t\t\t\tdriverVersion: pkgVersion,\n\t\t\t\t\t\t\tdetails: JSON.stringify({\n\t\t\t\t\t\t\t\t...this.getConnectionDetailsProps(),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}, 15000);\n\t\t\t}\n\t\t}\n\t\treturn this._disposed;\n\t}\n\n\t/**\n\t * Returns true in case the connection is not yet disposed and the socket is also connected. The expectation is\n\t * that it will be called only after connection is fully established. i.e. there should no way to submit an op\n\t * while we are connecting, as connection object is not exposed to Loader layer until connection is established.\n\t */\n\tprivate get connected(): boolean {\n\t\treturn !this.disposed && this.socket.connected;\n\t}\n\n\tprotected emitMessages(type: string, messages: IDocumentMessage[][]) {\n\t\t// Only submit the op/signals if we are connected.\n\t\tif (this.connected) {\n\t\t\tthis.socket.emit(type, this.clientId, messages);\n\t\t}\n\t}\n\n\t/**\n\t * Submits a new delta operation to the server\n\t * @param message - delta operation to submit\n\t */\n\tpublic submit(messages: IDocumentMessage[]): void {\n\t\tthis.emitMessages(\"submitOp\", [messages]);\n\t}\n\n\t/**\n\t * Submits a new signal to the server\n\t *\n\t * @param message - signal to submit\n\t */\n\tpublic submitSignal(message: IDocumentMessage): void {\n\t\tthis.emitMessages(\"submitSignal\", [[message]]);\n\t}\n\n\t/**\n\t * Critical path where we need to also close the socket for an error.\n\t * @param error - Error causing the socket to close.\n\t */\n\tprotected closeSocketCore(error: IAnyDriverError) {\n\t\tconst socket = this.socketReference;\n\t\tassert(socket !== undefined, 0x416 /* reentrancy not supported in close socket */);\n\t\tsocket.closeSocket(error);\n\t\tassert(\n\t\t\tthis.socketReference === undefined,\n\t\t\t0x417 /* disconnect flow did not work correctly */,\n\t\t);\n\t}\n\n\t/**\n\t * Disconnect from the websocket\n\t */\n\tprotected disconnectCore() {\n\t\tconst socket = this.socketReference;\n\t\tassert(socket !== undefined, 0x0a2 /* \"reentrancy not supported!\" */);\n\t\tthis.socketReference = undefined;\n\n\t\tsocket.off(\"disconnect\", this.disconnectHandler);\n\t\tif (this.hasDetails) {\n\t\t\t// tell the server we are disconnecting this client from the document\n\t\t\tthis.socket.emit(\"disconnect_document\", this.clientId, this.documentId);\n\t\t}\n\n\t\tsocket.removeSocketIoReference();\n\t}\n}\n"]}