Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client Changes in Fluid Server Cluster Discovery Feature #9706

Merged
merged 39 commits into from
Apr 20, 2022
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
2fd9a5e
FRS-Echo-Openapis-POC
tianzhu007 Jul 29, 2021
b801558
Update openapi.json
tianzhu007 Jul 30, 2021
aa136b6
Update openapi.json
tianzhu007 Jul 30, 2021
41e35af
Upload openapi.yaml
tianzhu007 Aug 3, 2021
48b352f
Update openapi.json
tianzhu007 Aug 4, 2021
ef18375
Update openapi.json
tianzhu007 Aug 4, 2021
f5302a9
Update openapi.json
tianzhu007 Aug 4, 2021
007588a
Update openapi.json
tianzhu007 Aug 5, 2021
46e2b32
Remove openapi
tianzhu007 Nov 17, 2021
b4ae673
Merge branch 'microsoft:main' into main
tianzhu007 Dec 30, 2021
32559e6
Merge branch 'microsoft:main' into main
tianzhu007 Feb 5, 2022
14176fb
Merge branch 'microsoft:main' into main
tianzhu007 Feb 7, 2022
dcdec98
Merge branch 'microsoft:main' into main
tianzhu007 Mar 3, 2022
a03e2fa
Merge branch 'microsoft:main' into main
tianzhu007 Mar 4, 2022
16bc082
Merge branch 'microsoft:main' into main
tianzhu007 Mar 7, 2022
f9d82cb
Merge branch 'microsoft:main' into main
tianzhu007 Mar 10, 2022
cc3ffeb
Merge branch 'microsoft:main' into main
tianzhu007 Mar 30, 2022
896e174
Add the driver side change
tianzhu007 Apr 1, 2022
2560598
Merge branch 'microsoft:main' into Enable-Routing-Work-Driver
tianzhu007 Apr 1, 2022
a317f87
Add the typeValidation for driver
tianzhu007 Apr 1, 2022
3c47e1c
Merge branch 'Enable-Routing-Work-Driver' of https://github.com/tianz…
tianzhu007 Apr 1, 2022
6a0c4c0
Make enableDiscovery and noCacheManger as optional
tianzhu007 Apr 1, 2022
42aebca
Merge branch 'microsoft:main' into main
tianzhu007 Apr 5, 2022
972c260
Merge branch 'main' into Enable-Routing-Work-Driver
tianzhu007 Apr 5, 2022
9b3be88
Add the undefined check for session
tianzhu007 Apr 8, 2022
16b7f46
Add isCreateContainer flag
tianzhu007 Apr 8, 2022
626fa4e
Add the "!"
tianzhu007 Apr 8, 2022
b6f00b9
Refactor the urlUtils.ts
tianzhu007 Apr 11, 2022
0a60baf
Refactor the url methods
tianzhu007 Apr 12, 2022
ab5213f
Merge branch 'main' into Enable-Routing-Work-Driver
tianzhu007 Apr 12, 2022
824c001
Merge branch 'microsoft:main' into Enable-Routing-Work-Driver
tianzhu007 Apr 12, 2022
12467e2
Resolve url comments
tianzhu007 Apr 12, 2022
57cbf4d
Merge branch 'microsoft:main' into Enable-Routing-Work-Driver
tianzhu007 Apr 13, 2022
da55167
Change the urls, and add comments
tianzhu007 Apr 14, 2022
33d2bb1
Add the "="
tianzhu007 Apr 14, 2022
04a9eb2
Merge branch 'main' into Enable-Routing-Work-Driver
tianzhu007 Apr 18, 2022
8fbdb8d
Merge branch 'microsoft:main' into Enable-Routing-Work-Driver
tianzhu007 Apr 19, 2022
f4f696b
Merge ISession interfaces for client and server
tianzhu007 Apr 20, 2022
fbaf7bc
Remove in document metadata
tianzhu007 Apr 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions api-report/routerlicious-driver.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export class DocumentService implements api.IDocumentService {

// @public (undocumented)
export class DocumentStorageService extends DocumentStorageServiceProxy {
constructor(id: string, manager: GitManager, logger: ITelemetryLogger, policies?: IDocumentStorageServicePolicies, driverPolicies?: IRouterliciousDriverPolicies, blobCache?: ICache<ArrayBufferLike>, snapshotTreeCache?: ICache<ISnapshotTreeVersion>);
constructor(id: string, manager: GitManager, logger: ITelemetryLogger, policies?: IDocumentStorageServicePolicies, driverPolicies?: IRouterliciousDriverPolicies, blobCache?: ICache<ArrayBufferLike>, snapshotTreeCache?: ICache<ISnapshotTreeVersion>, noCacheGitManager?: GitManager | undefined);
// (undocumented)
getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null>;
// (undocumented)
Expand All @@ -85,11 +85,14 @@ export class DocumentStorageService extends DocumentStorageServiceProxy {
get logTailSha(): string | undefined;
// (undocumented)
manager: GitManager;
// (undocumented)
noCacheGitManager?: GitManager | undefined;
}

// @public (undocumented)
export interface IRouterliciousDriverPolicies {
aggregateBlobsSmallerThanBytes: number | undefined;
enableDiscovery?: boolean;
enablePrefetch: boolean;
enableRestLess: boolean;
enableWholeSummaryUpload: boolean;
Expand Down Expand Up @@ -143,7 +146,7 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
constructor(tokenProvider: ITokenProvider, driverPolicies?: Partial<IRouterliciousDriverPolicies>);
// (undocumented)
createContainer(createNewSummary: ISummaryTree | undefined, resolvedUrl: IResolvedUrl, logger?: ITelemetryBaseLogger, clientIsSummarizer?: boolean): Promise<IDocumentService>;
createDocumentService(resolvedUrl: IResolvedUrl, logger?: ITelemetryBaseLogger, clientIsSummarizer?: boolean): Promise<IDocumentService>;
createDocumentService(resolvedUrl: IResolvedUrl, logger?: ITelemetryBaseLogger, clientIsSummarizer?: boolean, isCreateContainer?: boolean): Promise<IDocumentService>;
// (undocumented)
readonly protocolName = "fluid:";
}
Expand Down
8 changes: 6 additions & 2 deletions packages/drivers/local-driver/src/localDocumentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class LocalDocumentService implements api.IDocumentService {
private readonly innerDocumentService?: api.IDocumentService,
) { }

public dispose() {}
public dispose() { }

/**
* Creates and returns a document storage service for local use.
Expand All @@ -43,7 +43,11 @@ export class LocalDocumentService implements api.IDocumentService {
this.documentId,
new GitManager(new TestHistorian(this.localDeltaConnectionServer.testDbFactory.testDatabase)),
new TelemetryNullLogger(),
{ minBlobSize: 2048 }); // Test blob aggregation.
{ minBlobSize: 2048 }, // Test blob aggregation.
undefined,
undefined,
undefined,
new GitManager(new TestHistorian(this.localDeltaConnectionServer.testDbFactory.testDatabase)));
}

/**
Expand Down
14 changes: 14 additions & 0 deletions packages/drivers/routerlicious-driver/src/contracts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*!
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
* Licensed under the MIT License.
*/

// Session information that includes the server urls and session status in the document's metadata
export interface ISession {
tianzhu007 marked this conversation as resolved.
Show resolved Hide resolved
// Orderer url of the session
ordererUrl: string;
// Historian url of the session
historianUrl: string;
// Session status
isSessionAlive: boolean;
}
9 changes: 8 additions & 1 deletion packages/drivers/routerlicious-driver/src/documentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ export class DocumentService implements api.IDocumentService {
false,
storageRestWrapper);
const gitManager = new GitManager(historian);
const noCacheHistorian = new Historian(
this.gitUrl,
true,
true,
storageRestWrapper);
const noCacheGitManager = new GitManager(noCacheHistorian);
const documentStorageServicePolicies: api.IDocumentStorageServicePolicies = {
caching: this.driverPolicies.enablePrefetch
? api.LoaderCachingPolicy.Prefetch
Expand All @@ -88,7 +94,8 @@ export class DocumentService implements api.IDocumentService {
documentStorageServicePolicies,
this.driverPolicies,
this.blobCache,
this.snapshotTreeCache);
this.snapshotTreeCache,
noCacheGitManager);
return this.documentStorageService;
}

Expand Down
69 changes: 50 additions & 19 deletions packages/drivers/routerlicious-driver/src/documentServiceFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@ import { IRouterliciousDriverPolicies } from "./policies";
import { ITokenProvider } from "./tokens";
import { RouterliciousOrdererRestWrapper } from "./restWrapper";
import { convertSummaryToCreateNewSummary } from "./createNewUtils";
import { parseFluidUrl, replaceDocumentIdInPath } from "./urlUtils";
import { parseFluidUrl, replaceDocumentIdInPath, getDiscoveredFluidResolvedUrl } from "./urlUtils";
import { InMemoryCache } from "./cache";
import { pkgVersion as driverVersion } from "./packageVersion";
import { ISnapshotTreeVersion } from "./definitions";
import { ISession } from "./contracts";

const defaultRouterliciousDriverPolicies: IRouterliciousDriverPolicies = {
enablePrefetch: true,
maxConcurrentStorageRequests: 100,
maxConcurrentOrdererRequests: 100,
aggregateBlobsSmallerThanBytes: undefined,
enableDiscovery: false,
enableWholeSummaryUpload: false,
enableRestLess: true,
};
Expand Down Expand Up @@ -66,7 +68,7 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
ensureFluidResolvedUrl(resolvedUrl);
assert(!!createNewSummary, 0x204 /* "create empty file not supported" */);
assert(!!resolvedUrl.endpoints.ordererUrl, 0x0b2 /* "Missing orderer URL!" */);
const parsedUrl = parseFluidUrl(resolvedUrl.url);
let parsedUrl = parseFluidUrl(resolvedUrl.url);
if (!parsedUrl.pathname) {
throw new Error("Parsed url should contain tenant and doc Id!!");
}
Expand All @@ -92,15 +94,14 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
resolvedUrl.endpoints.ordererUrl,
);

