# Order Status Synchronization - Solution Documentation

## Problem Statement

Orders were getting stuck in `pending_new` status indefinitely, causing stale data in the dashboard. This happened because:

1. **One-way data flow**: Bot → Database (no sync back)
2. **No status updates on fill**: When orders were filled, the database was never updated
3. **No background reconciliation**: No periodic check to sync actual order statuses from the exchange

## Solution Overview

We implemented a **three-layer solution** to handle stale order statuses:

### 1. Immediate Updates (Real-time Fix)
**Files Modified:**
- `src/services/TradeExecutor.ts`

**Changes:**
- Added `updateOrderStatus()` call when orders are **filled** (previously only called on cancel/reject)
- Added status update for both entry and exit orders
- Ensures database is updated immediately when order status changes

```typescript
// After order is verified as filled
supabaseService.updateOrderStatus?.(order.id, verifiedOrder.status || 'filled', new Date());
```

### 2. Background Sync Service (Periodic Reconciliation)
**Files Created:**
- `src/services/OrderStatusSyncService.ts`

**Files Modified:**
- `src/services/SupabaseService.ts` - Added `getStaleOrders()` method
- `src/index.ts` - Integrated sync service into main bot

**How it works:**
1. Runs every **5 minutes** in the background
2. Queries database for orders in `pending_new` status older than 5 minutes
3. Checks actual status on the exchange via `exchange.getOrder()`
4. Updates database with real status
5. Marks very old orders (>24h) as `unknown` if not found on exchange

**Key Features:**
- Non-blocking (runs in background)
- Handles up to 100 stale orders per sync
- Graceful error handling
- Detailed logging for monitoring

### 3. Visual Indicators (User Awareness)
**Files Modified:**
- `src/tabs/PositionsTab.tsx` (Dashboard)

**Features:**
- **Warning banner** at top when stale orders detected
- **Yellow badge** on individual stale orders (>5 min old)
- **Warning icon** (⚠️) next to stale order status
- Real-time age calculation

## Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                     Trading Bot Flow                         │
└─────────────────────────────────────────────────────────────┘

1. Order Placed
   ↓
2. TradeExecutor.openPosition()
   ↓
3. waitForFill() - Poll exchange for status
   ↓
4. ✅ NEW: updateOrderStatus() - Update DB immediately
   ↓
5. Track position locally

┌─────────────────────────────────────────────────────────────┐
│                Background Sync Service                       │
└─────────────────────────────────────────────────────────────┘

Every 5 minutes:
1. Query DB for pending_new orders > 5 min old
   ↓
2. For each order:
   - Check exchange.getOrder()
   - Get actual status
   - Update DB
   ↓
3. Mark >24h orders as 'unknown' if not found

┌─────────────────────────────────────────────────────────────┐
│                    Dashboard Display                         │
└─────────────────────────────────────────────────────────────┘

1. Fetch orders from DB
   ↓
2. Calculate age for each order
   ↓
3. Detect stale orders (pending_new > 5 min)
   ↓
4. Show warning banner + visual indicators
```

## Database Schema Assumptions

The solution assumes the `orders` table has:
- `id` or `order_id` - Primary key
- `status` - Order status (pending_new, filled, canceled, etc.)
- `created_at` - Timestamp when order was created
- `updated_at` - Timestamp of last update
- `filled_at` - Timestamp when order was filled (optional)

## Configuration

### Sync Interval
Default: **5 minutes**

To change, modify in `src/index.ts`:
```typescript
const orderSyncService = new OrderStatusSyncService(
    dataExchange, 
    10 * 60 * 1000  // 10 minutes
);
```

### Stale Threshold
Default: **5 minutes**

To change, modify in `src/services/SupabaseService.ts`:
```typescript
async getStaleOrders(staleThresholdMinutes: number = 10) // 10 minutes
```

## Manual Cleanup

For one-time cleanup of very old stale orders:

```bash
# Run the cleanup script
npm run cleanup-stale-orders
```

This will mark all orders >24 hours old in `pending_new` status as `unknown`.

## Monitoring & Logs

Look for these log messages:

### Successful Sync
```
[OrderSync] Found 5 stale orders to check
[OrderSync] Updating order abc123: pending_new → filled
[OrderSync] Sync complete: 5 updated, 0 not found on exchange, 0 failed
```

### No Stale Orders
```
[OrderSync] No stale orders found
```

### Errors
```
[OrderSync] Failed to sync order abc123: Order not found on exchange
[Supabase] Error fetching stale orders: <error message>
```

## Testing

### Test Immediate Updates
1. Place a new order via the bot
2. Check database - should see `pending_new` initially
3. Wait for order to fill (~3-30 seconds)
4. Check database - should see `filled` status

### Test Background Sync
1. Manually set an order to `pending_new` in DB (that's actually filled)
2. Wait 5 minutes
3. Check logs for sync activity
4. Verify order status updated to `filled`

### Test Dashboard Indicators
1. Create a stale order (pending_new > 5 min)
2. Open dashboard
3. Should see:
   - Yellow warning banner at top
   - Yellow badge on the order
   - ⚠️ icon next to status

## Troubleshooting

### Orders still showing as pending_new after sync

**Possible causes:**
1. Exchange doesn't support `getOrder()` API
2. Order ID mismatch between bot and exchange
3. Supabase credentials not configured

**Solution:**
- Check logs for specific error messages
- Verify exchange connector implements `getOrder()`
- Confirm order IDs match between systems

### Sync service not running

**Check:**
```bash
# Look for this in logs on bot startup:
[OrderSync] Background order status sync service started
```

**If missing:**
- Verify `OrderStatusSyncService` is imported in `index.ts`
- Check for startup errors

### Database not updating

**Possible causes:**
1. Supabase credentials missing/invalid
2. Table permissions issue
3. Field name mismatch (`id` vs `order_id`)

**Solution:**
- Check Supabase connection logs
- Verify table has both `id` and `order_id` columns (or update code)
- Test with manual query

## Performance Considerations

- **Sync batch size**: Limited to 100 orders per sync to avoid overload
- **Sync frequency**: 5 minutes balances freshness vs API rate limits
- **Exchange API calls**: One call per stale order (consider rate limits)

## Future Enhancements

1. **WebSocket status updates** - Real-time order status from exchange
2. **Retry logic** - Exponential backoff for failed syncs
3. **Metrics dashboard** - Track sync success rate, stale order trends
4. **Alert on persistent stale orders** - Notify if orders stay stale >1 hour
5. **Bulk status check** - If exchange supports batch order queries

## Related Files

### Core Implementation
- `src/services/TradeExecutor.ts` - Immediate status updates
- `src/services/OrderStatusSyncService.ts` - Background sync
- `src/services/SupabaseService.ts` - Database queries
- `src/index.ts` - Service initialization

### Dashboard
- `src/tabs/PositionsTab.tsx` - Visual indicators

### Utilities
- `src/scripts/cleanupStaleOrders.ts` - Manual cleanup

## Summary

This solution ensures order statuses are **always accurate** through:
1. ✅ **Immediate updates** when orders fill
2. ✅ **Background reconciliation** every 5 minutes
3. ✅ **Visual warnings** for users when stale data detected
4. ✅ **Manual cleanup** tools for maintenance

**Result:** No more stale `pending_new` orders! 🎉
