diff --git a/src/index.ts b/src/index.ts index 20a6914..7a1f516 100644 --- a/src/index.ts +++ b/src/index.ts @@ -52,6 +52,10 @@ let registeredGroups: Record = {}; let lastAgentTimestamp: Record = {}; // LID to phone number mapping (WhatsApp now sends LID JIDs for self-chats) let lidToPhoneMap: Record = {}; +// Guards to prevent duplicate loops on WhatsApp reconnect +let messageLoopRunning = false; +let ipcWatcherRunning = false; +let groupSyncTimerStarted = false; /** * Translate a JID from LID format to phone format if we have a mapping. @@ -292,6 +296,12 @@ async function sendMessage(jid: string, text: string): Promise { } function startIpcWatcher(): void { + if (ipcWatcherRunning) { + logger.debug('IPC watcher already running, skipping duplicate start'); + return; + } + ipcWatcherRunning = true; + const ipcBaseDir = path.join(DATA_DIR, 'ipc'); fs.mkdirSync(ipcBaseDir, { recursive: true }); @@ -697,12 +707,15 @@ async function connectWhatsApp(): Promise { syncGroupMetadata().catch((err) => logger.error({ err }, 'Initial group sync failed'), ); - // Set up daily sync timer - setInterval(() => { - syncGroupMetadata().catch((err) => - logger.error({ err }, 'Periodic group sync failed'), - ); - }, GROUP_SYNC_INTERVAL_MS); + // Set up daily sync timer (only once) + if (!groupSyncTimerStarted) { + groupSyncTimerStarted = true; + setInterval(() => { + syncGroupMetadata().catch((err) => + logger.error({ err }, 'Periodic group sync failed'), + ); + }, GROUP_SYNC_INTERVAL_MS); + } startSchedulerLoop({ sendMessage, registeredGroups: () => registeredGroups, @@ -745,6 +758,11 @@ async function connectWhatsApp(): Promise { } async function startMessageLoop(): Promise { + if (messageLoopRunning) { + logger.debug('Message loop already running, skipping duplicate start'); + return; + } + messageLoopRunning = true; logger.info(`NanoClaw running (trigger: @${ASSISTANT_NAME})`); while (true) { diff --git a/src/task-scheduler.ts b/src/task-scheduler.ts index 430a290..bb3857b 100644 --- a/src/task-scheduler.ts +++ b/src/task-scheduler.ts @@ -141,7 +141,14 @@ async function runTask( updateTaskAfterRun(task.id, nextRun, resultSummary); } +let schedulerRunning = false; + export function startSchedulerLoop(deps: SchedulerDependencies): void { + if (schedulerRunning) { + logger.debug('Scheduler loop already running, skipping duplicate start'); + return; + } + schedulerRunning = true; logger.info('Scheduler loop started'); const loop = async () => {