Skip to content

Commit 4dba700

Browse files
committed
ensure conat clients ack the initial info message
- i think sometimes this message is missed, so clients remain non-initialized
1 parent 654505e commit 4dba700

File tree

4 files changed

+44
-14
lines changed

4 files changed

+44
-14
lines changed

src/packages/conat/core/client.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,10 @@ export class Client extends EventEmitter {
510510
reconnection: true,
511511
});
512512

513-
this.conn.on("info", (info) => {
513+
this.conn.on("info", (info, ack) => {
514+
if (typeof ack == "function") {
515+
ack();
516+
}
514517
const firstTime = this.info == null;
515518
this.info = info;
516519
this.emit("info", info);

src/packages/conat/core/server.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ import {
5353
import { Patterns } from "./patterns";
5454
import { is_array } from "@cocalc/util/misc";
5555
import { UsageMonitor } from "@cocalc/conat/monitor/usage";
56-
import { once } from "@cocalc/util/async-utils";
56+
import { once, until } from "@cocalc/util/async-utils";
5757
import {
5858
clusterLink,
5959
type ClusterLink,
@@ -940,7 +940,7 @@ export class ConatServer extends EventEmitter {
940940
this.subscriptions[id] = new Set<string>();
941941
}
942942

943-
socket.emit("info", { ...this.info(), user });
943+
this.sendInfo(socket, user);
944944

945945
socket.on("stats", ({ recv0 }) => {
946946
const s = this.stats[socket.id];
@@ -1086,6 +1086,38 @@ export class ConatServer extends EventEmitter {
10861086
});
10871087
};
10881088

1089+
sendInfo = async (socket, user) => {
1090+
// we send info with an ack because I think sometimes the initial "info"
1091+
// message gets dropped, leaving a broken hanging connection that never
1092+
// does anything (until the user explicitly refreshes their browser).
1093+
// I did see what is probably this in production frequently.
1094+
try {
1095+
await until(
1096+
async () => {
1097+
if (!socket.conn?.readyState.startsWith("o")) {
1098+
// logger.debug(`failed to send "info" message to ${socket.id}`);
1099+
// readyState not defined or not opened or opening, so connection must
1100+
// have been closed before success.
1101+
return true;
1102+
}
1103+
try {
1104+
await socket
1105+
.timeout(7500)
1106+
.emitWithAck("info", { ...this.info(), user });
1107+
return true;
1108+
} catch (err) {
1109+
// logger.debug(`error sending "info" message to ${socket.id}`, err);
1110+
return false;
1111+
}
1112+
},
1113+
{ min: 5000, max: 30000, timeout: 120_000 },
1114+
);
1115+
} catch {
1116+
// never ack'd "info" after a few minutes -- could just be an old client,
1117+
// so don't do anything at this point.
1118+
}
1119+
};
1120+
10891121
address = () => getServerAddress(this.options);
10901122

10911123
// create new client in the same process connected to this server.
@@ -1349,8 +1381,8 @@ export class ConatServer extends EventEmitter {
13491381
const usage = async () => {
13501382
return { [this.id]: this.usage.stats() };
13511383
};
1352-
// user has to explicitly refresh there browser after
1353-
// being disconnected this way
1384+
// user has to explicitly refresh their browser after
1385+
// being disconnected this way:
13541386
const disconnect = async (ids: string | string[]) => {
13551387
if (typeof ids == "string") {
13561388
ids = [ids];

src/packages/frontend/client/idle.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export class IdleClient {
8484

8585
if (NEVER_TIMEOUT_VISIBLE) {
8686
// If the document is visible right now, then we
87-
// reset the idle timeout., just as if the mouse moved. This means
87+
// reset the idle timeout, just as if the mouse moved. This means
8888
// that users never get the standby timeout if their current browser
8989
// tab is considered visible according to the Page Visibility API
9090
// https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
@@ -110,6 +110,7 @@ export class IdleClient {
110110
// so that if the user sees the idle banner and immediately
111111
// dismisses it, then the experience is less disruptive.
112112
this.delayed_disconnect = setTimeout(() => {
113+
this.delayed_disconnect = undefined;
113114
console.log("Entering standby mode");
114115
this.standbyMode = true;
115116
// console.log("idle timeout: disconnect!");

src/scripts/g-tmux.sh

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,8 @@ sleep 2
1212
tmux send-keys -t mysession:1 'pnpm database' C-m
1313

1414
if [ -n "$NO_RSPACK_DEV_SERVER" ]; then
15-
sleep 2
16-
tmux send-keys -t mysession:2 'pnpm rspack' C-m
17-
18-
else
19-
20-
# no longer needed, due to using rspack for nextjs
21-
#sleep 2
22-
#tmux send-keys -t mysession:2 '$PWD/scripts/memory_monitor.py' C-m
15+
sleep 2
16+
tmux send-keys -t mysession:2 'pnpm rspack' C-m
2317
fi
2418

2519
tmux attach -t mysession:1

0 commit comments

Comments
 (0)