From 5cceb959a8369f28932bb108e6da47b49cc20192 Mon Sep 17 00:00:00 2001 From: larchanka Date: Wed, 1 Apr 2026 09:23:26 +0200 Subject: [PATCH] fix(cron): improve cron job stability and visibility by adding immediate Telegram feedback and robust logging --- src/core/orchestrator.ts | 24 +++++++++++------- src/services/cron-manager.ts | 48 ++++++++++++++++++------------------ 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/src/core/orchestrator.ts b/src/core/orchestrator.ts index bbc97d3..a042b6b 100644 --- a/src/core/orchestrator.ts +++ b/src/core/orchestrator.ts @@ -191,22 +191,25 @@ export class Orchestrator { return; } // Handle cron AI query events from cron-manager - if (fromProcess === "cron-manager" && envelope.type === "event.cron.ai_query") { - this.handleCronAIQueryEvent(envelope); - return; - } + if (fromProcess === "cron-manager") { + if (envelope.type === "event.cron.ai_query") { + this.handleCronAIQueryEvent(envelope); + } else if (envelope.type === "event.cron.completed") { + this.handleCronReminderEvent(envelope); + } - // Handle cron reminder events from cron-manager - if (fromProcess === "cron-manager" && envelope.type === "event.cron.completed") { - this.handleCronReminderEvent(envelope); - // Also forward to logger as before + // Always forward cron events to logger for audit trail const logger = this.children.get("logger"); if (logger?.stdin.writable) { logger.stdin.write(trimmed + "\n"); ConsoleLogger.ipc("core", "→", envelope); this.broadcastIpcLog("→", "core", "logger", envelope); } - return; + + // If it was one of our handled events, we're done + if (envelope.type === "event.cron.ai_query" || envelope.type === "event.cron.completed") { + return; + } } if (to === "core") { @@ -999,6 +1002,9 @@ export class Orchestrator { ConsoleLogger.info("core", `Triggering autonomous AI task: "${query}" for chatId ${chatIdNum} (taskId: ${taskId})`); + // Immediate feedback so user knows the cron triggered + this.sendToTelegram(chatIdNum, `🤖 Autonomous task triggered: "${query}"\n\nStarting planning...`, true, "HTML"); + // Route to task queue (priority 0 for synthetic) this.enqueueTask({ chatId: chatIdNum, diff --git a/src/services/cron-manager.ts b/src/services/cron-manager.ts index 11f0591..98e6272 100644 --- a/src/services/cron-manager.ts +++ b/src/services/cron-manager.ts @@ -72,27 +72,15 @@ export class CronManager extends BaseProcess { private runJob(row: ScheduleRow): void { const now = Date.now(); - this.emitEvent("event.cron.started", { scheduleId: row.id, taskType: row.task_type, timestamp: now }); + this.emitEvent("event.cron.started", { + scheduleId: row.id, + taskType: row.task_type, + timestamp: now, + }); + try { const payload = row.payload ? JSON.parse(row.payload) : {}; - - // AI Query task type - if (row.task_type === "ai_query") { - const query = payload.reminderMessage || payload.query || ""; - const chatId = payload.chatId; - const userId = payload.userId; - - this.emitEvent("event.cron.ai_query", { - scheduleId: row.id, - taskType: row.task_type, - query, - chatId, - userId, - timestamp: Date.now() - }); - return; - } - + // Default: Reminder or generic task payload const reminderPayload: Record = { scheduleId: row.id, @@ -101,13 +89,25 @@ export class CronManager extends BaseProcess { timestamp: Date.now(), }; - // If this is a reminder task, extract structured fields - if (row.task_type === "reminder" || payload.chatId || payload.reminderMessage) { - reminderPayload.chatId = payload.chatId; - reminderPayload.reminderMessage = payload.reminderMessage; - reminderPayload.userId = payload.userId; + // Extract common fields for easier routing in Orchestrator if present + const q = payload.reminderMessage || payload.query; + if (q) reminderPayload.reminderMessage = q; + if (payload.chatId !== undefined) reminderPayload.chatId = payload.chatId; + if (payload.userId !== undefined) reminderPayload.userId = payload.userId; + + // Emit specific event types for legacy/orchestrator compatibility + if (row.task_type === "ai_query") { + this.emitEvent("event.cron.ai_query", { + scheduleId: row.id, + taskType: row.task_type, + query: payload.reminderMessage || payload.query || "", + chatId: payload.chatId, + userId: payload.userId, + timestamp: Date.now(), + }); } + // Always emit completed event for tracking and logging this.emitEvent("event.cron.completed", reminderPayload); } catch (err) { const message = err instanceof Error ? err.message : String(err);