Skip to content

Commit

Permalink
added support for multiple stacks in repos
Browse files Browse the repository at this point in the history
  • Loading branch information
Felioh committed Nov 17, 2024
1 parent b946b11 commit 26bd199
Show file tree
Hide file tree
Showing 7 changed files with 504 additions and 172 deletions.
51 changes: 51 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Dev with Debugger",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"port": 9229,
"env": {
"NODE_ENV": "development"
},
"console": "integratedTerminal",
"sourceMaps": true,
"smartStep": true
},
{
"name": "Launch Backend",
"type": "node",
"request": "launch",
"runtimeExecutable": "ts-node",
"args": ["${workspaceFolder}/backend/dockge-server.ts"],
"preLaunchTask": "tsc: build - tsconfig.json",
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"env": {
"NODE_ENV": "development"
},
"sourceMaps": true,
"smartStep": true
},
{
"name": "Launch Frontend",
"type": "chrome",
"request": "launch",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}/frontend",
"preLaunchTask": "npm: start"
},
{
"name": "Attach to Backend",
"type": "node",
"request": "attach",
"port": 9229,
"restart": true,
"protocol": "inspector",
"sourceMaps": true,
"smartStep": true
}
]
}
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"editor.formatOnSave": false,
"editor.formatOnType": false,
"editor.formatOnPaste": false
}
189 changes: 123 additions & 66 deletions backend/agent-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,20 @@ import dayjs, { Dayjs } from "dayjs";
* One AgentManager per Socket connection
*/
export class AgentManager {

protected socket : DockgeSocket;
protected agentSocketList : Record<string, SocketClient> = {};
protected agentLoggedInList : Record<string, boolean> = {};
protected _firstConnectTime : Dayjs = dayjs();
protected socket: DockgeSocket;
protected agentSocketList: Record<string, SocketClient> = {};
protected agentLoggedInList: Record<string, boolean> = {};
protected _firstConnectTime: Dayjs = dayjs();

constructor(socket: DockgeSocket) {
this.socket = socket;
}

get firstConnectTime() : Dayjs {
get firstConnectTime(): Dayjs {
return this._firstConnectTime;
}

test(url : string, username : string, password : string) : Promise<void> {
test(url: string, username: string, password: string): Promise<void> {
return new Promise((resolve, reject) => {
let obj = new URL(url);
let endpoint = obj.host;
Expand All @@ -43,26 +42,32 @@ export class AgentManager {
reconnection: false,
extraHeaders: {
endpoint,
}
},
});

client.on("connect", () => {
client.emit("login", {
username: username,
password: password,
}, (res : LooseObject) => {
if (res.ok) {
resolve();
} else {
reject(new Error(res.msg));
client.emit(
"login",
{
username: username,
password: password,
},
(res: LooseObject) => {
if (res.ok) {
resolve();
} else {
reject(new Error(res.msg));
}
client.disconnect();
}
client.disconnect();
});
);
});

client.on("connect_error", (err) => {
if (err.message === "xhr poll error") {
reject(new Error("Unable to connect to the Dockge instance"));
reject(
new Error("Unable to connect to the Dockge instance")
);
} else {
reject(err);
}
Expand All @@ -77,7 +82,7 @@ export class AgentManager {
* @param username
* @param password
*/
async add(url : string, username : string, password : string) : Promise<Agent> {
async add(url: string, username: string, password: string): Promise<Agent> {
let bean = R.dispense("agent") as Agent;
bean.url = url;
bean.username = username;
Expand All @@ -90,10 +95,8 @@ export class AgentManager {
*
* @param url
*/
async remove(url : string) {
let bean = await R.findOne("agent", " url = ? ", [
url,
]);
async remove(url: string) {
let bean = await R.findOne("agent", " url = ? ", [url]);

Check warning on line 99 in backend/agent-manager.ts

View workflow job for this annotation

GitHub Actions / ci (macos-latest, 22)

A space is required after '['

Check warning on line 99 in backend/agent-manager.ts

View workflow job for this annotation

GitHub Actions / ci (macos-latest, 22)

A space is required before ']'

Check warning on line 99 in backend/agent-manager.ts

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 22)

A space is required after '['

Check warning on line 99 in backend/agent-manager.ts

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 22)

A space is required before ']'

Check warning on line 99 in backend/agent-manager.ts

View workflow job for this annotation

GitHub Actions / ci (windows-latest, 22)

A space is required after '['

Check warning on line 99 in backend/agent-manager.ts

View workflow job for this annotation

GitHub Actions / ci (windows-latest, 22)

A space is required before ']'

Check warning on line 99 in backend/agent-manager.ts

View workflow job for this annotation

GitHub Actions / ci (ARM64, 22)

A space is required after '['

Check warning on line 99 in backend/agent-manager.ts

View workflow job for this annotation

GitHub Actions / ci (ARM64, 22)

A space is required before ']'

Check warning on line 99 in backend/agent-manager.ts

View workflow job for this annotation

GitHub Actions / ci (ARM, 22)

A space is required after '['

Check warning on line 99 in backend/agent-manager.ts

View workflow job for this annotation

GitHub Actions / ci (ARM, 22)

A space is required before ']'

if (bean) {
await R.trash(bean);
Expand All @@ -106,7 +109,7 @@ export class AgentManager {
}
}

connect(url : string, username : string, password : string) {
connect(url: string, username: string, password: string) {
let obj = new URL(url);
let endpoint = obj.host;

Expand All @@ -116,64 +119,92 @@ export class AgentManager {
});

if (!endpoint) {
log.error("agent-manager", "Invalid endpoint: " + endpoint + " URL: " + url);
log.error(
"agent-manager",
"Invalid endpoint: " + endpoint + " URL: " + url
);
return;
}

if (this.agentSocketList[endpoint]) {
log.debug("agent-manager", "Already connected to the socket server: " + endpoint);
log.debug(
"agent-manager",
"Already connected to the socket server: " + endpoint
);
return;
}

log.info("agent-manager", "Connecting to the socket server: " + endpoint);
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 : LooseObject) => {
if (res.ok) {
log.info("agent-manager", "Logged in to the socket server: " + endpoint);
this.agentLoggedInList[endpoint] = true;
this.socket.emit("agentStatus", {
endpoint: endpoint,
status: "online",
});
} else {
log.error("agent-manager", "Failed to login to the socket server: " + endpoint);
this.agentLoggedInList[endpoint] = false;
this.socket.emit("agentStatus", {
endpoint: endpoint,
status: "offline",
});
log.info(
"agent-manager",
"Connected to the socket server: " + endpoint
);

client.emit(
"login",
{
username: username,
password: password,
},
(res: LooseObject) => {
if (res.ok) {
log.info(
"agent-manager",
"Logged in to the socket server: " + endpoint
);
this.agentLoggedInList[endpoint] = true;
this.socket.emit("agentStatus", {
endpoint: endpoint,
status: "online",
});
} else {
log.error(
"agent-manager",
"Failed to login to the socket server: " + endpoint
);
this.agentLoggedInList[endpoint] = false;
this.socket.emit("agentStatus", {
endpoint: endpoint,
status: "offline",
});
}
}
});
);
});

client.on("connect_error", (err) => {
log.error("agent-manager", "Error from the socket server: " + endpoint);
log.error(
"agent-manager",
"Error from the socket server: " + endpoint
);
this.socket.emit("agentStatus", {
endpoint: endpoint,
status: "offline",
});
});

client.on("disconnect", () => {
log.info("agent-manager", "Disconnected from the socket server: " + endpoint);
log.info(
"agent-manager",
"Disconnected from the socket server: " + endpoint
);
this.socket.emit("agentStatus", {
endpoint: endpoint,
status: "offline",
});
});

client.on("agent", (...args : unknown[]) => {
client.on("agent", (...args: unknown[]) => {
this.socket.emit("agent", ...args);
});

Expand All @@ -194,7 +225,7 @@ export class AgentManager {
this.agentSocketList[endpoint] = client;
}

disconnect(endpoint : string) {
disconnect(endpoint: string) {
let client = this.agentSocketList[endpoint];
client?.disconnect();
}
Expand All @@ -203,14 +234,20 @@ export class AgentManager {
this._firstConnectTime = dayjs();

if (this.socket.endpoint) {
log.info("agent-manager", "This connection is connected as an agent, skip connectAll()");
log.info(
"agent-manager",
"This connection is connected as an agent, skip connectAll()"
);
return;
}

let list : Record<string, Agent> = await Agent.getAgentList();
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)...");
log.info(
"agent-manager",
"Connecting to all instance socket server(s)..."
);
}

for (let endpoint in list) {
Expand All @@ -225,13 +262,22 @@ export class AgentManager {
}
}

async emitToEndpoint(endpoint: string, eventName: string, ...args : unknown[]) {
async emitToEndpoint(
endpoint: string,
eventName: string,
...args: unknown[]
) {
log.debug("agent-manager", "Emitting event to endpoint: " + endpoint);
let client = this.agentSocketList[endpoint];

if (!client) {
log.error("agent-manager", "Socket client not found for endpoint: " + endpoint);
throw new Error("Socket client not found for endpoint: " + endpoint);
log.error(
"agent-manager",
"Socket client not found for endpoint: " + endpoint
);
throw new Error(
"Socket client not found for endpoint: " + endpoint
);
}

if (!client.connected || !this.agentLoggedInList[endpoint]) {
Expand All @@ -242,25 +288,36 @@ export class AgentManager {
let ok = false;
while (diff < 10) {
if (client.connected && this.agentLoggedInList[endpoint]) {
log.debug("agent-manager", `${endpoint}: Connected & Logged in`);
log.debug(
"agent-manager",
`${endpoint}: Connected & Logged in`
);
ok = true;
break;
}
log.debug("agent-manager", endpoint + ": not ready yet, retrying in 1 second...");
log.debug(
"agent-manager",
endpoint + ": not ready yet, retrying in 1 second..."
);
await sleep(1000);
diff = dayjs().diff(this.firstConnectTime, "second");
}

if (!ok) {
log.error("agent-manager", `${endpoint}: Socket client not connected`);
throw new Error("Socket client not connected for endpoint: " + endpoint);
log.error(
"agent-manager",
`${endpoint}: Socket client not connected`
);
throw new Error(
"Socket client not connected for endpoint: " + endpoint
);
}
}

client.emit("agent", endpoint, eventName, ...args);
}

emitToAllEndpoints(eventName: string, ...args : unknown[]) {
emitToAllEndpoints(eventName: string, ...args: unknown[]) {
log.debug("agent-manager", "Emitting event to all endpoints");
for (let endpoint in this.agentSocketList) {
this.emitToEndpoint(endpoint, eventName, ...args).catch((e) => {
Expand All @@ -271,7 +328,7 @@ export class AgentManager {

async sendAgentList() {
let list = await Agent.getAgentList();
let result : Record<string, LooseObject> = {};
let result: Record<string, LooseObject> = {};

// Myself
result[""] = {
Expand Down
Loading

0 comments on commit 26bd199

Please sign in to comment.