courrier multi account restore compose
This commit is contained in:
parent
764f194a72
commit
0368bd1069
@ -82,20 +82,31 @@ export async function POST(request: Request) {
|
|||||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const { emailId, folderName } = await request.json();
|
const { emailId, folderName, accountId } = await request.json();
|
||||||
|
|
||||||
if (!emailId) {
|
if (!emailId) {
|
||||||
return NextResponse.json({ error: 'Missing emailId parameter' }, { status: 400 });
|
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
|
// Invalidate Redis cache for the folder
|
||||||
if (folderName) {
|
if (normalizedFolder) {
|
||||||
await invalidateFolderCache(session.user.id, 'default', folderName);
|
await invalidateFolderCache(session.user.id, effectiveAccountId, normalizedFolder);
|
||||||
} else {
|
} else {
|
||||||
// If no folder specified, invalidate all folders (using a wildcard pattern)
|
// If no folder specified, invalidate all folders (using a wildcard pattern)
|
||||||
const folders = ['INBOX', 'Sent', 'Drafts', 'Trash', 'Junk'];
|
const folders = ['INBOX', 'Sent', 'Drafts', 'Trash', 'Junk'];
|
||||||
for (const folder of folders) {
|
for (const folder of folders) {
|
||||||
await invalidateFolderCache(session.user.id, 'default', folder);
|
await invalidateFolderCache(session.user.id, effectiveAccountId, folder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -184,7 +184,13 @@ export const useCourrier = () => {
|
|||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
|
||||||
// Still refresh in background for fresh data
|
// 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);
|
console.error('Background refresh error:', err);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -68,28 +68,35 @@ export async function getCachedEmailsWithTimeout(
|
|||||||
return null;
|
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
|
// Normalize folder name by removing account prefix if present
|
||||||
// This ensures consistent cache key format regardless of how folder name is passed
|
// This ensures consistent cache key format regardless of how folder name is passed
|
||||||
const normalizedFolder = folder.includes(':') ? folder.split(':')[1] : folder;
|
const normalizedFolder = folder.includes(':') ? folder.split(':')[1] : folder;
|
||||||
|
|
||||||
// Log the normalization for debugging
|
// Log the normalization for debugging
|
||||||
if (folder !== normalizedFolder) {
|
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) => {
|
return new Promise((resolve) => {
|
||||||
const timeoutId = setTimeout(() => {
|
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);
|
resolve(null);
|
||||||
}, timeoutMs);
|
}, timeoutMs);
|
||||||
|
|
||||||
getCachedEmailList(userId, accountId || 'default', normalizedFolder, page, perPage)
|
getCachedEmailList(userId, effectiveAccountId, normalizedFolder, page, perPage)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
if (result) {
|
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);
|
resolve(result);
|
||||||
} else {
|
} else {
|
||||||
|
console.log(`Redis cache miss for ${userId}:${effectiveAccountId}:${normalizedFolder}:${page}:${perPage}, fetching emails from IMAP`);
|
||||||
resolve(null);
|
resolve(null);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -112,11 +119,16 @@ export async function refreshEmailsInBackground(
|
|||||||
perPage: number = 20,
|
perPage: number = 20,
|
||||||
accountId?: string
|
accountId?: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// Normalize folder name by removing account prefix if present
|
// Extract account ID from folder name if present and none was explicitly provided
|
||||||
const normalizedFolder = folder.includes(':') ? folder.split(':')[1] : folder;
|
|
||||||
const folderAccountId = folder.includes(':') ? folder.split(':')[0] : accountId;
|
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
|
// Skip if already in progress or in cooldown
|
||||||
if (!shouldPrefetch(userId, prefetchKey)) {
|
if (!shouldPrefetch(userId, prefetchKey)) {
|
||||||
@ -126,9 +138,9 @@ export async function refreshEmailsInBackground(
|
|||||||
// Use setTimeout to ensure this runs after current execution context
|
// Use setTimeout to ensure this runs after current execution context
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
try {
|
try {
|
||||||
console.log(`Background refresh for ${userId}:${normalizedFolder}:${page}:${perPage}${folderAccountId ? ` for account ${folderAccountId}` : ''}`);
|
console.log(`Background refresh for ${userId}:${normalizedFolder}:${page}:${perPage} for account ${effectiveAccountId}`);
|
||||||
const freshData = await getEmails(userId, normalizedFolder, page, perPage, folderAccountId);
|
const freshData = await getEmails(userId, normalizedFolder, page, perPage, effectiveAccountId);
|
||||||
console.log(`Background refresh completed for ${userId}:${normalizedFolder}${folderAccountId ? ` for account ${folderAccountId}` : ''}`);
|
console.log(`Background refresh completed for ${userId}:${normalizedFolder} for account ${effectiveAccountId}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Background refresh error:', error);
|
console.error('Background refresh error:', error);
|
||||||
} finally {
|
} finally {
|
||||||
@ -232,11 +244,16 @@ export async function prefetchFolderEmails(
|
|||||||
startPage: number = 1,
|
startPage: number = 1,
|
||||||
accountId?: string
|
accountId?: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// Normalize folder name by removing account prefix if present
|
// Extract account ID from folder name if present and none was explicitly provided
|
||||||
const normalizedFolder = folder.includes(':') ? folder.split(':')[1] : folder;
|
|
||||||
const folderAccountId = folder.includes(':') ? folder.split(':')[0] : accountId;
|
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
|
// Skip if already in progress or in cooldown
|
||||||
if (!shouldPrefetch(userId, prefetchKey)) {
|
if (!shouldPrefetch(userId, prefetchKey)) {
|
||||||
@ -244,7 +261,7 @@ export async function prefetchFolderEmails(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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
|
// Calculate the range of pages to prefetch
|
||||||
const pagesToFetch = Array.from(
|
const pagesToFetch = Array.from(
|
||||||
@ -257,19 +274,19 @@ export async function prefetchFolderEmails(
|
|||||||
// Fetch multiple pages in parallel
|
// Fetch multiple pages in parallel
|
||||||
await Promise.allSettled(
|
await Promise.allSettled(
|
||||||
pagesToFetch.map(page =>
|
pagesToFetch.map(page =>
|
||||||
getEmails(userId, normalizedFolder, page, 20, folderAccountId)
|
getEmails(userId, normalizedFolder, page, 20, effectiveAccountId)
|
||||||
.then(result => {
|
.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;
|
return result;
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.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;
|
return null;
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`Completed prefetching ${pages} pages for ${normalizedFolder}`);
|
console.log(`Completed prefetching ${pages} pages for ${normalizedFolder} in account ${effectiveAccountId}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error during folder prefetch:`, error);
|
console.error(`Error during folder prefetch:`, error);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user