Skip to content

Commit 33d36d6

Browse files
sonalideshpandemsftlindsnguyensonalivdeshpande
authored
Move marker and load to sequence number API to legacy alpha (#27891)
- Promotes these APIs from internal imports to legacy-alpha entrypoints: - `IVersionMarkResolver`, `ResolveResult`, and `VersionMarkCapture` - `loadContainerToSequenceNumber` and `ILoadContainerToSequenceNumberProps` - `OdspPointInTimeDocumentServiceFactory` - Renames `captureVersionMark(): Promise<VersionMarkCapture>` to synchronous `sealAndCaptureVersionMark(): VersionMarkCapture`, making its batch-flush side effect explicit. - Adds the required legacy-alpha package exports, API Extractor configuration, API reports, and API documentation. - Updates tests for the renamed synchronous capture API. - Expands `versionMarks/DEV.md` with implementation details, MSN cache behavior, limitations, and future work --------- Co-authored-by: Lindsey Nguyen <lindsnguyen@microsoft.com> Co-authored-by: Sonali Deshpande <sdeshpande@microsoft.com> Copilot-Session: 24008af9-6872-4245-863e-ad08c733bbf1
1 parent b580df2 commit 33d36d6

17 files changed

Lines changed: 987 additions & 55 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3+
"extends": "<projectFolder>/../../../common/build/build-common/api-extractor-lint.entrypoint.json",
4+
"mainEntryPointFilePath": "<projectFolder>/dist/legacyAlpha.d.ts"
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3+
"extends": "<projectFolder>/../../../common/build/build-common/api-extractor-lint.entrypoint.json",
4+
"mainEntryPointFilePath": "<projectFolder>/lib/legacyAlpha.d.ts"
5+
}
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
{
22
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3-
"extends": "<projectFolder>/../../../common/build/build-common/api-extractor-report.esm.legacy.json"
3+
"extends": "<projectFolder>/../../../common/build/build-common/api-extractor-report.esm.legacy.json",
4+
"mainEntryPointFilePath": "<projectFolder>/lib/legacyAlpha.d.ts",
5+
"apiReport": {
6+
"reportVariants": ["public", "beta", "alpha"]
7+
}
48
}
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
## Alpha API Report File for "@fluidframework/odsp-driver"
2+
3+
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
4+
5+
```ts
6+
7+
// @beta @legacy
8+
export function checkUrl(documentUrl: URL): DriverPreCheckInfo | undefined;
9+
10+
// @beta @legacy
11+
export function createLocalOdspDocumentServiceFactory(localSnapshot: Uint8Array | string): IDocumentServiceFactory;
12+
13+
// @beta @legacy
14+
export function createOdspCreateContainerRequest(siteUrl: string, driveId: string, filePath: string, fileName: string, createShareLinkType?: ISharingLinkKind, containerPackageInfo?: IContainerPackageInfo | undefined): IRequest;
15+
16+
// @beta @legacy
17+
export function createOdspUrl(l: OdspFluidDataStoreLocator): string;
18+
19+
// @beta @legacy
20+
export function encodeOdspFluidDataStoreLocator(locator: OdspFluidDataStoreLocator): string;
21+
22+
// @beta @legacy
23+
export class EpochTracker implements IPersistedFileCache {
24+
constructor(cache: IPersistedCache, fileEntry: IFileEntry, logger: ITelemetryLoggerExt, clientIsSummarizer?: boolean | undefined);
25+
// (undocumented)
26+
protected readonly cache: IPersistedCache;
27+
// (undocumented)
28+
protected readonly clientIsSummarizer?: boolean | undefined;
29+
fetch(url: string, fetchOptions: RequestInit, fetchType: FetchType, addInBody?: boolean, fetchReason?: string): Promise<IOdspResponse<Response>>;
30+
fetchAndParseAsJSON<T>(url: string, fetchOptions: RequestInit, fetchType: FetchType, addInBody?: boolean, fetchReason?: string): Promise<IOdspResponse<T>>;
31+
fetchArray(url: string, fetchOptions: {
32+
[index: string]: RequestInit;
33+
}, fetchType: FetchType, addInBody?: boolean, fetchReason?: string): Promise<IOdspResponse<ArrayBuffer>>;
34+
// (undocumented)
35+
protected readonly fileEntry: IFileEntry;
36+
// (undocumented)
37+
get fluidEpoch(): string | undefined;
38+
// (undocumented)
39+
get(entry: IEntry): Promise<any>;
40+
// (undocumented)
41+
protected readonly logger: ITelemetryLoggerExt;
42+
// (undocumented)
43+
put(entry: IEntry, value: any): Promise<void>;
44+
// (undocumented)
45+
readonly rateLimiter: RateLimiter;
46+
// (undocumented)
47+
removeEntries(): Promise<void>;
48+
// (undocumented)
49+
setEpoch(epoch: string, fromCache: boolean, fetchType: FetchTypeInternal): void;
50+
// (undocumented)
51+
validateEpoch(epoch: string | undefined, fetchType: FetchType): Promise<void>;
52+
// (undocumented)
53+
protected validateEpochFromResponse(epochFromResponse: string | undefined, fetchType: FetchTypeInternal, fromCache?: boolean): void;
54+
}
55+
56+
// @beta @legacy (undocumented)
57+
export type FetchType = "blob" | "createBlob" | "createFile" | "joinSession" | "ops" | "test" | "snapshotTree" | "treesLatest" | "uploadSummary" | "push" | "versions" | "renameFile";
58+
59+
// @beta @legacy (undocumented)
60+
export type FetchTypeInternal = FetchType | "cache";
61+
62+
// @beta @legacy
63+
export function getHashedDocumentId(driveId: string, itemId: string): Promise<string>;
64+
65+
// @beta @legacy
66+
export function getLocatorFromOdspUrl(url: URL, requireFluidSignature?: boolean): OdspFluidDataStoreLocator | undefined;
67+
68+
// @beta @legacy (undocumented)
69+
export interface ICacheAndTracker {
70+
// (undocumented)
71+
cache: IOdspCache;
72+
// (undocumented)
73+
epochTracker: EpochTracker;
74+
}
75+
76+
// @beta @legacy
77+
export interface INonPersistentCache {
78+
readonly fileUrlCache: PromiseCache<string, IOdspResolvedUrl>;
79+
readonly sessionJoinCache: PromiseCache<string, {
80+
entryTime: number;
81+
joinSessionResponse: ISocketStorageDiscovery;
82+
}>;
83+
readonly snapshotPrefetchResultCache: PromiseCache<string, IPrefetchSnapshotContents>;
84+
}
85+
86+
// @beta @legacy
87+
export interface IOdspCache extends INonPersistentCache {
88+
readonly persistedCache: IPersistedFileCache;
89+
}
90+
91+
// @beta @legacy (undocumented)
92+
export interface IOdspResponse<T> {
93+
// (undocumented)
94+
content: T;
95+
// (undocumented)
96+
duration: number;
97+
// (undocumented)
98+
headers: Map<string, string>;
99+
// (undocumented)
100+
propsToLog: ITelemetryBaseProperties;
101+
}
102+
103+
// @beta @legacy
104+
export interface IPersistedFileCache {
105+
// (undocumented)
106+
get(entry: IEntry): Promise<any>;
107+
// (undocumented)
108+
put(entry: IEntry, value: any): Promise<void>;
109+
// (undocumented)
110+
removeEntries(): Promise<void>;
111+
}
112+
113+
// @beta @legacy (undocumented)
114+
export interface IPrefetchSnapshotContents extends ISnapshot {
115+
// (undocumented)
116+
fluidEpoch: string;
117+
// (undocumented)
118+
prefetchStartTime: number;
119+
}
120+
121+
// @beta @deprecated @legacy (undocumented)
122+
export interface ISnapshotContents {
123+
// (undocumented)
124+
blobs: Map<string, ArrayBuffer>;
125+
latestSequenceNumber: number | undefined;
126+
// (undocumented)
127+
ops: ISequencedDocumentMessage[];
128+
sequenceNumber: number | undefined;
129+
// (undocumented)
130+
snapshotTree: ISnapshotTree;
131+
}
132+
133+
// @beta @legacy
134+
export function isOdspResolvedUrl(resolvedUrl: IResolvedUrl): resolvedUrl is IOdspResolvedUrl;
135+
136+
// @beta @legacy
137+
export const locatorQueryParamName = "nav";
138+
139+
// @beta @legacy (undocumented)
140+
export const OdcApiSiteOrigin = "https://my.microsoftpersonalcontent.com";
141+
142+
// @beta @legacy (undocumented)
143+
export const OdcFileSiteOrigin = "https://1drv.ms";
144+
145+
// @beta @legacy
146+
export class OdspDocumentServiceFactory extends OdspDocumentServiceFactoryCore {
147+
constructor(getStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>, getWebsocketToken: TokenFetcher<OdspResourceTokenFetchOptions> | undefined, persistedCache?: IPersistedCache, hostPolicy?: HostStoragePolicy);
148+
}
149+
150+
// @beta @legacy
151+
export class OdspDocumentServiceFactoryCore implements IDocumentServiceFactory, IRelaySessionAwareDriverFactory {
152+
constructor(getStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>, getWebsocketToken: TokenFetcher<OdspResourceTokenFetchOptions> | undefined, persistedCache?: IPersistedCache, hostPolicy?: HostStoragePolicy);
153+
// (undocumented)
154+
createContainer(createNewSummary: ISummaryTree | undefined, createNewResolvedUrl: IResolvedUrl, logger?: ITelemetryBaseLogger, clientIsSummarizer?: boolean): Promise<IDocumentService>;
155+
// (undocumented)
156+
createDocumentService(resolvedUrl: IResolvedUrl, logger?: ITelemetryBaseLogger, clientIsSummarizer?: boolean): Promise<IDocumentService>;
157+
// (undocumented)
158+
protected createDocumentServiceCore(resolvedUrl: IResolvedUrl, odspLogger: ITelemetryBaseLogger, cacheAndTrackerArg?: ICacheAndTracker, clientIsSummarizer?: boolean): Promise<IDocumentService>;
159+
getRelayServiceSessionInfo(resolvedUrl: IResolvedUrl): Promise<ISocketStorageDiscovery | undefined>;
160+
readonly ILayerCompatDetails?: unknown;
161+
// (undocumented)
162+
get IRelaySessionAwareDriverFactory(): this;
163+
// (undocumented)
164+
protected persistedCache: IPersistedCache;
165+
// (undocumented)
166+
get snapshotPrefetchResultCache(): PromiseCache<string, IPrefetchSnapshotContents>;
167+
}
168+
169+
// @beta @legacy
170+
export class OdspDriverUrlResolver implements IUrlResolver {
171+
constructor();
172+
getAbsoluteUrl(resolvedUrl: IResolvedUrl, relativeUrl: string, packageInfoSource?: IContainerPackageInfo): Promise<string>;
173+
resolve(request: IRequest): Promise<IOdspResolvedUrl>;
174+
}
175+
176+
// @beta @legacy
177+
export class OdspDriverUrlResolverForShareLink implements IUrlResolver {
178+
constructor(shareLinkFetcherProps?: ShareLinkFetcherProps | undefined, logger?: ITelemetryBaseLogger, appName?: string | undefined, getContext?: ((resolvedUrl: IOdspResolvedUrl, dataStorePath: string) => Promise<string | undefined>) | undefined, containerPackageInfo?: IContainerPackageInfo | undefined);
179+
appendDataStorePath(requestUrl: URL, pathToAppend: string): string | undefined;
180+
appendLocatorParams(baseUrl: string, resolvedUrl: IResolvedUrl, dataStorePath: string, packageInfoSource?: IContainerPackageInfo): Promise<string>;
181+
static createDocumentUrl(baseUrl: string, driverInfo: OdspFluidDataStoreLocator): string;
182+
getAbsoluteUrl(resolvedUrl: IResolvedUrl, dataStorePath: string, packageInfoSource?: IContainerPackageInfo): Promise<string>;
183+
resolve(request: IRequest): Promise<IOdspResolvedUrl>;
184+
}
185+
186+
// @beta @legacy (undocumented)
187+
export interface OdspFluidDataStoreLocator extends IOdspUrlParts {
188+
// (undocumented)
189+
appName?: string | undefined;
190+
// (undocumented)
191+
containerPackageName?: string | undefined;
192+
// (undocumented)
193+
context?: string | undefined;
194+
// (undocumented)
195+
dataStorePath: string;
196+
// (undocumented)
197+
fileVersion?: string | undefined;
198+
}
199+
200+
// @alpha @legacy
201+
export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFactoryCore {
202+
constructor(getStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>, getWebsocketToken: TokenFetcher<OdspResourceTokenFetchOptions> | undefined, persistedCache?: IPersistedCache, hostPolicy?: HostStoragePolicy);
203+
createPointInTimeDocumentService(resolvedUrl: IResolvedUrl, targetSequenceNumber: number, logger?: ITelemetryBaseLogger, clientIsSummarizer?: boolean): Promise<IDocumentService>;
204+
}
205+
206+
// @beta @legacy
207+
export function prefetchLatestSnapshot(resolvedUrl: IResolvedUrl, getStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>, persistedCache: IPersistedCache, _forceAccessTokenViaAuthorizationHeader: boolean, logger: ITelemetryBaseLogger, hostSnapshotFetchOptions: ISnapshotOptions | undefined, enableRedeemFallback?: boolean, _fetchBinarySnapshotFormat?: boolean, _snapshotFormatFetchType?: SnapshotFormatSupportType, odspDocumentServiceFactory?: OdspDocumentServiceFactory): Promise<boolean>;
208+
209+
// @beta @legacy
210+
export interface ShareLinkFetcherProps {
211+
identityType: IdentityType;
212+
tokenFetcher: TokenFetcher<OdspResourceTokenFetchOptions>;
213+
}
214+
215+
// @beta @legacy
216+
export enum SnapshotFormatSupportType {
217+
// (undocumented)
218+
Binary = 1,
219+
// (undocumented)
220+
Json = 0,
221+
// (undocumented)
222+
JsonAndBinary = 2
223+
}
224+
225+
// @beta @legacy
226+
export function storeLocatorInOdspUrl(url: URL, locator: OdspFluidDataStoreLocator): void;
227+
228+
// (No @packageDocumentation comment for this package)
229+
230+
```

