Agenda refactor
This commit is contained in:
parent
0cdf3dd691
commit
631524b8a8
@ -378,14 +378,14 @@ export default async function CalendarPage() {
|
|||||||
|
|
||||||
// Trigger sync for Microsoft calendars that need it (async, don't wait)
|
// Trigger sync for Microsoft calendars that need it (async, don't wait)
|
||||||
for (const syncConfig of microsoftSyncConfigs) {
|
for (const syncConfig of microsoftSyncConfigs) {
|
||||||
// For Microsoft, use a more frequent check (2 minutes) for better reactivity
|
// For Microsoft, use a more frequent check (1 minute) for better reactivity
|
||||||
// This allows new events to appear faster without overloading the API
|
// This allows new events to appear faster without overloading the API
|
||||||
const microsoftMinSyncInterval = 2; // minutes
|
const microsoftMinSyncInterval = 1; // minutes (reduced from 2 to 1 for faster sync)
|
||||||
const minutesSinceLastSync = syncConfig.lastSyncAt
|
const minutesSinceLastSync = syncConfig.lastSyncAt
|
||||||
? (Date.now() - syncConfig.lastSyncAt.getTime()) / (1000 * 60)
|
? (Date.now() - syncConfig.lastSyncAt.getTime()) / (1000 * 60)
|
||||||
: Infinity;
|
: Infinity;
|
||||||
|
|
||||||
// Sync if never synced, or if enough time has passed (use minimum of 2 min or configured frequency)
|
// Sync if never synced, or if enough time has passed (use minimum of 1 min or configured frequency)
|
||||||
const needsSync = !syncConfig.lastSyncAt ||
|
const needsSync = !syncConfig.lastSyncAt ||
|
||||||
minutesSinceLastSync >= Math.min(microsoftMinSyncInterval, syncConfig.syncFrequency);
|
minutesSinceLastSync >= Math.min(microsoftMinSyncInterval, syncConfig.syncFrequency);
|
||||||
|
|
||||||
|
|||||||
@ -98,22 +98,31 @@ export async function GET(req: NextRequest) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Extract mission calendars (excluding those already in personalCalendars)
|
// Extract mission calendars (excluding those already in personalCalendars)
|
||||||
|
// Use a Set to avoid duplicate calendars by ID
|
||||||
|
const personalCalendarIds = new Set(personalCalendars.map(cal => cal.id));
|
||||||
const missionCalendars = missionUserRelations
|
const missionCalendars = missionUserRelations
|
||||||
.flatMap(mu => mu.mission.calendars)
|
.flatMap(mu => mu.mission.calendars)
|
||||||
.filter(cal => cal.userId !== session.user.id); // Exclude calendars owned by user (already in personalCalendars)
|
.filter(cal => !personalCalendarIds.has(cal.id)); // Exclude calendars already in personalCalendars
|
||||||
|
|
||||||
// Combine personal and mission calendars
|
// Combine personal and mission calendars
|
||||||
const calendars = [...personalCalendars, ...missionCalendars];
|
const calendars = [...personalCalendars, ...missionCalendars];
|
||||||
|
|
||||||
|
// Remove duplicate calendars by ID (in case same calendar appears multiple times)
|
||||||
|
const uniqueCalendars = Array.from(
|
||||||
|
new Map(calendars.map(cal => [cal.id, cal])).values()
|
||||||
|
);
|
||||||
|
|
||||||
logger.debug('[CALENDAR] Fetched calendars with events', {
|
logger.debug('[CALENDAR] Fetched calendars with events', {
|
||||||
userId: session.user.id,
|
userId: session.user.id,
|
||||||
count: calendars.length,
|
personalCount: personalCalendars.length,
|
||||||
|
missionCount: missionCalendars.length,
|
||||||
|
totalCount: uniqueCalendars.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Cache the results
|
// Cache the results
|
||||||
await cacheCalendarData(session.user.id, calendars);
|
await cacheCalendarData(session.user.id, uniqueCalendars);
|
||||||
|
|
||||||
return NextResponse.json(calendars);
|
return NextResponse.json(uniqueCalendars);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('[CALENDAR] Erreur lors de la récupération des calendriers', {
|
logger.error('[CALENDAR] Erreur lors de la récupération des calendriers', {
|
||||||
error: error instanceof Error ? error.message : String(error),
|
error: error instanceof Error ? error.message : String(error),
|
||||||
|
|||||||
@ -477,6 +477,14 @@ export async function syncMicrosoftCalendar(
|
|||||||
? existingEventsByExternalId.get(microsoftId)
|
? existingEventsByExternalId.get(microsoftId)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
if (existingEvent) {
|
||||||
|
logger.debug('Matched event by externalEventId', {
|
||||||
|
microsoftId,
|
||||||
|
eventId: existingEvent.id,
|
||||||
|
title: caldavEvent.summary,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Priority 2: Fallback to checking description for [MS_ID:xxx] (backward compatibility)
|
// Priority 2: Fallback to checking description for [MS_ID:xxx] (backward compatibility)
|
||||||
if (!existingEvent && microsoftId) {
|
if (!existingEvent && microsoftId) {
|
||||||
existingEvent = existingEvents.find((e) => {
|
existingEvent = existingEvents.find((e) => {
|
||||||
@ -487,23 +495,53 @@ export async function syncMicrosoftCalendar(
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (existingEvent) {
|
||||||
|
logger.debug('Matched event by description [MS_ID]', {
|
||||||
|
microsoftId,
|
||||||
|
eventId: existingEvent.id,
|
||||||
|
title: caldavEvent.summary,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Priority 3: Fallback to title + date matching for events without externalEventId
|
// Priority 3: Fallback to title + date matching for events without externalEventId
|
||||||
|
// IMPORTANT: Only match if the event doesn't have an externalEventId (to avoid false matches)
|
||||||
if (!existingEvent) {
|
if (!existingEvent) {
|
||||||
existingEvent = existingEvents.find(
|
existingEvent = existingEvents.find(
|
||||||
(e) => {
|
(e) => {
|
||||||
// Access externalEventId safely (may not be in Prisma type if client not regenerated)
|
// Access externalEventId safely (may not be in Prisma type if client not regenerated)
|
||||||
const hasExternalId = !!(e as any).externalEventId;
|
const hasExternalId = !!(e as any).externalEventId;
|
||||||
if (!hasExternalId && // Only match events that don't have externalEventId yet
|
// Only match events that don't have externalEventId yet (to avoid false matches)
|
||||||
e.title === caldavEvent.summary) {
|
if (hasExternalId) {
|
||||||
|
return false; // Skip events that already have externalEventId
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match by title and date (within 1 minute)
|
||||||
|
if (e.title === caldavEvent.summary) {
|
||||||
const timeDiff = Math.abs(new Date(e.start).getTime() - caldavEvent.start.getTime());
|
const timeDiff = Math.abs(new Date(e.start).getTime() - caldavEvent.start.getTime());
|
||||||
return timeDiff < 60000; // Within 1 minute
|
if (timeDiff < 60000) { // Within 1 minute
|
||||||
|
logger.debug('Matched event by title + date (no externalEventId)', {
|
||||||
|
eventId: e.id,
|
||||||
|
title: caldavEvent.summary,
|
||||||
|
timeDiff,
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Log if no match found (new event)
|
||||||
|
if (!existingEvent) {
|
||||||
|
logger.debug('No match found, will create new event', {
|
||||||
|
microsoftId,
|
||||||
|
title: caldavEvent.summary,
|
||||||
|
start: caldavEvent.start.toISOString(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Clean description (remove [MS_ID:xxx] prefix if present from previous syncs)
|
// Clean description (remove [MS_ID:xxx] prefix if present from previous syncs)
|
||||||
const cleanedDescription = cleanDescription(caldavEvent.description);
|
const cleanedDescription = cleanDescription(caldavEvent.description);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user