@fluidframework/container-loader 0.54.2 → 0.56.0-49831
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +1 -1
- package/dist/connectionStateHandler.d.ts +1 -0
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +11 -2
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +6 -12
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +50 -58
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +11 -3
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +12 -6
- 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.map +1 -1
- package/dist/deltaManager.d.ts +0 -11
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +0 -13
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaManagerProxy.d.ts +0 -1
- package/dist/deltaManagerProxy.d.ts.map +1 -1
- package/dist/deltaManagerProxy.js +0 -3
- package/dist/deltaManagerProxy.js.map +1 -1
- package/dist/loader.d.ts +3 -3
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.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/retriableDocumentStorageService.d.ts +1 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +1 -0
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +11 -2
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +6 -12
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +52 -60
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +11 -3
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +12 -6
- 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.map +1 -1
- package/lib/deltaManager.d.ts +0 -11
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +0 -13
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaManagerProxy.d.ts +0 -1
- package/lib/deltaManagerProxy.d.ts.map +1 -1
- package/lib/deltaManagerProxy.js +0 -3
- package/lib/deltaManagerProxy.js.map +1 -1
- package/lib/loader.d.ts +3 -3
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.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/retriableDocumentStorageService.d.ts +1 -1
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/package.json +19 -18
- package/src/connectionStateHandler.ts +13 -3
- package/src/container.ts +71 -69
- package/src/containerContext.ts +18 -9
- package/src/containerStorageAdapter.ts +1 -1
- package/src/deltaManager.ts +0 -14
- package/src/deltaManagerProxy.ts +0 -4
- package/src/loader.ts +3 -3
- package/src/packageVersion.ts +1 -1
- package/src/retriableDocumentStorageService.ts +1 -1
package/.eslintrc.js
CHANGED
|
@@ -35,6 +35,7 @@ export declare class ConnectionStateHandler {
|
|
|
35
35
|
private startJoinOpTimer;
|
|
36
36
|
private stopJoinOpTimer;
|
|
37
37
|
dispose(): void;
|
|
38
|
+
containerSaved(): void;
|
|
38
39
|
receivedAddMemberEvent(clientId: string): void;
|
|
39
40
|
private applyForConnectedState;
|
|
40
41
|
receivedRemoveMemberEvent(clientId: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectionStateHandler.d.ts","sourceRoot":"","sources":["../src/connectionStateHandler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAGxF,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,uBAAuB;IACpC,eAAe,EAAE,MAAM,iBAAiB,GAAG,SAAS,CAAC;IACrD,iCAAiC,EAC7B,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC7F,qBAAqB,EAAE,MAAM,OAAO,CAAC;IACrC,sBAAsB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,sBAAsB,EAAE,MAAM,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC3D,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B;AAID,qBAAa,sBAAsB;IA0B3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IA1B3B,OAAO,CAAC,gBAAgB,CAAgC;IACxD,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAQ;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAEpC,OAAO,CAAC,SAAS,CAA+B;IAEhD,IAAW,eAAe,IAAI,eAAe,CAE5C;IAED,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED,IAAW,QAAQ,IAAI,MAAM,GAAG,SAAS,CAExC;IAED,IAAW,eAAe,IAAI,MAAM,GAAG,SAAS,CAE/C;gBAGoB,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,gBAAgB;
|
|
1
|
+
{"version":3,"file":"connectionStateHandler.d.ts","sourceRoot":"","sources":["../src/connectionStateHandler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAGxF,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,uBAAuB;IACpC,eAAe,EAAE,MAAM,iBAAiB,GAAG,SAAS,CAAC;IACrD,iCAAiC,EAC7B,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC7F,qBAAqB,EAAE,MAAM,OAAO,CAAC;IACrC,sBAAsB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,sBAAsB,EAAE,MAAM,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC3D,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B;AAID,qBAAa,sBAAsB;IA0B3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IA1B3B,OAAO,CAAC,gBAAgB,CAAgC;IACxD,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAQ;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAEpC,OAAO,CAAC,SAAS,CAA+B;IAEhD,IAAW,eAAe,IAAI,eAAe,CAE5C;IAED,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED,IAAW,QAAQ,IAAI,MAAM,GAAG,SAAS,CAExC;IAED,IAAW,eAAe,IAAI,MAAM,GAAG,SAAS,CAE/C;gBAGoB,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,gBAAgB;IA4B7C,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,eAAe;IAKhB,OAAO;IAKP,cAAc;IASd,sBAAsB,CAAC,QAAQ,EAAE,MAAM;IAsB9C,OAAO,CAAC,sBAAsB;IA4BvB,yBAAyB,CAAC,QAAQ,EAAE,MAAM;IAQ1C,uBAAuB,CAAC,MAAM,EAAE,MAAM;IAOtC,oBAAoB,CACvB,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,kBAAkB;IAgC/B,OAAO,CAAC,kBAAkB;CAuD7B"}
|
|
@@ -16,8 +16,9 @@ class ConnectionStateHandler {
|
|
|
16
16
|
this.logger = logger;
|
|
17
17
|
this._connectionState = container_1.ConnectionState.Disconnected;
|
|
18
18
|
this.prevClientLeftTimer = new common_utils_1.Timer((_a =
|
|
19
|
-
// Default is
|
|
20
|
-
|
|
19
|
+
// Default is 5 min for which we are going to wait for its own "leave" message. This is same as
|
|
20
|
+
// the max time on server after which leave op is sent.
|
|
21
|
+
this.handler.maxClientLeaveWaitTime) !== null && _a !== void 0 ? _a : 300000, () => {
|
|
21
22
|
common_utils_1.assert(!this.connected, 0x2ac /* "Connected when timeout waiting for leave from previous session fired!" */);
|
|
22
23
|
this.applyForConnectedState("timeout");
|
|
23
24
|
});
|
|
@@ -56,6 +57,14 @@ class ConnectionStateHandler {
|
|
|
56
57
|
common_utils_1.assert(!this.joinOpTimer.hasTimer, 0x2a5 /* "join timer" */);
|
|
57
58
|
this.prevClientLeftTimer.clear();
|
|
58
59
|
}
|
|
60
|
+
containerSaved() {
|
|
61
|
+
// If we were waiting for moving to Connected state, then only apply for state change. Since the container
|
|
62
|
+
// is now saved and we don't have any ops to roundtrip, we can clear the timer and apply for connected state.
|
|
63
|
+
if (this.prevClientLeftTimer.hasTimer) {
|
|
64
|
+
this.prevClientLeftTimer.clear();
|
|
65
|
+
this.applyForConnectedState("containerSaved");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
59
68
|
receivedAddMemberEvent(clientId) {
|
|
60
69
|
// This is the only one that requires the pending client ID
|
|
61
70
|
if (clientId === this.pendingClientId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectionStateHandler.js","sourceRoot":"","sources":["../src/connectionStateHandler.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { IConnectionDetails } from \"@fluidframework/container-definitions\";\nimport { ProtocolOpHandler } from \"@fluidframework/protocol-base\";\nimport { ConnectionMode, ISequencedClient } from \"@fluidframework/protocol-definitions\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { assert, Timer } from \"@fluidframework/common-utils\";\nimport { ConnectionState } from \"./container\";\n\nexport interface IConnectionStateHandler {\n protocolHandler: () => ProtocolOpHandler | undefined,\n logConnectionStateChangeTelemetry:\n (value: ConnectionState, oldState: ConnectionState, reason?: string | undefined) => void,\n shouldClientJoinWrite: () => boolean,\n maxClientLeaveWaitTime: number | undefined,\n logConnectionIssue: (eventName: string) => void,\n connectionStateChanged: () => void,\n}\n\nexport interface ILocalSequencedClient extends ISequencedClient {\n shouldHaveLeft?: boolean;\n}\n\nconst JoinOpTimer = 45000;\n\nexport class ConnectionStateHandler {\n private _connectionState = ConnectionState.Disconnected;\n private _pendingClientId: string | undefined;\n private _clientId: string | undefined;\n private readonly prevClientLeftTimer: Timer;\n private readonly joinOpTimer: Timer;\n\n private waitEvent: PerformanceEvent | undefined;\n\n public get connectionState(): ConnectionState {\n return this._connectionState;\n }\n\n public get connected(): boolean {\n return this.connectionState === ConnectionState.Connected;\n }\n\n public get clientId(): string | undefined {\n return this._clientId;\n }\n\n public get pendingClientId(): string | undefined {\n return this._pendingClientId;\n }\n\n constructor(\n private readonly handler: IConnectionStateHandler,\n private readonly logger: ITelemetryLogger,\n ) {\n this.prevClientLeftTimer = new Timer(\n // Default is 90 sec for which we are going to wait for its own \"leave\" message.\n this.handler.maxClientLeaveWaitTime ?? 90000,\n () => {\n assert(!this.connected,\n 0x2ac /* \"Connected when timeout waiting for leave from previous session fired!\" */);\n this.applyForConnectedState(\"timeout\");\n },\n );\n\n // Based on recent data, it looks like majority of cases where we get stuck are due to really slow or\n // timing out ops fetches. So attempt recovery infrequently. Also fetch uses 30 second timeout, so\n // if retrying fixes the problem, we should not see these events.\n this.joinOpTimer = new Timer(\n JoinOpTimer,\n () => {\n // I've observed timer firing within couple ms from disconnect event, looks like\n // queued timer callback is not cancelled if timer is cancelled while callback sits in the queue.\n if (this.connectionState === ConnectionState.Connecting) {\n this.handler.logConnectionIssue(\"NoJoinOp\");\n }\n },\n );\n }\n\n private startJoinOpTimer() {\n assert(!this.joinOpTimer.hasTimer, 0x234 /* \"has joinOpTimer\" */);\n this.joinOpTimer.start();\n }\n\n private stopJoinOpTimer() {\n assert(this.joinOpTimer.hasTimer, 0x235 /* \"no joinOpTimer\" */);\n this.joinOpTimer.clear();\n }\n\n public dispose() {\n assert(!this.joinOpTimer.hasTimer, 0x2a5 /* \"join timer\" */);\n this.prevClientLeftTimer.clear();\n }\n\n public receivedAddMemberEvent(clientId: string) {\n // This is the only one that requires the pending client ID\n if (clientId === this.pendingClientId) {\n if (this.joinOpTimer.hasTimer) {\n this.stopJoinOpTimer();\n } else {\n // timer has already fired, meaning it took too long to get join on.\n // Record how long it actually took to recover.\n this.handler.logConnectionIssue(\"ReceivedJoinOp\");\n }\n // Start the event in case we are waiting for leave or timeout.\n if (this.prevClientLeftTimer.hasTimer) {\n this.waitEvent = PerformanceEvent.start(this.logger, {\n eventName: \"WaitBeforeClientLeave\",\n waitOnClientId: this._clientId,\n hadOutstandingOps: this.handler.shouldClientJoinWrite(),\n });\n }\n this.applyForConnectedState(\"addMemberEvent\");\n }\n }\n\n private applyForConnectedState(source: \"removeMemberEvent\" | \"addMemberEvent\" | \"timeout\") {\n const protocolHandler = this.handler.protocolHandler();\n assert(protocolHandler !== undefined, 0x236 /* \"In all cases it should be already installed\" */);\n // Move to connected state only if we are in Connecting state, we have seen our join op\n // and there is no timer running which means we are not waiting for previous client to leave\n // or timeout has occured while doing so.\n if (this.pendingClientId !== this.clientId\n && this.pendingClientId !== undefined\n && protocolHandler.quorum.getMember(this.pendingClientId) !== undefined\n && !this.prevClientLeftTimer.hasTimer\n ) {\n this.waitEvent?.end({ source });\n this.setConnectionState(ConnectionState.Connected);\n } else {\n // Adding this event temporarily so that we can get help debugging if something goes wrong.\n this.logger.sendTelemetryEvent({\n eventName: \"connectedStateRejected\",\n category: source === \"timeout\" ? \"error\" : \"generic\",\n source,\n pendingClientId: this.pendingClientId,\n clientId: this.clientId,\n hasTimer: this.prevClientLeftTimer.hasTimer,\n inQuorum: protocolHandler !== undefined && this.pendingClientId !== undefined\n && protocolHandler.quorum.getMember(this.pendingClientId) !== undefined,\n });\n }\n }\n\n public receivedRemoveMemberEvent(clientId: string) {\n // If the client which has left was us, then finish the timer.\n if (this.clientId === clientId) {\n this.prevClientLeftTimer.clear();\n this.applyForConnectedState(\"removeMemberEvent\");\n }\n }\n\n public receivedDisconnectEvent(reason: string) {\n if (this.joinOpTimer.hasTimer) {\n this.stopJoinOpTimer();\n }\n this.setConnectionState(ConnectionState.Disconnected, reason);\n }\n\n public receivedConnectEvent(\n connectionMode: ConnectionMode,\n details: IConnectionDetails,\n ) {\n const oldState = this._connectionState;\n this._connectionState = ConnectionState.Connecting;\n\n // Stash the clientID to detect when transitioning from connecting (socket.io channel open) to connected\n // (have received the join message for the client ID)\n // This is especially important in the reconnect case. It's possible there could be outstanding\n // ops sent by this client, so we should keep the old client id until we see our own client's\n // join message. after we see the join message for out new connection with our new client id,\n // we know there can no longer be outstanding ops that we sent with the previous client id.\n this._pendingClientId = details.clientId;\n\n // Report telemetry after we set client id, but before transitioning to Connected state below!\n this.handler.logConnectionStateChangeTelemetry(ConnectionState.Connecting, oldState);\n\n const protocolHandler = this.handler.protocolHandler();\n // Check if we already processed our own join op through delta storage!\n // we are fetching ops from storage in parallel to connecting to ordering service\n // Given async processes, it's possible that we have already processed our own join message before\n // connection was fully established.\n // Note that we might be still initializing quorum - connection is established proactively on load!\n if ((protocolHandler !== undefined && protocolHandler.quorum.getMember(details.clientId) !== undefined)\n || connectionMode === \"read\"\n ) {\n assert(!this.prevClientLeftTimer.hasTimer, 0x2a6 /* \"there should be no timer for 'read' connections\" */);\n this.setConnectionState(ConnectionState.Connected);\n } else if (connectionMode === \"write\") {\n this.startJoinOpTimer();\n }\n }\n\n private setConnectionState(value: ConnectionState.Disconnected, reason: string);\n private setConnectionState(value: ConnectionState.Connected);\n private setConnectionState(value: ConnectionState, reason?: string) {\n if (this.connectionState === value) {\n // Already in the desired state - exit early\n this.logger.sendErrorEvent({ eventName: \"setConnectionStateSame\", value });\n return;\n }\n\n const oldState = this._connectionState;\n this._connectionState = value;\n const quorum = this.handler.protocolHandler()?.quorum;\n let client: ILocalSequencedClient | undefined;\n if (this._clientId !== undefined) {\n client = quorum?.getMember(this._clientId);\n }\n if (value === ConnectionState.Connected) {\n assert(oldState === ConnectionState.Connecting,\n 0x1d8 /* \"Should only transition from Connecting state\" */);\n // Mark our old client should have left in the quorum if it's still there\n if (client !== undefined) {\n client.shouldHaveLeft = true;\n }\n this._clientId = this.pendingClientId;\n } else if (value === ConnectionState.Disconnected) {\n // Important as we process our own joinSession message through delta request\n this._pendingClientId = undefined;\n // Only wait for \"leave\" message if the connected client exists in the quorum because only the write\n // client will exist in the quorum and only for those clients we will receive \"removeMember\" event and\n // the client has some unacked ops.\n // Also server would not accept ops from read client. Also check if the timer is not already running as\n // we could receive \"Disconnected\" event multiple times without getting connected and in that case we\n // don't want to reset the timer as we still want to wait on original client which started this timer.\n if (client !== undefined\n && this.handler.shouldClientJoinWrite()\n && this.prevClientLeftTimer.hasTimer === false\n ) {\n this.prevClientLeftTimer.restart();\n } else {\n // Adding this event temporarily so that we can get help debugging if something goes wrong.\n this.logger.sendTelemetryEvent({\n eventName: \"noWaitOnDisconnected\",\n inQuorum: client !== undefined,\n hasTimer: this.prevClientLeftTimer.hasTimer,\n shouldClientJoinWrite: this.handler.shouldClientJoinWrite(),\n });\n }\n }\n\n // Report transition before we propagate event across layers\n this.handler.logConnectionStateChangeTelemetry(this._connectionState, oldState, reason);\n\n // Propagate event across layers\n this.handler.connectionStateChanged();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"connectionStateHandler.js","sourceRoot":"","sources":["../src/connectionStateHandler.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { IConnectionDetails } from \"@fluidframework/container-definitions\";\nimport { ProtocolOpHandler } from \"@fluidframework/protocol-base\";\nimport { ConnectionMode, ISequencedClient } from \"@fluidframework/protocol-definitions\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { assert, Timer } from \"@fluidframework/common-utils\";\nimport { ConnectionState } from \"./container\";\n\nexport interface IConnectionStateHandler {\n protocolHandler: () => ProtocolOpHandler | undefined,\n logConnectionStateChangeTelemetry:\n (value: ConnectionState, oldState: ConnectionState, reason?: string | undefined) => void,\n shouldClientJoinWrite: () => boolean,\n maxClientLeaveWaitTime: number | undefined,\n logConnectionIssue: (eventName: string) => void,\n connectionStateChanged: () => void,\n}\n\nexport interface ILocalSequencedClient extends ISequencedClient {\n shouldHaveLeft?: boolean;\n}\n\nconst JoinOpTimer = 45000;\n\nexport class ConnectionStateHandler {\n private _connectionState = ConnectionState.Disconnected;\n private _pendingClientId: string | undefined;\n private _clientId: string | undefined;\n private readonly prevClientLeftTimer: Timer;\n private readonly joinOpTimer: Timer;\n\n private waitEvent: PerformanceEvent | undefined;\n\n public get connectionState(): ConnectionState {\n return this._connectionState;\n }\n\n public get connected(): boolean {\n return this.connectionState === ConnectionState.Connected;\n }\n\n public get clientId(): string | undefined {\n return this._clientId;\n }\n\n public get pendingClientId(): string | undefined {\n return this._pendingClientId;\n }\n\n constructor(\n private readonly handler: IConnectionStateHandler,\n private readonly logger: ITelemetryLogger,\n ) {\n this.prevClientLeftTimer = new Timer(\n // Default is 5 min for which we are going to wait for its own \"leave\" message. This is same as\n // the max time on server after which leave op is sent.\n this.handler.maxClientLeaveWaitTime ?? 300000,\n () => {\n assert(!this.connected,\n 0x2ac /* \"Connected when timeout waiting for leave from previous session fired!\" */);\n this.applyForConnectedState(\"timeout\");\n },\n );\n\n // Based on recent data, it looks like majority of cases where we get stuck are due to really slow or\n // timing out ops fetches. So attempt recovery infrequently. Also fetch uses 30 second timeout, so\n // if retrying fixes the problem, we should not see these events.\n this.joinOpTimer = new Timer(\n JoinOpTimer,\n () => {\n // I've observed timer firing within couple ms from disconnect event, looks like\n // queued timer callback is not cancelled if timer is cancelled while callback sits in the queue.\n if (this.connectionState === ConnectionState.Connecting) {\n this.handler.logConnectionIssue(\"NoJoinOp\");\n }\n },\n );\n }\n\n private startJoinOpTimer() {\n assert(!this.joinOpTimer.hasTimer, 0x234 /* \"has joinOpTimer\" */);\n this.joinOpTimer.start();\n }\n\n private stopJoinOpTimer() {\n assert(this.joinOpTimer.hasTimer, 0x235 /* \"no joinOpTimer\" */);\n this.joinOpTimer.clear();\n }\n\n public dispose() {\n assert(!this.joinOpTimer.hasTimer, 0x2a5 /* \"join timer\" */);\n this.prevClientLeftTimer.clear();\n }\n\n public containerSaved() {\n // If we were waiting for moving to Connected state, then only apply for state change. Since the container\n // is now saved and we don't have any ops to roundtrip, we can clear the timer and apply for connected state.\n if (this.prevClientLeftTimer.hasTimer) {\n this.prevClientLeftTimer.clear();\n this.applyForConnectedState(\"containerSaved\");\n }\n }\n\n public receivedAddMemberEvent(clientId: string) {\n // This is the only one that requires the pending client ID\n if (clientId === this.pendingClientId) {\n if (this.joinOpTimer.hasTimer) {\n this.stopJoinOpTimer();\n } else {\n // timer has already fired, meaning it took too long to get join on.\n // Record how long it actually took to recover.\n this.handler.logConnectionIssue(\"ReceivedJoinOp\");\n }\n // Start the event in case we are waiting for leave or timeout.\n if (this.prevClientLeftTimer.hasTimer) {\n this.waitEvent = PerformanceEvent.start(this.logger, {\n eventName: \"WaitBeforeClientLeave\",\n waitOnClientId: this._clientId,\n hadOutstandingOps: this.handler.shouldClientJoinWrite(),\n });\n }\n this.applyForConnectedState(\"addMemberEvent\");\n }\n }\n\n private applyForConnectedState(source: \"removeMemberEvent\" | \"addMemberEvent\" | \"timeout\" | \"containerSaved\") {\n const protocolHandler = this.handler.protocolHandler();\n assert(protocolHandler !== undefined, 0x236 /* \"In all cases it should be already installed\" */);\n // Move to connected state only if we are in Connecting state, we have seen our join op\n // and there is no timer running which means we are not waiting for previous client to leave\n // or timeout has occured while doing so.\n if (this.pendingClientId !== this.clientId\n && this.pendingClientId !== undefined\n && protocolHandler.quorum.getMember(this.pendingClientId) !== undefined\n && !this.prevClientLeftTimer.hasTimer\n ) {\n this.waitEvent?.end({ source });\n this.setConnectionState(ConnectionState.Connected);\n } else {\n // Adding this event temporarily so that we can get help debugging if something goes wrong.\n this.logger.sendTelemetryEvent({\n eventName: \"connectedStateRejected\",\n category: source === \"timeout\" ? \"error\" : \"generic\",\n source,\n pendingClientId: this.pendingClientId,\n clientId: this.clientId,\n hasTimer: this.prevClientLeftTimer.hasTimer,\n inQuorum: protocolHandler !== undefined && this.pendingClientId !== undefined\n && protocolHandler.quorum.getMember(this.pendingClientId) !== undefined,\n });\n }\n }\n\n public receivedRemoveMemberEvent(clientId: string) {\n // If the client which has left was us, then finish the timer.\n if (this.clientId === clientId) {\n this.prevClientLeftTimer.clear();\n this.applyForConnectedState(\"removeMemberEvent\");\n }\n }\n\n public receivedDisconnectEvent(reason: string) {\n if (this.joinOpTimer.hasTimer) {\n this.stopJoinOpTimer();\n }\n this.setConnectionState(ConnectionState.Disconnected, reason);\n }\n\n public receivedConnectEvent(\n connectionMode: ConnectionMode,\n details: IConnectionDetails,\n ) {\n const oldState = this._connectionState;\n this._connectionState = ConnectionState.Connecting;\n\n // Stash the clientID to detect when transitioning from connecting (socket.io channel open) to connected\n // (have received the join message for the client ID)\n // This is especially important in the reconnect case. It's possible there could be outstanding\n // ops sent by this client, so we should keep the old client id until we see our own client's\n // join message. after we see the join message for out new connection with our new client id,\n // we know there can no longer be outstanding ops that we sent with the previous client id.\n this._pendingClientId = details.clientId;\n\n // Report telemetry after we set client id, but before transitioning to Connected state below!\n this.handler.logConnectionStateChangeTelemetry(ConnectionState.Connecting, oldState);\n\n const protocolHandler = this.handler.protocolHandler();\n // Check if we already processed our own join op through delta storage!\n // we are fetching ops from storage in parallel to connecting to ordering service\n // Given async processes, it's possible that we have already processed our own join message before\n // connection was fully established.\n // Note that we might be still initializing quorum - connection is established proactively on load!\n if ((protocolHandler !== undefined && protocolHandler.quorum.getMember(details.clientId) !== undefined)\n || connectionMode === \"read\"\n ) {\n assert(!this.prevClientLeftTimer.hasTimer, 0x2a6 /* \"there should be no timer for 'read' connections\" */);\n this.setConnectionState(ConnectionState.Connected);\n } else if (connectionMode === \"write\") {\n this.startJoinOpTimer();\n }\n }\n\n private setConnectionState(value: ConnectionState.Disconnected, reason: string);\n private setConnectionState(value: ConnectionState.Connected);\n private setConnectionState(value: ConnectionState, reason?: string) {\n if (this.connectionState === value) {\n // Already in the desired state - exit early\n this.logger.sendErrorEvent({ eventName: \"setConnectionStateSame\", value });\n return;\n }\n\n const oldState = this._connectionState;\n this._connectionState = value;\n const quorum = this.handler.protocolHandler()?.quorum;\n let client: ILocalSequencedClient | undefined;\n if (this._clientId !== undefined) {\n client = quorum?.getMember(this._clientId);\n }\n if (value === ConnectionState.Connected) {\n assert(oldState === ConnectionState.Connecting,\n 0x1d8 /* \"Should only transition from Connecting state\" */);\n // Mark our old client should have left in the quorum if it's still there\n if (client !== undefined) {\n client.shouldHaveLeft = true;\n }\n this._clientId = this.pendingClientId;\n } else if (value === ConnectionState.Disconnected) {\n // Important as we process our own joinSession message through delta request\n this._pendingClientId = undefined;\n // Only wait for \"leave\" message if the connected client exists in the quorum because only the write\n // client will exist in the quorum and only for those clients we will receive \"removeMember\" event and\n // the client has some unacked ops.\n // Also server would not accept ops from read client. Also check if the timer is not already running as\n // we could receive \"Disconnected\" event multiple times without getting connected and in that case we\n // don't want to reset the timer as we still want to wait on original client which started this timer.\n if (client !== undefined\n && this.handler.shouldClientJoinWrite()\n && this.prevClientLeftTimer.hasTimer === false\n ) {\n this.prevClientLeftTimer.restart();\n } else {\n // Adding this event temporarily so that we can get help debugging if something goes wrong.\n this.logger.sendTelemetryEvent({\n eventName: \"noWaitOnDisconnected\",\n inQuorum: client !== undefined,\n hasTimer: this.prevClientLeftTimer.hasTimer,\n shouldClientJoinWrite: this.handler.shouldClientJoinWrite(),\n });\n }\n }\n\n // Report transition before we propagate event across layers\n this.handler.logConnectionStateChangeTelemetry(this._connectionState, oldState, reason);\n\n // Propagate event across layers\n this.handler.connectionStateChanged();\n }\n}\n"]}
|
package/dist/container.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { IRequest, IResponse, IFluidRouter, IFluidCodeDetails } from "@fluidframework/core-interfaces";
|
|
6
6
|
import { IAudience, IContainer, IContainerEvents, IDeltaManager, ICriticalContainerError, ContainerWarning, AttachState, ReadOnlyInfo, IContainerLoadMode } from "@fluidframework/container-definitions";
|
|
7
7
|
import { IDocumentStorageService, IFluidResolvedUrl, IResolvedUrl } from "@fluidframework/driver-definitions";
|
|
8
|
-
import { IClientConfiguration, IClientDetails, IDocumentMessage,
|
|
8
|
+
import { IClientConfiguration, IClientDetails, IDocumentMessage, IQuorumClients, ISequencedDocumentMessage, IVersion } from "@fluidframework/protocol-definitions";
|
|
9
9
|
import { EventEmitterWithErrorHandling, TelemetryLogger } from "@fluidframework/telemetry-utils";
|
|
10
10
|
import { ILoaderOptions, Loader } from "./loader";
|
|
11
11
|
export interface IContainerLoadOptions {
|
|
@@ -78,7 +78,7 @@ export declare class Container extends EventEmitterWithErrorHandling<IContainerE
|
|
|
78
78
|
static rehydrateDetachedFromSnapshot(loader: Loader, snapshot: string): Promise<Container>;
|
|
79
79
|
subLogger: TelemetryLogger;
|
|
80
80
|
private readonly _canReconnect;
|
|
81
|
-
private readonly
|
|
81
|
+
private readonly mc;
|
|
82
82
|
private _lifecycleState;
|
|
83
83
|
private get loaded();
|
|
84
84
|
private set loaded(value);
|
|
@@ -106,6 +106,7 @@ export declare class Container extends EventEmitterWithErrorHandling<IContainerE
|
|
|
106
106
|
private attachStarted;
|
|
107
107
|
private _dirtyContainer;
|
|
108
108
|
private lastVisible;
|
|
109
|
+
private readonly visibilityEventHandler;
|
|
109
110
|
private readonly connectionStateHandler;
|
|
110
111
|
private setAutoReconnectTime;
|
|
111
112
|
private readonly collabWindowTracker;
|
|
@@ -118,7 +119,6 @@ export declare class Container extends EventEmitterWithErrorHandling<IContainerE
|
|
|
118
119
|
* Tracks host requiring read-only mode.
|
|
119
120
|
*/
|
|
120
121
|
forceReadonly(readonly: boolean): void;
|
|
121
|
-
get id(): string;
|
|
122
122
|
get deltaManager(): IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;
|
|
123
123
|
get connectionState(): ConnectionState;
|
|
124
124
|
get connected(): boolean;
|
|
@@ -138,13 +138,6 @@ export declare class Container extends EventEmitterWithErrorHandling<IContainerE
|
|
|
138
138
|
*/
|
|
139
139
|
get scopes(): string[] | undefined;
|
|
140
140
|
get clientDetails(): IClientDetails;
|
|
141
|
-
/**
|
|
142
|
-
* The current code details for the container's runtime
|
|
143
|
-
* @deprecated use getSpecifiedCodeDetails for the code details currently specified for this container, or
|
|
144
|
-
* getLoadedCodeDetails for the code details that the container's context was loaded with.
|
|
145
|
-
* To be removed after getSpecifiedCodeDetails and getLoadedCodeDetails become ubiquitous.
|
|
146
|
-
*/
|
|
147
|
-
get codeDetails(): IFluidCodeDetails | undefined;
|
|
148
141
|
/**
|
|
149
142
|
* Get the code details that are currently specified for the container.
|
|
150
143
|
* @returns The current code details if any are specified, undefined if none are specified.
|
|
@@ -168,14 +161,14 @@ export declare class Container extends EventEmitterWithErrorHandling<IContainerE
|
|
|
168
161
|
get isDirty(): boolean;
|
|
169
162
|
private get serviceFactory();
|
|
170
163
|
private get urlResolver();
|
|
171
|
-
|
|
164
|
+
readonly options: ILoaderOptions;
|
|
172
165
|
private get scope();
|
|
173
166
|
private get codeLoader();
|
|
174
167
|
constructor(loader: Loader, config: IContainerConfig);
|
|
175
168
|
/**
|
|
176
169
|
* Retrieves the quorum associated with the document
|
|
177
170
|
*/
|
|
178
|
-
getQuorum():
|
|
171
|
+
getQuorum(): IQuorumClients;
|
|
179
172
|
close(error?: ICriticalContainerError): void;
|
|
180
173
|
closeAndGetPendingLocalState(): string;
|
|
181
174
|
get attachState(): AttachState;
|
|
@@ -187,6 +180,7 @@ export declare class Container extends EventEmitterWithErrorHandling<IContainerE
|
|
|
187
180
|
resume(): void;
|
|
188
181
|
private resumeInternal;
|
|
189
182
|
/**
|
|
183
|
+
* @deprecated 0.56, will be removed in next release from IContainerContext
|
|
190
184
|
* Raise non-critical error to host. Calling this API will not close container.
|
|
191
185
|
* For critical errors, please call Container.close(error).
|
|
192
186
|
* @param error - an error to raise
|
package/dist/container.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,OAAO,EACH,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,iBAAiB,EAEpB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACH,SAAS,EAET,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,gBAAgB,EAChB,WAAW,EAGX,YAAY,EACZ,kBAAkB,EACrB,MAAM,uCAAuC,CAAC;AAO/C,OAAO,EAEH,uBAAuB,EACvB,iBAAiB,EACjB,YAAY,EACf,MAAM,oCAAoC,CAAC;AAc5C,OAAO,EAGH,oBAAoB,EACpB,cAAc,EAGd,gBAAgB,EAGhB,cAAc,EAGd,yBAAyB,EASzB,QAAQ,EAIX,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAEH,6BAA6B,EAG7B,eAAe,EAMlB,MAAM,iCAAiC,CAAC;AAMzC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAkB,MAAM,UAAU,CAAC;AAgBlE,MAAM,WAAW,qBAAqB;IAClC;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,qBAAqB,CAAC,EAAE,cAAc,CAAC;IACvC,WAAW,EAAE,iBAAiB,CAAC;IAC/B;;OAEG;IACH,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B;;OAEG;IACH,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC7B,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,qBAAqB,CAAC,EAAE,cAAc,CAAC;CAC1C;AAED,oBAAY,eAAe;IACvB;;OAEG;IACH,YAAY,IAAA;IAEZ;;OAEG;IACH,UAAU,IAAA;IAEV;;OAEG;IACH,SAAS,IAAA;CACZ;AAED;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,UAAU,oBAmDjE;AAMD,qBAAa,SAAU,SAAQ,6BAA6B,CAAC,gBAAgB,CAAE,YAAW,UAAU;IAsS5F,OAAO,CAAC,QAAQ,CAAC,MAAM;IArS3B,OAAc,OAAO,SAAY;IAEjC;;OAEG;WACiB,IAAI,CACpB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,qBAAqB,EAClC,iBAAiB,CAAC,EAAE,OAAO,GAC5B,OAAO,CAAC,SAAS,CAAC;IAiDrB;;OAEG;WACiB,cAAc,CAC9B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,iBAAiB,GAC/B,OAAO,CAAC,SAAS,CAAC;IAgBrB;;;OAGG;WACiB,6BAA6B,CAC7C,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,SAAS,CAAC;IAgBd,SAAS,EAAE,eAAe,CAAC;IAIlC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiB;IAE/C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;IAEvC,OAAO,CAAC,eAAe,CAAsE;IAE7F,OAAO,KAAK,MAAM,GAEjB;IAED,OAAO,KAAK,MAAM,QASjB;IAED,IAAW,MAAM,IAAI,OAAO,CAE3B;IAED,OAAO,CAAC,YAAY,CAAwB;IAE5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;IACnD,IAAW,OAAO,IAAI,uBAAuB,CAE5C;IAED,OAAO,CAAC,eAAe,CAAoD;IAC3E,OAAO,KAAK,cAAc,GAKzB;IAED,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA6B;IACnE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkC;IAChE,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IAErC,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,KAAK,OAAO,GAKlB;IACD,OAAO,CAAC,gBAAgB,CAAgC;IACxD,OAAO,KAAK,eAAe,GAK1B;IAED,OAAO,CAAC,4BAA4B,CAAS;IAC7C,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,yBAAyB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAgB;IAC1D,OAAO,CAAC,8BAA8B,CAAa;IACnD,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,YAAY,CAAgC;IACpD,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,eAAe,CAAS;IAEhC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA2B;IAClE,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAyB;IAEhE,OAAO,CAAC,oBAAoB,CAAqB;IAEjD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAKlC;IAEF,OAAO,KAAK,cAAc,GAAkE;IAE5F,IAAW,YAAY,IAAI,YAAY,CAAiB;IAExD,IAAW,WAAW,IAAI,YAAY,GAAG,SAAS,CAEjD;IAED,IAAW,iBAAiB,IAAI,QAAQ,GAAG,SAAS,CAEnD;IAED,IAAW,YAAY,IAAI,YAAY,CAEtC;IAED;;OAEG;IACI,aAAa,CAAC,QAAQ,EAAE,OAAO;IAItC,IAAW,YAAY,IAAI,aAAa,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,CAEpF;IAED,IAAW,eAAe,IAAI,eAAe,CAE5C;IAED,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED;;;OAGG;IACH,IAAW,oBAAoB,IAAI,oBAAoB,GAAG,SAAS,CAElE;IAED;;;OAGG;IACH,IAAW,QAAQ,IAAI,MAAM,GAAG,SAAS,CAExC;IAED;;;OAGG;IACH,IAAW,MAAM,IAAI,MAAM,EAAE,GAAG,SAAS,CAExC;IAED,IAAW,aAAa,IAAI,cAAc,CAEzC;IAED;;;OAGG;IACI,uBAAuB,IAAI,iBAAiB,GAAG,SAAS;IAI/D;;;;OAIG;IACI,oBAAoB,IAAI,iBAAiB,GAAG,SAAS;IAI5D;;OAEG;IACH,IAAW,QAAQ,IAAI,SAAS,CAE/B;IAED;;;;OAIG;IACH,IAAW,OAAO,YAEjB;IAED,OAAO,KAAK,cAAc,GAAwD;IAClF,OAAO,KAAK,WAAW,GAA6C;IACpE,SAAgB,OAAO,EAAE,cAAc,CAAC;IACxC,OAAO,KAAK,KAAK,GAAwC;IACzD,OAAO,KAAK,UAAU,GAA6C;gBAG9C,MAAM,EAAE,MAAM,EAC/B,MAAM,EAAE,gBAAgB;IAqK5B;;OAEG;IACI,SAAS,IAAI,cAAc;IAI3B,KAAK,CAAC,KAAK,CAAC,EAAE,uBAAuB;IAkDrC,4BAA4B,IAAI,MAAM;IAkB7C,IAAW,WAAW,IAAI,WAAW,CAEpC;IAEM,SAAS,IAAI,MAAM;IAab,MAAM,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA8GxC,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAS3C,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB5E,gBAAgB,CAAC,SAAS,EAAE,OAAO;IAqCnC,MAAM;IASb,OAAO,CAAC,cAAc;IActB;;;;;OAKG;IACI,qBAAqB,CAAC,OAAO,EAAE,gBAAgB;IASzC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAWhE,kBAAkB,CAAC,WAAW,EAAE,iBAAiB;YAmBhD,mBAAmB;YAgBnB,YAAY;IAwB1B,OAAO,CAAC,YAAY;YAwDN,UAAU;IAKxB,OAAO,CAAC,sBAAsB;IAM9B,OAAO,CAAC,oBAAoB;IAW5B;;;;;;OAMG;YACW,IAAI;YAuHJ,cAAc;YAuCd,6BAA6B;YA4B7B,qBAAqB;YAsBrB,qBAAqB;YA2BrB,8BAA8B;YA2B9B,uBAAuB;IAwDrC,OAAO,CAAC,sBAAsB;IAmC9B,OAAO,CAAC,wBAAwB;IAQhC,OAAO,KAAK,MAAM,GAkBjB;IAED;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,kBAAkB;YAuDZ,2BAA2B;IAiBzC,OAAO,CAAC,iCAAiC;IA4DzC,OAAO,CAAC,wBAAwB;IAuBhC,OAAO,CAAC,sBAAsB;IA4B9B,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,oBAAoB;IAoC5B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,aAAa;IAiBrB;;;;OAIG;YACW,iBAAiB;YAkBjB,0BAA0B;YAkB1B,kBAAkB;IAwChC,OAAO,CAAC,iBAAiB;CAG5B"}
|
package/dist/container.js
CHANGED
|
@@ -111,9 +111,9 @@ const getCodeProposal =
|
|
|
111
111
|
(quorum) => { var _a; return (_a = quorum.get("code")) !== null && _a !== void 0 ? _a : quorum.get("code2"); };
|
|
112
112
|
class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
113
113
|
constructor(loader, config) {
|
|
114
|
-
var _a, _b;
|
|
114
|
+
var _a, _b, _c;
|
|
115
115
|
super((name, error) => {
|
|
116
|
-
this.logger.sendErrorEvent({
|
|
116
|
+
this.mc.logger.sendErrorEvent({
|
|
117
117
|
eventName: "ContainerEventHandlerException",
|
|
118
118
|
name: typeof name === "string" ? name : undefined,
|
|
119
119
|
}, error);
|
|
@@ -149,12 +149,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
149
149
|
all: {
|
|
150
150
|
clientType,
|
|
151
151
|
containerId: uuid_1.v4(),
|
|
152
|
-
docId: () => this.id,
|
|
152
|
+
docId: () => { var _a, _b; return (_b = (_a = this._resolvedUrl) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : undefined; },
|
|
153
153
|
containerAttachState: () => this._attachState,
|
|
154
154
|
containerLifecycleState: () => this._lifecycleState,
|
|
155
155
|
containerConnectionState: () => ConnectionState[this.connectionState],
|
|
156
156
|
},
|
|
157
|
-
// we need to be judicious with our logging here to avoid
|
|
157
|
+
// we need to be judicious with our logging here to avoid generating too much data
|
|
158
158
|
// all data logged here should be broadly applicable, and not specific to a
|
|
159
159
|
// specific error or class of errors
|
|
160
160
|
error: {
|
|
@@ -167,12 +167,13 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
167
167
|
dmLastMsqSeqNumber: () => { var _a, _b; return (_b = (_a = this.deltaManager) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.sequenceNumber; },
|
|
168
168
|
dmLastMsqSeqTimestamp: () => { var _a, _b; return (_b = (_a = this.deltaManager) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.timestamp; },
|
|
169
169
|
dmLastMsqSeqClientId: () => { var _a, _b; return (_b = (_a = this.deltaManager) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.clientId; },
|
|
170
|
-
connectionState: () => ConnectionState[this.connectionState],
|
|
171
170
|
connectionStateDuration: () => common_utils_1.performance.now() - this.connectionTransitionTimes[this.connectionState],
|
|
172
171
|
},
|
|
173
172
|
});
|
|
174
173
|
// Prefix all events in this file with container-loader
|
|
175
|
-
this.
|
|
174
|
+
this.mc = telemetry_utils_1.loggerToMonitoringContext(telemetry_utils_1.ChildLogger.create(this.subLogger, "Container"));
|
|
175
|
+
const summarizeProtocolTree = (_c = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree")) !== null && _c !== void 0 ? _c : this.loader.services.options.summarizeProtocolTree;
|
|
176
|
+
this.options = Object.assign(Object.assign({}, this.loader.services.options), { summarizeProtocolTree });
|
|
176
177
|
this.connectionStateHandler = new connectionStateHandler_1.ConnectionStateHandler({
|
|
177
178
|
protocolHandler: () => this._protocolHandler,
|
|
178
179
|
logConnectionStateChangeTelemetry: (value, oldState, reason) => this.logConnectionStateChangeTelemetry(value, oldState, reason),
|
|
@@ -191,14 +192,17 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
191
192
|
this.propagateConnectionState();
|
|
192
193
|
}
|
|
193
194
|
},
|
|
194
|
-
}, this.logger);
|
|
195
|
+
}, this.mc.logger);
|
|
196
|
+
this.on(savedContainerEvent, () => {
|
|
197
|
+
this.connectionStateHandler.containerSaved();
|
|
198
|
+
});
|
|
195
199
|
this._deltaManager = this.createDeltaManager();
|
|
196
200
|
this._storage = new containerStorageAdapter_1.ContainerStorageAdapter(() => {
|
|
197
201
|
if (this.attachState !== container_definitions_1.AttachState.Attached) {
|
|
198
202
|
if (this.loader.services.detachedBlobStorage !== undefined) {
|
|
199
|
-
return new containerStorageAdapter_1.BlobOnlyStorage(this.loader.services.detachedBlobStorage, this.logger);
|
|
203
|
+
return new containerStorageAdapter_1.BlobOnlyStorage(this.loader.services.detachedBlobStorage, this.mc.logger);
|
|
200
204
|
}
|
|
201
|
-
this.logger.sendErrorEvent({
|
|
205
|
+
this.mc.logger.sendErrorEvent({
|
|
202
206
|
eventName: "NoRealStorageInDetachedContainer",
|
|
203
207
|
});
|
|
204
208
|
throw new Error("Real storage calls not allowed in Unattached container");
|
|
@@ -212,7 +216,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
212
216
|
// keep track of last time page was visible for telemetry
|
|
213
217
|
if (isDomAvailable) {
|
|
214
218
|
this.lastVisible = document.hidden ? common_utils_1.performance.now() : undefined;
|
|
215
|
-
|
|
219
|
+
this.visibilityEventHandler = () => {
|
|
216
220
|
if (document.hidden) {
|
|
217
221
|
this.lastVisible = common_utils_1.performance.now();
|
|
218
222
|
}
|
|
@@ -220,7 +224,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
220
224
|
// settimeout so this will hopefully fire after disconnect event if being hidden caused it
|
|
221
225
|
setTimeout(() => this.lastVisible = undefined, 0);
|
|
222
226
|
}
|
|
223
|
-
}
|
|
227
|
+
};
|
|
228
|
+
document.addEventListener("visibilitychange", this.visibilityEventHandler);
|
|
224
229
|
}
|
|
225
230
|
// We observed that most users of platform do not check Container.connected event on load, causing bugs.
|
|
226
231
|
// As such, we are raising events when new listener pops up.
|
|
@@ -253,7 +258,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
253
258
|
default:
|
|
254
259
|
}
|
|
255
260
|
}).catch((error) => {
|
|
256
|
-
this.logger.sendErrorEvent({ eventName: "RaiseConnectedEventError" }, error);
|
|
261
|
+
this.mc.logger.sendErrorEvent({ eventName: "RaiseConnectedEventError" }, error);
|
|
257
262
|
});
|
|
258
263
|
});
|
|
259
264
|
}
|
|
@@ -266,7 +271,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
266
271
|
resolvedUrl: loadOptions.resolvedUrl,
|
|
267
272
|
canReconnect: loadOptions.canReconnect,
|
|
268
273
|
});
|
|
269
|
-
return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.logger, { eventName: "Load" }, async (event) => new Promise((
|
|
274
|
+
return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "Load" }, async (event) => new Promise((resolve, reject) => {
|
|
270
275
|
var _a;
|
|
271
276
|
container._lifecycleState = "loading";
|
|
272
277
|
const version = loadOptions.version;
|
|
@@ -276,7 +281,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
276
281
|
common_utils_1.assert(pendingLocalState === undefined || loadOptions.loadMode === undefined, 0x1e1 /* "pending state requires immediate connection!" */);
|
|
277
282
|
const mode = (_a = loadOptions.loadMode) !== null && _a !== void 0 ? _a : defaultMode;
|
|
278
283
|
const onClosed = (err) => {
|
|
279
|
-
|
|
284
|
+
reject(err !== null && err !== void 0 ? err : new container_utils_1.GenericError("containerClosedWithoutErrorDuringLoad"));
|
|
280
285
|
};
|
|
281
286
|
container.on("closed", onClosed);
|
|
282
287
|
container.load(version, mode, pendingLocalState)
|
|
@@ -285,7 +290,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
285
290
|
})
|
|
286
291
|
.then((props) => {
|
|
287
292
|
event.end(Object.assign(Object.assign({}, props), loadOptions.loadMode));
|
|
288
|
-
|
|
293
|
+
resolve(container);
|
|
289
294
|
}, (error) => {
|
|
290
295
|
const err = telemetry_utils_1.normalizeError(error);
|
|
291
296
|
// Depending where error happens, we can be attempting to connect to web socket
|
|
@@ -301,7 +306,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
301
306
|
*/
|
|
302
307
|
static async createDetached(loader, codeDetails) {
|
|
303
308
|
const container = new Container(loader, {});
|
|
304
|
-
return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.logger, { eventName: "CreateDetached" }, async (_event) => {
|
|
309
|
+
return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "CreateDetached" }, async (_event) => {
|
|
305
310
|
container._lifecycleState = "loading";
|
|
306
311
|
await container.createDetached(codeDetails);
|
|
307
312
|
return container;
|
|
@@ -313,7 +318,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
313
318
|
*/
|
|
314
319
|
static async rehydrateDetachedFromSnapshot(loader, snapshot) {
|
|
315
320
|
const container = new Container(loader, {});
|
|
316
|
-
return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.logger, { eventName: "RehydrateDetachedFromSnapshot" }, async (_event) => {
|
|
321
|
+
return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "RehydrateDetachedFromSnapshot" }, async (_event) => {
|
|
317
322
|
const deserializedSummary = JSON.parse(snapshot);
|
|
318
323
|
container._lifecycleState = "loading";
|
|
319
324
|
await container.rehydrateDetachedFromSnapshot(deserializedSummary);
|
|
@@ -373,10 +378,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
373
378
|
forceReadonly(readonly) {
|
|
374
379
|
this._deltaManager.connectionManager.forceReadonly(readonly);
|
|
375
380
|
}
|
|
376
|
-
get id() {
|
|
377
|
-
var _a, _b;
|
|
378
|
-
return (_b = (_a = this._resolvedUrl) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : "";
|
|
379
|
-
}
|
|
380
381
|
get deltaManager() {
|
|
381
382
|
return this._deltaManager;
|
|
382
383
|
}
|
|
@@ -410,16 +411,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
410
411
|
get clientDetails() {
|
|
411
412
|
return this._deltaManager.clientDetails;
|
|
412
413
|
}
|
|
413
|
-
/**
|
|
414
|
-
* The current code details for the container's runtime
|
|
415
|
-
* @deprecated use getSpecifiedCodeDetails for the code details currently specified for this container, or
|
|
416
|
-
* getLoadedCodeDetails for the code details that the container's context was loaded with.
|
|
417
|
-
* To be removed after getSpecifiedCodeDetails and getLoadedCodeDetails become ubiquitous.
|
|
418
|
-
*/
|
|
419
|
-
get codeDetails() {
|
|
420
|
-
var _a, _b;
|
|
421
|
-
return (_b = (_a = this._context) === null || _a === void 0 ? void 0 : _a.codeDetails) !== null && _b !== void 0 ? _b : this.getCodeDetailsFromQuorum();
|
|
422
|
-
}
|
|
423
414
|
/**
|
|
424
415
|
* Get the code details that are currently specified for the container.
|
|
425
416
|
* @returns The current code details if any are specified, undefined if none are specified.
|
|
@@ -452,7 +443,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
452
443
|
}
|
|
453
444
|
get serviceFactory() { return this.loader.services.documentServiceFactory; }
|
|
454
445
|
get urlResolver() { return this.loader.services.urlResolver; }
|
|
455
|
-
get options() { return this.loader.services.options; }
|
|
456
446
|
get scope() { return this.loader.services.scope; }
|
|
457
447
|
get codeLoader() { return this.loader.services.codeLoader; }
|
|
458
448
|
/**
|
|
@@ -482,14 +472,17 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
482
472
|
(_d = this.service) === null || _d === void 0 ? void 0 : _d.dispose(error);
|
|
483
473
|
}
|
|
484
474
|
catch (exception) {
|
|
485
|
-
this.logger.sendErrorEvent({ eventName: "ContainerCloseException" }, exception);
|
|
475
|
+
this.mc.logger.sendErrorEvent({ eventName: "ContainerCloseException" }, exception);
|
|
486
476
|
}
|
|
487
|
-
this.logger.sendTelemetryEvent({
|
|
477
|
+
this.mc.logger.sendTelemetryEvent({
|
|
488
478
|
eventName: "ContainerClose",
|
|
489
479
|
category: error === undefined ? "generic" : "error",
|
|
490
480
|
}, error);
|
|
491
481
|
this.emit("closed", error);
|
|
492
482
|
this.removeAllListeners();
|
|
483
|
+
if (this.visibilityEventHandler !== undefined) {
|
|
484
|
+
document.removeEventListener("visibilitychange", this.visibilityEventHandler);
|
|
485
|
+
}
|
|
493
486
|
}
|
|
494
487
|
finally {
|
|
495
488
|
this._lifecycleState = "closed";
|
|
@@ -522,7 +515,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
522
515
|
return JSON.stringify(combinedSummary);
|
|
523
516
|
}
|
|
524
517
|
async attach(request) {
|
|
525
|
-
await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.logger, { eventName: "Attach" }, async () => {
|
|
518
|
+
await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Attach" }, async () => {
|
|
526
519
|
if (this._lifecycleState !== "loaded") {
|
|
527
520
|
throw new container_utils_1.UsageError(`containerNotValidForAttach [${this._lifecycleState}]`);
|
|
528
521
|
}
|
|
@@ -552,7 +545,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
552
545
|
const createNewResolvedUrl = await this.urlResolver.resolve(request);
|
|
553
546
|
driver_utils_1.ensureFluidResolvedUrl(createNewResolvedUrl);
|
|
554
547
|
if (this.service === undefined) {
|
|
555
|
-
this.service = await driver_utils_1.runWithRetry(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger), "containerAttach", this.logger, {});
|
|
548
|
+
this.service = await driver_utils_1.runWithRetry(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger), "containerAttach", this.mc.logger, {});
|
|
556
549
|
}
|
|
557
550
|
const resolvedUrl = this.service.resolvedUrl;
|
|
558
551
|
driver_utils_1.ensureFluidResolvedUrl(resolvedUrl);
|
|
@@ -606,12 +599,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
606
599
|
}, { start: true, end: true, cancel: "generic" });
|
|
607
600
|
}
|
|
608
601
|
async request(path) {
|
|
609
|
-
return telemetry_utils_1.PerformanceEvent.timedExecAsync(this.logger, { eventName: "Request" }, async () => this.context.request(path), { end: true, cancel: "error" });
|
|
602
|
+
return telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Request" }, async () => this.context.request(path), { end: true, cancel: "error" });
|
|
610
603
|
}
|
|
611
604
|
async snapshot(tagMessage, fullTree = false) {
|
|
612
605
|
// Only snapshot once a code quorum has been established
|
|
613
606
|
if (!this.protocolHandler.quorum.has("code") && !this.protocolHandler.quorum.has("code2")) {
|
|
614
|
-
this.logger.sendTelemetryEvent({ eventName: "SkipSnapshot" });
|
|
607
|
+
this.mc.logger.sendTelemetryEvent({ eventName: "SkipSnapshot" });
|
|
615
608
|
return;
|
|
616
609
|
}
|
|
617
610
|
// Stop inbound message processing while we complete the snapshot
|
|
@@ -620,7 +613,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
620
613
|
await this.snapshotCore(tagMessage, fullTree);
|
|
621
614
|
}
|
|
622
615
|
catch (ex) {
|
|
623
|
-
this.logger.sendErrorEvent({ eventName: "SnapshotExceptionError" }, ex);
|
|
616
|
+
this.mc.logger.sendErrorEvent({ eventName: "SnapshotExceptionError" }, ex);
|
|
624
617
|
throw ex;
|
|
625
618
|
}
|
|
626
619
|
finally {
|
|
@@ -639,7 +632,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
639
632
|
const now = common_utils_1.performance.now();
|
|
640
633
|
const duration = now - this.setAutoReconnectTime;
|
|
641
634
|
this.setAutoReconnectTime = now;
|
|
642
|
-
this.logger.sendTelemetryEvent({
|
|
635
|
+
this.mc.logger.sendTelemetryEvent({
|
|
643
636
|
eventName: reconnect ? "AutoReconnectEnabled" : "AutoReconnectDisabled",
|
|
644
637
|
connectionMode: this.connectionMode,
|
|
645
638
|
connectionState: ConnectionState[this.connectionState],
|
|
@@ -677,6 +670,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
677
670
|
this.connectToDeltaStream(args);
|
|
678
671
|
}
|
|
679
672
|
/**
|
|
673
|
+
* @deprecated 0.56, will be removed in next release from IContainerContext
|
|
680
674
|
* Raise non-critical error to host. Calling this API will not close container.
|
|
681
675
|
* For critical errors, please call Container.close(error).
|
|
682
676
|
* @param error - an error to raise
|
|
@@ -701,12 +695,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
701
695
|
throw new Error("Provided codeDetails are not IFluidCodeDetails");
|
|
702
696
|
}
|
|
703
697
|
if (this.codeLoader.IFluidCodeDetailsComparer) {
|
|
704
|
-
const
|
|
705
|
-
if (
|
|
698
|
+
const comparison = await this.codeLoader.IFluidCodeDetailsComparer.compare(codeDetails, this.getCodeDetailsFromQuorum());
|
|
699
|
+
if (comparison !== undefined && comparison <= 0) {
|
|
706
700
|
throw new Error("Proposed code details should be greater than the current");
|
|
707
701
|
}
|
|
708
702
|
}
|
|
709
|
-
return this.
|
|
703
|
+
return this.protocolHandler.quorum.propose("code", codeDetails)
|
|
710
704
|
.then(() => true)
|
|
711
705
|
.catch(() => false);
|
|
712
706
|
}
|
|
@@ -735,7 +729,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
735
729
|
const deltaDetails = `${this._deltaManager.lastSequenceNumber}:${this._deltaManager.minimumSequenceNumber}`;
|
|
736
730
|
const message = `Commit @${deltaDetails} ${tagMessage}`;
|
|
737
731
|
// Pull in the prior version and snapshot tree to store against
|
|
738
|
-
const lastVersion = await this.getVersion(
|
|
732
|
+
const lastVersion = await this.getVersion(null);
|
|
739
733
|
const parents = lastVersion !== undefined ? [lastVersion.id] : [];
|
|
740
734
|
// Write the full snapshot
|
|
741
735
|
return this.storageService.write(root, parents, message, "");
|
|
@@ -772,7 +766,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
772
766
|
});
|
|
773
767
|
// Save attributes for the document
|
|
774
768
|
const documentAttributes = {
|
|
775
|
-
branch: this.id,
|
|
776
769
|
minimumSequenceNumber: this._deltaManager.minimumSequenceNumber,
|
|
777
770
|
sequenceNumber: this._deltaManager.lastSequenceNumber,
|
|
778
771
|
term: this._deltaManager.referenceTerm,
|
|
@@ -961,8 +954,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
961
954
|
common_utils_1.assert(this.service !== undefined, 0x1ef /* "services must be defined" */);
|
|
962
955
|
const storageService = await this.service.connectToStorage();
|
|
963
956
|
this._storageService =
|
|
964
|
-
new retriableDocumentStorageService_1.RetriableDocumentStorageService(storageService, this.logger);
|
|
957
|
+
new retriableDocumentStorageService_1.RetriableDocumentStorageService(storageService, this.mc.logger);
|
|
965
958
|
if (this.options.summarizeProtocolTree === true) {
|
|
959
|
+
this.mc.logger.sendTelemetryEvent({ eventName: "summarizeProtocolTreeEnabled" });
|
|
966
960
|
this._storageService =
|
|
967
961
|
new protocolTreeDocumentStorageService_1.ProtocolTreeStorageService(this._storageService, () => this.captureProtocolSummary());
|
|
968
962
|
}
|
|
@@ -1024,7 +1018,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1024
1018
|
protocol.quorum.on("approveProposal", (sequenceNumber, key, value) => {
|
|
1025
1019
|
if (key === "code" || key === "code2") {
|
|
1026
1020
|
if (!core_interfaces_1.isFluidCodeDetails(value)) {
|
|
1027
|
-
this.logger.sendErrorEvent({
|
|
1021
|
+
this.mc.logger.sendErrorEvent({
|
|
1028
1022
|
eventName: "CodeProposalNotIFluidCodeDetails",
|
|
1029
1023
|
});
|
|
1030
1024
|
}
|
|
@@ -1178,7 +1172,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1178
1172
|
connectionInitiationReason = "AutoReconnect";
|
|
1179
1173
|
}
|
|
1180
1174
|
}
|
|
1181
|
-
this.logger.sendPerformanceEvent(Object.assign({ eventName: `ConnectionStateChange_${ConnectionState[value]}`, from: ConnectionState[oldState], duration,
|
|
1175
|
+
this.mc.logger.sendPerformanceEvent(Object.assign({ eventName: `ConnectionStateChange_${ConnectionState[value]}`, from: ConnectionState[oldState], duration,
|
|
1182
1176
|
durationFromDisconnected,
|
|
1183
1177
|
reason,
|
|
1184
1178
|
connectionInitiationReason, pendingClientId: this.connectionStateHandler.pendingClientId, clientId: this.clientId, autoReconnect,
|
|
@@ -1201,9 +1195,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1201
1195
|
}
|
|
1202
1196
|
common_utils_1.assert(this.protocolHandler !== undefined, 0x0dc /* "Protocol handler should be set here" */);
|
|
1203
1197
|
this.protocolHandler.quorum.setConnectionState(state, this.clientId);
|
|
1204
|
-
telemetry_utils_1.raiseConnectedEvent(this.logger, this, state, this.clientId);
|
|
1198
|
+
telemetry_utils_1.raiseConnectedEvent(this.mc.logger, this, state, this.clientId);
|
|
1205
1199
|
if (logOpsOnReconnect) {
|
|
1206
|
-
this.logger.sendTelemetryEvent({ eventName: "OpsSentOnReconnect", count: this.messageCountAfterDisconnection });
|
|
1200
|
+
this.mc.logger.sendTelemetryEvent({ eventName: "OpsSentOnReconnect", count: this.messageCountAfterDisconnection });
|
|
1207
1201
|
}
|
|
1208
1202
|
}
|
|
1209
1203
|
submitContainerMessage(type, contents, batch, metadata) {
|
|
@@ -1233,7 +1227,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1233
1227
|
}
|
|
1234
1228
|
submitMessage(type, contents, batch, metadata) {
|
|
1235
1229
|
if (this.connectionState !== ConnectionState.Connected) {
|
|
1236
|
-
this.logger.sendErrorEvent({ eventName: "SubmitMessageWithNoConnection", type });
|
|
1230
|
+
this.mc.logger.sendErrorEvent({ eventName: "SubmitMessageWithNoConnection", type });
|
|
1237
1231
|
return -1;
|
|
1238
1232
|
}
|
|
1239
1233
|
this.messageCountAfterDisconnection += 1;
|
|
@@ -1296,15 +1290,15 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1296
1290
|
*/
|
|
1297
1291
|
async fetchSnapshotTree(specifiedVersion) {
|
|
1298
1292
|
var _a;
|
|
1299
|
-
const version = await this.getVersion(specifiedVersion !== null && specifiedVersion !== void 0 ? specifiedVersion :
|
|
1293
|
+
const version = await this.getVersion(specifiedVersion !== null && specifiedVersion !== void 0 ? specifiedVersion : null);
|
|
1300
1294
|
if (version === undefined && specifiedVersion !== undefined) {
|
|
1301
1295
|
// We should have a defined version to load from if specified version requested
|
|
1302
|
-
this.logger.sendErrorEvent({ eventName: "NoVersionFoundWhenSpecified", id: specifiedVersion });
|
|
1296
|
+
this.mc.logger.sendErrorEvent({ eventName: "NoVersionFoundWhenSpecified", id: specifiedVersion });
|
|
1303
1297
|
}
|
|
1304
1298
|
this._loadedFromVersion = version;
|
|
1305
1299
|
const snapshot = (_a = await this.storageService.getSnapshotTree(version)) !== null && _a !== void 0 ? _a : undefined;
|
|
1306
1300
|
if (snapshot === undefined && version !== undefined) {
|
|
1307
|
-
this.logger.sendErrorEvent({ eventName: "getSnapshotTreeFailed", id: version.id });
|
|
1301
|
+
this.mc.logger.sendErrorEvent({ eventName: "getSnapshotTreeFailed", id: version.id });
|
|
1308
1302
|
}
|
|
1309
1303
|
return { snapshot, versionId: version === null || version === void 0 ? void 0 : version.id };
|
|
1310
1304
|
}
|
|
@@ -1320,7 +1314,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1320
1314
|
common_utils_1.assert(((_a = this._context) === null || _a === void 0 ? void 0 : _a.disposed) !== false, 0x0dd /* "Existing context not disposed" */);
|
|
1321
1315
|
// If this assert fires, our state tracking is likely not synchronized between COntainer & runtime.
|
|
1322
1316
|
if (this._dirtyContainer) {
|
|
1323
|
-
this.logger.sendErrorEvent({ eventName: "DirtyContainerReloadContainer" });
|
|
1317
|
+
this.mc.logger.sendErrorEvent({ eventName: "DirtyContainerReloadContainer" });
|
|
1324
1318
|
}
|
|
1325
1319
|
// The relative loader will proxy requests to '/' to the loader itself assuming no non-cache flags
|
|
1326
1320
|
// are set. Global requests will still go directly to the loader
|
|
@@ -1331,10 +1325,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1331
1325
|
}, existing, pendingLocalState);
|
|
1332
1326
|
this.emit("contextChanged", codeDetails);
|
|
1333
1327
|
}
|
|
1334
|
-
// Please avoid calling it directly.
|
|
1335
|
-
// raiseContainerWarning() is the right flow for most cases
|
|
1336
1328
|
logContainerError(warning) {
|
|
1337
|
-
this.logger.sendErrorEvent({ eventName: "ContainerWarning" }, warning);
|
|
1329
|
+
this.mc.logger.sendErrorEvent({ eventName: "ContainerWarning" }, warning);
|
|
1338
1330
|
}
|
|
1339
1331
|
}
|
|
1340
1332
|
exports.Container = Container;
|