Agenda refactor

This commit is contained in:
alma 2026-01-15 17:27:43 +01:00
parent 533c42bff4
commit 510fbfc3e0

View File

@ -320,8 +320,12 @@ export default async function CalendarPage() {
} }
// Clean up duplicate calendars for the same mailCredentialId // Clean up duplicate calendars for the same mailCredentialId
// Keep only the most recent one with syncEnabled=true, delete others // NOTE: This is mainly for cleaning up OLD duplicates created before we fixed the cascade deletion
const allSyncs = await prisma.calendarSync.findMany({ // 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: { where: {
calendar: { calendar: {
userId: session?.user?.id || '' userId: session?.user?.id || ''
@ -329,97 +333,111 @@ export default async function CalendarPage() {
mailCredentialId: { mailCredentialId: {
in: Array.from(allMailCredentialIds) in: Array.from(allMailCredentialIds)
} }
},
include: {
calendar: true,
mailCredential: true
},
orderBy: {
createdAt: 'desc'
} }
}); });
// Group by mailCredentialId and provider // Only run full cleanup if there are multiple syncs (likely duplicates)
const syncsByAccount = new Map<string, typeof allSyncs>(); if (syncCountCheck > allMailCredentialIds.size) {
for (const sync of allSyncs) { const allSyncs = await prisma.calendarSync.findMany({
if (sync.mailCredentialId) { where: {
const key = `${sync.mailCredentialId}-${sync.provider}`; calendar: {
if (!syncsByAccount.has(key)) { userId: session?.user?.id || ''
syncsByAccount.set(key, []); },
mailCredentialId: {
in: Array.from(allMailCredentialIds)
}
},
include: {
calendar: true,
mailCredential: true
},
orderBy: {
createdAt: 'desc'
}
});
// Group by mailCredentialId and provider
const syncsByAccount = new Map<string, typeof allSyncs>();
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 // 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 // IMPORTANT: Only process if there are actually multiple ENABLED syncs to avoid disabling active syncs
for (const [key, syncs] of syncsByAccount.entries()) { for (const [key, syncs] of syncsByAccount.entries()) {
if (syncs.length > 1) { if (syncs.length > 1) {
// Count how many are actually enabled // Count how many are actually enabled
const enabledSyncs = syncs.filter(s => s.syncEnabled === true); 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`);
// Sort by syncEnabled first (enabled first), then by lastSyncAt (most recently synced first), then by createdAt (newest first) // Only clean up if there are multiple ENABLED syncs
syncs.sort((a, b) => { // If there's only one enabled sync, don't touch it even if there are disabled duplicates
if (a.syncEnabled !== b.syncEnabled) { if (enabledSyncs.length > 1) {
return a.syncEnabled ? -1 : 1; console.log(`[AGENDA] Found ${enabledSyncs.length} enabled syncs for ${key}, cleaning up duplicates`);
}
// Among enabled syncs, prefer the one with most recent sync // Sort by syncEnabled first (enabled first), then by lastSyncAt (most recently synced first), then by createdAt (newest first)
if (a.syncEnabled && b.syncEnabled) { syncs.sort((a, b) => {
if (a.lastSyncAt && b.lastSyncAt) { if (a.syncEnabled !== b.syncEnabled) {
return new Date(b.lastSyncAt).getTime() - new Date(a.lastSyncAt).getTime(); return a.syncEnabled ? -1 : 1;
} }
if (a.lastSyncAt && !b.lastSyncAt) return -1; // Among enabled syncs, prefer the one with most recent sync
if (!a.lastSyncAt && b.lastSyncAt) return 1; if (a.syncEnabled && b.syncEnabled) {
} if (a.lastSyncAt && b.lastSyncAt) {
return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(); return new Date(b.lastSyncAt).getTime() - new Date(a.lastSyncAt).getTime();
}); }
if (a.lastSyncAt && !b.lastSyncAt) return -1;
const keepSync = syncs[0]; if (!a.lastSyncAt && b.lastSyncAt) return 1;
const duplicates = syncs.slice(1); }
return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
// 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})`); const keepSync = syncs[0];
await prisma.calendar.delete({ const duplicates = syncs.slice(1);
where: { id: duplicate.calendarId }
}); // 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`);
} }
} }
} }