// the backend responds with the actual document ID associated with the new container.

// @TODO: Remove returned "string" type when removing back-compat code
const res = await ordererRestWrapper.post<{ id: string, token?: string } | string>(
const res = await ordererRestWrapper.post<{ id: string, token?: string, session?: ISession } | string>(
`/documents/${tenantId}`,
{
summary: convertSummaryToCreateNewSummary(appSummary),
sequenceNumber: documentAttributes.sequenceNumber,
values: quorumValues,
enableDiscovery: this.driverPolicies.enableDiscovery,
generateToken: this.tokenProvider.documentPostCreateCallback !== undefined,
},
);
Expand All @@ -111,13 +112,21 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact

let documentId: string;
let token: string | undefined;

let session: ISession | undefined;
let fluidResolvedUrl: IResolvedUrl;
if (typeof res === "string") {
documentId = res;
} else {
documentId = res.id;
token = res.token;
session = res.session;
}
if (session && this.driverPolicies.enableDiscovery) {
fluidResolvedUrl = getDiscoveredFluidResolvedUrl(resolvedUrl, session);
} else {
fluidResolvedUrl = resolvedUrl;
}
parsedUrl = parseFluidUrl(fluidResolvedUrl.url);

// @TODO: Remove token from the condition, checking the documentPostCreateCallback !== undefined
// is sufficient to determine if the token will be undefined or not.
Expand All @@ -126,7 +135,7 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
}

