mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-21 22:31:46 +00:00
feat(photos): add 1h disk cache for remote thumbnails and keep tabs mounted
Closes #686 - Add trekPhotoCache service: SHA1-keyed disk cache under uploads/photos/trek/, 1h TTL, in-flight dedup map to prevent stampedes on concurrent requests - Add migration 108: trek_photo_cache_meta table - Hook cache into streamPhoto for Immich/Synology thumbnail path; originals bypass cache - Add fetchImmichThumbnailBytes / fetchSynologyThumbnailBytes returning Buffer instead of piping, used by the cache layer - Add scheduler entry (every 2h + startup sweep) to evict expired disk files and DB rows via sweepExpired() - Client: convert journey tab conditional-mount to hidden-toggle so img elements stay in DOM across tab switches, preventing redundant thumbnail requests on rapid tab changes - Expose invalidateSize() on JourneyMapHandle; call it on map tab activation to fix Leaflet rendering in previously-hidden container
This commit is contained in:
+25
-1
@@ -248,12 +248,36 @@ function startIdempotencyCleanup(): void {
|
||||
}, { timezone: tz });
|
||||
}
|
||||
|
||||
// Trek photo cache cleanup: every 2 hours — evict disk files and DB rows past their 1h TTL
|
||||
let trekPhotoCacheTask: ScheduledTask | null = null;
|
||||
|
||||
function startTrekPhotoCacheCleanup(): void {
|
||||
if (trekPhotoCacheTask) { trekPhotoCacheTask.stop(); trekPhotoCacheTask = null; }
|
||||
|
||||
// Run once immediately on startup to evict any entries left over from a previous run
|
||||
try {
|
||||
const { sweepExpired } = require('./services/memories/trekPhotoCache');
|
||||
sweepExpired();
|
||||
} catch { /* cache dir may not exist yet — harmless */ }
|
||||
|
||||
trekPhotoCacheTask = cron.schedule('0 */2 * * *', () => {
|
||||
try {
|
||||
const { sweepExpired } = require('./services/memories/trekPhotoCache');
|
||||
sweepExpired();
|
||||
} catch (err: unknown) {
|
||||
const { logError: le } = require('./services/auditLog');
|
||||
le(`Trek photo cache cleanup: ${err instanceof Error ? err.message : err}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function stop(): void {
|
||||
if (currentTask) { currentTask.stop(); currentTask = null; }
|
||||
if (demoTask) { demoTask.stop(); demoTask = null; }
|
||||
if (reminderTask) { reminderTask.stop(); reminderTask = null; }
|
||||
if (versionCheckTask) { versionCheckTask.stop(); versionCheckTask = null; }
|
||||
if (idempotencyCleanupTask) { idempotencyCleanupTask.stop(); idempotencyCleanupTask = null; }
|
||||
if (trekPhotoCacheTask) { trekPhotoCacheTask.stop(); trekPhotoCacheTask = null; }
|
||||
}
|
||||
|
||||
export { start, stop, startDemoReset, startTripReminders, startVersionCheck, startIdempotencyCleanup, loadSettings, saveSettings, VALID_INTERVALS };
|
||||
export { start, stop, startDemoReset, startTripReminders, startVersionCheck, startIdempotencyCleanup, startTrekPhotoCacheCleanup, loadSettings, saveSettings, VALID_INTERVALS };
|
||||
|
||||
Reference in New Issue
Block a user