Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3a9b032

Browse filesBrowse files
authored
Add heartbeat file (coder#1115)
Fixes coder#1050.
1 parent f73e922 commit 3a9b032
Copy full SHA for 3a9b032

1 file changed

+49Lines changed: 49 additions & 0 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/node/server.ts‎

Copy file name to clipboardExpand all lines: src/node/server.ts
+49Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,9 @@ export class MainServer extends Server {
474474
private readonly proxyTimeout = 5000;
475475

476476
private settings: Settings = {};
477+
private heartbeatTimer?: NodeJS.Timeout;
478+
private heartbeatInterval = 60000;
479+
private lastHeartbeat = 0;
477480

478481
public constructor(options: ServerOptions, args: ParsedArgs) {
479482
super(options);
@@ -491,6 +494,7 @@ export class MainServer extends Server {
491494
}
492495

493496
protected async handleWebSocket(socket: net.Socket, parsedUrl: url.UrlWithParsedQuery): Promise<void> {
497+
this.heartbeat();
494498
if (!parsedUrl.query.reconnectionToken) {
495499
throw new Error("Reconnection token is missing from query parameters");
496500
}
@@ -514,6 +518,7 @@ export class MainServer extends Server {
514518
parsedUrl: url.UrlWithParsedQuery,
515519
request: http.IncomingMessage,
516520
): Promise<Response> {
521+
this.heartbeat();
517522
switch (base) {
518523
case "/": return this.getRoot(request, parsedUrl);
519524
case "/resource":
@@ -876,4 +881,48 @@ export class MainServer extends Server {
876881
(this.services.get(ILogService) as ILogService).warn(error.message);
877882
}
878883
}
884+
885+
/**
886+
* Return the file path for the heartbeat file.
887+
*/
888+
private get heartbeatPath(): string {
889+
const environment = this.services.get(IEnvironmentService) as IEnvironmentService;
890+
return path.join(environment.userDataPath, "heartbeat");
891+
}
892+
893+
/**
894+
* Return all online connections regardless of type.
895+
*/
896+
private get onlineConnections(): Connection[] {
897+
const online = <Connection[]>[];
898+
this.connections.forEach((connections) => {
899+
connections.forEach((connection) => {
900+
if (typeof connection.offline === "undefined") {
901+
online.push(connection);
902+
}
903+
});
904+
});
905+
return online;
906+
}
907+
908+
/**
909+
* Write to the heartbeat file if we haven't already done so within the
910+
* timeout and start or reset a timer that keeps running as long as there are
911+
* active connections. Failures are logged as warnings.
912+
*/
913+
private heartbeat(): void {
914+
const now = Date.now();
915+
if (now - this.lastHeartbeat >= this.heartbeatInterval) {
916+
util.promisify(fs.writeFile)(this.heartbeatPath, "").catch((error) => {
917+
(this.services.get(ILogService) as ILogService).warn(error.message);
918+
});
919+
this.lastHeartbeat = now;
920+
clearTimeout(this.heartbeatTimer!); // We can clear undefined so ! is fine.
921+
this.heartbeatTimer = setTimeout(() => {
922+
if (this.onlineConnections.length > 0) {
923+
this.heartbeat();
924+
}
925+
}, this.heartbeatInterval);
926+
}
927+
}
879928
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.