# Cache Debugging Guide

## Quick Diagnosis Checklist

### Symptom: Stale Data Showing in UI

**Quick Checks:**
1. ✅ Is React Query DevTools showing the query?
2. ✅ What's the `dataUpdatedAt` timestamp?
3. ✅ Are there any failed network requests in browser DevTools?
4. ✅ Is the cache key correct for the data you're expecting?

**Common Causes:**
- Cache not being invalidated after mutation
- Wrong cache key being used
- Realtime subscription not connected
- Optimistic update not rolled back on error

### Symptom: Data Loads Slowly

**Quick Checks:**
1. ✅ Check cache hit/miss in React Query DevTools
2. ✅ Look for duplicate queries with same key
3. ✅ Check if `staleTime` is too short
4. ✅ Verify network tab for slow API calls

**Common Causes:**
- Cache misses due to incorrect keys
- Too aggressive invalidation
- Missing cache-first strategies
- No prefetching for predictable navigation

### Symptom: Data Not Updating After Mutation

**Quick Checks:**
1. ✅ Check if mutation `onSuccess` is firing
2. ✅ Verify correct invalidation helper called
3. ✅ Check React Query DevTools for query state
4. ✅ Look for JavaScript errors in console

**Common Causes:**
- Missing cache invalidation in mutation
- Wrong query key in invalidation
- Error in mutation preventing `onSuccess`
- Realtime subscription overwriting changes

## Using React Query DevTools

### Installation Check
```typescript
// Already installed in src/App.tsx
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

// In development, you'll see floating React Query icon in bottom-right
```

### Key Features

#### 1. Query Explorer
- See all active queries and their states
- Check `status`: `'success'`, `'error'`, `'pending'`
- View `dataUpdatedAt` to see when data was last fetched
- Inspect `staleTime` and `cacheTime` settings

#### 2. Query Details
Click on any query to see:
- **Data**: The actual cached data
- **Query Key**: The exact key used (useful for debugging invalidation)
- **Observers**: How many components are using this query
- **Last Updated**: Timestamp of last successful fetch

#### 3. Mutations Tab
- See all recent mutations
- Check success/error states
- View mutation variables
- Inspect error messages

### Debugging Workflow

```mermaid
graph TD
    A[Issue Reported] --> B{Data Stale?}
    B -->|Yes| C[Open DevTools]
    C --> D[Find Query by Key]
    D --> E{Query Exists?}
    E -->|No| F[Check Component Using Correct Key]
    E -->|Yes| G{Data Correct?}
    G -->|Yes| H[Check dataUpdatedAt Timestamp]
    G -->|No| I[Check Last Mutation]
    I --> J{Mutation Succeeded?}
    J -->|Yes| K[Check Invalidation Called]
    J -->|No| L[Check Error in Mutations Tab]
    K --> M{Correct Keys Invalidated?}
    M -->|No| N[Fix Invalidation Keys]
    M -->|Yes| O[Check Realtime Subscription]
```

## Common Issues & Solutions

### Issue 1: Profile Data Not Updating

**Symptoms:**
- Changed profile but old data still showing
- Avatar or display name stuck on old value

**Debug Steps:**
```typescript
// 1. Open DevTools, find query
['profile', userId]

// 2. Check mutation hook
useProfileUpdateMutation()

// 3. Verify invalidation in onSuccess
invalidateUserProfile(userId);
invalidateProfileStats(userId);
invalidateProfileActivity(userId);
```

**Solution:**
```typescript
// Make sure all profile queries invalidated
onSuccess: (_data, { userId }) => {
  invalidateUserProfile(userId);
  invalidateProfileStats(userId);
  invalidateProfileActivity(userId);
  // If username changed, also invalidate search
  if (updates.username) {
    invalidateUserSearch();
  }
}
```

### Issue 2: List Not Refreshing After Create/Update

**Symptoms:**
- Created new park/ride but not in list
- Edited entity but changes not showing in list

**Debug Steps:**
```typescript
// 1. Check what queries are active for list
['parks'] // All parks
['parks', 'owner', ownerSlug] // Owner's parks
['parks', parkSlug, 'rides'] // Park's rides

// 2. Verify mutation invalidates list
onSuccess: () => {
  invalidateParks(); // Global lists
  invalidateParkDetail(parkSlug); // Specific park
  invalidateHomepage(); // Recent changes
}
```

