fix: mark agent offline only if the session was removed properly
This commit is contained in:
parent
4e17daf6fe
commit
9bb5d2c916
5 changed files with 36 additions and 40 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import { logger } from "@zerobyte/core/node";
|
||||
import type { BackupRunPayload } from "@zerobyte/contracts/agent-protocol";
|
||||
import { config } from "../../core/config";
|
||||
import type { AgentBackupEventHandlers } from "./controller/server";
|
||||
import { createAgentManagerRuntime, type AgentBackupEventHandlers } from "./controller/server";
|
||||
import { spawnLocalAgentProcess, stopLocalAgentProcess } from "./local/process";
|
||||
import type { BackupExecutionProgress, BackupExecutionResult } from "./helpers/runtime-state";
|
||||
import { createAgentRuntimeState } from "./helpers/runtime-state";
|
||||
|
|
@ -155,7 +155,6 @@ export const startAgentController = async () => {
|
|||
runtime.agentManager = null;
|
||||
}
|
||||
|
||||
const { createAgentManagerRuntime } = await import("./controller/server");
|
||||
const nextAgentManager = createAgentManagerRuntime();
|
||||
nextAgentManager.setBackupEventHandlers(backupEventHandlers);
|
||||
|
||||
|
|
|
|||
|
|
@ -197,10 +197,11 @@ export function createAgentManagerRuntime() {
|
|||
});
|
||||
},
|
||||
close: (ws) => {
|
||||
removeSession(ws.data.agentId, ws.data.id);
|
||||
void agentsService.markAgentOffline(ws.data.agentId).catch((error) => {
|
||||
logger.error(`Failed to mark agent ${ws.data.agentId} as offline: ${toMessage(error)}`);
|
||||
});
|
||||
if (removeSession(ws.data.agentId, ws.data.id)) {
|
||||
void agentsService.markAgentOffline(ws.data.agentId).catch((error) => {
|
||||
logger.error(`Failed to mark agent ${ws.data.agentId} as offline: ${toMessage(error)}`);
|
||||
});
|
||||
}
|
||||
logger.info(`Agent "${ws.data.agentName}" (${ws.data.agentId}) disconnected`);
|
||||
},
|
||||
},
|
||||
|
|
@ -214,11 +215,9 @@ export function createAgentManagerRuntime() {
|
|||
catch: (error) => new StopAgentManagerServerError({ cause: error }),
|
||||
}),
|
||||
),
|
||||
Effect.catchAll((error) =>
|
||||
Effect.sync(() => {
|
||||
logger.error(`Failed to stop Agent Manager server: ${toMessage(error.cause)}`);
|
||||
}),
|
||||
),
|
||||
Effect.catchAll((error) => {
|
||||
return logger.effect.error(`Failed to stop Agent Manager server: ${toMessage(error.cause)}`);
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
@ -233,6 +232,7 @@ export function createAgentManagerRuntime() {
|
|||
await Effect.runPromise(Scope.close(scope, Exit.succeed(undefined)));
|
||||
};
|
||||
|
||||
// TODO: Move the effect boundary up
|
||||
const start = async () => {
|
||||
if (runtimeScope) {
|
||||
await stop();
|
||||
|
|
|
|||
|
|
@ -136,16 +136,13 @@ export const createControllerAgentSession = (
|
|||
yield* Effect.addFinalizer(() => closeSession());
|
||||
|
||||
const handleSendFailure = (reason: string) => {
|
||||
logger.error(
|
||||
`Closing session for agent ${socket.data.agentId} on ${socket.data.id} after an outbound websocket send failed: ${reason}`,
|
||||
);
|
||||
|
||||
socket.close();
|
||||
|
||||
void Effect.runPromise(closeSession()).catch((error) => {
|
||||
return Effect.gen(function* () {
|
||||
logger.error(
|
||||
`Failed to close session for agent ${socket.data.agentId} on ${socket.data.id}: ${toMessage(error)}`,
|
||||
`Closing session for agent ${socket.data.agentId} on ${socket.data.id} after an outbound websocket send failed: ${reason}`,
|
||||
);
|
||||
|
||||
yield* Effect.sync(() => socket.close());
|
||||
yield* closeSession();
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -154,17 +151,16 @@ export const createControllerAgentSession = (
|
|||
Effect.forever(
|
||||
Effect.gen(function* () {
|
||||
const message = yield* Queue.take(outboundQueue);
|
||||
yield* Effect.sync(() => {
|
||||
try {
|
||||
const sendResult = socket.send(message);
|
||||
if (sendResult === 0) {
|
||||
handleSendFailure("connection issue");
|
||||
}
|
||||
} catch (error) {
|
||||
handleSendFailure(toMessage(error));
|
||||
}
|
||||
|
||||
const sendResult = yield* Effect.try({
|
||||
try: () => socket.send(message),
|
||||
catch: (error) => toMessage(error),
|
||||
});
|
||||
}),
|
||||
|
||||
if (sendResult === 0) {
|
||||
yield* handleSendFailure("connection issue");
|
||||
}
|
||||
}).pipe(Effect.catchAll((reason) => handleSendFailure(reason))),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
@ -200,9 +196,7 @@ export const createControllerAgentSession = (
|
|||
at: readyAt,
|
||||
});
|
||||
|
||||
yield* Effect.sync(() => {
|
||||
logger.info(`Agent "${socket.data.agentName}" (${socket.data.agentId}) is ready`);
|
||||
});
|
||||
yield* logger.effect.info(`Agent "${socket.data.agentName}" (${socket.data.agentId}) is ready`);
|
||||
break;
|
||||
}
|
||||
case "backup.started": {
|
||||
|
|
@ -210,7 +204,7 @@ export const createControllerAgentSession = (
|
|||
scheduleId: message.payload.scheduleId,
|
||||
state: "active",
|
||||
});
|
||||
logger.info(
|
||||
yield* logger.effect.info(
|
||||
`Backup ${message.payload.jobId} started on agent ${socket.data.agentId} for schedule ${message.payload.scheduleId}`,
|
||||
);
|
||||
yield* handlers.onBackupStarted(message.payload);
|
||||
|
|
@ -258,16 +252,12 @@ export const createControllerAgentSession = (
|
|||
const parsed = parseAgentMessage(data);
|
||||
|
||||
if (parsed === null) {
|
||||
yield* Effect.sync(() => {
|
||||
logger.warn(`Invalid JSON from agent ${socket.data.agentId}`);
|
||||
});
|
||||
yield* logger.effect.warn(`Invalid JSON from agent ${socket.data.agentId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!parsed.success) {
|
||||
yield* Effect.sync(() => {
|
||||
logger.warn(`Invalid agent message from ${socket.data.agentId}: ${parsed.error.message}`);
|
||||
});
|
||||
yield* logger.effect.warn(`Invalid agent message from ${socket.data.agentId}: ${parsed.error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export const handleBackupRunCommand = (context: ControllerCommandContext, payloa
|
|||
return;
|
||||
}
|
||||
|
||||
logger.info(`Starting backup ${payload.jobId} for schedule ${payload.scheduleId}`);
|
||||
yield* logger.effect.info(`Starting backup ${payload.jobId} for schedule ${payload.scheduleId}`);
|
||||
const abortController = new AbortController();
|
||||
yield* context.setRunningJob(payload.jobId, { scheduleId: payload.scheduleId, abortController });
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { format } from "date-fns";
|
|||
import { createConsola, type ConsolaReporter } from "consola";
|
||||
import { formatWithOptions } from "node:util";
|
||||
import { sanitizeSensitiveData } from "../utils/sanitize";
|
||||
import { Effect } from "effect";
|
||||
|
||||
type LogLevel = "debug" | "info" | "warn" | "error";
|
||||
|
||||
|
|
@ -102,4 +103,10 @@ export const logger = {
|
|||
info: (...messages: unknown[]) => consola.info(formatMessages(messages).join(" ")),
|
||||
warn: (...messages: unknown[]) => consola.warn(formatMessages(messages).join(" ")),
|
||||
error: (...messages: unknown[]) => consola.error(formatMessages(messages).join(" ")),
|
||||
effect: {
|
||||
debug: (...messages: unknown[]) => Effect.sync(() => consola.debug(formatMessages(messages).join(" "))),
|
||||
info: (...messages: unknown[]) => Effect.sync(() => consola.info(formatMessages(messages).join(" "))),
|
||||
warn: (...messages: unknown[]) => Effect.sync(() => consola.warn(formatMessages(messages).join(" "))),
|
||||
error: (...messages: unknown[]) => Effect.sync(() => consola.error(formatMessages(messages).join(" "))),
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue