@fluidframework/odsp-driver 2.0.0-dev.5.2.0.169897 → 2.0.0-dev.5.3.2.178189

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 (110) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/contracts.d.ts +0 -25
  3. package/dist/contracts.d.ts.map +1 -1
  4. package/dist/contracts.js.map +1 -1
  5. package/dist/epochTracker.d.ts.map +1 -1
  6. package/dist/epochTracker.js +7 -1
  7. package/dist/epochTracker.js.map +1 -1
  8. package/dist/localOdspDriver/localOdspDocumentServiceFactory.d.ts +1 -1
  9. package/dist/localOdspDriver/localOdspDocumentServiceFactory.d.ts.map +1 -1
  10. package/dist/localOdspDriver/localOdspDocumentServiceFactory.js.map +1 -1
  11. package/dist/odspCache.d.ts +2 -3
  12. package/dist/odspCache.d.ts.map +1 -1
  13. package/dist/odspCache.js +5 -5
  14. package/dist/odspCache.js.map +1 -1
  15. package/dist/odspDelayLoadedDeltaStream.d.ts.map +1 -1
  16. package/dist/odspDelayLoadedDeltaStream.js +1 -1
  17. package/dist/odspDelayLoadedDeltaStream.js.map +1 -1
  18. package/dist/odspDeltaStorageService.d.ts +1 -1
  19. package/dist/odspDeltaStorageService.d.ts.map +1 -1
  20. package/dist/odspDeltaStorageService.js +6 -3
  21. package/dist/odspDeltaStorageService.js.map +1 -1
  22. package/dist/odspDocumentServiceFactoryCore.d.ts +12 -4
  23. package/dist/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  24. package/dist/odspDocumentServiceFactoryCore.js +14 -0
  25. package/dist/odspDocumentServiceFactoryCore.js.map +1 -1
  26. package/dist/odspDocumentStorageManager.d.ts.map +1 -1
  27. package/dist/odspDocumentStorageManager.js +2 -0
  28. package/dist/odspDocumentStorageManager.js.map +1 -1
  29. package/dist/odspDriverUrlResolverForShareLink.d.ts +1 -2
  30. package/dist/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  31. package/dist/odspDriverUrlResolverForShareLink.js.map +1 -1
  32. package/dist/odspUtils.d.ts +2 -1
  33. package/dist/odspUtils.d.ts.map +1 -1
  34. package/dist/odspUtils.js +5 -1
  35. package/dist/odspUtils.js.map +1 -1
  36. package/dist/packageVersion.d.ts +1 -1
  37. package/dist/packageVersion.js +1 -1
  38. package/dist/packageVersion.js.map +1 -1
  39. package/dist/prefetchLatestSnapshot.d.ts +1 -1
  40. package/dist/prefetchLatestSnapshot.d.ts.map +1 -1
  41. package/dist/prefetchLatestSnapshot.js +14 -5
  42. package/dist/prefetchLatestSnapshot.js.map +1 -1
  43. package/dist/retryErrorsStorageAdapter.d.ts +1 -1
  44. package/dist/retryErrorsStorageAdapter.d.ts.map +1 -1
  45. package/dist/retryErrorsStorageAdapter.js.map +1 -1
  46. package/dist/vroom.d.ts +1 -2
  47. package/dist/vroom.d.ts.map +1 -1
  48. package/dist/vroom.js.map +1 -1
  49. package/lib/contracts.d.ts +0 -25
  50. package/lib/contracts.d.ts.map +1 -1
  51. package/lib/contracts.js.map +1 -1
  52. package/lib/epochTracker.d.ts.map +1 -1
  53. package/lib/epochTracker.js +8 -2
  54. package/lib/epochTracker.js.map +1 -1
  55. package/lib/localOdspDriver/localOdspDocumentServiceFactory.d.ts +1 -1
  56. package/lib/localOdspDriver/localOdspDocumentServiceFactory.d.ts.map +1 -1
  57. package/lib/localOdspDriver/localOdspDocumentServiceFactory.js.map +1 -1
  58. package/lib/odspCache.d.ts +2 -3
  59. package/lib/odspCache.d.ts.map +1 -1
  60. package/lib/odspCache.js +1 -1
  61. package/lib/odspCache.js.map +1 -1
  62. package/lib/odspDelayLoadedDeltaStream.d.ts.map +1 -1
  63. package/lib/odspDelayLoadedDeltaStream.js +2 -2
  64. package/lib/odspDelayLoadedDeltaStream.js.map +1 -1
  65. package/lib/odspDeltaStorageService.d.ts +1 -1
  66. package/lib/odspDeltaStorageService.d.ts.map +1 -1
  67. package/lib/odspDeltaStorageService.js +6 -3
  68. package/lib/odspDeltaStorageService.js.map +1 -1
  69. package/lib/odspDocumentServiceFactoryCore.d.ts +12 -4
  70. package/lib/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  71. package/lib/odspDocumentServiceFactoryCore.js +15 -1
  72. package/lib/odspDocumentServiceFactoryCore.js.map +1 -1
  73. package/lib/odspDocumentStorageManager.d.ts.map +1 -1
  74. package/lib/odspDocumentStorageManager.js +2 -0
  75. package/lib/odspDocumentStorageManager.js.map +1 -1
  76. package/lib/odspDriverUrlResolverForShareLink.d.ts +1 -2
  77. package/lib/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  78. package/lib/odspDriverUrlResolverForShareLink.js.map +1 -1
  79. package/lib/odspUtils.d.ts +2 -1
  80. package/lib/odspUtils.d.ts.map +1 -1
  81. package/lib/odspUtils.js +3 -0
  82. package/lib/odspUtils.js.map +1 -1
  83. package/lib/packageVersion.d.ts +1 -1
  84. package/lib/packageVersion.js +1 -1
  85. package/lib/packageVersion.js.map +1 -1
  86. package/lib/prefetchLatestSnapshot.d.ts +1 -1
  87. package/lib/prefetchLatestSnapshot.d.ts.map +1 -1
  88. package/lib/prefetchLatestSnapshot.js +14 -5
  89. package/lib/prefetchLatestSnapshot.js.map +1 -1
  90. package/lib/retryErrorsStorageAdapter.d.ts +1 -1
  91. package/lib/retryErrorsStorageAdapter.d.ts.map +1 -1
  92. package/lib/retryErrorsStorageAdapter.js.map +1 -1
  93. package/lib/vroom.d.ts +1 -2
  94. package/lib/vroom.d.ts.map +1 -1
  95. package/lib/vroom.js.map +1 -1
  96. package/package.json +29 -14
  97. package/src/contracts.ts +0 -34
  98. package/src/epochTracker.ts +8 -5
  99. package/src/localOdspDriver/localOdspDocumentServiceFactory.ts +1 -1
  100. package/src/odspCache.ts +2 -2
  101. package/src/odspDelayLoadedDeltaStream.ts +7 -3
  102. package/src/odspDeltaStorageService.ts +7 -4
  103. package/src/odspDocumentServiceFactoryCore.ts +27 -2
  104. package/src/odspDocumentStorageManager.ts +2 -0
  105. package/src/odspDriverUrlResolverForShareLink.ts +1 -2
  106. package/src/odspUtils.ts +5 -1
  107. package/src/packageVersion.ts +1 -1
  108. package/src/prefetchLatestSnapshot.ts +15 -6
  109. package/src/retryErrorsStorageAdapter.ts +1 -1
  110. package/src/vroom.ts +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"prefetchLatestSnapshot.js","sourceRoot":"","sources":["../src/prefetchLatestSnapshot.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { default as AbortController } from \"abort-controller\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/common-definitions\";\nimport { assert, Deferred, performance } from \"@fluidframework/common-utils\";\nimport { IResolvedUrl } from \"@fluidframework/driver-definitions\";\nimport {\n\tIOdspResolvedUrl,\n\tIPersistedCache,\n\tISnapshotOptions,\n\tOdspResourceTokenFetchOptions,\n\tTokenFetcher,\n\tIOdspUrlParts,\n\tgetKeyForCacheEntry,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ChildLogger, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport {\n\tcreateCacheSnapshotKey,\n\tcreateOdspLogger,\n\tgetOdspResolvedUrl,\n\ttoInstrumentedOdspTokenFetcher,\n} from \"./odspUtils\";\nimport {\n\tdownloadSnapshot,\n\tfetchSnapshotWithRedeem,\n\tSnapshotFormatSupportType,\n} from \"./fetchSnapshot\";\nimport { IVersionedValueWithEpoch } from \"./contracts\";\nimport { IPrefetchSnapshotContents } from \"./odspCache\";\nimport { OdspDocumentServiceFactory } from \"./odspDocumentServiceFactory\";\n\n/**\n * Function to prefetch the snapshot and cached it in the persistant cache, so that when the container is loaded\n * the cached latest snapshot could be used and removes the network call from the critical path.\n *\n * @param resolvedUrl - Resolved url to fetch the snapshot.\n * @param getStorageToken - function that can provide the storage token for a given site. This is\n * is also referred to as the \"VROOM\" token in SPO.\n * @param persistedCache - Cache to store the fetched snapshot.\n * @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header.\n * @param logger - Logger to have telemetry events.\n * @param hostSnapshotFetchOptions - Options to fetch the snapshot if any. Otherwise default will be used.\n * @param enableRedeemFallback - True to have the sharing link redeem fallback in case the Trees Latest/Redeem\n * 1RT call fails with redeem error. During fallback it will first redeem the sharing link and then make\n * the Trees latest call.\n * Note: this can be considered deprecated - it will be replaced with `snapshotFormatFetchType`.\n * @param fetchBinarySnapshotFormat - Control if we want to fetch binary format snapshot.\n * @param snapshotFormatFetchType - Snapshot format to fetch.\n * @param odspDocumentServiceFactory - factory to access the non persistent cache and store the prefetch promise.\n *\n * @returns - True if the snapshot is cached, false otherwise.\n */\nexport async function prefetchLatestSnapshot(\n\tresolvedUrl: IResolvedUrl,\n\tgetStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n\tpersistedCache: IPersistedCache,\n\tforceAccessTokenViaAuthorizationHeader: boolean,\n\tlogger: ITelemetryBaseLogger,\n\thostSnapshotFetchOptions: ISnapshotOptions | undefined,\n\tenableRedeemFallback: boolean = true,\n\tfetchBinarySnapshotFormat?: boolean,\n\tsnapshotFormatFetchType?: SnapshotFormatSupportType,\n\todspDocumentServiceFactory?: OdspDocumentServiceFactory,\n): Promise<boolean> {\n\tconst odspLogger = createOdspLogger(ChildLogger.create(logger, \"PrefetchSnapshot\"));\n\tconst odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);\n\n\tconst resolvedUrlData: IOdspUrlParts = {\n\t\tsiteUrl: odspResolvedUrl.siteUrl,\n\t\tdriveId: odspResolvedUrl.driveId,\n\t\titemId: odspResolvedUrl.itemId,\n\t};\n\tconst storageTokenFetcher = toInstrumentedOdspTokenFetcher(\n\t\todspLogger,\n\t\tresolvedUrlData,\n\t\tgetStorageToken,\n\t\ttrue /* throwOnNullToken */,\n\t);\n\n\tconst snapshotDownloader = async (\n\t\tfinalOdspResolvedUrl: IOdspResolvedUrl,\n\t\tstorageToken: string,\n\t\tsnapshotOptions: ISnapshotOptions | undefined,\n\t\tcontroller?: AbortController,\n\t) => {\n\t\treturn downloadSnapshot(\n\t\t\tfinalOdspResolvedUrl,\n\t\t\tstorageToken,\n\t\t\todspLogger,\n\t\t\tsnapshotOptions,\n\t\t\tundefined,\n\t\t\tcontroller,\n\t\t);\n\t};\n\tconst snapshotKey = createCacheSnapshotKey(odspResolvedUrl);\n\tlet cacheP: Promise<void> | undefined;\n\tlet snapshotEpoch: string | undefined;\n\tconst putInCache = async (valueWithEpoch: IVersionedValueWithEpoch) => {\n\t\tsnapshotEpoch = valueWithEpoch.fluidEpoch;\n\t\tcacheP = persistedCache.put(snapshotKey, valueWithEpoch);\n\t\treturn cacheP;\n\t};\n\tconst removeEntries = async () => persistedCache.removeEntries(snapshotKey.file);\n\treturn PerformanceEvent.timedExecAsync(\n\t\todspLogger,\n\t\t{ eventName: \"PrefetchLatestSnapshot\" },\n\t\tasync () => {\n\t\t\tconst prefetchStartTime = performance.now();\n\t\t\t// Add the deferred promise to the cache, so that it can be leveraged while loading the container.\n\t\t\tconst snapshotContentsWithEpochP = new Deferred<IPrefetchSnapshotContents>();\n\t\t\tconst nonPersistentCacheKey = getKeyForCacheEntry(snapshotKey);\n\t\t\tconst snapshotNonPersistentCache =\n\t\t\t\todspDocumentServiceFactory?.snapshotPrefetchResultCache;\n\t\t\tsnapshotNonPersistentCache?.add(\n\t\t\t\tnonPersistentCacheKey,\n\t\t\t\tasync () => snapshotContentsWithEpochP.promise,\n\t\t\t);\n\t\t\tawait fetchSnapshotWithRedeem(\n\t\t\t\todspResolvedUrl,\n\t\t\t\tstorageTokenFetcher,\n\t\t\t\thostSnapshotFetchOptions,\n\t\t\t\tforceAccessTokenViaAuthorizationHeader,\n\t\t\t\todspLogger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t\tputInCache,\n\t\t\t\tremoveEntries,\n\t\t\t\tenableRedeemFallback,\n\t\t\t)\n\t\t\t\t.then(async (value) => {\n\t\t\t\t\tassert(\n\t\t\t\t\t\t!!snapshotEpoch,\n\t\t\t\t\t\t0x585 /* prefetched snapshot should have a valid epoch */,\n\t\t\t\t\t);\n\t\t\t\t\tsnapshotContentsWithEpochP.resolve({\n\t\t\t\t\t\t...value,\n\t\t\t\t\t\tfluidEpoch: snapshotEpoch,\n\t\t\t\t\t\tprefetchStartTime,\n\t\t\t\t\t});\n\t\t\t\t\tassert(cacheP !== undefined, 0x1e7 /* \"caching was not performed!\" */);\n\t\t\t\t\tawait cacheP;\n\t\t\t\t})\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tsnapshotContentsWithEpochP.reject(err);\n\t\t\t\t\tthrow err;\n\t\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\t// Remove it from the non persistent cache once it is cached in the persistent cache or an error\n\t\t\t\t\t// occured.\n\t\t\t\t\tsnapshotNonPersistentCache?.remove(nonPersistentCacheKey);\n\t\t\t\t});\n\t\t\treturn true;\n\t\t},\n\t).catch(async (error) => {\n\t\todspLogger.sendErrorEvent({ eventName: \"PrefetchLatestSnapshotError\" }, error);\n\t\treturn false;\n\t});\n}\n"]}
