@fluidframework/odsp-driver 0.51.3 → 0.53.0-46105

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 (126) hide show
  1. package/dist/contractsPublic.d.ts +0 -4
  2. package/dist/contractsPublic.d.ts.map +1 -1
  3. package/dist/contractsPublic.js.map +1 -1
  4. package/dist/createFile.d.ts.map +1 -1
  5. package/dist/createFile.js +11 -9
  6. package/dist/createFile.js.map +1 -1
  7. package/dist/createNewUtils.js +5 -4
  8. package/dist/createNewUtils.js.map +1 -1
  9. package/dist/epochTracker.d.ts +2 -1
  10. package/dist/epochTracker.d.ts.map +1 -1
  11. package/dist/epochTracker.js +51 -25
  12. package/dist/epochTracker.js.map +1 -1
  13. package/dist/fetchSnapshot.d.ts.map +1 -1
  14. package/dist/fetchSnapshot.js +1 -1
  15. package/dist/fetchSnapshot.js.map +1 -1
  16. package/dist/getFileLink.d.ts +1 -1
  17. package/dist/getFileLink.d.ts.map +1 -1
  18. package/dist/getFileLink.js +32 -22
  19. package/dist/getFileLink.js.map +1 -1
  20. package/dist/odspDeltaStorageService.d.ts +3 -3
  21. package/dist/odspDeltaStorageService.d.ts.map +1 -1
  22. package/dist/odspDeltaStorageService.js +7 -4
  23. package/dist/odspDeltaStorageService.js.map +1 -1
  24. package/dist/odspDocumentDeltaConnection.d.ts.map +1 -1
  25. package/dist/odspDocumentDeltaConnection.js +2 -0
  26. package/dist/odspDocumentDeltaConnection.js.map +1 -1
  27. package/dist/odspDocumentService.d.ts.map +1 -1
  28. package/dist/odspDocumentService.js +3 -3
  29. package/dist/odspDocumentService.js.map +1 -1
  30. package/dist/odspDocumentStorageManager.d.ts.map +1 -1
  31. package/dist/odspDocumentStorageManager.js +30 -34
  32. package/dist/odspDocumentStorageManager.js.map +1 -1
  33. package/dist/odspDriverUrlResolver.d.ts +0 -4
  34. package/dist/odspDriverUrlResolver.d.ts.map +1 -1
  35. package/dist/odspDriverUrlResolver.js +0 -7
  36. package/dist/odspDriverUrlResolver.js.map +1 -1
  37. package/dist/odspDriverUrlResolverForShareLink.d.ts +2 -6
  38. package/dist/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  39. package/dist/odspDriverUrlResolverForShareLink.js +4 -15
  40. package/dist/odspDriverUrlResolverForShareLink.js.map +1 -1
  41. package/dist/odspError.d.ts.map +1 -1
  42. package/dist/odspError.js +3 -1
  43. package/dist/odspError.js.map +1 -1
  44. package/dist/odspSummaryUploadManager.js +24 -4
  45. package/dist/odspSummaryUploadManager.js.map +1 -1
  46. package/dist/odspUtils.d.ts.map +1 -1
  47. package/dist/odspUtils.js +31 -23
  48. package/dist/odspUtils.js.map +1 -1
  49. package/dist/packageVersion.d.ts +1 -1
  50. package/dist/packageVersion.d.ts.map +1 -1
  51. package/dist/packageVersion.js +1 -1
  52. package/dist/packageVersion.js.map +1 -1
  53. package/dist/zipItDataRepresentationUtils.d.ts.map +1 -1
  54. package/dist/zipItDataRepresentationUtils.js +3 -4
  55. package/dist/zipItDataRepresentationUtils.js.map +1 -1
  56. package/lib/contractsPublic.d.ts +0 -4
  57. package/lib/contractsPublic.d.ts.map +1 -1
  58. package/lib/contractsPublic.js.map +1 -1
  59. package/lib/createFile.d.ts.map +1 -1
  60. package/lib/createFile.js +12 -10
  61. package/lib/createFile.js.map +1 -1
  62. package/lib/createNewUtils.js +5 -4
  63. package/lib/createNewUtils.js.map +1 -1
  64. package/lib/epochTracker.d.ts +2 -1
  65. package/lib/epochTracker.d.ts.map +1 -1
  66. package/lib/epochTracker.js +52 -26
  67. package/lib/epochTracker.js.map +1 -1
  68. package/lib/fetchSnapshot.d.ts.map +1 -1
  69. package/lib/fetchSnapshot.js +1 -1
  70. package/lib/fetchSnapshot.js.map +1 -1
  71. package/lib/getFileLink.d.ts +1 -1
  72. package/lib/getFileLink.d.ts.map +1 -1
  73. package/lib/getFileLink.js +34 -24
  74. package/lib/getFileLink.js.map +1 -1
  75. package/lib/odspDeltaStorageService.d.ts +3 -3
  76. package/lib/odspDeltaStorageService.d.ts.map +1 -1
  77. package/lib/odspDeltaStorageService.js +7 -4
  78. package/lib/odspDeltaStorageService.js.map +1 -1
  79. package/lib/odspDocumentDeltaConnection.d.ts.map +1 -1
  80. package/lib/odspDocumentDeltaConnection.js +2 -0
  81. package/lib/odspDocumentDeltaConnection.js.map +1 -1
  82. package/lib/odspDocumentService.d.ts.map +1 -1
  83. package/lib/odspDocumentService.js +4 -4
  84. package/lib/odspDocumentService.js.map +1 -1
  85. package/lib/odspDocumentStorageManager.d.ts.map +1 -1
  86. package/lib/odspDocumentStorageManager.js +33 -37
  87. package/lib/odspDocumentStorageManager.js.map +1 -1
  88. package/lib/odspDriverUrlResolver.d.ts +0 -4
  89. package/lib/odspDriverUrlResolver.d.ts.map +1 -1
  90. package/lib/odspDriverUrlResolver.js +0 -7
  91. package/lib/odspDriverUrlResolver.js.map +1 -1
  92. package/lib/odspDriverUrlResolverForShareLink.d.ts +2 -6
  93. package/lib/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  94. package/lib/odspDriverUrlResolverForShareLink.js +5 -16
  95. package/lib/odspDriverUrlResolverForShareLink.js.map +1 -1
  96. package/lib/odspError.d.ts.map +1 -1
  97. package/lib/odspError.js +3 -1
  98. package/lib/odspError.js.map +1 -1
  99. package/lib/odspSummaryUploadManager.js +5 -4
  100. package/lib/odspSummaryUploadManager.js.map +1 -1
  101. package/lib/odspUtils.d.ts.map +1 -1
  102. package/lib/odspUtils.js +33 -25
  103. package/lib/odspUtils.js.map +1 -1
  104. package/lib/packageVersion.d.ts +1 -1
  105. package/lib/packageVersion.d.ts.map +1 -1
  106. package/lib/packageVersion.js +1 -1
  107. package/lib/packageVersion.js.map +1 -1
  108. package/lib/zipItDataRepresentationUtils.d.ts.map +1 -1
  109. package/lib/zipItDataRepresentationUtils.js +3 -4
  110. package/lib/zipItDataRepresentationUtils.js.map +1 -1
  111. package/package.json +12 -12
  112. package/src/contractsPublic.ts +0 -5
  113. package/src/createFile.ts +13 -9
  114. package/src/epochTracker.ts +52 -25
  115. package/src/fetchSnapshot.ts +2 -1
  116. package/src/getFileLink.ts +47 -27
  117. package/src/odspDeltaStorageService.ts +10 -3
  118. package/src/odspDocumentDeltaConnection.ts +2 -0
  119. package/src/odspDocumentService.ts +8 -4
  120. package/src/odspDocumentStorageManager.ts +49 -38
  121. package/src/odspDriverUrlResolver.ts +0 -13
  122. package/src/odspDriverUrlResolverForShareLink.ts +10 -23
  123. package/src/odspError.ts +5 -1
  124. package/src/odspUtils.ts +43 -35
  125. package/src/packageVersion.ts +1 -1
  126. package/src/zipItDataRepresentationUtils.ts +4 -8
