@fluidframework/routerlicious-driver 2.1.0-276326 → 2.1.0-281041

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 (117) hide show
  1. package/README.md +3 -1
  2. package/api-extractor/{api-extractor-lint-beta.cjs.json → api-extractor.current.json} +2 -2
  3. package/api-extractor/api-extractor.legacy.json +1 -1
  4. package/api-extractor.json +1 -1
  5. package/api-report/routerlicious-driver.legacy.public.api.md +22 -0
  6. package/dist/createNewUtils.d.ts.map +1 -1
  7. package/dist/createNewUtils.js +1 -3
  8. package/dist/createNewUtils.js.map +1 -1
  9. package/dist/deltaStorageService.js +1 -1
  10. package/dist/deltaStorageService.js.map +1 -1
  11. package/dist/documentService.d.ts.map +1 -1
  12. package/dist/documentService.js +5 -2
  13. package/dist/documentService.js.map +1 -1
  14. package/dist/documentServiceFactory.d.ts.map +1 -1
  15. package/dist/documentServiceFactory.js +6 -3
  16. package/dist/documentServiceFactory.js.map +1 -1
  17. package/dist/historian.d.ts.map +1 -1
  18. package/dist/historian.js.map +1 -1
  19. package/dist/legacy.d.ts +1 -1
  20. package/dist/packageVersion.d.ts +1 -1
  21. package/dist/packageVersion.js +1 -1
  22. package/dist/packageVersion.js.map +1 -1
  23. package/dist/public.d.ts +1 -1
  24. package/dist/queryStringUtils.d.ts +12 -0
  25. package/dist/queryStringUtils.d.ts.map +1 -0
  26. package/dist/queryStringUtils.js +25 -0
  27. package/dist/queryStringUtils.js.map +1 -0
  28. package/dist/r11sSnapshotParser.d.ts.map +1 -1
  29. package/dist/r11sSnapshotParser.js +4 -2
  30. package/dist/r11sSnapshotParser.js.map +1 -1
  31. package/dist/restWrapper.d.ts +9 -2
  32. package/dist/restWrapper.d.ts.map +1 -1
  33. package/dist/restWrapper.js +44 -13
  34. package/dist/restWrapper.js.map +1 -1
  35. package/dist/restWrapperBase.d.ts +27 -7
  36. package/dist/restWrapperBase.d.ts.map +1 -1
  37. package/dist/restWrapperBase.js +35 -27
  38. package/dist/restWrapperBase.js.map +1 -1
  39. package/dist/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
  40. package/dist/shreddedSummaryDocumentStorageService.js +4 -3
  41. package/dist/shreddedSummaryDocumentStorageService.js.map +1 -1
  42. package/dist/summaryTreeUploadManager.d.ts.map +1 -1
  43. package/dist/summaryTreeUploadManager.js +3 -3
  44. package/dist/summaryTreeUploadManager.js.map +1 -1
  45. package/dist/urlUtils.d.ts.map +1 -1
  46. package/dist/urlUtils.js +2 -0
  47. package/dist/urlUtils.js.map +1 -1
  48. package/dist/wholeSummaryDocumentStorageService.d.ts.map +1 -1
  49. package/dist/wholeSummaryDocumentStorageService.js +4 -3
  50. package/dist/wholeSummaryDocumentStorageService.js.map +1 -1
  51. package/internal.d.ts +1 -1
  52. package/legacy.d.ts +1 -1
  53. package/lib/createNewUtils.d.ts.map +1 -1
  54. package/lib/createNewUtils.js +1 -3
  55. package/lib/createNewUtils.js.map +1 -1
  56. package/lib/deltaStorageService.js +1 -1
  57. package/lib/deltaStorageService.js.map +1 -1
  58. package/lib/documentService.d.ts.map +1 -1
  59. package/lib/documentService.js +5 -2
  60. package/lib/documentService.js.map +1 -1
  61. package/lib/documentServiceFactory.d.ts.map +1 -1
  62. package/lib/documentServiceFactory.js +6 -3
  63. package/lib/documentServiceFactory.js.map +1 -1
  64. package/lib/historian.d.ts.map +1 -1
  65. package/lib/historian.js.map +1 -1
  66. package/lib/legacy.d.ts +1 -1
  67. package/lib/packageVersion.d.ts +1 -1
  68. package/lib/packageVersion.js +1 -1
  69. package/lib/packageVersion.js.map +1 -1
  70. package/lib/public.d.ts +1 -1
  71. package/lib/queryStringUtils.d.ts +12 -0
  72. package/lib/queryStringUtils.d.ts.map +1 -0
  73. package/lib/queryStringUtils.js +21 -0
  74. package/lib/queryStringUtils.js.map +1 -0
  75. package/lib/r11sSnapshotParser.d.ts.map +1 -1
  76. package/lib/r11sSnapshotParser.js +4 -2
  77. package/lib/r11sSnapshotParser.js.map +1 -1
  78. package/lib/restWrapper.d.ts +9 -2
  79. package/lib/restWrapper.d.ts.map +1 -1
  80. package/lib/restWrapper.js +44 -12
  81. package/lib/restWrapper.js.map +1 -1
  82. package/lib/restWrapperBase.d.ts +27 -7
  83. package/lib/restWrapperBase.d.ts.map +1 -1
  84. package/lib/restWrapperBase.js +34 -25
  85. package/lib/restWrapperBase.js.map +1 -1
  86. package/lib/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
  87. package/lib/shreddedSummaryDocumentStorageService.js +4 -3
  88. package/lib/shreddedSummaryDocumentStorageService.js.map +1 -1
  89. package/lib/summaryTreeUploadManager.d.ts.map +1 -1
  90. package/lib/summaryTreeUploadManager.js +3 -3
  91. package/lib/summaryTreeUploadManager.js.map +1 -1
  92. package/lib/urlUtils.d.ts.map +1 -1
  93. package/lib/urlUtils.js +2 -0
  94. package/lib/urlUtils.js.map +1 -1
  95. package/lib/wholeSummaryDocumentStorageService.d.ts.map +1 -1
  96. package/lib/wholeSummaryDocumentStorageService.js +4 -3
  97. package/lib/wholeSummaryDocumentStorageService.js.map +1 -1
  98. package/package.json +23 -33
  99. package/src/createNewUtils.ts +1 -4
  100. package/src/deltaStorageService.ts +1 -1
  101. package/src/documentService.ts +8 -5
  102. package/src/documentServiceFactory.ts +8 -5
  103. package/src/historian.ts +2 -1
  104. package/src/packageVersion.ts +1 -1
  105. package/src/queryStringUtils.ts +23 -0
  106. package/src/r11sSnapshotParser.ts +5 -3
  107. package/src/restWrapper.ts +78 -35
  108. package/src/restWrapperBase.ts +35 -32
  109. package/src/shreddedSummaryDocumentStorageService.ts +4 -3
  110. package/src/summaryTreeUploadManager.ts +4 -4
  111. package/src/urlUtils.ts +4 -2
  112. package/src/wholeSummaryDocumentStorageService.ts +4 -3
  113. package/tsconfig.json +0 -1
  114. package/api-extractor/api-extractor-lint-beta.esm.json +0 -5
  115. package/beta.d.ts +0 -11
  116. package/dist/beta.d.ts +0 -15
  117. package/lib/beta.d.ts +0 -15