packages/drivers/odsp-driver/package.json

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@
3333
"default": "./dist/index.js"
3434
}
3535
},
36+
"./legacy/alpha": {
37+
"import": {
38+
"types": "./lib/legacyAlpha.d.ts",
39+
"default": "./lib/index.js"
40+
},
41+
"require": {
42+
"types": "./dist/legacyAlpha.d.ts",
43+
"default": "./dist/index.js"
44+
}
45+
},
3646
"./internal": {
3747
"import": {
3848
"types": "./lib/index.d.ts",
@@ -55,8 +65,8 @@
5565
"build:compile": "fluid-build . --task compile",
5666
"build:docs": "api-extractor run --local",
5767
"build:entrypoints": "fluid-build . --task build:entrypoints",
58-
"build:entrypoints:cjs": "flub generate entrypoints --resolutionConditions require --outFileLegacyBeta legacy --outDir ./dist",
59-
"build:entrypoints:esm": "flub generate entrypoints --outFileLegacyBeta legacy --outDir ./lib --node10TypeCompat",
68+
"build:entrypoints:cjs": "flub generate entrypoints --resolutionConditions require --outFileLegacyBeta legacy --outFileLegacyAlpha legacyAlpha --outDir ./dist",
69+
"build:entrypoints:esm": "flub generate entrypoints --outFileLegacyBeta legacy --outFileLegacyAlpha legacyAlpha --outDir ./lib --node10TypeCompat",
6070
"build:esnext": "tsc --project ./tsconfig.json",
6171
"build:genver": "gen-version",
6272
"build:test": "concurrently npm:build:test:esm npm:build:test:cjs",
@@ -67,15 +77,17 @@
6777
"check:exports": "concurrently \"npm:check:exports:*\"",
6878
"check:exports:bundle-release-tags": "api-extractor run --config api-extractor/api-extractor-lint-bundle.json",
6979
"check:exports:cjs:legacy": "api-extractor run --config api-extractor/api-extractor-lint-legacy.cjs.json",
80+
"check:exports:cjs:legacyAlpha": "api-extractor run --config api-extractor/api-extractor-lint-legacyAlpha.cjs.json",
7081
"check:exports:cjs:public": "api-extractor run --config api-extractor/api-extractor-lint-public.cjs.json",
7182
"check:exports:esm:legacy": "api-extractor run --config api-extractor/api-extractor-lint-legacy.esm.json",
83+
"check:exports:esm:legacyAlpha": "api-extractor run --config api-extractor/api-extractor-lint-legacyAlpha.esm.json",
7284
"check:exports:esm:public": "api-extractor run --config api-extractor/api-extractor-lint-public.esm.json",
7385
"check:format": "npm run check:biome",
7486
"ci:build:api-reports": "concurrently \"npm:ci:build:api-reports:*\"",
7587
"ci:build:api-reports:current": "api-extractor run --config api-extractor/api-extractor.current.json",
7688
"ci:build:api-reports:legacy": "api-extractor run --config api-extractor/api-extractor.legacy.json",
7789
"ci:build:docs": "api-extractor run",
78-
"clean": "rimraf --glob dist lib {alpha,beta,internal,legacy}.d.ts \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
90+
"clean": "rimraf --glob dist lib {alpha,beta,internal,legacy}.d.ts legacyAlpha.d.ts \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
7991
"eslint": "eslint --quiet --format stylish src",
8092
"eslint:fix": "eslint --quiet --format stylish src --fix --fix-type problem,suggestion,layout",
8193
"format": "npm run format:biome",

packages/drivers/odsp-driver/src/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,22 @@ import { OdspPointInTimeDocumentService } from "./odspPointInTimeDocumentService
4949
* hosts that want to load a container to a target sequence number must construct this factory
5050
* (rather than the legacy `OdspDocumentServiceFactory`) and pass it to the loader.
5151
*
52-
* @internal
52+
* @legacy @alpha
5353
*/
5454
export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFactoryCore {
5555
/**
5656
* The storage token fetcher, captured here because the base class keeps it private.
5757
*/
5858
private readonly getStorageTokenForVersions: TokenFetcher<OdspResourceTokenFetchOptions>;
5959

60+
/**
61+
* Creates a point-in-time-capable ODSP document service factory.
62+
*
63+
* @param getStorageToken - Fetches storage access tokens.
64+
* @param getWebsocketToken - Fetches websocket access tokens, or `undefined` when unavailable.
65+
* @param persistedCache - Optional persisted ODSP cache.
66+
* @param hostPolicy - Optional host storage policy.
67+
*/
6068
constructor(
6169
getStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>,
6270
getWebsocketToken: TokenFetcher<OdspResourceTokenFetchOptions> | undefined,
@@ -71,6 +79,12 @@ export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFa
7179
* Creates a document service that reads its snapshot from the closest file version at or before
7280
* the target and its deltas from the live document, materializing a requested sequence number
7381
* through replay.
82+
*
83+
* @param resolvedUrl - The resolved ODSP document URL.
84+
* @param targetSequenceNumber - The sequence number at which to materialize the document.
85+
* @param logger - Optional telemetry logger.
86+
* @param clientIsSummarizer - Whether the requesting client is a summarizer.
87+
* @returns A read-only document service materialized at the requested sequence number.
7488
*/
7589
public async createPointInTimeDocumentService(
7690
resolvedUrl: IResolvedUrl,

packages/loader/container-loader/api-report/container-loader.legacy.alpha.api.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ export interface IFluidModuleWithDetails {
9898
module: IFluidModule;
9999
}
100100

101+
// @alpha @legacy
102+
export interface ILoadContainerToSequenceNumberProps extends IContainerHostProps, IContainerDriverServices {
103+
readonly loadToSequenceNumber: number;
104+
readonly request: IRequest;
105+
readonly signal?: AbortSignal | undefined;
106+
}
107+
101108
// @beta @legacy
102109
export interface ILoaderProps {
103110
readonly codeLoader: ICodeDetailsLoader;
@@ -181,6 +188,9 @@ export interface IScribeProtocolState {
181188
values: [string, ICommittedProposal][];
182189
}
183190

191+
// @alpha @legacy
192+
export function loadContainerToSequenceNumber(props: ILoadContainerToSequenceNumberProps): Promise<IContainer>;
193+
184194
// @beta @legacy
185195
export class Loader implements IHostLoader {
186196
constructor(loaderProps: ILoaderProps);

packages/loader/container-loader/src/loadContainerToSequenceNumber.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
* point-in-time capability the loader detects. For ODSP, pass an
2828
* `OdspPointInTimeDocumentServiceFactory` directly.
2929
*
30-
* @internal
30+
* @legacy @alpha
3131
*/
3232
export interface ILoadContainerToSequenceNumberProps
3333
extends IContainerHostProps,
@@ -62,7 +62,11 @@ export interface ILoadContainerToSequenceNumberProps
6262
* `@fluidframework/odsp-driver`) directly - the loader materializes the point-in-time view itself,
6363
* so no wrapping or decoration is required.
6464
*
65-
* @internal
65+
* @param props - The load options, point-in-time-capable driver services, target sequence number, and
66+
* optional cancellation signal.
67+
* @returns A disconnected, read-only container materialized at the requested sequence number.
68+
*
69+
* @legacy @alpha
6670
*/
6771
export async function loadContainerToSequenceNumber(
6872
props: ILoadContainerToSequenceNumberProps,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3+
"extends": "<projectFolder>/../../../common/build/build-common/api-extractor-lint.entrypoint.json",
4+
"mainEntryPointFilePath": "<projectFolder>/dist/legacyAlpha.d.ts"
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3+
"extends": "<projectFolder>/../../../common/build/build-common/api-extractor-lint.entrypoint.json",
4+
"mainEntryPointFilePath": "<projectFolder>/lib/legacyAlpha.d.ts"
5+
}

0 commit comments

Comments
 (0)