**Solution:**
```typescript
// Invalidate ALL affected lists
onSuccess: () => {
  invalidateParks();              // Global list
  invalidateParkRides(parkSlug);  // Park's rides list
  invalidateRideDetail(rideSlug); // Detail page
  invalidateHomepage();           // Homepage feed
}
```

### Issue 3: Realtime Not Working

**Symptoms:**
- Changes by other users not appearing
- Manual refresh required to see updates

**Debug Steps:**
```typescript
// 1. Check browser console for subscription errors
// Look for: "Realtime subscription error"

// 2. Check useRealtimeSubscriptions hook
// Verify subscription is active

// 3. Check Supabase dashboard for realtime status
```

**Solution:**
```typescript
// Check table has realtime enabled in Supabase
// Verify RLS policies allow SELECT
// Ensure subscription filters match your queries

// In useRealtimeSubscriptions.ts:
channel
  .on('postgres_changes', 
    { 
      event: '*', 
      schema: 'public', 
      table: 'parks' // Correct table name
    },
    (payload) => {
      // Invalidation happens here
    }
  )
```

### Issue 4: Optimistic Update Not Rolling Back

**Symptoms:**
- UI shows change but it failed
- Error toast shown but UI not reverted

**Debug Steps:**
```typescript
// 1. Check mutation has onError handler
onError: (error, variables, context) => {
  // Should rollback here
}

// 2. Check context has previousData
onMutate: async (variables) => {
  const previousData = queryClient.getQueryData(queryKey);
  return { previousData }; // Must return this
}

// 3. Check rollback logic
if (context?.previousData) {
  queryClient.setQueryData(queryKey, context.previousData);
}
```

**Solution:**
```typescript
export function useMyMutation() {
  return useMutation({
    mutationFn: async (data) => { /* ... */ },
    onMutate: async (variables) => {
      // Cancel outgoing queries
      await queryClient.cancelQueries({ queryKey });
      
      // Get previous data
      const previousData = queryClient.getQueryData(queryKey);
      
      // Optimistically update
      queryClient.setQueryData(queryKey, newData);
      
      // MUST return previous data
      return { previousData };
    },
    onError: (error, variables, context) => {
      // Rollback using context
      if (context?.previousData) {
        queryClient.setQueryData(queryKey, context.previousData);
      }
      toast.error("Failed", { description: getErrorMessage(error) });
    }
  });
}
```

### Issue 5: Queries Firing Too Often

**Symptoms:**
- Too many network requests
- Poor performance
- Rate limiting errors

**Debug Steps:**
```typescript
// 1. Check staleTime setting
useQuery({
  queryKey,
  queryFn,
  staleTime: 1000 * 60 * 5 // 5 minutes - good
  // staleTime: 0 // BAD - refetches constantly
})

// 2. Check for duplicate queries
// Open DevTools, look for same key multiple times

// 3. Check refetchOnWindowFocus
useQuery({
  queryKey,
  queryFn,
  refetchOnWindowFocus: false // Disable if not needed
})
```

**Solution:**
```typescript
// Set appropriate staleTime
Profile data:     5 minutes
List data:        2 minutes  
Static data:      10 minutes
Real-time data:   30 seconds

// Example:
useQuery({
  queryKey: ['profile', userId],
  queryFn: fetchProfile,
  staleTime: 1000 * 60 * 5, // 5 minutes
  refetchOnWindowFocus: true, // Good for user data
})
```

## Cache Monitoring Tools

### Built-in Monitoring

**File**: `src/lib/cacheMonitoring.ts`

```typescript
import { cacheMonitor } from '@/lib/cacheMonitoring';

// Start monitoring
cacheMonitor.start();

// Get metrics
const metrics = cacheMonitor.getMetrics();
console.log('Cache hit rate:', metrics.hitRate);
console.log('Avg query time:', metrics.avgQueryTime);

// Log slow queries
cacheMonitor.onSlowQuery((queryKey, duration) => {
  console.warn('Slow query:', queryKey, duration);
});
```

### Manual Cache Inspection

