@fluidframework/container-loader 2.0.0-internal.7.1.1 → 2.0.0-internal.7.2.1
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 +4 -0
- package/api-report/container-loader.api.md +13 -2
- package/dist/connectionManager.d.ts +1 -1
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +9 -4
- package/dist/connectionManager.js.map +1 -1
- package/dist/container.d.ts +6 -5
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +21 -19
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +2 -2
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +1 -1
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +3 -3
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +1 -1
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/deltaManager.d.ts +1 -1
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +3 -8
- package/dist/deltaManager.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +4 -4
- package/dist/loader.js +7 -7
- package/dist/loader.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/retriableDocumentStorageService.d.ts +3 -2
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +18 -11
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/utils.d.ts +23 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +11 -3
- package/dist/utils.js.map +1 -1
- package/lib/connectionManager.d.ts +1 -1
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +9 -4
- package/lib/connectionManager.js.map +1 -1
- package/lib/container.d.ts +6 -5
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +21 -19
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +2 -2
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +1 -1
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +3 -3
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +1 -1
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/deltaManager.d.ts +1 -1
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +3 -8
- package/lib/deltaManager.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/loader.d.ts +4 -4
- package/lib/loader.js +8 -8
- package/lib/loader.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/retriableDocumentStorageService.d.ts +3 -2
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +18 -11
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/utils.d.ts +23 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +9 -1
- package/lib/utils.js.map +1 -1
- package/package.json +15 -16
- package/src/connectionManager.ts +13 -5
- package/src/container.ts +34 -24
- package/src/containerContext.ts +1 -1
- package/src/containerStorageAdapter.ts +3 -3
- package/src/contracts.ts +1 -1
- package/src/deltaManager.ts +6 -23
- package/src/index.ts +1 -0
- package/src/loader.ts +8 -8
- package/src/packageVersion.ts +1 -1
- package/src/retriableDocumentStorageService.ts +29 -15
- package/src/utils.ts +23 -1
- package/dist/container-loader-alpha.d.ts +0 -297
- package/dist/container-loader-beta.d.ts +0 -297
- package/dist/container-loader-public.d.ts +0 -297
- package/dist/container-loader.d.ts +0 -297
package/lib/packageVersion.js
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export const pkgName = "@fluidframework/container-loader";
|
|
8
|
-
export const pkgVersion = "2.0.0-internal.7.
|
|
8
|
+
export const pkgVersion = "2.0.0-internal.7.2.1";
|
|
9
9
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-loader\";\nexport const pkgVersion = \"2.0.0-internal.7.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-loader\";\nexport const pkgVersion = \"2.0.0-internal.7.2.1\";\n"]}
|
|
@@ -7,10 +7,11 @@ import { ICreateBlobResponse, ISnapshotTree, ISummaryHandle, ISummaryTree, IVers
|
|
|
7
7
|
import { IDisposable } from "@fluidframework/core-interfaces";
|
|
8
8
|
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
9
9
|
export declare class RetriableDocumentStorageService implements IDocumentStorageService, IDisposable {
|
|
10
|
-
private readonly
|
|
10
|
+
private readonly internalStorageServiceP;
|
|
11
11
|
private readonly logger;
|
|
12
12
|
private _disposed;
|
|
13
|
-
|
|
13
|
+
private internalStorageService;
|
|
14
|
+
constructor(internalStorageServiceP: Promise<IDocumentStorageService>, logger: ITelemetryLoggerExt);
|
|
14
15
|
get policies(): IDocumentStorageServicePolicies | undefined;
|
|
15
16
|
get disposed(): boolean;
|
|
16
17
|
dispose(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retriableDocumentStorageService.d.ts","sourceRoot":"","sources":["../src/retriableDocumentStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,WAAW,EACX,uBAAuB,EACvB,+BAA+B,EAC/B,eAAe,EACf,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACN,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAgB,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAGpF,qBAAa,+BAAgC,YAAW,uBAAuB,EAAE,WAAW;
|
|
1
|
+
{"version":3,"file":"retriableDocumentStorageService.d.ts","sourceRoot":"","sources":["../src/retriableDocumentStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,WAAW,EACX,uBAAuB,EACvB,+BAA+B,EAC/B,eAAe,EACf,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACN,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAgB,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAGpF,qBAAa,+BAAgC,YAAW,uBAAuB,EAAE,WAAW;IAI1F,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,sBAAsB,CAAsC;gBAElD,uBAAuB,EAAE,OAAO,CAAC,uBAAuB,CAAC,EACzD,MAAM,EAAE,mBAAmB;IAK7C,IAAW,QAAQ,IAAI,+BAA+B,GAAG,SAAS,CAKjE;IACD,IAAW,QAAQ,YAElB;IACM,OAAO;IAId,IAAW,aAAa,IAAI,MAAM,CAKjC;IAEY,eAAe,CAC3B,OAAO,CAAC,EAAE,QAAQ,EAClB,YAAY,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAUnB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAO9C,WAAW,CACvB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,WAAW,GACvB,OAAO,CAAC,QAAQ,EAAE,CAAC;IAUT,wBAAwB,CACpC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,eAAe,GACtB,OAAO,CAAC,MAAM,CAAC;IA8BL,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAO9D,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAO5E,OAAO,CAAC,oBAAoB;YAiBd,YAAY;CAM1B"}
|
|
@@ -6,13 +6,17 @@ import { assert } from "@fluidframework/core-utils";
|
|
|
6
6
|
import { GenericError } from "@fluidframework/telemetry-utils";
|
|
7
7
|
import { runWithRetry } from "@fluidframework/driver-utils";
|
|
8
8
|
export class RetriableDocumentStorageService {
|
|
9
|
-
constructor(
|
|
10
|
-
this.
|
|
9
|
+
constructor(internalStorageServiceP, logger) {
|
|
10
|
+
this.internalStorageServiceP = internalStorageServiceP;
|
|
11
11
|
this.logger = logger;
|
|
12
12
|
this._disposed = false;
|
|
13
|
+
this.internalStorageServiceP.then((s) => (this.internalStorageService = s)).catch(() => { });
|
|
13
14
|
}
|
|
14
15
|
get policies() {
|
|
15
|
-
|
|
16
|
+
if (this.internalStorageService) {
|
|
17
|
+
return this.internalStorageService.policies;
|
|
18
|
+
}
|
|
19
|
+
throw new Error("storage service not yet instantiated");
|
|
16
20
|
}
|
|
17
21
|
get disposed() {
|
|
18
22
|
return this._disposed;
|
|
@@ -21,16 +25,19 @@ export class RetriableDocumentStorageService {
|
|
|
21
25
|
this._disposed = true;
|
|
22
26
|
}
|
|
23
27
|
get repositoryUrl() {
|
|
24
|
-
|
|
28
|
+
if (this.internalStorageService) {
|
|
29
|
+
return this.internalStorageService.repositoryUrl;
|
|
30
|
+
}
|
|
31
|
+
throw new Error("storage service not yet instantiated");
|
|
25
32
|
}
|
|
26
33
|
async getSnapshotTree(version, scenarioName) {
|
|
27
|
-
return this.runWithRetry(async () => this.
|
|
34
|
+
return this.runWithRetry(async () => this.internalStorageServiceP.then(async (s) => s.getSnapshotTree(version, scenarioName)), "storage_getSnapshotTree");
|
|
28
35
|
}
|
|
29
36
|
async readBlob(id) {
|
|
30
|
-
return this.runWithRetry(async () => this.
|
|
37
|
+
return this.runWithRetry(async () => this.internalStorageServiceP.then(async (s) => s.readBlob(id)), "storage_readBlob");
|
|
31
38
|
}
|
|
32
39
|
async getVersions(versionId, count, scenarioName, fetchSource) {
|
|
33
|
-
return this.runWithRetry(async () => this.
|
|
40
|
+
return this.runWithRetry(async () => this.internalStorageServiceP.then(async (s) => s.getVersions(versionId, count, scenarioName, fetchSource)), "storage_getVersions");
|
|
34
41
|
}
|
|
35
42
|
async uploadSummaryWithContext(summary, context) {
|
|
36
43
|
// Not using retry loop here. Couple reasons:
|
|
@@ -44,16 +51,16 @@ export class RetriableDocumentStorageService {
|
|
|
44
51
|
// But retry loop is required for creation flow (Container.attach)
|
|
45
52
|
assert((context.referenceSequenceNumber === 0) === (context.ackHandle === undefined), 0x251 /* "creation summary has to have seq=0 && handle === undefined" */);
|
|
46
53
|
if (context.referenceSequenceNumber !== 0) {
|
|
47
|
-
return this.
|
|
54
|
+
return this.internalStorageServiceP.then(async (s) => s.uploadSummaryWithContext(summary, context));
|
|
48
55
|
}
|
|
49
56
|
// Creation flow with attachment blobs - need to do retries!
|
|
50
|
-
return this.runWithRetry(async () => this.
|
|
57
|
+
return this.runWithRetry(async () => this.internalStorageServiceP.then(async (s) => s.uploadSummaryWithContext(summary, context)), "storage_uploadSummaryWithContext");
|
|
51
58
|
}
|
|
52
59
|
async downloadSummary(handle) {
|
|
53
|
-
return this.runWithRetry(async () => this.
|
|
60
|
+
return this.runWithRetry(async () => this.internalStorageServiceP.then(async (s) => s.downloadSummary(handle)), "storage_downloadSummary");
|
|
54
61
|
}
|
|
55
62
|
async createBlob(file) {
|
|
56
|
-
return this.runWithRetry(async () => this.
|
|
63
|
+
return this.runWithRetry(async () => this.internalStorageServiceP.then(async (s) => s.createBlob(file)), "storage_createBlob");
|
|
57
64
|
}
|
|
58
65
|
checkStorageDisposed(callName, error) {
|
|
59
66
|
if (this._disposed) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retriableDocumentStorageService.js","sourceRoot":"","sources":["../src/retriableDocumentStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAepD,OAAO,EAAE,YAAY,EAAuB,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,MAAM,OAAO,+BAA+B;
|
|
1
|
+
{"version":3,"file":"retriableDocumentStorageService.js","sourceRoot":"","sources":["../src/retriableDocumentStorageService.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 { assert } from \"@fluidframework/core-utils\";\nimport {\n\tFetchSource,\n\tIDocumentStorageService,\n\tIDocumentStorageServicePolicies,\n\tISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport {\n\tICreateBlobResponse,\n\tISnapshotTree,\n\tISummaryHandle,\n\tISummaryTree,\n\tIVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport { IDisposable } from \"@fluidframework/core-interfaces\";\nimport { GenericError, ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport { runWithRetry } from \"@fluidframework/driver-utils\";\n\nexport class RetriableDocumentStorageService implements IDocumentStorageService, IDisposable {\n\tprivate _disposed = false;\n\tprivate internalStorageService: IDocumentStorageService | undefined;\n\tconstructor(\n\t\tprivate readonly internalStorageServiceP: Promise<IDocumentStorageService>,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t) {\n\t\tthis.internalStorageServiceP.then((s) => (this.internalStorageService = s)).catch(() => {});\n\t}\n\n\tpublic get policies(): IDocumentStorageServicePolicies | undefined {\n\t\tif (this.internalStorageService) {\n\t\t\treturn this.internalStorageService.policies;\n\t\t}\n\t\tthrow new Error(\"storage service not yet instantiated\");\n\t}\n\tpublic get disposed() {\n\t\treturn this._disposed;\n\t}\n\tpublic dispose() {\n\t\tthis._disposed = true;\n\t}\n\n\tpublic get repositoryUrl(): string {\n\t\tif (this.internalStorageService) {\n\t\t\treturn this.internalStorageService.repositoryUrl;\n\t\t}\n\t\tthrow new Error(\"storage service not yet instantiated\");\n\t}\n\n\tpublic async getSnapshotTree(\n\t\tversion?: IVersion,\n\t\tscenarioName?: string,\n\t): Promise<ISnapshotTree | null> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () =>\n\t\t\t\tthis.internalStorageServiceP.then(async (s) =>\n\t\t\t\t\ts.getSnapshotTree(version, scenarioName),\n\t\t\t\t),\n\t\t\t\"storage_getSnapshotTree\",\n\t\t);\n\t}\n\n\tpublic async readBlob(id: string): Promise<ArrayBufferLike> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageServiceP.then(async (s) => s.readBlob(id)),\n\t\t\t\"storage_readBlob\",\n\t\t);\n\t}\n\n\tpublic async getVersions(\n\t\tversionId: string | null,\n\t\tcount: number,\n\t\tscenarioName?: string,\n\t\tfetchSource?: FetchSource,\n\t): Promise<IVersion[]> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () =>\n\t\t\t\tthis.internalStorageServiceP.then(async (s) =>\n\t\t\t\t\ts.getVersions(versionId, count, scenarioName, fetchSource),\n\t\t\t\t),\n\t\t\t\"storage_getVersions\",\n\t\t);\n\t}\n\n\tpublic async uploadSummaryWithContext(\n\t\tsummary: ISummaryTree,\n\t\tcontext: ISummaryContext,\n\t): Promise<string> {\n\t\t// Not using retry loop here. Couple reasons:\n\t\t// 1. If client lost connectivity, then retry loop will result in uploading stale summary\n\t\t// by stale summarizer after connectivity comes back. It will cause failures for this client and for\n\t\t// real (new) summarizer. This problem in particular should be solved in future by supplying abort handle\n\t\t// on all APIs and caller (ContainerRuntime.submitSummary) aborting call on loss of connectivity\n\t\t// 2. Similar, if we get 429 with retryAfter = 10 minutes, it's likely not the right call to retry summary\n\t\t// upload in 10 minutes - it's better to keep processing ops and retry later. Though caller needs to take\n\t\t// retryAfter into account!\n\t\t// But retry loop is required for creation flow (Container.attach)\n\t\tassert(\n\t\t\t(context.referenceSequenceNumber === 0) === (context.ackHandle === undefined),\n\t\t\t0x251 /* \"creation summary has to have seq=0 && handle === undefined\" */,\n\t\t);\n\t\tif (context.referenceSequenceNumber !== 0) {\n\t\t\treturn this.internalStorageServiceP.then(async (s) =>\n\t\t\t\ts.uploadSummaryWithContext(summary, context),\n\t\t\t);\n\t\t}\n\n\t\t// Creation flow with attachment blobs - need to do retries!\n\t\treturn this.runWithRetry(\n\t\t\tasync () =>\n\t\t\t\tthis.internalStorageServiceP.then(async (s) =>\n\t\t\t\t\ts.uploadSummaryWithContext(summary, context),\n\t\t\t\t),\n\t\t\t\"storage_uploadSummaryWithContext\",\n\t\t);\n\t}\n\n\tpublic async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageServiceP.then(async (s) => s.downloadSummary(handle)),\n\t\t\t\"storage_downloadSummary\",\n\t\t);\n\t}\n\n\tpublic async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n\t\treturn this.runWithRetry(\n\t\t\tasync () => this.internalStorageServiceP.then(async (s) => s.createBlob(file)),\n\t\t\t\"storage_createBlob\",\n\t\t);\n\t}\n\n\tprivate checkStorageDisposed(callName: string, error: unknown) {\n\t\tif (this._disposed) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: `${callName}_abortedStorageDisposed`,\n\t\t\t\t\tfetchCallName: callName, // fetchCallName matches logs in runWithRetry.ts\n\t\t\t\t},\n\t\t\t\terror,\n\t\t\t);\n\t\t\t// pre-0.58 error message: storageServiceDisposedCannotRetry\n\t\t\tthrow new GenericError(\"Storage Service is disposed. Cannot retry\", {\n\t\t\t\tcanRetry: false,\n\t\t\t});\n\t\t}\n\t\treturn;\n\t}\n\n\tprivate async runWithRetry<T>(api: () => Promise<T>, callName: string): Promise<T> {\n\t\treturn runWithRetry(api, callName, this.logger, {\n\t\t\tonRetry: (_delayInMs: number, error: unknown) =>\n\t\t\t\tthis.checkStorageDisposed(callName, error),\n\t\t});\n\t}\n}\n"]}
|
package/lib/utils.d.ts
CHANGED
|
@@ -12,9 +12,23 @@ export interface ISnapshotTreeWithBlobContents extends ISnapshotTree {
|
|
|
12
12
|
[path: string]: ISnapshotTreeWithBlobContents;
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Interface to represent the parsed parts of IResolvedUrl.url to help
|
|
17
|
+
* in getting info about different parts of the url.
|
|
18
|
+
* May not be compatible or relevant for any Url Resolver
|
|
19
|
+
*/
|
|
15
20
|
export interface IParsedUrl {
|
|
21
|
+
/**
|
|
22
|
+
* It is combination of tenantid/docId part of the url.
|
|
23
|
+
*/
|
|
16
24
|
id: string;
|
|
25
|
+
/**
|
|
26
|
+
* It is the deep link path in the url.
|
|
27
|
+
*/
|
|
17
28
|
path: string;
|
|
29
|
+
/**
|
|
30
|
+
* Query string part of the url.
|
|
31
|
+
*/
|
|
18
32
|
query: string;
|
|
19
33
|
/**
|
|
20
34
|
* Null means do not use snapshots, undefined means load latest snapshot
|
|
@@ -23,7 +37,15 @@ export interface IParsedUrl {
|
|
|
23
37
|
*/
|
|
24
38
|
version: string | null | undefined;
|
|
25
39
|
}
|
|
26
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Utility api to parse the IResolvedUrl.url into specific parts like querystring, path to get
|
|
42
|
+
* deep link info etc.
|
|
43
|
+
* Warning - This function may not be compatible with any Url Resolver's resolved url. It works
|
|
44
|
+
* with urls of type: protocol://<string>/.../..?<querystring>
|
|
45
|
+
* @param url - This is the IResolvedUrl.url part of the resolved url.
|
|
46
|
+
* @returns The IParsedUrl representing the input URL, or undefined if the format was not supported
|
|
47
|
+
*/
|
|
48
|
+
export declare function tryParseCompatibleResolvedUrl(url: string): IParsedUrl | undefined;
|
|
27
49
|
/**
|
|
28
50
|
* Combine the app summary and protocol summary in 1 tree.
|
|
29
51
|
* @param appSummary - Summary of the app.
|
package/lib/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAe,MAAM,sCAAsC,CAAC;AAEhG,OAAO,EACN,6BAA6B,EAC7B,mCAAmC,EAEnC,MAAM,8BAA8B,CAAC;AAKtC,MAAM,WAAW,6BAA8B,SAAQ,aAAa;IACnE,aAAa,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,KAAK,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,6BAA6B,CAAA;KAAE,CAAC;CACzD;AAED,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACnC;AAED,wBAAgB,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAe,MAAM,sCAAsC,CAAC;AAEhG,OAAO,EACN,6BAA6B,EAC7B,mCAAmC,EAEnC,MAAM,8BAA8B,CAAC;AAKtC,MAAM,WAAW,6BAA8B,SAAQ,aAAa;IACnE,aAAa,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,KAAK,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,6BAA6B,CAAA;KAAE,CAAC;CACzD;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IAC1B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAWjF;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC3C,UAAU,EAAE,YAAY,EACxB,eAAe,EAAE,YAAY,GAC3B,6BAA6B,CAiB/B;AA0DD;;;;GAIG;AACH,wBAAgB,0CAA0C,CACzD,mBAAmB,EAAE,YAAY,EACjC,cAAc,EAAE,YAAY,GAC1B,6BAA6B,CAW/B;AAID,eAAO,MAAM,sCAAsC,8BACvB,YAAY,KACrC,6BAYF,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa,CAE9E;AAED,wBAAgB,qCAAqC,CACpD,KAAK,EAAE,GAAG,GACR,KAAK,IAAI,mCAAmC,CAM9C"}
|
package/lib/utils.js
CHANGED
|
@@ -10,7 +10,15 @@ import { SummaryType } from "@fluidframework/protocol-definitions";
|
|
|
10
10
|
import { LoggingError } from "@fluidframework/telemetry-utils";
|
|
11
11
|
import { isCombinedAppAndProtocolSummary, } from "@fluidframework/driver-utils";
|
|
12
12
|
import { DriverErrorTypes } from "@fluidframework/driver-definitions";
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Utility api to parse the IResolvedUrl.url into specific parts like querystring, path to get
|
|
15
|
+
* deep link info etc.
|
|
16
|
+
* Warning - This function may not be compatible with any Url Resolver's resolved url. It works
|
|
17
|
+
* with urls of type: protocol://<string>/.../..?<querystring>
|
|
18
|
+
* @param url - This is the IResolvedUrl.url part of the resolved url.
|
|
19
|
+
* @returns The IParsedUrl representing the input URL, or undefined if the format was not supported
|
|
20
|
+
*/
|
|
21
|
+
export function tryParseCompatibleResolvedUrl(url) {
|
|
14
22
|
const parsed = parse(url, true);
|
|
15
23
|
if (typeof parsed.pathname !== "string") {
|
|
16
24
|
throw new LoggingError("Failed to parse pathname");
|
package/lib/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.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 { parse } from \"url\";\nimport { v4 as uuid } from \"uuid\";\nimport { stringToBuffer, Uint8ArrayToArrayBuffer } from \"@fluid-internal/client-utils\";\nimport { assert, unreachableCase } from \"@fluidframework/core-utils\";\nimport { ISummaryTree, ISnapshotTree, SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { LoggingError } from \"@fluidframework/telemetry-utils\";\nimport {\n\tCombinedAppAndProtocolSummary,\n\tDeltaStreamConnectionForbiddenError,\n\tisCombinedAppAndProtocolSummary,\n} from \"@fluidframework/driver-utils\";\nimport { DriverErrorTypes } from \"@fluidframework/driver-definitions\";\n\n// This is used when we rehydrate a container from the snapshot. Here we put the blob contents\n// in separate property: blobContents.\nexport interface ISnapshotTreeWithBlobContents extends ISnapshotTree {\n\tblobsContents: { [path: string]: ArrayBufferLike };\n\ttrees: { [path: string]: ISnapshotTreeWithBlobContents };\n}\n\nexport interface IParsedUrl {\n\tid: string;\n\tpath: string;\n\tquery: string;\n\t/**\n\t * Null means do not use snapshots, undefined means load latest snapshot\n\t * otherwise it's version ID passed to IDocumentStorageService.getVersions() to figure out what snapshot to use.\n\t * If needed, can add undefined which is treated by Container.load() as load latest snapshot.\n\t */\n\tversion: string | null | undefined;\n}\n\nexport function parseUrl(url: string): IParsedUrl | undefined {\n\tconst parsed = parse(url, true);\n\tif (typeof parsed.pathname !== \"string\") {\n\t\tthrow new LoggingError(\"Failed to parse pathname\");\n\t}\n\tconst query = parsed.search ?? \"\";\n\tconst regex = /^\\/([^/]*\\/[^/]*)(\\/?.*)$/;\n\tconst match = regex.exec(parsed.pathname);\n\treturn match?.length === 3\n\t\t? { id: match[1], path: match[2], query, version: parsed.query.version as string }\n\t\t: undefined;\n}\n\n/**\n * Combine the app summary and protocol summary in 1 tree.\n * @param appSummary - Summary of the app.\n * @param protocolSummary - Summary of the protocol.\n * @internal\n */\nexport function combineAppAndProtocolSummary(\n\tappSummary: ISummaryTree,\n\tprotocolSummary: ISummaryTree,\n): CombinedAppAndProtocolSummary {\n\tassert(\n\t\t!isCombinedAppAndProtocolSummary(appSummary),\n\t\t0x5a8 /* app summary is already a combined tree! */,\n\t);\n\tassert(\n\t\t!isCombinedAppAndProtocolSummary(protocolSummary),\n\t\t0x5a9 /* protocol summary is already a combined tree! */,\n\t);\n\tconst createNewSummary: CombinedAppAndProtocolSummary = {\n\t\ttype: SummaryType.Tree,\n\t\ttree: {\n\t\t\t\".protocol\": protocolSummary,\n\t\t\t\".app\": appSummary,\n\t\t},\n\t};\n\treturn createNewSummary;\n}\n\n/**\n * Converts summary tree (for upload) to snapshot tree (for download).\n * Summary tree blobs contain contents, but snapshot tree blobs normally\n * contain IDs pointing to storage. This will create 2 blob entries in the\n * snapshot tree for each blob in the summary tree. One will be the regular\n * path pointing to a uniquely generated ID. Then there will be another\n * entry with the path as that uniquely generated ID, and value as the\n * blob contents as a base-64 string.\n * @param summary - summary to convert\n */\nfunction convertSummaryToSnapshotWithEmbeddedBlobContents(\n\tsummary: ISummaryTree,\n): ISnapshotTreeWithBlobContents {\n\tconst treeNode: ISnapshotTreeWithBlobContents = {\n\t\tblobs: {},\n\t\tblobsContents: {},\n\t\ttrees: {},\n\t\tid: uuid(),\n\t\tunreferenced: summary.unreferenced,\n\t};\n\tconst keys = Object.keys(summary.tree);\n\tfor (const key of keys) {\n\t\tconst summaryObject = summary.tree[key];\n\n\t\tswitch (summaryObject.type) {\n\t\t\tcase SummaryType.Tree: {\n\t\t\t\ttreeNode.trees[key] =\n\t\t\t\t\tconvertSummaryToSnapshotWithEmbeddedBlobContents(summaryObject);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Attachment:\n\t\t\t\ttreeNode.blobs[key] = summaryObject.id;\n\t\t\t\tbreak;\n\t\t\tcase SummaryType.Blob: {\n\t\t\t\tconst blobId = uuid();\n\t\t\t\ttreeNode.blobs[key] = blobId;\n\t\t\t\tconst contentBuffer =\n\t\t\t\t\ttypeof summaryObject.content === \"string\"\n\t\t\t\t\t\t? stringToBuffer(summaryObject.content, \"utf8\")\n\t\t\t\t\t\t: Uint8ArrayToArrayBuffer(summaryObject.content);\n\t\t\t\ttreeNode.blobsContents[blobId] = contentBuffer;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Handle:\n\t\t\t\tthrow new LoggingError(\n\t\t\t\t\t\"No handles should be there in summary in detached container!!\",\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault: {\n\t\t\t\tunreachableCase(summaryObject, `Unknown tree type ${(summaryObject as any).type}`);\n\t\t\t}\n\t\t}\n\t}\n\treturn treeNode;\n}\n\n/**\n * Combine and convert protocol and app summary tree to format which is readable by container while rehydrating.\n * @param protocolSummaryTree - Protocol Summary Tree\n * @param appSummaryTree - App Summary Tree\n */\nexport function convertProtocolAndAppSummaryToSnapshotTree(\n\tprotocolSummaryTree: ISummaryTree,\n\tappSummaryTree: ISummaryTree,\n): ISnapshotTreeWithBlobContents {\n\t// Shallow copy is fine, since we are doing a deep clone below.\n\tconst combinedSummary: ISummaryTree = {\n\t\ttype: SummaryType.Tree,\n\t\ttree: { ...appSummaryTree.tree },\n\t};\n\n\tcombinedSummary.tree[\".protocol\"] = protocolSummaryTree;\n\tconst snapshotTreeWithBlobContents =\n\t\tconvertSummaryToSnapshotWithEmbeddedBlobContents(combinedSummary);\n\treturn snapshotTreeWithBlobContents;\n}\n\n// This function converts the snapshot taken in detached container(by serialize api) to snapshotTree with which\n// a detached container can be rehydrated.\nexport const getSnapshotTreeFromSerializedContainer = (\n\tdetachedContainerSnapshot: ISummaryTree,\n): ISnapshotTreeWithBlobContents => {\n\tassert(\n\t\tisCombinedAppAndProtocolSummary(detachedContainerSnapshot),\n\t\t0x1e0 /* \"Protocol and App summary trees should be present\" */,\n\t);\n\tconst protocolSummaryTree = detachedContainerSnapshot.tree[\".protocol\"];\n\tconst appSummaryTree = detachedContainerSnapshot.tree[\".app\"];\n\tconst snapshotTreeWithBlobContents = convertProtocolAndAppSummaryToSnapshotTree(\n\t\tprotocolSummaryTree,\n\t\tappSummaryTree,\n\t);\n\treturn snapshotTreeWithBlobContents;\n};\n\nexport function getProtocolSnapshotTree(snapshot: ISnapshotTree): ISnapshotTree {\n\treturn \".protocol\" in snapshot.trees ? snapshot.trees[\".protocol\"] : snapshot;\n}\n\nexport function isDeltaStreamConnectionForbiddenError(\n\terror: any,\n): error is DeltaStreamConnectionForbiddenError {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\terror?.errorType === DriverErrorTypes.deltaStreamConnectionForbidden\n\t);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.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 { parse } from \"url\";\nimport { v4 as uuid } from \"uuid\";\nimport { stringToBuffer, Uint8ArrayToArrayBuffer } from \"@fluid-internal/client-utils\";\nimport { assert, unreachableCase } from \"@fluidframework/core-utils\";\nimport { ISummaryTree, ISnapshotTree, SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { LoggingError } from \"@fluidframework/telemetry-utils\";\nimport {\n\tCombinedAppAndProtocolSummary,\n\tDeltaStreamConnectionForbiddenError,\n\tisCombinedAppAndProtocolSummary,\n} from \"@fluidframework/driver-utils\";\nimport { DriverErrorTypes } from \"@fluidframework/driver-definitions\";\n\n// This is used when we rehydrate a container from the snapshot. Here we put the blob contents\n// in separate property: blobContents.\nexport interface ISnapshotTreeWithBlobContents extends ISnapshotTree {\n\tblobsContents: { [path: string]: ArrayBufferLike };\n\ttrees: { [path: string]: ISnapshotTreeWithBlobContents };\n}\n\n/**\n * Interface to represent the parsed parts of IResolvedUrl.url to help\n * in getting info about different parts of the url.\n * May not be compatible or relevant for any Url Resolver\n */\nexport interface IParsedUrl {\n\t/**\n\t * It is combination of tenantid/docId part of the url.\n\t */\n\tid: string;\n\t/**\n\t * It is the deep link path in the url.\n\t */\n\tpath: string;\n\t/**\n\t * Query string part of the url.\n\t */\n\tquery: string;\n\t/**\n\t * Null means do not use snapshots, undefined means load latest snapshot\n\t * otherwise it's version ID passed to IDocumentStorageService.getVersions() to figure out what snapshot to use.\n\t * If needed, can add undefined which is treated by Container.load() as load latest snapshot.\n\t */\n\tversion: string | null | undefined;\n}\n\n/**\n * Utility api to parse the IResolvedUrl.url into specific parts like querystring, path to get\n * deep link info etc.\n * Warning - This function may not be compatible with any Url Resolver's resolved url. It works\n * with urls of type: protocol://<string>/.../..?<querystring>\n * @param url - This is the IResolvedUrl.url part of the resolved url.\n * @returns The IParsedUrl representing the input URL, or undefined if the format was not supported\n */\nexport function tryParseCompatibleResolvedUrl(url: string): IParsedUrl | undefined {\n\tconst parsed = parse(url, true);\n\tif (typeof parsed.pathname !== \"string\") {\n\t\tthrow new LoggingError(\"Failed to parse pathname\");\n\t}\n\tconst query = parsed.search ?? \"\";\n\tconst regex = /^\\/([^/]*\\/[^/]*)(\\/?.*)$/;\n\tconst match = regex.exec(parsed.pathname);\n\treturn match?.length === 3\n\t\t? { id: match[1], path: match[2], query, version: parsed.query.version as string }\n\t\t: undefined;\n}\n\n/**\n * Combine the app summary and protocol summary in 1 tree.\n * @param appSummary - Summary of the app.\n * @param protocolSummary - Summary of the protocol.\n * @internal\n */\nexport function combineAppAndProtocolSummary(\n\tappSummary: ISummaryTree,\n\tprotocolSummary: ISummaryTree,\n): CombinedAppAndProtocolSummary {\n\tassert(\n\t\t!isCombinedAppAndProtocolSummary(appSummary),\n\t\t0x5a8 /* app summary is already a combined tree! */,\n\t);\n\tassert(\n\t\t!isCombinedAppAndProtocolSummary(protocolSummary),\n\t\t0x5a9 /* protocol summary is already a combined tree! */,\n\t);\n\tconst createNewSummary: CombinedAppAndProtocolSummary = {\n\t\ttype: SummaryType.Tree,\n\t\ttree: {\n\t\t\t\".protocol\": protocolSummary,\n\t\t\t\".app\": appSummary,\n\t\t},\n\t};\n\treturn createNewSummary;\n}\n\n/**\n * Converts summary tree (for upload) to snapshot tree (for download).\n * Summary tree blobs contain contents, but snapshot tree blobs normally\n * contain IDs pointing to storage. This will create 2 blob entries in the\n * snapshot tree for each blob in the summary tree. One will be the regular\n * path pointing to a uniquely generated ID. Then there will be another\n * entry with the path as that uniquely generated ID, and value as the\n * blob contents as a base-64 string.\n * @param summary - summary to convert\n */\nfunction convertSummaryToSnapshotWithEmbeddedBlobContents(\n\tsummary: ISummaryTree,\n): ISnapshotTreeWithBlobContents {\n\tconst treeNode: ISnapshotTreeWithBlobContents = {\n\t\tblobs: {},\n\t\tblobsContents: {},\n\t\ttrees: {},\n\t\tid: uuid(),\n\t\tunreferenced: summary.unreferenced,\n\t};\n\tconst keys = Object.keys(summary.tree);\n\tfor (const key of keys) {\n\t\tconst summaryObject = summary.tree[key];\n\n\t\tswitch (summaryObject.type) {\n\t\t\tcase SummaryType.Tree: {\n\t\t\t\ttreeNode.trees[key] =\n\t\t\t\t\tconvertSummaryToSnapshotWithEmbeddedBlobContents(summaryObject);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Attachment:\n\t\t\t\ttreeNode.blobs[key] = summaryObject.id;\n\t\t\t\tbreak;\n\t\t\tcase SummaryType.Blob: {\n\t\t\t\tconst blobId = uuid();\n\t\t\t\ttreeNode.blobs[key] = blobId;\n\t\t\t\tconst contentBuffer =\n\t\t\t\t\ttypeof summaryObject.content === \"string\"\n\t\t\t\t\t\t? stringToBuffer(summaryObject.content, \"utf8\")\n\t\t\t\t\t\t: Uint8ArrayToArrayBuffer(summaryObject.content);\n\t\t\t\ttreeNode.blobsContents[blobId] = contentBuffer;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Handle:\n\t\t\t\tthrow new LoggingError(\n\t\t\t\t\t\"No handles should be there in summary in detached container!!\",\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault: {\n\t\t\t\tunreachableCase(summaryObject, `Unknown tree type ${(summaryObject as any).type}`);\n\t\t\t}\n\t\t}\n\t}\n\treturn treeNode;\n}\n\n/**\n * Combine and convert protocol and app summary tree to format which is readable by container while rehydrating.\n * @param protocolSummaryTree - Protocol Summary Tree\n * @param appSummaryTree - App Summary Tree\n */\nexport function convertProtocolAndAppSummaryToSnapshotTree(\n\tprotocolSummaryTree: ISummaryTree,\n\tappSummaryTree: ISummaryTree,\n): ISnapshotTreeWithBlobContents {\n\t// Shallow copy is fine, since we are doing a deep clone below.\n\tconst combinedSummary: ISummaryTree = {\n\t\ttype: SummaryType.Tree,\n\t\ttree: { ...appSummaryTree.tree },\n\t};\n\n\tcombinedSummary.tree[\".protocol\"] = protocolSummaryTree;\n\tconst snapshotTreeWithBlobContents =\n\t\tconvertSummaryToSnapshotWithEmbeddedBlobContents(combinedSummary);\n\treturn snapshotTreeWithBlobContents;\n}\n\n// This function converts the snapshot taken in detached container(by serialize api) to snapshotTree with which\n// a detached container can be rehydrated.\nexport const getSnapshotTreeFromSerializedContainer = (\n\tdetachedContainerSnapshot: ISummaryTree,\n): ISnapshotTreeWithBlobContents => {\n\tassert(\n\t\tisCombinedAppAndProtocolSummary(detachedContainerSnapshot),\n\t\t0x1e0 /* \"Protocol and App summary trees should be present\" */,\n\t);\n\tconst protocolSummaryTree = detachedContainerSnapshot.tree[\".protocol\"];\n\tconst appSummaryTree = detachedContainerSnapshot.tree[\".app\"];\n\tconst snapshotTreeWithBlobContents = convertProtocolAndAppSummaryToSnapshotTree(\n\t\tprotocolSummaryTree,\n\t\tappSummaryTree,\n\t);\n\treturn snapshotTreeWithBlobContents;\n};\n\nexport function getProtocolSnapshotTree(snapshot: ISnapshotTree): ISnapshotTree {\n\treturn \".protocol\" in snapshot.trees ? snapshot.trees[\".protocol\"] : snapshot;\n}\n\nexport function isDeltaStreamConnectionForbiddenError(\n\terror: any,\n): error is DeltaStreamConnectionForbiddenError {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\terror?.errorType === DriverErrorTypes.deltaStreamConnectionForbidden\n\t);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/container-loader",
|
|
3
|
-
"version": "2.0.0-internal.7.
|
|
3
|
+
"version": "2.0.0-internal.7.2.1",
|
|
4
4
|
"description": "Fluid container loader",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -35,16 +35,16 @@
|
|
|
35
35
|
"temp-directory": "nyc/.nyc_output"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@fluid-internal/client-utils": ">=2.0.0-internal.7.
|
|
39
|
-
"@fluidframework/container-definitions": ">=2.0.0-internal.7.
|
|
40
|
-
"@fluidframework/core-interfaces": ">=2.0.0-internal.7.
|
|
41
|
-
"@fluidframework/core-utils": ">=2.0.0-internal.7.
|
|
42
|
-
"@fluidframework/driver-definitions": ">=2.0.0-internal.7.
|
|
43
|
-
"@fluidframework/driver-utils": ">=2.0.0-internal.7.
|
|
38
|
+
"@fluid-internal/client-utils": ">=2.0.0-internal.7.2.1 <2.0.0-internal.7.3.0",
|
|
39
|
+
"@fluidframework/container-definitions": ">=2.0.0-internal.7.2.1 <2.0.0-internal.7.3.0",
|
|
40
|
+
"@fluidframework/core-interfaces": ">=2.0.0-internal.7.2.1 <2.0.0-internal.7.3.0",
|
|
41
|
+
"@fluidframework/core-utils": ">=2.0.0-internal.7.2.1 <2.0.0-internal.7.3.0",
|
|
42
|
+
"@fluidframework/driver-definitions": ">=2.0.0-internal.7.2.1 <2.0.0-internal.7.3.0",
|
|
43
|
+
"@fluidframework/driver-utils": ">=2.0.0-internal.7.2.1 <2.0.0-internal.7.3.0",
|
|
44
44
|
"@fluidframework/protocol-base": "^2.0.1",
|
|
45
45
|
"@fluidframework/protocol-definitions": "^3.0.0",
|
|
46
|
-
"@fluidframework/telemetry-utils": ">=2.0.0-internal.7.
|
|
47
|
-
"debug": "^4.
|
|
46
|
+
"@fluidframework/telemetry-utils": ">=2.0.0-internal.7.2.1 <2.0.0-internal.7.3.0",
|
|
47
|
+
"debug": "^4.3.4",
|
|
48
48
|
"double-ended-queue": "^2.1.0-0",
|
|
49
49
|
"events": "^3.1.0",
|
|
50
50
|
"lodash": "^4.17.21",
|
|
@@ -52,13 +52,13 @@
|
|
|
52
52
|
"uuid": "^9.0.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@fluid-internal/test-loader-utils": ">=2.0.0-internal.7.
|
|
56
|
-
"@fluid-tools/build-cli": "^0.
|
|
57
|
-
"@fluidframework/build-common": "^2.0.
|
|
58
|
-
"@fluidframework/build-tools": "^0.
|
|
55
|
+
"@fluid-internal/test-loader-utils": ">=2.0.0-internal.7.2.1 <2.0.0-internal.7.3.0",
|
|
56
|
+
"@fluid-tools/build-cli": "^0.26.1",
|
|
57
|
+
"@fluidframework/build-common": "^2.0.3",
|
|
58
|
+
"@fluidframework/build-tools": "^0.26.1",
|
|
59
59
|
"@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@2.0.0-internal.7.1.0",
|
|
60
60
|
"@fluidframework/eslint-config-fluid": "^3.0.0",
|
|
61
|
-
"@fluidframework/mocha-test-setup": ">=2.0.0-internal.7.
|
|
61
|
+
"@fluidframework/mocha-test-setup": ">=2.0.0-internal.7.2.1 <2.0.0-internal.7.3.0",
|
|
62
62
|
"@microsoft/api-extractor": "^7.37.0",
|
|
63
63
|
"@types/double-ended-queue": "^2.1.0",
|
|
64
64
|
"@types/events": "^3.0.0",
|
|
@@ -67,7 +67,6 @@
|
|
|
67
67
|
"@types/node": "^16.18.38",
|
|
68
68
|
"@types/sinon": "^7.0.13",
|
|
69
69
|
"c8": "^7.7.1",
|
|
70
|
-
"copyfiles": "^2.4.1",
|
|
71
70
|
"cross-env": "^7.0.3",
|
|
72
71
|
"eslint": "~8.50.0",
|
|
73
72
|
"mocha": "^10.2.0",
|
|
@@ -91,7 +90,7 @@
|
|
|
91
90
|
"build:genver": "gen-version",
|
|
92
91
|
"build:test": "tsc --project ./src/test/tsconfig.json",
|
|
93
92
|
"ci:build:docs": "api-extractor run",
|
|
94
|
-
"clean": "rimraf --glob
|
|
93
|
+
"clean": "rimraf --glob dist lib \"*.tsbuildinfo\" \"*.build.log\" _api-extractor-temp nyc",
|
|
95
94
|
"eslint": "eslint --format stylish src",
|
|
96
95
|
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
|
|
97
96
|
"format": "npm run prettier:fix",
|
package/src/connectionManager.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { IDisposable, ITelemetryProperties } from "@fluidframework/core-interfaces";
|
|
6
|
+
import { IDisposable, ITelemetryProperties, LogLevel } from "@fluidframework/core-interfaces";
|
|
7
7
|
import { assert } from "@fluidframework/core-utils";
|
|
8
8
|
import { performance, TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
9
9
|
import {
|
|
@@ -585,6 +585,14 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
585
585
|
this.logger.sendTelemetryEvent({ eventName: "ReceivedClosedConnection" });
|
|
586
586
|
connection = undefined;
|
|
587
587
|
}
|
|
588
|
+
this.logger.sendTelemetryEvent(
|
|
589
|
+
{
|
|
590
|
+
eventName: "ConnectionReceived",
|
|
591
|
+
connected: connection !== undefined && connection.disposed === false,
|
|
592
|
+
},
|
|
593
|
+
undefined,
|
|
594
|
+
LogLevel.verbose,
|
|
595
|
+
);
|
|
588
596
|
} catch (origError: any) {
|
|
589
597
|
if (isDeltaStreamConnectionForbiddenError(origError)) {
|
|
590
598
|
connection = new NoDeltaStream(origError.storageOnlyReason, {
|
|
@@ -674,8 +682,8 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
674
682
|
);
|
|
675
683
|
}
|
|
676
684
|
|
|
677
|
-
// Check for abort signal after while loop as well
|
|
678
|
-
if (abortSignal.aborted === true) {
|
|
685
|
+
// Check for abort signal after while loop as well or we've been disposed
|
|
686
|
+
if (abortSignal.aborted === true || this._disposed) {
|
|
679
687
|
connection.dispose();
|
|
680
688
|
this.logger.sendTelemetryEvent({
|
|
681
689
|
eventName: "ConnectionAttemptCancelled",
|
|
@@ -1051,9 +1059,9 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
1051
1059
|
};
|
|
1052
1060
|
}
|
|
1053
1061
|
|
|
1054
|
-
public submitSignal(content: any) {
|
|
1062
|
+
public submitSignal(content: any, targetClientId?: string) {
|
|
1055
1063
|
if (this.connection !== undefined) {
|
|
1056
|
-
this.connection.submitSignal(content);
|
|
1064
|
+
this.connection.submitSignal(content, targetClientId);
|
|
1057
1065
|
} else {
|
|
1058
1066
|
this.logger.sendErrorEvent({ eventName: "submitSignalDisconnected" });
|
|
1059
1067
|
}
|
package/src/container.ts
CHANGED
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
IRuntime,
|
|
41
41
|
ReadOnlyInfo,
|
|
42
42
|
isFluidCodeDetails,
|
|
43
|
+
IGetPendingLocalStateProps,
|
|
43
44
|
} from "@fluidframework/container-definitions";
|
|
44
45
|
import {
|
|
45
46
|
IDocumentService,
|
|
@@ -134,6 +135,8 @@ const savedContainerEvent = "saved";
|
|
|
134
135
|
|
|
135
136
|
const packageNotFactoryError = "Code package does not implement IRuntimeFactory";
|
|
136
137
|
|
|
138
|
+
const hasBlobsSummaryTree = ".hasAttachmentBlobs";
|
|
139
|
+
|
|
137
140
|
/**
|
|
138
141
|
* @internal
|
|
139
142
|
*/
|
|
@@ -473,7 +476,11 @@ export class Container
|
|
|
473
476
|
container.mc.logger,
|
|
474
477
|
{ eventName: "RehydrateDetachedFromSnapshot" },
|
|
475
478
|
async (_event) => {
|
|
476
|
-
const deserializedSummary = JSON.parse(snapshot)
|
|
479
|
+
const deserializedSummary = JSON.parse(snapshot);
|
|
480
|
+
if (!isCombinedAppAndProtocolSummary(deserializedSummary, hasBlobsSummaryTree)) {
|
|
481
|
+
throw new UsageError("Cannot rehydrate detached container. Incorrect format");
|
|
482
|
+
}
|
|
483
|
+
|
|
477
484
|
await container.rehydrateDetachedFromSnapshot(deserializedSummary);
|
|
478
485
|
return container;
|
|
479
486
|
},
|
|
@@ -580,6 +587,7 @@ export class Container
|
|
|
580
587
|
private readonly savedOps: ISequencedDocumentMessage[] = [];
|
|
581
588
|
private baseSnapshot?: ISnapshotTree;
|
|
582
589
|
private baseSnapshotBlobs?: ISerializableBlobContents;
|
|
590
|
+
private readonly _containerId: string;
|
|
583
591
|
|
|
584
592
|
private lastVisible: number | undefined;
|
|
585
593
|
private readonly visibilityEventHandler: (() => void) | undefined;
|
|
@@ -815,6 +823,8 @@ export class Container
|
|
|
815
823
|
const clientType = `${interactive ? "interactive" : "noninteractive"}${
|
|
816
824
|
type !== undefined && type !== "" ? `/${type}` : ""
|
|
817
825
|
}`;
|
|
826
|
+
|
|
827
|
+
this._containerId = uuid();
|
|
818
828
|
// Need to use the property getter for docId because for detached flow we don't have the docId initially.
|
|
819
829
|
// We assign the id later so property getter is used.
|
|
820
830
|
this.subLogger = createChildLogger({
|
|
@@ -822,7 +832,7 @@ export class Container
|
|
|
822
832
|
properties: {
|
|
823
833
|
all: {
|
|
824
834
|
clientType, // Differentiating summarizer container from main container
|
|
825
|
-
containerId:
|
|
835
|
+
containerId: this._containerId,
|
|
826
836
|
docId: () => this.resolvedUrl?.id,
|
|
827
837
|
containerAttachState: () => this._attachState,
|
|
828
838
|
containerLifecycleState: () => this._lifecycleState,
|
|
@@ -1103,12 +1113,17 @@ export class Container
|
|
|
1103
1113
|
}
|
|
1104
1114
|
}
|
|
1105
1115
|
|
|
1106
|
-
public async closeAndGetPendingLocalState(
|
|
1116
|
+
public async closeAndGetPendingLocalState(
|
|
1117
|
+
stopBlobAttachingSignal?: AbortSignal,
|
|
1118
|
+
): Promise<string> {
|
|
1107
1119
|
// runtime matches pending ops to successful ones by clientId and client seq num, so we need to close the
|
|
1108
1120
|
// container at the same time we get pending state, otherwise this container could reconnect and resubmit with
|
|
1109
1121
|
// a new clientId and a future container using stale pending state without the new clientId would resubmit them
|
|
1110
1122
|
this.disconnectInternal({ text: "closeAndGetPendingLocalState" }); // TODO https://dev.azure.com/fluidframework/internal/_workitems/edit/5127
|
|
1111
|
-
const pendingState = await this.getPendingLocalStateCore({
|
|
1123
|
+
const pendingState = await this.getPendingLocalStateCore({
|
|
1124
|
+
notifyImminentClosure: true,
|
|
1125
|
+
stopBlobAttachingSignal,
|
|
1126
|
+
});
|
|
1112
1127
|
this.close();
|
|
1113
1128
|
return pendingState;
|
|
1114
1129
|
}
|
|
@@ -1117,7 +1132,7 @@ export class Container
|
|
|
1117
1132
|
return this.getPendingLocalStateCore({ notifyImminentClosure: false });
|
|
1118
1133
|
}
|
|
1119
1134
|
|
|
1120
|
-
private async getPendingLocalStateCore(props:
|
|
1135
|
+
private async getPendingLocalStateCore(props: IGetPendingLocalStateProps) {
|
|
1121
1136
|
return PerformanceEvent.timedExecAsync(
|
|
1122
1137
|
this.mc.logger,
|
|
1123
1138
|
{
|
|
@@ -1178,7 +1193,7 @@ export class Container
|
|
|
1178
1193
|
const combinedSummary = combineAppAndProtocolSummary(appSummary, protocolSummary);
|
|
1179
1194
|
|
|
1180
1195
|
if (this.detachedBlobStorage && this.detachedBlobStorage.size > 0) {
|
|
1181
|
-
combinedSummary.tree[
|
|
1196
|
+
combinedSummary.tree[hasBlobsSummaryTree] = {
|
|
1182
1197
|
type: SummaryType.Blob,
|
|
1183
1198
|
content: "true",
|
|
1184
1199
|
};
|
|
@@ -1264,7 +1279,7 @@ export class Container
|
|
|
1264
1279
|
}, // progress
|
|
1265
1280
|
);
|
|
1266
1281
|
}
|
|
1267
|
-
|
|
1282
|
+
this.storageAdapter.connectToService(this.service);
|
|
1268
1283
|
|
|
1269
1284
|
if (hasAttachmentBlobs) {
|
|
1270
1285
|
// upload blobs to storage
|
|
@@ -1574,14 +1589,7 @@ export class Container
|
|
|
1574
1589
|
this.connectToDeltaStream(connectionArgs);
|
|
1575
1590
|
}
|
|
1576
1591
|
|
|
1577
|
-
|
|
1578
|
-
await this.storageAdapter.connectToService(this.service);
|
|
1579
|
-
} else {
|
|
1580
|
-
// if we have pendingLocalState we can load without storage; don't wait for connection
|
|
1581
|
-
this.storageAdapter.connectToService(this.service).catch((error) => {
|
|
1582
|
-
this.close(error);
|
|
1583
|
-
});
|
|
1584
|
-
}
|
|
1592
|
+
this.storageAdapter.connectToService(this.service);
|
|
1585
1593
|
|
|
1586
1594
|
this._attachState = AttachState.Attached;
|
|
1587
1595
|
|
|
@@ -1815,12 +1823,13 @@ export class Container
|
|
|
1815
1823
|
}
|
|
1816
1824
|
|
|
1817
1825
|
private async rehydrateDetachedFromSnapshot(detachedContainerSnapshot: ISummaryTree) {
|
|
1818
|
-
if (detachedContainerSnapshot.tree[
|
|
1826
|
+
if (detachedContainerSnapshot.tree[hasBlobsSummaryTree] !== undefined) {
|
|
1819
1827
|
assert(
|
|
1820
1828
|
!!this.detachedBlobStorage && this.detachedBlobStorage.size > 0,
|
|
1821
1829
|
0x250 /* "serialized container with attachment blobs must be rehydrated with detached blob storage" */,
|
|
1822
1830
|
);
|
|
1823
|
-
delete
|
|
1831
|
+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
1832
|
+
delete detachedContainerSnapshot.tree[hasBlobsSummaryTree];
|
|
1824
1833
|
}
|
|
1825
1834
|
|
|
1826
1835
|
const snapshotTree = getSnapshotTreeFromSerializedContainer(detachedContainerSnapshot);
|
|
@@ -2007,6 +2016,7 @@ export class Container
|
|
|
2007
2016
|
client.details.environment = [
|
|
2008
2017
|
client.details.environment,
|
|
2009
2018
|
` loaderVersion:${pkgVersion}`,
|
|
2019
|
+
` containerId:${this._containerId}`,
|
|
2010
2020
|
].join(";");
|
|
2011
2021
|
return client;
|
|
2012
2022
|
}
|
|
@@ -2335,8 +2345,8 @@ export class Container
|
|
|
2335
2345
|
this.emit("op", message);
|
|
2336
2346
|
}
|
|
2337
2347
|
|
|
2338
|
-
private submitSignal(
|
|
2339
|
-
this._deltaManager.submitSignal(JSON.stringify(
|
|
2348
|
+
private submitSignal(content: any, targetClientId?: string) {
|
|
2349
|
+
this._deltaManager.submitSignal(JSON.stringify(content), targetClientId);
|
|
2340
2350
|
}
|
|
2341
2351
|
|
|
2342
2352
|
private processSignal(message: ISignalMessage) {
|
|
@@ -2430,7 +2440,7 @@ export class Container
|
|
|
2430
2440
|
this.submitSummaryMessage(summaryOp, referenceSequenceNumber),
|
|
2431
2441
|
(batch: IBatchMessage[], referenceSequenceNumber?: number) =>
|
|
2432
2442
|
this.submitBatch(batch, referenceSequenceNumber),
|
|
2433
|
-
(
|
|
2443
|
+
(content, targetClientId) => this.submitSignal(content, targetClientId),
|
|
2434
2444
|
(error?: ICriticalContainerError) => this.dispose(error),
|
|
2435
2445
|
(error?: ICriticalContainerError) => this.close(error),
|
|
2436
2446
|
this.updateDirtyContainerState,
|
|
@@ -2513,7 +2523,7 @@ export class Container
|
|
|
2513
2523
|
|
|
2514
2524
|
/**
|
|
2515
2525
|
* IContainer interface that includes experimental features still under development.
|
|
2516
|
-
* @
|
|
2526
|
+
* @alpha
|
|
2517
2527
|
*/
|
|
2518
2528
|
export interface IContainerExperimental extends IContainer {
|
|
2519
2529
|
/**
|
|
@@ -2521,7 +2531,7 @@ export interface IContainerExperimental extends IContainer {
|
|
|
2521
2531
|
* submission and potential document corruption. The blob returned MUST be deleted if and when this
|
|
2522
2532
|
* container emits a "connected" event.
|
|
2523
2533
|
* @returns serialized blob that can be passed to Loader.resolve()
|
|
2524
|
-
* @
|
|
2534
|
+
* @alpha misuse of this API can result in duplicate op submission and potential document corruption
|
|
2525
2535
|
* {@link https://github.com/microsoft/FluidFramework/blob/main/packages/loader/container-loader/closeAndGetPendingLocalState.md}
|
|
2526
2536
|
*/
|
|
2527
2537
|
getPendingLocalState?(): Promise<string>;
|
|
@@ -2529,8 +2539,8 @@ export interface IContainerExperimental extends IContainer {
|
|
|
2529
2539
|
/**
|
|
2530
2540
|
* Closes the container and returns serialized local state intended to be
|
|
2531
2541
|
* given to a newly loaded container.
|
|
2532
|
-
* @
|
|
2542
|
+
* @alpha
|
|
2533
2543
|
* {@link https://github.com/microsoft/FluidFramework/blob/main/packages/loader/container-loader/closeAndGetPendingLocalState.md}
|
|
2534
2544
|
*/
|
|
2535
|
-
closeAndGetPendingLocalState?(): Promise<string>;
|
|
2545
|
+
closeAndGetPendingLocalState?(stopBlobAttachingSignal?: AbortSignal): Promise<string>;
|
|
2536
2546
|
}
|
package/src/containerContext.ts
CHANGED
|
@@ -85,7 +85,7 @@ export class ContainerContext implements IContainerContext {
|
|
|
85
85
|
batch: IBatchMessage[],
|
|
86
86
|
referenceSequenceNumber?: number,
|
|
87
87
|
) => number,
|
|
88
|
-
public readonly submitSignalFn: (
|
|
88
|
+
public readonly submitSignalFn: (content: any, targetClientId?: string) => void,
|
|
89
89
|
public readonly disposeFn: (error?: ICriticalContainerError) => void,
|
|
90
90
|
public readonly closeFn: (error?: ICriticalContainerError) => void,
|
|
91
91
|
public readonly updateDirtyContainerState: (dirty: boolean) => void,
|
|
@@ -79,14 +79,14 @@ export class ContainerStorageAdapter implements IDocumentStorageService, IDispos
|
|
|
79
79
|
this.disposed = true;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
public
|
|
82
|
+
public connectToService(service: IDocumentService): void {
|
|
83
83
|
if (!(this._storageService instanceof BlobOnlyStorage)) {
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
const
|
|
87
|
+
const storageServiceP = service.connectToStorage();
|
|
88
88
|
const retriableStorage = (this._storageService = new RetriableDocumentStorageService(
|
|
89
|
-
|
|
89
|
+
storageServiceP,
|
|
90
90
|
this.logger,
|
|
91
91
|
));
|
|
92
92
|
|
package/src/contracts.ts
CHANGED
|
@@ -100,7 +100,7 @@ export interface IConnectionManager {
|
|
|
100
100
|
* Submits signal to relay service.
|
|
101
101
|
* Called only when active connection is present.
|
|
102
102
|
*/
|
|
103
|
-
submitSignal(content: any): void;
|
|
103
|
+
submitSignal(content: any, targetClientId?: string): void;
|
|
104
104
|
|
|
105
105
|
/**
|
|
106
106
|
* Submits messages to relay service.
|