From 510fbfc3e08f79a43206eef13b691a1d16b92684 Mon Sep 17 00:00:00 2001 From: alma Date: Thu, 15 Jan 2026 17:27:43 +0100 Subject: [PATCH] Agenda refactor --- app/agenda/page.tsx | 182 ++++++++++++++++++++++++-------------------- 1 file changed, 100 insertions(+), 82 deletions(-) diff --git a/app/agenda/page.tsx b/app/agenda/page.tsx index 8a1bee1..ac6f433 100644 --- a/app/agenda/page.tsx +++ b/app/agenda/page.tsx @@ -320,8 +320,12 @@ export default async function CalendarPage() { } // Clean up duplicate calendars for the same mailCredentialId - // Keep only the most recent one with syncEnabled=true, delete others - const allSyncs = await prisma.calendarSync.findMany({ + // NOTE: This is mainly for cleaning up OLD duplicates created before we fixed the cascade deletion + // New duplicates should not occur since we now delete calendars when mail accounts are deleted + // This cleanup is conservative: only processes if there are multiple ENABLED syncs for the same account + + // Only run cleanup if there are actually multiple syncs to check (performance optimization) + const syncCountCheck = await prisma.calendarSync.count({ where: { calendar: { userId: session?.user?.id || '' @@ -329,97 +333,111 @@ export default async function CalendarPage() { mailCredentialId: { in: Array.from(allMailCredentialIds) } - }, - include: { - calendar: true, - mailCredential: true - }, - orderBy: { - createdAt: 'desc' } }); - // Group by mailCredentialId and provider - const syncsByAccount = new Map(); - for (const sync of allSyncs) { - if (sync.mailCredentialId) { - const key = `${sync.mailCredentialId}-${sync.provider}`; - if (!syncsByAccount.has(key)) { - syncsByAccount.set(key, []); + // Only run full cleanup if there are multiple syncs (likely duplicates) + if (syncCountCheck > allMailCredentialIds.size) { + const allSyncs = await prisma.calendarSync.findMany({ + where: { + calendar: { + userId: session?.user?.id || '' + }, + mailCredentialId: { + in: Array.from(allMailCredentialIds) + } + }, + include: { + calendar: true, + mailCredential: true + }, + orderBy: { + createdAt: 'desc' + } + }); + + // Group by mailCredentialId and provider + const syncsByAccount = new Map(); + for (const sync of allSyncs) { + if (sync.mailCredentialId) { + const key = `${sync.mailCredentialId}-${sync.provider}`; + if (!syncsByAccount.has(key)) { + syncsByAccount.set(key, []); + } + syncsByAccount.get(key)!.push(sync); } - syncsByAccount.get(key)!.push(sync); } - } - // For each account, keep only the most recent enabled sync, disable or delete others - // IMPORTANT: Only process if there are actually multiple ENABLED syncs to avoid disabling active syncs - for (const [key, syncs] of syncsByAccount.entries()) { - if (syncs.length > 1) { - // Count how many are actually enabled - const enabledSyncs = syncs.filter(s => s.syncEnabled === true); - - // Only clean up if there are multiple ENABLED syncs - // If there's only one enabled sync, don't touch it even if there are disabled duplicates - if (enabledSyncs.length > 1) { - console.log(`[AGENDA] Found ${enabledSyncs.length} enabled syncs for ${key}, cleaning up duplicates`); + // For each account, keep only the most recent enabled sync, disable or delete others + // IMPORTANT: Only process if there are actually multiple ENABLED syncs to avoid disabling active syncs + for (const [key, syncs] of syncsByAccount.entries()) { + if (syncs.length > 1) { + // Count how many are actually enabled + const enabledSyncs = syncs.filter(s => s.syncEnabled === true); - // Sort by syncEnabled first (enabled first), then by lastSyncAt (most recently synced first), then by createdAt (newest first) - syncs.sort((a, b) => { - if (a.syncEnabled !== b.syncEnabled) { - return a.syncEnabled ? -1 : 1; - } - // Among enabled syncs, prefer the one with most recent sync - if (a.syncEnabled && b.syncEnabled) { - if (a.lastSyncAt && b.lastSyncAt) { - return new Date(b.lastSyncAt).getTime() - new Date(a.lastSyncAt).getTime(); + // Only clean up if there are multiple ENABLED syncs + // If there's only one enabled sync, don't touch it even if there are disabled duplicates + if (enabledSyncs.length > 1) { + console.log(`[AGENDA] Found ${enabledSyncs.length} enabled syncs for ${key}, cleaning up duplicates`); + + // Sort by syncEnabled first (enabled first), then by lastSyncAt (most recently synced first), then by createdAt (newest first) + syncs.sort((a, b) => { + if (a.syncEnabled !== b.syncEnabled) { + return a.syncEnabled ? -1 : 1; } - if (a.lastSyncAt && !b.lastSyncAt) return -1; - if (!a.lastSyncAt && b.lastSyncAt) return 1; - } - return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(); - }); - - const keepSync = syncs[0]; - const duplicates = syncs.slice(1); - - // Additional safety check: only disable duplicates if the sync to keep is actually valid - // (has events or has been synced recently) - const keepSyncEventCount = await prisma.event.count({ - where: { calendarId: keepSync.calendarId } - }); - const keepSyncIsValid = keepSyncEventCount > 0 || keepSync.lastSyncAt; - - if (!keepSyncIsValid) { - console.log(`[AGENDA] WARNING: Sync to keep ${keepSync.id} has no events and no sync history - skipping cleanup to avoid disabling valid syncs`); - continue; // Skip this group to avoid disabling a potentially valid sync - } - - console.log(`[AGENDA] Keeping sync ${keepSync.id} (calendar: ${keepSync.calendar.name}, events: ${keepSyncEventCount}), disabling ${duplicates.length} duplicates`); - - // Disable or delete duplicate syncs - for (const duplicate of duplicates) { - if (duplicate.syncEnabled) { - // Disable the duplicate sync - console.log(`[AGENDA] Disabling duplicate sync ${duplicate.id} (calendar: ${duplicate.calendar.name})`); - await prisma.calendarSync.update({ - where: { id: duplicate.id }, - data: { syncEnabled: false } - }); - } - // Delete the calendar if it has no events - const eventCount = await prisma.event.count({ - where: { calendarId: duplicate.calendarId } + // Among enabled syncs, prefer the one with most recent sync + if (a.syncEnabled && b.syncEnabled) { + if (a.lastSyncAt && b.lastSyncAt) { + return new Date(b.lastSyncAt).getTime() - new Date(a.lastSyncAt).getTime(); + } + if (a.lastSyncAt && !b.lastSyncAt) return -1; + if (!a.lastSyncAt && b.lastSyncAt) return 1; + } + return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(); }); - if (eventCount === 0) { - console.log(`[AGENDA] Deleting empty calendar ${duplicate.calendar.name} (${duplicate.calendarId})`); - await prisma.calendar.delete({ - where: { id: duplicate.calendarId } - }); + + const keepSync = syncs[0]; + const duplicates = syncs.slice(1); + + // Additional safety check: only disable duplicates if the sync to keep is actually valid + // (has events or has been synced recently) + const keepSyncEventCount = await prisma.event.count({ + where: { calendarId: keepSync.calendarId } + }); + const keepSyncIsValid = keepSyncEventCount > 0 || keepSync.lastSyncAt; + + if (!keepSyncIsValid) { + console.log(`[AGENDA] WARNING: Sync to keep ${keepSync.id} has no events and no sync history - skipping cleanup to avoid disabling valid syncs`); + continue; // Skip this group to avoid disabling a potentially valid sync } + + console.log(`[AGENDA] Keeping sync ${keepSync.id} (calendar: ${keepSync.calendar.name}, events: ${keepSyncEventCount}), disabling ${duplicates.length} duplicates`); + + // Disable or delete duplicate syncs + for (const duplicate of duplicates) { + if (duplicate.syncEnabled) { + // Disable the duplicate sync + console.log(`[AGENDA] Disabling duplicate sync ${duplicate.id} (calendar: ${duplicate.calendar.name})`); + await prisma.calendarSync.update({ + where: { id: duplicate.id }, + data: { syncEnabled: false } + }); + } + // Delete the calendar if it has no events + const eventCount = await prisma.event.count({ + where: { calendarId: duplicate.calendarId } + }); + if (eventCount === 0) { + console.log(`[AGENDA] Deleting empty calendar ${duplicate.calendar.name} (${duplicate.calendarId})`); + await prisma.calendar.delete({ + where: { id: duplicate.calendarId } + }); + } + } + } else if (enabledSyncs.length === 1 && syncs.length > 1) { + // There's only one enabled sync but multiple disabled ones - this is fine, don't touch anything + console.log(`[AGENDA] Found 1 enabled sync and ${syncs.length - 1} disabled syncs for ${key} - no cleanup needed`); } - } else if (enabledSyncs.length === 1 && syncs.length > 1) { - // There's only one enabled sync but multiple disabled ones - this is fine, don't touch anything - console.log(`[AGENDA] Found 1 enabled sync and ${syncs.length - 1} disabled syncs for ${key} - no cleanup needed`); } } }