```typescript
import { useQueryClient } from '@tanstack/react-query';

function DebugComponent() {
  const queryClient = useQueryClient();
  
  // Get all queries
  const queries = queryClient.getQueryCache().getAll();
  console.log('Active queries:', queries.length);
  
  // Get specific query data
  const profileData = queryClient.getQueryData(['profile', userId]);
  console.log('Profile data:', profileData);
  
  // Check query state
  const query = queryClient.getQueryState(['profile', userId]);
  console.log('Query state:', query?.status);
  console.log('Data updated at:', query?.dataUpdatedAt);
  
  return null;
}
```

## Advanced Debugging Techniques

### 1. Network Tab Analysis

**Chrome DevTools → Network Tab**

Look for:
- Duplicate requests to same endpoint
- Slow API responses (>500ms)
- Failed requests (4xx, 5xx errors)
- Request timing (waiting, download time)

Filter by:
- `supabase` - See all Supabase calls
- `rpc` - See database function calls
- `rest` - See table queries

### 2. Console Logging

```typescript
// Add temporary logging to mutation
onSuccess: (data, variables) => {
  console.group('Mutation Success');
  console.log('Data:', data);
  console.log('Variables:', variables);
  console.log('Invalidating:', ['profile', variables.userId]);
  console.groupEnd();
  
  // Your invalidation code
}
```

### 3. React DevTools Profiler

1. Open React DevTools
2. Go to Profiler tab
3. Click record
4. Perform action
5. Stop recording
6. Analyze which components re-rendered

Look for:
- Unnecessary re-renders
- Slow components (>16ms)
- Deep component trees

### 4. Performance Monitoring

```typescript
// Add performance marks
performance.mark('query-start');
const data = await queryFn();
performance.mark('query-end');
performance.measure('query', 'query-start', 'query-end');

// Log slow queries
const entries = performance.getEntriesByName('query');
entries.forEach(entry => {
  if (entry.duration > 500) {
    console.warn('Slow query:', entry.duration);
  }
});
```

## Preventive Measures

### Code Review Checklist

When adding new mutations:
- [ ] Has proper `onSuccess` with invalidation
- [ ] Has `onError` with rollback
- [ ] Uses `onMutate` for optimistic updates (if applicable)
- [ ] Invalidates all affected queries
- [ ] Uses centralized invalidation helpers
- [ ] Has proper TypeScript types
- [ ] Includes error handling with toast

When adding new queries:
- [ ] Uses proper query key from `queryKeys.ts`
- [ ] Has appropriate `staleTime`
- [ ] Has `enabled` flag if conditional
- [ ] Returns typed data
- [ ] Handles loading and error states

### Testing Strategy

```typescript
// Test cache invalidation
it('should invalidate cache after mutation', async () => {
  const { result } = renderHook(() => useProfileUpdateMutation());
  const queryClient = new QueryClient();
  
  // Spy on invalidation
  const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries');
  
  await result.current.mutateAsync({ userId, updates });
  
  expect(invalidateSpy).toHaveBeenCalledWith({ 
    queryKey: ['profile', userId] 
  });
});
```

## When to Ask for Help

If you've tried the above and still have issues:

1. **Gather information:**
   - React Query DevTools screenshots
   - Network tab screenshots
   - Console error messages
   - Steps to reproduce

2. **Check documentation:**
   - [API_PATTERNS.md](./API_PATTERNS.md)
   - [CACHE_INVALIDATION_GUIDE.md](./CACHE_INVALIDATION_GUIDE.md)
   - [PRODUCTION_READY.md](./PRODUCTION_READY.md)

3. **Create issue with:**
   - Clear description
   - Expected vs actual behavior
   - Debugging steps already tried
   - Relevant code snippets

---

## Quick Reference

### Essential Tools
- React Query DevTools: Visual query inspector
- Browser Network Tab: API call monitoring  
- Console Logging: Quick debugging
- `cacheMonitoring.ts`: Performance metrics

### Common Commands
```typescript
// Manually invalidate
queryClient.invalidateQueries({ queryKey: ['profile'] });

// Manually refetch
queryClient.refetchQueries({ queryKey: ['profile'] });

// Clear cache
queryClient.clear();

// Get cache data
queryClient.getQueryData(['profile', userId]);
```

### Debug Mode
```typescript
// Enable React Query debugging
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

// Always show (not just in dev)
<ReactQueryDevtools initialIsOpen={false} buttonPosition="bottom-right" />
```