@@ -1 +1 @@
1
- {"version":3,"file":"wholeSummaryDocumentStorageService.js","sourceRoot":"","sources":["../src/wholeSummaryDocumentStorageService.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 { Uint8ArrayToString, performance, stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { getW3CData, promiseRaceWithWinner } from \"@fluidframework/driver-base/internal\";\nimport { ISummaryHandle, ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport {\n\tIDocumentStorageService,\n\tIDocumentStorageServicePolicies,\n\tISummaryContext,\n\tICreateBlobResponse,\n\tISnapshotTree,\n\tIVersion,\n} from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tITelemetryLoggerExt,\n\tMonitoringContext,\n\tPerformanceEvent,\n\tcreateChildMonitoringContext,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { ICache, InMemoryCache } from \"./cache.js\";\nimport { INormalizedWholeSnapshot, IWholeFlatSnapshot } from \"./contracts.js\";\nimport { GitManager } from \"./gitManager.js\";\nimport { IRouterliciousDriverPolicies } from \"./policies.js\";\nimport { convertWholeFlatSnapshotToSnapshotTreeAndBlobs } from \"./r11sSnapshotParser.js\";\nimport { IR11sResponse } from \"./restWrapper.js\";\nimport { ISummaryUploadManager } from \"./storageContracts.js\";\nimport {\n\tconvertSnapshotAndBlobsToSummaryTree,\n\tevalBlobsAndTrees,\n\tvalidateBlobsAndTrees,\n} from \"./treeUtils.js\";\nimport { WholeSummaryUploadManager } from \"./wholeSummaryUploadManager.js\";\n\nconst latestSnapshotId: string = \"latest\";\n\nexport class WholeSummaryDocumentStorageService implements IDocumentStorageService {\n\tprivate readonly mc: MonitoringContext;\n\tprivate firstVersionsCall: boolean = true;\n\n\tprivate async getSummaryUploadManager(): Promise<ISummaryUploadManager> {\n\t\tconst manager = await this.getStorageManager();\n\t\treturn new WholeSummaryUploadManager(manager);\n\t}\n\n\tconstructor(\n\t\tprotected readonly id: string,\n\t\tprotected readonly manager: GitManager,\n\t\tprotected readonly logger: ITelemetryLoggerExt,\n\t\tpublic readonly policies: IDocumentStorageServicePolicies,\n\t\tprivate readonly driverPolicies?: IRouterliciousDriverPolicies,\n\t\tprivate readonly blobCache: ICache<ArrayBufferLike> = new InMemoryCache(),\n\t\tprivate readonly snapshotTreeCache: ICache<INormalizedWholeSnapshot> = new InMemoryCache(),\n\t\tprivate readonly noCacheGitManager?: GitManager,\n\t\tprivate readonly getStorageManager: (\n\t\t\tdisableCache?: boolean,\n\t\t) => Promise<GitManager> = async (disableCache) =>\n\t\t\tdisableCache && this.noCacheGitManager !== undefined\n\t\t\t\t? this.noCacheGitManager\n\t\t\t\t: this.manager,\n\t) {\n\t\tthis.mc = createChildMonitoringContext({\n\t\t\tlogger,\n\t\t});\n\t}\n\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n\t\tif (versionId !== this.id && versionId !== null) {\n\t\t\t// Blobs/Trees in this scenario will never have multiple versions, so return versionId as is\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: versionId,\n\t\t\t\t\ttreeId: undefined!,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\t// If this is the first versions call for the document, we know we will want the latest summary.\n\t\t// Fetch latest summary, cache it, and return its id.\n\t\tif (this.firstVersionsCall && count === 1) {\n\t\t\tconst normalizedSnapshotContents = await PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"ObtainSnapshot\",\n\t\t\t\t\tversionId: versionId ?? undefined,\n\t\t\t\t\tcount,\n\t\t\t\t\tenableDiscovery: this.driverPolicies?.enableDiscovery,\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tlet method: string;\n\t\t\t\t\tconst cachedSnapshotP = this.snapshotTreeCache.get(\n\t\t\t\t\t\tthis.getCacheKey(latestSnapshotId),\n\t\t\t\t\t);\n\n\t\t\t\t\tconst networkSnapshotP = !this.driverPolicies?.enableDiscovery\n\t\t\t\t\t\t? this.fetchSnapshotTree(latestSnapshotId, false, \"getVersions\")\n\t\t\t\t\t\t: this.fetchSnapshotTree(latestSnapshotId, true, \"getVersions\");\n\n\t\t\t\t\tconst promiseRaceWinner = await promiseRaceWithWinner([\n\t\t\t\t\t\tcachedSnapshotP.catch(() => undefined),\n\t\t\t\t\t\tnetworkSnapshotP.catch(() => undefined),\n\t\t\t\t\t]);\n\n\t\t\t\t\tlet retrievedSnapshot = promiseRaceWinner.value;\n\t\t\t\t\tmethod = promiseRaceWinner.index === 0 ? \"cache\" : \"network\";\n\n\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t// if network failed -> wait for cache ( then return network failure)\n\t\t\t\t\t\t// If cache returned empty or failed -> wait for network (success of failure)\n\t\t\t\t\t\tif (promiseRaceWinner.index === 1) {\n\t\t\t\t\t\t\tretrievedSnapshot = await cachedSnapshotP;\n\t\t\t\t\t\t\tmethod = \"cache\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\tretrievedSnapshot = await networkSnapshotP;\n\t\t\t\t\t\t\tmethod = \"network\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\tmethod,\n\t\t\t\t\t});\n\t\t\t\t\treturn retrievedSnapshot;\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst _id = await this.initializeFromSnapshot(normalizedSnapshotContents);\n\t\t\tthis.firstVersionsCall = false;\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: _id,\n\t\t\t\t\ttreeId: normalizedSnapshotContents.snapshotTree.id!,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\t// Otherwise, get the latest version of the document as normal.\n\t\tconst id = versionId ? versionId : this.id;\n\t\tconst commits = await PerformanceEvent.timedExecAsync(\n\t\t\tthis.logger,\n\t\t\t{\n\t\t\t\teventName: \"getVersions\",\n\t\t\t\tversionId: id,\n\t\t\t\tcount,\n\t\t\t},\n\t\t\tasync () => {\n\t\t\t\tconst manager = await this.getStorageManager();\n\t\t\t\treturn (await manager.getCommits(id, count)).content;\n\t\t\t},\n\t\t);\n\t\treturn commits.map((commit) => ({\n\t\t\tdate: commit.commit.author.date,\n\t\t\tid: commit.sha,\n\t\t\ttreeId: commit.commit.tree.sha,\n\t\t}));\n\t}\n\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\tlet requestVersion = version;\n\t\tif (!requestVersion) {\n\t\t\tconst versions = await this.getVersions(this.id, 1);\n\t\t\tif (versions.length === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\trequestVersion = versions[0];\n\t\t}\n\n\t\tlet normalizedWholeSnapshot = await this.snapshotTreeCache.get(\n\t\t\tthis.getCacheKey(requestVersion.id),\n\t\t);\n\t\tif (normalizedWholeSnapshot !== undefined) {\n\t\t\treturn normalizedWholeSnapshot.snapshotTree;\n\t\t}\n\n\t\tnormalizedWholeSnapshot = await this.fetchSnapshotTree(\n\t\t\trequestVersion.id,\n\t\t\tundefined,\n\t\t\t\"getSnapshotTree\",\n\t\t);\n\n\t\t// Currently retrieving blobs from network is not supported by AFR for WholeSummaryDocumentStorageService\n\t\t// Blobs are expected to be put in the cache\n\t\tawait this.updateBlobsCache(normalizedWholeSnapshot.blobs);\n\n\t\treturn normalizedWholeSnapshot.snapshotTree;\n\t}\n\n\tpublic async readBlob(blobId: string): Promise<ArrayBufferLike> {\n\t\tconst cachedBlob = await this.blobCache.get(this.getCacheKey(blobId));\n\t\tif (cachedBlob !== undefined) {\n\t\t\treturn cachedBlob;\n\t\t}\n\n\t\t// Note: AFR does not support readBlobs, but potentially other r11s like servers do\n\t\tconst blob = await PerformanceEvent.timedExecAsync(\n\t\t\tthis.logger,\n\t\t\t{\n\t\t\t\teventName: \"readBlob\",\n\t\t\t\tblobId,\n\t\t\t},\n\t\t\tasync (event) => {\n\t\t\t\tconst manager = await this.getStorageManager();\n\t\t\t\tconst response = (await manager.getBlob(blobId)).content;\n\t\t\t\tevent.end({\n\t\t\t\t\tsize: response.size,\n\t\t\t\t});\n\t\t\t\treturn response;\n\t\t\t},\n\t\t\tundefined, // workers\n\t\t\tthis.mc.config.getNumber(\"Fluid.Driver.ReadBlobTelemetrySampling\"),\n\t\t);\n\t\tconst bufferValue = stringToBuffer(blob.content, blob.encoding);\n\n\t\tawait this.blobCache.put(this.getCacheKey(blob.sha), bufferValue);\n\n\t\treturn bufferValue;\n\t}\n\n\tpublic async uploadSummaryWithContext(\n\t\tsummary: ISummaryTree,\n\t\tcontext: ISummaryContext,\n\t): Promise<string> {\n\t\tconst summaryHandle = await PerformanceEvent.timedExecAsync(\n\t\t\tthis.logger,\n\t\t\t{\n\t\t\t\teventName: \"uploadSummaryWithContext\",\n\t\t\t\tproposalHandle: context.proposalHandle,\n\t\t\t\tackHandle: context.ackHandle,\n\t\t\t\treferenceSequenceNumber: context.referenceSequenceNumber,\n\t\t\t},\n\t\t\tasync () => {\n\t\t\t\tconst summaryUploadManager = await this.getSummaryUploadManager();\n\t\t\t\treturn summaryUploadManager.writeSummaryTree(\n\t\t\t\t\tsummary,\n\t\t\t\t\tcontext.ackHandle ?? \"\",\n\t\t\t\t\t\"channel\",\n\t\t\t\t);\n\t\t\t},\n\t\t);\n\t\treturn summaryHandle;\n\t}\n\n\tpublic async downloadSummary(summaryHandle: ISummaryHandle): Promise<ISummaryTree> {\n\t\tconst wholeFlatSnapshot = await PerformanceEvent.timedExecAsync(\n\t\t\tthis.logger,\n\t\t\t{\n\t\t\t\teventName: \"getWholeFlatSummary\",\n\t\t\t\ttreeId: summaryHandle.handle,\n\t\t\t},\n\t\t\tasync (event) => {\n\t\t\t\tconst manager = await this.getStorageManager();\n\t\t\t\tconst response = await manager.getSnapshot(summaryHandle.handle);\n\t\t\t\tevent.end({\n\t\t\t\t\tsize: response.content.trees[0]?.entries.length,\n\t\t\t\t});\n\t\t\t\treturn response.content;\n\t\t\t},\n\t\t);\n\n\t\tconst { blobs, snapshotTree } = convertWholeFlatSnapshotToSnapshotTreeAndBlobs(\n\t\t\twholeFlatSnapshot,\n\t\t\t\"\",\n\t\t);\n\t\treturn convertSnapshotAndBlobsToSummaryTree(snapshotTree, blobs);\n\t}\n\n\tpublic async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n\t\tconst uint8ArrayFile = new Uint8Array(file);\n\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\tthis.logger,\n\t\t\t{\n\t\t\t\teventName: \"createBlob\",\n\t\t\t\tsize: uint8ArrayFile.length,\n\t\t\t},\n\t\t\tasync (event) => {\n\t\t\t\tconst manager = await this.getStorageManager();\n\t\t\t\tconst response = await manager\n\t\t\t\t\t.createBlob(Uint8ArrayToString(uint8ArrayFile, \"base64\"), \"base64\")\n\t\t\t\t\t.then((r) => ({ id: r.content.sha, url: r.content.url }));\n\t\t\t\tevent.end({\n\t\t\t\t\tblobId: response.id,\n\t\t\t\t});\n\t\t\t\treturn response;\n\t\t\t},\n\t\t);\n\t}\n\n\tprivate async fetchSnapshotTree(\n\t\tversionId: string,\n\t\tdisableCache?: boolean,\n\t\tscenarioName?: string,\n\t): Promise<INormalizedWholeSnapshot> {\n\t\tconst normalizedWholeSummary = await PerformanceEvent.timedExecAsync(\n\t\t\tthis.logger,\n\t\t\t{\n\t\t\t\teventName: \"getWholeFlatSummary\",\n\t\t\t\ttreeId: versionId,\n\t\t\t\tscenarioName,\n\t\t\t},\n\t\t\tasync (event) => {\n\t\t\t\tconst manager = await this.getStorageManager(disableCache);\n\t\t\t\tconst response: IR11sResponse<IWholeFlatSnapshot> =\n\t\t\t\t\tawait manager.getSnapshot(versionId);\n\t\t\t\tconst start = performance.now();\n\t\t\t\tconst snapshot: INormalizedWholeSnapshot =\n\t\t\t\t\tconvertWholeFlatSnapshotToSnapshotTreeAndBlobs(response.content);\n\t\t\t\tconst snapshotConversionTime = performance.now() - start;\n\t\t\t\tvalidateBlobsAndTrees(snapshot.snapshotTree);\n\t\t\t\tconst { trees, numBlobs, encodedBlobsSize } = evalBlobsAndTrees(snapshot);\n\n\t\t\t\tevent.end({\n\t\t\t\t\tsize: response.content.trees[0]?.entries.length,\n\t\t\t\t\ttrees,\n\t\t\t\t\tblobs: numBlobs,\n\t\t\t\t\tencodedBlobsSize,\n\t\t\t\t\tsequenceNumber: snapshot.sequenceNumber,\n\t\t\t\t\t...response.propsToLog,\n\t\t\t\t\tsnapshotConversionTime,\n\t\t\t\t\t...getW3CData(response.requestUrl, \"xmlhttprequest\"),\n\t\t\t\t});\n\t\t\t\treturn snapshot;\n\t\t\t},\n\t\t);\n\n\t\t// Also add the result into the cache.\n\t\tawait this.snapshotTreeCache\n\t\t\t.put(this.getCacheKey(versionId), normalizedWholeSummary)\n\t\t\t.catch(() => undefined);\n\t\treturn normalizedWholeSummary;\n\t}\n\n\tprivate async initializeFromSnapshot(\n\t\tnormalizedWholeSummary: INormalizedWholeSnapshot,\n\t): Promise<string> {\n\t\tconst snapshotId = normalizedWholeSummary.id;\n\t\tassert(snapshotId !== undefined, 0x275 /* \"Root tree should contain the id\" */);\n\t\tconst cachePs: Promise<any>[] = [\n\t\t\tthis.snapshotTreeCache.put(this.getCacheKey(snapshotId), normalizedWholeSummary),\n\t\t\tthis.updateBlobsCache(normalizedWholeSummary.blobs),\n\t\t];\n\n\t\tawait Promise.all(cachePs);\n\n\t\treturn snapshotId;\n\t}\n\n\tprivate async updateBlobsCache(blobs: Map<string, ArrayBuffer>): Promise<void> {\n\t\tconst blobCachePutPs: Promise<void>[] = [];\n\t\tblobs.forEach((value, id) => {\n\t\t\tconst cacheKey = this.getCacheKey(id);\n\t\t\tblobCachePutPs.push(this.blobCache.put(cacheKey, value));\n\t\t});\n\t\tawait Promise.all(blobCachePutPs);\n\t}\n\n\tprivate getCacheKey(blobId: string): string {\n\t\treturn `${this.id}:${blobId}`;\n\t}\n}\n"]}
1
+ {"version":3,"file":"wholeSummaryDocumentStorageService.js","sourceRoot":"","sources":["../src/wholeSummaryDocumentStorageService.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 { Uint8ArrayToString, performance, stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { getW3CData, promiseRaceWithWinner } from \"@fluidframework/driver-base/internal\";\nimport { ISummaryHandle, ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport {\n\tIDocumentStorageService,\n\tIDocumentStorageServicePolicies,\n\tISummaryContext,\n\tICreateBlobResponse,\n\tISnapshotTree,\n\tIVersion,\n} from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tITelemetryLoggerExt,\n\tMonitoringContext,\n\tPerformanceEvent,\n\tcreateChildMonitoringContext,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { ICache, InMemoryCache } from \"./cache.js\";\nimport { INormalizedWholeSnapshot, IWholeFlatSnapshot } from \"./contracts.js\";\nimport { GitManager } from \"./gitManager.js\";\nimport { IRouterliciousDriverPolicies } from \"./policies.js\";\nimport { convertWholeFlatSnapshotToSnapshotTreeAndBlobs } from \"./r11sSnapshotParser.js\";\nimport { IR11sResponse } from \"./restWrapper.js\";\nimport { ISummaryUploadManager } from \"./storageContracts.js\";\nimport {\n\tconvertSnapshotAndBlobsToSummaryTree,\n\tevalBlobsAndTrees,\n\tvalidateBlobsAndTrees,\n} from \"./treeUtils.js\";\nimport { WholeSummaryUploadManager } from \"./wholeSummaryUploadManager.js\";\n\nconst latestSnapshotId: string = \"latest\";\n\nexport class WholeSummaryDocumentStorageService implements IDocumentStorageService {\n\tprivate readonly mc: MonitoringContext;\n\tprivate firstVersionsCall: boolean = true;\n\n\tprivate async getSummaryUploadManager(): Promise<ISummaryUploadManager> {\n\t\tconst manager = await this.getStorageManager();\n\t\treturn new WholeSummaryUploadManager(manager);\n\t}\n\n\tconstructor(\n\t\tprotected readonly id: string,\n\t\tprotected readonly manager: GitManager,\n\t\tprotected readonly logger: ITelemetryLoggerExt,\n\t\tpublic readonly policies: IDocumentStorageServicePolicies,\n\t\tprivate readonly driverPolicies?: IRouterliciousDriverPolicies,\n\t\tprivate readonly blobCache: ICache<ArrayBufferLike> = new InMemoryCache(),\n\t\tprivate readonly snapshotTreeCache: ICache<INormalizedWholeSnapshot> = new InMemoryCache(),\n\t\tprivate readonly noCacheGitManager?: GitManager,\n\t\tprivate readonly getStorageManager: (\n\t\t\tdisableCache?: boolean,\n\t\t) => Promise<GitManager> = async (disableCache) =>\n\t\t\tdisableCache && this.noCacheGitManager !== undefined\n\t\t\t\t? this.noCacheGitManager\n\t\t\t\t: this.manager,\n\t) {\n\t\tthis.mc = createChildMonitoringContext({\n\t\t\tlogger,\n\t\t});\n\t}\n\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n\t\tif (versionId !== this.id && versionId !== null) {\n\t\t\t// Blobs/Trees in this scenario will never have multiple versions, so return versionId as is\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: versionId,\n\t\t\t\t\ttreeId: undefined!,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\t// If this is the first versions call for the document, we know we will want the latest summary.\n\t\t// Fetch latest summary, cache it, and return its id.\n\t\tif (this.firstVersionsCall && count === 1) {\n\t\t\tconst normalizedSnapshotContents = await PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"ObtainSnapshot\",\n\t\t\t\t\tversionId: versionId ?? undefined,\n\t\t\t\t\tcount,\n\t\t\t\t\tenableDiscovery: this.driverPolicies?.enableDiscovery,\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tlet method: string;\n\t\t\t\t\tconst cachedSnapshotP = this.snapshotTreeCache.get(\n\t\t\t\t\t\tthis.getCacheKey(latestSnapshotId),\n\t\t\t\t\t);\n\n\t\t\t\t\tconst networkSnapshotP = !this.driverPolicies?.enableDiscovery\n\t\t\t\t\t\t? this.fetchSnapshotTree(latestSnapshotId, false, \"getVersions\")\n\t\t\t\t\t\t: this.fetchSnapshotTree(latestSnapshotId, true, \"getVersions\");\n\n\t\t\t\t\tconst promiseRaceWinner = await promiseRaceWithWinner([\n\t\t\t\t\t\tcachedSnapshotP.catch(() => undefined),\n\t\t\t\t\t\tnetworkSnapshotP.catch(() => undefined),\n\t\t\t\t\t]);\n\n\t\t\t\t\tlet retrievedSnapshot = promiseRaceWinner.value;\n\t\t\t\t\tmethod = promiseRaceWinner.index === 0 ? \"cache\" : \"network\";\n\n\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t// if network failed -> wait for cache ( then return network failure)\n\t\t\t\t\t\t// If cache returned empty or failed -> wait for network (success of failure)\n\t\t\t\t\t\tif (promiseRaceWinner.index === 1) {\n\t\t\t\t\t\t\tretrievedSnapshot = await cachedSnapshotP;\n\t\t\t\t\t\t\tmethod = \"cache\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\tretrievedSnapshot = await networkSnapshotP;\n\t\t\t\t\t\t\tmethod = \"network\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\tmethod,\n\t\t\t\t\t});\n\t\t\t\t\treturn retrievedSnapshot;\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst _id = await this.initializeFromSnapshot(normalizedSnapshotContents);\n\t\t\tthis.firstVersionsCall = false;\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: _id,\n\t\t\t\t\ttreeId: normalizedSnapshotContents.snapshotTree.id!,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\t// Otherwise, get the latest version of the document as normal.\n\t\tconst id = versionId ? versionId : this.id;\n\t\tconst commits = await PerformanceEvent.timedExecAsync(\n\t\t\tthis.logger,\n\t\t\t{\n\t\t\t\teventName: \"getVersions\",\n\t\t\t\tversionId: id,\n\t\t\t\tcount,\n\t\t\t},\n\t\t\tasync () => {\n\t\t\t\tconst manager = await this.getStorageManager();\n\t\t\t\treturn (await manager.getCommits(id, count)).content;\n\t\t\t},\n\t\t);\n\t\treturn commits.map((commit) => ({\n\t\t\tdate: commit.commit.author.date,\n\t\t\tid: commit.sha,\n\t\t\ttreeId: commit.commit.tree.sha,\n\t\t}));\n\t}\n\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\tlet requestVersion = version;\n\t\tif (requestVersion === undefined) {\n\t\t\tconst versions = await this.getVersions(this.id, 1);\n\t\t\tconst firstVersion = versions[0];\n\t\t\tif (firstVersion === undefined) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\trequestVersion = firstVersion;\n\t\t}\n\n\t\tlet normalizedWholeSnapshot = await this.snapshotTreeCache.get(\n\t\t\tthis.getCacheKey(requestVersion.id),\n\t\t);\n\t\tif (normalizedWholeSnapshot !== undefined) {\n\t\t\treturn normalizedWholeSnapshot.snapshotTree;\n\t\t}\n\n\t\tnormalizedWholeSnapshot = await this.fetchSnapshotTree(\n\t\t\trequestVersion.id,\n\t\t\tundefined,\n\t\t\t\"getSnapshotTree\",\n\t\t);\n\n\t\t// Currently retrieving blobs from network is not supported by AFR for WholeSummaryDocumentStorageService\n\t\t// Blobs are expected to be put in the cache\n\t\tawait this.updateBlobsCache(normalizedWholeSnapshot.blobs);\n\n\t\treturn normalizedWholeSnapshot.snapshotTree;\n\t}\n\n\tpublic async readBlob(blobId: string): Promise<ArrayBufferLike> {\n\t\tconst cachedBlob = await this.blobCache.get(this.getCacheKey(blobId));\n\t\tif (cachedBlob !== undefined) {\n\t\t\treturn cachedBlob;\n\t\t}\n\n\t\t// Note: AFR does not support readBlobs, but potentially other r11s like servers do\n\t\tconst blob = await PerformanceEvent.timedExecAsync(\n\t\t\tthis.logger,\n\t\t\t{\n\t\t\t\teventName: \"readBlob\",\n\t\t\t\tblobId,\n\t\t\t},\n\t\t\tasync (event) => {\n\t\t\t\tconst manager = await this.getStorageManager();\n\t\t\t\tconst response = (await manager.getBlob(blobId)).content;\n\t\t\t\tevent.end({\n\t\t\t\t\tsize: response.size,\n\t\t\t\t});\n\t\t\t\treturn response;\n\t\t\t},\n\t\t\tundefined, // workers\n\t\t\tthis.mc.config.getNumber(\"Fluid.Driver.ReadBlobTelemetrySampling\"),\n\t\t);\n\t\tconst bufferValue = stringToBuffer(blob.content, blob.encoding);\n\n\t\tawait this.blobCache.put(this.getCacheKey(blob.sha), bufferValue);\n\n\t\treturn bufferValue;\n\t}\n\n\tpublic async uploadSummaryWithContext(\n\t\tsummary: ISummaryTree,\n\t\tcontext: ISummaryContext,\n\t): Promise<string> {\n\t\tconst summaryHandle = await PerformanceEvent.timedExecAsync(\n\t\t\tthis.logger,\n\t\t\t{\n\t\t\t\teventName: \"uploadSummaryWithContext\",\n\t\t\t\tproposalHandle: context.proposalHandle,\n\t\t\t\tackHandle: context.ackHandle,\n\t\t\t\treferenceSequenceNumber: context.referenceSequenceNumber,\n\t\t\t},\n\t\t\tasync () => {\n\t\t\t\tconst summaryUploadManager = await this.getSummaryUploadManager();\n\t\t\t\treturn summaryUploadManager.writeSummaryTree(\n\t\t\t\t\tsummary,\n\t\t\t\t\tcontext.ackHandle ?? \"\",\n\t\t\t\t\t\"channel\",\n\t\t\t\t);\n\t\t\t},\n\t\t);\n\t\treturn summaryHandle;\n\t}\n\n\tpublic async downloadSummary(summaryHandle: ISummaryHandle): Promise<ISummaryTree> {\n\t\tconst wholeFlatSnapshot = await PerformanceEvent.timedExecAsync(\n\t\t\tthis.logger,\n\t\t\t{\n\t\t\t\teventName: \"getWholeFlatSummary\",\n\t\t\t\ttreeId: summaryHandle.handle,\n\t\t\t},\n\t\t\tasync (event) => {\n\t\t\t\tconst manager = await this.getStorageManager();\n\t\t\t\tconst response = await manager.getSnapshot(summaryHandle.handle);\n\t\t\t\tevent.end({\n\t\t\t\t\tsize: response.content.trees[0]?.entries.length,\n\t\t\t\t});\n\t\t\t\treturn response.content;\n\t\t\t},\n\t\t);\n\n\t\tconst { blobs, snapshotTree } = convertWholeFlatSnapshotToSnapshotTreeAndBlobs(\n\t\t\twholeFlatSnapshot,\n\t\t\t\"\",\n\t\t);\n\t\treturn convertSnapshotAndBlobsToSummaryTree(snapshotTree, blobs);\n\t}\n\n\tpublic async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n\t\tconst uint8ArrayFile = new Uint8Array(file);\n\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\tthis.logger,\n\t\t\t{\n\t\t\t\teventName: \"createBlob\",\n\t\t\t\tsize: uint8ArrayFile.length,\n\t\t\t},\n\t\t\tasync (event) => {\n\t\t\t\tconst manager = await this.getStorageManager();\n\t\t\t\tconst response = await manager\n\t\t\t\t\t.createBlob(Uint8ArrayToString(uint8ArrayFile, \"base64\"), \"base64\")\n\t\t\t\t\t.then((r) => ({ id: r.content.sha, url: r.content.url }));\n\t\t\t\tevent.end({\n\t\t\t\t\tblobId: response.id,\n\t\t\t\t});\n\t\t\t\treturn response;\n\t\t\t},\n\t\t);\n\t}\n\n\tprivate async fetchSnapshotTree(\n\t\tversionId: string,\n\t\tdisableCache?: boolean,\n\t\tscenarioName?: string,\n\t): Promise<INormalizedWholeSnapshot> {\n\t\tconst normalizedWholeSummary = await PerformanceEvent.timedExecAsync(\n\t\t\tthis.logger,\n\t\t\t{\n\t\t\t\teventName: \"getWholeFlatSummary\",\n\t\t\t\ttreeId: versionId,\n\t\t\t\tscenarioName,\n\t\t\t},\n\t\t\tasync (event) => {\n\t\t\t\tconst manager = await this.getStorageManager(disableCache);\n\t\t\t\tconst response: IR11sResponse<IWholeFlatSnapshot> =\n\t\t\t\t\tawait manager.getSnapshot(versionId);\n\t\t\t\tconst start = performance.now();\n\t\t\t\tconst snapshot: INormalizedWholeSnapshot =\n\t\t\t\t\tconvertWholeFlatSnapshotToSnapshotTreeAndBlobs(response.content);\n\t\t\t\tconst snapshotConversionTime = performance.now() - start;\n\t\t\t\tvalidateBlobsAndTrees(snapshot.snapshotTree);\n\t\t\t\tconst { trees, numBlobs, encodedBlobsSize } = evalBlobsAndTrees(snapshot);\n\n\t\t\t\tevent.end({\n\t\t\t\t\tsize: response.content.trees[0]?.entries.length,\n\t\t\t\t\ttrees,\n\t\t\t\t\tblobs: numBlobs,\n\t\t\t\t\tencodedBlobsSize,\n\t\t\t\t\tsequenceNumber: snapshot.sequenceNumber,\n\t\t\t\t\t...response.propsToLog,\n\t\t\t\t\tsnapshotConversionTime,\n\t\t\t\t\t...getW3CData(response.requestUrl, \"xmlhttprequest\"),\n\t\t\t\t});\n\t\t\t\treturn snapshot;\n\t\t\t},\n\t\t);\n\n\t\t// Also add the result into the cache.\n\t\tawait this.snapshotTreeCache\n\t\t\t.put(this.getCacheKey(versionId), normalizedWholeSummary)\n\t\t\t.catch(() => undefined);\n\t\treturn normalizedWholeSummary;\n\t}\n\n\tprivate async initializeFromSnapshot(\n\t\tnormalizedWholeSummary: INormalizedWholeSnapshot,\n\t): Promise<string> {\n\t\tconst snapshotId = normalizedWholeSummary.id;\n\t\tassert(snapshotId !== undefined, 0x275 /* \"Root tree should contain the id\" */);\n\t\tconst cachePs: Promise<any>[] = [\n\t\t\tthis.snapshotTreeCache.put(this.getCacheKey(snapshotId), normalizedWholeSummary),\n\t\t\tthis.updateBlobsCache(normalizedWholeSummary.blobs),\n\t\t];\n\n\t\tawait Promise.all(cachePs);\n\n\t\treturn snapshotId;\n\t}\n\n\tprivate async updateBlobsCache(blobs: Map<string, ArrayBuffer>): Promise<void> {\n\t\tconst blobCachePutPs: Promise<void>[] = [];\n\t\tblobs.forEach((value, id) => {\n\t\t\tconst cacheKey = this.getCacheKey(id);\n\t\t\tblobCachePutPs.push(this.blobCache.put(cacheKey, value));\n\t\t});\n\t\tawait Promise.all(blobCachePutPs);\n\t}\n\n\tprivate getCacheKey(blobId: string): string {\n\t\treturn `${this.id}:${blobId}`;\n\t}\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/routerlicious-driver",
3
- "version": "2.1.0-276326",
3
+ "version": "2.1.0-281041",
4
4
  "description": "Socket.IO + Git implementation of Fluid service API",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -23,16 +23,6 @@
23
23
  "default": "./dist/index.js"
24
24
  }
25
25
  },