@@ -7,8 +7,6 @@ import { default as AbortController } from "abort-controller";
7
7
  import { ITelemetryLogger } from "@fluidframework/common-definitions";
8
8
  import {
9
9
  assert,
10
- stringToBuffer,
11
- bufferToString,
12
10
  delay,
13
11
  } from "@fluidframework/common-utils";
14
12
  import {
@@ -19,9 +17,9 @@ import {
19
17
  ISummaryContext,
20
18
  IDocumentStorageService,
21
19
  LoaderCachingPolicy,
20
+ DriverErrorType,
22
21
  } from "@fluidframework/driver-definitions";
23
- import { RateLimiter } from "@fluidframework/driver-utils";
24
- import { throwOdspNetworkError } from "@fluidframework/odsp-doclib-utils";
22
+ import { RateLimiter, NonRetryableError } from "@fluidframework/driver-utils";
25
23
  import {
26
24
  IOdspResolvedUrl,
27
25
  ISnapshotOptions,
@@ -315,17 +313,7 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
315
313
  this.blobCache.setBlob(blobId, blob);
316
314
  }
317
315
 
318
- if (!this.attributesBlobHandles.has(blobId)) {
319
- return blob;
320
- }
321
- // ODSP document ids are random guids (different per session)
322
- // fix the branch name in attributes
323
- // this prevents issues when generating summaries
324
- const documentAttributes: api.IDocumentAttributes = JSON.parse(bufferToString(blob, "utf8"));
325
- documentAttributes.branch = this.documentId;
326
- const content = JSON.stringify(documentAttributes);
327
- const patchedBlob = stringToBuffer(content, "utf8");
328
- return patchedBlob;
316
+ return blob;
329
317
  }
