redis caching updated optimized loading and data readiness
This commit is contained in:
+66
-16
@@ -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}`);
|
||||
|
||||
Reference in New Issue
Block a user