@fluidframework/container-loader 2.0.0-internal.5.4.0 → 2.0.0-internal.5.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +1 -18
- package/dist/container.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/protocol.d.ts +4 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +23 -1
- package/dist/protocol.js.map +1 -1
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +2 -19
- package/lib/container.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/protocol.d.ts +4 -2
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +23 -1
- package/lib/protocol.js.map +1 -1
- package/package.json +9 -9
- package/src/container.ts +13 -24
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +33 -1
package/lib/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/container-loader";
|
|
8
|
-
export declare const pkgVersion = "2.0.0-internal.5.4.
|
|
8
|
+
export declare const pkgVersion = "2.0.0-internal.5.4.2";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/lib/packageVersion.js
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export const pkgName = "@fluidframework/container-loader";
|
|
8
|
-
export const pkgVersion = "2.0.0-internal.5.4.
|
|
8
|
+
export const pkgVersion = "2.0.0-internal.5.4.2";
|
|
9
9
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-loader\";\nexport const pkgVersion = \"2.0.0-internal.5.4.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-loader\";\nexport const pkgVersion = \"2.0.0-internal.5.4.2\";\n"]}
|
package/lib/protocol.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { IAudienceOwner } from "@fluidframework/container-definitions";
|
|
6
6
|
import { IProtocolHandler as IBaseProtocolHandler, IQuorumSnapshot, ProtocolOpHandler } from "@fluidframework/protocol-base";
|
|
7
|
-
import { IDocumentAttributes, ISignalMessage } from "@fluidframework/protocol-definitions";
|
|
7
|
+
import { IDocumentAttributes, IProcessMessageResult, ISequencedDocumentMessage, ISignalMessage } from "@fluidframework/protocol-definitions";
|
|
8
8
|
export declare const OnlyValidTermValue: 1;
|
|
9
9
|
export declare enum SignalType {
|
|
10
10
|
ClientJoin = "join",
|
|
@@ -21,7 +21,9 @@ export interface IProtocolHandler extends IBaseProtocolHandler {
|
|
|
21
21
|
}
|
|
22
22
|
export declare class ProtocolHandler extends ProtocolOpHandler implements IProtocolHandler {
|
|
23
23
|
readonly audience: IAudienceOwner;
|
|
24
|
-
|
|
24
|
+
private readonly shouldClientHaveLeft;
|
|
25
|
+
constructor(attributes: IDocumentAttributes, quorumSnapshot: IQuorumSnapshot, sendProposal: (key: string, value: any) => number, audience: IAudienceOwner, shouldClientHaveLeft: (clientId: string) => boolean);
|
|
26
|
+
processMessage(message: ISequencedDocumentMessage, local: boolean): IProcessMessageResult;
|
|
25
27
|
processSignal(message: ISignalMessage): void;
|
|
26
28
|
}
|
|
27
29
|
/**
|
package/lib/protocol.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAEvE,OAAO,EACN,gBAAgB,IAAI,oBAAoB,EACxC,eAAe,EACf,iBAAiB,EACjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACN,mBAAmB,EACnB,qBAAqB,EAErB,yBAAyB,EAEzB,cAAc,EAEd,MAAM,sCAAsC,CAAC;AAG9C,eAAO,MAAM,kBAAkB,GAAa,CAAC;AAG7C,oBAAY,UAAU;IACrB,UAAU,SAAS;IACnB,WAAW,UAAU;IACrB,KAAK,UAAU;CACf;AAED;;GAEG;AACH,oBAAY,sBAAsB,GAAG,CACpC,UAAU,EAAE,mBAAmB,EAC/B,QAAQ,EAAE,eAAe,EACzB,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,MAAM,KAC7C,gBAAgB,CAAC;AAEtB,MAAM,WAAW,gBAAiB,SAAQ,oBAAoB;IAC7D,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,aAAa,CAAC,OAAO,EAAE,cAAc,OAAE;CACvC;AAED,qBAAa,eAAgB,SAAQ,iBAAkB,YAAW,gBAAgB;aAKhE,QAAQ,EAAE,cAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,oBAAoB;gBAJrC,UAAU,EAAE,mBAAmB,EAC/B,cAAc,EAAE,eAAe,EAC/B,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,MAAM,EACjC,QAAQ,EAAE,cAAc,EACvB,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO;IAsB9D,cAAc,CACpB,OAAO,EAAE,yBAAyB,EAClC,KAAK,EAAE,OAAO,GACZ,qBAAqB;IAuBjB,aAAa,CAAC,OAAO,EAAE,cAAc;CAgC5C;AAED;;;;GAIG;AACH,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,cAAc,WAWzE"}
|
package/lib/protocol.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
+
import { canBeCoalescedByService } from "@fluidframework/driver-utils";
|
|
5
6
|
import { ProtocolOpHandler, } from "@fluidframework/protocol-base";
|
|
7
|
+
import { MessageType, } from "@fluidframework/protocol-definitions";
|
|
6
8
|
// "term" was an experimental feature that is being removed. The only safe value to use is 1.
|
|
7
9
|
export const OnlyValidTermValue = 1;
|
|
8
10
|
// ADO: #1986: Start using enum from protocol-base.
|
|
@@ -13,9 +15,10 @@ export var SignalType;
|
|
|
13
15
|
SignalType["Clear"] = "clear";
|
|
14
16
|
})(SignalType || (SignalType = {}));
|
|
15
17
|
export class ProtocolHandler extends ProtocolOpHandler {
|
|
16
|
-
constructor(attributes, quorumSnapshot, sendProposal, audience) {
|
|
18
|
+
constructor(attributes, quorumSnapshot, sendProposal, audience, shouldClientHaveLeft) {
|
|
17
19
|
super(attributes.minimumSequenceNumber, attributes.sequenceNumber, OnlyValidTermValue, quorumSnapshot.members, quorumSnapshot.proposals, quorumSnapshot.values, sendProposal);
|
|
18
20
|
this.audience = audience;
|
|
21
|
+
this.shouldClientHaveLeft = shouldClientHaveLeft;
|
|
19
22
|
// Join / leave signals are ignored for "write" clients in favor of join / leave ops
|
|
20
23
|
this.quorum.on("addMember", (clientId, details) => audience.addMember(clientId, details.client));
|
|
21
24
|
this.quorum.on("removeMember", (clientId) => audience.removeMember(clientId));
|
|
@@ -23,6 +26,25 @@ export class ProtocolHandler extends ProtocolOpHandler {
|
|
|
23
26
|
this.audience.addMember(clientId, details.client);
|
|
24
27
|
}
|
|
25
28
|
}
|
|
29
|
+
processMessage(message, local) {
|
|
30
|
+
const client = this.quorum.getMember(message.clientId);
|
|
31
|
+
// Check and report if we're getting messages from a clientId that we previously
|
|
32
|
+
// flagged as shouldHaveLeft, or from a client that's not in the quorum but should be
|
|
33
|
+
if (message.clientId != null) {
|
|
34
|
+
if (client === undefined && message.type !== MessageType.ClientJoin) {
|
|
35
|
+
// pre-0.58 error message: messageClientIdMissingFromQuorum
|
|
36
|
+
throw new Error("Remote message's clientId is missing from the quorum");
|
|
37
|
+
}
|
|
38
|
+
// Here checking canBeCoalescedByService is used as an approximation of "is benign to process despite being unexpected".
|
|
39
|
+
// It's still not good to see these messages from unexpected clientIds, but since they don't harm the integrity of the
|
|
40
|
+
// document we don't need to blow up aggressively.
|
|
41
|
+
if (this.shouldClientHaveLeft(message.clientId) && !canBeCoalescedByService(message)) {
|
|
42
|
+
// pre-0.58 error message: messageClientIdShouldHaveLeft
|
|
43
|
+
throw new Error("Remote message's clientId already should have left");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return super.processMessage(message, local);
|
|
47
|
+
}
|
|
26
48
|
processSignal(message) {
|
|
27
49
|
var _a;
|
|
28
50
|
const innerContent = message.content;
|
package/lib/protocol.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAGN,iBAAiB,GACjB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.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 { IAudienceOwner } from \"@fluidframework/container-definitions\";\nimport { canBeCoalescedByService } from \"@fluidframework/driver-utils\";\nimport {\n\tIProtocolHandler as IBaseProtocolHandler,\n\tIQuorumSnapshot,\n\tProtocolOpHandler,\n} from \"@fluidframework/protocol-base\";\nimport {\n\tIDocumentAttributes,\n\tIProcessMessageResult,\n\tISequencedClient,\n\tISequencedDocumentMessage,\n\tISignalClient,\n\tISignalMessage,\n\tMessageType,\n} from \"@fluidframework/protocol-definitions\";\n\n// \"term\" was an experimental feature that is being removed. The only safe value to use is 1.\nexport const OnlyValidTermValue = 1 as const;\n\n// ADO: #1986: Start using enum from protocol-base.\nexport enum SignalType {\n\tClientJoin = \"join\", // same value as MessageType.ClientJoin,\n\tClientLeave = \"leave\", // same value as MessageType.ClientLeave,\n\tClear = \"clear\", // used only by client for synthetic signals\n}\n\n/**\n * Function to be used for creating a protocol handler.\n */\nexport type ProtocolHandlerBuilder = (\n\tattributes: IDocumentAttributes,\n\tsnapshot: IQuorumSnapshot,\n\tsendProposal: (key: string, value: any) => number,\n) => IProtocolHandler;\n\nexport interface IProtocolHandler extends IBaseProtocolHandler {\n\treadonly audience: IAudienceOwner;\n\tprocessSignal(message: ISignalMessage);\n}\n\nexport class ProtocolHandler extends ProtocolOpHandler implements IProtocolHandler {\n\tconstructor(\n\t\tattributes: IDocumentAttributes,\n\t\tquorumSnapshot: IQuorumSnapshot,\n\t\tsendProposal: (key: string, value: any) => number,\n\t\tpublic readonly audience: IAudienceOwner,\n\t\tprivate readonly shouldClientHaveLeft: (clientId: string) => boolean,\n\t) {\n\t\tsuper(\n\t\t\tattributes.minimumSequenceNumber,\n\t\t\tattributes.sequenceNumber,\n\t\t\tOnlyValidTermValue,\n\t\t\tquorumSnapshot.members,\n\t\t\tquorumSnapshot.proposals,\n\t\t\tquorumSnapshot.values,\n\t\t\tsendProposal,\n\t\t);\n\n\t\t// Join / leave signals are ignored for \"write\" clients in favor of join / leave ops\n\t\tthis.quorum.on(\"addMember\", (clientId, details) =>\n\t\t\taudience.addMember(clientId, details.client),\n\t\t);\n\t\tthis.quorum.on(\"removeMember\", (clientId) => audience.removeMember(clientId));\n\t\tfor (const [clientId, details] of this.quorum.getMembers()) {\n\t\t\tthis.audience.addMember(clientId, details.client);\n\t\t}\n\t}\n\n\tpublic processMessage(\n\t\tmessage: ISequencedDocumentMessage,\n\t\tlocal: boolean,\n\t): IProcessMessageResult {\n\t\tconst client: ISequencedClient | undefined = this.quorum.getMember(message.clientId);\n\n\t\t// Check and report if we're getting messages from a clientId that we previously\n\t\t// flagged as shouldHaveLeft, or from a client that's not in the quorum but should be\n\t\tif (message.clientId != null) {\n\t\t\tif (client === undefined && message.type !== MessageType.ClientJoin) {\n\t\t\t\t// pre-0.58 error message: messageClientIdMissingFromQuorum\n\t\t\t\tthrow new Error(\"Remote message's clientId is missing from the quorum\");\n\t\t\t}\n\n\t\t\t// Here checking canBeCoalescedByService is used as an approximation of \"is benign to process despite being unexpected\".\n\t\t\t// It's still not good to see these messages from unexpected clientIds, but since they don't harm the integrity of the\n\t\t\t// document we don't need to blow up aggressively.\n\t\t\tif (this.shouldClientHaveLeft(message.clientId) && !canBeCoalescedByService(message)) {\n\t\t\t\t// pre-0.58 error message: messageClientIdShouldHaveLeft\n\t\t\t\tthrow new Error(\"Remote message's clientId already should have left\");\n\t\t\t}\n\t\t}\n\n\t\treturn super.processMessage(message, local);\n\t}\n\n\tpublic processSignal(message: ISignalMessage) {\n\t\tconst innerContent = message.content as { content: any; type: string };\n\t\tswitch (innerContent.type) {\n\t\t\tcase SignalType.Clear: {\n\t\t\t\tconst members = this.audience.getMembers();\n\t\t\t\tfor (const [clientId, client] of members) {\n\t\t\t\t\tif (client.mode === \"read\") {\n\t\t\t\t\t\tthis.audience.removeMember(clientId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SignalType.ClientJoin: {\n\t\t\t\tconst newClient = innerContent.content as ISignalClient;\n\t\t\t\t// Ignore write clients - quorum will control such clients.\n\t\t\t\tif (newClient.client.mode === \"read\") {\n\t\t\t\t\tthis.audience.addMember(newClient.clientId, newClient.client);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SignalType.ClientLeave: {\n\t\t\t\tconst leftClientId = innerContent.content as string;\n\t\t\t\t// Ignore write clients - quorum will control such clients.\n\t\t\t\tif (this.audience.getMember(leftClientId)?.mode === \"read\") {\n\t\t\t\t\tthis.audience.removeMember(leftClientId);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Function to check whether the protocol handler should process the Signal.\n * The protocol handler should strictly handle only ClientJoin, ClientLeave\n * and Clear signal types.\n */\nexport function protocolHandlerShouldProcessSignal(message: ISignalMessage) {\n\t// Signal originates from server\n\tif (message.clientId === null) {\n\t\tconst innerContent = message.content as { content: unknown; type: string };\n\t\treturn (\n\t\t\tinnerContent.type === SignalType.Clear ||\n\t\t\tinnerContent.type === SignalType.ClientJoin ||\n\t\t\tinnerContent.type === SignalType.ClientLeave\n\t\t);\n\t}\n\treturn false;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/container-loader",
|
|
3
|
-
"version": "2.0.0-internal.5.4.
|
|
3
|
+
"version": "2.0.0-internal.5.4.2",
|
|
4
4
|
"description": "Fluid container loader",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -37,14 +37,14 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
39
39
|
"@fluidframework/common-utils": "^1.1.1",
|
|
40
|
-
"@fluidframework/container-definitions": ">=2.0.0-internal.5.4.
|
|
41
|
-
"@fluidframework/container-utils": ">=2.0.0-internal.5.4.
|
|
42
|
-
"@fluidframework/core-interfaces": ">=2.0.0-internal.5.4.
|
|
43
|
-
"@fluidframework/driver-definitions": ">=2.0.0-internal.5.4.
|
|
44
|
-
"@fluidframework/driver-utils": ">=2.0.0-internal.5.4.
|
|
40
|
+
"@fluidframework/container-definitions": ">=2.0.0-internal.5.4.2 <2.0.0-internal.5.5.0",
|
|
41
|
+
"@fluidframework/container-utils": ">=2.0.0-internal.5.4.2 <2.0.0-internal.5.5.0",
|
|
42
|
+
"@fluidframework/core-interfaces": ">=2.0.0-internal.5.4.2 <2.0.0-internal.5.5.0",
|
|
43
|
+
"@fluidframework/driver-definitions": ">=2.0.0-internal.5.4.2 <2.0.0-internal.5.5.0",
|
|
44
|
+
"@fluidframework/driver-utils": ">=2.0.0-internal.5.4.2 <2.0.0-internal.5.5.0",
|
|
45
45
|
"@fluidframework/protocol-base": "^0.1039.1000",
|
|
46
46
|
"@fluidframework/protocol-definitions": "^1.1.0",
|
|
47
|
-
"@fluidframework/telemetry-utils": ">=2.0.0-internal.5.4.
|
|
47
|
+
"@fluidframework/telemetry-utils": ">=2.0.0-internal.5.4.2 <2.0.0-internal.5.5.0",
|
|
48
48
|
"debug": "^4.1.1",
|
|
49
49
|
"double-ended-queue": "^2.1.0-0",
|
|
50
50
|
"events": "^3.1.0",
|
|
@@ -53,13 +53,13 @@
|
|
|
53
53
|
"uuid": "^8.3.1"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@fluid-internal/test-loader-utils": ">=2.0.0-internal.5.4.
|
|
56
|
+
"@fluid-internal/test-loader-utils": ">=2.0.0-internal.5.4.2 <2.0.0-internal.5.5.0",
|
|
57
57
|
"@fluid-tools/build-cli": "^0.21.0",
|
|
58
58
|
"@fluidframework/build-common": "^1.2.0",
|
|
59
59
|
"@fluidframework/build-tools": "^0.21.0",
|
|
60
60
|
"@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@2.0.0-internal.5.2.0",
|
|
61
61
|
"@fluidframework/eslint-config-fluid": "^2.0.0",
|
|
62
|
-
"@fluidframework/mocha-test-setup": ">=2.0.0-internal.5.4.
|
|
62
|
+
"@fluidframework/mocha-test-setup": ">=2.0.0-internal.5.4.2 <2.0.0-internal.5.5.0",
|
|
63
63
|
"@microsoft/api-extractor": "^7.34.4",
|
|
64
64
|
"@types/double-ended-queue": "^2.1.0",
|
|
65
65
|
"@types/events": "^3.0.0",
|
package/src/container.ts
CHANGED
|
@@ -62,7 +62,6 @@ import {
|
|
|
62
62
|
runWithRetry,
|
|
63
63
|
isCombinedAppAndProtocolSummary,
|
|
64
64
|
MessageType2,
|
|
65
|
-
canBeCoalescedByService,
|
|
66
65
|
} from "@fluidframework/driver-utils";
|
|
67
66
|
import { IQuorumSnapshot } from "@fluidframework/protocol-base";
|
|
68
67
|
import {
|
|
@@ -748,7 +747,19 @@ export class Container
|
|
|
748
747
|
this.scope = scope;
|
|
749
748
|
this.detachedBlobStorage = detachedBlobStorage;
|
|
750
749
|
this.protocolHandlerBuilder =
|
|
751
|
-
protocolHandlerBuilder ??
|
|
750
|
+
protocolHandlerBuilder ??
|
|
751
|
+
((
|
|
752
|
+
attributes: IDocumentAttributes,
|
|
753
|
+
quorumSnapshot: IQuorumSnapshot,
|
|
754
|
+
sendProposal: (key: string, value: any) => number,
|
|
755
|
+
) =>
|
|
756
|
+
new ProtocolHandler(
|
|
757
|
+
attributes,
|
|
758
|
+
quorumSnapshot,
|
|
759
|
+
sendProposal,
|
|
760
|
+
new Audience(),
|
|
761
|
+
(clientId: string) => this.clientsWhoShouldHaveLeft.has(clientId),
|
|
762
|
+
));
|
|
752
763
|
|
|
753
764
|
// Note that we capture the createProps here so we can replicate the creation call when we want to clone.
|
|
754
765
|
this.clone = async (
|
|
@@ -2157,28 +2168,6 @@ export class Container
|
|
|
2157
2168
|
}
|
|
2158
2169
|
const local = this.clientId === message.clientId;
|
|
2159
2170
|
|
|
2160
|
-
// Check and report if we're getting messages from a clientId that we previously
|
|
2161
|
-
// flagged should have left, or from a client that's not in the quorum but should be
|
|
2162
|
-
if (message.clientId != null) {
|
|
2163
|
-
const client = this.protocolHandler.quorum.getMember(message.clientId);
|
|
2164
|
-
|
|
2165
|
-
if (client === undefined && message.type !== MessageType.ClientJoin) {
|
|
2166
|
-
// pre-0.58 error message: messageClientIdMissingFromQuorum
|
|
2167
|
-
throw new Error("Remote message's clientId is missing from the quorum");
|
|
2168
|
-
}
|
|
2169
|
-
|
|
2170
|
-
// Here checking canBeCoalescedByService is used as an approximation of "is benign to process despite being unexpected".
|
|
2171
|
-
// It's still not good to see these messages from unexpected clientIds, but since they don't harm the integrity of the
|
|
2172
|
-
// document we don't need to blow up aggressively.
|
|
2173
|
-
if (
|
|
2174
|
-
this.clientsWhoShouldHaveLeft.has(message.clientId) &&
|
|
2175
|
-
!canBeCoalescedByService(message)
|
|
2176
|
-
) {
|
|
2177
|
-
// pre-0.58 error message: messageClientIdShouldHaveLeft
|
|
2178
|
-
throw new Error("Remote message's clientId already should have left");
|
|
2179
|
-
}
|
|
2180
|
-
}
|
|
2181
|
-
|
|
2182
2171
|
// Allow the protocol handler to process the message
|
|
2183
2172
|
const result = this.protocolHandler.processMessage(message, local);
|
|
2184
2173
|
|
package/src/packageVersion.ts
CHANGED
package/src/protocol.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { IAudienceOwner } from "@fluidframework/container-definitions";
|
|
7
|
+
import { canBeCoalescedByService } from "@fluidframework/driver-utils";
|
|
7
8
|
import {
|
|
8
9
|
IProtocolHandler as IBaseProtocolHandler,
|
|
9
10
|
IQuorumSnapshot,
|
|
@@ -11,8 +12,12 @@ import {
|
|
|
11
12
|
} from "@fluidframework/protocol-base";
|
|
12
13
|
import {
|
|
13
14
|
IDocumentAttributes,
|
|
15
|
+
IProcessMessageResult,
|
|
16
|
+
ISequencedClient,
|
|
17
|
+
ISequencedDocumentMessage,
|
|
14
18
|
ISignalClient,
|
|
15
19
|
ISignalMessage,
|
|
20
|
+
MessageType,
|
|
16
21
|
} from "@fluidframework/protocol-definitions";
|
|
17
22
|
|
|
18
23
|
// "term" was an experimental feature that is being removed. The only safe value to use is 1.
|
|
@@ -44,7 +49,8 @@ export class ProtocolHandler extends ProtocolOpHandler implements IProtocolHandl
|
|
|
44
49
|
attributes: IDocumentAttributes,
|
|
45
50
|
quorumSnapshot: IQuorumSnapshot,
|
|
46
51
|
sendProposal: (key: string, value: any) => number,
|
|
47
|
-
readonly audience: IAudienceOwner,
|
|
52
|
+
public readonly audience: IAudienceOwner,
|
|
53
|
+
private readonly shouldClientHaveLeft: (clientId: string) => boolean,
|
|
48
54
|
) {
|
|
49
55
|
super(
|
|
50
56
|
attributes.minimumSequenceNumber,
|
|
@@ -66,6 +72,32 @@ export class ProtocolHandler extends ProtocolOpHandler implements IProtocolHandl
|
|
|
66
72
|
}
|
|
67
73
|
}
|
|
68
74
|
|
|
75
|
+
public processMessage(
|
|
76
|
+
message: ISequencedDocumentMessage,
|
|
77
|
+
local: boolean,
|
|
78
|
+
): IProcessMessageResult {
|
|
79
|
+
const client: ISequencedClient | undefined = this.quorum.getMember(message.clientId);
|
|
80
|
+
|
|
81
|
+
// Check and report if we're getting messages from a clientId that we previously
|
|
82
|
+
// flagged as shouldHaveLeft, or from a client that's not in the quorum but should be
|
|
83
|
+
if (message.clientId != null) {
|
|
84
|
+
if (client === undefined && message.type !== MessageType.ClientJoin) {
|
|
85
|
+
// pre-0.58 error message: messageClientIdMissingFromQuorum
|
|
86
|
+
throw new Error("Remote message's clientId is missing from the quorum");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Here checking canBeCoalescedByService is used as an approximation of "is benign to process despite being unexpected".
|
|
90
|
+
// It's still not good to see these messages from unexpected clientIds, but since they don't harm the integrity of the
|
|
91
|
+
// document we don't need to blow up aggressively.
|
|
92
|
+
if (this.shouldClientHaveLeft(message.clientId) && !canBeCoalescedByService(message)) {
|
|
93
|
+
// pre-0.58 error message: messageClientIdShouldHaveLeft
|
|
94
|
+
throw new Error("Remote message's clientId already should have left");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return super.processMessage(message, local);
|
|
99
|
+
}
|
|
100
|
+
|
|
69
101
|
public processSignal(message: ISignalMessage) {
|
|
70
102
|
const innerContent = message.content as { content: any; type: string };
|
|
71
103
|
switch (innerContent.type) {
|