@fluidframework/routerlicious-driver 2.0.0-dev.4.1.0.148229 → 2.0.0-dev.4.3.0.157531
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/CHANGELOG.md +5 -0
- package/README.md +38 -0
- package/dist/contracts.d.ts +15 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +7 -0
- package/dist/contracts.js.map +1 -0
- package/dist/deltaStorageService.d.ts +1 -1
- package/dist/deltaStorageService.d.ts.map +1 -1
- package/dist/deltaStorageService.js +7 -4
- package/dist/deltaStorageService.js.map +1 -1
- package/dist/documentService.d.ts +4 -2
- package/dist/documentService.d.ts.map +1 -1
- package/dist/documentService.js +11 -9
- package/dist/documentService.js.map +1 -1
- package/dist/documentServiceFactory.d.ts +2 -1
- package/dist/documentServiceFactory.d.ts.map +1 -1
- package/dist/documentServiceFactory.js +18 -8
- package/dist/documentServiceFactory.js.map +1 -1
- package/dist/documentStorageService.d.ts +3 -2
- package/dist/documentStorageService.d.ts.map +1 -1
- package/dist/documentStorageService.js +4 -4
- package/dist/documentStorageService.js.map +1 -1
- package/dist/gitManager.d.ts +30 -0
- package/dist/gitManager.d.ts.map +1 -0
- package/dist/gitManager.js +89 -0
- package/dist/gitManager.js.map +1 -0
- package/dist/historian.d.ts +33 -0
- package/dist/historian.d.ts.map +1 -0
- package/dist/historian.js +65 -0
- package/dist/historian.js.map +1 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/r11sSnapshotParser.d.ts +15 -0
- package/dist/r11sSnapshotParser.d.ts.map +1 -0
- package/dist/r11sSnapshotParser.js +75 -0
- package/dist/r11sSnapshotParser.js.map +1 -0
- package/dist/restWrapper.d.ts +21 -8
- package/dist/restWrapper.d.ts.map +1 -1
- package/dist/restWrapper.js +93 -25
- package/dist/restWrapper.js.map +1 -1
- package/dist/restWrapperBase.d.ts +26 -0
- package/dist/restWrapperBase.d.ts.map +1 -0
- package/dist/restWrapperBase.js +55 -0
- package/dist/restWrapperBase.js.map +1 -0
- package/dist/retriableGitManager.d.ts +10 -21
- package/dist/retriableGitManager.d.ts.map +1 -1
- package/dist/retriableGitManager.js +0 -36
- 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 +6 -6
- package/dist/shreddedSummaryDocumentStorageService.js.map +1 -1
- package/dist/storageContracts.d.ts +44 -0
- package/dist/storageContracts.d.ts.map +1 -0
- package/dist/storageContracts.js +7 -0
- package/dist/storageContracts.js.map +1 -0
- package/dist/summaryTreeUploadManager.d.ts +23 -0
- package/dist/summaryTreeUploadManager.d.ts.map +1 -0
- package/dist/summaryTreeUploadManager.js +110 -0
- package/dist/summaryTreeUploadManager.js.map +1 -0
- package/dist/treeUtils.d.ts +7 -0
- package/dist/treeUtils.d.ts.map +1 -1
- package/dist/treeUtils.js +23 -1
- package/dist/treeUtils.js.map +1 -1
- package/dist/wholeSummaryDocumentStorageService.d.ts +5 -4
- package/dist/wholeSummaryDocumentStorageService.d.ts.map +1 -1
- package/dist/wholeSummaryDocumentStorageService.js +74 -42
- package/dist/wholeSummaryDocumentStorageService.js.map +1 -1
- package/dist/wholeSummaryUploadManager.d.ts +16 -0
- package/dist/wholeSummaryUploadManager.d.ts.map +1 -0
- package/dist/wholeSummaryUploadManager.js +38 -0
- package/dist/wholeSummaryUploadManager.js.map +1 -0
- package/lib/contracts.d.ts +15 -0
- package/lib/contracts.d.ts.map +1 -0
- package/lib/contracts.js +6 -0
- package/lib/contracts.js.map +1 -0
- package/lib/deltaStorageService.d.ts +1 -1
- package/lib/deltaStorageService.d.ts.map +1 -1
- package/lib/deltaStorageService.js +7 -4
- package/lib/deltaStorageService.js.map +1 -1
- package/lib/documentService.d.ts +4 -2
- package/lib/documentService.d.ts.map +1 -1
- package/lib/documentService.js +9 -7
- package/lib/documentService.js.map +1 -1
- package/lib/documentServiceFactory.d.ts +2 -1
- package/lib/documentServiceFactory.d.ts.map +1 -1
- package/lib/documentServiceFactory.js +18 -8
- package/lib/documentServiceFactory.js.map +1 -1
- package/lib/documentStorageService.d.ts +3 -2
- package/lib/documentStorageService.d.ts.map +1 -1
- package/lib/documentStorageService.js +4 -4
- package/lib/documentStorageService.js.map +1 -1
- package/lib/gitManager.d.ts +30 -0
- package/lib/gitManager.d.ts.map +1 -0
- package/lib/gitManager.js +85 -0
- package/lib/gitManager.js.map +1 -0
- package/lib/historian.d.ts +33 -0
- package/lib/historian.d.ts.map +1 -0
- package/lib/historian.js +60 -0
- package/lib/historian.js.map +1 -0
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/r11sSnapshotParser.d.ts +15 -0
- package/lib/r11sSnapshotParser.d.ts.map +1 -0
- package/lib/r11sSnapshotParser.js +71 -0
- package/lib/r11sSnapshotParser.js.map +1 -0
- package/lib/restWrapper.d.ts +21 -8
- package/lib/restWrapper.d.ts.map +1 -1
- package/lib/restWrapper.js +92 -26
- package/lib/restWrapper.js.map +1 -1
- package/lib/restWrapperBase.d.ts +26 -0
- package/lib/restWrapperBase.d.ts.map +1 -0
- package/lib/restWrapperBase.js +50 -0
- package/lib/restWrapperBase.js.map +1 -0
- package/lib/retriableGitManager.d.ts +10 -21
- package/lib/retriableGitManager.d.ts.map +1 -1
- package/lib/retriableGitManager.js +0 -36
- 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 +5 -5
- package/lib/shreddedSummaryDocumentStorageService.js.map +1 -1
- package/lib/storageContracts.d.ts +44 -0
- package/lib/storageContracts.d.ts.map +1 -0
- package/lib/storageContracts.js +6 -0
- package/lib/storageContracts.js.map +1 -0
- package/lib/summaryTreeUploadManager.d.ts +23 -0
- package/lib/summaryTreeUploadManager.d.ts.map +1 -0
- package/lib/summaryTreeUploadManager.js +106 -0
- package/lib/summaryTreeUploadManager.js.map +1 -0
- package/lib/treeUtils.d.ts +7 -0
- package/lib/treeUtils.d.ts.map +1 -1
- package/lib/treeUtils.js +20 -0
- package/lib/treeUtils.js.map +1 -1
- package/lib/wholeSummaryDocumentStorageService.d.ts +5 -4
- package/lib/wholeSummaryDocumentStorageService.d.ts.map +1 -1
- package/lib/wholeSummaryDocumentStorageService.js +74 -42
- package/lib/wholeSummaryDocumentStorageService.js.map +1 -1
- package/lib/wholeSummaryUploadManager.d.ts +16 -0
- package/lib/wholeSummaryUploadManager.d.ts.map +1 -0
- package/lib/wholeSummaryUploadManager.js +34 -0
- package/lib/wholeSummaryUploadManager.js.map +1 -0
- package/package.json +9 -10
- package/src/contracts.ts +16 -0
- package/src/deltaStorageService.ts +11 -3
- package/src/documentService.ts +11 -11
- package/src/documentServiceFactory.ts +35 -16
- package/src/documentStorageService.ts +8 -4
- package/src/gitManager.ts +116 -0
- package/src/historian.ts +121 -0
- package/src/packageVersion.ts +1 -1
- package/src/r11sSnapshotParser.ts +83 -0
- package/src/restWrapper.ts +114 -38
- package/src/restWrapperBase.ts +146 -0
- package/src/retriableGitManager.ts +17 -95
- package/src/shreddedSummaryDocumentStorageService.ts +7 -9
- package/src/storageContracts.ts +63 -0
- package/src/summaryTreeUploadManager.ts +160 -0
- package/src/treeUtils.ts +30 -0
- package/src/wholeSummaryDocumentStorageService.ts +117 -58
- package/src/wholeSummaryUploadManager.ts +64 -0
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { assert } from "@fluidframework/common-utils";
|
|
7
|
+
import { getW3CData } from "@fluidframework/driver-base";
|
|
7
8
|
import {
|
|
8
9
|
FiveDaysMs,
|
|
9
10
|
IDocumentService,
|
|
@@ -33,6 +34,7 @@ import { parseFluidUrl, replaceDocumentIdInPath, getDiscoveredFluidResolvedUrl }
|
|
|
33
34
|
import { ICache, InMemoryCache, NullCache } from "./cache";
|
|
34
35
|
import { pkgVersion as driverVersion } from "./packageVersion";
|
|
35
36
|
import { ISnapshotTreeVersion } from "./definitions";
|
|
37
|
+
import { INormalizedWholeSummary } from "./contracts";
|
|
36
38
|
|
|
37
39
|
const maximumSnapshotCacheDurationMs: FiveDaysMs = 432_000_000; // 5 days in ms
|
|
38
40
|
|
|
@@ -54,7 +56,8 @@ const defaultRouterliciousDriverPolicies: IRouterliciousDriverPolicies = {
|
|
|
54
56
|
export class RouterliciousDocumentServiceFactory implements IDocumentServiceFactory {
|
|
55
57
|
private readonly driverPolicies: IRouterliciousDriverPolicies;
|
|
56
58
|
private readonly blobCache: ICache<ArrayBufferLike>;
|
|
57
|
-
private readonly
|
|
59
|
+
private readonly wholeSnapshotTreeCache: ICache<INormalizedWholeSummary> = new NullCache();
|
|
60
|
+
private readonly shreddedSummaryTreeCache: ICache<ISnapshotTreeVersion> = new NullCache();
|
|
58
61
|
|
|
59
62
|
constructor(
|
|
60
63
|
private readonly tokenProvider: ITokenProvider,
|
|
@@ -68,9 +71,17 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
|
|
|
68
71
|
...driverPolicies,
|
|
69
72
|
};
|
|
70
73
|
this.blobCache = new InMemoryCache<ArrayBufferLike>();
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
if (this.driverPolicies.enableInternalSummaryCaching) {
|
|
75
|
+
if (this.driverPolicies.enableWholeSummaryUpload) {
|
|
76
|
+
this.wholeSnapshotTreeCache = new InMemoryCache<INormalizedWholeSummary>(
|
|
77
|
+
snapshotCacheExpiryMs,
|
|
78
|
+
);
|
|
79
|
+
} else {
|
|
80
|
+
this.shreddedSummaryTreeCache = new InMemoryCache<ISnapshotTreeVersion>(
|
|
81
|
+
snapshotCacheExpiryMs,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
74
85
|
}
|
|
75
86
|
|
|
76
87
|
/**
|
|
@@ -128,15 +139,17 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
|
|
|
128
139
|
},
|
|
129
140
|
async (event) => {
|
|
130
141
|
// @TODO: Remove returned "string" type when removing back-compat code
|
|
131
|
-
const postRes =
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
142
|
+
const postRes = (
|
|
143
|
+
await ordererRestWrapper.post<
|
|
144
|
+
{ id: string; token?: string; session?: ISession } | string
|
|
145
|
+
>(`/documents/${tenantId}`, {
|
|
146
|
+
summary: convertSummaryToCreateNewSummary(appSummary),
|
|
147
|
+
sequenceNumber: documentAttributes.sequenceNumber,
|
|
148
|
+
values: quorumValues,
|
|
149
|
+
enableDiscovery: this.driverPolicies.enableDiscovery,
|
|
150
|
+
generateToken: this.tokenProvider.documentPostCreateCallback !== undefined,
|
|
151
|
+
})
|
|
152
|
+
).content;
|
|
140
153
|
|
|
141
154
|
event.end({
|
|
142
155
|
docId: typeof postRes === "string" ? postRes : postRes.id,
|
|
@@ -253,11 +266,16 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
|
|
|
253
266
|
eventName: "DiscoverSession",
|
|
254
267
|
docId: documentId,
|
|
255
268
|
},
|
|
256
|
-
async () => {
|
|
269
|
+
async (event) => {
|
|
257
270
|
// The service responds with the current document session associated with the container.
|
|
258
|
-
|
|
271
|
+
const response = await ordererRestWrapper.get<ISession>(
|
|
259
272
|
`${resolvedUrl.endpoints.ordererUrl}/documents/${tenantId}/session/${documentId}`,
|
|
260
273
|
);
|
|
274
|
+
event.end({
|
|
275
|
+
...response.propsToLog,
|
|
276
|
+
...getW3CData(response.requestUrl, "xmlhttprequest"),
|
|
277
|
+
});
|
|
278
|
+
return response.content;
|
|
261
279
|
},
|
|
262
280
|
);
|
|
263
281
|
return getDiscoveredFluidResolvedUrl(resolvedUrl, discoveredSession);
|
|
@@ -299,7 +317,8 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
|
|
|
299
317
|
documentStorageServicePolicies,
|
|
300
318
|
this.driverPolicies,
|
|
301
319
|
this.blobCache,
|
|
302
|
-
this.
|
|
320
|
+
this.wholeSnapshotTreeCache,
|
|
321
|
+
this.shreddedSummaryTreeCache,
|
|
303
322
|
discoverFluidResolvedUrl,
|
|
304
323
|
);
|
|
305
324
|
}
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
LoaderCachingPolicy,
|
|
11
11
|
} from "@fluidframework/driver-definitions";
|
|
12
12
|
import { ISnapshotTree, IVersion } from "@fluidframework/protocol-definitions";
|
|
13
|
-
import { GitManager } from "@fluidframework/server-services-client";
|
|
14
13
|
import {
|
|
15
14
|
DocumentStorageServiceProxy,
|
|
16
15
|
PrefetchDocumentStorageService,
|
|
@@ -19,7 +18,9 @@ import { IRouterliciousDriverPolicies } from "./policies";
|
|
|
19
18
|
import { ICache } from "./cache";
|
|
20
19
|
import { WholeSummaryDocumentStorageService } from "./wholeSummaryDocumentStorageService";
|
|
21
20
|
import { ShreddedSummaryDocumentStorageService } from "./shreddedSummaryDocumentStorageService";
|
|
21
|
+
import { GitManager } from "./gitManager";
|
|
22
22
|
import { ISnapshotTreeVersion } from "./definitions";
|
|
23
|
+
import { INormalizedWholeSummary } from "./contracts";
|
|
23
24
|
|
|
24
25
|
export class DocumentStorageService extends DocumentStorageServiceProxy {
|
|
25
26
|
private _logTailSha: string | undefined = undefined;
|
|
@@ -35,7 +36,8 @@ export class DocumentStorageService extends DocumentStorageServiceProxy {
|
|
|
35
36
|
policies: IDocumentStorageServicePolicies,
|
|
36
37
|
driverPolicies?: IRouterliciousDriverPolicies,
|
|
37
38
|
blobCache?: ICache<ArrayBufferLike>,
|
|
38
|
-
snapshotTreeCache?: ICache<
|
|
39
|
+
snapshotTreeCache?: ICache<INormalizedWholeSummary>,
|
|
40
|
+
shreddedSummaryTreeCache?: ICache<ISnapshotTreeVersion>,
|
|
39
41
|
noCacheGitManager?: GitManager,
|
|
40
42
|
getStorageManager?: (disableCache?: boolean) => Promise<GitManager>,
|
|
41
43
|
): IDocumentStorageService {
|
|
@@ -58,7 +60,7 @@ export class DocumentStorageService extends DocumentStorageServiceProxy {
|
|
|
58
60
|
policies,
|
|
59
61
|
driverPolicies,
|
|
60
62
|
blobCache,
|
|
61
|
-
|
|
63
|
+
shreddedSummaryTreeCache,
|
|
62
64
|
getStorageManager,
|
|
63
65
|
);
|
|
64
66
|
// TODO: worth prefetching latest summary making version + snapshot call with WholeSummary storage?
|
|
@@ -78,7 +80,8 @@ export class DocumentStorageService extends DocumentStorageServiceProxy {
|
|
|
78
80
|
policies: IDocumentStorageServicePolicies,
|
|
79
81
|
driverPolicies?: IRouterliciousDriverPolicies,
|
|
80
82
|
blobCache?: ICache<ArrayBufferLike>,
|
|
81
|
-
snapshotTreeCache?: ICache<
|
|
83
|
+
snapshotTreeCache?: ICache<INormalizedWholeSummary>,
|
|
84
|
+
shreddedSummaryTreeCache?: ICache<ISnapshotTreeVersion>,
|
|
82
85
|
public noCacheGitManager?: GitManager,
|
|
83
86
|
getStorageManager?: (disableCache?: boolean) => Promise<GitManager>,
|
|
84
87
|
) {
|
|
@@ -91,6 +94,7 @@ export class DocumentStorageService extends DocumentStorageServiceProxy {
|
|
|
91
94
|
driverPolicies,
|
|
92
95
|
blobCache,
|
|
93
96
|
snapshotTreeCache,
|
|
97
|
+
shreddedSummaryTreeCache,
|
|
94
98
|
noCacheGitManager,
|
|
95
99
|
getStorageManager,
|
|
96
100
|
),
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as resources from "@fluidframework/gitresources";
|
|
7
|
+
import {
|
|
8
|
+
IWholeFlatSummary,
|
|
9
|
+
IWholeSummaryPayload,
|
|
10
|
+
IWriteSummaryResponse,
|
|
11
|
+
} from "@fluidframework/server-services-client";
|
|
12
|
+
import { IGitManager, IHistorian } from "./storageContracts";
|
|
13
|
+
import { IR11sResponse, createR11sResponseFromContent } from "./restWrapper";
|
|
14
|
+
|
|
15
|
+
export class GitManager implements IGitManager {
|
|
16
|
+
private readonly blobCache = new Map<string, resources.IBlob>();
|
|
17
|
+
private readonly commitCache = new Map<string, resources.ICommit>();
|
|
18
|
+
private readonly treeCache = new Map<string, resources.ITree>();
|
|
19
|
+
private readonly refCache = new Map<string, string>();
|
|
20
|
+
|
|
21
|
+
constructor(private readonly historian: IHistorian) {}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Reads the object with the given ID. We defer to the client implementation to do the actual read.
|
|
25
|
+
*/
|
|
26
|
+
public async getCommits(
|
|
27
|
+
shaOrRef: string,
|
|
28
|
+
count: number,
|
|
29
|
+
): Promise<IR11sResponse<resources.ICommitDetails[]>> {
|
|
30
|
+
let sha: string | undefined = shaOrRef;
|
|
31
|
+
|
|
32
|
+
// See if the sha is really a ref and convert
|
|
33
|
+
if (this.refCache.has(shaOrRef)) {
|
|
34
|
+
sha = this.refCache.get(shaOrRef);
|
|
35
|
+
|
|
36
|
+
// Delete refcache after first use
|
|
37
|
+
this.refCache.delete(shaOrRef);
|
|
38
|
+
|
|
39
|
+
// If null is stored for the ref then there are no commits - return an empty array
|
|
40
|
+
if (!sha) {
|
|
41
|
+
return createR11sResponseFromContent([]);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// See if the commit sha is hashed and return it if so
|
|
46
|
+
const commit = this.commitCache.get(sha);
|
|
47
|
+
if (commit !== undefined) {
|
|
48
|
+
return createR11sResponseFromContent([
|
|
49
|
+
{
|
|
50
|
+
commit: {
|
|
51
|
+
author: commit.author,
|
|
52
|
+
committer: commit.committer,
|
|
53
|
+
message: commit.message,
|
|
54
|
+
tree: commit.tree,
|
|
55
|
+
url: commit.url,
|
|
56
|
+
},
|
|
57
|
+
parents: commit.parents,
|
|
58
|
+
sha: commit.sha,
|
|
59
|
+
url: commit.url,
|
|
60
|
+
},
|
|
61
|
+
]);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Otherwise fall back to the historian
|
|
65
|
+
return this.historian.getCommits(sha, count);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Reads the object with the given ID. We defer to the client implementation to do the actual read.
|
|
70
|
+
*/
|
|
71
|
+
public async getTree(root: string, recursive = true): Promise<IR11sResponse<resources.ITree>> {
|
|
72
|
+
const tree = this.treeCache.get(root);
|
|
73
|
+
if (tree !== undefined) {
|
|
74
|
+
return createR11sResponseFromContent(tree);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return this.historian.getTree(root, recursive);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public async getBlob(sha: string): Promise<IR11sResponse<resources.IBlob>> {
|
|
81
|
+
const blob = this.blobCache.get(sha);
|
|
82
|
+
if (blob !== undefined) {
|
|
83
|
+
return createR11sResponseFromContent(blob);
|
|
84
|
+
}
|
|
85
|
+
return this.historian.getBlob(sha);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public async createBlob(
|
|
89
|
+
content: string,
|
|
90
|
+
encoding: "utf-8" | "base64",
|
|
91
|
+
): Promise<IR11sResponse<resources.ICreateBlobResponse>> {
|
|
92
|
+
const blob: resources.ICreateBlobParams = {
|
|
93
|
+
content,
|
|
94
|
+
encoding,
|
|
95
|
+
};
|
|
96
|
+
return this.historian.createBlob(blob);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public async createGitTree(
|
|
100
|
+
params: resources.ICreateTreeParams,
|
|
101
|
+
): Promise<IR11sResponse<resources.ITree>> {
|
|
102
|
+
const treeP = this.historian.createTree(params);
|
|
103
|
+
return treeP;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public async createSummary(
|
|
107
|
+
summary: IWholeSummaryPayload,
|
|
108
|
+
initial: boolean = false,
|
|
109
|
+
): Promise<IR11sResponse<IWriteSummaryResponse>> {
|
|
110
|
+
return this.historian.createSummary(summary, initial);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public async getSummary(sha: string): Promise<IR11sResponse<IWholeFlatSummary>> {
|
|
114
|
+
return this.historian.getSummary(sha);
|
|
115
|
+
}
|
|
116
|
+
}
|
package/src/historian.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { fromUtf8ToBase64 } from "@fluidframework/common-utils";
|
|
7
|
+
import * as git from "@fluidframework/gitresources";
|
|
8
|
+
import {
|
|
9
|
+
IWholeFlatSummary,
|
|
10
|
+
IWholeSummaryPayload,
|
|
11
|
+
IWriteSummaryResponse,
|
|
12
|
+
} from "@fluidframework/server-services-client";
|
|
13
|
+
import { QueryStringType, RestWrapper } from "./restWrapperBase";
|
|
14
|
+
import { IR11sResponse } from "./restWrapper";
|
|
15
|
+
import { IHistorian } from "./storageContracts";
|
|
16
|
+
|
|
17
|
+
export interface ICredentials {
|
|
18
|
+
user: string;
|
|
19
|
+
password: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const getAuthorizationTokenFromCredentials = (credentials: ICredentials): string =>
|
|
23
|
+
`Basic ${fromUtf8ToBase64(`${credentials.user}:${credentials.password}`)}`;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Implementation of the IHistorian interface that calls out to a REST interface
|
|
27
|
+
*/
|
|
28
|
+
export class Historian implements IHistorian {
|
|
29
|
+
private readonly defaultQueryString: QueryStringType = {};
|
|
30
|
+
private readonly cacheBust: boolean;
|
|
31
|
+
|
|
32
|
+
constructor(
|
|
33
|
+
private readonly historianApi: boolean,
|
|
34
|
+
disableCache: boolean,
|
|
35
|
+
private readonly restWrapper: RestWrapper,
|
|
36
|
+
) {
|
|
37
|
+
if (disableCache && this.historianApi) {
|
|
38
|
+
this.defaultQueryString.disableCache = disableCache;
|
|
39
|
+
this.cacheBust = false;
|
|
40
|
+
} else {
|
|
41
|
+
this.cacheBust = disableCache;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public async getBlob(sha: string): Promise<IR11sResponse<git.IBlob>> {
|
|
46
|
+
return this.restWrapper.get<git.IBlob>(
|
|
47
|
+
`/git/blobs/${encodeURIComponent(sha)}`,
|
|
48
|
+
this.getQueryString(),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public async createBlob(
|
|
53
|
+
blob: git.ICreateBlobParams,
|
|
54
|
+
): Promise<IR11sResponse<git.ICreateBlobResponse>> {
|
|
55
|
+
return this.restWrapper.post<git.ICreateBlobResponse>(
|
|
56
|
+
`/git/blobs`,
|
|
57
|
+
blob,
|
|
58
|
+
this.getQueryString(),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public async getCommits(
|
|
63
|
+
sha: string,
|
|
64
|
+
count: number,
|
|
65
|
+
): Promise<IR11sResponse<git.ICommitDetails[]>> {
|
|
66
|
+
return this.restWrapper
|
|
67
|
+
.get<git.ICommitDetails[]>(`/commits`, this.getQueryString({ count, sha }))
|
|
68
|
+
.catch((error) =>
|
|
69
|
+
error.statusCode === 400 || error.statusCode === 404
|
|
70
|
+
? {
|
|
71
|
+
content: [],
|
|
72
|
+
headers: new Map(),
|
|
73
|
+
propsToLog: {},
|
|
74
|
+
requestUrl: "",
|
|
75
|
+
}
|
|
76
|
+
: Promise.reject<IR11sResponse<git.ICommitDetails[]>>(error),
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public async createTree(tree: git.ICreateTreeParams): Promise<IR11sResponse<git.ITree>> {
|
|
81
|
+
return this.restWrapper.post<git.ITree>(`/git/trees`, tree, this.getQueryString());
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public async getTree(sha: string, recursive: boolean): Promise<IR11sResponse<git.ITree>> {
|
|
85
|
+
return this.restWrapper.get<git.ITree>(
|
|
86
|
+
`/git/trees/${encodeURIComponent(sha)}`,
|
|
87
|
+
this.getQueryString({ recursive: recursive ? 1 : 0 }),
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
public async createSummary(
|
|
91
|
+
summary: IWholeSummaryPayload,
|
|
92
|
+
initial?: boolean,
|
|
93
|
+
): Promise<IR11sResponse<IWriteSummaryResponse>> {
|
|
94
|
+
return this.restWrapper.post<IWriteSummaryResponse>(
|
|
95
|
+
`/git/summaries`,
|
|
96
|
+
summary,
|
|
97
|
+
this.getQueryString(initial !== undefined ? { initial } : undefined),
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public async getSummary(sha: string): Promise<IR11sResponse<IWholeFlatSummary>> {
|
|
102
|
+
return this.restWrapper.get<IWholeFlatSummary>(
|
|
103
|
+
`/git/summaries/${sha}`,
|
|
104
|
+
this.getQueryString(),
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private getQueryString(queryString?: QueryStringType): QueryStringType {
|
|
109
|
+
if (this.cacheBust) {
|
|
110
|
+
return {
|
|
111
|
+
cacheBust: Date.now(),
|
|
112
|
+
...this.defaultQueryString,
|
|
113
|
+
...queryString,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
...this.defaultQueryString,
|
|
118
|
+
...queryString,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
package/src/packageVersion.ts
CHANGED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ISnapshotTree } from "@fluidframework/protocol-definitions";
|
|
7
|
+
import { IWholeFlatSummary, IWholeFlatSummaryTree } from "@fluidframework/server-services-client";
|
|
8
|
+
import { stringToBuffer } from "@fluidframework/common-utils";
|
|
9
|
+
import { INormalizedWholeSummary } from "./contracts";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Build a tree heirarchy from a flat tree.
|
|
13
|
+
*
|
|
14
|
+
* @param flatTree - a flat tree
|
|
15
|
+
* @param treePrefixToRemove - tree prefix to strip
|
|
16
|
+
* @returns the heirarchical tree
|
|
17
|
+
*/
|
|
18
|
+
function buildHierarchy(
|
|
19
|
+
flatTree: IWholeFlatSummaryTree,
|
|
20
|
+
treePrefixToRemove: string,
|
|
21
|
+
): ISnapshotTree {
|
|
22
|
+
const lookup: { [path: string]: ISnapshotTree } = {};
|
|
23
|
+
// Root tree id will be used to determine which version was downloaded.
|
|
24
|
+
const root: ISnapshotTree = { id: flatTree.id, blobs: {}, trees: {} };
|
|
25
|
+
lookup[""] = root;
|
|
26
|
+
|
|
27
|
+
for (const entry of flatTree.entries) {
|
|
28
|
+
// Strip the `treePrefixToRemove` path from tree entries such that they are stored under root.
|
|
29
|
+
const entryPath = entry.path.replace(new RegExp(`^${treePrefixToRemove}/`), "");
|
|
30
|
+
const lastIndex = entryPath.lastIndexOf("/");
|
|
31
|
+
const entryPathDir = entryPath.slice(0, Math.max(0, lastIndex));
|
|
32
|
+
const entryPathBase = entryPath.slice(lastIndex + 1);
|
|
33
|
+
|
|
34
|
+
// The flat output is breadth-first so we can assume we see tree nodes prior to their contents
|
|
35
|
+
const node = lookup[entryPathDir];
|
|
36
|
+
|
|
37
|
+
// Add in either the blob or tree
|
|
38
|
+
if (entry.type === "tree") {
|
|
39
|
+
const newTree: ISnapshotTree = {
|
|
40
|
+
blobs: {},
|
|
41
|
+
trees: {},
|
|
42
|
+
unreferenced: entry.unreferenced,
|
|
43
|
+
};
|
|
44
|
+
node.trees[decodeURIComponent(entryPathBase)] = newTree;
|
|
45
|
+
lookup[entryPath] = newTree;
|
|
46
|
+
} else if (entry.type === "blob") {
|
|
47
|
+
node.blobs[decodeURIComponent(entryPathBase)] = entry.id;
|
|
48
|
+
} else {
|
|
49
|
+
throw new Error(`Unknown entry type!!`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return root;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Converts existing IWholeFlatSummary to snapshot tree, blob array, and sequence number.
|
|
58
|
+
*
|
|
59
|
+
* @param flatSummary - flat summary
|
|
60
|
+
* @param treePrefixToRemove - tree prefix to strip. By default we are stripping ".app" prefix
|
|
61
|
+
* @returns snapshot tree, blob array, and sequence number
|
|
62
|
+
*/
|
|
63
|
+
export function convertWholeFlatSummaryToSnapshotTreeAndBlobs(
|
|
64
|
+
flatSummary: IWholeFlatSummary,
|
|
65
|
+
treePrefixToRemove: string = ".app",
|
|
66
|
+
): INormalizedWholeSummary {
|
|
67
|
+
const blobs = new Map<string, ArrayBuffer>();
|
|
68
|
+
if (flatSummary.blobs) {
|
|
69
|
+
flatSummary.blobs.forEach((blob) => {
|
|
70
|
+
blobs.set(blob.id, stringToBuffer(blob.content, blob.encoding ?? "utf-8"));
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
const flatSummaryTree = flatSummary.trees?.[0];
|
|
74
|
+
const sequenceNumber = flatSummaryTree?.sequenceNumber;
|
|
75
|
+
const snapshotTree = buildHierarchy(flatSummaryTree, treePrefixToRemove);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
blobs,
|
|
79
|
+
snapshotTree,
|
|
80
|
+
sequenceNumber,
|
|
81
|
+
id: flatSummary.id,
|
|
82
|
+
};
|
|
83
|
+
}
|