1
+ {"version":3,"file":"prefetchLatestSnapshot.js","sourceRoot":"","sources":["../src/prefetchLatestSnapshot.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { default as AbortController } from \"abort-controller\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert, Deferred, performance } from \"@fluidframework/common-utils\";\nimport { IResolvedUrl } from \"@fluidframework/driver-definitions\";\nimport {\n\tIOdspResolvedUrl,\n\tIPersistedCache,\n\tISnapshotOptions,\n\tOdspResourceTokenFetchOptions,\n\tTokenFetcher,\n\tIOdspUrlParts,\n\tgetKeyForCacheEntry,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ChildLogger, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport {\n\tcreateCacheSnapshotKey,\n\tcreateOdspLogger,\n\tgetOdspResolvedUrl,\n\ttoInstrumentedOdspTokenFetcher,\n} from \"./odspUtils\";\nimport {\n\tdownloadSnapshot,\n\tfetchSnapshotWithRedeem,\n\tSnapshotFormatSupportType,\n} from \"./fetchSnapshot\";\nimport { IVersionedValueWithEpoch } from \"./contracts\";\nimport { IPrefetchSnapshotContents } from \"./odspCache\";\nimport { OdspDocumentServiceFactory } from \"./odspDocumentServiceFactory\";\n\n/**\n * Function to prefetch the snapshot and cached it in the persistant cache, so that when the container is loaded\n * the cached latest snapshot could be used and removes the network call from the critical path.\n *\n * @param resolvedUrl - Resolved url to fetch the snapshot.\n * @param getStorageToken - function that can provide the storage token for a given site. This is\n * is also referred to as the \"VROOM\" token in SPO.\n * @param persistedCache - Cache to store the fetched snapshot.\n * @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header.\n * @param logger - Logger to have telemetry events.\n * @param hostSnapshotFetchOptions - Options to fetch the snapshot if any. Otherwise default will be used.\n * @param enableRedeemFallback - True to have the sharing link redeem fallback in case the Trees Latest/Redeem\n * 1RT call fails with redeem error. During fallback it will first redeem the sharing link and then make\n * the Trees latest call.\n * Note: this can be considered deprecated - it will be replaced with `snapshotFormatFetchType`.\n * @param fetchBinarySnapshotFormat - Control if we want to fetch binary format snapshot.\n * @param snapshotFormatFetchType - Snapshot format to fetch.\n * @param odspDocumentServiceFactory - factory to access the non persistent cache and store the prefetch promise.\n *\n * @returns - True if the snapshot is cached, false otherwise.\n */\nexport async function prefetchLatestSnapshot(\n\tresolvedUrl: IResolvedUrl,\n\tgetStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n\tpersistedCache: IPersistedCache,\n\tforceAccessTokenViaAuthorizationHeader: boolean,\n\tlogger: ITelemetryBaseLogger,\n\thostSnapshotFetchOptions: ISnapshotOptions | undefined,\n\tenableRedeemFallback: boolean = true,\n\tfetchBinarySnapshotFormat?: boolean,\n\tsnapshotFormatFetchType?: SnapshotFormatSupportType,\n\todspDocumentServiceFactory?: OdspDocumentServiceFactory,\n): Promise<boolean> {\n\tconst odspLogger = createOdspLogger(ChildLogger.create(logger, \"PrefetchSnapshot\"));\n\tconst odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);\n\n\tconst resolvedUrlData: IOdspUrlParts = {\n\t\tsiteUrl: odspResolvedUrl.siteUrl,\n\t\tdriveId: odspResolvedUrl.driveId,\n\t\titemId: odspResolvedUrl.itemId,\n\t};\n\tconst storageTokenFetcher = toInstrumentedOdspTokenFetcher(\n\t\todspLogger,\n\t\tresolvedUrlData,\n\t\tgetStorageToken,\n\t\ttrue /* throwOnNullToken */,\n\t);\n\n\tconst snapshotDownloader = async (\n\t\tfinalOdspResolvedUrl: IOdspResolvedUrl,\n\t\tstorageToken: string,\n\t\tsnapshotOptions: ISnapshotOptions | undefined,\n\t\tcontroller?: AbortController,\n\t) => {\n\t\treturn downloadSnapshot(\n\t\t\tfinalOdspResolvedUrl,\n\t\t\tstorageToken,\n\t\t\todspLogger,\n\t\t\tsnapshotOptions,\n\t\t\tundefined,\n\t\t\tcontroller,\n\t\t);\n\t};\n\tconst snapshotKey = createCacheSnapshotKey(odspResolvedUrl);\n\tlet cacheP: Promise<void> | undefined;\n\tlet snapshotEpoch: string | undefined;\n\tconst putInCache = async (valueWithEpoch: IVersionedValueWithEpoch) => {\n\t\tsnapshotEpoch = valueWithEpoch.fluidEpoch;\n\t\tcacheP = persistedCache.put(snapshotKey, valueWithEpoch);\n\t\treturn cacheP;\n\t};\n\tconst removeEntries = async () => persistedCache.removeEntries(snapshotKey.file);\n\treturn PerformanceEvent.timedExecAsync(\n\t\todspLogger,\n\t\t{ eventName: \"PrefetchLatestSnapshot\" },\n\t\tasync () => {\n\t\t\tconst prefetchStartTime = performance.now();\n\t\t\t// Add the deferred promise to the cache, so that it can be leveraged while loading the container.\n\t\t\tconst snapshotContentsWithEpochP = new Deferred<IPrefetchSnapshotContents>();\n\t\t\tconst nonPersistentCacheKey = getKeyForCacheEntry(snapshotKey);\n\t\t\tconst snapshotNonPersistentCache =\n\t\t\t\todspDocumentServiceFactory?.snapshotPrefetchResultCache;\n\t\t\tsnapshotNonPersistentCache?.add(\n\t\t\t\tnonPersistentCacheKey,\n\t\t\t\tasync () => snapshotContentsWithEpochP.promise,\n\t\t\t);\n\t\t\tawait fetchSnapshotWithRedeem(\n\t\t\t\todspResolvedUrl,\n\t\t\t\tstorageTokenFetcher,\n\t\t\t\thostSnapshotFetchOptions,\n\t\t\t\tforceAccessTokenViaAuthorizationHeader,\n\t\t\t\todspLogger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t\tputInCache,\n\t\t\t\tremoveEntries,\n\t\t\t\tenableRedeemFallback,\n\t\t\t)\n\t\t\t\t.then(async (value) => {\n\t\t\t\t\tassert(\n\t\t\t\t\t\t!!snapshotEpoch,\n\t\t\t\t\t\t0x585 /* prefetched snapshot should have a valid epoch */,\n\t\t\t\t\t);\n\t\t\t\t\tsnapshotContentsWithEpochP.resolve({\n\t\t\t\t\t\t...value,\n\t\t\t\t\t\tfluidEpoch: snapshotEpoch,\n\t\t\t\t\t\tprefetchStartTime,\n\t\t\t\t\t});\n\t\t\t\t\tassert(cacheP !== undefined, 0x1e7 /* \"caching was not performed!\" */);\n\t\t\t\t\tawait cacheP;\n\t\t\t\t\t// Schedule it to remove from cache after 5s.\n\t\t\t\t\t// 1. While it's in snapshotNonPersistentCache: Load flow will use this value and will not attempt\n\t\t\t\t\t// to fetch snapshot from network again. That's the best from perf POV, but cache will not be\n\t\t\t\t\t// updated if we keep it in this cache, thus we want to eventually remove snapshot from this cache.\n\t\t\t\t\t// 2. After it's removed from snapshotNonPersistentCache: snapshot is present in persistent cache,\n\t\t\t\t\t// so we sill still use it (in accordance with cache policy controlled by host). But load flow will\n\t\t\t\t\t// also fetch snapshot (in parallel) from storage and update cache. This is fine long term,\n\t\t\t\t\t// but is an extra cost (unneeded network call). However since it is 5s older, new network call\n\t\t\t\t\t// will update the snapshot in cache.\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsnapshotNonPersistentCache?.remove(nonPersistentCacheKey);\n\t\t\t\t\t}, 5000);\n\t\t\t\t})\n\t\t\t\t.catch((err) => {\n\t\t\t\t\t// Remove it from the non persistent cache if an error occured.\n\t\t\t\t\tsnapshotNonPersistentCache?.remove(nonPersistentCacheKey);\n\t\t\t\t\tsnapshotContentsWithEpochP.reject(err);\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\t\t\treturn true;\n\t\t},\n\t).catch(async (error) => {\n\t\todspLogger.sendErrorEvent({ eventName: \"PrefetchLatestSnapshotError\" }, error);\n\t\treturn false;\n\t});\n}\n"]}
@@ -5,7 +5,7 @@
5
5
  import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
