@fluidframework/odsp-driver 2.113.1 → 2.115.0

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 (77) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/api-extractor/api-extractor-lint-legacyAlpha.cjs.json +5 -0
  3. package/api-extractor/api-extractor-lint-legacyAlpha.esm.json +5 -0
  4. package/api-extractor/api-extractor.legacy.json +5 -1
  5. package/api-report/odsp-driver.legacy.alpha.api.md +232 -0
  6. package/dist/getUrlAndHeadersWithAuth.d.ts +4 -0
  7. package/dist/getUrlAndHeadersWithAuth.d.ts.map +1 -1
  8. package/dist/getUrlAndHeadersWithAuth.js +4 -0
  9. package/dist/getUrlAndHeadersWithAuth.js.map +1 -1
  10. package/dist/index.d.ts +3 -2
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +7 -3
  13. package/dist/index.js.map +1 -1
  14. package/dist/legacy.d.ts +1 -1
  15. package/dist/legacyAlpha.d.ts +49 -0
  16. package/dist/odspVersionManager/odspFileVersionFetcher.d.ts +40 -1
  17. package/dist/odspVersionManager/odspFileVersionFetcher.d.ts.map +1 -1
  18. package/dist/odspVersionManager/odspFileVersionFetcher.js +52 -14
  19. package/dist/odspVersionManager/odspFileVersionFetcher.js.map +1 -1
  20. package/dist/odspVersionManager/odspVersionManager.d.ts +23 -45
  21. package/dist/odspVersionManager/odspVersionManager.d.ts.map +1 -1
  22. package/dist/odspVersionManager/odspVersionManager.js +68 -33
  23. package/dist/odspVersionManager/odspVersionManager.js.map +1 -1
  24. package/dist/packageVersion.d.ts +1 -1
  25. package/dist/packageVersion.js +1 -1
  26. package/dist/packageVersion.js.map +1 -1
  27. package/dist/pointInTimeDriver/odspPointInTimeDocumentService.d.ts +5 -0
  28. package/dist/pointInTimeDriver/odspPointInTimeDocumentService.d.ts.map +1 -1
  29. package/dist/pointInTimeDriver/odspPointInTimeDocumentService.js +6 -3
  30. package/dist/pointInTimeDriver/odspPointInTimeDocumentService.js.map +1 -1
  31. package/dist/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.d.ts +25 -33
  32. package/dist/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.d.ts.map +1 -1
  33. package/dist/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.js +62 -38
  34. package/dist/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.js.map +1 -1
  35. package/dist/public.d.ts +1 -1
  36. package/internal.d.ts +1 -1
  37. package/legacy/alpha.d.ts +11 -0
  38. package/legacy.d.ts +1 -1
  39. package/lib/getUrlAndHeadersWithAuth.d.ts +4 -0
  40. package/lib/getUrlAndHeadersWithAuth.d.ts.map +1 -1
  41. package/lib/getUrlAndHeadersWithAuth.js +4 -0
  42. package/lib/getUrlAndHeadersWithAuth.js.map +1 -1
  43. package/lib/index.d.ts +3 -2
  44. package/lib/index.d.ts.map +1 -1
  45. package/lib/index.js +5 -3
  46. package/lib/index.js.map +1 -1
  47. package/lib/legacy.d.ts +1 -1
  48. package/lib/legacyAlpha.d.ts +49 -0
  49. package/lib/odspVersionManager/odspFileVersionFetcher.d.ts +40 -1
  50. package/lib/odspVersionManager/odspFileVersionFetcher.d.ts.map +1 -1
  51. package/lib/odspVersionManager/odspFileVersionFetcher.js +53 -15
  52. package/lib/odspVersionManager/odspFileVersionFetcher.js.map +1 -1
  53. package/lib/odspVersionManager/odspVersionManager.d.ts +23 -45
  54. package/lib/odspVersionManager/odspVersionManager.d.ts.map +1 -1
  55. package/lib/odspVersionManager/odspVersionManager.js +68 -33
  56. package/lib/odspVersionManager/odspVersionManager.js.map +1 -1
  57. package/lib/packageVersion.d.ts +1 -1
  58. package/lib/packageVersion.js +1 -1
  59. package/lib/packageVersion.js.map +1 -1
  60. package/lib/pointInTimeDriver/odspPointInTimeDocumentService.d.ts +5 -0
  61. package/lib/pointInTimeDriver/odspPointInTimeDocumentService.d.ts.map +1 -1
  62. package/lib/pointInTimeDriver/odspPointInTimeDocumentService.js +6 -3
  63. package/lib/pointInTimeDriver/odspPointInTimeDocumentService.js.map +1 -1
  64. package/lib/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.d.ts +25 -33
  65. package/lib/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.d.ts.map +1 -1
  66. package/lib/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.js +62 -38
  67. package/lib/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.js.map +1 -1
  68. package/lib/public.d.ts +1 -1
  69. package/package.json +29 -17
  70. package/src/getUrlAndHeadersWithAuth.ts +4 -0
  71. package/src/index.ts +8 -3
  72. package/src/odspVersionManager/DEV.md +376 -54
  73. package/src/odspVersionManager/odspFileVersionFetcher.ts +111 -16
  74. package/src/odspVersionManager/odspVersionManager.ts +106 -68
  75. package/src/packageVersion.ts +1 -1
  76. package/src/pointInTimeDriver/odspPointInTimeDocumentService.ts +8 -4
  77. package/src/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.ts +123 -48