parsedUrl.set("pathname", replaceDocumentIdInPath(parsedUrl.pathname, documentId));
const deltaStorageUrl = resolvedUrl.endpoints.deltaStorageUrl;
const deltaStorageUrl = fluidResolvedUrl.endpoints.deltaStorageUrl;
if (!deltaStorageUrl) {
throw new Error(
`All endpoints urls must be provided. [deltaStorageUrl:${deltaStorageUrl}]`);
Expand All @@ -136,16 +145,17 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact

return this.createDocumentService(
{
...resolvedUrl,
...fluidResolvedUrl,
url: parsedUrl.toString(),
id: documentId,
endpoints: {
...resolvedUrl.endpoints,
...fluidResolvedUrl.endpoints,
deltaStorageUrl: parsedDeltaStorageUrl.toString(),
},
},
logger,
clientIsSummarizer,
true,
);
}

Expand All @@ -159,10 +169,40 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
resolvedUrl: IResolvedUrl,
logger?: ITelemetryBaseLogger,
clientIsSummarizer?: boolean,
isCreateContainer?: boolean,
): Promise<IDocumentService> {
ensureFluidResolvedUrl(resolvedUrl);

const fluidResolvedUrl = resolvedUrl;
const parsedUrl = parseFluidUrl(resolvedUrl.url);
const [, tenantId, documentId] = parsedUrl.pathname.split("/");
if (!documentId || !tenantId) {
throw new Error(
`Couldn't parse documentId and/or tenantId. [documentId:${documentId}][tenantId:${tenantId}]`);
}
const logger2 = ChildLogger.create(logger, "RouterliciousDriver", { all: { driverVersion }});

let fluidResolvedUrl: IResolvedUrl;
if (!isCreateContainer && this.driverPolicies.enableDiscovery) {
const rateLimiter = new RateLimiter(this.driverPolicies.maxConcurrentOrdererRequests);
const ordererRestWrapper = await RouterliciousOrdererRestWrapper.load(
tenantId,
documentId,
this.tokenProvider,
logger2,
rateLimiter,
this.driverPolicies.enableRestLess,
resolvedUrl.endpoints.ordererUrl,
);

// the backend responds with the actual document session associated with the container.
const session: ISession = await ordererRestWrapper.get<ISession>(
`/documents/${tenantId}/session/${documentId}`,
);
fluidResolvedUrl = getDiscoveredFluidResolvedUrl(resolvedUrl, session);
} else {
fluidResolvedUrl = resolvedUrl;
}

const storageUrl = fluidResolvedUrl.endpoints.storageUrl;
const ordererUrl = fluidResolvedUrl.endpoints.ordererUrl;
const deltaStorageUrl = fluidResolvedUrl.endpoints.deltaStorageUrl;
Expand All @@ -171,15 +211,6 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
`All endpoints urls must be provided. [ordererUrl:${ordererUrl}][deltaStorageUrl:${deltaStorageUrl}]`);
}

