@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
package/src/urlUtils.ts
CHANGED
|
@@ -8,7 +8,7 @@ import URLParse from "url-parse";
|
|
|
8
8
|
import { ISession } from "@fluidframework/server-services-client";
|
|
9
9
|
|
|
10
10
|
export const parseFluidUrl = (fluidUrl: string): URLParse => {
|
|
11
|
-
|
|
11
|
+
return new URLParse(fluidUrl, true);
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -18,29 +18,32 @@ export const parseFluidUrl = (fluidUrl: string): URLParse => {
|
|
|
18
18
|
* TODO: Ideally we would be able to regenerate the resolvedUrl, rather than patching the current one.
|
|
19
19
|
*/
|
|
20
20
|
export const replaceDocumentIdInPath = (urlPath: string, documentId: string): string =>
|
|
21
|
-
|
|
21
|
+
urlPath.split("/").slice(0, -1).concat([documentId]).join("/");
|
|
22
22
|
|
|
23
|
-
export const getDiscoveredFluidResolvedUrl = (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
export const getDiscoveredFluidResolvedUrl = (
|
|
24
|
+
resolvedUrl: IFluidResolvedUrl,
|
|
25
|
+
session: ISession,
|
|
26
|
+
): IFluidResolvedUrl => {
|
|
27
|
+
const discoveredOrdererUrl = new URLParse(session.ordererUrl);
|
|
28
|
+
const deltaStorageUrl = new URLParse(resolvedUrl.endpoints.deltaStorageUrl);
|
|
29
|
+
deltaStorageUrl.set("host", discoveredOrdererUrl.host);
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
const discoveredStorageUrl = new URLParse(session.historianUrl);
|
|
32
|
+
const storageUrl = new URLParse(resolvedUrl.endpoints.storageUrl);
|
|
33
|
+
storageUrl.set("host", discoveredStorageUrl.host);
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
const parsedUrl = parseFluidUrl(resolvedUrl.url);
|
|
36
|
+
const discoveredResolvedUrl: IFluidResolvedUrl = {
|
|
37
|
+
endpoints: {
|
|
38
|
+
deltaStorageUrl: deltaStorageUrl.toString(),
|
|
39
|
+
ordererUrl: session.ordererUrl,
|
|
40
|
+
deltaStreamUrl: session.deltaStreamUrl,
|
|
41
|
+
storageUrl: storageUrl.toString(),
|
|
42
|
+
},
|
|
43
|
+
id: resolvedUrl.id,
|
|
44
|
+
tokens: resolvedUrl.tokens,
|
|
45
|
+
type: resolvedUrl.type,
|
|
46
|
+
url: new URLParse(`fluid://${discoveredOrdererUrl.host}${parsedUrl.pathname}`).toString(),
|
|
47
|
+
};
|
|
48
|
+
return discoveredResolvedUrl;
|
|
46
49
|
};
|
|
@@ -4,269 +4,289 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
7
|
+
import { assert, stringToBuffer, Uint8ArrayToString } from "@fluidframework/common-utils";
|
|
7
8
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from "@fluidframework/common-utils";
|
|
12
|
-
import {
|
|
13
|
-
IDocumentStorageService,
|
|
14
|
-
ISummaryContext,
|
|
15
|
-
IDocumentStorageServicePolicies,
|
|
9
|
+
IDocumentStorageService,
|
|
10
|
+
ISummaryContext,
|
|
11
|
+
IDocumentStorageServicePolicies,
|
|
16
12
|
} from "@fluidframework/driver-definitions";
|
|
17
13
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
ISummaryHandle,
|
|
24
|
-
ISummaryTree,
|
|
25
|
-
IVersion,
|
|
14
|
+
ICreateBlobResponse,
|
|
15
|
+
ISnapshotTree,
|
|
16
|
+
ISummaryHandle,
|
|
17
|
+
ISummaryTree,
|
|
18
|
+
IVersion,
|
|
26
19
|
} from "@fluidframework/protocol-definitions";
|
|
27
20
|
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
convertWholeFlatSummaryToSnapshotTreeAndBlobs,
|
|
22
|
+
GitManager,
|
|
23
|
+
ISummaryUploadManager,
|
|
24
|
+
WholeSummaryUploadManager,
|
|
32
25
|
} from "@fluidframework/server-services-client";
|
|
33
26
|
import { PerformanceEvent } from "@fluidframework/telemetry-utils";
|
|
34
27
|
import { ICache, InMemoryCache } from "./cache";
|
|
35
28
|
import { ISnapshotTreeVersion } from "./definitions";
|
|
36
29
|
import { IRouterliciousDriverPolicies } from "./policies";
|
|
30
|
+
import { convertSnapshotAndBlobsToSummaryTree } from "./treeUtils";
|
|
37
31
|
|
|
38
32
|
const latestSnapshotId: string = "latest";
|
|
39
33
|
|
|
40
34
|
export class WholeSummaryDocumentStorageService implements IDocumentStorageService {
|
|
41
|
-
|
|
35
|
+
private firstVersionsCall: boolean = true;
|
|
42
36
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
public get repositoryUrl(): string {
|
|
38
|
+
return "";
|
|
39
|
+
}
|
|
46
40
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
private async getSummaryUploadManager(): Promise<ISummaryUploadManager> {
|
|
42
|
+
const manager = await this.getStorageManager();
|
|
43
|
+
return new WholeSummaryUploadManager(manager);
|
|
44
|
+
}
|
|
51
45
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
46
|
+
constructor(
|
|
47
|
+
protected readonly id: string,
|
|
48
|
+
protected readonly manager: GitManager,
|
|
49
|
+
protected readonly logger: ITelemetryLogger,
|
|
50
|
+
public readonly policies: IDocumentStorageServicePolicies,
|
|
51
|
+
private readonly driverPolicies?: IRouterliciousDriverPolicies,
|
|
52
|
+
private readonly blobCache: ICache<ArrayBufferLike> = new InMemoryCache(),
|
|
53
|
+
private readonly snapshotTreeCache: ICache<ISnapshotTreeVersion> = new InMemoryCache(),
|
|
54
|
+
private readonly noCacheGitManager?: GitManager,
|
|
55
|
+
private readonly getStorageManager: (
|
|
56
|
+
disableCache?: boolean,
|
|
57
|
+
) => Promise<GitManager> = async (disableCache) =>
|
|
58
|
+
disableCache && this.noCacheGitManager !== undefined
|
|
59
|
+
? this.noCacheGitManager
|
|
60
|
+
: this.manager,
|
|
61
|
+
) {}
|
|
65
62
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
63
|
+
public async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {
|
|
64
|
+
if (versionId !== this.id && versionId !== null) {
|
|
65
|
+
// Blobs/Trees in this scenario will never have multiple versions, so return versionId as is
|
|
66
|
+
return [
|
|
67
|
+
{
|
|
68
|
+
id: versionId,
|
|
69
|
+
treeId: undefined!,
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
// If this is the first versions call for the document, we know we will want the latest summary.
|
|
74
|
+
// Fetch latest summary, cache it, and return its id.
|
|
75
|
+
if (this.firstVersionsCall && count === 1) {
|
|
76
|
+
this.firstVersionsCall = false;
|
|
77
|
+
const { id: _id, snapshotTree } = !this.driverPolicies?.enableDiscovery
|
|
78
|
+
? await this.fetchAndCacheSnapshotTree(latestSnapshotId, false)
|
|
79
|
+
: await this.fetchAndCacheSnapshotTree(latestSnapshotId, true);
|
|
80
|
+
return [
|
|
81
|
+
{
|
|
82
|
+
id: _id,
|
|
83
|
+
treeId: snapshotTree.id!,
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
}
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
88
|
+
// Otherwise, get the latest version of the document as normal.
|
|
89
|
+
const id = versionId ? versionId : this.id;
|
|
90
|
+
const commits = await PerformanceEvent.timedExecAsync(
|
|
91
|
+
this.logger,
|
|
92
|
+
{
|
|
93
|
+
eventName: "getVersions",
|
|
94
|
+
versionId: id,
|
|
95
|
+
count,
|
|
96
|
+
},
|
|
97
|
+
async () => {
|
|
98
|
+
const manager = await this.getStorageManager();
|
|
99
|
+
return manager.getCommits(id, count);
|
|
100
|
+
},
|
|
101
|
+
);
|
|
102
|
+
return commits.map((commit) => ({
|
|
103
|
+
date: commit.commit.author.date,
|
|
104
|
+
id: commit.sha,
|
|
105
|
+
treeId: commit.commit.tree.sha,
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
107
108
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
109
|
+
public async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {
|
|
110
|
+
let requestVersion = version;
|
|
111
|
+
if (!requestVersion) {
|
|
112
|
+
const versions = await this.getVersions(this.id, 1);
|
|
113
|
+
if (versions.length === 0) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
115
116
|
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
requestVersion = versions[0];
|
|
118
|
+
}
|
|
118
119
|
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
return (await this.fetchAndCacheSnapshotTree(requestVersion.id)).snapshotTree;
|
|
121
|
+
}
|
|
121
122
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
public async readBlob(blobId: string): Promise<ArrayBufferLike> {
|
|
124
|
+
const cachedBlob = await this.blobCache.get(this.getCacheKey(blobId));
|
|
125
|
+
if (cachedBlob !== undefined) {
|
|
126
|
+
return cachedBlob;
|
|
127
|
+
}
|
|
127
128
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
129
|
+
const blob = await PerformanceEvent.timedExecAsync(
|
|
130
|
+
this.logger,
|
|
131
|
+
{
|
|
132
|
+
eventName: "readBlob",
|
|
133
|
+
blobId,
|
|
134
|
+
},
|
|
135
|
+
async (event) => {
|
|
136
|
+
const manager = await this.getStorageManager();
|
|
137
|
+
const response = await manager.getBlob(blobId);
|
|
138
|
+
event.end({
|
|
139
|
+
size: response.size,
|
|
140
|
+
});
|
|
141
|
+
return response;
|
|
142
|
+
},
|
|
143
|
+
);
|
|
144
|
+
const bufferValue = stringToBuffer(blob.content, blob.encoding);
|
|
144
145
|
|
|
145
|
-
|
|
146
|
+
await this.blobCache.put(this.getCacheKey(blob.sha), bufferValue);
|
|
146
147
|
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
return bufferValue;
|
|
149
|
+
}
|
|
149
150
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
151
|
+
public async uploadSummaryWithContext(
|
|
152
|
+
summary: ISummaryTree,
|
|
153
|
+
context: ISummaryContext,
|
|
154
|
+
): Promise<string> {
|
|
155
|
+
const summaryHandle = await PerformanceEvent.timedExecAsync(
|
|
156
|
+
this.logger,
|
|
157
|
+
{
|
|
158
|
+
eventName: "uploadSummaryWithContext",
|
|
159
|
+
proposalHandle: context.proposalHandle,
|
|
160
|
+
ackHandle: context.ackHandle,
|
|
161
|
+
referenceSequenceNumber: context.referenceSequenceNumber,
|
|
162
|
+
},
|
|
163
|
+
async () => {
|
|
164
|
+
const summaryUploadManager = await this.getSummaryUploadManager();
|
|
165
|
+
return summaryUploadManager.writeSummaryTree(
|
|
166
|
+
summary,
|
|
167
|
+
context.ackHandle ?? "",
|
|
168
|
+
"channel",
|
|
169
|
+
);
|
|
170
|
+
},
|
|
171
|
+
);
|
|
172
|
+
return summaryHandle;
|
|
173
|
+
}
|
|
166
174
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
175
|
+
public async downloadSummary(summaryHandle: ISummaryHandle): Promise<ISummaryTree> {
|
|
176
|
+
const wholeFlatSummary = await PerformanceEvent.timedExecAsync(
|
|
177
|
+
this.logger,
|
|
178
|
+
{
|
|
179
|
+
eventName: "getWholeFlatSummary",
|
|
180
|
+
treeId: summaryHandle.handle,
|
|
181
|
+
},
|
|
182
|
+
async (event) => {
|
|
183
|
+
const manager = await this.getStorageManager();
|
|
184
|
+
const response = await manager.getSummary(summaryHandle.handle);
|
|
185
|
+
event.end({
|
|
186
|
+
size: response.trees[0]?.entries.length,
|
|
187
|
+
});
|
|
188
|
+
return response;
|
|
189
|
+
},
|
|
190
|
+
);
|
|
183
191
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
192
|
+
const { blobs, snapshotTree } = convertWholeFlatSummaryToSnapshotTreeAndBlobs(
|
|
193
|
+
wholeFlatSummary,
|
|
194
|
+
"",
|
|
195
|
+
);
|
|
196
|
+
return convertSnapshotAndBlobsToSummaryTree(snapshotTree, blobs);
|
|
197
|
+
}
|
|
187
198
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
199
|
+
public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {
|
|
200
|
+
const uint8ArrayFile = new Uint8Array(file);
|
|
201
|
+
return PerformanceEvent.timedExecAsync(
|
|
202
|
+
this.logger,
|
|
203
|
+
{
|
|
204
|
+
eventName: "createBlob",
|
|
205
|
+
size: uint8ArrayFile.length,
|
|
206
|
+
},
|
|
207
|
+
async (event) => {
|
|
208
|
+
const manager = await this.getStorageManager();
|
|
209
|
+
const response = await manager
|
|
210
|
+
.createBlob(Uint8ArrayToString(uint8ArrayFile, "base64"), "base64")
|
|
211
|
+
.then((r) => ({ id: r.sha, url: r.url }));
|
|
212
|
+
event.end({
|
|
213
|
+
blobId: response.id,
|
|
214
|
+
});
|
|
215
|
+
return response;
|
|
216
|
+
},
|
|
217
|
+
);
|
|
218
|
+
}
|
|
209
219
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
220
|
+
private async fetchAndCacheSnapshotTree(
|
|
221
|
+
versionId: string,
|
|
222
|
+
disableCache?: boolean,
|
|
223
|
+
): Promise<ISnapshotTreeVersion> {
|
|
224
|
+
const cachedSnapshotTreeVersion = await this.snapshotTreeCache.get(
|
|
225
|
+
this.getCacheKey(versionId),
|
|
226
|
+
);
|
|
227
|
+
if (cachedSnapshotTreeVersion !== undefined) {
|
|
228
|
+
return {
|
|
229
|
+
id: cachedSnapshotTreeVersion.id,
|
|
230
|
+
snapshotTree: cachedSnapshotTreeVersion.snapshotTree,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
215
233
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
234
|
+
const wholeFlatSummary = await PerformanceEvent.timedExecAsync(
|
|
235
|
+
this.logger,
|
|
236
|
+
{
|
|
237
|
+
eventName: "getWholeFlatSummary",
|
|
238
|
+
treeId: versionId,
|
|
239
|
+
},
|
|
240
|
+
async (event) => {
|
|
241
|
+
const manager = await this.getStorageManager(disableCache);
|
|
242
|
+
const response = await manager.getSummary(versionId);
|
|
243
|
+
event.end({
|
|
244
|
+
size: response.trees[0]?.entries.length,
|
|
245
|
+
});
|
|
246
|
+
return response;
|
|
247
|
+
},
|
|
248
|
+
);
|
|
249
|
+
const normalizedWholeSummary =
|
|
250
|
+
convertWholeFlatSummaryToSnapshotTreeAndBlobs(wholeFlatSummary);
|
|
251
|
+
assert(
|
|
252
|
+
normalizedWholeSummary.snapshotTree.id !== undefined,
|
|
253
|
+
0x275 /* "Root tree should contain the id" */,
|
|
254
|
+
);
|
|
255
|
+
const wholeFlatSummaryId: string = wholeFlatSummary.id;
|
|
256
|
+
const snapshotTreeVersion = {
|
|
257
|
+
id: wholeFlatSummaryId,
|
|
258
|
+
snapshotTree: normalizedWholeSummary.snapshotTree,
|
|
259
|
+
};
|
|
236
260
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
this.getCacheKey(versionId),
|
|
251
|
-
snapshotTreeVersion,
|
|
252
|
-
));
|
|
253
|
-
}
|
|
261
|
+
const cachePs: Promise<any>[] = [
|
|
262
|
+
this.snapshotTreeCache.put(this.getCacheKey(wholeFlatSummaryId), snapshotTreeVersion),
|
|
263
|
+
this.initBlobCache(normalizedWholeSummary.blobs),
|
|
264
|
+
];
|
|
265
|
+
if (wholeFlatSummaryId !== versionId) {
|
|
266
|
+
// versionId could be "latest". When summarizer checks cache for "latest", we want it to be available.
|
|
267
|
+
// TODO: For in-memory cache, <latest,snapshotTree> will be a shared pointer with <snapshotId,snapshotTree>,
|
|
268
|
+
// However, for something like Redis, this will cache the same value twice. Alternatively, could we simply
|
|
269
|
+
// cache with versionId?
|
|
270
|
+
cachePs.push(
|
|
271
|
+
this.snapshotTreeCache.put(this.getCacheKey(versionId), snapshotTreeVersion),
|
|
272
|
+
);
|
|
273
|
+
}
|
|
254
274
|
|
|
255
|
-
|
|
275
|
+
await Promise.all(cachePs);
|
|
256
276
|
|
|
257
|
-
|
|
258
|
-
|
|
277
|
+
return snapshotTreeVersion;
|
|
278
|
+
}
|
|
259
279
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
280
|
+
private async initBlobCache(blobs: Map<string, ArrayBuffer>): Promise<void> {
|
|
281
|
+
const blobCachePutPs: Promise<void>[] = [];
|
|
282
|
+
blobs.forEach((value, id) => {
|
|
283
|
+
const cacheKey = this.getCacheKey(id);
|
|
284
|
+
blobCachePutPs.push(this.blobCache.put(cacheKey, value));
|
|
285
|
+
});
|
|
286
|
+
await Promise.all(blobCachePutPs);
|
|
287
|
+
}
|
|
268
288
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
289
|
+
private getCacheKey(blobId: string): string {
|
|
290
|
+
return `${this.id}:${blobId}`;
|
|
291
|
+
}
|
|
272
292
|
}
|
package/tsconfig.esnext.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "./lib",
|
|
5
|
+
"module": "esnext",
|
|
6
|
+
},
|
|
7
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
},
|
|
12
|
-
"include": [
|
|
13
|
-
"src/**/*"
|
|
14
|
-
]
|
|
2
|
+
"extends": "@fluidframework/build-common/ts-common-config.json",
|
|
3
|
+
"exclude": ["src/test/**/*"],
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"composite": true,
|
|
8
|
+
"types": ["node"],
|
|
9
|
+
},
|
|
10
|
+
"include": ["src/**/*"],
|
|
15
11
|
}
|