mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-22 07:31:12 -05:00
feat: Implement Phase 5 optimization and best practices
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
import { useEffect, useRef, useState, useCallback } from 'react';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import { logger } from '@/lib/logger';
|
||||
import { MODERATION_CONSTANTS } from '@/lib/moderation/constants';
|
||||
import type { RealtimeChannel } from '@supabase/supabase-js';
|
||||
import type { ModerationItem, EntityFilter, StatusFilter } from '@/types/moderation';
|
||||
import type { useEntityCache } from './useEntityCache';
|
||||
@@ -47,7 +49,7 @@ export interface RealtimeSubscriptionConfig {
|
||||
/** Pause subscriptions when tab is hidden (default: true) */
|
||||
pauseWhenHidden?: boolean;
|
||||
|
||||
/** Debounce delay for UPDATE events in milliseconds (default: 500) */
|
||||
/** Debounce delay for UPDATE events in milliseconds */
|
||||
debounceMs?: number;
|
||||
|
||||
/** Entity cache for resolving entity names */
|
||||
@@ -95,7 +97,7 @@ export function useRealtimeSubscriptions(
|
||||
onUpdateItem,
|
||||
onItemRemoved,
|
||||
pauseWhenHidden = true,
|
||||
debounceMs = 500,
|
||||
debounceMs = MODERATION_CONSTANTS.REALTIME_DEBOUNCE_MS,
|
||||
entityCache,
|
||||
profileCache,
|
||||
recentlyRemovedIds,
|
||||
@@ -151,7 +153,7 @@ export function useRealtimeSubscriptions(
|
||||
.single();
|
||||
|
||||
if (error || !submission) {
|
||||
console.error('Error fetching submission details:', error);
|
||||
logger.error('Error fetching submission details:', error);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -243,17 +245,17 @@ export function useRealtimeSubscriptions(
|
||||
const handleInsert = useCallback(async (payload: any) => {
|
||||
const newSubmission = payload.new as any;
|
||||
|
||||
console.log('🆕 Realtime INSERT:', newSubmission.id);
|
||||
logger.log('🆕 Realtime INSERT:', newSubmission.id);
|
||||
|
||||
// Queue updates if tab is hidden
|
||||
if (pauseWhenHidden && document.hidden) {
|
||||
console.log('📴 Realtime event received while hidden - queuing for later');
|
||||
logger.log('📴 Realtime event received while hidden - queuing for later');
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore if recently removed (optimistic update)
|
||||
if (recentlyRemovedIds.has(newSubmission.id)) {
|
||||
console.log('⏭️ Ignoring INSERT for recently removed submission:', newSubmission.id);
|
||||
logger.log('⏭️ Ignoring INSERT for recently removed submission:', newSubmission.id);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -271,7 +273,7 @@ export function useRealtimeSubscriptions(
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('✅ NEW submission matches filters, invalidating query:', newSubmission.id);
|
||||
logger.log('✅ NEW submission matches filters, invalidating query:', newSubmission.id);
|
||||
|
||||
// Invalidate the query to trigger background refetch
|
||||
await queryClient.invalidateQueries({ queryKey: ['moderation-queue'] });
|
||||
@@ -296,7 +298,7 @@ export function useRealtimeSubscriptions(
|
||||
|
||||
onNewItem(fullItem);
|
||||
} catch (error) {
|
||||
console.error('Error building new item notification:', error);
|
||||
logger.error('Error building new item notification:', error);
|
||||
}
|
||||
}, [
|
||||
filters,
|
||||
@@ -316,23 +318,23 @@ export function useRealtimeSubscriptions(
|
||||
const updatedSubmission = payload.new as any;
|
||||
const oldSubmission = payload.old as any;
|
||||
|
||||
console.log('🔄 Realtime UPDATE:', updatedSubmission.id);
|
||||
logger.log('🔄 Realtime UPDATE:', updatedSubmission.id);
|
||||
|
||||
// Queue updates if tab is hidden
|
||||
if (pauseWhenHidden && document.hidden) {
|
||||
console.log('📴 Realtime UPDATE received while hidden - queuing for later');
|
||||
logger.log('📴 Realtime UPDATE received while hidden - queuing for later');
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore if recently removed (optimistic update in progress)
|
||||
if (recentlyRemovedIds.has(updatedSubmission.id)) {
|
||||
console.log('⏭️ Ignoring UPDATE for recently removed submission:', updatedSubmission.id);
|
||||
logger.log('⏭️ Ignoring UPDATE for recently removed submission:', updatedSubmission.id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore if currently being interacted with
|
||||
if (interactingWithIds.has(updatedSubmission.id)) {
|
||||
console.log('⏭️ Ignoring UPDATE for interacting submission:', updatedSubmission.id);
|
||||
logger.log('⏭️ Ignoring UPDATE for interacting submission:', updatedSubmission.id);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -340,7 +342,7 @@ export function useRealtimeSubscriptions(
|
||||
const isStatusChange = oldSubmission?.status !== updatedSubmission.status;
|
||||
|
||||
if (isStatusChange) {
|
||||
console.log('⚡ Status change detected, invalidating immediately');
|
||||
logger.log('⚡ Status change detected, invalidating immediately');
|
||||
await queryClient.invalidateQueries({ queryKey: ['moderation-queue'] });
|
||||
|
||||
const matchesEntity = matchesEntityFilter(updatedSubmission, filters.entityFilter);
|
||||
@@ -355,7 +357,7 @@ export function useRealtimeSubscriptions(
|
||||
|
||||
// Use debounce for non-critical updates
|
||||
debouncedUpdate(updatedSubmission.id, async () => {
|
||||
console.log('🔄 Invalidating query due to UPDATE:', updatedSubmission.id);
|
||||
logger.log('🔄 Invalidating query due to UPDATE:', updatedSubmission.id);
|
||||
|
||||
// Simply invalidate the query - TanStack Query handles the rest
|
||||
await queryClient.invalidateQueries({ queryKey: ['moderation-queue'] });
|
||||
@@ -388,7 +390,7 @@ export function useRealtimeSubscriptions(
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('📡 Setting up INSERT subscription');
|
||||
logger.log('📡 Setting up INSERT subscription');
|
||||
|
||||
const channel = supabase
|
||||
.channel('moderation-new-submissions')
|
||||
@@ -402,7 +404,7 @@ export function useRealtimeSubscriptions(
|
||||
handleInsert
|
||||
)
|
||||
.subscribe((status) => {
|
||||
console.log('INSERT subscription status:', status);
|
||||
logger.log('INSERT subscription status:', status);
|
||||
if (status === 'SUBSCRIBED') {
|
||||
setChannelStatus('connected');
|
||||
} else if (status === 'CHANNEL_ERROR') {
|
||||
@@ -413,7 +415,7 @@ export function useRealtimeSubscriptions(
|
||||
insertChannelRef.current = channel;
|
||||
|
||||
return () => {
|
||||
console.log('🛑 Cleaning up INSERT subscription');
|
||||
logger.log('🛑 Cleaning up INSERT subscription');
|
||||
supabase.removeChannel(channel);
|
||||
insertChannelRef.current = null;
|
||||
};
|
||||
@@ -425,7 +427,7 @@ export function useRealtimeSubscriptions(
|
||||
useEffect(() => {
|
||||
if (!enabled) return;
|
||||
|
||||
console.log('📡 Setting up UPDATE subscription');
|
||||
logger.log('📡 Setting up UPDATE subscription');
|
||||
|
||||
const channel = supabase
|
||||
.channel('moderation-updated-submissions')
|
||||
@@ -439,7 +441,7 @@ export function useRealtimeSubscriptions(
|
||||
handleUpdate
|
||||
)
|
||||
.subscribe((status) => {
|
||||
console.log('UPDATE subscription status:', status);
|
||||
logger.log('UPDATE subscription status:', status);
|
||||
if (status === 'SUBSCRIBED') {
|
||||
setChannelStatus('connected');
|
||||
} else if (status === 'CHANNEL_ERROR') {
|
||||
@@ -450,7 +452,7 @@ export function useRealtimeSubscriptions(
|
||||
updateChannelRef.current = channel;
|
||||
|
||||
return () => {
|
||||
console.log('🛑 Cleaning up UPDATE subscription');
|
||||
logger.log('🛑 Cleaning up UPDATE subscription');
|
||||
supabase.removeChannel(channel);
|
||||
updateChannelRef.current = null;
|
||||
};
|
||||
@@ -470,7 +472,7 @@ export function useRealtimeSubscriptions(
|
||||
* Manual reconnect function
|
||||
*/
|
||||
const reconnect = useCallback(() => {
|
||||
console.log('🔄 Manually reconnecting subscriptions...');
|
||||
logger.log('🔄 Manually reconnecting subscriptions...');
|
||||
setReconnectTrigger(prev => prev + 1);
|
||||
}, []);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user