Fix: Reduce maintenance data request frequency.
Fix: The maintenance list should refresh immediately after a new maintenance entry is created.
This commit is contained in:
@@ -6,14 +6,21 @@ import { MaintenanceItem } from '../../types/maintenance.types';
|
||||
// Cache for maintenance records
|
||||
let cachedMaintenanceRecords: MaintenanceItem[] | null = null;
|
||||
let lastFetchTimestamp = 0;
|
||||
const CACHE_EXPIRY_MS = 60000; // 1 minute cache expiry
|
||||
const CACHE_EXPIRY_MS = 600000; // 10 minutes cache expiry (increased significantly)
|
||||
|
||||
/**
|
||||
* Check if cache is valid and can be used
|
||||
*/
|
||||
export const isCacheValid = (): boolean => {
|
||||
const now = Date.now();
|
||||
return !!(cachedMaintenanceRecords && now - lastFetchTimestamp < CACHE_EXPIRY_MS);
|
||||
const isValid = !!(cachedMaintenanceRecords && now - lastFetchTimestamp < CACHE_EXPIRY_MS);
|
||||
|
||||
// Minimal logging to reduce console spam
|
||||
if (isValid) {
|
||||
console.log("Using cached maintenance data");
|
||||
}
|
||||
|
||||
return isValid;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -21,7 +28,7 @@ export const isCacheValid = (): boolean => {
|
||||
*/
|
||||
export const getCachedRecords = () => {
|
||||
if (cachedMaintenanceRecords) {
|
||||
console.log("Using cached maintenance records", cachedMaintenanceRecords.length);
|
||||
console.log("Returning cached maintenance records:", cachedMaintenanceRecords.length);
|
||||
return [...cachedMaintenanceRecords]; // Return a copy to prevent mutation
|
||||
}
|
||||
return null;
|
||||
@@ -44,3 +51,20 @@ export const clearCache = (): void => {
|
||||
lastFetchTimestamp = 0;
|
||||
console.log("Maintenance cache cleared");
|
||||
};
|
||||
|
||||
/**
|
||||
* Get cache statistics for debugging
|
||||
*/
|
||||
export const getCacheStats = () => {
|
||||
const now = Date.now();
|
||||
const cacheAge = lastFetchTimestamp ? now - lastFetchTimestamp : 0;
|
||||
const timeUntilExpiry = lastFetchTimestamp ? CACHE_EXPIRY_MS - cacheAge : 0;
|
||||
|
||||
return {
|
||||
hasCache: !!cachedMaintenanceRecords,
|
||||
cacheSize: cachedMaintenanceRecords?.length || 0,
|
||||
cacheAge: Math.round(cacheAge / 1000), // in seconds
|
||||
timeUntilExpiry: Math.round(timeUntilExpiry / 1000), // in seconds
|
||||
isValid: isCacheValid()
|
||||
};
|
||||
};
|
||||
@@ -2,58 +2,104 @@
|
||||
import { pb } from '@/lib/pocketbase';
|
||||
import { MaintenanceItem } from '../../types/maintenance.types';
|
||||
import { normalizeMaintenanceItem } from '../maintenanceUtils';
|
||||
import { isCacheValid, getCachedRecords, updateCache } from './maintenanceCache';
|
||||
import { isCacheValid, getCachedRecords, updateCache, clearCache } from './maintenanceCache';
|
||||
|
||||
// Request management
|
||||
let currentRequest: Promise<MaintenanceItem[]> | null = null;
|
||||
let lastRequestTime = 0;
|
||||
const MIN_REQUEST_INTERVAL = 30000; // 30 seconds minimum between requests
|
||||
|
||||
/**
|
||||
* Get all maintenance records from the API with optimized caching
|
||||
* Get all maintenance records from the API with strict request control
|
||||
*/
|
||||
export const fetchAllMaintenanceRecords = async (forceRefresh = false): Promise<MaintenanceItem[]> => {
|
||||
try {
|
||||
const now = Date.now();
|
||||
|
||||
// If forced refresh, clear cache first
|
||||
if (forceRefresh) {
|
||||
clearCache();
|
||||
console.log('Cache cleared for forced refresh');
|
||||
}
|
||||
|
||||
// Return cached data if available and not forced refresh
|
||||
if (!forceRefresh && isCacheValid()) {
|
||||
return getCachedRecords() as MaintenanceItem[];
|
||||
}
|
||||
|
||||
// Use a unique requestKey to prevent caching issues
|
||||
const timestamp = now;
|
||||
// Request deduplication: if a request is already in progress, wait for it
|
||||
if (currentRequest) {
|
||||
console.log('Request already in progress, waiting for completion');
|
||||
return await currentRequest;
|
||||
}
|
||||
|
||||
// Increase items per page and use fields parameter to fetch only needed data
|
||||
// Also expand the assigned_users relation to get user details
|
||||
// Strict rate limiting - prevent requests too close together (unless forced)
|
||||
const timeSinceLastRequest = now - lastRequestTime;
|
||||
if (timeSinceLastRequest < MIN_REQUEST_INTERVAL && !forceRefresh) {
|
||||
console.log(`Rate limiting: ${Math.round((MIN_REQUEST_INTERVAL - timeSinceLastRequest) / 1000)}s remaining`);
|
||||
return getCachedRecords() || [];
|
||||
}
|
||||
|
||||
lastRequestTime = now;
|
||||
|
||||
// Create the request promise
|
||||
currentRequest = performRequest(now);
|
||||
|
||||
try {
|
||||
const result = await currentRequest;
|
||||
return result;
|
||||
} finally {
|
||||
currentRequest = null; // Clear the current request
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
currentRequest = null; // Clear the current request on error
|
||||
|
||||
console.error('Error fetching maintenance records:', error);
|
||||
|
||||
// Return cached data on error if available
|
||||
return getCachedRecords() || [];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform the actual API request
|
||||
*/
|
||||
const performRequest = async (timestamp: number): Promise<MaintenanceItem[]> => {
|
||||
console.log('Making API request for maintenance records...');
|
||||
|
||||
// Create abort controller for request timeout
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout
|
||||
|
||||
try {
|
||||
const result = await pb.collection('maintenance').getList(1, 200, {
|
||||
sort: '-created',
|
||||
requestKey: `maintenance-${timestamp}`,
|
||||
$cancelKey: `maintenance-fetch-${timestamp}`,
|
||||
expand: 'assigned_users', // Expand the relation to get user details
|
||||
expand: 'assigned_users',
|
||||
signal: controller.signal,
|
||||
});
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (!result || !result.items || result.items.length === 0) {
|
||||
const emptyData: MaintenanceItem[] = [];
|
||||
updateCache(emptyData, now);
|
||||
updateCache(emptyData, timestamp);
|
||||
return emptyData;
|
||||
}
|
||||
|
||||
// Process and normalize data
|
||||
const normalizedData = result.items.map(item => {
|
||||
console.log("Processing maintenance item:", item.id);
|
||||
console.log("Item assigned_users:", item.assigned_users);
|
||||
console.log("Notification channel:", item.notification_channel_id);
|
||||
return normalizeMaintenanceItem(item);
|
||||
});
|
||||
const normalizedData = result.items.map(item => normalizeMaintenanceItem(item));
|
||||
|
||||
// Update cache
|
||||
updateCache(normalizedData, now);
|
||||
updateCache(normalizedData, timestamp);
|
||||
|
||||
console.log(`Successfully fetched ${normalizedData.length} maintenance records`);
|
||||
return normalizedData;
|
||||
} catch (error) {
|
||||
// Handle abort errors gracefully without console errors
|
||||
if ((error as any)?.isAbort) {
|
||||
console.log("Request aborted:", error);
|
||||
return getCachedRecords() || [];
|
||||
}
|
||||
|
||||
console.error('Error fetching maintenance records:', error);
|
||||
return getCachedRecords() || [];
|
||||
} catch (error) {
|
||||
clearTimeout(timeoutId);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -61,12 +61,14 @@ const getCompletedMaintenance = async (): Promise<MaintenanceItem[]> => {
|
||||
const createMaintenance = async (data: CreateMaintenanceInput): Promise<void> => {
|
||||
await createMaintenanceRecord(data);
|
||||
clearMaintenanceCache(); // Force cache refresh after creation
|
||||
console.log('Maintenance created and cache cleared');
|
||||
};
|
||||
|
||||
// Update an existing maintenance record
|
||||
const updateMaintenanceRecord = async (id: string, data: Partial<MaintenanceItem>): Promise<void> => {
|
||||
await updateMaintenance(id, data);
|
||||
clearMaintenanceCache(); // Force cache refresh after update
|
||||
console.log('Maintenance updated and cache cleared');
|
||||
};
|
||||
|
||||
// Refresh cache manually
|
||||
@@ -89,4 +91,4 @@ export const maintenanceService = {
|
||||
};
|
||||
|
||||
// Re-export types for convenience
|
||||
export type { MaintenanceItem, CreateMaintenanceInput };
|
||||
export type { MaintenanceItem, CreateMaintenanceInput };
|
||||
Reference in New Issue
Block a user