From 69b33720b3cad10dacf85f6aed92e3fcba20c869 Mon Sep 17 00:00:00 2001 From: Joerg Date: Thu, 22 Jan 2026 13:17:16 +0100 Subject: [PATCH] fix: prevent infinite retry loop for auto-sync users without credentials When auto-sync is enabled but credentials (LoTW/DCL) are removed, the scheduler would continuously try to sync every minute, logging the same warning forever. Now: - Split pending users into those with and without credentials - For users without credentials, update nextSyncAt to retry in 24 hours - Log a warning with affected user IDs - Only return users with valid credentials for job processing This prevents log spam and unnecessary database queries while still periodically checking if credentials have been restored. Co-Authored-By: Claude --- src/backend/services/auto-sync.service.js | 35 ++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/backend/services/auto-sync.service.js b/src/backend/services/auto-sync.service.js index f703b71..748aa04 100644 --- a/src/backend/services/auto-sync.service.js +++ b/src/backend/services/auto-sync.service.js @@ -237,6 +237,7 @@ export async function getPendingSyncUsers(service) { const enabledField = service === 'lotw' ? autoSyncSettings.lotwEnabled : autoSyncSettings.dclEnabled; const nextSyncField = service === 'lotw' ? autoSyncSettings.lotwNextSyncAt : autoSyncSettings.dclNextSyncAt; const credentialField = service === 'lotw' ? users.lotwUsername : users.dclApiKey; + const intervalField = service === 'lotw' ? autoSyncSettings.lotwIntervalHours : autoSyncSettings.dclIntervalHours; const now = new Date(); @@ -261,13 +262,45 @@ export async function getPendingSyncUsers(service) { ) ); - // Filter out users without credentials + // Split into users with and without credentials const withCredentials = results.filter(r => r.hasCredentials); + const withoutCredentials = results.filter(r => !r.hasCredentials); + + // For users without credentials, update their next sync time to retry in 24 hours + // This prevents them from being continuously retried every minute + if (withoutCredentials.length > 0) { + const retryDate = new Date(); + retryDate.setHours(retryDate.getHours() + 24); + + for (const user of withoutCredentials) { + const updateData = { + updatedAt: new Date(), + }; + + if (service === 'lotw') { + updateData.lotwNextSyncAt = retryDate; + } else { + updateData.dclNextSyncAt = retryDate; + } + + await db + .update(autoSyncSettings) + .set(updateData) + .where(eq(autoSyncSettings.userId, user.userId)); + } + + logger.warn('Skipped auto-sync for users without credentials, will retry in 24 hours', { + service, + count: withoutCredentials.length, + userIds: withoutCredentials.map(u => u.userId), + }); + } logger.debug('Found pending sync users', { service, total: results.length, withCredentials: withCredentials.length, + withoutCredentials: withoutCredentials.length, }); return withCredentials;