Skip to content

Commit b09bd29

Browse files
committed
add terminal heartbeat
1 parent c19ad9b commit b09bd29

File tree

4 files changed

+33
-3
lines changed

4 files changed

+33
-3
lines changed

src/packages/conat/service/typed.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type { Options, ServiceCall } from "./service";
99
export type { ConatService };
1010

1111
export interface Extra {
12-
ping: typeof pingConatService;
12+
ping: (opts?: { maxWait?: number }) => Promise<void>;
1313
waitFor: (opts?: { maxWait?: number }) => Promise<void>;
1414
}
1515

src/packages/frontend/frame-editors/terminal-editor/conat-terminal.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
} from "@cocalc/conat/service/terminal";
1313
import { until } from "@cocalc/util/async-utils";
1414

15+
const DEFAULT_HEARTBEAT_INTERVAL = 15_000;
16+
1517
type State = "disconnected" | "init" | "running" | "closed";
1618

1719
export class ConatTerminal extends EventEmitter {
@@ -29,6 +31,7 @@ export class ConatTerminal extends EventEmitter {
2931
private writeQueue: string = "";
3032
private ephemeral?: boolean;
3133
private computeServers?;
34+
private heartbeatInterval: number;
3235

3336
constructor({
3437
project_id,
@@ -40,6 +43,7 @@ export class ConatTerminal extends EventEmitter {
4043
options,
4144
measureSize,
4245
ephemeral,
46+
heartbeatInterval = DEFAULT_HEARTBEAT_INTERVAL,
4347
}: {
4448
project_id: string;
4549
path: string;
@@ -50,6 +54,7 @@ export class ConatTerminal extends EventEmitter {
5054
options?;
5155
measureSize?;
5256
ephemeral?: boolean;
57+
heartbeatInterval?: number;
5358
}) {
5459
super();
5560
this.ephemeral = ephemeral;
@@ -63,13 +68,35 @@ export class ConatTerminal extends EventEmitter {
6368
this.terminalResize = terminalResize;
6469
this.openPaths = openPaths;
6570
this.closePaths = closePaths;
71+
this.heartbeatInterval = heartbeatInterval;
6672
webapp_client.conat_client.on("connected", this.clearWriteQueue);
6773
this.computeServers = webapp_client.project_client.computeServers(
6874
this.project_id,
6975
);
7076
this.computeServers?.on("change", this.handleComputeServersChange);
7177
}
7278

79+
// ping server periodically -- if failure, closes conenction immediately
80+
// so it can be fixed when user comes back, instead of having to react to
81+
// a write failing (which also handles the same issue)
82+
private heartbeat = reuseInFlight(async () => {
83+
await until(
84+
async () => {
85+
if (this.isClosed()) {
86+
return true;
87+
}
88+
try {
89+
await this.api.conat.ping({ maxWait: 5000 });
90+
return false;
91+
} catch {
92+
this.close();
93+
return true;
94+
}
95+
},
96+
{ min: this.heartbeatInterval, max: this.heartbeatInterval },
97+
);
98+
});
99+
73100
clearWriteQueue = () => {
74101
if (this.writeQueue) {
75102
this.write("");
@@ -147,6 +174,8 @@ export class ConatTerminal extends EventEmitter {
147174
}
148175
};
149176

177+
isClosed = () => this.state == "closed";
178+
150179
close = () => {
151180
webapp_client.conat_client.removeListener(
152181
"connected",
@@ -239,6 +268,7 @@ export class ConatTerminal extends EventEmitter {
239268
init = reuseInFlight(async () => {
240269
await Promise.all([this.start(), this.getStream()]);
241270
await this.setReady();
271+
this.heartbeat();
242272
});
243273

244274
private handleStreamData = (data) => {

src/packages/util/async-utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export async function until(
4545
}: RetryOptions = {},
4646
) {
4747
const end = timeout ? Date.now() + timeout : undefined;
48-
let d = start;
48+
let d = Math.max(min, start);
4949
while (end === undefined || Date.now() < end) {
5050
const x = await f();
5151
if (x) {

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=1755363036;
2+
exports.version=1755523373;

0 commit comments

Comments
 (0)