@fluidframework/container-loader 2.0.0-internal.6.4.0 → 2.0.0-internal.7.1.0
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 +118 -0
- package/api-extractor.json +9 -1
- package/api-report/container-loader.api.md +142 -0
- package/dist/catchUpMonitor.d.ts +2 -2
- package/dist/catchUpMonitor.d.ts.map +1 -1
- package/dist/connectionManager.d.ts +1 -0
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +109 -83
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionState.js +1 -1
- package/dist/connectionState.js.map +1 -1
- package/dist/connectionStateHandler.js +9 -9
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container-loader-alpha.d.ts +297 -0
- package/dist/container-loader-beta.d.ts +297 -0
- package/dist/container-loader-public.d.ts +297 -0
- package/dist/container-loader.d.ts +297 -0
- package/dist/container.d.ts +6 -1
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +215 -215
- package/dist/container.js.map +1 -1
- package/dist/containerContext.js +16 -16
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +6 -8
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +5 -4
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.d.ts.map +1 -1
- package/dist/debugLogger.js +4 -4
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +90 -89
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.js +14 -14
- package/dist/deltaQueue.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +3 -6
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +20 -85
- package/dist/loader.js.map +1 -1
- package/dist/location-redirection-utilities/index.d.ts +6 -0
- package/dist/location-redirection-utilities/index.d.ts.map +1 -0
- package/dist/location-redirection-utilities/index.js +11 -0
- package/dist/location-redirection-utilities/index.js.map +1 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts +22 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js +51 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/protocol.d.ts +1 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +3 -5
- package/dist/protocol.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/catchUpMonitor.d.ts +2 -2
- package/lib/catchUpMonitor.d.ts.map +1 -1
- package/lib/connectionManager.d.ts +1 -0
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +112 -84
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.js +9 -9
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +6 -1
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +216 -216
- package/lib/container.js.map +1 -1
- package/lib/containerContext.js +16 -16
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +6 -8
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +5 -4
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.d.ts.map +1 -1
- package/lib/debugLogger.js +4 -4
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +90 -89
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.js +14 -14
- package/lib/deltaQueue.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 +3 -6
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +20 -85
- package/lib/loader.js.map +1 -1
- package/lib/location-redirection-utilities/index.d.ts +6 -0
- package/lib/location-redirection-utilities/index.d.ts.map +1 -0
- package/lib/location-redirection-utilities/index.js +6 -0
- package/lib/location-redirection-utilities/index.js.map +1 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts +22 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js +46 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -0
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/protocol.d.ts +1 -2
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +1 -3
- package/lib/protocol.js.map +1 -1
- package/package.json +23 -24
- package/src/connectionManager.ts +57 -16
- package/src/container.ts +15 -15
- package/src/containerStorageAdapter.ts +0 -6
- package/src/contracts.ts +8 -4
- package/src/debugLogger.ts +4 -1
- package/src/deltaManager.ts +11 -9
- package/src/index.ts +4 -0
- package/src/loader.ts +24 -92
- package/src/location-redirection-utilities/index.ts +9 -0
- package/src/location-redirection-utilities/resolveWithLocationRedirection.ts +59 -0
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +2 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/container-loader",
|
|
3
|
-
"version": "2.0.0-internal.
|
|
3
|
+
"version": "2.0.0-internal.7.1.0",
|
|
4
4
|
"description": "Fluid container loader",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -35,16 +35,15 @@
|
|
|
35
35
|
"temp-directory": "nyc/.nyc_output"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@fluid-internal/client-utils": ">=2.0.0-internal.
|
|
39
|
-
"@fluidframework/container-definitions": ">=2.0.0-internal.
|
|
40
|
-
"@fluidframework/
|
|
41
|
-
"@fluidframework/core-
|
|
42
|
-
"@fluidframework/
|
|
43
|
-
"@fluidframework/driver-
|
|
44
|
-
"@fluidframework/
|
|
45
|
-
"@fluidframework/protocol-
|
|
46
|
-
"@fluidframework/
|
|
47
|
-
"@fluidframework/telemetry-utils": ">=2.0.0-internal.6.4.0 <2.0.0-internal.6.5.0",
|
|
38
|
+
"@fluid-internal/client-utils": ">=2.0.0-internal.7.1.0 <2.0.0-internal.7.2.0",
|
|
39
|
+
"@fluidframework/container-definitions": ">=2.0.0-internal.7.1.0 <2.0.0-internal.7.2.0",
|
|
40
|
+
"@fluidframework/core-interfaces": ">=2.0.0-internal.7.1.0 <2.0.0-internal.7.2.0",
|
|
41
|
+
"@fluidframework/core-utils": ">=2.0.0-internal.7.1.0 <2.0.0-internal.7.2.0",
|
|
42
|
+
"@fluidframework/driver-definitions": ">=2.0.0-internal.7.1.0 <2.0.0-internal.7.2.0",
|
|
43
|
+
"@fluidframework/driver-utils": ">=2.0.0-internal.7.1.0 <2.0.0-internal.7.2.0",
|
|
44
|
+
"@fluidframework/protocol-base": "^2.0.1",
|
|
45
|
+
"@fluidframework/protocol-definitions": "^3.0.0",
|
|
46
|
+
"@fluidframework/telemetry-utils": ">=2.0.0-internal.7.1.0 <2.0.0-internal.7.2.0",
|
|
48
47
|
"debug": "^4.1.1",
|
|
49
48
|
"double-ended-queue": "^2.1.0-0",
|
|
50
49
|
"events": "^3.1.0",
|
|
@@ -53,14 +52,14 @@
|
|
|
53
52
|
"uuid": "^9.0.0"
|
|
54
53
|
},
|
|
55
54
|
"devDependencies": {
|
|
56
|
-
"@fluid-internal/test-loader-utils": ">=2.0.0-internal.
|
|
57
|
-
"@fluid-tools/build-cli": "^0.
|
|
58
|
-
"@fluidframework/build-common": "^2.0.
|
|
59
|
-
"@fluidframework/build-tools": "^0.
|
|
60
|
-
"@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@2.0.0-internal.
|
|
61
|
-
"@fluidframework/eslint-config-fluid": "^
|
|
62
|
-
"@fluidframework/mocha-test-setup": ">=2.0.0-internal.
|
|
63
|
-
"@microsoft/api-extractor": "^7.
|
|
55
|
+
"@fluid-internal/test-loader-utils": ">=2.0.0-internal.7.1.0 <2.0.0-internal.7.2.0",
|
|
56
|
+
"@fluid-tools/build-cli": "^0.25.0",
|
|
57
|
+
"@fluidframework/build-common": "^2.0.1",
|
|
58
|
+
"@fluidframework/build-tools": "^0.25.0",
|
|
59
|
+
"@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@2.0.0-internal.7.0.0",
|
|
60
|
+
"@fluidframework/eslint-config-fluid": "^3.0.0",
|
|
61
|
+
"@fluidframework/mocha-test-setup": ">=2.0.0-internal.7.1.0 <2.0.0-internal.7.2.0",
|
|
62
|
+
"@microsoft/api-extractor": "^7.37.0",
|
|
64
63
|
"@types/double-ended-queue": "^2.1.0",
|
|
65
64
|
"@types/events": "^3.0.0",
|
|
66
65
|
"@types/lodash": "^4.14.118",
|
|
@@ -70,15 +69,15 @@
|
|
|
70
69
|
"c8": "^7.7.1",
|
|
71
70
|
"copyfiles": "^2.4.1",
|
|
72
71
|
"cross-env": "^7.0.3",
|
|
73
|
-
"eslint": "~8.
|
|
72
|
+
"eslint": "~8.50.0",
|
|
74
73
|
"mocha": "^10.2.0",
|
|
75
74
|
"mocha-json-output-reporter": "^2.0.1",
|
|
76
75
|
"mocha-multi-reporters": "^1.5.1",
|
|
77
76
|
"moment": "^2.21.0",
|
|
78
|
-
"prettier": "~
|
|
77
|
+
"prettier": "~3.0.3",
|
|
79
78
|
"rimraf": "^4.4.0",
|
|
80
79
|
"sinon": "^7.4.2",
|
|
81
|
-
"typescript": "~
|
|
80
|
+
"typescript": "~5.1.6"
|
|
82
81
|
},
|
|
83
82
|
"typeValidation": {
|
|
84
83
|
"broken": {}
|
|
@@ -87,11 +86,11 @@
|
|
|
87
86
|
"build": "fluid-build . --task build",
|
|
88
87
|
"build:commonjs": "fluid-build . --task commonjs",
|
|
89
88
|
"build:compile": "fluid-build . --task compile",
|
|
90
|
-
"build:docs": "api-extractor run --local
|
|
89
|
+
"build:docs": "api-extractor run --local",
|
|
91
90
|
"build:esnext": "tsc --project ./tsconfig.esnext.json",
|
|
92
91
|
"build:genver": "gen-version",
|
|
93
92
|
"build:test": "tsc --project ./src/test/tsconfig.json",
|
|
94
|
-
"ci:build:docs": "api-extractor run
|
|
93
|
+
"ci:build:docs": "api-extractor run",
|
|
95
94
|
"clean": "rimraf --glob 'dist' 'lib' '*.tsbuildinfo' '*.build.log' '_api-extractor-temp' 'nyc'",
|
|
96
95
|
"eslint": "eslint --format stylish src",
|
|
97
96
|
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
|
package/src/connectionManager.ts
CHANGED
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
IDocumentService,
|
|
17
17
|
IDocumentDeltaConnection,
|
|
18
18
|
IDocumentDeltaConnectionEvents,
|
|
19
|
+
// eslint-disable-next-line import/no-deprecated
|
|
20
|
+
DriverErrorType,
|
|
19
21
|
} from "@fluidframework/driver-definitions";
|
|
20
22
|
import {
|
|
21
23
|
canRetryOnError,
|
|
@@ -45,6 +47,7 @@ import {
|
|
|
45
47
|
import {
|
|
46
48
|
formatTick,
|
|
47
49
|
GenericError,
|
|
50
|
+
isFluidError,
|
|
48
51
|
ITelemetryLoggerExt,
|
|
49
52
|
normalizeError,
|
|
50
53
|
UsageError,
|
|
@@ -112,7 +115,15 @@ class NoDeltaStream
|
|
|
112
115
|
blockSize: 0,
|
|
113
116
|
};
|
|
114
117
|
checkpointSequenceNumber?: number | undefined = undefined;
|
|
115
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Connection which is not connected to socket.
|
|
120
|
+
* @param storageOnlyReason - Reason on why the connection to delta stream is not allowed.
|
|
121
|
+
* @param readonlyConnectionReason - reason/error if any which lead to using NoDeltaStream.
|
|
122
|
+
*/
|
|
123
|
+
constructor(
|
|
124
|
+
public readonly storageOnlyReason?: string,
|
|
125
|
+
public readonly readonlyConnectionReason?: IConnectionStateChangeReason,
|
|
126
|
+
) {
|
|
116
127
|
super();
|
|
117
128
|
}
|
|
118
129
|
submit(messages: IDocumentMessage[]): void {
|
|
@@ -409,7 +420,7 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
409
420
|
// Notify everyone we are in read-only state.
|
|
410
421
|
// Useful for data stores in case we hit some critical error,
|
|
411
422
|
// to switch to a mode where user edits are not accepted
|
|
412
|
-
this.set_readonlyPermissions(true, oldReadonlyValue);
|
|
423
|
+
this.set_readonlyPermissions(true, oldReadonlyValue, disconnectReason);
|
|
413
424
|
}
|
|
414
425
|
}
|
|
415
426
|
|
|
@@ -473,10 +484,11 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
473
484
|
private set_readonlyPermissions(
|
|
474
485
|
newReadonlyValue: boolean,
|
|
475
486
|
oldReadonlyValue: boolean | undefined,
|
|
487
|
+
readonlyConnectionReason?: IConnectionStateChangeReason,
|
|
476
488
|
) {
|
|
477
489
|
this._readonlyPermissions = newReadonlyValue;
|
|
478
490
|
if (oldReadonlyValue !== this.readonly) {
|
|
479
|
-
this.props.readonlyChangeHandler(this.readonly);
|
|
491
|
+
this.props.readonlyChangeHandler(this.readonly, readonlyConnectionReason);
|
|
480
492
|
}
|
|
481
493
|
}
|
|
482
494
|
|
|
@@ -575,7 +587,23 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
575
587
|
}
|
|
576
588
|
} catch (origError: any) {
|
|
577
589
|
if (isDeltaStreamConnectionForbiddenError(origError)) {
|
|
578
|
-
connection = new NoDeltaStream(origError.storageOnlyReason
|
|
590
|
+
connection = new NoDeltaStream(origError.storageOnlyReason, {
|
|
591
|
+
text: origError.message,
|
|
592
|
+
error: origError,
|
|
593
|
+
});
|
|
594
|
+
requestedMode = "read";
|
|
595
|
+
break;
|
|
596
|
+
} else if (
|
|
597
|
+
isFluidError(origError) &&
|
|
598
|
+
// eslint-disable-next-line import/no-deprecated
|
|
599
|
+
origError.errorType === DriverErrorType.outOfStorageError
|
|
600
|
+
) {
|
|
601
|
+
// If we get out of storage error from calling joinsession, then use the NoDeltaStream object so
|
|
602
|
+
// that user can at least load the container.
|
|
603
|
+
connection = new NoDeltaStream(undefined, {
|
|
604
|
+
text: origError.message,
|
|
605
|
+
error: origError,
|
|
606
|
+
});
|
|
579
607
|
requestedMode = "read";
|
|
580
608
|
break;
|
|
581
609
|
}
|
|
@@ -708,7 +736,7 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
708
736
|
|
|
709
737
|
// Remove listeners first so we don't try to retrigger this flow accidentally through reconnectOnError
|
|
710
738
|
connection.off("op", this.opHandler);
|
|
711
|
-
connection.off("signal", this.
|
|
739
|
+
connection.off("signal", this.signalHandler);
|
|
712
740
|
connection.off("nack", this.nackHandler);
|
|
713
741
|
connection.off("disconnect", this.disconnectHandlerInternal);
|
|
714
742
|
connection.off("error", this.errorHandler);
|
|
@@ -791,7 +819,11 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
791
819
|
0x0e8 /* "readonly perf with write connection" */,
|
|
792
820
|
);
|
|
793
821
|
|
|
794
|
-
this.set_readonlyPermissions(
|
|
822
|
+
this.set_readonlyPermissions(
|
|
823
|
+
readonly,
|
|
824
|
+
oldReadonlyValue,
|
|
825
|
+
isNoDeltaStreamConnection(connection) ? connection.readonlyConnectionReason : undefined,
|
|
826
|
+
);
|
|
795
827
|
|
|
796
828
|
if (this._disposed) {
|
|
797
829
|
// Raise proper events, Log telemetry event and close connection.
|
|
@@ -802,7 +834,7 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
802
834
|
this._outbound.resume();
|
|
803
835
|
|
|
804
836
|
connection.on("op", this.opHandler);
|
|
805
|
-
connection.on("signal", this.
|
|
837
|
+
connection.on("signal", this.signalHandler);
|
|
806
838
|
connection.on("nack", this.nackHandler);
|
|
807
839
|
connection.on("disconnect", this.disconnectHandlerInternal);
|
|
808
840
|
connection.on("error", this.errorHandler);
|
|
@@ -868,28 +900,32 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
868
900
|
type: SignalType.Clear,
|
|
869
901
|
}),
|
|
870
902
|
};
|
|
871
|
-
this.props.signalHandler(clearSignal);
|
|
872
903
|
|
|
873
|
-
|
|
874
|
-
|
|
904
|
+
// list of signals to process due to this new connection
|
|
905
|
+
let signalsToProcess: ISignalMessage[] = [clearSignal];
|
|
906
|
+
|
|
907
|
+
const clientJoinSignals: ISignalMessage[] = (connection.initialClients ?? []).map(
|
|
908
|
+
(priorClient) => ({
|
|
875
909
|
clientId: null, // system signal
|
|
876
910
|
content: JSON.stringify({
|
|
877
911
|
type: SignalType.ClientJoin,
|
|
878
912
|
content: priorClient, // ISignalClient
|
|
879
913
|
}),
|
|
880
|
-
}
|
|
881
|
-
|
|
914
|
+
}),
|
|
915
|
+
);
|
|
916
|
+
if (clientJoinSignals.length > 0) {
|
|
917
|
+
signalsToProcess = signalsToProcess.concat(clientJoinSignals);
|
|
882
918
|
}
|
|
883
919
|
|
|
884
920
|
// Unfortunately, there is no defined order between initialSignals (including join & leave signals)
|
|
885
921
|
// and connection.initialClients. In practice, connection.initialSignals quite often contains join signal
|
|
886
922
|
// for "self" and connection.initialClients does not contain "self", so we have to process them after
|
|
887
923
|
// "clear" signal above.
|
|
888
|
-
if (connection.initialSignals !== undefined) {
|
|
889
|
-
|
|
890
|
-
this.props.signalHandler(signal);
|
|
891
|
-
}
|
|
924
|
+
if (connection.initialSignals !== undefined && connection.initialSignals.length > 0) {
|
|
925
|
+
signalsToProcess = signalsToProcess.concat(connection.initialSignals);
|
|
892
926
|
}
|
|
927
|
+
|
|
928
|
+
this.props.signalHandler(signalsToProcess);
|
|
893
929
|
}
|
|
894
930
|
|
|
895
931
|
/**
|
|
@@ -1107,6 +1143,11 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
1107
1143
|
this.props.incomingOpHandler(messages, "opHandler");
|
|
1108
1144
|
};
|
|
1109
1145
|
|
|
1146
|
+
private readonly signalHandler = (signalsArg: ISignalMessage | ISignalMessage[]) => {
|
|
1147
|
+
const signals = Array.isArray(signalsArg) ? signalsArg : [signalsArg];
|
|
1148
|
+
this.props.signalHandler(signals);
|
|
1149
|
+
};
|
|
1150
|
+
|
|
1110
1151
|
// Always connect in write mode after getting nacked.
|
|
1111
1152
|
private readonly nackHandler = (documentId: string, messages: INack[]) => {
|
|
1112
1153
|
const message = messages[0];
|
package/src/container.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
TelemetryEventCategory,
|
|
16
16
|
IRequest,
|
|
17
17
|
IResponse,
|
|
18
|
+
// eslint-disable-next-line import/no-deprecated
|
|
18
19
|
IFluidRouter,
|
|
19
20
|
FluidObject,
|
|
20
21
|
LogLevel,
|
|
@@ -121,7 +122,6 @@ import { ConnectionManager } from "./connectionManager";
|
|
|
121
122
|
import { ConnectionState } from "./connectionState";
|
|
122
123
|
import {
|
|
123
124
|
IProtocolHandler,
|
|
124
|
-
OnlyValidTermValue,
|
|
125
125
|
ProtocolHandler,
|
|
126
126
|
ProtocolHandlerBuilder,
|
|
127
127
|
protocolHandlerShouldProcessSignal,
|
|
@@ -359,7 +359,6 @@ export interface IPendingContainerState {
|
|
|
359
359
|
*/
|
|
360
360
|
savedOps: ISequencedDocumentMessage[];
|
|
361
361
|
url: string;
|
|
362
|
-
term: number;
|
|
363
362
|
clientId?: string;
|
|
364
363
|
}
|
|
365
364
|
|
|
@@ -595,6 +594,10 @@ export class Container
|
|
|
595
594
|
return this._deltaManager.connectionManager.connectionMode;
|
|
596
595
|
}
|
|
597
596
|
|
|
597
|
+
/**
|
|
598
|
+
* @deprecated Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
599
|
+
*/
|
|
600
|
+
// eslint-disable-next-line import/no-deprecated
|
|
598
601
|
public get IFluidRouter(): IFluidRouter {
|
|
599
602
|
return this;
|
|
600
603
|
}
|
|
@@ -1151,7 +1154,6 @@ export class Container
|
|
|
1151
1154
|
snapshotBlobs: this.baseSnapshotBlobs,
|
|
1152
1155
|
savedOps: this.savedOps,
|
|
1153
1156
|
url: this.resolvedUrl.url,
|
|
1154
|
-
term: OnlyValidTermValue,
|
|
1155
1157
|
// no need to save this if there is no pending runtime state
|
|
1156
1158
|
clientId: pendingRuntimeState !== undefined ? this.clientId : undefined,
|
|
1157
1159
|
};
|
|
@@ -1333,6 +1335,9 @@ export class Container
|
|
|
1333
1335
|
);
|
|
1334
1336
|
}
|
|
1335
1337
|
|
|
1338
|
+
/**
|
|
1339
|
+
* @deprecated Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
1340
|
+
*/
|
|
1336
1341
|
public async request(path: IRequest): Promise<IResponse> {
|
|
1337
1342
|
return PerformanceEvent.timedExecAsync(
|
|
1338
1343
|
this.mc.logger,
|
|
@@ -1551,18 +1556,15 @@ export class Container
|
|
|
1551
1556
|
this.client.details.type === summarizerClientType,
|
|
1552
1557
|
);
|
|
1553
1558
|
|
|
1554
|
-
//
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
// connections to same file) in two ways:
|
|
1561
|
-
// A) creation flow breaks (as one of the clients "sees" file as existing, and hits #2 above)
|
|
1562
|
-
// B) Once file is created, transition from view-only connection to write does not work - some bugs to be fixed.
|
|
1559
|
+
// Except in cases where it has stashed ops or requested by feature gate, the container will connect in "read" mode
|
|
1560
|
+
const mode =
|
|
1561
|
+
this.mc.config.getBoolean("Fluid.Container.ForceWriteConnection") === true ||
|
|
1562
|
+
(pendingLocalState?.savedOps.length ?? 0) > 0
|
|
1563
|
+
? "write"
|
|
1564
|
+
: "read";
|
|
1563
1565
|
const connectionArgs: IConnectionArgs = {
|
|
1564
1566
|
reason: { text: "DocumentOpen" },
|
|
1565
|
-
mode
|
|
1567
|
+
mode,
|
|
1566
1568
|
fetchOpsFromStorage: false,
|
|
1567
1569
|
};
|
|
1568
1570
|
|
|
@@ -1791,7 +1793,6 @@ export class Container
|
|
|
1791
1793
|
private async createDetached(codeDetails: IFluidCodeDetails) {
|
|
1792
1794
|
const attributes: IDocumentAttributes = {
|
|
1793
1795
|
sequenceNumber: detachedContainerRefSeqNumber,
|
|
1794
|
-
term: OnlyValidTermValue,
|
|
1795
1796
|
minimumSequenceNumber: 0,
|
|
1796
1797
|
};
|
|
1797
1798
|
|
|
@@ -1857,7 +1858,6 @@ export class Container
|
|
|
1857
1858
|
return {
|
|
1858
1859
|
minimumSequenceNumber: 0,
|
|
1859
1860
|
sequenceNumber: 0,
|
|
1860
|
-
term: OnlyValidTermValue,
|
|
1861
1861
|
};
|
|
1862
1862
|
}
|
|
1863
1863
|
|
|
@@ -99,12 +99,6 @@ export class ContainerStorageAdapter implements IDocumentStorageService, IDispos
|
|
|
99
99
|
this.addProtocolSummaryIfMissing,
|
|
100
100
|
);
|
|
101
101
|
}
|
|
102
|
-
|
|
103
|
-
// ensure we did not lose that policy in the process of wrapping
|
|
104
|
-
assert(
|
|
105
|
-
storageService.policies?.minBlobSize === this._storageService.policies?.minBlobSize,
|
|
106
|
-
0x0e0 /* "lost minBlobSize policy" */,
|
|
107
|
-
);
|
|
108
102
|
}
|
|
109
103
|
|
|
110
104
|
public loadSnapshotForRehydratingContainer(snapshotTree: ISnapshotTreeWithBlobContents) {
|
package/src/contracts.ts
CHANGED
|
@@ -133,10 +133,10 @@ export interface IConnectionManagerFactoryArgs {
|
|
|
133
133
|
readonly incomingOpHandler: (messages: ISequencedDocumentMessage[], reason: string) => void;
|
|
134
134
|
|
|
135
135
|
/**
|
|
136
|
-
* Called by connection manager for each incoming
|
|
137
|
-
*
|
|
136
|
+
* Called by connection manager for each incoming signal.
|
|
137
|
+
* May be called before connectHandler is called (due to initial signals on socket connection)
|
|
138
138
|
*/
|
|
139
|
-
readonly signalHandler: (
|
|
139
|
+
readonly signalHandler: (signals: ISignalMessage[]) => void;
|
|
140
140
|
|
|
141
141
|
/**
|
|
142
142
|
* Called when connection manager experiences delay in connecting to relay service.
|
|
@@ -179,8 +179,12 @@ export interface IConnectionManagerFactoryArgs {
|
|
|
179
179
|
*
|
|
180
180
|
* @param readonly - Whether or not the container is now read-only.
|
|
181
181
|
* `undefined` indicates that user permissions are not yet known.
|
|
182
|
+
* @param readonlyConnectionReason - reason/error if any for the change
|
|
182
183
|
*/
|
|
183
|
-
readonly readonlyChangeHandler: (
|
|
184
|
+
readonly readonlyChangeHandler: (
|
|
185
|
+
readonly?: boolean,
|
|
186
|
+
readonlyConnectionReason?: IConnectionStateChangeReason,
|
|
187
|
+
) => void;
|
|
184
188
|
|
|
185
189
|
/**
|
|
186
190
|
* Called whenever we try to start establishing a new connection.
|
package/src/debugLogger.ts
CHANGED
|
@@ -60,7 +60,10 @@ export class DebugLogger implements ITelemetryBaseLogger {
|
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
private constructor(
|
|
63
|
+
private constructor(
|
|
64
|
+
private readonly debug: IDebugger,
|
|
65
|
+
private readonly debugErr: IDebugger,
|
|
66
|
+
) {}
|
|
64
67
|
|
|
65
68
|
/**
|
|
66
69
|
* Send an event to debug loggers
|
package/src/deltaManager.ts
CHANGED
|
@@ -50,7 +50,6 @@ import {
|
|
|
50
50
|
IConnectionStateChangeReason,
|
|
51
51
|
} from "./contracts";
|
|
52
52
|
import { DeltaQueue } from "./deltaQueue";
|
|
53
|
-
import { OnlyValidTermValue } from "./protocol";
|
|
54
53
|
import { ThrottlingWarning } from "./error";
|
|
55
54
|
|
|
56
55
|
export interface IConnectionArgs {
|
|
@@ -403,7 +402,11 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
403
402
|
this.close(normalizeError(error));
|
|
404
403
|
}
|
|
405
404
|
},
|
|
406
|
-
signalHandler: (
|
|
405
|
+
signalHandler: (signals: ISignalMessage[]) => {
|
|
406
|
+
for (const signal of signals) {
|
|
407
|
+
this._inboundSignal.push(signal);
|
|
408
|
+
}
|
|
409
|
+
},
|
|
407
410
|
reconnectionDelayHandler: (delayMs: number, error: unknown) =>
|
|
408
411
|
this.emitDelayInfo(this.deltaStreamDelayId, delayMs, error),
|
|
409
412
|
closeHandler: (error: any) => this.close(error),
|
|
@@ -412,8 +415,12 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
412
415
|
connectHandler: (connection: IConnectionDetailsInternal) =>
|
|
413
416
|
this.connectHandler(connection),
|
|
414
417
|
pongHandler: (latency: number) => this.emit("pong", latency),
|
|
415
|
-
readonlyChangeHandler: (
|
|
416
|
-
|
|
418
|
+
readonlyChangeHandler: (
|
|
419
|
+
readonly?: boolean,
|
|
420
|
+
readonlyConnectionReason?: IConnectionStateChangeReason,
|
|
421
|
+
) => {
|
|
422
|
+
safeRaiseEvent(this, this.logger, "readonly", readonly, readonlyConnectionReason);
|
|
423
|
+
},
|
|
417
424
|
establishConnectionHandler: (reason: IConnectionStateChangeReason) =>
|
|
418
425
|
this.establishingConnection(reason),
|
|
419
426
|
cancelConnectionHandler: (reason: IConnectionStateChangeReason) =>
|
|
@@ -1059,11 +1066,6 @@ export class DeltaManager<TConnectionManager extends IConnectionManager>
|
|
|
1059
1066
|
0x267 /* "lastObservedSeqNumber should be updated first" */,
|
|
1060
1067
|
);
|
|
1061
1068
|
|
|
1062
|
-
// Back-compat for older server with no term
|
|
1063
|
-
if (message.term === undefined) {
|
|
1064
|
-
message.term = OnlyValidTermValue;
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
1069
|
if (this.handler === undefined) {
|
|
1068
1070
|
throw new Error("Attempted to process an inbound message without a handler attached");
|
|
1069
1071
|
}
|
package/src/index.ts
CHANGED
|
@@ -15,4 +15,8 @@ export {
|
|
|
15
15
|
Loader,
|
|
16
16
|
requestResolvedObjectFromContainer,
|
|
17
17
|
} from "./loader";
|
|
18
|
+
export {
|
|
19
|
+
isLocationRedirectionError,
|
|
20
|
+
resolveWithLocationRedirectionHandling,
|
|
21
|
+
} from "./location-redirection-utilities";
|
|
18
22
|
export { IProtocolHandler, ProtocolHandlerBuilder } from "./protocol";
|
package/src/loader.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
import {
|
|
18
18
|
ITelemetryBaseLogger,
|
|
19
19
|
FluidObject,
|
|
20
|
+
// eslint-disable-next-line import/no-deprecated
|
|
20
21
|
IFluidRouter,
|
|
21
22
|
IRequest,
|
|
22
23
|
IRequestHeader,
|
|
@@ -45,10 +46,6 @@ import { pkgVersion } from "./packageVersion";
|
|
|
45
46
|
import { ProtocolHandlerBuilder } from "./protocol";
|
|
46
47
|
import { DebugLogger } from "./debugLogger";
|
|
47
48
|
|
|
48
|
-
function canUseCache(request: IRequest): boolean {
|
|
49
|
-
return request.headers?.[LoaderHeader.cache] === true;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
49
|
function ensureResolvedUrlDefined(
|
|
53
50
|
resolved: IResolvedUrl | undefined,
|
|
54
51
|
): asserts resolved is IResolvedUrl {
|
|
@@ -68,29 +65,26 @@ export class RelativeLoader implements ILoader {
|
|
|
68
65
|
/**
|
|
69
66
|
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the Container's IFluidRouter/request.
|
|
70
67
|
*/
|
|
68
|
+
// eslint-disable-next-line import/no-deprecated
|
|
71
69
|
public get IFluidRouter(): IFluidRouter {
|
|
72
70
|
return this;
|
|
73
71
|
}
|
|
74
72
|
|
|
75
73
|
public async resolve(request: IRequest): Promise<IContainer> {
|
|
76
74
|
if (request.url.startsWith("/")) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
},
|
|
91
|
-
);
|
|
92
|
-
return container;
|
|
93
|
-
}
|
|
75
|
+
ensureResolvedUrlDefined(this.container.resolvedUrl);
|
|
76
|
+
const container = await this.container.clone(
|
|
77
|
+
{
|
|
78
|
+
resolvedUrl: { ...this.container.resolvedUrl },
|
|
79
|
+
version: request.headers?.[LoaderHeader.version] ?? undefined,
|
|
80
|
+
loadMode: request.headers?.[LoaderHeader.loadMode],
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
canReconnect: request.headers?.[LoaderHeader.reconnect],
|
|
84
|
+
clientDetailsOverride: request.headers?.[LoaderHeader.clientDetails],
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
return container;
|
|
94
88
|
}
|
|
95
89
|
|
|
96
90
|
if (this.loader === undefined) {
|
|
@@ -100,7 +94,7 @@ export class RelativeLoader implements ILoader {
|
|
|
100
94
|
}
|
|
101
95
|
|
|
102
96
|
/**
|
|
103
|
-
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the
|
|
97
|
+
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
104
98
|
*/
|
|
105
99
|
public async request(request: IRequest): Promise<IResponse> {
|
|
106
100
|
if (request.url.startsWith("/")) {
|
|
@@ -279,6 +273,7 @@ export type IDetachedBlobStorage = Pick<IDocumentStorageService, "createBlob" |
|
|
|
279
273
|
* With an already-resolved container, we can request a component directly, without loading the container again
|
|
280
274
|
* @param container - a resolved container
|
|
281
275
|
* @returns component on the container
|
|
276
|
+
* @deprecated Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
282
277
|
*/
|
|
283
278
|
export async function requestResolvedObjectFromContainer(
|
|
284
279
|
container: IContainer,
|
|
@@ -291,6 +286,7 @@ export async function requestResolvedObjectFromContainer(
|
|
|
291
286
|
throw new Error(`Invalid URL ${container.resolvedUrl.url}`);
|
|
292
287
|
}
|
|
293
288
|
|
|
289
|
+
// eslint-disable-next-line import/no-deprecated
|
|
294
290
|
const entryPoint: FluidObject<IFluidRouter> | undefined = await container.getEntryPoint?.();
|
|
295
291
|
const router = entryPoint?.IFluidRouter ?? container.IFluidRouter;
|
|
296
292
|
|
|
@@ -304,7 +300,6 @@ export async function requestResolvedObjectFromContainer(
|
|
|
304
300
|
* Manages Fluid resource loading
|
|
305
301
|
*/
|
|
306
302
|
export class Loader implements IHostLoader {
|
|
307
|
-
private readonly containers = new Map<string, Promise<Container>>();
|
|
308
303
|
public readonly services: ILoaderServices;
|
|
309
304
|
private readonly mc: MonitoringContext;
|
|
310
305
|
|
|
@@ -354,6 +349,7 @@ export class Loader implements IHostLoader {
|
|
|
354
349
|
/**
|
|
355
350
|
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the Container's IFluidRouter/request.
|
|
356
351
|
*/
|
|
352
|
+
// eslint-disable-next-line import/no-deprecated
|
|
357
353
|
public get IFluidRouter(): IFluidRouter {
|
|
358
354
|
return this;
|
|
359
355
|
}
|
|
@@ -365,25 +361,13 @@ export class Loader implements IHostLoader {
|
|
|
365
361
|
clientDetailsOverride?: IClientDetails;
|
|
366
362
|
},
|
|
367
363
|
): Promise<IContainer> {
|
|
368
|
-
|
|
364
|
+
return Container.createDetached(
|
|
369
365
|
{
|
|
370
366
|
...createDetachedProps,
|
|
371
367
|
...this.services,
|
|
372
368
|
},
|
|
373
369
|
codeDetails,
|
|
374
370
|
);
|
|
375
|
-
|
|
376
|
-
if (this.cachingEnabled) {
|
|
377
|
-
container.once("attached", () => {
|
|
378
|
-
ensureResolvedUrlDefined(container.resolvedUrl);
|
|
379
|
-
const parsedUrl = parseUrl(container.resolvedUrl.url);
|
|
380
|
-
if (parsedUrl !== undefined) {
|
|
381
|
-
this.addToContainerCache(parsedUrl.id, Promise.resolve(container));
|
|
382
|
-
}
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
return container;
|
|
387
371
|
}
|
|
388
372
|
|
|
389
373
|
public async rehydrateDetachedContainerFromSnapshot(
|
|
@@ -430,37 +414,6 @@ export class Loader implements IHostLoader {
|
|
|
430
414
|
);
|
|
431
415
|
}
|
|
432
416
|
|
|
433
|
-
private getKeyForContainerCache(request: IRequest, parsedUrl: IParsedUrl): string {
|
|
434
|
-
const key =
|
|
435
|
-
request.headers?.[LoaderHeader.version] !== undefined
|
|
436
|
-
? `${parsedUrl.id}@${request.headers[LoaderHeader.version]}`
|
|
437
|
-
: parsedUrl.id;
|
|
438
|
-
return key;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
private addToContainerCache(key: string, containerP: Promise<Container>) {
|
|
442
|
-
this.containers.set(key, containerP);
|
|
443
|
-
containerP
|
|
444
|
-
.then((container) => {
|
|
445
|
-
// If the container is closed/disposed or becomes closed/disposed after we resolve it,
|
|
446
|
-
// remove it from the cache.
|
|
447
|
-
if (container.closed || container.disposed) {
|
|
448
|
-
this.containers.delete(key);
|
|
449
|
-
} else {
|
|
450
|
-
container.once("closed", () => {
|
|
451
|
-
this.containers.delete(key);
|
|
452
|
-
});
|
|
453
|
-
container.once("disposed", () => {
|
|
454
|
-
this.containers.delete(key);
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
|
-
})
|
|
458
|
-
.catch((error) => {
|
|
459
|
-
// If an error occured while resolving the container request, then remove it from the cache.
|
|
460
|
-
this.containers.delete(key);
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
|
|
464
417
|
private async resolveCore(
|
|
465
418
|
request: IRequest,
|
|
466
419
|
pendingLocalState?: IPendingContainerState,
|
|
@@ -489,11 +442,6 @@ export class Loader implements IHostLoader {
|
|
|
489
442
|
// If set in both query string and headers, use query string. Also write the value from the query string into the header either way.
|
|
490
443
|
request.headers[LoaderHeader.version] =
|
|
491
444
|
parsed.version ?? request.headers[LoaderHeader.version];
|
|
492
|
-
const cacheHeader = request.headers[LoaderHeader.cache];
|
|
493
|
-
const canCache =
|
|
494
|
-
// Take header value if present, else use ILoaderOptions.cache value
|
|
495
|
-
(cacheHeader !== undefined ? cacheHeader === true : this.cachingEnabled) &&
|
|
496
|
-
pendingLocalState === undefined;
|
|
497
445
|
const fromSequenceNumber = request.headers[LoaderHeader.sequenceNumber] as
|
|
498
446
|
| number
|
|
499
447
|
| undefined;
|
|
@@ -513,26 +461,10 @@ export class Loader implements IHostLoader {
|
|
|
513
461
|
throw new UsageError('opsBeforeReturn must be set to "sequenceNumber"');
|
|
514
462
|
}
|
|
515
463
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
if (maybeContainer !== undefined) {
|
|
521
|
-
container = maybeContainer;
|
|
522
|
-
} else {
|
|
523
|
-
const containerP = this.loadContainer(request, resolvedAsFluid);
|
|
524
|
-
this.addToContainerCache(key, containerP);
|
|
525
|
-
container = await containerP;
|
|
526
|
-
}
|
|
527
|
-
} else {
|
|
528
|
-
container = await this.loadContainer(request, resolvedAsFluid, pendingLocalState);
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
return { container, parsed };
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
private get cachingEnabled() {
|
|
535
|
-
return this.services.options.cache === true;
|
|
464
|
+
return {
|
|
465
|
+
container: await this.loadContainer(request, resolvedAsFluid, pendingLocalState),
|
|
466
|
+
parsed,
|
|
467
|
+
};
|
|
536
468
|
}
|
|
537
469
|
|
|
538
470
|
private async loadContainer(
|