@@ -6,18 +6,24 @@
6
6
  import type { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
7
7
  import type {
8
8
  IDocumentService,
9
+ IDocumentServiceFactory,
9
10
  IPersistedCache,
10
11
  IResolvedUrl,
11
12
  } from "@fluidframework/driver-definitions/internal";
12
13
  import type {
13
14
  HostStoragePolicy,
15
+ IOdspResolvedUrl,
14
16
  IOdspUrlParts,
15
17
  OdspResourceTokenFetchOptions,
16
18
  TokenFetcher,
17
19
  } from "@fluidframework/odsp-driver-definitions/internal";
18
- import { UsageError, createChildLogger } from "@fluidframework/telemetry-utils/internal";
20
+ import {
21
+ UsageError,
22
+ createChildLogger,
23
+ type TelemetryLoggerExt,
24
+ } from "@fluidframework/telemetry-utils/internal";
19
25
 
20
- import { createOdspCacheAndTracker } from "../epochTracker.js";
26
+ import { createOdspCacheAndTracker, type EpochTracker } from "../epochTracker.js";
21
27
  import { NonPersistentCache } from "../odspCache.js";
22
28
  import { OdspDocumentServiceFactoryCore } from "../odspDocumentServiceFactoryCore.js";
23
29
  import { OdspDriverUrlResolver } from "../odspDriverUrlResolver.js";
@@ -34,24 +40,49 @@ import {
34
40
  import { OdspPointInTimeDocumentService } from "./odspPointInTimeDocumentService.js";
35
41
 
36
42
  /**
37
- * ODSP document service factory that additionally supports point-in-time (sequence-number-based)
38
- * loading.
43
+ * An ODSP document service factory that supports point-in-time (sequence-number-based) loading.
39
44
  *
40
45
  * @remarks
41
- * This extends {@link OdspDocumentServiceFactoryCore} with the ability to materialize a read-only
42
- * document service at a requested Fluid sequence number. The loader detects this capability via the
43
- * presence of {@link OdspPointInTimeDocumentServiceFactory.createPointInTimeDocumentService}, so
44
- * hosts that want to load a container to a target sequence number must construct this factory
45
- * (rather than the legacy `OdspDocumentServiceFactory`) and pass it to the loader.
46
+ * The loader detects this capability structurally, so hosts can pass this factory directly to
47
+ * `loadContainerToSequenceNumber`.
46
48
  *
47
- * @internal
49
+ * @legacy @alpha
48
50
  */
49
- export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFactoryCore {
51
+ export interface IPointInTimeDocumentServiceFactory extends IDocumentServiceFactory {
52
+ /**
53
+ * Creates a document service that materializes the document at the requested sequence number.
54
+ *
55
+ * @param resolvedUrl - The resolved ODSP document URL.
56
+ * @param targetSequenceNumber - The sequence number at which to materialize the document.
57
+ * @param logger - Optional telemetry logger.
58
+ * @param clientIsSummarizer - Whether the requesting client is a summarizer.
59
+ * @returns A read-only document service materialized at the requested sequence number.
60
+ */
61
+ createPointInTimeDocumentService(
62
+ resolvedUrl: IResolvedUrl,
63
+ targetSequenceNumber: number,
64
+ logger?: ITelemetryBaseLogger,
65
+ clientIsSummarizer?: boolean,
66
+ ): Promise<IDocumentService>;
67
+ }
68
+
69
+ class OdspPointInTimeDocumentServiceFactory
70
+ extends OdspDocumentServiceFactoryCore
71
+ implements IPointInTimeDocumentServiceFactory
72
+ {
50
73
  /**
51
74
  * The storage token fetcher, captured here because the base class keeps it private.
52
75
  */
53
76
  private readonly getStorageTokenForVersions: TokenFetcher<OdspResourceTokenFetchOptions>;
54
77
 
78
+ /**
79
+ * Creates a point-in-time-capable ODSP document service factory.
80
+ *
81
+ * @param getStorageToken - Fetches storage access tokens.
82
+ * @param getWebsocketToken - Fetches websocket access tokens, or `undefined` when unavailable.
83
+ * @param persistedCache - Optional persisted ODSP cache.
84
+ * @param hostPolicy - Optional host storage policy.
85
+ */
55
86
  constructor(
56
87
  getStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>,
57
88
  getWebsocketToken: TokenFetcher<OdspResourceTokenFetchOptions> | undefined,
@@ -66,6 +97,12 @@ export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFa
66
97
  * Creates a document service that reads its snapshot from the closest file version at or before
67
98
  * the target and its deltas from the live document, materializing a requested sequence number
68
99
  * through replay.
100
+ *
101
+ * @param resolvedUrl - The resolved ODSP document URL.
102
+ * @param targetSequenceNumber - The sequence number at which to materialize the document.
103
+ * @param logger - Optional telemetry logger.
104
+ * @param clientIsSummarizer - Whether the requesting client is a summarizer.
105
+ * @returns A read-only document service materialized at the requested sequence number.
69
106
  */
70
107
  public async createPointInTimeDocumentService(
71
108
  resolvedUrl: IResolvedUrl,
@@ -73,11 +110,37 @@ export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFa
73
110
  logger?: ITelemetryBaseLogger,
74
111
  clientIsSummarizer?: boolean,
75
112
  ): Promise<IDocumentService> {
76
- const versionManager = await this.createVersionManager(
77
- resolvedUrl,
78
- logger,
113
+ const odspLogger = createOdspLogger(logger);
114
+ const extLogger = createChildLogger({ logger: odspLogger });
115
+ const odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);
116
+
117
+ // Build ONE cache-and-tracker and thread its EpochTracker through every read this method
118
+ // makes: the version-history reads that pick the base, the recoverable base snapshot, and the
119
+ // live op stream. This shared tracker IS the lineage guard.
120
+ //
121
+ // ODSP stamps each response with the file's epoch; an EpochTracker instance pins itself to the
122
+ // first epoch it sees and throws on any later divergence (see setEpoch / checkForEpochError in
123
+ // epochTracker.ts).
124
+ //
125
+ // A fresh NonPersistentCache keeps this read-only historical load isolated from the factory's
126
+ // shared cache, so a base file version's snapshot can never leak into a normal live load.
127
+ const cacheAndTracker = createOdspCacheAndTracker(
128
+ this.persistedCache,
129
+ new NonPersistentCache(),
130
+ {
131
+ resolvedUrl: odspResolvedUrl,
132
+ docId: odspResolvedUrl.hashedDocumentId,
133
+ fileVersion: odspResolvedUrl.fileVersion,
134
+ },
135
+ extLogger,
79
136
  clientIsSummarizer,
80
137
  );
138
+
139
+ const versionManager = this.createVersionManager(
140
+ odspResolvedUrl,
141
+ extLogger,
142
+ cacheAndTracker.epochTracker,
143
+ );
81
144
  const baseResult = await versionManager.findBaseForSeq(targetSequenceNumber);
82
145
  if (baseResult.kind === "noBaseVersion") {
83
146
  const oldestResolvedSequenceDetail =
@@ -93,14 +156,18 @@ export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFa
93
156
  resolvedUrl,
94
157
  baseResult.base.versionId,
95
158
  );
96
- const recoverableDocumentService = await this.createDocumentService(
159
+ // Both services are created via createDocumentServiceCore with the shared cacheAndTracker, so
160
+ // their reads validate against the same epoch - see the lineage-guard note above.
161
+ const recoverableDocumentService = await this.createDocumentServiceCore(
97
162
  recoverableResolvedUrl,
98
- logger,
163
+ odspLogger,
164
+ cacheAndTracker,
99
165
  clientIsSummarizer,
100
166
  );
101
- const liveDocumentService = await this.createDocumentService(
167
+ const liveDocumentService = await this.createDocumentServiceCore(
102
168
  resolvedUrl,
103
- logger,
169
+ odspLogger,
170
+ cacheAndTracker,
104
171
  clientIsSummarizer,
105
172
  );
106
173
  return new OdspPointInTimeDocumentService(
@@ -116,49 +183,32 @@ export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFa
116
183
  * versions and resolves the closest version at or before a target sequence number.
117
184
  *
118
185
  * @remarks
119
- * This wires up the plumbing the version manager needs to talk to ODSP: it resolves the URL to
120
- * its ODSP parts (site/drive/item), creates a scoped child logger, an epoch tracker (from a fresh
121
- * NonPersistentCache, since only the tracker is needed for consistency checks), and an
122
- * instrumented storage-token/auth-header fetcher. The resulting manager is used by
123
- * {@link OdspPointInTimeDocumentServiceFactory.createPointInTimeDocumentService} to pick the base
124
- * snapshot for point-in-time loading.
186
+ * The caller passes in the shared {@link EpochTracker} so the version-history reads validate
187
+ * against the same epoch as the recoverable and live document services - this is the lineage
188
+ * guard used by `createPointInTimeDocumentService`.
189
+ * The manager itself only needs the URL parts and an instrumented storage-token/auth-header
190
+ * fetcher wired to that tracker.
125
191
  */
126
- private async createVersionManager(
127
- resolvedUrl: IResolvedUrl,
128
- logger?: ITelemetryBaseLogger,
129
- clientIsSummarizer?: boolean,
130
- ): Promise<IOdspVersionManager> {
131
- const odspLogger = createOdspLogger(logger);
132
- const extLogger = createChildLogger({ logger: odspLogger });
133
- const odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);
192
+ private createVersionManager(
193
+ odspResolvedUrl: IOdspResolvedUrl,
194
+ logger: TelemetryLoggerExt,
195
+ epochTracker: EpochTracker,
196
+ ): IOdspVersionManager {
134
197
  const urlParts: IOdspUrlParts = {
135
198
  siteUrl: odspResolvedUrl.siteUrl,
136
199
  driveId: odspResolvedUrl.driveId,
137
200
  itemId: odspResolvedUrl.itemId,
138
201
  };
139
- // Only the epochTracker from the returned cacheAndTracker is used below, so a fresh
140
- // NonPersistentCache is sufficient here.
141
- const cacheAndTracker = createOdspCacheAndTracker(
142
- this.persistedCache,
143
- new NonPersistentCache(),
144
- {
145
- resolvedUrl: odspResolvedUrl,
146
- docId: odspResolvedUrl.hashedDocumentId,
147
- fileVersion: odspResolvedUrl.fileVersion,
148
- },
149
- extLogger,
150
- clientIsSummarizer,
151
- );
152
202
  const getAuthHeader = toInstrumentedOdspStorageTokenFetcher(
153
- extLogger,
203
+ logger,
154
204
  urlParts,
155
205
  this.getStorageTokenForVersions,
156
206
  );
157
207
  return createOdspVersionManager({
158
208
  urlParts,
159
209
  getAuthHeader,
160
- epochTracker: cacheAndTracker.epochTracker,
161
- logger: extLogger,
210
+ epochTracker,
211
+ logger,
162
212
  });
163
213
  }
164
214
 
@@ -183,3 +233,28 @@ export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFa
183
233
  });
184
234
  }
185
235
  }
236
+
237
+ /**
238
+ * Creates an ODSP document service factory that supports point-in-time loading.
239
+ *
240
+ * @param getStorageToken - Fetches storage access tokens.
241
+ * @param getWebsocketToken - Fetches websocket access tokens, or `undefined` when unavailable.
242
+ * @param persistedCache - Optional persisted ODSP cache.
243
+ * @param hostPolicy - Optional host storage policy.
244
+ * @returns An ODSP document service factory with point-in-time loading capability.
245
+ *
246
+ * @legacy @alpha
247
+ */
248
+ export function getOdspPointInTimeDocumentServiceFactory(
249
+ getStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>,
250
+ getWebsocketToken: TokenFetcher<OdspResourceTokenFetchOptions> | undefined,
251
+ persistedCache?: IPersistedCache,
252
+ hostPolicy?: HostStoragePolicy,
253
+ ): IPointInTimeDocumentServiceFactory {
254
+ return new OdspPointInTimeDocumentServiceFactory(
255
+ getStorageToken,
256
+ getWebsocketToken,
257
+ persistedCache,
258
+ hostPolicy,
259
+ );
260
+ }