@fluidframework/routerlicious-driver 2.0.0-dev.2.3.0.115467 → 2.0.0-dev.4.1.0.148229
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.
- package/.eslintrc.js +10 -12
- package/.mocharc.js +2 -2
- package/README.md +1 -1
- package/api-extractor.json +2 -2
- package/dist/cache.d.ts +3 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +6 -4
- package/dist/cache.js.map +1 -1
- package/dist/createNewUtils.d.ts.map +1 -1
- package/dist/createNewUtils.js +4 -2
- package/dist/createNewUtils.js.map +1 -1
- package/dist/defaultTokenProvider.d.ts.map +1 -1
- package/dist/defaultTokenProvider.js.map +1 -1
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js.map +1 -1
- package/dist/deltaStorageService.d.ts.map +1 -1
- package/dist/deltaStorageService.js +4 -1
- package/dist/deltaStorageService.js.map +1 -1
- package/dist/documentDeltaConnection.d.ts.map +1 -1
- package/dist/documentDeltaConnection.js.map +1 -1
- package/dist/documentService.d.ts +4 -2
- package/dist/documentService.d.ts.map +1 -1
- package/dist/documentService.js +28 -41
- package/dist/documentService.js.map +1 -1
- package/dist/documentServiceFactory.d.ts +0 -1
- package/dist/documentServiceFactory.d.ts.map +1 -1
- package/dist/documentServiceFactory.js +26 -13
- package/dist/documentServiceFactory.js.map +1 -1
- package/dist/documentStorageService.d.ts +1 -1
- package/dist/documentStorageService.d.ts.map +1 -1
- package/dist/documentStorageService.js +8 -6
- package/dist/documentStorageService.js.map +1 -1
- package/dist/errorUtils.d.ts +11 -3
- package/dist/errorUtils.d.ts.map +1 -1
- package/dist/errorUtils.js +19 -6
- package/dist/errorUtils.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/mapWithExpiration.d.ts +34 -0
- package/dist/mapWithExpiration.d.ts.map +1 -0
- package/dist/mapWithExpiration.js +105 -0
- package/dist/mapWithExpiration.js.map +1 -0
- package/dist/nullBlobStorageService.d.ts.map +1 -1
- package/dist/nullBlobStorageService.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/policies.d.ts.map +1 -1
- package/dist/policies.js.map +1 -1
- package/dist/restWrapper.d.ts +8 -5
- package/dist/restWrapper.d.ts.map +1 -1
- package/dist/restWrapper.js +38 -44
- package/dist/restWrapper.js.map +1 -1
- package/dist/retriableGitManager.d.ts.map +1 -1
- package/dist/retriableGitManager.js.map +1 -1
- package/dist/shreddedSummaryDocumentStorageService.d.ts +1 -1
- package/dist/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
- package/dist/shreddedSummaryDocumentStorageService.js +9 -5
- package/dist/shreddedSummaryDocumentStorageService.js.map +1 -1
- package/dist/tokens.d.ts +24 -7
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js.map +1 -1
- package/dist/treeUtils.d.ts +51 -0
- package/dist/treeUtils.d.ts.map +1 -0
- package/dist/treeUtils.js +85 -0
- package/dist/treeUtils.js.map +1 -0
- package/dist/urlUtils.d.ts.map +1 -1
- package/dist/urlUtils.js.map +1 -1
- package/dist/wholeSummaryDocumentStorageService.d.ts +1 -1
- package/dist/wholeSummaryDocumentStorageService.d.ts.map +1 -1
- package/dist/wholeSummaryDocumentStorageService.js +30 -17
- package/dist/wholeSummaryDocumentStorageService.js.map +1 -1
- package/lib/cache.d.ts +3 -0
- package/lib/cache.d.ts.map +1 -1
- package/lib/cache.js +6 -4
- package/lib/cache.js.map +1 -1
- package/lib/createNewUtils.d.ts.map +1 -1
- package/lib/createNewUtils.js +4 -2
- package/lib/createNewUtils.js.map +1 -1
- package/lib/defaultTokenProvider.d.ts.map +1 -1
- package/lib/defaultTokenProvider.js.map +1 -1
- package/lib/definitions.d.ts.map +1 -1
- package/lib/definitions.js.map +1 -1
- package/lib/deltaStorageService.d.ts.map +1 -1
- package/lib/deltaStorageService.js +4 -1
- package/lib/deltaStorageService.js.map +1 -1
- package/lib/documentDeltaConnection.d.ts.map +1 -1
- package/lib/documentDeltaConnection.js.map +1 -1
- package/lib/documentService.d.ts +4 -2
- package/lib/documentService.d.ts.map +1 -1
- package/lib/documentService.js +30 -24
- package/lib/documentService.js.map +1 -1
- package/lib/documentServiceFactory.d.ts +0 -1
- package/lib/documentServiceFactory.d.ts.map +1 -1
- package/lib/documentServiceFactory.js +27 -14
- package/lib/documentServiceFactory.js.map +1 -1
- package/lib/documentStorageService.d.ts +1 -1
- package/lib/documentStorageService.d.ts.map +1 -1
- package/lib/documentStorageService.js +9 -7
- package/lib/documentStorageService.js.map +1 -1
- package/lib/errorUtils.d.ts +11 -3
- package/lib/errorUtils.d.ts.map +1 -1
- package/lib/errorUtils.js +18 -5
- package/lib/errorUtils.js.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -1
- package/lib/index.js.map +1 -1
- package/lib/mapWithExpiration.d.ts +34 -0
- package/lib/mapWithExpiration.d.ts.map +1 -0
- package/lib/mapWithExpiration.js +101 -0
- package/lib/mapWithExpiration.js.map +1 -0
- package/lib/nullBlobStorageService.d.ts.map +1 -1
- package/lib/nullBlobStorageService.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/policies.d.ts.map +1 -1
- package/lib/policies.js.map +1 -1
- package/lib/restWrapper.d.ts +8 -5
- package/lib/restWrapper.d.ts.map +1 -1
- package/lib/restWrapper.js +38 -44
- package/lib/restWrapper.js.map +1 -1
- package/lib/retriableGitManager.d.ts.map +1 -1
- package/lib/retriableGitManager.js.map +1 -1
- package/lib/shreddedSummaryDocumentStorageService.d.ts +1 -1
- package/lib/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
- package/lib/shreddedSummaryDocumentStorageService.js +10 -6
- package/lib/shreddedSummaryDocumentStorageService.js.map +1 -1
- package/lib/tokens.d.ts +24 -7
- package/lib/tokens.d.ts.map +1 -1
- package/lib/tokens.js.map +1 -1
- package/lib/treeUtils.d.ts +51 -0
- package/lib/treeUtils.d.ts.map +1 -0
- package/lib/treeUtils.js +80 -0
- package/lib/treeUtils.js.map +1 -0
- package/lib/urlUtils.d.ts.map +1 -1
- package/lib/urlUtils.js.map +1 -1
- package/lib/wholeSummaryDocumentStorageService.d.ts +1 -1
- package/lib/wholeSummaryDocumentStorageService.d.ts.map +1 -1
- package/lib/wholeSummaryDocumentStorageService.js +30 -17
- package/lib/wholeSummaryDocumentStorageService.js.map +1 -1
- package/package.json +55 -52
- package/prettier.config.cjs +1 -1
- package/src/cache.ts +21 -14
- package/src/createNewUtils.ts +24 -22
- package/src/defaultTokenProvider.ts +13 -15
- package/src/definitions.ts +2 -2
- package/src/deltaStorageService.ts +99 -95
- package/src/documentDeltaConnection.ts +53 -47
- package/src/documentService.ts +260 -241
- package/src/documentServiceFactory.ts +268 -237
- package/src/documentStorageService.ts +87 -83
- package/src/errorUtils.ts +91 -76
- package/src/index.ts +7 -1
- package/src/mapWithExpiration.ts +124 -0
- package/src/nullBlobStorageService.ts +24 -21
- package/src/packageVersion.ts +1 -1
- package/src/policies.ts +44 -44
- package/src/restWrapper.ts +270 -208
- package/src/retriableGitManager.ts +152 -151
- package/src/shreddedSummaryDocumentStorageService.ts +202 -194
- package/src/tokens.ts +69 -44
- package/src/treeUtils.ts +107 -0
- package/src/urlUtils.ts +26 -23
- package/src/wholeSummaryDocumentStorageService.ts +248 -228
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +9 -13
|
@@ -5,18 +5,22 @@
|
|
|
5
5
|
|
|
6
6
|
import { assert } from "@fluidframework/common-utils";
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
FiveDaysMs,
|
|
9
|
+
IDocumentService,
|
|
10
|
+
IDocumentServiceFactory,
|
|
11
|
+
IDocumentStorageServicePolicies,
|
|
12
|
+
IFluidResolvedUrl,
|
|
13
|
+
IResolvedUrl,
|
|
14
|
+
LoaderCachingPolicy,
|
|
12
15
|
} from "@fluidframework/driver-definitions";
|
|
13
16
|
import { ITelemetryBaseLogger } from "@fluidframework/common-definitions";
|
|
14
17
|
import { ISummaryTree } from "@fluidframework/protocol-definitions";
|
|
15
18
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
ensureFluidResolvedUrl,
|
|
20
|
+
getDocAttributesFromProtocolSummary,
|
|
21
|
+
getQuorumValuesFromProtocolSummary,
|
|
22
|
+
isCombinedAppAndProtocolSummary,
|
|
23
|
+
RateLimiter,
|
|
20
24
|
} from "@fluidframework/driver-utils";
|
|
21
25
|
import { ChildLogger, PerformanceEvent } from "@fluidframework/telemetry-utils";
|
|
22
26
|
import { ISession } from "@fluidframework/server-services-client";
|
|
@@ -30,15 +34,17 @@ import { ICache, InMemoryCache, NullCache } from "./cache";
|
|
|
30
34
|
import { pkgVersion as driverVersion } from "./packageVersion";
|
|
31
35
|
import { ISnapshotTreeVersion } from "./definitions";
|
|
32
36
|
|
|
37
|
+
const maximumSnapshotCacheDurationMs: FiveDaysMs = 432_000_000; // 5 days in ms
|
|
38
|
+
|
|
33
39
|
const defaultRouterliciousDriverPolicies: IRouterliciousDriverPolicies = {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
enablePrefetch: true,
|
|
41
|
+
maxConcurrentStorageRequests: 100,
|
|
42
|
+
maxConcurrentOrdererRequests: 100,
|
|
43
|
+
aggregateBlobsSmallerThanBytes: undefined,
|
|
44
|
+
enableDiscovery: false,
|
|
45
|
+
enableWholeSummaryUpload: false,
|
|
46
|
+
enableRestLess: true,
|
|
47
|
+
enableInternalSummaryCaching: true,
|
|
42
48
|
};
|
|
43
49
|
|
|
44
50
|
/**
|
|
@@ -46,234 +52,257 @@ const defaultRouterliciousDriverPolicies: IRouterliciousDriverPolicies = {
|
|
|
46
52
|
* use the routerlicious implementation.
|
|
47
53
|
*/
|
|
48
54
|
export class RouterliciousDocumentServiceFactory implements IDocumentServiceFactory {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
55
|
+
private readonly driverPolicies: IRouterliciousDriverPolicies;
|
|
56
|
+
private readonly blobCache: ICache<ArrayBufferLike>;
|
|
57
|
+
private readonly snapshotTreeCache: ICache<ISnapshotTreeVersion>;
|
|
58
|
+
|
|
59
|
+
constructor(
|
|
60
|
+
private readonly tokenProvider: ITokenProvider,
|
|
61
|
+
driverPolicies: Partial<IRouterliciousDriverPolicies> = {},
|
|
62
|
+
) {
|
|
63
|
+
// Use the maximum allowed by the policy (IDocumentStorageServicePolicies.maximumCacheDurationMs set below)
|
|
64
|
+
const snapshotCacheExpiryMs: FiveDaysMs = maximumSnapshotCacheDurationMs;
|
|
65
|
+
|
|
66
|
+
this.driverPolicies = {
|
|
67
|
+
...defaultRouterliciousDriverPolicies,
|
|
68
|
+
...driverPolicies,
|
|
69
|
+
};
|
|
70
|
+
this.blobCache = new InMemoryCache<ArrayBufferLike>();
|
|
71
|
+
this.snapshotTreeCache = this.driverPolicies.enableInternalSummaryCaching
|
|
72
|
+
? new InMemoryCache<ISnapshotTreeVersion>(snapshotCacheExpiryMs)
|
|
73
|
+
: new NullCache<ISnapshotTreeVersion>();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* {@inheritDoc @fluidframework/driver-definitions#IDocumentServiceFactory.createContainer}
|
|
78
|
+
*
|
|
79
|
+
* @throws {@link DocumentPostCreateError}
|
|
80
|
+
* If an exception is thrown while invoking the provided {@link ITokenProvider.documentPostCreateCallback}.
|
|
81
|
+
*/
|
|
82
|
+
public async createContainer(
|
|
83
|
+
createNewSummary: ISummaryTree | undefined,
|
|
84
|
+
resolvedUrl: IResolvedUrl,
|
|
85
|
+
logger?: ITelemetryBaseLogger,
|
|
86
|
+
clientIsSummarizer?: boolean,
|
|
87
|
+
): Promise<IDocumentService> {
|
|
88
|
+
ensureFluidResolvedUrl(resolvedUrl);
|
|
89
|
+
if (createNewSummary === undefined) {
|
|
90
|
+
throw new Error("Empty file summary creation isn't supported in this driver.");
|
|
91
|
+
}
|
|
92
|
+
assert(!!resolvedUrl.endpoints.ordererUrl, 0x0b2 /* "Missing orderer URL!" */);
|
|
93
|
+
let parsedUrl = parseFluidUrl(resolvedUrl.url);
|
|
94
|
+
if (!parsedUrl.pathname) {
|
|
95
|
+
throw new Error("Parsed url should contain tenant and doc Id!!");
|
|
96
|
+
}
|
|
97
|
+
const [, tenantId] = parsedUrl.pathname.split("/");
|
|
53
98
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
...defaultRouterliciousDriverPolicies,
|
|
60
|
-
...driverPolicies,
|
|
61
|
-
};
|
|
62
|
-
this.blobCache = new InMemoryCache<ArrayBufferLike>();
|
|
63
|
-
this.snapshotTreeCache = this.driverPolicies.enableInternalSummaryCaching
|
|
64
|
-
? new InMemoryCache<ISnapshotTreeVersion>()
|
|
65
|
-
: new NullCache<ISnapshotTreeVersion>();
|
|
66
|
-
}
|
|
99
|
+
if (!isCombinedAppAndProtocolSummary(createNewSummary)) {
|
|
100
|
+
throw new Error("Protocol and App Summary required in the full summary");
|
|
101
|
+
}
|
|
102
|
+
const protocolSummary = createNewSummary.tree[".protocol"];
|
|
103
|
+
const appSummary = createNewSummary.tree[".app"];
|
|
67
104
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
*
|
|
71
|
-
* @throws {@link DocumentPostCreateError}
|
|
72
|
-
* If an exception is thrown while invoking the provided {@link ITokenProvider.documentPostCreateCallback}.
|
|
73
|
-
*/
|
|
74
|
-
public async createContainer(
|
|
75
|
-
createNewSummary: ISummaryTree | undefined,
|
|
76
|
-
resolvedUrl: IResolvedUrl,
|
|
77
|
-
logger?: ITelemetryBaseLogger,
|
|
78
|
-
clientIsSummarizer?: boolean,
|
|
79
|
-
): Promise<IDocumentService> {
|
|
80
|
-
ensureFluidResolvedUrl(resolvedUrl);
|
|
81
|
-
if (createNewSummary === undefined) {
|
|
82
|
-
throw new Error("Empty file summary creation isn't supported in this driver.");
|
|
83
|
-
}
|
|
84
|
-
assert(!!resolvedUrl.endpoints.ordererUrl, 0x0b2 /* "Missing orderer URL!" */);
|
|
85
|
-
let parsedUrl = parseFluidUrl(resolvedUrl.url);
|
|
86
|
-
if (!parsedUrl.pathname) {
|
|
87
|
-
throw new Error("Parsed url should contain tenant and doc Id!!");
|
|
88
|
-
}
|
|
89
|
-
const [, tenantId] = parsedUrl.pathname.split("/");
|
|
105
|
+
const documentAttributes = getDocAttributesFromProtocolSummary(protocolSummary);
|
|
106
|
+
const quorumValues = getQuorumValuesFromProtocolSummary(protocolSummary);
|
|
90
107
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
108
|
+
const logger2 = ChildLogger.create(logger, "RouterliciousDriver");
|
|
109
|
+
const rateLimiter = new RateLimiter(this.driverPolicies.maxConcurrentOrdererRequests);
|
|
110
|
+
const ordererRestWrapper = await RouterliciousOrdererRestWrapper.load(
|
|
111
|
+
tenantId,
|
|
112
|
+
undefined,
|
|
113
|
+
this.tokenProvider,
|
|
114
|
+
logger2,
|
|
115
|
+
rateLimiter,
|
|
116
|
+
this.driverPolicies.enableRestLess,
|
|
117
|
+
resolvedUrl.endpoints.ordererUrl,
|
|
118
|
+
);
|
|
98
119
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
120
|
+
const res = await PerformanceEvent.timedExecAsync(
|
|
121
|
+
logger2,
|
|
122
|
+
{
|
|
123
|
+
eventName: "CreateNew",
|
|
124
|
+
details: JSON.stringify({
|
|
125
|
+
enableDiscovery: this.driverPolicies.enableDiscovery,
|
|
126
|
+
sequenceNumber: documentAttributes.sequenceNumber,
|
|
127
|
+
}),
|
|
128
|
+
},
|
|
129
|
+
async (event) => {
|
|
130
|
+
// @TODO: Remove returned "string" type when removing back-compat code
|
|
131
|
+
const postRes = await ordererRestWrapper.post<
|
|
132
|
+
{ id: string; token?: string; session?: ISession } | string
|
|
133
|
+
>(`/documents/${tenantId}`, {
|
|
134
|
+
summary: convertSummaryToCreateNewSummary(appSummary),
|
|
135
|
+
sequenceNumber: documentAttributes.sequenceNumber,
|
|
136
|
+
values: quorumValues,
|
|
137
|
+
enableDiscovery: this.driverPolicies.enableDiscovery,
|
|
138
|
+
generateToken: this.tokenProvider.documentPostCreateCallback !== undefined,
|
|
139
|
+
});
|
|
110
140
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
sequenceNumber: documentAttributes.sequenceNumber,
|
|
118
|
-
}),
|
|
119
|
-
},
|
|
120
|
-
async (event) => {
|
|
121
|
-
// @TODO: Remove returned "string" type when removing back-compat code
|
|
122
|
-
const postRes = await ordererRestWrapper.post<
|
|
123
|
-
{ id: string; token?: string; session?: ISession; } | string
|
|
124
|
-
>(`/documents/${tenantId}`, {
|
|
125
|
-
summary: convertSummaryToCreateNewSummary(appSummary),
|
|
126
|
-
sequenceNumber: documentAttributes.sequenceNumber,
|
|
127
|
-
values: quorumValues,
|
|
128
|
-
enableDiscovery: this.driverPolicies.enableDiscovery,
|
|
129
|
-
generateToken:
|
|
130
|
-
this.tokenProvider.documentPostCreateCallback !==
|
|
131
|
-
undefined,
|
|
132
|
-
});
|
|
141
|
+
event.end({
|
|
142
|
+
docId: typeof postRes === "string" ? postRes : postRes.id,
|
|
143
|
+
});
|
|
144
|
+
return postRes;
|
|
145
|
+
},
|
|
146
|
+
);
|
|
133
147
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return postRes;
|
|
138
|
-
}
|
|
139
|
-
);
|
|
148
|
+
// For supporting backward compatibility, when the request has generateToken === true, it will return
|
|
149
|
+
// an object instead of string
|
|
150
|
+
// @TODO: Remove the logic when no need to support back-compat
|
|
140
151
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
152
|
+
let documentId: string;
|
|
153
|
+
let token: string | undefined;
|
|
154
|
+
let session: ISession | undefined;
|
|
155
|
+
if (typeof res === "string") {
|
|
156
|
+
documentId = res;
|
|
157
|
+
} else {
|
|
158
|
+
documentId = res.id;
|
|
159
|
+
token = res.token;
|
|
160
|
+
session = this.driverPolicies.enableDiscovery ? res.session : undefined;
|
|
161
|
+
}
|
|
162
|
+
parsedUrl = parseFluidUrl(resolvedUrl.url);
|
|
144
163
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
164
|
+
// @TODO: Remove token from the condition, checking the documentPostCreateCallback !== undefined
|
|
165
|
+
// is sufficient to determine if the token will be undefined or not.
|
|
166
|
+
try {
|
|
167
|
+
await PerformanceEvent.timedExecAsync(
|
|
168
|
+
logger2,
|
|
169
|
+
{
|
|
170
|
+
eventName: "DocPostCreateCallback",
|
|
171
|
+
docId: documentId,
|
|
172
|
+
},
|
|
173
|
+
async () => {
|
|
174
|
+
if (token && this.tokenProvider.documentPostCreateCallback !== undefined) {
|
|
175
|
+
return this.tokenProvider.documentPostCreateCallback(documentId, token);
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
);
|
|
179
|
+
} catch (error: any) {
|
|
180
|
+
throw new DocumentPostCreateError(error);
|
|
181
|
+
}
|
|
156
182
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
} catch (error: any) {
|
|
172
|
-
throw new DocumentPostCreateError(error);
|
|
173
|
-
}
|
|
183
|
+
parsedUrl.set("pathname", replaceDocumentIdInPath(parsedUrl.pathname, documentId));
|
|
184
|
+
const deltaStorageUrl = resolvedUrl.endpoints.deltaStorageUrl;
|
|
185
|
+
if (!deltaStorageUrl) {
|
|
186
|
+
throw new Error(
|
|
187
|
+
`All endpoints urls must be provided. [deltaStorageUrl:${deltaStorageUrl}]`,
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
const parsedDeltaStorageUrl = new URL(deltaStorageUrl);
|
|
191
|
+
parsedDeltaStorageUrl.pathname = replaceDocumentIdInPath(
|
|
192
|
+
parsedDeltaStorageUrl.pathname,
|
|
193
|
+
documentId,
|
|
194
|
+
);
|
|
174
195
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
196
|
+
return this.createDocumentService(
|
|
197
|
+
{
|
|
198
|
+
...resolvedUrl,
|
|
199
|
+
url: parsedUrl.toString(),
|
|
200
|
+
id: documentId,
|
|
201
|
+
endpoints: {
|
|
202
|
+
...resolvedUrl.endpoints,
|
|
203
|
+
deltaStorageUrl: parsedDeltaStorageUrl.toString(),
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
logger,
|
|
207
|
+
clientIsSummarizer,
|
|
208
|
+
session,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
183
211
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
212
|
+
/**
|
|
213
|
+
* {@inheritDoc @fluidframework/driver-definitions#IDocumentServiceFactory.createDocumentService}
|
|
214
|
+
*
|
|
215
|
+
* @returns Routerlicious document service.
|
|
216
|
+
*/
|
|
217
|
+
public async createDocumentService(
|
|
218
|
+
resolvedUrl: IResolvedUrl,
|
|
219
|
+
logger?: ITelemetryBaseLogger,
|
|
220
|
+
clientIsSummarizer?: boolean,
|
|
221
|
+
session?: ISession,
|
|
222
|
+
): Promise<IDocumentService> {
|
|
223
|
+
ensureFluidResolvedUrl(resolvedUrl);
|
|
224
|
+
const parsedUrl = parseFluidUrl(resolvedUrl.url);
|
|
225
|
+
const [, tenantId, documentId] = parsedUrl.pathname.split("/");
|
|
226
|
+
if (!documentId || !tenantId) {
|
|
227
|
+
throw new Error(
|
|
228
|
+
`Couldn't parse documentId and/or tenantId. [documentId:${documentId}][tenantId:${tenantId}]`,
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
const logger2 = ChildLogger.create(logger, "RouterliciousDriver", {
|
|
232
|
+
all: { driverVersion },
|
|
233
|
+
});
|
|
199
234
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
session?: ISession,
|
|
210
|
-
): Promise<IDocumentService> {
|
|
211
|
-
ensureFluidResolvedUrl(resolvedUrl);
|
|
235
|
+
const rateLimiter = new RateLimiter(this.driverPolicies.maxConcurrentOrdererRequests);
|
|
236
|
+
const ordererRestWrapper = await RouterliciousOrdererRestWrapper.load(
|
|
237
|
+
tenantId,
|
|
238
|
+
documentId,
|
|
239
|
+
this.tokenProvider,
|
|
240
|
+
logger2,
|
|
241
|
+
rateLimiter,
|
|
242
|
+
this.driverPolicies.enableRestLess,
|
|
243
|
+
);
|
|
212
244
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
`Couldn't parse documentId and/or tenantId. [documentId:${documentId}][tenantId:${tenantId}]`);
|
|
218
|
-
}
|
|
219
|
-
const logger2 = ChildLogger.create(logger, "RouterliciousDriver", { all: { driverVersion } });
|
|
245
|
+
const discoverFluidResolvedUrl = async (): Promise<IFluidResolvedUrl> => {
|
|
246
|
+
if (!this.driverPolicies.enableDiscovery) {
|
|
247
|
+
return resolvedUrl;
|
|
248
|
+
}
|
|
220
249
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
250
|
+
const discoveredSession = await PerformanceEvent.timedExecAsync(
|
|
251
|
+
logger2,
|
|
252
|
+
{
|
|
253
|
+
eventName: "DiscoverSession",
|
|
254
|
+
docId: documentId,
|
|
255
|
+
},
|
|
256
|
+
async () => {
|
|
257
|
+
// The service responds with the current document session associated with the container.
|
|
258
|
+
return ordererRestWrapper.get<ISession>(
|
|
259
|
+
`${resolvedUrl.endpoints.ordererUrl}/documents/${tenantId}/session/${documentId}`,
|
|
260
|
+
);
|
|
261
|
+
},
|
|
262
|
+
);
|
|
263
|
+
return getDiscoveredFluidResolvedUrl(resolvedUrl, discoveredSession);
|
|
264
|
+
};
|
|
265
|
+
const fluidResolvedUrl: IFluidResolvedUrl =
|
|
266
|
+
session !== undefined
|
|
267
|
+
? getDiscoveredFluidResolvedUrl(resolvedUrl, session)
|
|
268
|
+
: await discoverFluidResolvedUrl();
|
|
235
269
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
`/documents/${tenantId}/session/${documentId}`);
|
|
246
|
-
});
|
|
247
|
-
return getDiscoveredFluidResolvedUrl(resolvedUrl, discoveredSession);
|
|
248
|
-
};
|
|
249
|
-
const fluidResolvedUrl: IFluidResolvedUrl = session !== undefined
|
|
250
|
-
? getDiscoveredFluidResolvedUrl(resolvedUrl, session)
|
|
251
|
-
: await discoverFluidResolvedUrl();
|
|
270
|
+
const storageUrl = fluidResolvedUrl.endpoints.storageUrl;
|
|
271
|
+
const ordererUrl = fluidResolvedUrl.endpoints.ordererUrl;
|
|
272
|
+
const deltaStorageUrl = fluidResolvedUrl.endpoints.deltaStorageUrl;
|
|
273
|
+
const deltaStreamUrl = fluidResolvedUrl.endpoints.deltaStreamUrl || ordererUrl; // backward compatibility
|
|
274
|
+
if (!ordererUrl || !deltaStorageUrl) {
|
|
275
|
+
throw new Error(
|
|
276
|
+
`All endpoints urls must be provided. [ordererUrl:${ordererUrl}][deltaStorageUrl:${deltaStorageUrl}]`,
|
|
277
|
+
);
|
|
278
|
+
}
|
|
252
279
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
280
|
+
const documentStorageServicePolicies: IDocumentStorageServicePolicies = {
|
|
281
|
+
caching: this.driverPolicies.enablePrefetch
|
|
282
|
+
? LoaderCachingPolicy.Prefetch
|
|
283
|
+
: LoaderCachingPolicy.NoCaching,
|
|
284
|
+
minBlobSize: this.driverPolicies.aggregateBlobsSmallerThanBytes,
|
|
285
|
+
maximumCacheDurationMs: maximumSnapshotCacheDurationMs,
|
|
286
|
+
};
|
|
261
287
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
288
|
+
return new DocumentService(
|
|
289
|
+
fluidResolvedUrl,
|
|
290
|
+
ordererUrl,
|
|
291
|
+
deltaStorageUrl,
|
|
292
|
+
deltaStreamUrl,
|
|
293
|
+
storageUrl,
|
|
294
|
+
logger2,
|
|
295
|
+
this.tokenProvider,
|
|
296
|
+
tenantId,
|
|
297
|
+
documentId,
|
|
298
|
+
ordererRestWrapper,
|
|
299
|
+
documentStorageServicePolicies,
|
|
300
|
+
this.driverPolicies,
|
|
301
|
+
this.blobCache,
|
|
302
|
+
this.snapshotTreeCache,
|
|
303
|
+
discoverFluidResolvedUrl,
|
|
304
|
+
);
|
|
305
|
+
}
|
|
277
306
|
}
|
|
278
307
|
|
|
279
308
|
/**
|
|
@@ -288,16 +317,18 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
|
|
|
288
317
|
* - What would a retry pattern look like here?
|
|
289
318
|
*/
|
|
290
319
|
export class DocumentPostCreateError extends Error {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
320
|
+
public constructor(
|
|
321
|
+
/**
|
|
322
|
+
* Inner error being wrapped.
|
|
323
|
+
*/
|
|
324
|
+
private readonly innerError: Error,
|
|
325
|
+
) {
|
|
326
|
+
super(innerError.message);
|
|
327
|
+
}
|
|
299
328
|
|
|
300
|
-
|
|
329
|
+
public readonly name = "DocumentPostCreateError";
|
|
301
330
|
|
|
302
|
-
|
|
331
|
+
public get stack() {
|
|
332
|
+
return this.innerError.stack;
|
|
333
|
+
}
|
|
303
334
|
}
|