courrier multi account restore compose

This commit is contained in:
alma 2025-04-29 11:24:39 +02:00
parent 764f194a72
commit 0368bd1069
3 changed files with 57 additions and 23 deletions

View File

@ -82,20 +82,31 @@ export async function POST(request: Request) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { emailId, folderName } = await request.json();
const { emailId, folderName, accountId } = await request.json();
if (!emailId) {
return NextResponse.json({ error: 'Missing emailId parameter' }, { status: 400 });
}
// Use account ID or default if not provided
const effectiveAccountId = accountId || 'default';
// Normalize folder name by removing account prefix if present
const normalizedFolder = folderName && folderName.includes(':')
? folderName.split(':')[1]
: folderName;
// Log the cache invalidation operation
console.log(`Invalidating cache for user ${session.user.id}, account ${effectiveAccountId}, folder ${normalizedFolder || 'all folders'}`);
// Invalidate Redis cache for the folder
if (folderName) {
await invalidateFolderCache(session.user.id, 'default', folderName);
if (normalizedFolder) {
await invalidateFolderCache(session.user.id, effectiveAccountId, normalizedFolder);
} else {
// If no folder specified, invalidate all folders (using a wildcard pattern)
const folders = ['INBOX', 'Sent', 'Drafts', 'Trash', 'Junk'];
for (const folder of folders) {
await invalidateFolderCache(session.user.id, 'default', folder);
await invalidateFolderCache(session.user.id, effectiveAccountId, folder);
}
}

View File

@ -184,7 +184,13 @@ export const useCourrier = () => {
setIsLoading(false);
// Still refresh in background for fresh data
refreshEmailsInBackground(session.user.id, currentFolder, currentRequestPage, perPage).catch(err => {
refreshEmailsInBackground(
session.user.id,
currentFolder,
currentRequestPage,
perPage,
accountId // Make sure accountId is passed
).catch(err => {
console.error('Background refresh error:', err);
});
return;

View File

@ -68,28 +68,35 @@ export async function getCachedEmailsWithTimeout(
return null;
}
// Extract account ID from folder name if present and none was explicitly provided
const folderAccountId = folder.includes(':') ? folder.split(':')[0] : accountId;
// Use the most specific account ID available
const effectiveAccountId = folderAccountId || accountId || 'default';
// Normalize folder name by removing account prefix if present
// This ensures consistent cache key format regardless of how folder name is passed
const normalizedFolder = folder.includes(':') ? folder.split(':')[1] : folder;
// Log the normalization for debugging
if (folder !== normalizedFolder) {
console.log(`Normalized folder name from ${folder} to ${normalizedFolder} for cache lookup`);
console.log(`Normalized folder name from ${folder} to ${normalizedFolder} for cache lookup with account ID ${effectiveAccountId}`);
}
return new Promise((resolve) => {
const timeoutId = setTimeout(() => {
console.log(`Cache access timeout for ${userId}:${normalizedFolder}:${page}:${perPage}${accountId ? ` for account ${accountId}` : ''}`);
console.log(`Cache access timeout for ${userId}:${normalizedFolder}:${page}:${perPage} for account ${effectiveAccountId}`);
resolve(null);
}, timeoutMs);
getCachedEmailList(userId, accountId || 'default', normalizedFolder, page, perPage)
getCachedEmailList(userId, effectiveAccountId, normalizedFolder, page, perPage)
.then(result => {
clearTimeout(timeoutId);
if (result) {
console.log(`Using cached data for ${userId}:${normalizedFolder}:${page}:${perPage}${accountId ? ` for account ${accountId}` : ''}`);
console.log(`Using cached data for ${userId}:${normalizedFolder}:${page}:${perPage} for account ${effectiveAccountId}`);
resolve(result);
} else {
console.log(`Redis cache miss for ${userId}:${effectiveAccountId}:${normalizedFolder}:${page}:${perPage}, fetching emails from IMAP`);
resolve(null);
}
})
@ -112,11 +119,16 @@ export async function refreshEmailsInBackground(
perPage: number = 20,
accountId?: string
): Promise<void> {
// Normalize folder name by removing account prefix if present
const normalizedFolder = folder.includes(':') ? folder.split(':')[1] : folder;
// Extract account ID from folder name if present and none was explicitly provided
const folderAccountId = folder.includes(':') ? folder.split(':')[0] : accountId;
const prefetchKey = `refresh:${normalizedFolder}:${page}:${folderAccountId || ''}`;
// Use the most specific account ID available
const effectiveAccountId = folderAccountId || accountId || 'default';
// Normalize folder name by removing account prefix if present
const normalizedFolder = folder.includes(':') ? folder.split(':')[1] : folder;
const prefetchKey = `refresh:${normalizedFolder}:${page}:${effectiveAccountId}`;
// Skip if already in progress or in cooldown
if (!shouldPrefetch(userId, prefetchKey)) {
@ -126,9 +138,9 @@ export async function refreshEmailsInBackground(
// Use setTimeout to ensure this runs after current execution context
setTimeout(async () => {
try {
console.log(`Background refresh for ${userId}:${normalizedFolder}:${page}:${perPage}${folderAccountId ? ` for account ${folderAccountId}` : ''}`);
const freshData = await getEmails(userId, normalizedFolder, page, perPage, folderAccountId);
console.log(`Background refresh completed for ${userId}:${normalizedFolder}${folderAccountId ? ` for account ${folderAccountId}` : ''}`);
console.log(`Background refresh for ${userId}:${normalizedFolder}:${page}:${perPage} for account ${effectiveAccountId}`);
const freshData = await getEmails(userId, normalizedFolder, page, perPage, effectiveAccountId);
console.log(`Background refresh completed for ${userId}:${normalizedFolder} for account ${effectiveAccountId}`);
} catch (error) {
console.error('Background refresh error:', error);
} finally {
@ -232,11 +244,16 @@ export async function prefetchFolderEmails(
startPage: number = 1,
accountId?: string
): Promise<void> {
// Normalize folder name by removing account prefix if present
const normalizedFolder = folder.includes(':') ? folder.split(':')[1] : folder;
// Extract account ID from folder name if present and none was explicitly provided
const folderAccountId = folder.includes(':') ? folder.split(':')[0] : accountId;
const prefetchKey = `folder:${normalizedFolder}:${startPage}:${folderAccountId || ''}`;
// Use the most specific account ID available
const effectiveAccountId = folderAccountId || accountId || 'default';
// Normalize folder name by removing account prefix if present
const normalizedFolder = folder.includes(':') ? folder.split(':')[1] : folder;
const prefetchKey = `folder:${normalizedFolder}:${startPage}:${effectiveAccountId}`;
// Skip if already in progress or in cooldown
if (!shouldPrefetch(userId, prefetchKey)) {
@ -244,7 +261,7 @@ export async function prefetchFolderEmails(
}
try {
console.log(`Prefetching ${pages} pages of emails for folder ${normalizedFolder} starting from page ${startPage}${folderAccountId ? ` for account ${folderAccountId}` : ''}`);
console.log(`Prefetching ${pages} pages of emails for folder ${normalizedFolder} starting from page ${startPage} for account ${effectiveAccountId}`);
// Calculate the range of pages to prefetch
const pagesToFetch = Array.from(
@ -257,19 +274,19 @@ export async function prefetchFolderEmails(
// Fetch multiple pages in parallel
await Promise.allSettled(
pagesToFetch.map(page =>
getEmails(userId, normalizedFolder, page, 20, folderAccountId)
getEmails(userId, normalizedFolder, page, 20, effectiveAccountId)
.then(result => {
console.log(`Successfully prefetched and cached page ${page} of ${normalizedFolder} with ${result.emails.length} emails`);
console.log(`Successfully prefetched and cached page ${page} of ${normalizedFolder} with ${result.emails.length} emails for account ${effectiveAccountId}`);
return result;
})
.catch(err => {
console.error(`Error prefetching page ${page} of ${normalizedFolder}:`, err);
console.error(`Error prefetching page ${page} of ${normalizedFolder} for account ${effectiveAccountId}:`, err);
return null;
})
)
);
console.log(`Completed prefetching ${pages} pages for ${normalizedFolder}`);
console.log(`Completed prefetching ${pages} pages for ${normalizedFolder} in account ${effectiveAccountId}`);
} catch (error) {
console.error(`Error during folder prefetch:`, error);
} finally {