Path: blob/master/src/packages/conat/socket/keepalive.ts
1453 views
import { delay } from "awaiting";1import { getLogger } from "@cocalc/conat/client";2import { type Role } from "./util";34const logger = getLogger("socket:keepalive");56export function keepAlive(opts: {7role: Role;8ping: () => Promise<any>;9disconnect: () => void;10keepAlive: number;11}) {12return new KeepAlive(opts.ping, opts.disconnect, opts.keepAlive, opts.role);13}1415export class KeepAlive {16private last: number = Date.now();17private state: "ready" | "closed" = "ready";1819constructor(20private ping: () => Promise<any>,21private disconnect: () => void,22private keepAlive: number,23private role: Role,24) {25this.run();26}2728private run = async () => {29while (this.state == "ready") {30try {31logger.silly(this.role, "keepalive -- sending ping");32await this.ping?.();33} catch (err) {34logger.silly(this.role, "keepalive -- ping failed -- disconnecting");35this.disconnect?.();36this.close();37return;38}39this.last = Date.now();40if (this.state == ("closed" as any)) {41return;42}43await delay(this.keepAlive - (Date.now() - this.last));44}45};4647// call this when any data is received, which defers having to waste resources on48// sending a ping49recv = () => {50this.last = Date.now();51};5253close = () => {54this.state = "closed";55// @ts-ignore56delete this.last;57// @ts-ignore58delete this.ping;59// @ts-ignore60delete this.disconnect;61};62}636465