dockge/backend/agent-manager.ts
Louis Lam 37f261480a WIP
2023-12-21 20:47:47 +08:00

160 lines
4.9 KiB
TypeScript

import { DockgeSocket } from "./util-server";
import { io, Socket as SocketClient } from "socket.io-client";
import { log } from "./log";
import { Agent } from "./models/agent";
import { LooseObject } from "../common/util-common";
/**
* Dockge Instance Manager
*/
export class AgentManager {
protected socket : DockgeSocket;
protected instanceSocketList : Record<string, SocketClient> = {};
constructor(socket: DockgeSocket) {
this.socket = socket;
}
connect(url : string, username : string, password : string) {
let obj = new URL(url);
let endpoint = obj.host;
this.socket.emit("agentStatus", {
endpoint: endpoint,
status: "connecting",
});
if (!endpoint) {
log.error("agent-manager", "Invalid endpoint: " + endpoint + " URL: " + url);
return;
}
if (this.instanceSocketList[endpoint]) {
log.debug("agent-manager", "Already connected to the socket server: " + endpoint);
return;
}
log.info("agent-manager", "Connecting to the socket server: " + endpoint);
let client = io(url, {
extraHeaders: {
endpoint,
}
});
client.on("connect", () => {
log.info("agent-manager", "Connected to the socket server: " + endpoint);
client.emit("login", {
username: username,
password: password,
}, (res) => {
if (res.ok) {
log.info("agent-manager", "Logged in to the socket server: " + endpoint);
this.socket.emit("agentStatus", {
endpoint: endpoint,
status: "online",
});
} else {
log.error("agent-manager", "Failed to login to the socket server: " + endpoint);
this.socket.emit("agentStatus", {
endpoint: endpoint,
status: "offline",
});
}
});
});
client.on("error", (err) => {
log.error("agent-manager", "Error from the socket server: " + endpoint);
log.error("agent-manager", err);
this.socket.emit("agentStatus", {
endpoint: endpoint,
status: "offline",
});
});
client.on("disconnect", () => {
log.info("agent-manager", "Disconnected from the socket server: " + endpoint);
this.socket.emit("agentStatus", {
endpoint: endpoint,
status: "offline",
});
});
client.on("agent", (...args : unknown[]) => {
log.debug("agent-manager", "Forward event");
this.socket.emit("agent", ...args);
});
this.instanceSocketList[endpoint] = client;
}
disconnect(endpoint : string) {
let client = this.instanceSocketList[endpoint];
client?.disconnect();
}
async connectAll() {
if (this.socket.endpoint) {
log.info("agent-manager", "This connection is connected as an agent, skip connectAll()");
return;
}
let list : Record<string, Agent> = await Agent.getAgentList();
if (Object.keys(list).length !== 0) {
log.info("agent-manager", "Connecting to all instance socket server(s)...");
}
for (let endpoint in list) {
let agent = list[endpoint];
this.connect(agent.url, agent.username, agent.password);
}
}
disconnectAll() {
for (let endpoint in this.instanceSocketList) {
this.disconnect(endpoint);
}
}
emitToEndpoint(endpoint: string, eventName: string, ...args : unknown[]) {
log.debug("agent-manager", "Emitting event to endpoint: " + endpoint);
let client = this.instanceSocketList[endpoint];
if (!client) {
log.error("agent-manager", "Socket client not found for endpoint: " + endpoint);
throw new Error("Socket client not found for endpoint: " + endpoint);
}
client?.emit("agent", endpoint, eventName, ...args);
}
emitToAllEndpoints(eventName: string, ...args : unknown[]) {
log.debug("agent-manager", "Emitting event to all endpoints");
for (let endpoint in this.instanceSocketList) {
this.emitToEndpoint(endpoint, eventName, ...args);
}
}
async sendAgentList() {
let list = await Agent.getAgentList();
let result : Record<string, LooseObject> = {};
// Myself
result[""] = {
url: "",
username: "",
endpoint: "",
};
for (let endpoint in list) {
let agent = list[endpoint];
result[endpoint] = agent.toJSON();
}
this.socket.emit("agentList", {
ok: true,
agentList: result,
});
}
}