@fluidframework/odsp-driver 1.1.0 → 1.2.0-77818

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 (108) hide show
  1. package/dist/contractsPublic.d.ts +1 -0
  2. package/dist/contractsPublic.d.ts.map +1 -1
  3. package/dist/contractsPublic.js.map +1 -1
  4. package/dist/localOdspDriver/localOdspDocumentService.d.ts +26 -0
  5. package/dist/localOdspDriver/localOdspDocumentService.d.ts.map +1 -0
  6. package/dist/localOdspDriver/localOdspDocumentService.js +39 -0
  7. package/dist/localOdspDriver/localOdspDocumentService.js.map +1 -0
  8. package/dist/localOdspDriver/localOdspDocumentServiceFactory.d.ts +24 -0
  9. package/dist/localOdspDriver/localOdspDocumentServiceFactory.d.ts.map +1 -0
  10. package/dist/localOdspDriver/localOdspDocumentServiceFactory.js +45 -0
  11. package/dist/localOdspDriver/localOdspDocumentServiceFactory.js.map +1 -0
  12. package/dist/localOdspDriver/localOdspDocumentStorageManager.d.ts +27 -0
  13. package/dist/localOdspDriver/localOdspDocumentStorageManager.d.ts.map +1 -0
  14. package/dist/localOdspDriver/localOdspDocumentStorageManager.js +66 -0
  15. package/dist/localOdspDriver/localOdspDocumentStorageManager.js.map +1 -0
  16. package/dist/odspDeltaStorageService.js.map +1 -1
  17. package/dist/odspDocumentService.d.ts.map +1 -1
  18. package/dist/odspDocumentService.js.map +1 -1
  19. package/dist/odspDocumentServiceFactory.d.ts +2 -1
  20. package/dist/odspDocumentServiceFactory.d.ts.map +1 -1
  21. package/dist/odspDocumentServiceFactory.js +7 -1
  22. package/dist/odspDocumentServiceFactory.js.map +1 -1
  23. package/dist/odspDocumentServiceFactoryCore.d.ts +3 -1
  24. package/dist/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  25. package/dist/odspDocumentServiceFactoryCore.js.map +1 -1
  26. package/dist/odspDocumentStorageManager.d.ts +5 -23
  27. package/dist/odspDocumentStorageManager.d.ts.map +1 -1
  28. package/dist/odspDocumentStorageManager.js +52 -245
  29. package/dist/odspDocumentStorageManager.js.map +1 -1
  30. package/dist/odspDocumentStorageServiceBase.d.ts +58 -0
  31. package/dist/odspDocumentStorageServiceBase.d.ts.map +1 -0
  32. package/dist/odspDocumentStorageServiceBase.js +216 -0
  33. package/dist/odspDocumentStorageServiceBase.js.map +1 -0
  34. package/dist/odspDriverUrlResolver.js +1 -1
  35. package/dist/odspDriverUrlResolver.js.map +1 -1
  36. package/dist/odspDriverUrlResolverForShareLink.d.ts +8 -2
  37. package/dist/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  38. package/dist/odspDriverUrlResolverForShareLink.js +11 -3
  39. package/dist/odspDriverUrlResolverForShareLink.js.map +1 -1
  40. package/dist/odspFluidFileLink.d.ts.map +1 -1
  41. package/dist/odspFluidFileLink.js +27 -21
  42. package/dist/odspFluidFileLink.js.map +1 -1
  43. package/dist/packageVersion.d.ts +1 -1
  44. package/dist/packageVersion.d.ts.map +1 -1
  45. package/dist/packageVersion.js +1 -1
  46. package/dist/packageVersion.js.map +1 -1
  47. package/lib/contractsPublic.d.ts +1 -0
  48. package/lib/contractsPublic.d.ts.map +1 -1
  49. package/lib/contractsPublic.js.map +1 -1
  50. package/lib/localOdspDriver/localOdspDocumentService.d.ts +26 -0
  51. package/lib/localOdspDriver/localOdspDocumentService.d.ts.map +1 -0
  52. package/lib/localOdspDriver/localOdspDocumentService.js +35 -0
  53. package/lib/localOdspDriver/localOdspDocumentService.js.map +1 -0
  54. package/lib/localOdspDriver/localOdspDocumentServiceFactory.d.ts +24 -0
  55. package/lib/localOdspDriver/localOdspDocumentServiceFactory.d.ts.map +1 -0
  56. package/lib/localOdspDriver/localOdspDocumentServiceFactory.js +41 -0
  57. package/lib/localOdspDriver/localOdspDocumentServiceFactory.js.map +1 -0
  58. package/lib/localOdspDriver/localOdspDocumentStorageManager.d.ts +27 -0
  59. package/lib/localOdspDriver/localOdspDocumentStorageManager.d.ts.map +1 -0
  60. package/lib/localOdspDriver/localOdspDocumentStorageManager.js +62 -0
  61. package/lib/localOdspDriver/localOdspDocumentStorageManager.js.map +1 -0
  62. package/lib/odspDeltaStorageService.js.map +1 -1
  63. package/lib/odspDocumentService.d.ts.map +1 -1
  64. package/lib/odspDocumentService.js +1 -1
  65. package/lib/odspDocumentService.js.map +1 -1
  66. package/lib/odspDocumentServiceFactory.d.ts +2 -1
  67. package/lib/odspDocumentServiceFactory.d.ts.map +1 -1
  68. package/lib/odspDocumentServiceFactory.js +5 -0
  69. package/lib/odspDocumentServiceFactory.js.map +1 -1
  70. package/lib/odspDocumentServiceFactoryCore.d.ts +3 -1
  71. package/lib/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  72. package/lib/odspDocumentServiceFactoryCore.js.map +1 -1
  73. package/lib/odspDocumentStorageManager.d.ts +5 -23
  74. package/lib/odspDocumentStorageManager.d.ts.map +1 -1
  75. package/lib/odspDocumentStorageManager.js +53 -246
  76. package/lib/odspDocumentStorageManager.js.map +1 -1
  77. package/lib/odspDocumentStorageServiceBase.d.ts +58 -0
  78. package/lib/odspDocumentStorageServiceBase.d.ts.map +1 -0
  79. package/lib/odspDocumentStorageServiceBase.js +212 -0
  80. package/lib/odspDocumentStorageServiceBase.js.map +1 -0
  81. package/lib/odspDriverUrlResolver.js +1 -1
  82. package/lib/odspDriverUrlResolver.js.map +1 -1
  83. package/lib/odspDriverUrlResolverForShareLink.d.ts +8 -2
  84. package/lib/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  85. package/lib/odspDriverUrlResolverForShareLink.js +11 -3
  86. package/lib/odspDriverUrlResolverForShareLink.js.map +1 -1
  87. package/lib/odspFluidFileLink.d.ts.map +1 -1
  88. package/lib/odspFluidFileLink.js +27 -21
  89. package/lib/odspFluidFileLink.js.map +1 -1
  90. package/lib/packageVersion.d.ts +1 -1
  91. package/lib/packageVersion.d.ts.map +1 -1
  92. package/lib/packageVersion.js +1 -1
  93. package/lib/packageVersion.js.map +1 -1
  94. package/package.json +11 -11
  95. package/src/contractsPublic.ts +1 -0
  96. package/src/localOdspDriver/localOdspDocumentService.ts +54 -0
  97. package/src/localOdspDriver/localOdspDocumentServiceFactory.ts +67 -0
  98. package/src/localOdspDriver/localOdspDocumentStorageManager.ts +83 -0
  99. package/src/odspDeltaStorageService.ts +1 -1
  100. package/src/odspDocumentService.ts +5 -1
  101. package/src/odspDocumentServiceFactory.ts +7 -3
  102. package/src/odspDocumentServiceFactoryCore.ts +1 -1
  103. package/src/odspDocumentStorageManager.ts +81 -312
  104. package/src/odspDocumentStorageServiceBase.ts +268 -0
  105. package/src/odspDriverUrlResolver.ts +1 -1
  106. package/src/odspDriverUrlResolverForShareLink.ts +13 -1
  107. package/src/odspFluidFileLink.ts +26 -22
  108. package/src/packageVersion.ts +1 -1