const parsedUrl = parseFluidUrl(fluidResolvedUrl.url);
const [, tenantId, documentId] = parsedUrl.pathname.split("/");
if (!documentId || !tenantId) {
throw new Error(
`Couldn't parse documentId and/or tenantId. [documentId:${documentId}][tenantId:${tenantId}]`);
}

const logger2 = ChildLogger.create(logger, "RouterliciousDriver", { all: { driverVersion }});

return new DocumentService(
fluidResolvedUrl,
ordererUrl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,18 @@ export class DocumentStorageService extends DocumentStorageServiceProxy {
policies: IDocumentStorageServicePolicies,
driverPolicies?: IRouterliciousDriverPolicies,
blobCache?: ICache<ArrayBufferLike>,
snapshotTreeCache?: ICache<ISnapshotTreeVersion>): IDocumentStorageService {
snapshotTreeCache?: ICache<ISnapshotTreeVersion>,
noCacheGitManager?: GitManager): IDocumentStorageService {
const storageService = driverPolicies?.enableWholeSummaryUpload ?
new WholeSummaryDocumentStorageService(
id,
manager,
logger,
policies,
driverPolicies,
blobCache,
snapshotTreeCache,
noCacheGitManager,
) :
new ShreddedSummaryDocumentStorageService(
id,
Expand All @@ -70,7 +73,8 @@ export class DocumentStorageService extends DocumentStorageServiceProxy {
policies: IDocumentStorageServicePolicies = {},
driverPolicies?: IRouterliciousDriverPolicies,
blobCache?: ICache<ArrayBufferLike>,
snapshotTreeCache?: ICache<ISnapshotTreeVersion>) {
snapshotTreeCache?: ICache<ISnapshotTreeVersion>,
public noCacheGitManager?: GitManager) {
super(DocumentStorageService.loadInternalDocumentStorageService(
id,
manager,
Expand All @@ -79,6 +83,7 @@ export class DocumentStorageService extends DocumentStorageServiceProxy {
driverPolicies,
blobCache,
snapshotTreeCache,
noCacheGitManager,
));
}

Expand Down
5 changes: 5 additions & 0 deletions packages/drivers/routerlicious-driver/src/policies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ export interface IRouterliciousDriverPolicies {
* Default: false
*/
enableWholeSummaryUpload: boolean;
/**
* Enable service endpoint discovery when creating or joining a session.
* Default: false
*/
enableDiscovery?: boolean;
/**
* Enable using RestLess which avoids CORS preflight requests.
* Default: true
Expand Down
31 changes: 31 additions & 0 deletions packages/drivers/routerlicious-driver/src/urlUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
* Licensed under the MIT License.
*/

import { IFluidResolvedUrl } from "@fluidframework/driver-definitions";
import URLParse from "url-parse";
import { ISession } from "./contracts";

export const parseFluidUrl = (fluidUrl: string): URLParse => {
return new URLParse(fluidUrl, true);
Expand All @@ -17,3 +19,32 @@ export const parseFluidUrl = (fluidUrl: string): URLParse => {
*/
export const replaceDocumentIdInPath = (urlPath: string, documentId: string): string =>
urlPath.split("/").slice(0, -1).concat([documentId]).join("/");

export const getDiscoveredFluidResolvedUrl = (resolvedUrl: IFluidResolvedUrl, session: ISession): IFluidResolvedUrl => {
if (session) {
const discoveredOrdererUrl = new URLParse(session.ordererUrl);
const deltaStorageUrl = new URLParse(resolvedUrl.endpoints.deltaStorageUrl);
deltaStorageUrl.set("host", discoveredOrdererUrl.host);

const discoveredStorageUrl = new URLParse(session.historianUrl);
const storageUrl = new URLParse(resolvedUrl.endpoints.storageUrl);
storageUrl.set("host", discoveredStorageUrl.host);

const parsedUrl = parseFluidUrl(resolvedUrl.url);
const discoveredResolvedUrl: IFluidResolvedUrl = {
endpoints: {
deltaStorageUrl: deltaStorageUrl.toString(),
ordererUrl: session.ordererUrl,
storageUrl: storageUrl.toString(),
},
id: resolvedUrl.id,
tokens: resolvedUrl.tokens,
type: resolvedUrl.type,
url: new URLParse(`fluid://${discoveredOrdererUrl.host}${parsedUrl.pathname}`).toString(),
};

return discoveredResolvedUrl;
} else {
return resolvedUrl;
}
};
Loading