Skip to content

Commit fd610cf

Browse files
committed
fix critical bug in sticky state prop
1 parent 45718de commit fd610cf

File tree

4 files changed

+71
-28
lines changed

4 files changed

+71
-28
lines changed

src/packages/backend/conat/test/setup.ts

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export async function before() {
128128
tempDir = await mkdtemp(join(tmpdir(), "conat-test"));
129129
syncFiles.local = join(tempDir, "local");
130130
syncFiles.archive = join(tempDir, "archive");
131-
131+
132132
server = await createServer();
133133
client = connect();
134134
persistServer = createPersistServer({ client });
@@ -184,40 +184,64 @@ export async function waitForConsistentState(
184184
// now look at everybody else's view of servers[i].
185185
// @ts-ignore
186186
const a = servers[i].interest.serialize().patterns;
187+
const b = servers[i].sticky;
188+
const hashServer = servers[i].hash();
187189
for (let j = 0; j < servers.length; j++) {
188190
if (i != j) {
189191
// @ts-ignore
190192
const link = servers[j].clusterLinks[clusterName]?.[servers[i].id];
191193
if (link == null) {
192194
throw Error(`node ${j} is not connected to node ${i}`);
193195
}
196+
const hashLink = link.hash();
194197
const x = link.interest.serialize().patterns;
198+
const y = link.sticky;
195199
const showInfo = () => {
196-
console.log(
197-
"server stream getAll: ",
198-
// @ts-ignore
199-
servers[i].clusterStreams.interest.stream.client.id,
200-
// @ts-ignore
201-
servers[i].clusterStreams.interest.stream.storage.path,
202-
// @ts-ignore
203-
servers[i].clusterStreams.interest.seqs(),
204-
// @ts-ignore
205-
//servers[i].clusterStreams.interest.getAll(),
206-
);
207-
console.log(
208-
"link stream getAll: ",
209-
// @ts-ignore
210-
link.streams.interest.stream.client.id,
211-
// @ts-ignore
212-
link.streams.interest.stream.storage.path,
213-
// @ts-ignore
214-
link.streams.interest.seqs(),
215-
// @ts-ignore
216-
//link.streams.interest.getAll(),
217-
);
218-
console.log("waitForConsistentState", { i, j, a, x });
200+
for (const type of ["interest", "sticky"]) {
201+
console.log(
202+
`server stream ${type}: `,
203+
hashServer[type],
204+
// @ts-ignore
205+
servers[i].clusterStreams[type].stream.client.id,
206+
// @ts-ignore
207+
servers[i].clusterStreams[type].stream.storage.path,
208+
// @ts-ignore
209+
servers[i].clusterStreams[type].seqs(),
210+
// @ts-ignore
211+
//servers[i].clusterStreams.interest.getAll(),
212+
);
213+
214+
console.log(
215+
`link stream ${type}: `,
216+
hashLink[type],
217+
// @ts-ignore
218+
link.streams[type].stream.client.id,
219+
// @ts-ignore
220+
link.streams[type].stream.storage.path,
221+
// @ts-ignore
222+
link.streams[type].seqs(),
223+
// @ts-ignore
224+
//link.streams.interest.getAll(),
225+
);
226+
}
227+
console.log("waitForConsistentState", {
228+
i,
229+
j,
230+
serverInterest: a,
231+
linkInterest: x,
232+
serverSticky: b,
233+
linkSticky: y,
234+
});
219235
};
220-
if (!isEqual(a, x)) {
236+
if (!isEqual(hashServer, hashLink)) {
237+
if (Date.now() - start > 3000) {
238+
console.log("hashes are not equal");
239+
// likely going to fail
240+
showInfo();
241+
}
242+
return false;
243+
}
244+
if (!isEqual(a, x) /*|| !isEqual(b, y) */) {
221245
// @ts-ignore
222246
const seqs0 = servers[i].clusterStreams.interest.seqs();
223247
const seqs1 = link.streams.interest.seqs();

src/packages/conat/core/cluster.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ class ClusterLink {
8383
for (const update of this.streams.interest.getAll()) {
8484
updateInterest(update, this.interest, this.sticky);
8585
}
86+
for (const update of this.streams.sticky.getAll()) {
87+
updateSticky(update, this.sticky);
88+
}
8689
// I have a slight concern about this because updates might not
8790
// arrive in order during automatic failover. That said, maybe
8891
// automatic failover doesn't matter with these streams, since
@@ -168,6 +171,13 @@ class ClusterLink {
168171

169172
return false;
170173
};
174+
175+
hash = (): { interest: number; sticky: number } => {
176+
return {
177+
interest: hashInterest(this.interest),
178+
sticky: hashSticky(this.sticky),
179+
};
180+
};
171181
}
172182

173183
function clusterStreamNames({

src/packages/conat/core/server.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ import {
6363
createClusterPersistServer,
6464
Sticky,
6565
Interest,
66+
hashInterest,
67+
hashSticky,
6668
} from "./cluster";
6769
import { type ConatSocketServer } from "@cocalc/conat/socket";
6870
import { throttle } from "lodash";
@@ -174,10 +176,10 @@ export class ConatServer extends EventEmitter {
174176
public state: State = "init";
175177

176178
private subscriptions: { [socketId: string]: Set<string> } = {};
177-
private interest: Interest = new Patterns();
179+
public interest: Interest = new Patterns();
178180
// the target string is JSON.stringify({ id: string; subject: string }),
179181
// which is the socket.io room to send the messages to.
180-
private sticky: Sticky = {};
182+
public sticky: Sticky = {};
181183

182184
private clusterStreams?: ClusterStreams;
183185
private clusterLinks: {
@@ -1532,6 +1534,13 @@ export class ConatServer extends EventEmitter {
15321534
}
15331535
return false;
15341536
};
1537+
1538+
hash = (): { interest: number; sticky: number } => {
1539+
return {
1540+
interest: hashInterest(this.interest),
1541+
sticky: hashSticky(this.sticky),
1542+
};
1543+
};
15351544
}
15361545

15371546
function getSubjectFromRoom(room: string) {

src/packages/util/smc-version.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
/* autogenerated by the update_version script */
2-
exports.version=1752021564;
2+
exports.version=1752088354;

0 commit comments

Comments
 (0)