@@ -4,15 +4,16 @@
4
4
  */
5
5
  import { ITelemetryLogger } from "@fluidframework/common-definitions";
6
6
  import * as api from "@fluidframework/protocol-definitions";
7
- import { ISummaryContext, IDocumentStorageService, LoaderCachingPolicy } from "@fluidframework/driver-definitions";
7
+ import { ISummaryContext } from "@fluidframework/driver-definitions";
8
8
  import { IOdspResolvedUrl, InstrumentedStorageTokenFetcher } from "@fluidframework/odsp-driver-definitions";
9
9
  import { HostStoragePolicyInternal } from "./contracts";
10
10
  import { SnapshotFormatSupportType } from "./fetchSnapshot";
11
11
  import { IOdspCache } from "./odspCache";
12
12
  import { EpochTracker } from "./epochTracker";
13
13
  import { FlushResult } from "./odspDocumentDeltaConnection";
14
+ import { OdspDocumentStorageServiceBase } from "./odspDocumentStorageServiceBase";
14
15
  export declare const defaultSummarizerCacheExpiryTimeout: number;
15
- export declare class OdspDocumentStorageService implements IDocumentStorageService {
16
+ export declare class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
16
17
  private readonly odspResolvedUrl;
17
18
  private readonly getStorageToken;
18
19
  private readonly logger;
@@ -22,17 +23,8 @@ export declare class OdspDocumentStorageService implements IDocumentStorageServi
22
23
  private readonly epochTracker;
23
24
  private readonly flushCallback;
24
25
  private readonly snapshotFormatFetchType?;
25
- readonly policies: {
26
- caching: LoaderCachingPolicy;
27
- minBlobSize: number;
28
- maximumCacheDurationMs: number;
29
- };
30
- private readonly commitCache;
31
- private readonly attributesBlobHandles;
32
26
  private readonly odspSummaryUploadManager;
33
- private _ops;
34
27
  private firstVersionCall;
35
- private _snapshotSequenceNumber;
36
28
  private readonly documentId;
37
29
  private readonly snapshotUrl;
38
30
  private readonly attachmentPOSTUrl;
@@ -45,27 +37,17 @@ export declare class OdspDocumentStorageService implements IDocumentStorageServi
45
37
  private readonly maxSnapshotSizeLimit;
46
38
  private readonly maxSnapshotFetchTimeout;
47
39
  private readonly createBlobRateLimiter;
48
- private readonly blobCache;
49
- set ops(ops: api.ISequencedDocumentMessage[] | undefined);
50
- get ops(): api.ISequencedDocumentMessage[] | undefined;
51
- get snapshotSequenceNumber(): number | undefined;
52
40
  constructor(odspResolvedUrl: IOdspResolvedUrl, getStorageToken: InstrumentedStorageTokenFetcher, logger: ITelemetryLogger, fetchFullSnapshot: boolean, cache: IOdspCache, hostPolicy: HostStoragePolicyInternal, epochTracker: EpochTracker, flushCallback: () => Promise<FlushResult>, snapshotFormatFetchType?: SnapshotFormatSupportType | undefined);
53
- get repositoryUrl(): string;
54
41
  createBlob(file: ArrayBufferLike): Promise<api.ICreateBlobResponse>;
55
- private readBlobCore;
56
- readBlob(blobId: string): Promise<ArrayBufferLike>;
42
+ protected fetchBlobFromStorage(blobId: string, evicted: boolean): Promise<ArrayBuffer>;
57
43
  getSnapshotTree(version?: api.IVersion, scenarioName?: string): Promise<api.ISnapshotTree | null>;
58
44
  getVersions(blobid: string | null, count: number, scenarioName?: string): Promise<api.IVersion[]>;
59
45
  private fetchSnapshot;
60
46
  private fetchSnapshotCore;
61
47
  uploadSummaryWithContext(summary: api.ISummaryTree, context: ISummaryContext): Promise<string>;
62
- downloadSummary(commit: api.ISummaryHandle): Promise<api.ISummaryTree>;
63
- private setRootTree;
64
- private initBlobsCache;
65
48
  private checkSnapshotUrl;
66
49
  private checkAttachmentPOSTUrl;
67
50
  private checkAttachmentGETUrl;
68
- private readTree;
69
- private combineProtocolAndAppSnapshotTree;
51
+ protected fetchTreeFromSnapshot(id: string, scenarioName?: string): Promise<api.ISnapshotTree | undefined>;
70
52
  }
