50 lines
1.5 KiB
TypeScript
50 lines
1.5 KiB
TypeScript
|
|
import { db } from "@tasks/database";
|
||
|
|
import IoRedis from "ioredis";
|
||
|
|
|
||
|
|
import { detectStalledConvoys } from "./db/convoy.js";
|
||
|
|
import { loadEnv } from "./env.js";
|
||
|
|
import { runOrchestratorTick } from "./tick.js";
|
||
|
|
|
||
|
|
async function main(): Promise<void> {
|
||
|
|
const env = loadEnv();
|
||
|
|
const redis = env.REDIS_URL ? new IoRedis(env.REDIS_URL) : null;
|
||
|
|
|
||
|
|
if (env.ORCHESTRATOR_DRY_RUN) {
|
||
|
|
console.info("[orchestrator] DRY-RUN mode — jobs will be logged, not enqueued");
|
||
|
|
} else if (!redis) {
|
||
|
|
console.warn("[orchestrator] REDIS_URL not set — running in DRY-RUN mode");
|
||
|
|
}
|
||
|
|
|
||
|
|
console.info(`[orchestrator] polling every ${env.ORCHESTRATOR_POLL_MS}ms`);
|
||
|
|
|
||
|
|
const loop = async () => {
|
||
|
|
try {
|
||
|
|
const results = await runOrchestratorTick(db, redis, {
|
||
|
|
...env,
|
||
|
|
ORCHESTRATOR_DRY_RUN: env.ORCHESTRATOR_DRY_RUN || !redis,
|
||
|
|
});
|
||
|
|
|
||
|
|
const stalled = await detectStalledConvoys(db, env.ORCHESTRATOR_STALL_MINUTES);
|
||
|
|
if (stalled.length > 0) {
|
||
|
|
console.warn(
|
||
|
|
`[orchestrator] stall detector: ${stalled.length} open agent_runs older than ${env.ORCHESTRATOR_STALL_MINUTES}m`,
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (results.length === 0) {
|
||
|
|
console.info("[orchestrator] no active convoys");
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error("[orchestrator] tick failed:", error);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
await loop();
|
||
|
|
setInterval(loop, env.ORCHESTRATOR_POLL_MS);
|
||
|
|
}
|
||
|
|
|
||
|
|
main().catch((error) => {
|
||
|
|
console.error("[orchestrator] fatal:", error);
|
||
|
|
process.exit(1);
|
||
|
|
});
|