Fix: Prevent console message loop on maintenance updates
The console was generating excessive messages after schedule maintenance updates.
This commit is contained in:
@@ -35,4 +35,52 @@ const api = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Mock fetch override for development
|
||||||
|
const originalFetch = window.fetch;
|
||||||
|
window.fetch = async (url, options = {}) => {
|
||||||
|
// Check if this is an API request to our mock endpoints
|
||||||
|
if (typeof url === 'string' && url.startsWith('/api/')) {
|
||||||
|
console.log('Intercepting API request:', url, options);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let body = {};
|
||||||
|
|
||||||
|
// Properly handle different body types
|
||||||
|
if (options.body) {
|
||||||
|
if (typeof options.body === 'string') {
|
||||||
|
body = JSON.parse(options.body);
|
||||||
|
} else {
|
||||||
|
// Handle ReadableStream or other BodyInit types
|
||||||
|
const bodyText = await new Response(options.body).text();
|
||||||
|
body = bodyText ? JSON.parse(bodyText) : {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await api.handleRequest(url, options.method || 'GET', body);
|
||||||
|
|
||||||
|
// Create a proper Response object
|
||||||
|
return new Response(JSON.stringify(result.json), {
|
||||||
|
status: result.status,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error in API handler:', error);
|
||||||
|
return new Response(JSON.stringify({
|
||||||
|
success: false,
|
||||||
|
message: 'Internal server error'
|
||||||
|
}), {
|
||||||
|
status: 500,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For all other requests, use the original fetch
|
||||||
|
return originalFetch(url, options);
|
||||||
|
};
|
||||||
|
|
||||||
export default api;
|
export default api;
|
||||||
@@ -58,7 +58,6 @@ export const useMaintenanceData = ({ refreshTrigger = 0 }: UseMaintenanceDataPro
|
|||||||
|
|
||||||
// Prevent duplicate requests
|
// Prevent duplicate requests
|
||||||
if (currentRequestRef.current) {
|
if (currentRequestRef.current) {
|
||||||
console.log("Request already in progress, waiting...");
|
|
||||||
await currentRequestRef.current;
|
await currentRequestRef.current;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -72,14 +71,11 @@ export const useMaintenanceData = ({ refreshTrigger = 0 }: UseMaintenanceDataPro
|
|||||||
|
|
||||||
const requestPromise = (async () => {
|
const requestPromise = (async () => {
|
||||||
try {
|
try {
|
||||||
console.log("Fetching maintenance data...", force ? "(forced)" : "");
|
|
||||||
const data = await maintenanceService.getMaintenanceRecords();
|
const data = await maintenanceService.getMaintenanceRecords();
|
||||||
|
|
||||||
// Check if component is still mounted before updating state
|
// Check if component is still mounted before updating state
|
||||||
if (!mountedRef.current) return;
|
if (!mountedRef.current) return;
|
||||||
|
|
||||||
console.log(`Fetched ${data.length} maintenance records`);
|
|
||||||
|
|
||||||
// Update state with fetched data
|
// Update state with fetched data
|
||||||
setAllMaintenanceData(data);
|
setAllMaintenanceData(data);
|
||||||
setInitialized(true);
|
setInitialized(true);
|
||||||
@@ -119,7 +115,6 @@ export const useMaintenanceData = ({ refreshTrigger = 0 }: UseMaintenanceDataPro
|
|||||||
|
|
||||||
// Initial fetch on mount - NO AUTOMATIC POLLING
|
// Initial fetch on mount - NO AUTOMATIC POLLING
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("useMaintenanceData hook mounted, fetching initial data");
|
|
||||||
mountedRef.current = true;
|
mountedRef.current = true;
|
||||||
|
|
||||||
// Only fetch initial data, no polling
|
// Only fetch initial data, no polling
|
||||||
@@ -134,7 +129,6 @@ export const useMaintenanceData = ({ refreshTrigger = 0 }: UseMaintenanceDataPro
|
|||||||
// Handle refresh trigger changes - ONLY when explicitly triggered
|
// Handle refresh trigger changes - ONLY when explicitly triggered
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (refreshTrigger > 0) {
|
if (refreshTrigger > 0) {
|
||||||
console.log("Manual refresh triggered, forcing data fetch");
|
|
||||||
fetchMaintenanceData(true); // Force refresh to bypass cache
|
fetchMaintenanceData(true); // Force refresh to bypass cache
|
||||||
}
|
}
|
||||||
}, [refreshTrigger, fetchMaintenanceData]);
|
}, [refreshTrigger, fetchMaintenanceData]);
|
||||||
|
|||||||
+125
-42
@@ -19,74 +19,157 @@ export const MaintenanceStatusChecker = ({
|
|||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const checkedItemsRef = useRef<Set<string>>(new Set());
|
const checkedItemsRef = useRef<Set<string>>(new Set());
|
||||||
const notificationSentRef = useRef<Set<string>>(new Set());
|
const notificationSentRef = useRef<Set<string>>(new Set());
|
||||||
|
const intervalRef = useRef<number | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!maintenanceData || maintenanceData.length === 0) return;
|
if (!maintenanceData || maintenanceData.length === 0) return;
|
||||||
|
|
||||||
// Check for maintenance items that need status update
|
|
||||||
const now = new Date();
|
|
||||||
const checkAndUpdateStatus = async () => {
|
const checkAndUpdateStatus = async () => {
|
||||||
|
const currentTime = new Date();
|
||||||
|
let hasUpdates = false;
|
||||||
|
|
||||||
|
console.log('MaintenanceStatusChecker: Checking status updates at', currentTime.toISOString());
|
||||||
|
console.log('MaintenanceStatusChecker: Checking', maintenanceData.length, 'maintenance items');
|
||||||
|
|
||||||
for (const item of maintenanceData) {
|
for (const item of maintenanceData) {
|
||||||
if (item.status.toLowerCase() !== 'scheduled') continue;
|
|
||||||
|
|
||||||
// Skip if we've already checked this item in this session
|
|
||||||
if (checkedItemsRef.current.has(item.id)) continue;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const startTime = new Date(item.start_time);
|
const startTime = new Date(item.start_time);
|
||||||
const endTime = new Date(item.end_time);
|
const endTime = new Date(item.end_time);
|
||||||
|
const status = item.status.toLowerCase();
|
||||||
|
|
||||||
// If current time is past start time but before end time, update to in_progress
|
console.log(`MaintenanceStatusChecker: Item ${item.id} - Status: ${status}, Start: ${startTime.toISOString()}, End: ${endTime.toISOString()}, Current: ${currentTime.toISOString()}`);
|
||||||
if (startTime <= now && now <= endTime) {
|
|
||||||
console.log(`Auto-updating maintenance ${item.title} to in_progress status`);
|
// Check if scheduled maintenance should start (become in_progress)
|
||||||
|
if (status === 'scheduled' && currentTime >= startTime && currentTime <= endTime) {
|
||||||
|
const checkKey = `${item.id}-started`;
|
||||||
|
const notificationKey = `${item.id}-start-notification`;
|
||||||
|
|
||||||
// Update status to in_progress
|
if (!checkedItemsRef.current.has(checkKey)) {
|
||||||
await maintenanceService.updateMaintenanceStatus(item.id, 'in_progress');
|
console.log(`MaintenanceStatusChecker: Starting maintenance ${item.id} at ${currentTime.toISOString()}`);
|
||||||
|
|
||||||
// Only send notification if not sent before
|
|
||||||
if (!notificationSentRef.current.has(item.id)) {
|
|
||||||
console.log(`Sending start notification for maintenance ${item.title}`);
|
|
||||||
|
|
||||||
// Send notification for maintenance start
|
// Update status to in_progress first
|
||||||
await maintenanceNotificationService.sendMaintenanceNotification({
|
await maintenanceService.updateMaintenanceStatus(item.id, 'in_progress');
|
||||||
maintenance: item,
|
|
||||||
notificationType: 'start'
|
// Send start notification only once
|
||||||
|
if (!notificationSentRef.current.has(notificationKey)) {
|
||||||
|
try {
|
||||||
|
await maintenanceNotificationService.sendMaintenanceNotification({
|
||||||
|
maintenance: item,
|
||||||
|
notificationType: 'start'
|
||||||
|
});
|
||||||
|
notificationSentRef.current.add(notificationKey);
|
||||||
|
console.log(`MaintenanceStatusChecker: Start notification sent for ${item.id}`);
|
||||||
|
} catch (notificationError) {
|
||||||
|
console.log('MaintenanceStatusChecker: Start notification failed', notificationError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: t('maintenanceInProgress'),
|
||||||
|
description: `${item.title} ${t('isNowInProgress')}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mark as notified
|
checkedItemsRef.current.add(checkKey);
|
||||||
notificationSentRef.current.add(item.id);
|
hasUpdates = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
toast({
|
|
||||||
title: t('maintenanceInProgress'),
|
|
||||||
description: `${item.title} ${t('isNowInProgress')}`,
|
|
||||||
});
|
|
||||||
|
|
||||||
onStatusUpdated();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark as checked regardless of outcome
|
// Check if in_progress maintenance should be completed
|
||||||
checkedItemsRef.current.add(item.id);
|
if (status === 'in_progress' && currentTime >= endTime) {
|
||||||
|
const checkKey = `${item.id}-completed`;
|
||||||
|
const notificationKey = `${item.id}-end-notification`;
|
||||||
|
|
||||||
|
if (!checkedItemsRef.current.has(checkKey)) {
|
||||||
|
console.log(`MaintenanceStatusChecker: Completing maintenance ${item.id} at ${currentTime.toISOString()}`);
|
||||||
|
|
||||||
|
// Update status to completed first
|
||||||
|
await maintenanceService.updateMaintenanceStatus(item.id, 'completed');
|
||||||
|
|
||||||
|
// Send completion notification only once
|
||||||
|
if (!notificationSentRef.current.has(notificationKey)) {
|
||||||
|
try {
|
||||||
|
await maintenanceNotificationService.sendMaintenanceNotification({
|
||||||
|
maintenance: item,
|
||||||
|
notificationType: 'end'
|
||||||
|
});
|
||||||
|
notificationSentRef.current.add(notificationKey);
|
||||||
|
console.log(`MaintenanceStatusChecker: Completion notification sent for ${item.id}`);
|
||||||
|
} catch (notificationError) {
|
||||||
|
console.log('MaintenanceStatusChecker: Completion notification failed', notificationError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: t('maintenanceCompleted'),
|
||||||
|
description: `${item.title} ${t('hasBeenCompleted')}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
checkedItemsRef.current.add(checkKey);
|
||||||
|
hasUpdates = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error auto-updating maintenance status for ${item.id}:`, error);
|
console.error('MaintenanceStatusChecker: Error updating status for item', item.id, error);
|
||||||
|
// Clear the check flags after 2 minutes to allow retry
|
||||||
// Add a small delay before trying again to prevent rapid retry cycles
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
checkedItemsRef.current.delete(item.id); // Allow retry on next check
|
checkedItemsRef.current.delete(`${item.id}-started`);
|
||||||
}, 300000); // 5 minutes before retry
|
checkedItemsRef.current.delete(`${item.id}-completed`);
|
||||||
|
notificationSentRef.current.delete(`${item.id}-start-notification`);
|
||||||
|
notificationSentRef.current.delete(`${item.id}-end-notification`);
|
||||||
|
}, 120000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasUpdates) {
|
||||||
|
console.log('MaintenanceStatusChecker: Status updates detected, triggering refresh');
|
||||||
|
// Force immediate refresh to update the UI
|
||||||
|
onStatusUpdated();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Run the check immediately
|
// Clear the interval if it exists
|
||||||
|
if (intervalRef.current) {
|
||||||
|
clearInterval(intervalRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial check immediately
|
||||||
checkAndUpdateStatus();
|
checkAndUpdateStatus();
|
||||||
|
|
||||||
// Set up interval to check every minute
|
// Check every 5 seconds for immediate status updates
|
||||||
const intervalId = setInterval(checkAndUpdateStatus, 60000);
|
intervalRef.current = window.setInterval(checkAndUpdateStatus, 5000);
|
||||||
|
|
||||||
return () => clearInterval(intervalId);
|
return () => {
|
||||||
|
if (intervalRef.current) {
|
||||||
|
clearInterval(intervalRef.current);
|
||||||
|
intervalRef.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
}, [maintenanceData, onStatusUpdated, t, toast]);
|
}, [maintenanceData, onStatusUpdated, t, toast]);
|
||||||
|
|
||||||
// This is a utility component with no UI render
|
// Clear check flags when maintenance data changes significantly
|
||||||
|
useEffect(() => {
|
||||||
|
const currentIds = new Set(maintenanceData.map(item => item.id));
|
||||||
|
|
||||||
|
// Clean up check flags for items that no longer exist
|
||||||
|
const keysToDelete = Array.from(checkedItemsRef.current).filter(key => {
|
||||||
|
const itemId = key.split('-')[0];
|
||||||
|
return !currentIds.has(itemId);
|
||||||
|
});
|
||||||
|
|
||||||
|
keysToDelete.forEach(key => {
|
||||||
|
checkedItemsRef.current.delete(key);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clean up notification flags for items that no longer exist
|
||||||
|
const notificationKeysToDelete = Array.from(notificationSentRef.current).filter(key => {
|
||||||
|
const itemId = key.split('-')[0];
|
||||||
|
return !currentIds.has(itemId);
|
||||||
|
});
|
||||||
|
|
||||||
|
notificationKeysToDelete.forEach(key => {
|
||||||
|
notificationSentRef.current.delete(key);
|
||||||
|
});
|
||||||
|
}, [maintenanceData]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
+1
-27
@@ -25,7 +25,6 @@ export const MaintenanceDetailContent = ({
|
|||||||
queryKey: ['users'],
|
queryKey: ['users'],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const usersList = await userService.getUsers();
|
const usersList = await userService.getUsers();
|
||||||
console.log("Fetched users for maintenance detail:", usersList);
|
|
||||||
return usersList || [];
|
return usersList || [];
|
||||||
},
|
},
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -36,7 +35,6 @@ export const MaintenanceDetailContent = ({
|
|||||||
queryKey: ['notificationChannels'],
|
queryKey: ['notificationChannels'],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const channels = await alertConfigService.getAlertConfigurations();
|
const channels = await alertConfigService.getAlertConfigurations();
|
||||||
console.log("Fetched notification channels:", channels);
|
|
||||||
return channels || [];
|
return channels || [];
|
||||||
},
|
},
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -45,9 +43,6 @@ export const MaintenanceDetailContent = ({
|
|||||||
// Process user information when users data is available
|
// Process user information when users data is available
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (users.length > 0 && maintenance) {
|
if (users.length > 0 && maintenance) {
|
||||||
console.log("Processing maintenance data with users:", maintenance);
|
|
||||||
console.log("Maintenance assigned_users:", maintenance.assigned_users);
|
|
||||||
|
|
||||||
// Create a copy of the maintenance object for modifications
|
// Create a copy of the maintenance object for modifications
|
||||||
const enhancedMaintenance = { ...maintenance };
|
const enhancedMaintenance = { ...maintenance };
|
||||||
|
|
||||||
@@ -58,7 +53,6 @@ export const MaintenanceDetailContent = ({
|
|||||||
// Step 1: Extract user IDs from various formats
|
// Step 1: Extract user IDs from various formats
|
||||||
if (Array.isArray(maintenance.assigned_users)) {
|
if (Array.isArray(maintenance.assigned_users)) {
|
||||||
userIds = maintenance.assigned_users;
|
userIds = maintenance.assigned_users;
|
||||||
console.log("Assigned users is an array:", userIds);
|
|
||||||
} else if (typeof maintenance.assigned_users === 'string') {
|
} else if (typeof maintenance.assigned_users === 'string') {
|
||||||
// Try parsing the string to extract user IDs
|
// Try parsing the string to extract user IDs
|
||||||
try {
|
try {
|
||||||
@@ -67,34 +61,28 @@ export const MaintenanceDetailContent = ({
|
|||||||
if (Array.isArray(parsedData)) {
|
if (Array.isArray(parsedData)) {
|
||||||
// Direct array format
|
// Direct array format
|
||||||
userIds = parsedData;
|
userIds = parsedData;
|
||||||
console.log("Parsed assigned_users from JSON array:", userIds);
|
|
||||||
} else if (typeof parsedData === 'string') {
|
} else if (typeof parsedData === 'string') {
|
||||||
// Nested JSON string
|
// Nested JSON string
|
||||||
try {
|
try {
|
||||||
const nestedData = JSON.parse(parsedData);
|
const nestedData = JSON.parse(parsedData);
|
||||||
if (Array.isArray(nestedData)) {
|
if (Array.isArray(nestedData)) {
|
||||||
userIds = nestedData;
|
userIds = nestedData;
|
||||||
console.log("Parsed assigned_users from nested JSON:", userIds);
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// If nested parsing fails, treat as single ID
|
// If nested parsing fails, treat as single ID
|
||||||
userIds = [parsedData];
|
userIds = [parsedData];
|
||||||
console.log("Using parsed string as single ID:", userIds);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Unknown format, use as is
|
// Unknown format, use as is
|
||||||
userIds = [String(parsedData)];
|
userIds = [String(parsedData)];
|
||||||
console.log("Using parsed data as single ID:", userIds);
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// If JSON parsing fails, try comma splitting
|
// If JSON parsing fails, try comma splitting
|
||||||
if (maintenance.assigned_users.includes(',')) {
|
if (maintenance.assigned_users.includes(',')) {
|
||||||
userIds = maintenance.assigned_users.split(',').map(id => id.trim()).filter(Boolean);
|
userIds = maintenance.assigned_users.split(',').map(id => id.trim()).filter(Boolean);
|
||||||
console.log("Split assigned_users by comma:", userIds);
|
|
||||||
} else {
|
} else {
|
||||||
// Single ID
|
// Single ID
|
||||||
userIds = [maintenance.assigned_users];
|
userIds = [maintenance.assigned_users];
|
||||||
console.log("Using string as single ID:", userIds);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,20 +95,15 @@ export const MaintenanceDetailContent = ({
|
|||||||
cleanId = cleanId.replace(/[\[\]"'\\]/g, '');
|
cleanId = cleanId.replace(/[\[\]"'\\]/g, '');
|
||||||
return cleanId;
|
return cleanId;
|
||||||
}).filter(Boolean);
|
}).filter(Boolean);
|
||||||
|
|
||||||
console.log("Cleaned user IDs:", userIds);
|
|
||||||
|
|
||||||
// Step 3: Find matching users from the users array
|
// Step 3: Find matching users from the users array
|
||||||
if (userIds.length > 0) {
|
if (userIds.length > 0) {
|
||||||
const matchedUsers = users.filter(user => userIds.includes(user.id));
|
const matchedUsers = users.filter(user => userIds.includes(user.id));
|
||||||
console.log("Matched assigned users:", matchedUsers);
|
|
||||||
setAssignedUsers(matchedUsers);
|
setAssignedUsers(matchedUsers);
|
||||||
} else {
|
} else {
|
||||||
console.log("No user IDs found in assigned_users");
|
|
||||||
setAssignedUsers([]);
|
setAssignedUsers([]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("No assigned users found in maintenance data");
|
|
||||||
setAssignedUsers([]);
|
setAssignedUsers([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,24 +121,15 @@ export const MaintenanceDetailContent = ({
|
|||||||
const channelId = maintenance.notification_channel_id || maintenance.notification_id;
|
const channelId = maintenance.notification_channel_id || maintenance.notification_id;
|
||||||
|
|
||||||
if (channelId && notificationChannels.length > 0) {
|
if (channelId && notificationChannels.length > 0) {
|
||||||
console.log("Looking for notification channel with ID:", channelId);
|
|
||||||
console.log("Available notification channels:", notificationChannels.map(c => ({ id: c.id, name: c.notify_name })));
|
|
||||||
|
|
||||||
const channel = notificationChannels.find(ch => ch.id === channelId);
|
const channel = notificationChannels.find(ch => ch.id === channelId);
|
||||||
if (channel) {
|
if (channel) {
|
||||||
console.log("Found notification channel:", channel);
|
|
||||||
enhancedMaintenance.notification_channel_name = `${channel.notify_name} (${channel.notification_type})`;
|
enhancedMaintenance.notification_channel_name = `${channel.notify_name} (${channel.notification_type})`;
|
||||||
} else {
|
} else {
|
||||||
console.log("No matching notification channel found for ID:", channelId);
|
|
||||||
enhancedMaintenance.notification_channel_name = `Channel ID: ${channelId}`;
|
enhancedMaintenance.notification_channel_name = `Channel ID: ${channelId}`;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
console.log("No channel ID available or no notification channels loaded");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Enhanced maintenance with details:", enhancedMaintenance);
|
|
||||||
console.log("Assigned users for display:", assignedUsers);
|
|
||||||
setMaintenanceWithDetails(enhancedMaintenance);
|
setMaintenanceWithDetails(enhancedMaintenance);
|
||||||
}
|
}
|
||||||
}, [maintenance, users, notificationChannels]);
|
}, [maintenance, users, notificationChannels]);
|
||||||
@@ -173,4 +147,4 @@ export const MaintenanceDetailContent = ({
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -13,14 +13,7 @@ const CACHE_EXPIRY_MS = 600000; // 10 minutes cache expiry (increased significan
|
|||||||
*/
|
*/
|
||||||
export const isCacheValid = (): boolean => {
|
export const isCacheValid = (): boolean => {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const isValid = !!(cachedMaintenanceRecords && now - lastFetchTimestamp < CACHE_EXPIRY_MS);
|
return !!(cachedMaintenanceRecords && now - lastFetchTimestamp < CACHE_EXPIRY_MS);
|
||||||
|
|
||||||
// Minimal logging to reduce console spam
|
|
||||||
if (isValid) {
|
|
||||||
console.log("Using cached maintenance data");
|
|
||||||
}
|
|
||||||
|
|
||||||
return isValid;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +21,6 @@ export const isCacheValid = (): boolean => {
|
|||||||
*/
|
*/
|
||||||
export const getCachedRecords = () => {
|
export const getCachedRecords = () => {
|
||||||
if (cachedMaintenanceRecords) {
|
if (cachedMaintenanceRecords) {
|
||||||
console.log("Returning cached maintenance records:", cachedMaintenanceRecords.length);
|
|
||||||
return [...cachedMaintenanceRecords]; // Return a copy to prevent mutation
|
return [...cachedMaintenanceRecords]; // Return a copy to prevent mutation
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -40,7 +32,6 @@ export const getCachedRecords = () => {
|
|||||||
export const updateCache = (data: MaintenanceItem[], timestamp?: number): void => {
|
export const updateCache = (data: MaintenanceItem[], timestamp?: number): void => {
|
||||||
cachedMaintenanceRecords = data;
|
cachedMaintenanceRecords = data;
|
||||||
lastFetchTimestamp = timestamp || Date.now();
|
lastFetchTimestamp = timestamp || Date.now();
|
||||||
console.log("Maintenance cache updated with", data.length, "records");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,7 +40,6 @@ export const updateCache = (data: MaintenanceItem[], timestamp?: number): void =
|
|||||||
export const clearCache = (): void => {
|
export const clearCache = (): void => {
|
||||||
cachedMaintenanceRecords = null;
|
cachedMaintenanceRecords = null;
|
||||||
lastFetchTimestamp = 0;
|
lastFetchTimestamp = 0;
|
||||||
console.log("Maintenance cache cleared");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ export const fetchAllMaintenanceRecords = async (forceRefresh = false): Promise<
|
|||||||
// If forced refresh, clear cache first
|
// If forced refresh, clear cache first
|
||||||
if (forceRefresh) {
|
if (forceRefresh) {
|
||||||
clearCache();
|
clearCache();
|
||||||
console.log('Cache cleared for forced refresh');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return cached data if available and not forced refresh
|
// Return cached data if available and not forced refresh
|
||||||
@@ -29,14 +28,12 @@ export const fetchAllMaintenanceRecords = async (forceRefresh = false): Promise<
|
|||||||
|
|
||||||
// Request deduplication: if a request is already in progress, wait for it
|
// Request deduplication: if a request is already in progress, wait for it
|
||||||
if (currentRequest) {
|
if (currentRequest) {
|
||||||
console.log('Request already in progress, waiting for completion');
|
|
||||||
return await currentRequest;
|
return await currentRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strict rate limiting - prevent requests too close together (unless forced)
|
// Strict rate limiting - prevent requests too close together (unless forced)
|
||||||
const timeSinceLastRequest = now - lastRequestTime;
|
const timeSinceLastRequest = now - lastRequestTime;
|
||||||
if (timeSinceLastRequest < MIN_REQUEST_INTERVAL && !forceRefresh) {
|
if (timeSinceLastRequest < MIN_REQUEST_INTERVAL && !forceRefresh) {
|
||||||
console.log(`Rate limiting: ${Math.round((MIN_REQUEST_INTERVAL - timeSinceLastRequest) / 1000)}s remaining`);
|
|
||||||
return getCachedRecords() || [];
|
return getCachedRecords() || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,8 +63,6 @@ export const fetchAllMaintenanceRecords = async (forceRefresh = false): Promise<
|
|||||||
* Perform the actual API request
|
* Perform the actual API request
|
||||||
*/
|
*/
|
||||||
const performRequest = async (timestamp: number): Promise<MaintenanceItem[]> => {
|
const performRequest = async (timestamp: number): Promise<MaintenanceItem[]> => {
|
||||||
console.log('Making API request for maintenance records...');
|
|
||||||
|
|
||||||
// Create abort controller for request timeout
|
// Create abort controller for request timeout
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout
|
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout
|
||||||
@@ -95,7 +90,6 @@ const performRequest = async (timestamp: number): Promise<MaintenanceItem[]> =>
|
|||||||
// Update cache
|
// Update cache
|
||||||
updateCache(normalizedData, timestamp);
|
updateCache(normalizedData, timestamp);
|
||||||
|
|
||||||
console.log(`Successfully fetched ${normalizedData.length} maintenance records`);
|
|
||||||
return normalizedData;
|
return normalizedData;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -61,14 +61,12 @@ const getCompletedMaintenance = async (): Promise<MaintenanceItem[]> => {
|
|||||||
const createMaintenance = async (data: CreateMaintenanceInput): Promise<void> => {
|
const createMaintenance = async (data: CreateMaintenanceInput): Promise<void> => {
|
||||||
await createMaintenanceRecord(data);
|
await createMaintenanceRecord(data);
|
||||||
clearMaintenanceCache(); // Force cache refresh after creation
|
clearMaintenanceCache(); // Force cache refresh after creation
|
||||||
console.log('Maintenance created and cache cleared');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update an existing maintenance record
|
// Update an existing maintenance record
|
||||||
const updateMaintenanceRecord = async (id: string, data: Partial<MaintenanceItem>): Promise<void> => {
|
const updateMaintenanceRecord = async (id: string, data: Partial<MaintenanceItem>): Promise<void> => {
|
||||||
await updateMaintenance(id, data);
|
await updateMaintenance(id, data);
|
||||||
clearMaintenanceCache(); // Force cache refresh after update
|
clearMaintenanceCache(); // Force cache refresh after update
|
||||||
console.log('Maintenance updated and cache cleared');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Refresh cache manually
|
// Refresh cache manually
|
||||||
|
|||||||
Reference in New Issue
Block a user