71
53
  //# sourceMappingURL=odspDocumentStorageManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"odspDocumentStorageManager.d.ts","sourceRoot":"","sources":["../src/odspDocumentStorageManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"odspDocumentStorageManager.d.ts","sourceRoot":"","sources":["../src/odspDocumentStorageManager.ts"],"names":[],"mappings":"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"}
@@ -4,15 +4,15 @@
4
4
  */
5
5
  import { assert, delay, } from "@fluidframework/common-utils";
6
6
  import { PerformanceEvent, } from "@fluidframework/telemetry-utils";
7
- import { LoaderCachingPolicy, DriverErrorType, } from "@fluidframework/driver-definitions";
7
+ import { DriverErrorType, } from "@fluidframework/driver-definitions";
8
8
  import { RateLimiter, NonRetryableError } from "@fluidframework/driver-utils";
9
9
  import { OdspErrorType, } from "@fluidframework/odsp-driver-definitions";
10
10
  import { downloadSnapshot, fetchSnapshot, fetchSnapshotWithRedeem } from "./fetchSnapshot";
11
11
  import { getUrlAndHeadersWithAuth } from "./getUrlAndHeadersWithAuth";
12
12
  import { createCacheSnapshotKey, getWithRetryForTokenRefresh, } from "./odspUtils";
