redis caching updated optimized loading and data readiness

This commit is contained in:
2025-12-28 06:19:55 +00:00
parent dd0eba8aee
commit ccdfeb782d
+66 -16
View File
@@ -81,25 +81,52 @@ app.get('/api/jobs', async (c) => {
// Fast endpoint: returns all jobs in a single cached request
app.get('/api/jobs-all', async (c) => {
const cacheKey = 'jobs:all';
const ttl = 300; // 5 minutes cache
const ttl = 1800; // 30 minutes cache
try {
// Try to get from cache first
// Always try cache first for instant response
if (isRedisConnected()) {
const cached = await getCache(cacheKey);
if (cached) {
logLine('logs/server.log', `Cache HIT for ${cacheKey} (${cached.items?.length || 0} jobs)`);
// Return cached data immediately, refresh in background if needed
setImmediate(async () => {
try {
await refreshJobsCache(cacheKey, ttl, c.req.header('Authorization') || '');
} catch (err) {
// Silently fail background refresh
}
});
return c.json(cached);
}
logLine('logs/server.log', `Cache MISS for ${cacheKey} - fetching all jobs`);
}
const authHeader = c.req.header('Authorization') || '';
// No cache available, fetch now
const result = await fetchAllJobsFromPocketBase(c.req.header('Authorization') || '');
// Cache the result
if (isRedisConnected()) {
await setCache(cacheKey, result, ttl);
logLine('logs/server.log', `Cached ${cacheKey} with ${result.items.length} jobs for ${ttl}s`);
}
return c.json(result);
} catch (err) {
logLine('logs/error.log', `jobs-all endpoint error: ${(err as Error)?.message || String(err)}`);
return c.json({ error: 'Failed to fetch jobs' }, 500);
}
});
// Helper function to fetch all jobs from PocketBase
async function fetchAllJobsFromPocketBase(authHeader: string): Promise<any> {
const allItems: any[] = [];
let page = 1;
const perPage = 500; // Large page size
const perPage = 500;
// Fetch all pages from PocketBase
while (true) {
const pbUrl = `https://pocketbase.ccllc.pro/api/collections/pbc_1407612689/records?page=${page}&perPage=${perPage}&sort=-Job_Number`;
const response = await fetch(pbUrl, {
@@ -120,27 +147,25 @@ app.get('/api/jobs-all', async (c) => {
page++;
}
const result = {
return {
page: 1,
perPage: allItems.length,
totalItems: allItems.length,
totalPages: 1,
items: allItems
};
}
// Cache the result
if (isRedisConnected()) {
// Helper function to refresh jobs cache in background
async function refreshJobsCache(cacheKey: string, ttl: number, authHeader: string): Promise<void> {
try {
const result = await fetchAllJobsFromPocketBase(authHeader);
await setCache(cacheKey, result, ttl);
logLine('logs/server.log', `Cached ${cacheKey} with ${allItems.length} jobs for ${ttl}s`);
}
return c.json(result);
logLine('logs/server.log', `Background refresh: cached ${cacheKey} with ${result.items.length} jobs`);
} catch (err) {
logLine('logs/error.log', `jobs-all endpoint error: ${(err as Error)?.message || String(err)}`);
return c.json({ error: 'Failed to fetch jobs' }, 500);
logLine('logs/error.log', `Background refresh error: ${(err as Error)?.message || String(err)}`);
}
});
}
// --- Microsoft Graph helpers ---
@@ -448,6 +473,31 @@ const PORT = Number(process.env.PORT || 3004);
logLine('logs/server.log', `Starting frontend server (Redis version) on port ${PORT}`);
// Warm up cache on startup
(async () => {
try {
if (isRedisConnected()) {
logLine('logs/server.log', 'Warming up jobs cache...');
const result = await fetchAllJobsFromPocketBase('');
await setCache('jobs:all', result, 1800);
logLine('logs/server.log', `✓ Cache warmed with ${result.items.length} jobs`);
}
} catch (err) {
logLine('logs/error.log', `Cache warmup failed: ${(err as Error)?.message || String(err)}`);
}
})();
// Background refresh every 5 minutes to keep cache hot
setInterval(async () => {
try {
if (isRedisConnected()) {
await refreshJobsCache('jobs:all', 1800, '');
}
} catch (err) {
logLine('logs/error.log', `Periodic refresh error: ${(err as Error)?.message || String(err)}`);
}
}, 5 * 60 * 1000); // Every 5 minutes
// Graceful shutdown logging
const shutdown = (signal: string) => {
logLine('logs/server.log', `Shutting down due to ${signal}`);