330
318
 
331
319
  public async readBlob(blobId: string): Promise<ArrayBufferLike> {
@@ -415,22 +403,31 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
415
403
  { eventName: "ObtainSnapshot" },
416
404
  async (event: PerformanceEvent) => {
417
405
  const props = {};
418
- let cachedSnapshot: ISnapshotContents | undefined;
406
+ let retrievedSnapshot: ISnapshotContents | undefined;
407
+ // Here's the logic to grab the persistent cache snapshot implemented by the host
408
+ // Epoch tracker is responsible for communicating with the persistent cache, handling epochs and cache versions
419
409
  const cachedSnapshotP: Promise<ISnapshotContents | undefined> =
420
410
  this.epochTracker.get(createCacheSnapshotKey(this.odspResolvedUrl))
421
- .then((snapshotCachedEntry: ISnapshotCachedEntry) => {
411
+ .then(async (snapshotCachedEntry: ISnapshotCachedEntry) => {
422
412
  if (snapshotCachedEntry !== undefined) {
423
413
  // If the cached entry does not contain the entry time, then assign it a default of 30 days old.
424
- // eslint-disable-next-line @typescript-eslint/dot-notation
425
- props["cacheEntryAge"] = Date.now() - (snapshotCachedEntry.cacheEntryTime ??
414
+ const age = Date.now() - (snapshotCachedEntry.cacheEntryTime ??
426
415
  (Date.now() - 30 * 24 * 60 * 60 * 1000));
416
+
417
+ // Record the cache age
418
+ // eslint-disable-next-line @typescript-eslint/dot-notation
419
+ props["cacheEntryAge"] = age;
427
420
  }
421
+
428
422
  return snapshotCachedEntry;
429
423
  });
430
424
 
425
+ // Based on the concurrentSnapshotFetch policy:
426
+ // Either retrieve both the network and cache snapshots concurrently and pick the first to return,
427
+ // or grab the cache value and then the network value if the cache value returns undefined.
431
428
  let method: string;
432
429
  if (this.hostPolicy.concurrentSnapshotFetch && !this.hostPolicy.summarizerClient) {
433
- const snapshotP = this.fetchSnapshot(hostSnapshotOptions);
430
+ const networkSnapshotP = this.fetchSnapshot(hostSnapshotOptions);
434
431
 
435
432
  // Ensure that failures on both paths are ignored initially.
436
433
  // I.e. if cache fails for some reason, we will proceed with network result.
@@ -438,20 +435,20 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
438
435
  // do want to attempt to succeed with cached data!
439
436
  const promiseRaceWinner = await promiseRaceWithWinner([
440
437
  cachedSnapshotP.catch(() => undefined),
441
- snapshotP.catch(() => undefined),
438
+ networkSnapshotP.catch(() => undefined),
442
439
  ]);
443
- cachedSnapshot = promiseRaceWinner.value;
440
+ retrievedSnapshot = promiseRaceWinner.value;
444
441
  method = promiseRaceWinner.index === 0 ? "cache" : "network";
445
442
 
446
- if (cachedSnapshot === undefined) {
443
+ if (retrievedSnapshot === undefined) {
447
444
  // if network failed -> wait for cache ( then return network failure)
448
445
  // If cache returned empty or failed -> wait for network (success of failure)
449
446
  if (promiseRaceWinner.index === 1) {
450
- cachedSnapshot = await cachedSnapshotP;
447
+ retrievedSnapshot = await cachedSnapshotP;
451
448
  method = "cache";
452
449
  }
453
- if (cachedSnapshot === undefined) {
454
- cachedSnapshot = await snapshotP;
450
+ if (retrievedSnapshot === undefined) {
451
+ retrievedSnapshot = await networkSnapshotP;
455
452
  method = "network";
456
453
  }
457
454
  }
@@ -459,12 +456,12 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
459
456
  // Note: There's a race condition here - another caller may come past the undefined check
460
457
  // while the first caller is awaiting later async code in this block.
461
458
 
462
- cachedSnapshot = await cachedSnapshotP;
459
+ retrievedSnapshot = await cachedSnapshotP;
463
460
 
464
- method = cachedSnapshot !== undefined ? "cache" : "network";
461
+ method = retrievedSnapshot !== undefined ? "cache" : "network";
465
462
 
466
- if (cachedSnapshot === undefined) {
467
- cachedSnapshot = await this.fetchSnapshot(hostSnapshotOptions);
463
+ if (retrievedSnapshot === undefined) {
464
+ retrievedSnapshot = await this.fetchSnapshot(hostSnapshotOptions);
468
465
  }
469
466
  }
470
467
  if (method === "network") {
@@ -472,12 +469,11 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
472
469
  props["cacheEntryAge"] = undefined;
473
470
  }
474
471
  event.end({ ...props, method });
475
- return cachedSnapshot;
472
+ return retrievedSnapshot;
476
473
  },
477
- {end: true, cancel: "error"},
478
474
  );
479
475
 
480
- // Successful call, redirect future calls to getVersion only!
476
+ // Successful call, make network calls only
481
477
  this.firstVersionCall = false;
482
478
 
483
479
  this._snapshotSequenceNumber = odspSnapshotCacheValue.sequenceNumber;
@@ -512,10 +508,16 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
512
508
  );
513
509
  const versionsResponse = response.content;
514
510
  if (!versionsResponse) {
515
- throwOdspNetworkError("getVersionsReturnedNoResponse", 400);
511
+ throw new NonRetryableError(
512
+ "getVersionsReturnedNoResponse",
513
+ "No response from /versions endpoint",
514
+ DriverErrorType.genericNetworkError);
516
515
  }
517
516
  if (!Array.isArray(versionsResponse.value)) {
518
- throwOdspNetworkError("getVersionsReturnedNonArrayResponse", 400);
517
+ throw new NonRetryableError(
518
+ "getVersionsReturnedNonArrayResponse",
519
+ "Incorrect response from /versions endpoint",
520
+ DriverErrorType.genericNetworkError);
519
521
  }
520
522
  return versionsResponse.value.map((version) => {
521
523
  // Parse the date from the message
@@ -687,19 +689,28 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
687
689
 
688
690
  private checkSnapshotUrl() {
689
691
  if (!this.snapshotUrl) {
690
- throwOdspNetworkError("methodNotSupportedBecauseNoSnapshotUrlWasProvided", 400);
692
+ throw new NonRetryableError(
693
+ "noSnapshotUrlProvided",
694
+ "Method failed because no snapshot url was available",
695
+ DriverErrorType.genericError);
691
696
  }
692
697
  }
693
698
 
694
699
  private checkAttachmentPOSTUrl() {
695
700
  if (!this.attachmentPOSTUrl) {
696
- throwOdspNetworkError("methodNotSupportedBecauseNoAttachmentPOSTUrlWasProvided", 400);
701
+ throw new NonRetryableError(
702
+ "noAttachmentPOSTUrlProvided",
703
+ "Method failed because no attachment POST url was available",
704
+ DriverErrorType.genericError);
697
705
  }
698
706
  }
699
707
 
700
708
  private checkAttachmentGETUrl() {
701
709
  if (!this.attachmentGETUrl) {
702
- throwOdspNetworkError("methodNotSupportedBecauseNoAttachmentGETUrlWasProvided", 400);
710
+ throw new NonRetryableError(
711
+ "noAttachmentGETUrlWasProvided",
712
+ "Method failed because no attachment GET url was available",
713
+ DriverErrorType.genericError);
703
714
  }
704
715
  }
705
716
 
@@ -7,7 +7,6 @@ import { assert } from "@fluidframework/common-utils";
7
7
  import { IFluidCodeDetails, IRequest, isFluidPackage } from "@fluidframework/core-interfaces";
8
8
  import { DriverHeader, IResolvedUrl, IUrlResolver } from "@fluidframework/driver-definitions";
9
9
  import { IOdspResolvedUrl, ShareLinkTypes, ShareLinkInfoType } from "@fluidframework/odsp-driver-definitions";
10
- import { createOdspCreateContainerRequest } from "./createOdspCreateContainerRequest";
11
10
  import { createOdspUrl } from "./createOdspUrl";
12
11
  import { getApiRoot } from "./odspUrlHelper";
13
12
  import { getOdspResolvedUrl } from "./odspUtils";
@@ -166,18 +165,6 @@ export class OdspDriverUrlResolver implements IUrlResolver {
166
165
  dataStorePath,
167
166
  });
168
167
  }
169
-
170
- /**
171
- * @deprecated - use createOdspCreateContainerRequest
172
- */
173
- public createCreateNewRequest(
174
- siteUrl: string,
175
- driveId: string,
176
- filePath: string,
177
- fileName: string,
178
- ): IRequest {
179
- return createOdspCreateContainerRequest(siteUrl, driveId, filePath, fileName);
180
- }
181
168
  }
182
169
 
183
170
  function decodeOdspUrl(url: string): {
@@ -7,7 +7,7 @@ import { PromiseCache } from "@fluidframework/common-utils";
7
7
  import { IFluidCodeDetails, IRequest, isFluidPackage } from "@fluidframework/core-interfaces";
8
8
  import { IResolvedUrl, IUrlResolver } from "@fluidframework/driver-definitions";
9
9
  import { ITelemetryBaseLogger, ITelemetryLogger } from "@fluidframework/common-definitions";
10
- import { fetchTokenErrorCode, throwOdspNetworkError } from "@fluidframework/odsp-doclib-utils";
10
+ import { NonRetryableError } from "@fluidframework/driver-utils";
11
11
  import { PerformanceEvent } from "@fluidframework/telemetry-utils";
12
12
  import {
13
13
  IOdspResolvedUrl,
@@ -15,6 +15,7 @@ import {
15
15
  isTokenFromCache,
16
16
  OdspResourceTokenFetchOptions,
17
17
  TokenFetcher,
18
+ OdspErrorType,
18
19
  } from "@fluidframework/odsp-driver-definitions";
19
20
  import {
20
21
  getLocatorFromOdspUrl,
@@ -22,8 +23,7 @@ import {
22
23
  encodeOdspFluidDataStoreLocator,
23
24
  locatorQueryParamName,
24
25
  } from "./odspFluidFileLink";
25
- import { OdspDocumentInfo, OdspFluidDataStoreLocator, SharingLinkHeader } from "./contractsPublic";
26
- import { createOdspCreateContainerRequest } from "./createOdspCreateContainerRequest";
26
+ import { OdspFluidDataStoreLocator, SharingLinkHeader } from "./contractsPublic";
27
27
  import { createOdspUrl } from "./createOdspUrl";
28
28
  import { OdspDriverUrlResolver } from "./odspDriverUrlResolver";
29
29
  import { getOdspResolvedUrl, createOdspLogger } from "./odspUtils";
@@ -77,18 +77,6 @@ export class OdspDriverUrlResolverForShareLink implements IUrlResolver {
77
77
  }
78
78
  }
79
79
 
80
- /**
81
- * @deprecated - use createOdspCreateContainerRequest
82
- */
83
- public createCreateNewRequest(
84
- siteUrl: string,
85
- driveId: string,
86
- filePath: string,
87
- fileName: string,
88
- ) {
89
- return createOdspCreateContainerRequest(siteUrl, driveId, filePath, fileName);
90
- }
91
-
92
80
  /**
93
81
  * Takes an already generated data store url (from requestUrl) and appends a path to the
94
82
  * existing data store information.
@@ -175,7 +163,10 @@ export class OdspDriverUrlResolverForShareLink implements IUrlResolver {
175
163
  { eventName: "GetSharingLinkToken" },
176
164
  async (event) => tokenFetcher(options).then((tokenResponse) => {
177
165
  if (tokenResponse === null) {
178
- throwOdspNetworkError("shareLinkTokenIsNull", fetchTokenErrorCode);
166
+ throw new NonRetryableError(
167
+ "shareLinkTokenIsNull",
168
+ "Token callback returned null",
169
+ OdspErrorType.fetchTokenError);
179
170
  }
180
171
  event.end({ fromCache: isTokenFromCache(tokenResponse) });
181
172
  return tokenResponse;
@@ -203,12 +194,8 @@ export class OdspDriverUrlResolverForShareLink implements IUrlResolver {
203
194
  resolvedUrl,
204
195
  this.shareLinkFetcherProps.identityType,
205
196
  this.logger,
206
- ).then((fileLink) => {
207
- if (!fileLink) {
208
- throw new Error("Failed to get share link");
209
- }
210
- return fileLink;
211
- }).catch((error) => {
197
+ ).catch((error) => {
198
+ // This should imply that error is a non-retriable error.
212
199
  this.logger.sendErrorEvent({ eventName: "FluidFileUrlError" }, error);
213
200
  this.sharingLinkCache.remove(key);
214
201
  throw error;
@@ -254,7 +241,7 @@ export class OdspDriverUrlResolverForShareLink implements IUrlResolver {
254
241
  /**
255
242
  * Crafts a supported document/driver URL
256
243
  */
257
- public static createDocumentUrl(baseUrl: string, driverInfo: OdspDocumentInfo) {
244
+ public static createDocumentUrl(baseUrl: string, driverInfo: OdspFluidDataStoreLocator) {
258
245
  const url = new URL(baseUrl);
259
246
 
260
247
  storeLocatorInOdspUrl(url, driverInfo);
package/src/odspError.ts CHANGED
@@ -11,9 +11,13 @@ import { IOdspSocketError } from "./contracts";
11
11
  */
12
12
  export function errorObjectFromSocketError(socketError: IOdspSocketError, handler: string) {
13
13
  const message = `OdspSocketError (${handler}): ${socketError.message}`;
14
- return createOdspNetworkError(
14
+ const error = createOdspNetworkError(
15
15
  `odspSocketError [${handler}]`,
16
16
  message,
17
17
  socketError.code,
18
18
  socketError.retryAfter);
19
+
20
+ error.addTelemetryProperties({ odspError: true, relayServiceError: true });
21
+
22
+ return error;
19
23
  }
package/src/odspUtils.ts CHANGED
@@ -5,19 +5,14 @@
5
5
 
6
6
  import { ITelemetryProperties, ITelemetryBaseLogger, ITelemetryLogger } from "@fluidframework/common-definitions";
7
7
  import { IResolvedUrl, DriverErrorType } from "@fluidframework/driver-definitions";
8
- import { isOnline, OnlineStatus } from "@fluidframework/driver-utils";
8
+ import { isOnline, OnlineStatus, RetryableError, NonRetryableError } from "@fluidframework/driver-utils";
9
9
  import { assert, performance } from "@fluidframework/common-utils";
10
10
  import { ISequencedDocumentMessage, ISnapshotTree } from "@fluidframework/protocol-definitions";
11
11
  import { ChildLogger, PerformanceEvent, wrapError } from "@fluidframework/telemetry-utils";
12
12
  import {
13
13
  fetchIncorrectResponse,
14
- offlineFetchFailureStatusCode,
15
- fetchFailureStatusCode,
16
- fetchTimeoutStatusCode,
17
14
  throwOdspNetworkError,
18
15
  getSPOAndGraphRequestIdsFromResponse,
19
- fetchTokenErrorCode,
20
- createOdspNetworkError,
21
16
  } from "@fluidframework/odsp-doclib-utils";
22
17
  import {
23
18
  IOdspResolvedUrl,
@@ -82,7 +77,7 @@ export async function getWithRetryForTokenRefresh<T>(get: (options: TokenFetchOp
82
77
  case DriverErrorType.authorizationError:
83
78
  return get({ ...options, claims: e.claims, tenantId: e.tenantId });
84
79
 
85
- case DriverErrorType.incorrectServerResponse: // fetchIncorrectResponse - some error on the wire, retry once
80
+ case DriverErrorType.incorrectServerResponse: // some error on the wire, retry once
86
81
  case OdspErrorType.fetchTokenError: // If the token was null, then retry once.
87
82
  return get(options);
88
83
 
@@ -107,7 +102,10 @@ export async function fetchHelper(
107
102
  const response = fetchResponse as any as Response;
108
103
  // Let's assume we can retry.
109
104
  if (!response) {
110
- throwOdspNetworkError("odspFetchErrorNoResponse", fetchIncorrectResponse);
105
+ throw new NonRetryableError(
106
+ "odspFetchErrorNoResponse",
107
+ "No response from fetch call",
108
+ DriverErrorType.incorrectServerResponse);
111
109
  }
112
110
  if (!response.ok || response.status < 200 || response.status >= 300) {
113
111
  throwOdspNetworkError(
@@ -130,11 +128,13 @@ export async function fetchHelper(
130
128
  if (errorText === "TypeError: Failed to fetch") {
131
129
  online = OnlineStatus.Offline;
132
130
  }
131
+ // This error is thrown by fetch() when AbortSignal is provided and it gets cancelled
133
132
  if (error.name === "AbortError") {
134
- throwOdspNetworkError("timeoutDuringFetch", fetchTimeoutStatusCode);
133
+ throw new RetryableError("fetchAbort", "Fetch Timeout (AbortError)", OdspErrorType.fetchTimeout);
135
134
  }
135
+ // TCP/IP timeout
136
136
  if (errorText.indexOf("ETIMEDOUT") !== -1) {
137
- throwOdspNetworkError("timeoutDuringFetch(ETIMEDOUT)", fetchTimeoutStatusCode);
137
+ throw new RetryableError("fetchETimedout", "Fetch Timeout (ETIMEDOUT)", OdspErrorType.fetchTimeout);
138
138
  }
139
139
 
140
140
  //
@@ -142,11 +142,11 @@ export async function fetchHelper(
142
142
  // It could container PII, like URI in message itself, or token in properties.
143
143
  // It is also non-serializable object due to circular references.
144
144
  //
145
- const failureCode = online === OnlineStatus.Offline ? offlineFetchFailureStatusCode : fetchFailureStatusCode;
146
- throwOdspNetworkError(
147
- `odspFetchThrewError [${failureCode}]`,
148
- failureCode,
149
- );
145
+ if (online === OnlineStatus.Offline) {
146
+ throw new RetryableError("OdspFetchOffline", `Offline: ${errorText}`, DriverErrorType.offlineError);
147
+ } else {
148
+ throw new RetryableError("OdspFetchError", `Fetch error: ${errorText}`, DriverErrorType.fetchFailure);
149
+ }
150
150
  });
151
151
  }
152
152
 
@@ -181,30 +181,31 @@ export async function fetchAndParseAsJSONHelper<T>(
181
181
  requestInit: RequestInit | undefined,
182
182
  ): Promise<IOdspResponse<T>> {
183
183
  const { content, headers, commonSpoHeaders, duration } = await fetchHelper(requestInfo, requestInit);
184
- // JSON.parse() can fail and message (that goes into telemetry) would container full request URI, including
185
- // tokens... It fails for me with "Unexpected end of JSON input" quite often - an attempt to download big file
186
- // (many ops) almost always ends up with this error - I'd guess 1% of op request end up here... It always
187
- // succeeds on retry.
184
+ let text: string | undefined;
188
185
  try {
189
- const text = await content.text();
190
-
191
- commonSpoHeaders.bodySize = text.length;
192
- const res = {
193
- headers,
194
- content: JSON.parse(text),
195
- commonSpoHeaders,
196
- duration,
197
- };
198
- return res;
186
+ text = await content.text();
199
187
  } catch (e) {
188
+ // JSON.parse() can fail and message would container full request URI, including
189
+ // tokens... It fails for me with "Unexpected end of JSON input" quite often - an attempt to download big file
190
+ // (many ops) almost always ends up with this error - I'd guess 1% of op request end up here... It always
191
+ // succeeds on retry.
192
+ // So do not log error object itself.
200
193
  throwOdspNetworkError(
201
194
  "errorWhileParsingFetchResponse",
202
195
  fetchIncorrectResponse,
203
- content,
204
- undefined,
205
- { error: Object(e) },
196
+ content, // response
197
+ text,
206
198
  );
207
199
  }
200
+
201
+ commonSpoHeaders.bodySize = text.length;
202
+ const res = {
203
+ headers,
204
+ content: JSON.parse(text),
205
+ commonSpoHeaders,
206
+ duration,
207
+ };
208
+ return res;
208
209
  }
209
210
 
210
211
  export interface INewFileInfo {
@@ -293,14 +294,21 @@ export function toInstrumentedOdspTokenFetcher(
293
294
  event.end({ fromCache: isTokenFromCache(tokenResponse), isNull: token === null });
294
295
  }
295
296
  if (token === null && throwOnNullToken) {
296
- throwOdspNetworkError("tokenIsNull", fetchTokenErrorCode, undefined, undefined, { method: name });
297
+ throw new NonRetryableError(
298
+ "storageTokenIsNull",
299
+ `Token is null for ${name} call`,
300
+ OdspErrorType.fetchTokenError,
301
+ { method: name });
297
302
  }
298
303
  return token;
299
304
  }, (error) => {
300
305
  const tokenError = wrapError(
301
306
  error,
302
- (errorMessage) => createOdspNetworkError("tokenFetcherFailed", errorMessage, fetchTokenErrorCode));
303
- // eslint-disable-next-line @typescript-eslint/no-throw-literal
307
+ (errorMessage) => new NonRetryableError(
308
+ "tokenFetcherFailed",
309
+ errorMessage,
310
+ OdspErrorType.fetchTokenError,
311
+ { method: name }));
304
312
  throw tokenError;
305
313
  }),
306
314
  { cancel: "generic" });
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/odsp-driver";
9
- export const pkgVersion = "0.51.3";
9
+ export const pkgVersion = "0.53.0-46105";
@@ -9,7 +9,8 @@
9
9
  */
10
10
 
11
11
  import { assert, IsoBuffer, Uint8ArrayToArrayBuffer, Uint8ArrayToString } from "@fluidframework/common-utils";
12
- import { createOdspNetworkError, fetchIncorrectResponse } from "@fluidframework/odsp-doclib-utils";
12
+ import { NonRetryableError } from "@fluidframework/driver-utils";
13
+ import { DriverErrorType } from "@fluidframework/driver-definitions";
13
14
  import { ReadBuffer } from "./ReadBufferUtils";
14
15
 
15
16
  // eslint-disable-next-line max-len
@@ -477,19 +478,14 @@ function throwBufferParseException(
477
478
  expectedNodeType: NodeType,
478
479
  message: string,
479
480
  ): never {
480
- const error = createOdspNetworkError(
481
+ throw new NonRetryableError(
481
482
  "bufferParsingException",
482
483
  message,
483
- fetchIncorrectResponse,
484
- undefined,
485
- undefined,
486
- undefined,
484
+ DriverErrorType.incorrectServerResponse,
487
485
  {
488
486
  nodeType: getNodeType(node),
489
487
  expectedNodeType,
490
488
  });
491
- // eslint-disable-next-line @typescript-eslint/no-throw-literal
492
- throw error;
493
489
  }
494
490
 
495
491
  function getNodeType(value: NodeTypes): NodeType {