feat: Add compression and caching to movie routes

Adds gzip compression middleware and an in-memory cache for movie data to improve performance. Also adds database indexes for common query patterns.

Co-authored-by: mathieumoran1 <[email protected]>
This commit is contained in:
Cursor Agent
2025-12-21 21:24:27 +00:00
co-authored by mathieumoran1
parent 1e7ab962d6
commit 3884ce6492
7 changed files with 165 additions and 30 deletions
+16 -15
View File
@@ -110,10 +110,6 @@ window.onload = async function () {
const oscarYearEl = document.getElementById('oscar-year');
if (oscarYearEl) oscarYearEl.textContent = String(activeYear);
// Load (public) "100% completion" modal content at runtime.
const completionModalContent = await fetchCompletionModalContent();
applyCompletionModalContent(completionModalContent);
const oscarEffectiveDate = await fetchOscarEffectiveDate(activeYear);
const targetDate =
parseLocalNoonFromIsoDate(oscarEffectiveDate) ||
@@ -159,27 +155,32 @@ window.onload = async function () {
window.location.href = '/';
}
const res = await fetch(`/api/movies?year=${encodeURIComponent(String(activeYear))}`, {
method: 'GET',
headers: { 'Authorization': `Bearer ${token}` }
});
// Fetch remaining data in parallel (Render latency is high).
const [completionModalContent, moviesRes, watchedRes] = await Promise.all([
fetchCompletionModalContent(),
fetch(`/api/movies?year=${encodeURIComponent(String(activeYear))}&view=checklist`, {
method: 'GET',
headers: { 'Authorization': `Bearer ${token}` }
}),
fetch('/api/movies/watchedMovies', {
method: 'GET',
headers: { 'Authorization': `Bearer ${token}` }
})
]);
if (!res.ok) {
applyCompletionModalContent(completionModalContent);
if (!moviesRes.ok) {
localStorage.removeItem('auth_token');
window.location.href = '/';
return;
}
const movies = await res.json();
const movies = await moviesRes.json();
// Sort movies alphabetically by title
movies.sort((a, b) => a.title.localeCompare(b.title, 'fr', { sensitivity: 'base' }));
const watchedRes = await fetch('/api/movies/watchedMovies', {
method: 'GET',
headers: { 'Authorization': `Bearer ${token}` }
});
let watchedMovies = [];
if (watchedRes.ok) {
watchedMovies = await watchedRes.json();
+12 -10
View File
@@ -108,10 +108,17 @@ window.onload = async function () {
// Populate "Dernière mise à jour des films" banner (per active year)
await fetchMoviesLastUpdated(activeYear, token);
const res = await fetch(`/api/movies?year=${encodeURIComponent(String(activeYear))}`, {
method: 'GET',
headers: { 'Authorization': `Bearer ${token}` },
});
// Fetch movies + watched list in parallel (Render latency is high).
const [res, watchedRes] = await Promise.all([
fetch(`/api/movies?year=${encodeURIComponent(String(activeYear))}`, {
method: 'GET',
headers: { 'Authorization': `Bearer ${token}` },
}),
fetch('/api/movies/watchedMovies', {
method: 'GET',
headers: { 'Authorization': `Bearer ${token}` },
})
]);
if (!res.ok) {
localStorage.removeItem('auth_token');
@@ -121,14 +128,9 @@ window.onload = async function () {
const movies = await res.json();
// Sort movies alphabetically by title
// Sort movies alphabetically by title (server also sorts, but keep client as a fallback)
movies.sort((a, b) => a.title.localeCompare(b.title, 'fr', { sensitivity: 'base' }));
const watchedRes = await fetch('/api/movies/watchedMovies', {
method: 'GET',
headers: { 'Authorization': `Bearer ${token}` },
});
let watchedMovies = [];
if (watchedRes.ok) {
watchedMovies = await watchedRes.json();