import { pb } from '@/lib/pocketbase'; import { UptimeData } from '@/types/service.types'; // Simple in-memory cache to avoid excessive requests const uptimeCache = new Map(); // Cache time-to-live in milliseconds const CACHE_TTL = 15000; // 15 seconds export const uptimeService = { async recordUptimeData(data: UptimeData): Promise { try { console.log(`Recording uptime data for service ${data.serviceId}: Status ${data.status}, Response time: ${data.responseTime}ms`); // Create a custom request options object to disable auto-cancellation const options = { $autoCancel: false, // Disable auto-cancellation for this request $cancelKey: `uptime_record_${data.serviceId}_${Date.now()}` // Unique key for this request }; // Store uptime history in the uptime_data collection // Format data for PocketBase (use snake_case) const record = await pb.collection('uptime_data').create({ service_id: data.serviceId, timestamp: data.timestamp, status: data.status, response_time: data.responseTime }, options); // Invalidate cache for this service after recording new data uptimeCache.delete(`uptime_${data.serviceId}`); console.log(`Uptime data recorded successfully with ID: ${record.id}`); } catch (error) { console.error("Error recording uptime data:", error); throw new Error(`Failed to record uptime data: ${error}`); } }, async getUptimeHistory( serviceId: string, limit: number = 200, startDate?: Date, endDate?: Date ): Promise { try { // Create cache key based on parameters const cacheKey = `uptime_${serviceId}_${limit}_${startDate?.toISOString() || ''}_${endDate?.toISOString() || ''}`; // Check if we have a valid cached result const cached = uptimeCache.get(cacheKey); if (cached && (Date.now() - cached.timestamp) < cached.expiresIn) { console.log(`Using cached uptime history for service ${serviceId}`); return cached.data; } console.log(`Fetching uptime history for service ${serviceId}, limit: ${limit}`); // Base filter for a specific service let filter = `service_id='${serviceId}'`; // Add date range filtering if provided if (startDate && endDate) { // Convert to ISO strings for PocketBase filtering const startISO = startDate.toISOString(); const endISO = endDate.toISOString(); // Log the date range we're filtering by console.log(`Date range filter: ${startISO} to ${endISO}`); filter += ` && timestamp >= '${startISO}' && timestamp <= '${endISO}'`; } // Calculate time difference to determine if it's a short range (like 60min) const isShortTimeRange = startDate && endDate && (endDate.getTime() - startDate.getTime() <= 60 * 60 * 1000); // For very short time ranges, adjust sorting and limit const sort = '-timestamp'; // Default: newest first const actualLimit = isShortTimeRange ? Math.max(limit, 300) : limit; // Ensure adequate points for short ranges // Create custom request options to disable auto-cancellation const options = { filter: filter, sort: sort, $autoCancel: false, // Disable auto-cancellation for this request $cancelKey: `uptime_history_${serviceId}_${Date.now()}` // Unique key for this request }; try { // Get uptime history for a specific service with date filtering const response = await pb.collection('uptime_data').getList(1, actualLimit, options); console.log(`Fetched ${response.items.length} uptime records for service ${serviceId}`); // Map and return the data const uptimeData = response.items.map(item => ({ id: item.id, serviceId: item.service_id, timestamp: item.timestamp, status: item.status, responseTime: item.response_time || 0, date: item.timestamp, // Mapping timestamp to date uptime: 100 // Default value for uptime })); // For short time ranges with few data points, we might need to ensure we have enough points const shouldAddPlaceholderData = isShortTimeRange && uptimeData.length <= 2; let finalData = uptimeData; if (shouldAddPlaceholderData && uptimeData.length > 0) { // We'll add some additional data points to ensure graph is visible console.log("Adding placeholder data points to ensure graph visibility"); finalData = [...uptimeData]; } // Cache the result uptimeCache.set(cacheKey, { data: finalData, timestamp: Date.now(), expiresIn: CACHE_TTL }); return finalData; } catch (err) { throw err; } } catch (error) { console.error("Error fetching uptime history:", error); // Try to return cached data even if it's expired, as a fallback const cacheKey = `uptime_${serviceId}_${limit}_${startDate?.toISOString() || ''}_${endDate?.toISOString() || ''}`; const cached = uptimeCache.get(cacheKey); if (cached) { console.log(`Using expired cached data for service ${serviceId} due to fetch error`); return cached.data; } throw new Error('Failed to load uptime history.'); } } };