message: Fix timeout and size restrictions handling for snapshot in odsp driver
diff: @@ -117,6 +117,9 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
  private readonly sharingLinkP: Promise<string> | undefined;
  private readonly attachmentPOSTUrl: string | undefined;
  private readonly attachmentGETUrl: string | undefined;
  + // Driver specified limits for snapshot size and time.
  + private readonly maxSnapshotSizeLimit = 25000000; // 25 MB
  + private readonly maxSnapshotFetchTimeout = 30000; // 30 sec
  public set ops(ops: ISequencedDeltaOpMessage[] | undefined) {
  assert(this._ops === undefined);
  @@ -339,18 +342,19 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
  this.logger.sendErrorEvent({ eventName: "TreeLatest_SecondCall", hasClaims: !!tokenFetchOptions.claims });
  }
  - // Choose min of host specified limits or driver specified limits.
  - const maxSnapshotSizeLimit = 25000000; // 25 MB
  - const maxSnapshotFetchTimeout = 30000; // 30 sec
  const snapshotOptions: ISnapshotOptions = {
  deltas: 1,
  channels: 1,
  blobs: 2,
  + mds: this.maxSnapshotSizeLimit,
  ...this.hostPolicy.snapshotOptions,
  - mds: this.hostPolicy.snapshotOptions?.mds ? Math.min(this.hostPolicy.snapshotOptions.mds, maxSnapshotSizeLimit) : maxSnapshotSizeLimit,
  - timeout: this.hostPolicy.snapshotOptions?.timeout ? Math.min(this.hostPolicy.snapshotOptions.timeout, maxSnapshotFetchTimeout) : maxSnapshotFetchTimeout,
  + timeout: this.hostPolicy.snapshotOptions?.timeout ? Math.min(this.hostPolicy.snapshotOptions.timeout, this.maxSnapshotFetchTimeout) : this.maxSnapshotFetchTimeout,
  };
  + // No limit on size of snapshot, as otherwise we fail all clients to summarize
  + if (this.hostPolicy.summarizerClient) {
  + snapshotOptions.mds = undefined;
  + }
  let cachedSnapshot: IOdspSnapshot | undefined;
  // No need to ask cache twice - if first request was unsuccessful, cache unlikely to have data on second turn.
  @@ -533,8 +537,9 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
  private async fetchSnapshotWithTimeout(snapshotOptions: ISnapshotOptions, tokenFetchOptions: TokenFetchOptions, usePost: boolean) {
  assert(snapshotOptions.timeout !== undefined, "Timeout should be provided for setting a limit");
  const abortController = new AbortController();
  - setTimeout(
  + const timeout = setTimeout(
  () => {
  + clearTimeout(timeout);
  abortController.abort();
  },
  snapshotOptions.timeout,
  @@ -543,8 +548,13 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
  const odspSnapshot = await this.fetchSnapshotCore(snapshotOptions, tokenFetchOptions, usePost, abortController);
  return odspSnapshot;
  } catch (error) {
  - if (error.errorType === OdspErrorType.snapshotTooBig || error.errorType === OdspErrorType.fetchTimeout) {
  - const snapshotOptionsWithoutBlobs: ISnapshotOptions = { ...snapshotOptions, blobs: undefined };
  + // If the snapshot size is too big and the host specified the size limitation, then don't try to fetch the snapshot again.
  + if (error.errorType === OdspErrorType.snapshotTooBig && this.hostPolicy.snapshotOptions?.mds !== undefined) {
  + throw error;
  + }
  + // If the first snapshot request was with blobs and we either timed out or the size was too big, then try to fetch without blobs.
  + if ((error.errorType === OdspErrorType.snapshotTooBig || error.errorType === OdspErrorType.fetchTimeout) && snapshotOptions.blobs) {
  + const snapshotOptionsWithoutBlobs: ISnapshotOptions = { ...snapshotOptions, blobs: undefined, mds: undefined };
  return this.fetchSnapshotCore(snapshotOptionsWithoutBlobs, tokenFetchOptions, usePost);
  }
  throw error;
  