6
6
  import { FetchSource, IDocumentStorageService, IDocumentStorageServicePolicies, ISummaryContext } from "@fluidframework/driver-definitions";
7
7
  import { ICreateBlobResponse, ISnapshotTree, ISummaryHandle, ISummaryTree, IVersion } from "@fluidframework/protocol-definitions";
8
- import { IDisposable } from "@fluidframework/common-definitions";
8
+ import { IDisposable } from "@fluidframework/core-interfaces";
9
9
  export declare class RetryErrorsStorageAdapter implements IDocumentStorageService, IDisposable {
10
10
  private readonly internalStorageService;
11
11
  private readonly logger;
@@ -1 +1 @@
1
- {"version":3,"file":"retryErrorsStorageAdapter.d.ts","sourceRoot":"","sources":["../src/retryErrorsStorageAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAgB,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EACN,WAAW,EACX,uBAAuB,EACvB,+BAA+B,EAC/B,eAAe,EACf,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACN,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAGjE,qBAAa,yBAA0B,YAAW,uBAAuB,EAAE,WAAW;IAGpF,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHxB,OAAO,CAAC,SAAS,CAAS;gBAER,sBAAsB,EAAE,uBAAuB,EAC/C,MAAM,EAAE,mBAAmB;IAG7C,IAAW,QAAQ,IAAI,+BAA+B,GAAG,SAAS,CAEjE;IACD,IAAW,QAAQ,YAElB;IACM,OAAO;IAId,IAAW,aAAa,IAAI,MAAM,CAEjC;IAGY,eAAe,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAOlE,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAO9C,WAAW,CAEvB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,WAAW,GACvB,OAAO,CAAC,QAAQ,EAAE,CAAC;IAaT,wBAAwB,CACpC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,eAAe,GACtB,OAAO,CAAC,MAAM,CAAC;IAQL,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAO9D,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAO5E,OAAO,CAAC,oBAAoB;YASd,YAAY;CAG1B"}
1
+ {"version":3,"file":"retryErrorsStorageAdapter.d.ts","sourceRoot":"","sources":["../src/retryErrorsStorageAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAgB,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EACN,WAAW,EACX,uBAAuB,EACvB,+BAA+B,EAC/B,eAAe,EACf,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACN,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAG9D,qBAAa,yBAA0B,YAAW,uBAAuB,EAAE,WAAW;IAGpF,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHxB,OAAO,CAAC,SAAS,CAAS;gBAER,sBAAsB,EAAE,uBAAuB,EAC/C,MAAM,EAAE,mBAAmB;IAG7C,IAAW,QAAQ,IAAI,+BAA+B,GAAG,SAAS,CAEjE;IACD,IAAW,QAAQ,YAElB;IACM,OAAO;IAId,IAAW,aAAa,IAAI,MAAM,CAEjC;IAGY,eAAe,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAOlE,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAO9C,WAAW,CAEvB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,WAAW,GACvB,OAAO,CAAC,QAAQ,EAAE,CAAC;IAaT,wBAAwB,CACpC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,eAAe,GACtB,OAAO,CAAC,MAAM,CAAC;IAQL,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAO9D,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAO5E,OAAO,CAAC,oBAAoB;YASd,YAAY;CAG1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"retryErrorsStorageAdapter.js","sourceRoot":"","sources":["../src/retryErrorsStorageAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAuB,MAAM,iCAAiC,CAAC;AAepF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,OAAO,yBAAyB;IAErC,YACkB,sBAA+C,EAC/C,MAA2B;QAD3B,2BAAsB,GAAtB,sBAAsB,CAAyB;QAC/C,WAAM,GAAN,MAAM,CAAqB;QAHrC,cAAS,GAAG,KAAK,CAAC;IAIvB,CAAC;IAEJ,IAAW,QAAQ;QAClB,OAAO,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC;IAC7C,CAAC;IACD,IAAW,QAAQ;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IACM,OAAO;QACb,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACvB,CAAC;IAED,IAAW,aAAa;QACvB,OAAO,IAAI,CAAC,sBAAsB,CAAC,aAAa,CAAC;IAClD,CAAC;IAED,kDAAkD;IAC3C,KAAK,CAAC,eAAe,CAAC,OAAkB;QAC9C,OAAO,IAAI,CAAC,YAAY,CACvB,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,eAAe,CAAC,OAAO,CAAC,EAChE,yBAAyB,CACzB,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,QAAQ,CAAC,EAAU;QAC/B,OAAO,IAAI,CAAC,YAAY,CACvB,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,EAAE,CAAC,EACpD,kBAAkB,CAClB,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,WAAW;IACvB,kDAAkD;IAClD,SAAwB,EACxB,KAAa,EACb,YAAqB,EACrB,WAAyB;QAEzB,OAAO,IAAI,CAAC,YAAY,CACvB,KAAK,IAAI,EAAE,CACV,IAAI,CAAC,sBAAsB,CAAC,WAAW,CACtC,SAAS,EACT,KAAK,EACL,YAAY,EACZ,WAAW,CACX,EACF,qBAAqB,CACrB,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,wBAAwB,CACpC,OAAqB,EACrB,OAAwB;QAExB,4DAA4D;QAC5D,OAAO,IAAI,CAAC,YAAY,CACvB,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,wBAAwB,CAAC,OAAO,EAAE,OAAO,CAAC,EAClF,kCAAkC,CAClC,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,MAAsB;QAClD,OAAO,IAAI,CAAC,YAAY,CACvB,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,eAAe,CAAC,MAAM,CAAC,EAC/D,yBAAyB,CACzB,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,IAAqB;QAC5C,OAAO,IAAI,CAAC,YAAY,CACvB,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,IAAI,CAAC,EACxD,oBAAoB,CACpB,CAAC;IACH,CAAC;IAEO,oBAAoB;QAC3B,IAAI,IAAI,CAAC,SAAS,EAAE;YACnB,4DAA4D;YAC5D,MAAM,IAAI,YAAY,CAAC,2CAA2C,EAAE;gBACnE,QAAQ,EAAE,KAAK;aACf,CAAC,CAAC;SACH;IACF,CAAC;IAEO,KAAK,CAAC,YAAY,CAAI,GAAqB,EAAE,QAAgB;QACpE,OAAO,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACpF,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { LoggingError, ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport {\n\tFetchSource,\n\tIDocumentStorageService,\n\tIDocumentStorageServicePolicies,\n\tISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport {\n\tICreateBlobResponse,\n\tISnapshotTree,\n\tISummaryHandle,\n\tISummaryTree,\n\tIVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport { IDisposable } from \"@fluidframework/common-definitions\";\nimport { runWithRetry } from \"./retryUtils\";\n\nexport class RetryErrorsStorageAdapter implements IDocumentStorageService, IDisposable {\n\tprivate _disposed = false;\n\tconstructor(\n\t\tprivate readonly internalStorageService: IDocumentStorageService,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t) {}\n\n\tpublic get policies(): IDocumentStorageServicePolicies | undefined {\n\t\treturn this.internalStorageService.policies;\n\t}\n\tpublic get disposed() {\n\t\treturn this._disposed;\n\t}\n\tpublic dispose() {\n\t\tthis._disposed = true;\n\t}\n\n\tpublic get repositoryUrl(): string {\n\t\treturn this.internalStorageService.repositoryUrl;\n\t}\n\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.getSnapshotTree(version),\n\t\t\t\"storage_getSnapshotTree\",\n\t\t);\n\t}\n\n\tpublic async readBlob(id: string): Promise<ArrayBufferLike> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.readBlob(id),\n\t\t\t\"storage_readBlob\",\n\t\t);\n\t}\n\n\tpublic async getVersions(\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tversionId: string | null,\n\t\tcount: number,\n\t\tscenarioName?: string,\n\t\tfetchSource?: FetchSource,\n\t): Promise<IVersion[]> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () =>\n\t\t\t\tthis.internalStorageService.getVersions(\n\t\t\t\t\tversionId,\n\t\t\t\t\tcount,\n\t\t\t\t\tscenarioName,\n\t\t\t\t\tfetchSource,\n\t\t\t\t),\n\t\t\t\"storage_getVersions\",\n\t\t);\n\t}\n\n\tpublic async uploadSummaryWithContext(\n\t\tsummary: ISummaryTree,\n\t\tcontext: ISummaryContext,\n\t): Promise<string> {\n\t\t// Creation flow with attachment blobs - need to do retries!\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.uploadSummaryWithContext(summary, context),\n\t\t\t\"storage_uploadSummaryWithContext\",\n\t\t);\n\t}\n\n\tpublic async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.downloadSummary(handle),\n\t\t\t\"storage_downloadSummary\",\n\t\t);\n\t}\n\n\tpublic async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.createBlob(file),\n\t\t\t\"storage_createBlob\",\n\t\t);\n\t}\n\n\tprivate checkStorageDisposed() {\n\t\tif (this._disposed) {\n\t\t\t// pre-0.58 error message: storageServiceDisposedCannotRetry\n\t\t\tthrow new LoggingError(\"Storage Service is disposed. Cannot retry\", {\n\t\t\t\tcanRetry: false,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async runWithRetry<T>(api: () => Promise<T>, callName: string): Promise<T> {\n\t\treturn runWithRetry(api, callName, this.logger, () => this.checkStorageDisposed());\n\t}\n}\n"]}
1
+ {"version":3,"file":"retryErrorsStorageAdapter.js","sourceRoot":"","sources":["../src/retryErrorsStorageAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAuB,MAAM,iCAAiC,CAAC;AAepF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,OAAO,yBAAyB;IAErC,YACkB,sBAA+C,EAC/C,MAA2B;QAD3B,2BAAsB,GAAtB,sBAAsB,CAAyB;QAC/C,WAAM,GAAN,MAAM,CAAqB;QAHrC,cAAS,GAAG,KAAK,CAAC;IAIvB,CAAC;IAEJ,IAAW,QAAQ;QAClB,OAAO,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC;IAC7C,CAAC;IACD,IAAW,QAAQ;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IACM,OAAO;QACb,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACvB,CAAC;IAED,IAAW,aAAa;QACvB,OAAO,IAAI,CAAC,sBAAsB,CAAC,aAAa,CAAC;IAClD,CAAC;IAED,kDAAkD;IAC3C,KAAK,CAAC,eAAe,CAAC,OAAkB;QAC9C,OAAO,IAAI,CAAC,YAAY,CACvB,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,eAAe,CAAC,OAAO,CAAC,EAChE,yBAAyB,CACzB,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,QAAQ,CAAC,EAAU;QAC/B,OAAO,IAAI,CAAC,YAAY,CACvB,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,EAAE,CAAC,EACpD,kBAAkB,CAClB,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,WAAW;IACvB,kDAAkD;IAClD,SAAwB,EACxB,KAAa,EACb,YAAqB,EACrB,WAAyB;QAEzB,OAAO,IAAI,CAAC,YAAY,CACvB,KAAK,IAAI,EAAE,CACV,IAAI,CAAC,sBAAsB,CAAC,WAAW,CACtC,SAAS,EACT,KAAK,EACL,YAAY,EACZ,WAAW,CACX,EACF,qBAAqB,CACrB,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,wBAAwB,CACpC,OAAqB,EACrB,OAAwB;QAExB,4DAA4D;QAC5D,OAAO,IAAI,CAAC,YAAY,CACvB,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,wBAAwB,CAAC,OAAO,EAAE,OAAO,CAAC,EAClF,kCAAkC,CAClC,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,MAAsB;QAClD,OAAO,IAAI,CAAC,YAAY,CACvB,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,eAAe,CAAC,MAAM,CAAC,EAC/D,yBAAyB,CACzB,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,IAAqB;QAC5C,OAAO,IAAI,CAAC,YAAY,CACvB,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,IAAI,CAAC,EACxD,oBAAoB,CACpB,CAAC;IACH,CAAC;IAEO,oBAAoB;QAC3B,IAAI,IAAI,CAAC,SAAS,EAAE;YACnB,4DAA4D;YAC5D,MAAM,IAAI,YAAY,CAAC,2CAA2C,EAAE;gBACnE,QAAQ,EAAE,KAAK;aACf,CAAC,CAAC;SACH;IACF,CAAC;IAEO,KAAK,CAAC,YAAY,CAAI,GAAqB,EAAE,QAAgB;QACpE,OAAO,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACpF,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { LoggingError, ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport {\n\tFetchSource,\n\tIDocumentStorageService,\n\tIDocumentStorageServicePolicies,\n\tISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport {\n\tICreateBlobResponse,\n\tISnapshotTree,\n\tISummaryHandle,\n\tISummaryTree,\n\tIVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport { IDisposable } from \"@fluidframework/core-interfaces\";\nimport { runWithRetry } from \"./retryUtils\";\n\nexport class RetryErrorsStorageAdapter implements IDocumentStorageService, IDisposable {\n\tprivate _disposed = false;\n\tconstructor(\n\t\tprivate readonly internalStorageService: IDocumentStorageService,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t) {}\n\n\tpublic get policies(): IDocumentStorageServicePolicies | undefined {\n\t\treturn this.internalStorageService.policies;\n\t}\n\tpublic get disposed() {\n\t\treturn this._disposed;\n\t}\n\tpublic dispose() {\n\t\tthis._disposed = true;\n\t}\n\n\tpublic get repositoryUrl(): string {\n\t\treturn this.internalStorageService.repositoryUrl;\n\t}\n\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.getSnapshotTree(version),\n\t\t\t\"storage_getSnapshotTree\",\n\t\t);\n\t}\n\n\tpublic async readBlob(id: string): Promise<ArrayBufferLike> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.readBlob(id),\n\t\t\t\"storage_readBlob\",\n\t\t);\n\t}\n\n\tpublic async getVersions(\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tversionId: string | null,\n\t\tcount: number,\n\t\tscenarioName?: string,\n\t\tfetchSource?: FetchSource,\n\t): Promise<IVersion[]> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () =>\n\t\t\t\tthis.internalStorageService.getVersions(\n\t\t\t\t\tversionId,\n\t\t\t\t\tcount,\n\t\t\t\t\tscenarioName,\n\t\t\t\t\tfetchSource,\n\t\t\t\t),\n\t\t\t\"storage_getVersions\",\n\t\t);\n\t}\n\n\tpublic async uploadSummaryWithContext(\n\t\tsummary: ISummaryTree,\n\t\tcontext: ISummaryContext,\n\t): Promise<string> {\n\t\t// Creation flow with attachment blobs - need to do retries!\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.uploadSummaryWithContext(summary, context),\n\t\t\t\"storage_uploadSummaryWithContext\",\n\t\t);\n\t}\n\n\tpublic async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.downloadSummary(handle),\n\t\t\t\"storage_downloadSummary\",\n\t\t);\n\t}\n\n\tpublic async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageService.createBlob(file),\n\t\t\t\"storage_createBlob\",\n\t\t);\n\t}\n\n\tprivate checkStorageDisposed() {\n\t\tif (this._disposed) {\n\t\t\t// pre-0.58 error message: storageServiceDisposedCannotRetry\n\t\t\tthrow new LoggingError(\"Storage Service is disposed. Cannot retry\", {\n\t\t\t\tcanRetry: false,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async runWithRetry<T>(api: () => Promise<T>, callName: string): Promise<T> {\n\t\treturn runWithRetry(api, callName, this.logger, () => this.checkStorageDisposed());\n\t}\n}\n"]}
package/lib/vroom.d.ts CHANGED
@@ -3,8 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
6
- import { InstrumentedStorageTokenFetcher, IOdspUrlParts } from "@fluidframework/odsp-driver-definitions";
7
- import { ISocketStorageDiscovery } from "./contracts";
6
+ import { InstrumentedStorageTokenFetcher, ISocketStorageDiscovery, IOdspUrlParts } from "@fluidframework/odsp-driver-definitions";
8
7
  import { TokenFetchOptionsEx } from "./odspUtils";
9
8
  import { EpochTracker } from "./epochTracker";
10
9
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"vroom.d.ts","sourceRoot":"","sources":["../src/vroom.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,mBAAmB,EAAoB,MAAM,iCAAiC,CAAC;AACxF,OAAO,EACN,+BAA+B,EAC/B,aAAa,EACb,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAa,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAQ9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,gBAAgB,CACrC,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,mBAAmB,EAC3B,eAAe,EAAE,+BAA+B,EAChD,YAAY,EAAE,YAAY,EAC1B,kBAAkB,EAAE,OAAO,EAC3B,OAAO,EAAE,mBAAmB,EAC5B,yBAAyB,EAAE,OAAO,GAAG,SAAS,EAC9C,uBAAuB,EAAE,OAAO,EAChC,gBAAgB,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,uBAAuB,CAAC,CA+ElC"}
1
+ {"version":3,"file":"vroom.d.ts","sourceRoot":"","sources":["../src/vroom.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,mBAAmB,EAAoB,MAAM,iCAAiC,CAAC;AACxF,OAAO,EACN,+BAA+B,EAC/B,uBAAuB,EACvB,aAAa,EACb,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAa,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAQ9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,gBAAgB,CACrC,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,mBAAmB,EAC3B,eAAe,EAAE,+BAA+B,EAChD,YAAY,EAAE,YAAY,EAC1B,kBAAkB,EAAE,OAAO,EAC3B,OAAO,EAAE,mBAAmB,EAC5B,yBAAyB,EAAE,OAAO,GAAG,SAAS,EAC9C,uBAAuB,EAAE,OAAO,EAChC,gBAAgB,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,uBAAuB,CAAC,CA+ElC"}
package/lib/vroom.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"vroom.js","sourceRoot":"","sources":["../src/vroom.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { v4 as uuid } from \"uuid\";\nimport { ITelemetryProperties } from \"@fluidframework/common-definitions\";\nimport { ITelemetryLoggerExt, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport {\n\tInstrumentedStorageTokenFetcher,\n\tIOdspUrlParts,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISocketStorageDiscovery } from \"./contracts\";\nimport { getOrigin, TokenFetchOptionsEx } from \"./odspUtils\";\nimport { getApiRoot } from \"./odspUrlHelper\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { runWithRetry } from \"./retryUtils\";\n\ninterface IJoinSessionBody {\n\trequestSocketToken: boolean;\n\tguestDisplayName: string;\n}\n\n/**\n * Makes join session call on SPO to get information about the web socket for a document\n * @param urlParts - The SPO drive id, itemId, siteUrl that this request should be made against\n * @param path - The API path that is relevant to this request\n * @param method - The type of request, such as GET or POST\n * @param logger - A logger to use for this request\n * @param getStorageToken - A function that is able to provide the access token for this request\n * @param epochTracker - fetch wrapper which incorporates epoch logic around joinSession call\n * @param requestSocketToken - flag indicating whether joinSession is expected to return access token\n * which is used when establishing websocket connection with collab session backend service.\n * @param options - Options to fetch the token.\n * @param disableJoinSessionRefresh - Whether the caller wants to disable refreshing join session periodically.\n * @param isRefreshingJoinSession - whether call is to refresh the session before expiry.\n * @param guestDisplayName - display name used to identify guest user joining a session.\n * This is optional and used only when collab session is being joined via invite.\n */\nexport async function fetchJoinSession(\n\turlParts: IOdspUrlParts,\n\tpath: string,\n\tmethod: string,\n\tlogger: ITelemetryLoggerExt,\n\tgetStorageToken: InstrumentedStorageTokenFetcher,\n\tepochTracker: EpochTracker,\n\trequestSocketToken: boolean,\n\toptions: TokenFetchOptionsEx,\n\tdisableJoinSessionRefresh: boolean | undefined,\n\tisRefreshingJoinSession: boolean,\n\tguestDisplayName?: string,\n): Promise<ISocketStorageDiscovery> {\n\tconst token = await getStorageToken(options, \"JoinSession\");\n\n\tconst tokenRefreshProps = options.refresh\n\t\t? { hasClaims: !!options.claims, hasTenantId: !!options.tenantId }\n\t\t: {};\n\tconst details: ITelemetryProperties = {\n\t\trefreshedToken: options.refresh,\n\t\trequestSocketToken,\n\t\t...tokenRefreshProps,\n\t\trefreshingSession: isRefreshingJoinSession,\n\t};\n\n\treturn PerformanceEvent.timedExecAsync(\n\t\tlogger,\n\t\t{\n\t\t\teventName: \"JoinSession\",\n\t\t\tattempts: options.refresh ? 2 : 1,\n\t\t\tdetails: JSON.stringify(details),\n\t\t\t...tokenRefreshProps,\n\t\t},\n\t\tasync (event) => {\n\t\t\tconst siteOrigin = getOrigin(urlParts.siteUrl);\n\t\t\tconst formBoundary = uuid();\n\t\t\tlet postBody = `--${formBoundary}\\r\\n`;\n\t\t\tpostBody += `Authorization: Bearer ${token}\\r\\n`;\n\t\t\tpostBody += `X-HTTP-Method-Override: POST\\r\\n`;\n\t\t\tpostBody += `Content-Type: application/json\\r\\n`;\n\t\t\tif (!disableJoinSessionRefresh) {\n\t\t\t\tpostBody += `prefer: FluidRemoveCheckAccess\\r\\n`;\n\t\t\t}\n\t\t\tpostBody += `_post: 1\\r\\n`;\n\t\t\t// Name should be there when socket token is requested and vice-versa.\n\t\t\tif (requestSocketToken && guestDisplayName !== undefined) {\n\t\t\t\tconst body: IJoinSessionBody = {\n\t\t\t\t\trequestSocketToken: true,\n\t\t\t\t\tguestDisplayName,\n\t\t\t\t};\n\t\t\t\tpostBody += `\\r\\n${JSON.stringify(body)}\\r\\n`;\n\t\t\t}\n\t\t\tpostBody += `\\r\\n--${formBoundary}--`;\n\t\t\tconst headers: { [index: string]: string } = {\n\t\t\t\t\"Content-Type\": `multipart/form-data;boundary=${formBoundary}`,\n\t\t\t};\n\n\t\t\tconst response = await runWithRetry(\n\t\t\t\tasync () =>\n\t\t\t\t\tepochTracker.fetchAndParseAsJSON<ISocketStorageDiscovery>(\n\t\t\t\t\t\t`${getApiRoot(siteOrigin)}/drives/${urlParts.driveId}/items/${\n\t\t\t\t\t\t\turlParts.itemId\n\t\t\t\t\t\t}/${path}?ump=1`,\n\t\t\t\t\t\t{ method, headers, body: postBody },\n\t\t\t\t\t\t\"joinSession\",\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t),\n\t\t\t\t\"joinSession\",\n\t\t\t\tlogger,\n\t\t\t);\n\n\t\t\tconst socketUrl = response.content.deltaStreamSocketUrl;\n\t\t\t// expecting socketUrl to be something like https://{hostName}/...\n\t\t\tconst webSocketHostName = socketUrl.split(\"/\")[2];\n\n\t\t\t// TODO SPO-specific telemetry\n\t\t\tevent.end({\n\t\t\t\t...response.propsToLog,\n\t\t\t\t// pushV2 websocket urls will contain pushf\n\t\t\t\tpushv2: socketUrl.includes(\"pushf\"),\n\t\t\t\twebSocketHostName,\n\t\t\t\trefreshSessionDurationSeconds: response.content.refreshSessionDurationSeconds,\n\t\t\t});\n\n\t\t\tif (response.content.runtimeTenantId && !response.content.tenantId) {\n\t\t\t\tresponse.content.tenantId = response.content.runtimeTenantId;\n\t\t\t}\n\n\t\t\treturn response.content;\n\t\t},\n\t);\n}\n"]}
1
+ {"version":3,"file":"vroom.js","sourceRoot":"","sources":["../src/vroom.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { v4 as uuid } from \"uuid\";\nimport { ITelemetryProperties } from \"@fluidframework/core-interfaces\";\nimport { ITelemetryLoggerExt, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport {\n\tInstrumentedStorageTokenFetcher,\n\tISocketStorageDiscovery,\n\tIOdspUrlParts,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { getOrigin, TokenFetchOptionsEx } from \"./odspUtils\";\nimport { getApiRoot } from \"./odspUrlHelper\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { runWithRetry } from \"./retryUtils\";\n\ninterface IJoinSessionBody {\n\trequestSocketToken: boolean;\n\tguestDisplayName: string;\n}\n\n/**\n * Makes join session call on SPO to get information about the web socket for a document\n * @param urlParts - The SPO drive id, itemId, siteUrl that this request should be made against\n * @param path - The API path that is relevant to this request\n * @param method - The type of request, such as GET or POST\n * @param logger - A logger to use for this request\n * @param getStorageToken - A function that is able to provide the access token for this request\n * @param epochTracker - fetch wrapper which incorporates epoch logic around joinSession call\n * @param requestSocketToken - flag indicating whether joinSession is expected to return access token\n * which is used when establishing websocket connection with collab session backend service.\n * @param options - Options to fetch the token.\n * @param disableJoinSessionRefresh - Whether the caller wants to disable refreshing join session periodically.\n * @param isRefreshingJoinSession - whether call is to refresh the session before expiry.\n * @param guestDisplayName - display name used to identify guest user joining a session.\n * This is optional and used only when collab session is being joined via invite.\n */\nexport async function fetchJoinSession(\n\turlParts: IOdspUrlParts,\n\tpath: string,\n\tmethod: string,\n\tlogger: ITelemetryLoggerExt,\n\tgetStorageToken: InstrumentedStorageTokenFetcher,\n\tepochTracker: EpochTracker,\n\trequestSocketToken: boolean,\n\toptions: TokenFetchOptionsEx,\n\tdisableJoinSessionRefresh: boolean | undefined,\n\tisRefreshingJoinSession: boolean,\n\tguestDisplayName?: string,\n): Promise<ISocketStorageDiscovery> {\n\tconst token = await getStorageToken(options, \"JoinSession\");\n\n\tconst tokenRefreshProps = options.refresh\n\t\t? { hasClaims: !!options.claims, hasTenantId: !!options.tenantId }\n\t\t: {};\n\tconst details: ITelemetryProperties = {\n\t\trefreshedToken: options.refresh,\n\t\trequestSocketToken,\n\t\t...tokenRefreshProps,\n\t\trefreshingSession: isRefreshingJoinSession,\n\t};\n\n\treturn PerformanceEvent.timedExecAsync(\n\t\tlogger,\n\t\t{\n\t\t\teventName: \"JoinSession\",\n\t\t\tattempts: options.refresh ? 2 : 1,\n\t\t\tdetails: JSON.stringify(details),\n\t\t\t...tokenRefreshProps,\n\t\t},\n\t\tasync (event) => {\n\t\t\tconst siteOrigin = getOrigin(urlParts.siteUrl);\n\t\t\tconst formBoundary = uuid();\n\t\t\tlet postBody = `--${formBoundary}\\r\\n`;\n\t\t\tpostBody += `Authorization: Bearer ${token}\\r\\n`;\n\t\t\tpostBody += `X-HTTP-Method-Override: POST\\r\\n`;\n\t\t\tpostBody += `Content-Type: application/json\\r\\n`;\n\t\t\tif (!disableJoinSessionRefresh) {\n\t\t\t\tpostBody += `prefer: FluidRemoveCheckAccess\\r\\n`;\n\t\t\t}\n\t\t\tpostBody += `_post: 1\\r\\n`;\n\t\t\t// Name should be there when socket token is requested and vice-versa.\n\t\t\tif (requestSocketToken && guestDisplayName !== undefined) {\n\t\t\t\tconst body: IJoinSessionBody = {\n\t\t\t\t\trequestSocketToken: true,\n\t\t\t\t\tguestDisplayName,\n\t\t\t\t};\n\t\t\t\tpostBody += `\\r\\n${JSON.stringify(body)}\\r\\n`;\n\t\t\t}\n\t\t\tpostBody += `\\r\\n--${formBoundary}--`;\n\t\t\tconst headers: { [index: string]: string } = {\n\t\t\t\t\"Content-Type\": `multipart/form-data;boundary=${formBoundary}`,\n\t\t\t};\n\n\t\t\tconst response = await runWithRetry(\n\t\t\t\tasync () =>\n\t\t\t\t\tepochTracker.fetchAndParseAsJSON<ISocketStorageDiscovery>(\n\t\t\t\t\t\t`${getApiRoot(siteOrigin)}/drives/${urlParts.driveId}/items/${\n\t\t\t\t\t\t\turlParts.itemId\n\t\t\t\t\t\t}/${path}?ump=1`,\n\t\t\t\t\t\t{ method, headers, body: postBody },\n\t\t\t\t\t\t\"joinSession\",\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t),\n\t\t\t\t\"joinSession\",\n\t\t\t\tlogger,\n\t\t\t);\n\n\t\t\tconst socketUrl = response.content.deltaStreamSocketUrl;\n\t\t\t// expecting socketUrl to be something like https://{hostName}/...\n\t\t\tconst webSocketHostName = socketUrl.split(\"/\")[2];\n\n\t\t\t// TODO SPO-specific telemetry\n\t\t\tevent.end({\n\t\t\t\t...response.propsToLog,\n\t\t\t\t// pushV2 websocket urls will contain pushf\n\t\t\t\tpushv2: socketUrl.includes(\"pushf\"),\n\t\t\t\twebSocketHostName,\n\t\t\t\trefreshSessionDurationSeconds: response.content.refreshSessionDurationSeconds,\n\t\t\t});\n\n\t\t\tif (response.content.runtimeTenantId && !response.content.tenantId) {\n\t\t\t\tresponse.content.tenantId = response.content.runtimeTenantId;\n\t\t\t}\n\n\t\t\treturn response.content;\n\t\t},\n\t);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/odsp-driver",
3
- "version": "2.0.0-dev.5.2.0.169897",
3
+ "version": "2.0.0-dev.5.3.2.178189",
4
4
  "description": "Socket storage implementation for SPO and ODC",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -37,28 +37,29 @@
37
37
  "dependencies": {
38
38
  "@fluidframework/common-definitions": "^0.20.1",
39
39
  "@fluidframework/common-utils": "^1.1.1",
40
- "@fluidframework/core-interfaces": "2.0.0-dev.5.2.0.169897",
41
- "@fluidframework/driver-base": "2.0.0-dev.5.2.0.169897",
42
- "@fluidframework/driver-definitions": "2.0.0-dev.5.2.0.169897",
43
- "@fluidframework/driver-utils": "2.0.0-dev.5.2.0.169897",
40
+ "@fluidframework/core-interfaces": "2.0.0-dev.5.3.2.178189",
41
+ "@fluidframework/core-utils": "2.0.0-dev.5.3.2.178189",
42
+ "@fluidframework/driver-base": "2.0.0-dev.5.3.2.178189",
43
+ "@fluidframework/driver-definitions": "2.0.0-dev.5.3.2.178189",
44
+ "@fluidframework/driver-utils": "2.0.0-dev.5.3.2.178189",
44
45
  "@fluidframework/gitresources": "^0.1039.1000",
45
- "@fluidframework/odsp-doclib-utils": "2.0.0-dev.5.2.0.169897",
46
- "@fluidframework/odsp-driver-definitions": "2.0.0-dev.5.2.0.169897",
46
+ "@fluidframework/odsp-doclib-utils": "2.0.0-dev.5.3.2.178189",
47
+ "@fluidframework/odsp-driver-definitions": "2.0.0-dev.5.3.2.178189",
47
48
  "@fluidframework/protocol-base": "^0.1039.1000",
48
49
  "@fluidframework/protocol-definitions": "^1.1.0",
49
- "@fluidframework/telemetry-utils": "2.0.0-dev.5.2.0.169897",
50
+ "@fluidframework/telemetry-utils": "2.0.0-dev.5.3.2.178189",
50
51
  "abort-controller": "^3.0.0",
51
52
  "node-fetch": "^2.6.9",
52
53
  "socket.io-client": "^4.6.1",
53
54
  "uuid": "^8.3.1"
54
55
  },
55
56
  "devDependencies": {
56
- "@fluid-tools/build-cli": "^0.20.0-169245",
57
+ "@fluid-tools/build-cli": "^0.21.0",
57
58
  "@fluidframework/build-common": "^1.2.0",
58
- "@fluidframework/build-tools": "^0.20.0-169245",
59
+ "@fluidframework/build-tools": "^0.21.0",
59
60
  "@fluidframework/eslint-config-fluid": "^2.0.0",
60
- "@fluidframework/mocha-test-setup": "2.0.0-dev.5.2.0.169897",
61
- "@fluidframework/odsp-driver-previous": "npm:@fluidframework/odsp-driver@2.0.0-internal.5.0.0",
61
+ "@fluidframework/mocha-test-setup": "2.0.0-dev.5.3.2.178189",
62
+ "@fluidframework/odsp-driver-previous": "npm:@fluidframework/odsp-driver@2.0.0-internal.5.2.0",
62
63
  "@microsoft/api-extractor": "^7.34.4",
63
64
  "@types/mocha": "^9.1.1",
64
65
  "@types/node": "^14.18.38",
@@ -80,7 +81,21 @@
80
81
  "typescript": "~4.5.5"
81
82
  },
82
83
  "typeValidation": {
83
- "broken": {}
84
+ "broken": {
85
+ "ClassDeclaration_OdspDocumentServiceFactoryWithCodeSplit": {
86
+ "forwardCompat": false
87
+ },
88
+ "ClassDeclaration_OdspDocumentServiceFactory": {
89
+ "forwardCompat": false
90
+ },
91
+ "ClassDeclaration_OdspDocumentServiceFactoryCore": {
92
+ "forwardCompat": false
93
+ },
94
+ "RemovedInterfaceDeclaration_ISocketStorageDiscovery": {
95
+ "forwardCompat": false,
96
+ "backCompat": false
97
+ }
98
+ }
84
99
  },
85
100
  "scripts": {
86
101
  "build": "fluid-build . --task build",
@@ -106,6 +121,6 @@
106
121
  "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
107
122
  "tsc": "tsc",
108
123
  "typetests:gen": "fluid-type-test-generator",
109
- "typetests:prepare": "flub generate typetests --prepare --dir . --pin"
124
+ "typetests:prepare": "flub typetests --dir . --reset --previous --normalize"
110
125
  }
111
126
  }
package/src/contracts.ts CHANGED
@@ -7,40 +7,6 @@ import * as api from "@fluidframework/protocol-definitions";
7
7
  import { HostStoragePolicy } from "@fluidframework/odsp-driver-definitions";
8
8
  import { ISnapshotContents } from "./odspPublicUtils";
9
9
 
10
- /**
11
- * Socket storage discovery api response
12
- */
13
- export interface ISocketStorageDiscovery {
14
- // The id of the web socket
15
- id: string;
16
-
17
- // SPO gives us runtimeTenantId, we remap it to tenantId
18
- // See getSocketStorageDiscovery
19
- runtimeTenantId?: string;
20
- tenantId: string;
21
-
22
- snapshotStorageUrl: string;
23
- deltaStorageUrl: string;
24
-
25
- /**
26
- * PUSH URL
27
- */
28
- deltaStreamSocketUrl: string;
29
-
30
- /**
31
- * The access token for PushChannel. Optionally returned, depending on implementation.
32
- * OneDrive for Consumer implementation returns it and OneDrive for Business implementation
33
- * does not return it and instead expects token to be returned via `getWebsocketToken` callback
34
- * passed as a parameter to `OdspDocumentService.create()` factory.
35
- */
36
- socketToken?: string;
37
-
38
- /**
39
- * This is the time within which client has to refresh the session on (ODSP) relay service.
40
- */
41
- refreshSessionDurationSeconds?: number;
42
- }
43
-
44
10
  /**
45
11
  * Interface for error responses for the WebSocket connection
46
12
  */
@@ -11,6 +11,7 @@ import {
11
11
  isFluidError,
12
12
  normalizeError,
13
13
  loggerToMonitoringContext,
14
+ wrapError,
14
15
  } from "@fluidframework/telemetry-utils";
15
16
  import {
16
17
  ThrottlingError,
@@ -443,11 +444,13 @@ export class EpochTracker implements IPersistedFileCache {
443
444
  // If it was categorized as epoch error but the epoch returned in response matches with the client epoch
444
445
  // then it was coherency 409, so rethrow it as throttling error so that it can retried. Default throttling
445
446
  // time is 1s.
446
- throw new ThrottlingError(
447
- `Coherency 409: ${error.message}`,
448
- 1 /* retryAfterSeconds */,
449
- { [Odsp409Error]: true, driverVersion },
450
- );
447
+ const newError = wrapError(error, (message: string) => {
448
+ return new ThrottlingError(`Coherency 409: ${message}`, 1 /* retryAfterSeconds */, {
449
+ [Odsp409Error]: true,
450
+ driverVersion,
451
+ });
452
+ });
453
+ throw newError;
451
454
  }
452
455
  }
453
456
 
@@ -7,7 +7,7 @@ import { IDocumentService, IResolvedUrl } from "@fluidframework/driver-definitio
7
7
  import { UsageError } from "@fluidframework/driver-utils";
8
8
  import { TelemetryLogger } from "@fluidframework/telemetry-utils";
9
9
  import { ISummaryTree } from "@fluidframework/protocol-definitions";
10
- import { ITelemetryBaseLogger } from "@fluidframework/common-definitions";
10
+ import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
11
11
  import { createOdspLogger, getOdspResolvedUrl } from "../odspUtils";
12
12
  import { ICacheAndTracker } from "../epochTracker";
13
13
  import { OdspDocumentServiceFactoryCore } from "../odspDocumentServiceFactoryCore";
package/src/odspCache.ts CHANGED
@@ -2,16 +2,16 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { PromiseCache } from "@fluidframework/common-utils";
5
+ import { PromiseCache } from "@fluidframework/core-utils";
6
6
  import {
7
7
  IOdspResolvedUrl,
8
8
  IFileEntry,
9
9
  IEntry,
10
10
  IPersistedCache,
11
11
  ICacheEntry,
12
+ ISocketStorageDiscovery,
12
13
  getKeyForCacheEntry,
13
14
  } from "@fluidframework/odsp-driver-definitions";
14
- import { ISocketStorageDiscovery } from "./contracts";
15
15
  import { ISnapshotContents } from "./odspPublicUtils";
16
16
 
17
17
  /**
@@ -25,13 +25,17 @@ import {
25
25
  TokenFetchOptions,
26
26
  HostStoragePolicy,
27
27
  InstrumentedStorageTokenFetcher,
28
+ ISocketStorageDiscovery,
28
29
  OdspErrorType,
29
30
  } from "@fluidframework/odsp-driver-definitions";
30
31
  import { hasFacetCodes } from "@fluidframework/odsp-doclib-utils";
31
- import { ISocketStorageDiscovery } from "./contracts";
32
32
  import { IOdspCache } from "./odspCache";
33
33
  import { OdspDocumentDeltaConnection } from "./odspDocumentDeltaConnection";
34
- import { getWithRetryForTokenRefresh, TokenFetchOptionsEx } from "./odspUtils";
34
+ import {
35
+ getJoinSessionCacheKey,
36
+ getWithRetryForTokenRefresh,
37
+ TokenFetchOptionsEx,
38
+ } from "./odspUtils";
35
39
  import { fetchJoinSession } from "./vroom";
36
40
  import { EpochTracker } from "./epochTracker";
37
41
  import { pkgVersion as driverVersion } from "./packageVersion";
@@ -79,7 +83,7 @@ export class OdspDelayLoadedDeltaStream {
79
83
  private readonly opsReceived: (ops: ISequencedDocumentMessage[]) => void,
80
84
  private readonly socketReferenceKeyPrefix?: string,
81
85
  ) {
82
- this.joinSessionKey = `${this.odspResolvedUrl.hashedDocumentId}/joinsession`;
86
+ this.joinSessionKey = getJoinSessionCacheKey(this.odspResolvedUrl);
83
87
  }
84
88
 
85
89
  public get resolvedUrl(): IResolvedUrl {
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { default as AbortController } from "abort-controller";
7
7
  import { v4 as uuid } from "uuid";
8
- import { ITelemetryProperties } from "@fluidframework/common-definitions";
8
+ import { ITelemetryProperties } from "@fluidframework/core-interfaces";
9
9
  import { validateMessages } from "@fluidframework/driver-base";
10
10
  import { ITelemetryLoggerExt, PerformanceEvent } from "@fluidframework/telemetry-utils";
11
11
  import { assert } from "@fluidframework/common-utils";
@@ -128,7 +128,7 @@ export class OdspDeltaStorageService {
128
128
  }
129
129
 
130
130
  export class OdspDeltaStorageWithCache implements IDocumentDeltaStorageService {
131
- private firstCacheMiss = Number.MAX_SAFE_INTEGER;
131
+ private firstCacheMiss = false;
132
132
 
133
133
  public constructor(
134
134
  private snapshotOps: ISequencedDocumentMessage[] | undefined,
@@ -189,9 +189,12 @@ export class OdspDeltaStorageWithCache implements IDocumentDeltaStorageService {
189
189
 
190
190
  // Cache in normal flow is continuous. Once there is a miss, stop consulting cache.
191
191
  // This saves a bit of processing time
192
- if (from < this.firstCacheMiss) {
192
+ if (!this.firstCacheMiss) {
193
193
  const messagesFromCache = await this.getCached(from, to);
194
194
  validateMessages("cached", messagesFromCache, from, this.logger);
195
+ // Set the firstCacheMiss as true in case we didn't get all the ops.
196
+ // This will save an extra cache read on "DocumentOpen" or "PostDocumentOpen".
197
+ this.firstCacheMiss = from + messagesFromCache.length < to;
195
198
  if (messagesFromCache.length !== 0) {
196
199
  opsFromCache += messagesFromCache.length;
197
200
  return {
@@ -199,7 +202,6 @@ export class OdspDeltaStorageWithCache implements IDocumentDeltaStorageService {
199
202
  partialResult: true,
200
203
  };
201
204
  }
202
- this.firstCacheMiss = Math.min(this.firstCacheMiss, from);
203
205
  }
204
206
 
205
207
  if (cachedOnly) {
@@ -238,6 +240,7 @@ export class OdspDeltaStorageWithCache implements IDocumentDeltaStorageService {
238
240
  opsFromSnapshot,
239
241
  opsFromCache,
240
242
  opsFromStorage,
243
+ reason: fetchReason,
241
244
  });
242
245
  }
243
246
  });
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { ITelemetryBaseLogger } from "@fluidframework/common-definitions";
6
+ import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
7
7
  import {
8
8
  IDocumentService,
9
9
  IDocumentServiceFactory,
@@ -27,6 +27,8 @@ import {
27
27
  SharingLinkRole,
28
28
  ShareLinkTypes,
29
29
  ISharingLinkKind,
30
+ ISocketStorageDiscovery,
31
+ IRelaySessionAwareDriverFactory,
30
32
  } from "@fluidframework/odsp-driver-definitions";
31
33
  import { v4 as uuid } from "uuid";
32
34
  import { INonPersistentCache, LocalPersistentCache, NonPersistentCache } from "./odspCache";
@@ -39,6 +41,7 @@ import {
39
41
  toInstrumentedOdspTokenFetcher,
40
42
  IExistingFileInfo,
41
43
  isNewFileInfo,
44
+ getJoinSessionCacheKey,
42
45
  } from "./odspUtils";
43
46
 
44
47
  /**
@@ -48,7 +51,9 @@ import {
48
51
  * This constructor should be used by environments that support dynamic imports and that wish
49
52
  * to leverage code splitting as a means to keep bundles as small as possible.
50
53
  */
51
- export class OdspDocumentServiceFactoryCore implements IDocumentServiceFactory {
54
+ export class OdspDocumentServiceFactoryCore
55
+ implements IDocumentServiceFactory, IRelaySessionAwareDriverFactory
56
+ {
52
57
  private readonly nonPersistentCache: INonPersistentCache = new NonPersistentCache();
53
58
  private readonly socketReferenceKeyPrefix?: string;
54
59
 
@@ -56,6 +61,26 @@ export class OdspDocumentServiceFactoryCore implements IDocumentServiceFactory {
56
61
  return this.nonPersistentCache.snapshotPrefetchResultCache;
57
62
  }
58
63
 
64
+ public get IRelaySessionAwareDriverFactory() {
65
+ return this;
66
+ }
67
+
68
+ /**
69
+ * This function would return info about relay service session only if this factory established (or attempted to
70
+ * establish) connection very recently. Otherwise, it will return undefined.
71
+ * @param resolvedUrl - resolved url for container
72
+ * @returns - Current join session response stored in cache. Undefined if not present.
73
+ */
74
+ public async getRelayServiceSessionInfo(
75
+ resolvedUrl: IResolvedUrl,
76
+ ): Promise<ISocketStorageDiscovery | undefined> {
77
+ const odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);
78
+ const joinSessionResponse = await this.nonPersistentCache.sessionJoinCache.get(
79
+ getJoinSessionCacheKey(odspResolvedUrl),
80
+ );
81
+ return joinSessionResponse?.joinSessionResponse;
82
+ }
83
+
59
84
  public async createContainer(
60
85
  createNewSummary: ISummaryTree | undefined,
61
86
  createNewResolvedUrl: IResolvedUrl,
@@ -437,6 +437,8 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
437
437
  const result = await this.cache.snapshotPrefetchResultCache
438
438
  ?.get(prefetchCacheKey)
439
439
  ?.then(async (response) => {
440
+ // Remove it from cache once used.
441
+ this.cache.snapshotPrefetchResultCache.remove(prefetchCacheKey);
440
442
  // Validate the epoch from the prefetched snapshot result.
441
443
  await this.epochTracker.validateEpoch(response.fluidEpoch, "treesLatest");
442
444
  return response;
@@ -3,13 +3,12 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { PromiseCache } from "@fluidframework/common-utils";
6
- import { IRequest } from "@fluidframework/core-interfaces";
6
+ import { ITelemetryBaseLogger, IRequest } from "@fluidframework/core-interfaces";
7
7
  import {
8
8
  IContainerPackageInfo,
9
9
  IResolvedUrl,
10
10
  IUrlResolver,
11
11
  } from "@fluidframework/driver-definitions";
12
- import { ITelemetryBaseLogger } from "@fluidframework/common-definitions";
13
12
  import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
14
13
  import {
15
14
  IOdspResolvedUrl,
package/src/odspUtils.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { ITelemetryProperties, ITelemetryBaseLogger } from "@fluidframework/common-definitions";
6
+ import { ITelemetryProperties, ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
7
7
  import { IResolvedUrl, DriverErrorType } from "@fluidframework/driver-definitions";
8
8
  import {
9
9
  isOnline,
@@ -445,3 +445,7 @@ export async function measureP<T>(callback: () => Promise<T>): Promise<[T, numbe
445
445
  const time = performance.now() - start;
446
446
  return [result, time];
447
447
  }
448
+
449
+ export function getJoinSessionCacheKey(odspResolvedUrl: IOdspResolvedUrl) {
450
+ return `${odspResolvedUrl.hashedDocumentId}/joinsession`;
451
+ }
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/odsp-driver";
9
- export const pkgVersion = "2.0.0-dev.5.2.0.169897";
9
+ export const pkgVersion = "2.0.0-dev.5.3.2.178189";
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { default as AbortController } from "abort-controller";
7
- import { ITelemetryBaseLogger } from "@fluidframework/common-definitions";
7
+ import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
8
8
  import { assert, Deferred, performance } from "@fluidframework/common-utils";
9
9
  import { IResolvedUrl } from "@fluidframework/driver-definitions";
10
10
  import {
@@ -141,15 +141,24 @@ export async function prefetchLatestSnapshot(
141
141
  });
142
142
  assert(cacheP !== undefined, 0x1e7 /* "caching was not performed!" */);
143
143
  await cacheP;
144
+ // Schedule it to remove from cache after 5s.
145
+ // 1. While it's in snapshotNonPersistentCache: Load flow will use this value and will not attempt
146
+ // to fetch snapshot from network again. That's the best from perf POV, but cache will not be
147
+ // updated if we keep it in this cache, thus we want to eventually remove snapshot from this cache.
148
+ // 2. After it's removed from snapshotNonPersistentCache: snapshot is present in persistent cache,
149
+ // so we sill still use it (in accordance with cache policy controlled by host). But load flow will
150
+ // also fetch snapshot (in parallel) from storage and update cache. This is fine long term,
151
+ // but is an extra cost (unneeded network call). However since it is 5s older, new network call
152
+ // will update the snapshot in cache.
153
+ setTimeout(() => {
154
+ snapshotNonPersistentCache?.remove(nonPersistentCacheKey);
155
+ }, 5000);
144
156
  })
145
157
  .catch((err) => {
158
+ // Remove it from the non persistent cache if an error occured.
159
+ snapshotNonPersistentCache?.remove(nonPersistentCacheKey);
146
160
  snapshotContentsWithEpochP.reject(err);
147
161
  throw err;
148
- })
149
- .finally(() => {
150
- // Remove it from the non persistent cache once it is cached in the persistent cache or an error
151
- // occured.
152
- snapshotNonPersistentCache?.remove(nonPersistentCacheKey);
153
162
  });
154
163
  return true;
155
164
  },
@@ -17,7 +17,7 @@ import {
17
17
  ISummaryTree,
18
18
  IVersion,
19
19
  } from "@fluidframework/protocol-definitions";
20
- import { IDisposable } from "@fluidframework/common-definitions";
20
+ import { IDisposable } from "@fluidframework/core-interfaces";
21
21
  import { runWithRetry } from "./retryUtils";
22
22
 
23
23
  export class RetryErrorsStorageAdapter implements IDocumentStorageService, IDisposable {
package/src/vroom.ts CHANGED
@@ -4,13 +4,13 @@
4
4
  */
5
5
 
6
6
  import { v4 as uuid } from "uuid";
7
- import { ITelemetryProperties } from "@fluidframework/common-definitions";
7
+ import { ITelemetryProperties } from "@fluidframework/core-interfaces";
8
8
  import { ITelemetryLoggerExt, PerformanceEvent } from "@fluidframework/telemetry-utils";
9
9
  import {
10
10
  InstrumentedStorageTokenFetcher,
11
+ ISocketStorageDiscovery,
11
12
  IOdspUrlParts,
12
13
  } from "@fluidframework/odsp-driver-definitions";
13
- import { ISocketStorageDiscovery } from "./contracts";
14
14
  import { getOrigin, TokenFetchOptionsEx } from "./odspUtils";
15
15
  import { getApiRoot } from "./odspUrlHelper";
16
16
  import { EpochTracker } from "./epochTracker";