courrier redis

This commit is contained in:
alma 2025-04-27 14:50:44 +02:00
parent d73442573d
commit 1db445e6c9
5 changed files with 72 additions and 11 deletions

View File

@ -209,8 +209,18 @@ export default function CourrierPage() {
// Handle loading more emails on scroll
const handleLoadMore = () => {
if (hasMoreEmails && !isLoading) {
// Increment the page and call loadEmails with isLoadMore=true
setPage(page + 1);
// Increment the page
const nextPage = page + 1;
setPage(nextPage);
// Also prefetch additional pages to make scrolling smoother
if (session?.user?.id) {
// Prefetch next 2 pages beyond the current next page
prefetchFolderEmails(session.user.id, currentFolder, 2, nextPage + 1).catch(err => {
console.error(`Error prefetching additional pages for ${currentFolder}:`, err);
});
}
// Note: loadEmails will be called automatically due to the page dependency in useEffect
}
};
@ -275,6 +285,7 @@ export default function CourrierPage() {
// Start prefetching additional pages for this folder
if (session?.user?.id && folder) {
// First two pages are most important - prefetch immediately
prefetchFolderEmails(session.user.id, folder, 3).catch(err => {
console.error(`Error prefetching ${folder}:`, err);
});

View File

@ -49,10 +49,16 @@ export default function EmailList({
const target = event.target as HTMLDivElement;
const { scrollTop, scrollHeight, clientHeight } = target;
// Save scroll position for restoration when needed
setScrollPosition(scrollTop);
// If user scrolls near the bottom and we have more emails, load more
if (scrollHeight - scrollTop - clientHeight < 200 && hasMoreEmails && !isLoading) {
// Store current scroll data before loading more
const currentScrollTop = scrollTop;
const currentScrollHeight = scrollHeight;
// Request more emails
onLoadMore();
}
};

View File

@ -83,9 +83,12 @@ export const useCourrier = () => {
setIsLoading(true);
setError(null);
// Keep reference to the current page for this request
const currentRequestPage = page;
try {
// First try Redis cache with low timeout
const cachedEmails = await getCachedEmailsWithTimeout(session.user.id, currentFolder, page, perPage, 100);
const cachedEmails = await getCachedEmailsWithTimeout(session.user.id, currentFolder, currentRequestPage, perPage, 100);
if (cachedEmails) {
// Ensure cached data has emails array property
if (Array.isArray(cachedEmails.emails)) {
@ -96,12 +99,26 @@ export const useCourrier = () => {
const existingIds = new Set(prevEmails.map(email => email.id));
// Filter out any duplicates before appending
const newEmails = cachedEmails.emails.filter((email: Email) => !existingIds.has(email.id));
// Log pagination info
console.log(`Added ${newEmails.length} cached emails from page ${currentRequestPage} to existing ${prevEmails.length} emails`);
return [...prevEmails, ...newEmails];
});
} else {
// For initial load, replace emails
console.log(`Setting ${cachedEmails.emails.length} cached emails for page ${currentRequestPage}`);
setEmails(cachedEmails.emails);
}
// Set pagination info from cache if available
if (cachedEmails.totalEmails) setTotalEmails(cachedEmails.totalEmails);
if (cachedEmails.totalPages) setTotalPages(cachedEmails.totalPages);
// Update available mailboxes if provided
if (cachedEmails.mailboxes && cachedEmails.mailboxes.length > 0) {
setMailboxes(cachedEmails.mailboxes);
}
} else if (Array.isArray(cachedEmails)) {
// Direct array response
if (isLoadMore) {
@ -110,10 +127,15 @@ export const useCourrier = () => {
const existingIds = new Set(prevEmails.map(email => email.id));
// Filter out any duplicates before appending
const newEmails = cachedEmails.filter((email: Email) => !existingIds.has(email.id));
// Log pagination info
console.log(`Added ${newEmails.length} cached emails from page ${currentRequestPage} to existing ${prevEmails.length} emails`);
return [...prevEmails, ...newEmails];
});
} else {
// For initial load, replace emails
console.log(`Setting ${cachedEmails.length} cached emails for page ${currentRequestPage}`);
setEmails(cachedEmails);
}
} else {
@ -123,7 +145,7 @@ export const useCourrier = () => {
setIsLoading(false);
// Still refresh in background for fresh data
refreshEmailsInBackground(session.user.id, currentFolder, page, perPage).catch(err => {
refreshEmailsInBackground(session.user.id, currentFolder, currentRequestPage, perPage).catch(err => {
console.error('Background refresh error:', err);
});
return;
@ -132,7 +154,7 @@ export const useCourrier = () => {
// Build query params
const queryParams = new URLSearchParams({
folder: currentFolder,
page: page.toString(),
page: currentRequestPage.toString(),
perPage: perPage.toString()
});
@ -157,10 +179,15 @@ export const useCourrier = () => {
const existingIds = new Set(prev.map(email => email.id));
// Filter out any duplicates before appending
const newEmails = data.emails.filter((email: Email) => !existingIds.has(email.id));
// Log pagination info
console.log(`Added ${newEmails.length} fetched emails from page ${currentRequestPage} to existing ${prev.length} emails`);
return [...prev, ...newEmails];
});
} else {
// Ensure we always set an array even if API returns invalid data
console.log(`Setting ${data.emails?.length || 0} fetched emails for page ${currentRequestPage}`);
setEmails(Array.isArray(data.emails) ? data.emails : []);
}
@ -178,7 +205,7 @@ export const useCourrier = () => {
setSelectedEmailIds([]);
}
} catch (err) {
console.error('Error loading emails:', err);
console.error(`Error loading emails for page ${currentRequestPage}:`, err);
// Set emails to empty array on error to prevent runtime issues
if (!isLoadMore) {
setEmails([]);

View File

@ -458,8 +458,9 @@ export async function getEmails(
mailboxes
};
// Cache the result if it's not a search query
// Always cache the result if it's not a search query, even for pagination
if (!searchQuery) {
console.log(`Caching email list for ${userId}:${folder}:${page}:${perPage}`);
await cacheEmailList(userId, folder, page, perPage, result);
}

View File

@ -169,16 +169,32 @@ export async function prefetchUserEmailData(userId: string): Promise<void> {
export async function prefetchFolderEmails(
userId: string,
folder: string,
pages: number = 3
pages: number = 3,
startPage: number = 1
): Promise<void> {
try {
console.log(`Prefetching ${pages} pages of emails for folder ${folder}`);
console.log(`Prefetching ${pages} pages of emails for folder ${folder} starting from page ${startPage}`);
// Calculate the range of pages to prefetch
const pagesToFetch = Array.from(
{ length: pages },
(_, i) => startPage + i
);
console.log(`Will prefetch pages: ${pagesToFetch.join(', ')}`);
// Fetch multiple pages in parallel
await Promise.allSettled(
Array.from({ length: pages }, (_, i) => i + 1).map(page =>
pagesToFetch.map(page =>
getEmails(userId, folder, page, 20)
.catch(err => console.error(`Error prefetching page ${page} of ${folder}:`, err))
.then(result => {
console.log(`Successfully prefetched and cached page ${page} of ${folder} with ${result.emails.length} emails`);
return result;
})
.catch(err => {
console.error(`Error prefetching page ${page} of ${folder}:`, err);
return null;
})
)
);