Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/conat/socket/keepalive.ts
1453 views
1
import { delay } from "awaiting";
2
import { getLogger } from "@cocalc/conat/client";
3
import { type Role } from "./util";
4
5
const logger = getLogger("socket:keepalive");
6
7
export function keepAlive(opts: {
8
role: Role;
9
ping: () => Promise<any>;
10
disconnect: () => void;
11
keepAlive: number;
12
}) {
13
return new KeepAlive(opts.ping, opts.disconnect, opts.keepAlive, opts.role);
14
}
15
16
export class KeepAlive {
17
private last: number = Date.now();
18
private state: "ready" | "closed" = "ready";
19
20
constructor(
21
private ping: () => Promise<any>,
22
private disconnect: () => void,
23
private keepAlive: number,
24
private role: Role,
25
) {
26
this.run();
27
}
28
29
private run = async () => {
30
while (this.state == "ready") {
31
try {
32
logger.silly(this.role, "keepalive -- sending ping");
33
await this.ping?.();
34
} catch (err) {
35
logger.silly(this.role, "keepalive -- ping failed -- disconnecting");
36
this.disconnect?.();
37
this.close();
38
return;
39
}
40
this.last = Date.now();
41
if (this.state == ("closed" as any)) {
42
return;
43
}
44
await delay(this.keepAlive - (Date.now() - this.last));
45
}
46
};
47
48
// call this when any data is received, which defers having to waste resources on
49
// sending a ping
50
recv = () => {
51
this.last = Date.now();
52
};
53
54
close = () => {
55
this.state = "closed";
56
// @ts-ignore
57
delete this.last;
58
// @ts-ignore
59
delete this.ping;
60
// @ts-ignore
61
delete this.disconnect;
62
};
63
}
64
65