13
- import { defaultCacheExpiryTimeoutMs } from "./epochTracker";
14
13
  import { OdspSummaryUploadManager } from "./odspSummaryUploadManager";
15
14
  import { pkgVersion as driverVersion } from "./packageVersion";
15
+ import { OdspDocumentStorageServiceBase } from "./odspDocumentStorageServiceBase";
16
16
  export const defaultSummarizerCacheExpiryTimeout = 60 * 1000; // 60 seconds.
17
17
  /* eslint-disable max-len */
18
18
  // An implementation of Promise.race that gives you the winner of the promise race
@@ -23,98 +23,10 @@ async function promiseRaceWithWinner(promises) {
23
23
  });
24
24
  });
25
25
  }
26
- class BlobCache {
27
- constructor() {
28
- // If the defer flag is set when the timeout fires, we'll reschedule rather than clear immediately
29
- // This deferral approach is used (rather than clearing/resetting the timer) as current calling patterns trigger
30
- // too many calls to setTimeout/clearTimeout.
31
- this.deferBlobCacheClear = false;
32
- this._blobCache = new Map();
33
- // Tracks all blob IDs evicted from cache
34
- this.blobsEvicted = new Set();
35
- // Initial time-out to purge data from cache
36
- // If this time out is very small, then we purge blobs from cache too soon and that results in a lot of
37
- // requests to storage, which brings down perf and may trip protection limits causing 429s
38
- this.blobCacheTimeoutDuration = 2 * 60 * 1000;
39
- // SPO does not keep old snapshots around for long, so we are running chances of not
40
- // being able to rehydrate data store / DDS in the future if we purge anything (and with blob de-duping,
41
- // even if blob read by runtime, it could be read again in the future)
42
- // So for now, purging is disabled.
43
- this.purgeEnabled = false;
44
- }
45
- get value() {
46
- return this._blobCache;
47
- }
48
- addBlobs(blobs) {
49
- blobs.forEach((value, blobId) => {
50
- this._blobCache.set(blobId, value);
51
- });
52
- // Reset the timer on cache set
53
- this.scheduleClearBlobsCache();
54
- }
55
- /**
56
- * Schedule a timer for clearing the blob cache or defer the current one.
57
- */
58
- scheduleClearBlobsCache() {
59
- if (this.blobCacheTimeout !== undefined) {
60
- // If we already have an outstanding timer, just signal that we should defer the clear
61
- this.deferBlobCacheClear = true;
62
- }
63
- else if (this.purgeEnabled) {
64
- // If we don't have an outstanding timer, set a timer
65
- // When the timer runs out, we'll decide whether to proceed with the cache clear or reset the timer
66
- const clearCacheOrDefer = () => {
67
- this.blobCacheTimeout = undefined;
68
- if (this.deferBlobCacheClear) {
69
- this.deferBlobCacheClear = false;
70
- this.scheduleClearBlobsCache();
71
- }
72
- else {
73
- // NOTE: Slightly better algorithm here would be to purge either only big blobs,
74
- // or sort them by size and purge enough big blobs to leave only 256Kb of small blobs in cache
75
- // Purging is optimizing memory footprint. But count controls potential number of storage requests
76
- // We want to optimize both - memory footprint and number of future requests to storage.
77
- // Note that Container can realize data store or DDS on-demand at any point in time, so we do not
78
- // control when blobs will be used.
79
- this._blobCache.forEach((_, blobId) => this.blobsEvicted.add(blobId));
80
- this._blobCache.clear();
81
- }
82
- };
83
- this.blobCacheTimeout = setTimeout(clearCacheOrDefer, this.blobCacheTimeoutDuration);
84
- // any future storage reads that get into the cache should be cleared from cache rather quickly -
85
- // there is not much value in keeping them longer
86
- this.blobCacheTimeoutDuration = 10 * 1000;
87
- }
88
- }
89
- getBlob(blobId) {
90
- // Reset the timer on attempted cache read
91
- this.scheduleClearBlobsCache();
92
- const blobContent = this._blobCache.get(blobId);
93
- const evicted = this.blobsEvicted.has(blobId);
94
- return { blobContent, evicted };
95
- }
96
- setBlob(blobId, blob) {
97
- // This API is called as result of cache miss and reading blob from storage.
98
- // Runtime never reads same blob twice.
99
- // The only reason we may get read request for same blob is blob de-duping in summaries.
100
- // Note that the bigger the size, the less likely blobs are the same, so there is very little benefit of caching big blobs.
101
- // Images are the only exception - user may insert same image twice. But we currently do not de-dup them - only snapshot
102
- // blobs are de-duped.
103
- const size = blob.byteLength;
104
- if (size < 256 * 1024) {
105
- // Reset the timer on cache set
106
- this.scheduleClearBlobsCache();
107
- return this._blobCache.set(blobId, blob);
108
- }
109
- else {
110
- // we evicted it here by not caching.
111
- this.blobsEvicted.add(blobId);
112
- }
113
- }
114
- }
115
- export class OdspDocumentStorageService {
26
+ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
116
27
  constructor(odspResolvedUrl, getStorageToken, logger, fetchFullSnapshot, cache, hostPolicy, epochTracker, flushCallback, snapshotFormatFetchType) {
117
28
  var _a;
29
+ super();
118
30
  this.odspResolvedUrl = odspResolvedUrl;
119
31
  this.getStorageToken = getStorageToken;
120
32
  this.logger = logger;
@@ -124,24 +36,6 @@ export class OdspDocumentStorageService {
124
36
  this.epochTracker = epochTracker;
125
37
  this.flushCallback = flushCallback;
126
38
  this.snapshotFormatFetchType = snapshotFormatFetchType;
127
- this.policies = {
128
- // By default, ODSP tells the container not to prefetch/cache.
129
- caching: LoaderCachingPolicy.NoCaching,
130
- // ODSP storage works better if it has less number of blobs / edges
131
- // Runtime creating many small blobs results in sub-optimal perf.
132
- // 2K seems like the sweat spot:
133
- // The smaller the number, less blobs we aggregate. Most storages are very likely to have notion
134
- // of minimal "cluster" size, so having small blobs is wasteful
135
- // At the same time increasing the limit ensure that more blobs with user content are aggregated,
136
- // reducing possibility for de-duping of same blobs (i.e. .attributes rolled into aggregate blob
137
- // are not reused across data stores, or even within data store, resulting in duplication of content)
138
- // Note that duplication of content should not have significant impact for bytes over wire as
139
- // compression of http payload mostly takes care of it, but it does impact storage size and in-memory sizes.
140
- minBlobSize: 2048,
141
- maximumCacheDurationMs: defaultCacheExpiryTimeoutMs,
142
- };
143
- this.commitCache = new Map();
144
- this.attributesBlobHandles = new Set();
145
39
  this.firstVersionCall = true;
146
40
  // Driver specified limits for snapshot size and time.
147
41
  /**
@@ -153,26 +47,12 @@ export class OdspDocumentStorageService {
153
47
  this.maxSnapshotFetchTimeout = 120000; // 2 min
154
48
  // limits the amount of parallel "attachment" blob uploads
155
49
  this.createBlobRateLimiter = new RateLimiter(1);
156
- this.blobCache = new BlobCache();
157
50
  this.documentId = this.odspResolvedUrl.hashedDocumentId;
158
51
  this.snapshotUrl = this.odspResolvedUrl.endpoints.snapshotStorageUrl;
159
52
  this.attachmentPOSTUrl = this.odspResolvedUrl.endpoints.attachmentPOSTStorageUrl;
160
53
  this.attachmentGETUrl = this.odspResolvedUrl.endpoints.attachmentGETStorageUrl;
161
54
  this.odspSummaryUploadManager = new OdspSummaryUploadManager(this.snapshotUrl, getStorageToken, logger, epochTracker, !!((_a = this.hostPolicy.sessionOptions) === null || _a === void 0 ? void 0 : _a.forceAccessTokenViaAuthorizationHeader));
162
55
  }
163
- set ops(ops) {
164
- assert(this._ops === undefined, 0x0a5 /* "Trying to set ops when they are already set!" */);
165
- this._ops = ops;
166
- }
167
- get ops() {
168
- return this._ops;
169
- }
170
- get snapshotSequenceNumber() {
171
- return this._snapshotSequenceNumber;
172
- }
173
- get repositoryUrl() {
174
- return "";
175
- }
176
56
  async createBlob(file) {
177
57
  this.checkAttachmentPOSTUrl();
178
58
  const response = await getWithRetryForTokenRefresh(async (options) => {
@@ -196,70 +76,38 @@ export class OdspDocumentStorageService {
196
76
  });
197
77
  return response.content;
198
78
  }
199
- async readBlobCore(blobId) {
200
- const { blobContent, evicted } = this.blobCache.getBlob(blobId);
201
- let blob = blobContent;
202
- if (blob === undefined) {
203
- this.checkAttachmentGETUrl();
204
- blob = await getWithRetryForTokenRefresh(async (options) => {
205
- var _a;
206
- const storageToken = await this.getStorageToken(options, "GetBlob");
207
- const unAuthedUrl = `${this.attachmentGETUrl}/${encodeURIComponent(blobId)}/content`;
208
- const { url, headers } = getUrlAndHeadersWithAuth(unAuthedUrl, storageToken, !!((_a = this.hostPolicy.sessionOptions) === null || _a === void 0 ? void 0 : _a.forceAccessTokenViaAuthorizationHeader));
209
- return PerformanceEvent.timedExecAsync(this.logger, {
210
- eventName: "readDataBlob",
211
- blobId,
212
- evicted,
213
- headers: Object.keys(headers).length !== 0 ? true : undefined,
214
- waitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,
215
- }, async (event) => {
216
- const res = await this.epochTracker.fetchArray(url, { headers }, "blob");
217
- event.end(Object.assign(Object.assign({ waitQueueLength: this.epochTracker.rateLimiter.waitQueueLength }, res.propsToLog), { attempts: options.refresh ? 2 : 1 }));
218
- const cacheControl = res.headers.get("cache-control");
219
- if (cacheControl === undefined || !(cacheControl.includes("private") || cacheControl.includes("public"))) {
220
- this.logger.sendErrorEvent(Object.assign({ eventName: "NonCacheableBlob", cacheControl,
221
- blobId }, res.propsToLog));
222
- }
223
- return res.content;
224
- });
79
+ async fetchBlobFromStorage(blobId, evicted) {
80
+ this.checkAttachmentGETUrl();
81
+ const blob = await getWithRetryForTokenRefresh(async (options) => {
82
+ var _a;
83
+ const storageToken = await this.getStorageToken(options, "GetBlob");
84
+ const unAuthedUrl = `${this.attachmentGETUrl}/${encodeURIComponent(blobId)}/content`;
85
+ const { url, headers } = getUrlAndHeadersWithAuth(unAuthedUrl, storageToken, !!((_a = this.hostPolicy.sessionOptions) === null || _a === void 0 ? void 0 : _a.forceAccessTokenViaAuthorizationHeader));
86
+ return PerformanceEvent.timedExecAsync(this.logger, {
87
+ eventName: "readDataBlob",
88
+ blobId,
89
+ evicted,
90
+ headers: Object.keys(headers).length !== 0 ? true : undefined,
91
+ waitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,
92
+ }, async (event) => {
93
+ const res = await this.epochTracker.fetchArray(url, { headers }, "blob");
94
+ event.end(Object.assign(Object.assign({ waitQueueLength: this.epochTracker.rateLimiter.waitQueueLength }, res.propsToLog), { attempts: options.refresh ? 2 : 1 }));
95
+ const cacheControl = res.headers.get("cache-control");
96
+ if (cacheControl === undefined || !(cacheControl.includes("private") || cacheControl.includes("public"))) {
97
+ this.logger.sendErrorEvent(Object.assign({ eventName: "NonCacheableBlob", cacheControl,
98
+ blobId }, res.propsToLog));
99
+ }
100
+ return res.content;
225
101
  });
226
- this.blobCache.setBlob(blobId, blob);
227
- }
102
+ });
103
+ this.blobCache.setBlob(blobId, blob);
228
104
  return blob;
229
105
  }
230
- async readBlob(blobId) {
231
- return this.readBlobCore(blobId);
232
- }
233
106
  async getSnapshotTree(version, scenarioName) {
234
107
  if (!this.snapshotUrl) {
235
108
  return null;
236
109
  }
237
- let id;
238
- if (!version || !version.id) {
239
- const versions = await this.getVersions(null, 1, scenarioName);
240
- if (!versions || versions.length === 0) {
241
- return null;
242
- }
243
- id = versions[0].id;
244
- }
245
- else {
246
- id = version.id;
247
- }
248
- const snapshotTree = await this.readTree(id, scenarioName);
249
- if (!snapshotTree) {
250
- return null;
251
- }
252
- if (snapshotTree.blobs) {
253
- const attributesBlob = snapshotTree.blobs.attributes;
254
- if (attributesBlob) {
255
- this.attributesBlobHandles.add(attributesBlob);
256
- }
257
- }
258
- // When we upload the container snapshot, we upload appTree in ".app" and protocol tree in ".protocol"
259
- // So when we request the snapshot we get ".app" as tree and not as commit node as in the case just above.
260
- const appTree = snapshotTree.trees[".app"];
261
- const protocolTree = snapshotTree.trees[".protocol"];
262
- return this.combineProtocolAndAppSnapshotTree(appTree, protocolTree);
110
+ return super.getSnapshotTree(version, scenarioName);
263
111
  }
264
112
  async getVersions(blobid, count, scenarioName) {
265
113
  // Regular load workflow uses blobId === documentID to indicate "latest".
@@ -358,19 +206,7 @@ export class OdspDocumentStorageService {
358
206
  });
359
207
  // Successful call, make network calls only
360
208
  this.firstVersionCall = false;
361
- this._snapshotSequenceNumber = odspSnapshotCacheValue.sequenceNumber;
362
- const { snapshotTree, blobs, ops } = odspSnapshotCacheValue;
363
- // id should be undefined in case of just ops in snapshot.
364
- let id;
365
- if (snapshotTree) {
366
- id = snapshotTree.id;
367
- assert(id !== undefined, 0x221 /* "Root tree should contain the id" */);
368
- this.setRootTree(id, snapshotTree);
369
- }
370
- if (blobs) {
371
- this.initBlobsCache(blobs);
372
- }
373
- this.ops = ops;
209
+ const id = this.initializeFromSnapshot(odspSnapshotCacheValue);
374
210
  return id ? [{ id, treeId: undefined }] : [];
375
211
  }
376
212
  return getWithRetryForTokenRefresh(async (options) => {
@@ -455,34 +291,25 @@ export class OdspDocumentStorageService {
455
291
  this.checkSnapshotUrl();
456
292
  // Enable flushing only if we have single commit summary and this is not the initial summary for an empty file
457
293
  if (".protocol" in summary.tree && context.ackHandle !== undefined) {
458
- let retry = 0;
294
+ let retry = 1;
459
295
  for (;;) {
460
296
  const result = await this.flushCallback();
461
297
  const seq = result.lastPersistedSequenceNumber;
462
298
  if (seq !== undefined && seq >= context.referenceSequenceNumber) {
463
299
  break;
464
300
  }
465
- retry++;
466
301
  if (retry > 3) {
467
302
  this.logger.sendErrorEvent(Object.assign(Object.assign({ eventName: "FlushFailure" }, result), { retry, referenceSequenceNumber: context.referenceSequenceNumber }));
468
303
  break;
469
304
  }
470
305
  this.logger.sendPerformanceEvent(Object.assign(Object.assign({ eventName: "FlushExtraCall" }, result), { retry, referenceSequenceNumber: context.referenceSequenceNumber }));
306
+ retry++;
471
307
  await delay(1000 * ((_a = result.retryAfter) !== null && _a !== void 0 ? _a : 1));
472
308
  }
473
309
  }
474
310
  const id = await this.odspSummaryUploadManager.writeSummaryTree(summary, context);
475
311
  return id;
476
312
  }
477
- async downloadSummary(commit) {
478
- throw new Error("Not implemented yet");
479
- }
480
- setRootTree(id, tree) {
481
- this.commitCache.set(id, tree);
482
- }
483
- initBlobsCache(blobs) {
484
- this.blobCache.addBlobs(blobs);
485
- }
486
313
  checkSnapshotUrl() {
487
314
  if (!this.snapshotUrl) {
488
315
  throw new NonRetryableError("Method failed because no snapshot url was available", DriverErrorType.genericError, { driverVersion });
@@ -498,47 +325,27 @@ export class OdspDocumentStorageService {
498
325
  throw new NonRetryableError("Method failed because no attachment GET url was available", DriverErrorType.genericError, { driverVersion });
499
326
  }
500
327
  }
501
- async readTree(id, scenarioName) {
502
- if (!this.snapshotUrl) {
503
- return null;
504
- }
505
- let tree = this.commitCache.get(id);
506
- if (!tree) {
507
- tree = await getWithRetryForTokenRefresh(async (options) => {
508
- var _a, _b;
509
- const storageToken = await this.getStorageToken(options, "ReadCommit");
510
- const snapshotDownloader = async (url, fetchOptions) => {
511
- return this.epochTracker.fetchAndParseAsJSON(url, fetchOptions, "snapshotTree", undefined, scenarioName);
512
- };
513
- const snapshot = await fetchSnapshot(this.snapshotUrl, storageToken, id, this.fetchFullSnapshot, !!((_a = this.hostPolicy.sessionOptions) === null || _a === void 0 ? void 0 : _a.forceAccessTokenViaAuthorizationHeader), this.logger, snapshotDownloader);
514
- let treeId = "";
515
- if (snapshot.snapshotTree) {
516
- assert(snapshot.snapshotTree.id !== undefined, 0x222 /* "Root tree should contain the id!!" */);
517
- treeId = snapshot.snapshotTree.id;
518
- this.setRootTree(treeId, snapshot.snapshotTree);
519
- }
520
- if (snapshot.blobs) {
521
- this.initBlobsCache(snapshot.blobs);
522
- }
523
- // If the version id doesn't match with the id of the tree, then use the id of first tree which in that case
524
- // will be the actual id of tree to be fetched.
525
- return (_b = this.commitCache.get(id)) !== null && _b !== void 0 ? _b : this.commitCache.get(treeId);
526
- });
527
- }
528
- if (!tree) {
529
- return null;
530
- }
531
- return tree;
532
- }
533
- combineProtocolAndAppSnapshotTree(hierarchicalAppTree, hierarchicalProtocolTree) {
534
- const summarySnapshotTree = {
535
- blobs: Object.assign({}, hierarchicalAppTree.blobs),
536
- trees: Object.assign(Object.assign({}, hierarchicalAppTree.trees), {
537
- // the app tree could have a .protocol
538
- // in that case we want to server protocol to override it
539
- ".protocol": hierarchicalProtocolTree }),
540
- };
541
- return summarySnapshotTree;
328
+ async fetchTreeFromSnapshot(id, scenarioName) {
329
+ return getWithRetryForTokenRefresh(async (options) => {
330
+ var _a, _b;
331
+ const storageToken = await this.getStorageToken(options, "ReadCommit");
332
+ const snapshotDownloader = async (url, fetchOptions) => {
333
+ return this.epochTracker.fetchAndParseAsJSON(url, fetchOptions, "snapshotTree", undefined, scenarioName);
334
+ };
335
+ const snapshot = await fetchSnapshot(this.snapshotUrl, storageToken, id, this.fetchFullSnapshot, !!((_a = this.hostPolicy.sessionOptions) === null || _a === void 0 ? void 0 : _a.forceAccessTokenViaAuthorizationHeader), this.logger, snapshotDownloader);
336
+ let treeId = "";
337
+ if (snapshot.snapshotTree) {
338
+ assert(snapshot.snapshotTree.id !== undefined, 0x222 /* "Root tree should contain the id!!" */);
339
+ treeId = snapshot.snapshotTree.id;
340
+ this.setRootTree(treeId, snapshot.snapshotTree);
341
+ }
342
+ if (snapshot.blobs) {
343
+ this.initBlobsCache(snapshot.blobs);
344
+ }
345
+ // If the version id doesn't match with the id of the tree, then use the id of first tree which in that case
346
+ // will be the actual id of tree to be fetched.
347
+ return (_b = this.commitCache.get(id)) !== null && _b !== void 0 ? _b : this.commitCache.get(treeId);
348
+ });
542
349
  }
543
350
  }
544
351
  /* eslint-enable max-len */