@fluidframework/routerlicious-driver 1.2.2 → 2.0.0-internal.1.0.0.82159
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/dist/deltaStorageService.d.ts +5 -3
- package/dist/deltaStorageService.d.ts.map +1 -1
- package/dist/deltaStorageService.js +9 -5
- package/dist/deltaStorageService.js.map +1 -1
- package/dist/documentService.d.ts +21 -5
- package/dist/documentService.d.ts.map +1 -1
- package/dist/documentService.js +92 -19
- package/dist/documentService.js.map +1 -1
- package/dist/documentServiceFactory.d.ts +3 -2
- package/dist/documentServiceFactory.d.ts.map +1 -1
- package/dist/documentServiceFactory.js +18 -23
- 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 +5 -5
- package/dist/documentStorageService.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/restWrapper.js +2 -1
- package/dist/restWrapper.js.map +1 -1
- package/dist/shreddedSummaryDocumentStorageService.d.ts +3 -2
- package/dist/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
- package/dist/shreddedSummaryDocumentStorageService.js +21 -7
- package/dist/shreddedSummaryDocumentStorageService.js.map +1 -1
- package/dist/wholeSummaryDocumentStorageService.d.ts +4 -3
- package/dist/wholeSummaryDocumentStorageService.d.ts.map +1 -1
- package/dist/wholeSummaryDocumentStorageService.js +23 -10
- package/dist/wholeSummaryDocumentStorageService.js.map +1 -1
- package/lib/deltaStorageService.d.ts +5 -3
- package/lib/deltaStorageService.d.ts.map +1 -1
- package/lib/deltaStorageService.js +9 -5
- package/lib/deltaStorageService.js.map +1 -1
- package/lib/documentService.d.ts +21 -5
- package/lib/documentService.d.ts.map +1 -1
- package/lib/documentService.js +92 -19
- package/lib/documentService.js.map +1 -1
- package/lib/documentServiceFactory.d.ts +3 -2
- package/lib/documentServiceFactory.d.ts.map +1 -1
- package/lib/documentServiceFactory.js +18 -23
- 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 +5 -5
- package/lib/documentStorageService.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/restWrapper.js +2 -1
- package/lib/restWrapper.js.map +1 -1
- package/lib/shreddedSummaryDocumentStorageService.d.ts +3 -2
- package/lib/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
- package/lib/shreddedSummaryDocumentStorageService.js +21 -7
- package/lib/shreddedSummaryDocumentStorageService.js.map +1 -1
- package/lib/wholeSummaryDocumentStorageService.d.ts +4 -3
- package/lib/wholeSummaryDocumentStorageService.d.ts.map +1 -1
- package/lib/wholeSummaryDocumentStorageService.js +23 -10
- package/lib/wholeSummaryDocumentStorageService.js.map +1 -1
- package/package.json +13 -13
- package/src/deltaStorageService.ts +10 -5
- package/src/documentService.ts +142 -42
- package/src/documentServiceFactory.ts +23 -25
- package/src/documentStorageService.ts +10 -3
- package/src/packageVersion.ts +1 -1
- package/src/restWrapper.ts +1 -1
- package/src/shreddedSummaryDocumentStorageService.ts +27 -13
- package/src/wholeSummaryDocumentStorageService.ts +26 -12
|
@@ -9,7 +9,7 @@ import { PerformanceEvent } from "@fluidframework/telemetry-utils";
|
|
|
9
9
|
import { InMemoryCache } from "./cache";
|
|
10
10
|
const latestSnapshotId = "latest";
|
|
11
11
|
export class WholeSummaryDocumentStorageService {
|
|
12
|
-
constructor(id, manager, logger, policies = {}, driverPolicies, blobCache = new InMemoryCache(), snapshotTreeCache = new InMemoryCache(), noCacheGitManager) {
|
|
12
|
+
constructor(id, manager, logger, policies = {}, driverPolicies, blobCache = new InMemoryCache(), snapshotTreeCache = new InMemoryCache(), noCacheGitManager, getStorageManager = async (disableCache) => disableCache && this.noCacheGitManager !== undefined ? this.noCacheGitManager : this.manager) {
|
|
13
13
|
this.id = id;
|
|
14
14
|
this.manager = manager;
|
|
15
15
|
this.logger = logger;
|
|
@@ -18,12 +18,16 @@ export class WholeSummaryDocumentStorageService {
|
|
|
18
18
|
this.blobCache = blobCache;
|
|
19
19
|
this.snapshotTreeCache = snapshotTreeCache;
|
|
20
20
|
this.noCacheGitManager = noCacheGitManager;
|
|
21
|
+
this.getStorageManager = getStorageManager;
|
|
21
22
|
this.firstVersionsCall = true;
|
|
22
|
-
this.summaryUploadManager = new WholeSummaryUploadManager(manager);
|
|
23
23
|
}
|
|
24
24
|
get repositoryUrl() {
|
|
25
25
|
return "";
|
|
26
26
|
}
|
|
27
|
+
async getSummaryUploadManager() {
|
|
28
|
+
const manager = await this.getStorageManager();
|
|
29
|
+
return new WholeSummaryUploadManager(manager);
|
|
30
|
+
}
|
|
27
31
|
async getVersions(versionId, count) {
|
|
28
32
|
var _a;
|
|
29
33
|
if (versionId !== this.id && versionId !== null) {
|
|
@@ -51,7 +55,10 @@ export class WholeSummaryDocumentStorageService {
|
|
|
51
55
|
eventName: "getVersions",
|
|
52
56
|
versionId: id,
|
|
53
57
|
count,
|
|
54
|
-
}, async () =>
|
|
58
|
+
}, async () => {
|
|
59
|
+
const manager = await this.getStorageManager();
|
|
60
|
+
return manager.getCommits(id, count);
|
|
61
|
+
});
|
|
55
62
|
return commits.map((commit) => ({
|
|
56
63
|
date: commit.commit.author.date,
|
|
57
64
|
id: commit.sha,
|
|
@@ -78,7 +85,8 @@ export class WholeSummaryDocumentStorageService {
|
|
|
78
85
|
eventName: "readBlob",
|
|
79
86
|
blobId,
|
|
80
87
|
}, async (event) => {
|
|
81
|
-
const
|
|
88
|
+
const manager = await this.getStorageManager();
|
|
89
|
+
const response = await manager.getBlob(blobId);
|
|
82
90
|
event.end({
|
|
83
91
|
size: response.size,
|
|
84
92
|
});
|
|
@@ -91,7 +99,11 @@ export class WholeSummaryDocumentStorageService {
|
|
|
91
99
|
async uploadSummaryWithContext(summary, context) {
|
|
92
100
|
const summaryHandle = await PerformanceEvent.timedExecAsync(this.logger, {
|
|
93
101
|
eventName: "uploadSummaryWithContext",
|
|
94
|
-
}, async () => {
|
|
102
|
+
}, async () => {
|
|
103
|
+
var _a;
|
|
104
|
+
const summaryUploadManager = await this.getSummaryUploadManager();
|
|
105
|
+
return summaryUploadManager.writeSummaryTree(summary, (_a = context.ackHandle) !== null && _a !== void 0 ? _a : "", "channel");
|
|
106
|
+
});
|
|
95
107
|
return summaryHandle;
|
|
96
108
|
}
|
|
97
109
|
async downloadSummary(summaryHandle) {
|
|
@@ -100,7 +112,8 @@ export class WholeSummaryDocumentStorageService {
|
|
|
100
112
|
treeId: summaryHandle.handle,
|
|
101
113
|
}, async (event) => {
|
|
102
114
|
var _a;
|
|
103
|
-
const
|
|
115
|
+
const manager = await this.getStorageManager();
|
|
116
|
+
const response = await manager.getSummary(summaryHandle.handle);
|
|
104
117
|
event.end({
|
|
105
118
|
size: (_a = response.trees[0]) === null || _a === void 0 ? void 0 : _a.entries.length,
|
|
106
119
|
});
|
|
@@ -115,7 +128,8 @@ export class WholeSummaryDocumentStorageService {
|
|
|
115
128
|
eventName: "createBlob",
|
|
116
129
|
size: uint8ArrayFile.length,
|
|
117
130
|
}, async (event) => {
|
|
118
|
-
const
|
|
131
|
+
const manager = await this.getStorageManager();
|
|
132
|
+
const response = await manager.createBlob(Uint8ArrayToString(uint8ArrayFile, "base64"), "base64").then((r) => ({ id: r.sha, url: r.url }));
|
|
119
133
|
event.end({
|
|
120
134
|
blobId: response.id,
|
|
121
135
|
});
|
|
@@ -132,9 +146,8 @@ export class WholeSummaryDocumentStorageService {
|
|
|
132
146
|
treeId: versionId,
|
|
133
147
|
}, async (event) => {
|
|
134
148
|
var _a;
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
await this.manager.getSummary(versionId);
|
|
149
|
+
const manager = await this.getStorageManager(disableCache);
|
|
150
|
+
const response = await manager.getSummary(versionId);
|
|
138
151
|
event.end({
|
|
139
152
|
size: (_a = response.trees[0]) === null || _a === void 0 ? void 0 : _a.entries.length,
|
|
140
153
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wholeSummaryDocumentStorageService.js","sourceRoot":"","sources":["../src/wholeSummaryDocumentStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACH,MAAM,EACN,cAAc,EACd,kBAAkB,GACrB,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EACH,oCAAoC,GACtC,MAAM,8BAA8B,CAAC;AAQvC,OAAO,EACH,6CAA6C,EAG7C,yBAAyB,GAC5B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAU,aAAa,EAAE,MAAM,SAAS,CAAC;AAIhD,MAAM,gBAAgB,GAAW,QAAQ,CAAC;AAE1C,MAAM,OAAO,kCAAkC;IAQ3C,YACuB,EAAU,EACV,OAAmB,EACnB,MAAwB,EAC3B,WAA4C,EAAE,EAC7C,cAA6C,EAC7C,YAAqC,IAAI,aAAa,EAAE,EACxD,oBAAkD,IAAI,aAAa,EAAE,EACnE,iBAA8B;QAP9B,OAAE,GAAF,EAAE,CAAQ;QACV,YAAO,GAAP,OAAO,CAAY;QACnB,WAAM,GAAN,MAAM,CAAkB;QAC3B,aAAQ,GAAR,QAAQ,CAAsC;QAC7C,mBAAc,GAAd,cAAc,CAA+B;QAC7C,cAAS,GAAT,SAAS,CAA+C;QACxD,sBAAiB,GAAjB,iBAAiB,CAAoD;QACnE,sBAAiB,GAAjB,iBAAiB,CAAa;QAd7C,sBAAiB,GAAY,IAAI,CAAC;QAetC,IAAI,CAAC,oBAAoB,GAAG,IAAI,yBAAyB,CAAC,OAAO,CAAC,CAAC;IACvE,CAAC;IAdD,IAAW,aAAa;QACpB,OAAO,EAAE,CAAC;IACd,CAAC;IAcM,KAAK,CAAC,WAAW,CAAC,SAAwB,EAAE,KAAa;;QAC5D,IAAI,SAAS,KAAK,IAAI,CAAC,EAAE,IAAI,SAAS,KAAK,IAAI,EAAE;YAC7C,4FAA4F;YAC5F,OAAO,CAAC;oBACJ,EAAE,EAAE,SAAS;oBACb,MAAM,EAAE,SAAU;iBACrB,CAAC,CAAC;SACN;QACD,gGAAgG;QAChG,qDAAqD;QACrD,IAAI,IAAI,CAAC,iBAAiB,IAAI,KAAK,KAAK,CAAC,EAAE;YACvC,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC;YAC/B,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,CAAC,CAAA,MAAA,IAAI,CAAC,cAAc,0CAAE,eAAe,CAAA,CAAC,CAAC;gBACrE,MAAM,IAAI,CAAC,yBAAyB,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC,CAAC;gBAC/D,MAAM,IAAI,CAAC,yBAAyB,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;YACjE,OAAO,CAAC;oBACJ,EAAE,EAAE,GAAG;oBACP,MAAM,EAAE,YAAY,CAAC,EAAG;iBAC3B,CAAC,CAAC;SACN;QAED,+DAA+D;QAC/D,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,cAAc,CACjD,IAAI,CAAC,MAAM,EACX;YACI,SAAS,EAAE,aAAa;YACxB,SAAS,EAAE,EAAE;YACb,KAAK;SACR,EACD,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,CACjD,CAAC;QACF,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI;YAC/B,EAAE,EAAE,MAAM,CAAC,GAAG;YACd,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG;SACjC,CAAC,CAAC,CAAC;IACR,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,OAAkB;QAC3C,IAAI,cAAc,GAAG,OAAO,CAAC;QAC7B,IAAI,CAAC,cAAc,EAAE;YACjB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YACpD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;gBACvB,OAAO,IAAI,CAAC;aACf;YAED,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;SAChC;QAED,OAAO,CAAC,MAAM,IAAI,CAAC,yBAAyB,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;IAClF,CAAC;IAEM,KAAK,CAAC,QAAQ,CAAC,MAAc;QAChC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,UAAU,KAAK,SAAS,EAAE;YAC1B,OAAO,UAAU,CAAC;SACrB;QAED,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,cAAc,CAC9C,IAAI,CAAC,MAAM,EACX;YACI,SAAS,EAAE,UAAU;YACrB,MAAM;SACT,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;YACZ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACpD,KAAK,CAAC,GAAG,CAAC;gBACN,IAAI,EAAE,QAAQ,CAAC,IAAI;aACtB,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC;QACpB,CAAC,CACJ,CAAC;QACF,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEhE,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAEhD,OAAO,WAAW,CAAC;IACvB,CAAC;IAEM,KAAK,CAAC,wBAAwB,CAAC,OAAqB,EAAE,OAAwB;QACjF,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,cAAc,CACvD,IAAI,CAAC,MAAM,EACX;YACI,SAAS,EAAE,0BAA0B;SACxC,EACD,KAAK,IAAI,EAAE,WAAC,OAAA,IAAI,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAA,OAAO,CAAC,SAAS,mCAAI,EAAE,EAAE,SAAS,CAAC,CAAA,EAAA,CACtG,CAAC;QACF,OAAO,aAAa,CAAC;IACzB,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,aAA6B;QACtD,MAAM,gBAAgB,GAAG,MAAM,gBAAgB,CAAC,cAAc,CAC1D,IAAI,CAAC,MAAM,EACX;YACI,SAAS,EAAE,qBAAqB;YAChC,MAAM,EAAE,aAAa,CAAC,MAAM;SAC/B,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;;YACZ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YACrE,KAAK,CAAC,GAAG,CAAC;gBACN,IAAI,EAAE,MAAA,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,0CAAE,OAAO,CAAC,MAAM;aAC1C,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC;QACpB,CAAC,CACJ,CAAC;QAEF,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,6CAA6C,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;QACpG,OAAO,oCAAoC,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IACrE,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,IAAqB;QACzC,MAAM,cAAc,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;QAC5C,OAAO,gBAAgB,CAAC,cAAc,CAClC,IAAI,CAAC,MAAM,EACX;YACI,SAAS,EAAE,YAAY;YACvB,IAAI,EAAE,cAAc,CAAC,MAAM;SAC9B,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;YACZ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAC1C,kBAAkB,CACd,cAAc,EAAE,QAAQ,CAAC,EAC7B,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACvD,KAAK,CAAC,GAAG,CAAC;gBACN,MAAM,EAAE,QAAQ,CAAC,EAAE;aACtB,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC;QACpB,CAAC,CACJ,CAAC;IACN,CAAC;IAEO,KAAK,CAAC,yBAAyB,CAAC,SAAiB,EAAE,YAAsB;QAC7E,MAAM,yBAAyB,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC9E,IAAI,yBAAyB,KAAK,SAAS,EAAE;YACzC,OAAO,EAAE,EAAE,EAAE,yBAAyB,CAAC,EAAE,EAAE,YAAY,EAAE,yBAAyB,CAAC,YAAY,EAAE,CAAC;SACrG;QAED,MAAM,gBAAgB,GAAG,MAAM,gBAAgB,CAAC,cAAc,CAC1D,IAAI,CAAC,MAAM,EACX;YACI,SAAS,EAAE,qBAAqB;YAChC,MAAM,EAAE,SAAS;SACpB,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;;YACZ,MAAM,QAAQ,GAAG,YAAY,IAAI,IAAI,CAAC,iBAAiB,KAAK,SAAS,CAAC,CAAC;gBACnE,MAAM,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;gBACpD,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YAC7C,KAAK,CAAC,GAAG,CAAC;gBACN,IAAI,EAAE,MAAA,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,0CAAE,OAAO,CAAC,MAAM;aAC1C,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC;QACpB,CAAC,CACJ,CAAC;QACF,MAAM,sBAAsB,GAAG,6CAA6C,CAAC,gBAAgB,CAAC,CAAC;QAC/F,MAAM,kBAAkB,GAAW,gBAAgB,CAAC,EAAE,CAAC;QACvD,MAAM,cAAc,GAAG,sBAAsB,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9D,MAAM,CAAC,cAAc,KAAK,SAAS,EAAE,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACpF,MAAM,mBAAmB,GAAG,EAAE,EAAE,EAAE,kBAAkB,EAAE,YAAY,EAAE,sBAAsB,CAAC,YAAY,EAAE,CAAC;QAE1G,MAAM,OAAO,GAAmB;YAC5B,IAAI,CAAC,iBAAiB,CAAC,GAAG,CACtB,cAAc,EACd,mBAAmB,CACtB;YACD,IAAI,CAAC,aAAa,CAAC,sBAAsB,CAAC,KAAK,CAAC;SACnD,CAAC;QACF,IAAI,cAAc,KAAK,SAAS,EAAE;YAC9B,sGAAsG;YACtG,4GAA4G;YAC5G,0GAA0G;YAC1G,wBAAwB;YACxB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CACnC,SAAS,EACT,mBAAmB,CACtB,CAAC,CAAC;SACN;QAED,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE3B,OAAO,mBAAmB,CAAC;IAC/B,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,KAA+B;QACvD,MAAM,cAAc,GAAoB,EAAE,CAAC;QAC3C,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YACxB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACtC,CAAC;CACJ","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport {\n assert,\n stringToBuffer,\n Uint8ArrayToString,\n} from \"@fluidframework/common-utils\";\nimport {\n IDocumentStorageService,\n ISummaryContext,\n IDocumentStorageServicePolicies,\n} from \"@fluidframework/driver-definitions\";\nimport {\n convertSnapshotAndBlobsToSummaryTree,\n } from \"@fluidframework/driver-utils\";\nimport {\n ICreateBlobResponse,\n ISnapshotTree,\n ISummaryHandle,\n ISummaryTree,\n IVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n convertWholeFlatSummaryToSnapshotTreeAndBlobs,\n GitManager,\n ISummaryUploadManager,\n WholeSummaryUploadManager,\n} from \"@fluidframework/server-services-client\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { ICache, InMemoryCache } from \"./cache\";\nimport { ISnapshotTreeVersion } from \"./definitions\";\nimport { IRouterliciousDriverPolicies } from \"./policies\";\n\nconst latestSnapshotId: string = \"latest\";\n\nexport class WholeSummaryDocumentStorageService implements IDocumentStorageService {\n private readonly summaryUploadManager: ISummaryUploadManager;\n private firstVersionsCall: boolean = true;\n\n public get repositoryUrl(): string {\n return \"\";\n }\n\n constructor(\n protected readonly id: string,\n protected readonly manager: GitManager,\n protected readonly logger: ITelemetryLogger,\n public readonly policies: IDocumentStorageServicePolicies = {},\n private readonly driverPolicies?: IRouterliciousDriverPolicies,\n private readonly blobCache: ICache<ArrayBufferLike> = new InMemoryCache(),\n private readonly snapshotTreeCache: ICache<ISnapshotTreeVersion> = new InMemoryCache(),\n protected readonly noCacheGitManager?: GitManager) {\n this.summaryUploadManager = new WholeSummaryUploadManager(manager);\n }\n\n public async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n if (versionId !== this.id && versionId !== null) {\n // Blobs/Trees in this scenario will never have multiple versions, so return versionId as is\n return [{\n id: versionId,\n treeId: undefined!,\n }];\n }\n // If this is the first versions call for the document, we know we will want the latest summary.\n // Fetch latest summary, cache it, and return its id.\n if (this.firstVersionsCall && count === 1) {\n this.firstVersionsCall = false;\n const { id: _id, snapshotTree } = !this.driverPolicies?.enableDiscovery ?\n await this.fetchAndCacheSnapshotTree(latestSnapshotId, false) :\n await this.fetchAndCacheSnapshotTree(latestSnapshotId, true);\n return [{\n id: _id,\n treeId: snapshotTree.id!,\n }];\n }\n\n // Otherwise, get the latest version of the document as normal.\n const id = versionId ? versionId : this.id;\n const commits = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getVersions\",\n versionId: id,\n count,\n },\n async () => this.manager.getCommits(id, count),\n );\n return commits.map((commit) => ({\n date: commit.commit.author.date,\n id: commit.sha,\n treeId: commit.commit.tree.sha,\n }));\n }\n\n public async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n let requestVersion = version;\n if (!requestVersion) {\n const versions = await this.getVersions(this.id, 1);\n if (versions.length === 0) {\n return null;\n }\n\n requestVersion = versions[0];\n }\n\n return (await this.fetchAndCacheSnapshotTree(requestVersion.id)).snapshotTree;\n }\n\n public async readBlob(blobId: string): Promise<ArrayBufferLike> {\n const cachedBlob = await this.blobCache.get(blobId);\n if (cachedBlob !== undefined) {\n return cachedBlob;\n }\n\n const blob = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"readBlob\",\n blobId,\n },\n async (event) => {\n const response = await this.manager.getBlob(blobId);\n event.end({\n size: response.size,\n });\n return response;\n },\n );\n const bufferValue = stringToBuffer(blob.content, blob.encoding);\n\n await this.blobCache.put(blob.sha, bufferValue);\n\n return bufferValue;\n }\n\n public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {\n const summaryHandle = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"uploadSummaryWithContext\",\n },\n async () => this.summaryUploadManager.writeSummaryTree(summary, context.ackHandle ?? \"\", \"channel\"),\n );\n return summaryHandle;\n }\n\n public async downloadSummary(summaryHandle: ISummaryHandle): Promise<ISummaryTree> {\n const wholeFlatSummary = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getWholeFlatSummary\",\n treeId: summaryHandle.handle,\n },\n async (event) => {\n const response = await this.manager.getSummary(summaryHandle.handle);\n event.end({\n size: response.trees[0]?.entries.length,\n });\n return response;\n },\n );\n\n const { blobs, snapshotTree } = convertWholeFlatSummaryToSnapshotTreeAndBlobs(wholeFlatSummary, \"\");\n return convertSnapshotAndBlobsToSummaryTree(snapshotTree, blobs);\n }\n\n public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n const uint8ArrayFile = new Uint8Array(file);\n return PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"createBlob\",\n size: uint8ArrayFile.length,\n },\n async (event) => {\n const response = await this.manager.createBlob(\n Uint8ArrayToString(\n uint8ArrayFile, \"base64\"),\n \"base64\").then((r) => ({ id: r.sha, url: r.url }));\n event.end({\n blobId: response.id,\n });\n return response;\n },\n );\n }\n\n private async fetchAndCacheSnapshotTree(versionId: string, disableCache?: boolean): Promise<ISnapshotTreeVersion> {\n const cachedSnapshotTreeVersion = await this.snapshotTreeCache.get(versionId);\n if (cachedSnapshotTreeVersion !== undefined) {\n return { id: cachedSnapshotTreeVersion.id, snapshotTree: cachedSnapshotTreeVersion.snapshotTree };\n }\n\n const wholeFlatSummary = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getWholeFlatSummary\",\n treeId: versionId,\n },\n async (event) => {\n const response = disableCache && this.noCacheGitManager !== undefined ?\n await this.noCacheGitManager.getSummary(versionId) :\n await this.manager.getSummary(versionId);\n event.end({\n size: response.trees[0]?.entries.length,\n });\n return response;\n },\n );\n const normalizedWholeSummary = convertWholeFlatSummaryToSnapshotTreeAndBlobs(wholeFlatSummary);\n const wholeFlatSummaryId: string = wholeFlatSummary.id;\n const snapshotTreeId = normalizedWholeSummary.snapshotTree.id;\n assert(snapshotTreeId !== undefined, 0x275 /* \"Root tree should contain the id\" */);\n const snapshotTreeVersion = { id: wholeFlatSummaryId, snapshotTree: normalizedWholeSummary.snapshotTree };\n\n const cachePs: Promise<any>[] = [\n this.snapshotTreeCache.put(\n snapshotTreeId,\n snapshotTreeVersion,\n ),\n this.initBlobCache(normalizedWholeSummary.blobs),\n ];\n if (snapshotTreeId !== versionId) {\n // versionId could be \"latest\". When summarizer checks cache for \"latest\", we want it to be available.\n // TODO: For in-memory cache, <latest,snapshotTree> will be a shared pointer with <snapshotId,snapshotTree>,\n // However, for something like Redis, this will cache the same value twice. Alternatively, could we simply\n // cache with versionId?\n cachePs.push(this.snapshotTreeCache.put(\n versionId,\n snapshotTreeVersion,\n ));\n }\n\n await Promise.all(cachePs);\n\n return snapshotTreeVersion;\n }\n\n private async initBlobCache(blobs: Map<string, ArrayBuffer>): Promise<void> {\n const blobCachePutPs: Promise<void>[] = [];\n blobs.forEach((value, id) => {\n blobCachePutPs.push(this.blobCache.put(id, value));\n });\n await Promise.all(blobCachePutPs);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"wholeSummaryDocumentStorageService.js","sourceRoot":"","sources":["../src/wholeSummaryDocumentStorageService.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport {\n assert,\n stringToBuffer,\n Uint8ArrayToString,\n} from \"@fluidframework/common-utils\";\nimport {\n IDocumentStorageService,\n ISummaryContext,\n IDocumentStorageServicePolicies,\n} from \"@fluidframework/driver-definitions\";\nimport {\n convertSnapshotAndBlobsToSummaryTree,\n} from \"@fluidframework/driver-utils\";\nimport {\n ICreateBlobResponse,\n ISnapshotTree,\n ISummaryHandle,\n ISummaryTree,\n IVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport {\n convertWholeFlatSummaryToSnapshotTreeAndBlobs,\n GitManager,\n ISummaryUploadManager,\n WholeSummaryUploadManager,\n} from \"@fluidframework/server-services-client\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { ICache, InMemoryCache } from \"./cache\";\nimport { ISnapshotTreeVersion } from \"./definitions\";\nimport { IRouterliciousDriverPolicies } from \"./policies\";\n\nconst latestSnapshotId: string = \"latest\";\n\nexport class WholeSummaryDocumentStorageService implements IDocumentStorageService {\n private firstVersionsCall: boolean = true;\n\n public get repositoryUrl(): string {\n return \"\";\n }\n\n private async getSummaryUploadManager(): Promise<ISummaryUploadManager> {\n const manager = await this.getStorageManager();\n return new WholeSummaryUploadManager(manager);\n }\n\n constructor(\n protected readonly id: string,\n protected readonly manager: GitManager,\n protected readonly logger: ITelemetryLogger,\n public readonly policies: IDocumentStorageServicePolicies = {},\n private readonly driverPolicies?: IRouterliciousDriverPolicies,\n private readonly blobCache: ICache<ArrayBufferLike> = new InMemoryCache(),\n private readonly snapshotTreeCache: ICache<ISnapshotTreeVersion> = new InMemoryCache(),\n private readonly noCacheGitManager?: GitManager,\n private readonly getStorageManager: (disableCache?: boolean) => Promise<GitManager> = async (disableCache) =>\n disableCache && this.noCacheGitManager !== undefined ? this.noCacheGitManager : this.manager,\n ) {\n }\n\n public async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n if (versionId !== this.id && versionId !== null) {\n // Blobs/Trees in this scenario will never have multiple versions, so return versionId as is\n return [{\n id: versionId,\n treeId: undefined!,\n }];\n }\n // If this is the first versions call for the document, we know we will want the latest summary.\n // Fetch latest summary, cache it, and return its id.\n if (this.firstVersionsCall && count === 1) {\n this.firstVersionsCall = false;\n const { id: _id, snapshotTree } = !this.driverPolicies?.enableDiscovery ?\n await this.fetchAndCacheSnapshotTree(latestSnapshotId, false) :\n await this.fetchAndCacheSnapshotTree(latestSnapshotId, true);\n return [{\n id: _id,\n treeId: snapshotTree.id!,\n }];\n }\n\n // Otherwise, get the latest version of the document as normal.\n const id = versionId ? versionId : this.id;\n const commits = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getVersions\",\n versionId: id,\n count,\n },\n async () => {\n const manager = await this.getStorageManager();\n return manager.getCommits(id, count);\n },\n );\n return commits.map((commit) => ({\n date: commit.commit.author.date,\n id: commit.sha,\n treeId: commit.commit.tree.sha,\n }));\n }\n\n public async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n let requestVersion = version;\n if (!requestVersion) {\n const versions = await this.getVersions(this.id, 1);\n if (versions.length === 0) {\n return null;\n }\n\n requestVersion = versions[0];\n }\n\n return (await this.fetchAndCacheSnapshotTree(requestVersion.id)).snapshotTree;\n }\n\n public async readBlob(blobId: string): Promise<ArrayBufferLike> {\n const cachedBlob = await this.blobCache.get(blobId);\n if (cachedBlob !== undefined) {\n return cachedBlob;\n }\n\n const blob = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"readBlob\",\n blobId,\n },\n async (event) => {\n const manager = await this.getStorageManager();\n const response = await manager.getBlob(blobId);\n event.end({\n size: response.size,\n });\n return response;\n },\n );\n const bufferValue = stringToBuffer(blob.content, blob.encoding);\n\n await this.blobCache.put(blob.sha, bufferValue);\n\n return bufferValue;\n }\n\n public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {\n const summaryHandle = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"uploadSummaryWithContext\",\n },\n async () => {\n const summaryUploadManager = await this.getSummaryUploadManager();\n return summaryUploadManager.writeSummaryTree(summary, context.ackHandle ?? \"\", \"channel\");\n },\n );\n return summaryHandle;\n }\n\n public async downloadSummary(summaryHandle: ISummaryHandle): Promise<ISummaryTree> {\n const wholeFlatSummary = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getWholeFlatSummary\",\n treeId: summaryHandle.handle,\n },\n async (event) => {\n const manager = await this.getStorageManager();\n const response = await manager.getSummary(summaryHandle.handle);\n event.end({\n size: response.trees[0]?.entries.length,\n });\n return response;\n },\n );\n\n const { blobs, snapshotTree } = convertWholeFlatSummaryToSnapshotTreeAndBlobs(wholeFlatSummary, \"\");\n return convertSnapshotAndBlobsToSummaryTree(snapshotTree, blobs);\n }\n\n public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n const uint8ArrayFile = new Uint8Array(file);\n return PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"createBlob\",\n size: uint8ArrayFile.length,\n },\n async (event) => {\n const manager = await this.getStorageManager();\n const response = await manager.createBlob(\n Uint8ArrayToString(\n uint8ArrayFile, \"base64\"),\n \"base64\").then((r) => ({ id: r.sha, url: r.url }));\n event.end({\n blobId: response.id,\n });\n return response;\n },\n );\n }\n\n private async fetchAndCacheSnapshotTree(versionId: string, disableCache?: boolean): Promise<ISnapshotTreeVersion> {\n const cachedSnapshotTreeVersion = await this.snapshotTreeCache.get(versionId);\n if (cachedSnapshotTreeVersion !== undefined) {\n return { id: cachedSnapshotTreeVersion.id, snapshotTree: cachedSnapshotTreeVersion.snapshotTree };\n }\n\n const wholeFlatSummary = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getWholeFlatSummary\",\n treeId: versionId,\n },\n async (event) => {\n const manager = await this.getStorageManager(disableCache);\n const response = await manager.getSummary(versionId);\n event.end({\n size: response.trees[0]?.entries.length,\n });\n return response;\n },\n );\n const normalizedWholeSummary = convertWholeFlatSummaryToSnapshotTreeAndBlobs(wholeFlatSummary);\n const wholeFlatSummaryId: string = wholeFlatSummary.id;\n const snapshotTreeId = normalizedWholeSummary.snapshotTree.id;\n assert(snapshotTreeId !== undefined, 0x275 /* \"Root tree should contain the id\" */);\n const snapshotTreeVersion = { id: wholeFlatSummaryId, snapshotTree: normalizedWholeSummary.snapshotTree };\n\n const cachePs: Promise<any>[] = [\n this.snapshotTreeCache.put(\n snapshotTreeId,\n snapshotTreeVersion,\n ),\n this.initBlobCache(normalizedWholeSummary.blobs),\n ];\n if (snapshotTreeId !== versionId) {\n // versionId could be \"latest\". When summarizer checks cache for \"latest\", we want it to be available.\n // TODO: For in-memory cache, <latest,snapshotTree> will be a shared pointer with <snapshotId,snapshotTree>,\n // However, for something like Redis, this will cache the same value twice. Alternatively, could we simply\n // cache with versionId?\n cachePs.push(this.snapshotTreeCache.put(\n versionId,\n snapshotTreeVersion,\n ));\n }\n\n await Promise.all(cachePs);\n\n return snapshotTreeVersion;\n }\n\n private async initBlobCache(blobs: Map<string, ArrayBuffer>): Promise<void> {\n const blobCachePutPs: Promise<void>[] = [];\n blobs.forEach((value, id) => {\n blobCachePutPs.push(this.blobCache.put(id, value));\n });\n await Promise.all(blobCachePutPs);\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/routerlicious-driver",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "2.0.0-internal.1.0.0.82159",
|
|
4
4
|
"description": "Socket.IO + Git implementation of Fluid service API",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -62,14 +62,14 @@
|
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
64
64
|
"@fluidframework/common-utils": "^0.32.1",
|
|
65
|
-
"@fluidframework/driver-base": "
|
|
66
|
-
"@fluidframework/driver-definitions": "
|
|
67
|
-
"@fluidframework/driver-utils": "
|
|
68
|
-
"@fluidframework/gitresources": "^0.
|
|
69
|
-
"@fluidframework/protocol-base": "^0.
|
|
70
|
-
"@fluidframework/protocol-definitions": "^0.
|
|
71
|
-
"@fluidframework/server-services-client": "^0.
|
|
72
|
-
"@fluidframework/telemetry-utils": "
|
|
65
|
+
"@fluidframework/driver-base": "2.0.0-internal.1.0.0.82159",
|
|
66
|
+
"@fluidframework/driver-definitions": "2.0.0-internal.1.0.0.82159",
|
|
67
|
+
"@fluidframework/driver-utils": "2.0.0-internal.1.0.0.82159",
|
|
68
|
+
"@fluidframework/gitresources": "^0.1037.1000-0",
|
|
69
|
+
"@fluidframework/protocol-base": "^0.1037.1000-0",
|
|
70
|
+
"@fluidframework/protocol-definitions": "^0.1029.1000-0",
|
|
71
|
+
"@fluidframework/server-services-client": "^0.1037.1000-0",
|
|
72
|
+
"@fluidframework/telemetry-utils": "2.0.0-internal.1.0.0.82159",
|
|
73
73
|
"cross-fetch": "^3.1.5",
|
|
74
74
|
"json-stringify-safe": "5.0.1",
|
|
75
75
|
"querystring": "^0.2.0",
|
|
@@ -79,10 +79,10 @@
|
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@fluidframework/build-common": "^0.24.0",
|
|
82
|
-
"@fluidframework/build-tools": "^0.
|
|
82
|
+
"@fluidframework/build-tools": "^0.3.0-0",
|
|
83
83
|
"@fluidframework/eslint-config-fluid": "^0.28.2000",
|
|
84
|
-
"@fluidframework/mocha-test-setup": "
|
|
85
|
-
"@fluidframework/routerlicious-driver-previous": "npm:@fluidframework/routerlicious-driver
|
|
84
|
+
"@fluidframework/mocha-test-setup": "2.0.0-internal.1.0.0.82159",
|
|
85
|
+
"@fluidframework/routerlicious-driver-previous": "npm:@fluidframework/routerlicious-driver@^1.0.0",
|
|
86
86
|
"@microsoft/api-extractor": "^7.22.2",
|
|
87
87
|
"@rushstack/eslint-config": "^2.5.1",
|
|
88
88
|
"@types/mocha": "^9.1.1",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"typescript-formatter": "7.1.0"
|
|
103
103
|
},
|
|
104
104
|
"typeValidation": {
|
|
105
|
-
"version": "
|
|
105
|
+
"version": "2.0.0",
|
|
106
106
|
"broken": {}
|
|
107
107
|
}
|
|
108
108
|
}
|
|
@@ -26,7 +26,7 @@ export class DocumentDeltaStorageService implements IDocumentDeltaStorageService
|
|
|
26
26
|
constructor(
|
|
27
27
|
private readonly tenantId: string,
|
|
28
28
|
private readonly id: string,
|
|
29
|
-
private readonly
|
|
29
|
+
private readonly deltaStorageService: IDeltaStorageService,
|
|
30
30
|
private readonly documentStorageService: DocumentStorageService) {
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -70,7 +70,7 @@ export class DocumentDeltaStorageService implements IDocumentDeltaStorageService
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
return this.
|
|
73
|
+
return this.deltaStorageService.get(this.tenantId, this.id, from, to);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
@@ -81,7 +81,10 @@ export class DeltaStorageService implements IDeltaStorageService {
|
|
|
81
81
|
constructor(
|
|
82
82
|
private readonly url: string,
|
|
83
83
|
private readonly restWrapper: RestWrapper,
|
|
84
|
-
private readonly logger: ITelemetryLogger
|
|
84
|
+
private readonly logger: ITelemetryLogger,
|
|
85
|
+
private readonly getRestWrapper: () => Promise<RestWrapper> = async () => this.restWrapper,
|
|
86
|
+
private readonly getDeltaStorageUrl: () => string = () => this.url,
|
|
87
|
+
) {
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
public async get(
|
|
@@ -98,8 +101,10 @@ export class DeltaStorageService implements IDeltaStorageService {
|
|
|
98
101
|
to,
|
|
99
102
|
},
|
|
100
103
|
async (event) => {
|
|
101
|
-
const
|
|
102
|
-
|
|
104
|
+
const restWrapper = await this.getRestWrapper();
|
|
105
|
+
const url = this.getDeltaStorageUrl();
|
|
106
|
+
const response = await restWrapper.get<ISequencedDocumentMessage[]>(
|
|
107
|
+
url,
|
|
103
108
|
{ from: from - 1, to });
|
|
104
109
|
event.end({
|
|
105
110
|
count: response.length,
|
package/src/documentService.ts
CHANGED
|
@@ -7,8 +7,9 @@ import { assert } from "@fluidframework/common-utils";
|
|
|
7
7
|
import * as api from "@fluidframework/driver-definitions";
|
|
8
8
|
import { RateLimiter } from "@fluidframework/driver-utils";
|
|
9
9
|
import { IClient } from "@fluidframework/protocol-definitions";
|
|
10
|
-
import { GitManager, Historian } from "@fluidframework/server-services-client";
|
|
10
|
+
import { GitManager, Historian, RestWrapper } from "@fluidframework/server-services-client";
|
|
11
11
|
import io from "socket.io-client";
|
|
12
|
+
import { PerformanceEvent } from "@fluidframework/telemetry-utils";
|
|
12
13
|
import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
13
14
|
import { DeltaStorageService, DocumentDeltaStorageService } from "./deltaStorageService";
|
|
14
15
|
import { DocumentStorageService } from "./documentStorageService";
|
|
@@ -20,16 +21,35 @@ import { IRouterliciousDriverPolicies } from "./policies";
|
|
|
20
21
|
import { ICache } from "./cache";
|
|
21
22
|
import { ISnapshotTreeVersion } from "./definitions";
|
|
22
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Amount of time between discoveries within which we don't need to rediscover on re-connect.
|
|
26
|
+
* Currently, R11s defines session length at 10 minutes. To avoid any weird unknown edge-cases though,
|
|
27
|
+
* we set the limit to 5 minutes here.
|
|
28
|
+
* In the future, we likely want to retrieve this information from service's "inactive session" definition.
|
|
29
|
+
*/
|
|
30
|
+
const RediscoverAfterTimeSinceDiscoveryMs = 5 * 60000; // 5 minute
|
|
31
|
+
|
|
23
32
|
/**
|
|
24
33
|
* The DocumentService manages the Socket.IO connection and manages routing requests to connected
|
|
25
|
-
* clients
|
|
34
|
+
* clients.
|
|
26
35
|
*/
|
|
27
36
|
export class DocumentService implements api.IDocumentService {
|
|
37
|
+
private lastDiscoveredAt: number = Date.now();
|
|
38
|
+
private discoverP: Promise<void> | undefined;
|
|
39
|
+
|
|
40
|
+
private storageManager: GitManager | undefined;
|
|
41
|
+
private noCacheStorageManager: GitManager | undefined;
|
|
42
|
+
private ordererRestWrapper: RestWrapper | undefined;
|
|
43
|
+
|
|
44
|
+
public get resolvedUrl() {
|
|
45
|
+
return this._resolvedUrl;
|
|
46
|
+
}
|
|
47
|
+
|
|
28
48
|
constructor(
|
|
29
|
-
|
|
49
|
+
private _resolvedUrl: api.IResolvedUrl,
|
|
30
50
|
protected ordererUrl: string,
|
|
31
|
-
private
|
|
32
|
-
private
|
|
51
|
+
private deltaStorageUrl: string,
|
|
52
|
+
private storageUrl: string,
|
|
33
53
|
private readonly logger: ITelemetryLogger,
|
|
34
54
|
protected tokenProvider: ITokenProvider,
|
|
35
55
|
protected tenantId: string,
|
|
@@ -37,6 +57,7 @@ export class DocumentService implements api.IDocumentService {
|
|
|
37
57
|
private readonly driverPolicies: IRouterliciousDriverPolicies,
|
|
38
58
|
private readonly blobCache: ICache<ArrayBufferLike>,
|
|
39
59
|
private readonly snapshotTreeCache: ICache<ISnapshotTreeVersion>,
|
|
60
|
+
private readonly discoverFluidResolvedUrl: () => Promise<api.IFluidResolvedUrl>,
|
|
40
61
|
) {
|
|
41
62
|
}
|
|
42
63
|
|
|
@@ -54,32 +75,45 @@ export class DocumentService implements api.IDocumentService {
|
|
|
54
75
|
return this.documentStorageService;
|
|
55
76
|
}
|
|
56
77
|
|
|
57
|
-
if (this.
|
|
78
|
+
if (this.storageUrl === undefined) {
|
|
58
79
|
return new NullBlobStorageService();
|
|
59
80
|
}
|
|
60
81
|
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
const getStorageManager = async (disableCache?: boolean): Promise<GitManager> => {
|
|
83
|
+
const shouldUpdateDiscoveredSessionInfo = this.shouldUpdateDiscoveredSessionInfo();
|
|
84
|
+
if (shouldUpdateDiscoveredSessionInfo) {
|
|
85
|
+
await this.refreshDiscovery();
|
|
86
|
+
}
|
|
87
|
+
if (!this.storageManager || !this.noCacheStorageManager || shouldUpdateDiscoveredSessionInfo) {
|
|
88
|
+
const rateLimiter = new RateLimiter(this.driverPolicies.maxConcurrentStorageRequests);
|
|
89
|
+
const storageRestWrapper = await RouterliciousStorageRestWrapper.load(
|
|
90
|
+
this.tenantId,
|
|
91
|
+
this.documentId,
|
|
92
|
+
this.tokenProvider,
|
|
93
|
+
this.logger,
|
|
94
|
+
rateLimiter,
|
|
95
|
+
this.driverPolicies.enableRestLess,
|
|
96
|
+
this.storageUrl,
|
|
97
|
+
);
|
|
98
|
+
const historian = new Historian(
|
|
99
|
+
this.storageUrl,
|
|
100
|
+
true,
|
|
101
|
+
false,
|
|
102
|
+
storageRestWrapper);
|
|
103
|
+
this.storageManager = new GitManager(historian);
|
|
104
|
+
const noCacheHistorian = new Historian(
|
|
105
|
+
this.storageUrl,
|
|
106
|
+
true,
|
|
107
|
+
true,
|
|
108
|
+
storageRestWrapper);
|
|
109
|
+
this.noCacheStorageManager = new GitManager(noCacheHistorian);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return disableCache ? this.noCacheStorageManager : this.storageManager;
|
|
113
|
+
};
|
|
114
|
+
// Initialize storageManager and noCacheStorageManager
|
|
115
|
+
const storageManager = await getStorageManager();
|
|
116
|
+
const noCacheStorageManager = await getStorageManager(true);
|
|
83
117
|
const documentStorageServicePolicies: api.IDocumentStorageServicePolicies = {
|
|
84
118
|
caching: this.driverPolicies.enablePrefetch
|
|
85
119
|
? api.LoaderCachingPolicy.Prefetch
|
|
@@ -89,13 +123,14 @@ export class DocumentService implements api.IDocumentService {
|
|
|
89
123
|
|
|
90
124
|
this.documentStorageService = new DocumentStorageService(
|
|
91
125
|
this.documentId,
|
|
92
|
-
|
|
126
|
+
storageManager,
|
|
93
127
|
this.logger,
|
|
94
128
|
documentStorageServicePolicies,
|
|
95
129
|
this.driverPolicies,
|
|
96
130
|
this.blobCache,
|
|
97
131
|
this.snapshotTreeCache,
|
|
98
|
-
|
|
132
|
+
noCacheStorageManager,
|
|
133
|
+
getStorageManager);
|
|
99
134
|
return this.documentStorageService;
|
|
100
135
|
}
|
|
101
136
|
|
|
@@ -108,18 +143,38 @@ export class DocumentService implements api.IDocumentService {
|
|
|
108
143
|
await this.connectToStorage();
|
|
109
144
|
assert(!!this.documentStorageService, 0x0b1 /* "Storage service not initialized" */);
|
|
110
145
|
|
|
111
|
-
const
|
|
112
|
-
|
|
146
|
+
const getRestWrapper = async (): Promise<RestWrapper> => {
|
|
147
|
+
const shouldUpdateDiscoveredSessionInfo = this.shouldUpdateDiscoveredSessionInfo();
|
|
148
|
+
if (shouldUpdateDiscoveredSessionInfo) {
|
|
149
|
+
await this.refreshDiscovery();
|
|
150
|
+
}
|
|
151
|
+
if (!this.ordererRestWrapper || shouldUpdateDiscoveredSessionInfo) {
|
|
152
|
+
const rateLimiter = new RateLimiter(this.driverPolicies.maxConcurrentOrdererRequests);
|
|
153
|
+
this.ordererRestWrapper = await RouterliciousOrdererRestWrapper.load(
|
|
154
|
+
this.tenantId,
|
|
155
|
+
this.documentId,
|
|
156
|
+
this.tokenProvider,
|
|
157
|
+
this.logger,
|
|
158
|
+
rateLimiter,
|
|
159
|
+
this.driverPolicies.enableRestLess,
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
return this.ordererRestWrapper;
|
|
163
|
+
};
|
|
164
|
+
const restWrapper = await getRestWrapper();
|
|
165
|
+
const deltaStorageService = new DeltaStorageService(
|
|
166
|
+
this.deltaStorageUrl,
|
|
167
|
+
restWrapper,
|
|
168
|
+
this.logger,
|
|
169
|
+
getRestWrapper,
|
|
170
|
+
() => this.deltaStorageUrl,
|
|
171
|
+
);
|
|
172
|
+
return new DocumentDeltaStorageService(
|
|
113
173
|
this.tenantId,
|
|
114
174
|
this.documentId,
|
|
115
|
-
|
|
116
|
-
this.
|
|
117
|
-
rateLimiter,
|
|
118
|
-
this.driverPolicies.enableRestLess,
|
|
175
|
+
deltaStorageService,
|
|
176
|
+
this.documentStorageService,
|
|
119
177
|
);
|
|
120
|
-
const deltaStorage = new DeltaStorageService(this.deltaStorageUrl, ordererRestWrapper, this.logger);
|
|
121
|
-
return new DocumentDeltaStorageService(this.tenantId, this.documentId,
|
|
122
|
-
deltaStorage, this.documentStorageService);
|
|
123
178
|
}
|
|
124
179
|
|
|
125
180
|
/**
|
|
@@ -129,6 +184,9 @@ export class DocumentService implements api.IDocumentService {
|
|
|
129
184
|
*/
|
|
130
185
|
public async connectToDeltaStream(client: IClient): Promise<api.IDocumentDeltaConnection> {
|
|
131
186
|
const connect = async (refreshToken?: boolean) => {
|
|
187
|
+
if (this.shouldUpdateDiscoveredSessionInfo()) {
|
|
188
|
+
await this.refreshDiscovery();
|
|
189
|
+
}
|
|
132
190
|
const ordererToken = await this.tokenProvider.fetchOrdererToken(
|
|
133
191
|
this.tenantId,
|
|
134
192
|
this.documentId,
|
|
@@ -147,16 +205,58 @@ export class DocumentService implements api.IDocumentService {
|
|
|
147
205
|
|
|
148
206
|
// Attempt to establish connection.
|
|
149
207
|
// Retry with new token on authorization error; otherwise, allow container layer to handle.
|
|
208
|
+
let connection: api.IDocumentDeltaConnection;
|
|
150
209
|
try {
|
|
151
|
-
|
|
152
|
-
return connection;
|
|
210
|
+
connection = await connect();
|
|
153
211
|
} catch (error: any) {
|
|
154
212
|
if (error?.statusCode === 401) {
|
|
155
213
|
// Fetch new token and retry once,
|
|
156
214
|
// otherwise 401 will be bubbled up as non-retriable AuthorizationError.
|
|
157
|
-
|
|
215
|
+
connection = await connect(true /* refreshToken */);
|
|
158
216
|
}
|
|
159
217
|
throw error;
|
|
160
218
|
}
|
|
219
|
+
return connection;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Re-discover session URLs if necessary.
|
|
224
|
+
*/
|
|
225
|
+
private async refreshDiscovery(): Promise<void> {
|
|
226
|
+
if (!this.discoverP) {
|
|
227
|
+
this.discoverP = PerformanceEvent.timedExecAsync(
|
|
228
|
+
this.logger,
|
|
229
|
+
{
|
|
230
|
+
eventName: "refreshSessionDiscovery",
|
|
231
|
+
},
|
|
232
|
+
async () => this.refreshDiscoveryCore(),
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
return this.discoverP;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
private async refreshDiscoveryCore(): Promise<void> {
|
|
239
|
+
const fluidResolvedUrl = await this.discoverFluidResolvedUrl();
|
|
240
|
+
this._resolvedUrl = fluidResolvedUrl;
|
|
241
|
+
this.storageUrl = fluidResolvedUrl.endpoints.storageUrl;
|
|
242
|
+
this.ordererUrl = fluidResolvedUrl.endpoints.ordererUrl;
|
|
243
|
+
this.deltaStorageUrl = fluidResolvedUrl.endpoints.deltaStorageUrl;
|
|
244
|
+
this.lastDiscoveredAt = Date.now();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Whether enough time has passed since last disconnect to warrant a new discovery call on reconnect.
|
|
249
|
+
*/
|
|
250
|
+
private shouldUpdateDiscoveredSessionInfo(): boolean {
|
|
251
|
+
if (!this.driverPolicies.enableDiscovery) {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
const now = Date.now();
|
|
255
|
+
// When connection is disconnected, we cannot know if session has moved or document has been deleted
|
|
256
|
+
// without re-doing discovery on the next attempt to connect.
|
|
257
|
+
// Disconnect event is not so reliable in local testing. To ensure re-discovery when necessary,
|
|
258
|
+
// re-discover if enough time has passed since last discovery.
|
|
259
|
+
const pastLastDiscoveryTimeThreshold = (now - this.lastDiscoveredAt) > RediscoverAfterTimeSinceDiscoveryMs;
|
|
260
|
+
return pastLastDiscoveryTimeThreshold;
|
|
161
261
|
}
|
|
162
262
|
}
|