Skip to content

Commit

Permalink
Close terminal if there is no clients (#60)
Browse files Browse the repository at this point in the history
* Close terminal if there is no clients connecting

* Only enable

* Join the terminal only if it is managed by Dockge

* Done
  • Loading branch information
louislam authored Nov 24, 2023
1 parent 45ab36d commit 766e751
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 9 deletions.
12 changes: 9 additions & 3 deletions backend/dockge-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { Cron } from "croner";
import gracefulShutdown from "http-graceful-shutdown";
import User from "./models/user";
import childProcess from "child_process";
import { Terminal } from "./terminal";

export class DockgeServer {
app : Express;
Expand Down Expand Up @@ -230,6 +231,11 @@ export class DockgeServer {

});

if (isDev) {
setInterval(() => {
log.debug("terminal", "Terminal count: " + Terminal.getTerminalCount());
}, 5000);
}
}

async afterLogin(socket : DockgeSocket, user : User) {
Expand Down Expand Up @@ -292,11 +298,11 @@ export class DockgeServer {
log.info("server", `Listening on ${this.config.port}`);
}

// Run every 5 seconds
Cron("*/2 * * * * *", {
// Run every 10 seconds
Cron("*/10 * * * * *", {
protect: true, // Enabled over-run protection.
}, () => {
log.debug("server", "Cron job running");
//log.debug("server", "Cron job running");
this.sendStackList(true);
});

Expand Down
4 changes: 3 additions & 1 deletion backend/socket-handlers/docker-socket-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ export class DockerSocketHandler extends SocketHandler {

const stack = Stack.getStack(server, stackName);

stack.joinCombinedTerminal(socket);
if (stack.isManagedByDockge) {
stack.joinCombinedTerminal(socket);
}

callback({
ok: true,
Expand Down
21 changes: 19 additions & 2 deletions backend/socket-handlers/terminal-socket-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,26 @@ export class TerminalSocketHandler extends SocketHandler {
}
});

// Close Terminal
socket.on("terminalClose", async (terminalName : unknown, callback : unknown) => {
// Leave Combined Terminal
socket.on("leaveCombinedTerminal", async (stackName : unknown, callback) => {
try {
checkLogin(socket);

log.debug("leaveCombinedTerminal", "Stack name: " + stackName);

if (typeof(stackName) !== "string") {
throw new ValidationError("Stack name must be a string.");
}

const stack = Stack.getStack(server, stackName);
await stack.leaveCombinedTerminal(socket);

callback({
ok: true,
});
} catch (e) {
callbackError(e, callback);
}
});

// TODO: Resize Terminal
Expand Down
11 changes: 10 additions & 1 deletion backend/stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ export class Stack {
}
}
} else {
log.debug("getStack", "Skip FS operations");
//log.debug("getStack", "Skip FS operations");
}

let stack : Stack;
Expand Down Expand Up @@ -374,12 +374,21 @@ export class Stack {
async joinCombinedTerminal(socket: DockgeSocket) {
const terminalName = getCombinedTerminalName(this.name);
const terminal = Terminal.getOrCreateTerminal(this.server, terminalName, "docker", [ "compose", "logs", "-f", "--tail", "100" ], this.path);
terminal.enableKeepAlive = true;
terminal.rows = COMBINED_TERMINAL_ROWS;
terminal.cols = COMBINED_TERMINAL_COLS;
terminal.join(socket);
terminal.start();
}

async leaveCombinedTerminal(socket: DockgeSocket) {
const terminalName = getCombinedTerminalName(this.name);
const terminal = Terminal.getTerminal(terminalName);
if (terminal) {
terminal.leave(socket);
}
}

async joinContainerTerminal(socket: DockgeSocket, serviceName: string, shell : string = "sh", index: number = 0) {
const terminalName = getContainerExecTerminalName(this.name, serviceName, index);
let terminal = Terminal.getTerminal(terminalName);
Expand Down
34 changes: 33 additions & 1 deletion backend/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ export class Terminal {
protected _rows : number = TERMINAL_ROWS;
protected _cols : number = TERMINAL_COLS;

public enableKeepAlive : boolean = false;
protected keepAliveInterval? : NodeJS.Timeout;

constructor(server : DockgeServer, name : string, file : string, args : string | string[], cwd : string) {
this.server = server;
this._name = name;
Expand Down Expand Up @@ -80,6 +83,25 @@ export class Terminal {
return;
}

if (this.enableKeepAlive) {
log.debug("Terminal", "Keep alive enabled for terminal " + this.name);

// Close if there is no clients
this.keepAliveInterval = setInterval(() => {
const clients = this.server.io.sockets.adapter.rooms.get(this.name);
const numClients = clients ? clients.size : 0;

if (numClients === 0) {
log.debug("Terminal", "Terminal " + this.name + " has no client, closing...");
this.close();
} else {
log.debug("Terminal", "Terminal " + this.name + " has " + numClients + " client(s)");
}
}, 60 * 1000);
} else {
log.debug("Terminal", "Keep alive disabled for terminal " + this.name);
}

try {
this._ptyProcess = pty.spawn(this.file, this.args, {
name: this.name,
Expand All @@ -100,6 +122,8 @@ export class Terminal {
this._ptyProcess.onExit(this.exit);
} catch (error) {
if (error instanceof Error) {
clearInterval(this.keepAliveInterval);

log.error("Terminal", "Failed to start terminal: " + error.message);
const exitCode = Number(error.message.split(" ").pop());
this.exit({
Expand All @@ -122,6 +146,8 @@ export class Terminal {
Terminal.terminalMap.delete(this.name);
log.debug("Terminal", "Terminal " + this.name + " exited with code " + res.exitCode);

clearInterval(this.keepAliveInterval);

if (this.callback) {
this.callback(res.exitCode);
}
Expand Down Expand Up @@ -158,7 +184,9 @@ export class Terminal {
}

close() {
this._ptyProcess?.kill();
clearInterval(this.keepAliveInterval);
// Send Ctrl+C to the terminal
this.ptyProcess?.write("\x03");
}

/**
Expand Down Expand Up @@ -193,6 +221,10 @@ export class Terminal {
terminal.start();
});
}

public static getTerminalCount() {
return Terminal.terminalMap.size;
}
}

/**
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/pages/Compose.vue
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,12 @@ export default {
},
deep: true,
},
$route(to, from) {
// Leave Combined Terminal
console.debug("leaveCombinedTerminal", from.params.stackName);
this.$root.getSocket().emit("leaveCombinedTerminal", this.stack.name, () => {});
}
},
mounted() {
if (this.isAdd) {
Expand Down Expand Up @@ -361,7 +367,7 @@ export default {
clearTimeout(serviceStatusTimeout);
serviceStatusTimeout = setTimeout(async () => {
this.requestServiceStatus();
}, 2000);
}, 5000);
},
requestServiceStatus() {
Expand Down

0 comments on commit 766e751

Please sign in to comment.