26
- "./beta": {
27
- "import": {
28
- "types": "./lib/beta.d.ts",
29
- "default": "./lib/index.js"
30
- },
31
- "require": {
32
- "types": "./dist/beta.d.ts",
33
- "default": "./dist/index.js"
34
- }
35
- },
36
26
  "./legacy": {
37
27
  "import": {
38
28
  "types": "./lib/legacy.d.ts",
@@ -77,14 +67,14 @@
77
67
  "temp-directory": "nyc/.nyc_output"
78
68
  },
79
69
  "dependencies": {
80
- "@fluid-internal/client-utils": "2.1.0-276326",
81
- "@fluidframework/core-interfaces": "2.1.0-276326",
82
- "@fluidframework/core-utils": "2.1.0-276326",
83
- "@fluidframework/driver-base": "2.1.0-276326",
84
- "@fluidframework/driver-definitions": "2.1.0-276326",
85
- "@fluidframework/driver-utils": "2.1.0-276326",
70
+ "@fluid-internal/client-utils": "2.1.0-281041",
71
+ "@fluidframework/core-interfaces": "2.1.0-281041",
72
+ "@fluidframework/core-utils": "2.1.0-281041",
73
+ "@fluidframework/driver-base": "2.1.0-281041",
74
+ "@fluidframework/driver-definitions": "2.1.0-281041",
75
+ "@fluidframework/driver-utils": "2.1.0-281041",
86
76
  "@fluidframework/server-services-client": "^5.0.0",
87
- "@fluidframework/telemetry-utils": "2.1.0-276326",
77
+ "@fluidframework/telemetry-utils": "2.1.0-281041",
88
78
  "cross-fetch": "^3.1.5",
89
79
  "json-stringify-safe": "5.0.1",
90
80
  "socket.io-client": "^4.7.3",
@@ -92,13 +82,13 @@
92
82
  },
93
83
  "devDependencies": {
94
84
  "@arethetypeswrong/cli": "^0.15.2",
95
- "@biomejs/biome": "^1.7.3",
96
- "@fluid-internal/mocha-test-setup": "2.1.0-276326",
97
- "@fluid-tools/build-cli": "^0.39.0",
85
+ "@biomejs/biome": "~1.8.3",
86
+ "@fluid-internal/mocha-test-setup": "2.1.0-281041",
87
+ "@fluid-tools/build-cli": "^0.40.0",
98
88
  "@fluidframework/build-common": "^2.0.3",
99
- "@fluidframework/build-tools": "^0.39.0",
89
+ "@fluidframework/build-tools": "^0.40.0",
100
90
  "@fluidframework/eslint-config-fluid": "^5.3.0",
101
- "@fluidframework/routerlicious-driver-previous": "npm:@fluidframework/routerlicious-driver@2.0.0-rc.5.0.0",
91
+ "@fluidframework/routerlicious-driver-previous": "npm:@fluidframework/routerlicious-driver@2.0.0",
102
92
  "@microsoft/api-extractor": "^7.45.1",
103
93
  "@types/mocha": "^9.1.1",
104
94
  "@types/nock": "^9.3.0",
@@ -129,36 +119,36 @@
129
119
  "api-extractor:commonjs": "flub generate entrypoints --outDir ./dist",
130
120
  "api-extractor:esnext": "flub generate entrypoints --outDir ./lib --node10TypeCompat",
131
121
  "build": "fluid-build . --task build",
122
+ "build:api-reports": "concurrently \"npm:build:api-reports:*\"",
123
+ "build:api-reports:current": "api-extractor run --local --config api-extractor/api-extractor.current.json",
124
+ "build:api-reports:legacy": "api-extractor run --local --config api-extractor/api-extractor.legacy.json",
132
125
  "build:commonjs": "fluid-build . --task commonjs",
133
126
  "build:compile": "fluid-build . --task compile",
134
- "build:docs": "concurrently \"npm:build:docs:*\"",
135
- "build:docs:current": "api-extractor run --local",
136
- "build:docs:legacy": "api-extractor run --local --config api-extractor/api-extractor.legacy.json",
127
+ "build:docs": "api-extractor run --local",
137
128
  "build:esnext": "tsc --project ./tsconfig.json",
138
129
  "build:genver": "gen-version",
139
130
  "build:test": "npm run build:test:esm && npm run build:test:cjs",
140
131
  "build:test:cjs": "fluid-tsc commonjs --project ./src/test/tsconfig.cjs.json",
141
132
  "build:test:esm": "tsc --project ./src/test/tsconfig.json",
142
133
  "check:are-the-types-wrong": "attw --pack .",
143
- "check:biome": "biome check . --formatter-enabled=true",
134
+ "check:biome": "biome check .",
144
135
  "check:exports": "concurrently \"npm:check:exports:*\"",
145
136
  "check:exports:bundle-release-tags": "api-extractor run --config api-extractor/api-extractor-lint-bundle.json",
146
- "check:exports:cjs:beta": "api-extractor run --config api-extractor/api-extractor-lint-beta.cjs.json",
147
137
  "check:exports:cjs:legacy": "api-extractor run --config api-extractor/api-extractor-lint-legacy.cjs.json",
148
138
  "check:exports:cjs:public": "api-extractor run --config api-extractor/api-extractor-lint-public.cjs.json",
149
- "check:exports:esm:beta": "api-extractor run --config api-extractor/api-extractor-lint-beta.esm.json",
150
139
  "check:exports:esm:legacy": "api-extractor run --config api-extractor/api-extractor-lint-legacy.esm.json",
151
140
  "check:exports:esm:public": "api-extractor run --config api-extractor/api-extractor-lint-public.esm.json",
152
141
  "check:format": "npm run check:biome",
153
142
  "check:prettier": "prettier --check . --cache --ignore-path ../../../.prettierignore",
154
- "ci:build:docs": "concurrently \"npm:ci:build:docs:*\"",
155
- "ci:build:docs:current": "api-extractor run",
156
- "ci:build:docs:legacy": "api-extractor run --config api-extractor/api-extractor.legacy.json",
143
+ "ci:build:api-reports": "concurrently \"npm:ci:build:api-reports:*\"",
144
+ "ci:build:api-reports:current": "api-extractor run --config api-extractor/api-extractor.current.json",
145
+ "ci:build:api-reports:legacy": "api-extractor run --config api-extractor/api-extractor.legacy.json",
146
+ "ci:build:docs": "api-extractor run",
157
147
  "clean": "rimraf --glob dist lib \"*.d.ts\" \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
158
148
  "eslint": "eslint --format stylish src",
159
149
  "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
160
150
  "format": "npm run format:biome",
161
- "format:biome": "biome check . --formatter-enabled=true --apply",
151
+ "format:biome": "biome check . --write",
162
152
  "format:prettier": "prettier --write . --cache --ignore-path ../../../.prettierignore",
163
153
  "lint": "fluid-build . --task lint",
164
154
  "lint:fix": "fluid-build . --task eslint:fix --task format",
@@ -12,10 +12,7 @@ import { ISummaryTree, SummaryType } from "@fluidframework/driver-definitions";
12
12
  * @returns Modified summary tree where the blob contents could be utf8 string only.
13
13
  */
14
14
  export function convertSummaryToCreateNewSummary(summary: ISummaryTree): ISummaryTree {
15
- const keys = Object.keys(summary.tree);
16
- for (const key of keys) {
17
- const summaryObject = summary.tree[key];
18
-
15
+ for (const [key, summaryObject] of Object.entries(summary.tree)) {
19
16
  switch (summaryObject.type) {
20
17
  case SummaryType.Tree: {
21
18
  summary.tree[key] = convertSummaryToCreateNewSummary(summaryObject);
@@ -83,7 +83,7 @@ export class DocumentDeltaStorageService implements IDocumentDeltaStorageService
83
83
  (op) => op.sequenceNumber >= from && op.sequenceNumber < to,
84
84
  );
85
85
  validateMessages("snapshotOps", messages, from, this.logger, false /* strict */);
86
- if (messages.length > 0 && messages[0].sequenceNumber === from) {
86
+ if (messages.length > 0 && messages[0] && messages[0].sequenceNumber === from) {
87
87
  this.snapshotOps = this.snapshotOps.filter((op) => op.sequenceNumber >= to);
88
88
  opsFromSnapshot += messages.length;
89
89
  return { messages, partialResult: true };
@@ -143,7 +143,7 @@ export class DocumentService
143
143
  this.logger,
144
144
  rateLimiter,
145
145
  this.driverPolicies.enableRestLess,
146
- this.storageUrl,
146
+ this.storageUrl /* baseUrl */,
147
147
  );
148
148
  }
149
149
  const historian = new Historian(true, false, this.storageRestWrapper);
@@ -327,10 +327,13 @@ export class DocumentService
327
327
  private async refreshDiscoveryCore(): Promise<void> {
328
328
  const fluidResolvedUrl = await this.discoverFluidResolvedUrl();
329
329
  this._resolvedUrl = fluidResolvedUrl;
330
- this.storageUrl = fluidResolvedUrl.endpoints.storageUrl;
331
- this.ordererUrl = fluidResolvedUrl.endpoints.ordererUrl;
332
- this.deltaStorageUrl = fluidResolvedUrl.endpoints.deltaStorageUrl;
333
- this.deltaStreamUrl = fluidResolvedUrl.endpoints.deltaStreamUrl || this.ordererUrl;
330
+ // TODO why are we non null asserting here?
331
+ this.storageUrl = fluidResolvedUrl.endpoints.storageUrl!;
332
+ // TODO why are we non null asserting here?
333
+ this.ordererUrl = fluidResolvedUrl.endpoints.ordererUrl!;
334
+ // TODO why are we non null asserting here?
335
+ this.deltaStorageUrl = fluidResolvedUrl.endpoints.deltaStorageUrl!;
336
+ this.deltaStreamUrl = fluidResolvedUrl.endpoints.deltaStreamUrl ?? this.ordererUrl;
334
337
  }
335
338
 
336
339
  /**
@@ -113,6 +113,7 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
113
113
  throw new Error("Parsed url should contain tenant and doc Id!!");
114
114
  }
115
115
  const [, tenantId] = parsedUrl.pathname.split("/");
116
+ assert(tenantId !== undefined, 0x9ac /* "Missing tenant ID!" */);
116
117
 
117
118
  if (!isCombinedAppAndProtocolSummary(createNewSummary)) {
118
119
  throw new Error("Protocol and App Summary required in the full summary");
@@ -136,7 +137,7 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
136
137
  logger2,
137
138
  rateLimiter,
138
139
  this.driverPolicies.enableRestLess,
139
- resolvedUrl.endpoints.ordererUrl,
140
+ resolvedUrl.endpoints.ordererUrl /* baseUrl */,
140
141
  );
141
142
 
142
143
  const createAsEphemeral = isRouterliciousResolvedUrl(resolvedUrl)
@@ -320,10 +321,12 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
320
321
  ? getDiscoveredFluidResolvedUrl(resolvedUrl, session)
321
322
  : await discoverFluidResolvedUrl();
322
323
 
323
- const storageUrl = fluidResolvedUrl.endpoints.storageUrl;
324
- const ordererUrl = fluidResolvedUrl.endpoints.ordererUrl;
324
+ // TODO why are we non null asserting here?
325
+ const storageUrl = fluidResolvedUrl.endpoints.storageUrl!;
326
+ // TODO why are we non null asserting here?
327
+ const ordererUrl = fluidResolvedUrl.endpoints.ordererUrl!;
325
328
  const deltaStorageUrl = fluidResolvedUrl.endpoints.deltaStorageUrl;
326
- const deltaStreamUrl = fluidResolvedUrl.endpoints.deltaStreamUrl || ordererUrl; // backward compatibility
329
+ const deltaStreamUrl = fluidResolvedUrl.endpoints.deltaStreamUrl ?? ordererUrl; // backward compatibility
327
330
  if (!ordererUrl || !deltaStorageUrl) {
328
331
  throw new Error(
329
332
  `All endpoints urls must be provided. [ordererUrl:${ordererUrl}][deltaStorageUrl:${deltaStorageUrl}]`,
@@ -336,7 +339,7 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
336
339
  logger2,
337
340
  new RateLimiter(this.driverPolicies.maxConcurrentStorageRequests),
338
341
  this.driverPolicies.enableRestLess,
339
- storageUrl,
342
+ storageUrl /* baseUrl */,
340
343
  storageTokenP,
341
344
  );
342
345
 
package/src/historian.ts CHANGED
@@ -18,8 +18,9 @@ import {
18
18
  } from "@fluidframework/server-services-client";
19
19
 
20
20
  import { IWholeFlatSnapshot } from "./contracts.js";
21
+ import { type QueryStringType } from "./queryStringUtils.js";
21
22
  import { IR11sResponse } from "./restWrapper.js";
22
- import { QueryStringType, RestWrapper } from "./restWrapperBase.js";
23
+ import { RestWrapper } from "./restWrapperBase.js";
23
24
  import { IHistorian } from "./storageContracts.js";
24
25
 
25
26
  export interface ICredentials {
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/routerlicious-driver";
9
- export const pkgVersion = "2.1.0-276326";
9
+ export const pkgVersion = "2.1.0-281041";
@@ -0,0 +1,23 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ export type QueryStringType = Record<string, string | number | boolean>;
7
+
8
+ /**
9
+ * Generates URL object from the given string request url and query parameters.
10
+ * @param url - URL to which query params should be appended. Can include base/default query params.
11
+ * @param queryParams - Query parameters to append. Will override any query params in url.
12
+ */
13
+ export function addOrUpdateQueryParams(url: URL | string, queryParams: QueryStringType): URL {
14
+ // Initialize urlSearchParams with query params from the base URL itself
15
+ const outputUrl = new URL(url);
16
+ const updatedSearchParams = outputUrl.searchParams;
17
+ for (const [key, value] of Object.entries(queryParams)) {
18
+ // Add/override search params from query params
19
+ updatedSearchParams.set(key, encodeURIComponent(value));
20
+ }
21
+ outputUrl.search = updatedSearchParams.toString();
22
+ return outputUrl;
23
+ }
@@ -36,7 +36,8 @@ function buildHierarchy(
36
36
  const entryPathBase = entryPath.slice(lastIndex + 1);
37
37
 
38
38
  // The flat output is breadth-first so we can assume we see tree nodes prior to their contents
39
- const node = lookup[entryPathDir];
39
+ // TODO why are we non null asserting here?
40
+ const node = lookup[entryPathDir]!;
40
41
 
41
42
  // Add in either the blob or tree
42
43
  if (entry.type === "tree") {
@@ -75,8 +76,9 @@ export function convertWholeFlatSnapshotToSnapshotTreeAndBlobs(
75
76
  blobs.set(blob.id, stringToBuffer(blob.content, blob.encoding ?? "utf-8"));
76
77
  });
77
78
  }
78
- const flatSnapshotTree = flatSnapshot.trees?.[0];
79
- const sequenceNumber = flatSnapshotTree?.sequenceNumber;
79
+ // TODO why are we non null asserting here?
80
+ const flatSnapshotTree = flatSnapshot.trees[0]!;
81
+ const sequenceNumber = flatSnapshotTree.sequenceNumber;
80
82
  const snapshotTree = buildHierarchy(flatSnapshotTree, treePrefixToRemove);
81
83
 
82
84
  return {
@@ -28,19 +28,19 @@ import safeStringify from "json-stringify-safe";
28
28
  import type { AxiosRequestConfig, RawAxiosRequestHeaders } from "./axios.cjs";
29
29
  import { RouterliciousErrorTypes, throwR11sNetworkError } from "./errorUtils.js";
30
30
  import { pkgVersion as driverVersion } from "./packageVersion.js";
31
- import { QueryStringType, RestWrapper } from "./restWrapperBase.js";
31
+ import { addOrUpdateQueryParams, type QueryStringType } from "./queryStringUtils.js";
32
+ import { RestWrapper } from "./restWrapperBase.js";
32
33
  import { ITokenProvider, ITokenResponse } from "./tokens.js";
33
34
 
34
35
  type AuthorizationHeaderGetter = (token: ITokenResponse) => string;
35
36
  export type TokenFetcher = (refresh?: boolean) => Promise<ITokenResponse>;
36
37
 
37
- const axiosRequestConfigToFetchRequestConfig = (
38
- requestConfig: AxiosRequestConfig,
39
- ): [RequestInfo, RequestInit] => {
40
- const requestInfo: string =
41
- requestConfig.baseURL !== undefined
42
- ? `${requestConfig.baseURL}${requestConfig.url ?? ""}`
43
- : requestConfig.url ?? "";
38
+ const buildRequestUrl = (requestConfig: AxiosRequestConfig) =>
39
+ requestConfig.baseURL !== undefined
40
+ ? `${requestConfig.baseURL ?? ""}${requestConfig.url ?? ""}`
41
+ : requestConfig.url ?? "";
42
+
43
+ const axiosBuildRequestInitConfig = (requestConfig: AxiosRequestConfig): RequestInit => {
44
44
  const requestInit: RequestInit = {
45
45
  method: requestConfig.method,
46
46
  // NOTE: I believe that although the Axios type permits non-string values in the header, here we are
@@ -48,7 +48,7 @@ const axiosRequestConfigToFetchRequestConfig = (
48
48
  headers: requestConfig.headers as Record<string, string>,
49
49
  body: requestConfig.data,
50
50
  };
51
- return [requestInfo, requestInit];
51
+ return requestInit;
52
52
  };
53
53
 
54
54
  export interface IR11sResponse<T> {
@@ -109,10 +109,17 @@ export function getPropsToLogFromResponse(headers: {
109
109
  return additionalProps;
110
110
  }
111
111
 
112
- export class RouterliciousRestWrapper extends RestWrapper {
112
+ class RouterliciousRestWrapper extends RestWrapper {
113
113
  private readonly restLess = new RestLessClient();
114
114
  private token: ITokenResponse | undefined;
115
115
 
116
+ /**
117
+ * A locally maintained map which saves the number of retries for any REST api call made through restWrapper.
118
+ * It uses the href of the request url as a key against which it saves the retry counts. Retries are only counted in case of failures.
119
+ * This feature is added to enable FRS to have more telemetry insights into whether the requests are being retried from same client or multiple.
120
+ */
121
+ private readonly retryCounter = new Map<string, number>();
122
+
116
123
  constructor(
117
124
  logger: ITelemetryLoggerExt,
118
125
  private readonly rateLimiter: RateLimiter,
@@ -131,36 +138,64 @@ export class RouterliciousRestWrapper extends RestWrapper {
131
138
  statusCode: number,
132
139
  canRetry = true,
133
140
  ): Promise<IR11sResponse<T>> {
141
+ if (requestConfig.params) {
142
+ // delete the retry param, if any. We do this to ensure there is no retry added by any of callers, which would conflict with the one we maintain here in the retryCounter map.
143
+ delete requestConfig.params.retry;
144
+ }
145
+
146
+ // Build the complete request url including baseUrl, url and query params. (all except 'retry' query param)
147
+ let completeRequestUrl = addOrUpdateQueryParams(
148
+ buildRequestUrl(requestConfig),
149
+ requestConfig.params,
150
+ );
151
+
152
+ // Check whether this request has been made before or if it is a retry.
153
+ // requestKey is built using the HTTP method appended with the complete URL ommitting the 'retry' param
154
+ const requestKey = `${requestConfig.method ?? ""}|${completeRequestUrl.href}`;
155
+ const requestRetryCount = this.retryCounter.get(requestKey);
156
+ if (requestRetryCount) {
157
+ completeRequestUrl = addOrUpdateQueryParams(completeRequestUrl, {
158
+ retry: requestRetryCount,
159
+ });
160
+ }
161
+
134
162
  const config = {
135
163
  ...requestConfig,
136
164
  headers: await this.generateHeaders(requestConfig.headers),
137
165
  };
138
166
 
139
167
  const translatedConfig = this.useRestLess ? this.restLess.translate(config) : config;
140
- const fetchRequestConfig = axiosRequestConfigToFetchRequestConfig(translatedConfig);
168
+ const fetchRequestConfig = axiosBuildRequestInitConfig(translatedConfig);
141
169
 
142
170
  const res = await this.rateLimiter.schedule(async () => {
143
171
  const perfStart = performance.now();
144
- const result = await fetch(...fetchRequestConfig).catch(async (error) => {
145
- // Browser Fetch throws a TypeError on network error, `node-fetch` throws a FetchError
146
- const isNetworkError = ["TypeError", "FetchError"].includes(error?.name);
147
- const errorMessage = isNetworkError
148
- ? `NetworkError: ${error.message}`
149
- : safeStringify(error);
150
- // If a service is temporarily down or a browser resource limit is reached, RestWrapper will throw
151
- // a network error with no status code (e.g. err:ERR_CONN_REFUSED or err:ERR_FAILED) and
152
- // the error message will start with NetworkError as defined in restWrapper.ts
153
- // If there exists a self-signed SSL certificates error, throw a NonRetryableError
154
- // TODO: instead of relying on string matching, filter error based on the error code like we do for websocket connections
155
- const err = errorMessage.includes("failed, reason: self signed certificate")
156
- ? new NonRetryableError(errorMessage, RouterliciousErrorTypes.sslCertError, {
157
- driverVersion,
158
- })
159
- : new GenericNetworkError(errorMessage, errorMessage.startsWith("NetworkError"), {
160
- driverVersion,
161
- });
162
- throw err;
163
- });
172
+ const result = await fetch(completeRequestUrl, fetchRequestConfig).catch(
173
+ async (error) => {
174
+ // on failure, add the request entry into the retryCounter map to count the subsequent retries, if any
175
+ this.retryCounter.set(requestKey, requestRetryCount ? requestRetryCount + 1 : 1);
176
+
177
+ // Browser Fetch throws a TypeError on network error, `node-fetch` throws a FetchError
178
+ const isNetworkError = ["TypeError", "FetchError"].includes(error?.name);
179
+ const errorMessage = isNetworkError
180
+ ? `NetworkError: ${error.message}`
181
+ : safeStringify(error);
182
+ // If a service is temporarily down or a browser resource limit is reached, RestWrapper will throw
183
+ // a network error with no status code (e.g. err:ERR_CONN_REFUSED or err:ERR_FAILED) and
184
+ // the error message will start with NetworkError as defined in restWrapper.ts
185
+ // If there exists a self-signed SSL certificates error, throw a NonRetryableError
186
+ // TODO: instead of relying on string matching, filter error based on the error code like we do for websocket connections
187
+ const err = errorMessage.includes("failed, reason: self signed certificate")
188
+ ? new NonRetryableError(errorMessage, RouterliciousErrorTypes.sslCertError, {
189
+ driverVersion,
190
+ retryCount: requestRetryCount,
191
+ })
192
+ : new GenericNetworkError(errorMessage, errorMessage.startsWith("NetworkError"), {
193
+ driverVersion,
194
+ retryCount: requestRetryCount,
195
+ });
196
+ throw err;
197
+ },
198
+ );
164
199
  return {
165
200
  response: result,
166
201
  duration: performance.now() - perfStart,
@@ -184,13 +219,14 @@ export class RouterliciousRestWrapper extends RestWrapper {
184
219
 
185
220
  // Success
186
221
  if (response.ok || response.status === statusCode) {
222
+ // on successful response, remove the entry from the retryCounter map
223
+ this.retryCounter.delete(requestKey);
187
224
  const result = responseBody as T;
188
225
  const headers = headersToMap(response.headers);
189
226
  return {
190
227
  content: result,
191
228
  headers,
192
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
193
- requestUrl: fetchRequestConfig[0].toString(),
229
+ requestUrl: completeRequestUrl.href,
194
230
  propsToLog: {
195
231
  ...getPropsToLogFromResponse(headers),
196
232
  bodySize,
@@ -200,17 +236,24 @@ export class RouterliciousRestWrapper extends RestWrapper {
200
236
  },
201
237
  };
202
238
  }
239
+
203
240
  // Failure
241
+ // on failure, add the request entry into the retryCounter map to count the subsequent retries
242
+ this.retryCounter.set(requestKey, requestRetryCount ? requestRetryCount + 1 : 1);
243
+
204
244
  if (response.status === 401 && canRetry) {
205
245
  // Refresh Authorization header and retry once
206
246
  this.token = await this.fetchRefreshedToken(true /* refreshToken */);
207
- return this.request<T>(config, statusCode, false);
247
+ return this.request<T>({ ...config }, statusCode, false);
208
248
  }
209
249
  if (response.status === 429 && responseBody?.retryAfter > 0) {
210
250
  // Retry based on retryAfter[Seconds]
211
251
  return new Promise<IR11sResponse<T>>((resolve, reject) =>
212
252
  setTimeout(() => {
213
- this.request<T>(config, statusCode).then(resolve).catch(reject);
253
+ // use the original request URL without the retryCount appended
254
+ this.request<T>({ ...config }, statusCode)
255
+ .then(resolve)
256
+ .catch(reject);
214
257
  }, responseBody.retryAfter * 1000),
215
258
  );
216
259
  }