All Stories
7-6-2-cash-out-executionReadyEpic 7.6
Story 7.6.2: Cash Out Execution
Status: ready-for-dev
Tasks
- **Task 1: Implement CashOutExecutor Class** (AC: #1, #2, #3, #4, #5)
- 1.1: Create CashOutExecutor class in server/app/services/betting/cash_out_executor.py
- 1.2: Implement execute_cash_out method with all parameters (user_id, bet_id, accepted_value, offer_timestamp)
- 1.3: Add Redis lock acquisition with key pattern "cash_out_lock:{bet_id}", nx=True, ex=30
- 1.4: Implement bet ownership validation (bet.user_id == user_id)
- 1.5: Implement bet status validation (bet.status == BetStatus.PENDING)
- 1.6: Add offer expiry check (datetime.now() > offer_timestamp + 10 seconds)
- 1.7: Implement odds movement check using CashOutPricingEngine (5% tolerance)
- 1.8: Add try/finally block to ensure lock cleanup
- **Task 2: Implement Atomic Database Transaction** (AC: #2, #3)
- 2.1: Create database transaction using async with db.transaction()
- 2.2: Update bets table: SET status='cashed_out', settled_at=NOW(), cash_out_amount=$1
- 2.3: Add WHERE clause: WHERE id=$2 AND status='pending' for optimistic locking
- 2.4: Update users table: SET balance=balance+$1 WHERE id=$2
- 2.5: Insert transaction record with type='cash_out', description formatted string
- 2.6: Verify transaction rollback on any failure (test with database errors)
- **Task 3: Create CashOutResult Enum** (AC: #5)
- 3.1: Define CashOutResult enum with values: SUCCESS, EXPIRED, ODDS_CHANGED, ALREADY_SETTLED, ERROR
- 3.2: Create CashOutExecutionResult dataclass with fields: success, result, message, amount, new_balance, new_value
- 3.3: Map each failure scenario to appropriate CashOutResult value
- 3.4: Ensure user-friendly error messages for each result type
- **Task 4: Implement Redis Lock Pattern** (AC: #4)
- 4.1: Add lock acquisition with SET lock_key "1" NX EX 30
- 4.2: Check lock result - if False, return ERROR with "Cash out in progress"
- 4.3: Add finally block with redis.delete(lock_key) to ensure cleanup
- 4.4: Test race condition with concurrent cash out attempts on same bet
- 4.5: Verify lock expires after 30 seconds (test with time.sleep in dev)
- **Task 5: Add Agent SSE Notification** (AC: #6)
- 5.1: Create notify_agent_cash_out function in server/app/services/notifications/agent_notifications.py
- 5.2: Build notification payload with all required fields (type, bet_id, user_id, username, amount, profit_loss)
- 5.3: Publish notification to agent's SSE stream (agent_id from bet.user.agent_id)
- 5.4: Call notification after successful transaction commit
- 5.5: Test notification appears in agent dashboard activity feed
- **Task 6: Create API Endpoint** (AC: #1-6)
- 6.1: Add POST /api/v1/betting/cash-out/{bet_id}/execute endpoint
- 6.2: Create CashOutExecuteRequest Pydantic model (accepted_value, offer_timestamp)
- 6.3: Create CashOutExecuteResponse Pydantic model (success, result, message, amount, new_balance, new_value)
- 6.4: Implement endpoint handler calling CashOutExecutor.execute_cash_out
- 6.5: Add JWT authentication with get_current_user dependency
- 6.6: Map CashOutResult to HTTP status codes (200, 400, 409)
- 6.7: Add endpoint documentation with OpenAPI examples
- **Task 7: Add Database Schema Additions** (AC: #2, #3)
- 7.1: Add migration for bets table: ADD COLUMN cash_out_amount DECIMAL(10,2)
- 7.2: Verify transactions table supports type='cash_out' (check enum or text field)
- 7.3: Add index on bets(status) if not exists for performance
- 7.4: Test migration on local database
- 7.5: Document rollback procedure in migration file
- **Task 8: Integration Testing** (AC: #1-6)
- 8.1: Test successful cash out flow end-to-end
- 8.2: Test expired offer (offer_timestamp > 10 seconds ago)
- 8.3: Test odds changed >5% (mock pricing engine to return different value)
- 8.4: Test already settled bet (status != PENDING)
- 8.5: Test concurrent cash out attempts (race condition with Redis lock)
- 8.6: Test bet ownership validation (different user_id)
- 8.7: Test agent notification received via SSE
- 8.8: Verify balance updated correctly in database
- 8.9: Verify transaction record created with correct fields
- **Task 9: Error Logging & Monitoring** (AC: #5)
- 9.1: Add structured logging for all error scenarios with context
- 9.2: Log successful cash outs with amount and user info (info level)
- 9.3: Log lock acquisition failures (warn level)
- 9.4: Log database transaction failures (error level with full traceback)
- 9.5: Add metrics tracking for cash out success rate (future Prometheus integration)
Progress
Tasks0/9
Acceptance Criteria0
Total Tasks9