From 3c7f4142aa75d2fafebab8aa612b7b83a8deee7d Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 31 Jan 2026 08:20:40 -0600 Subject: [PATCH] celery: add error logging for Sonauto API responses Also update CLAUDE.md to require commit+push after changes. Co-Authored-By: Claude Opus 4.5 --- CLAUDE.md | 169 ++++++++++++++++++++++----------------- backend/tasks/workers.py | 4 + 2 files changed, 100 insertions(+), 73 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index d3570e9..3886aee 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,96 +4,119 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Important: Read the Spec First -**At the start of every session, read the full specification document at `/documents/spec.md`.** This document contains the complete technical specification including API endpoints, database schema, background worker logic, and video generation details. Understanding the spec is essential before making any changes to this project. +**At the start of every session, read `/documents/spec.md`.** It contains the complete technical specification including API endpoints, database schema, background worker logic, and video generation details. ## Project Overview Valentine's Day 2026 AI-powered Pet Love Song Generator Microsite for Pets at Home. Users submit pet info, upload/crop a photo, and receive an AI-generated music video combining their pet photo with a custom song. -**Stack:** PHP (server-side rendering) + Alpine.js (reactive forms) + Cropper.js (image cropping) +**Stack:** PHP (server-side rendering) + Alpine.js (reactive forms) + Cropper.js (image cropping) | FastAPI + Celery + PostgreSQL + Redis (backend) ## Running the Project ```bash -# Start PHP development server +# Frontend (PHP) php -S localhost:8000 + +# Backend (Docker - recommended) +cd backend && docker compose up --build + +# Backend (local venv alternative) +cd backend +pip install -r requirements.txt +uvicorn app.main:app --host 0.0.0.0 --port 8000 + +# Run migrations (from backend/) +alembic upgrade head ``` -Access at `http://localhost:8000` +## Project Structure -## Architecture +``` +/ # PHP frontend pages +├── index.php # Form page (Alpine.js + Cropper.js) +├── waiting.php # Loading page with polling +├── result.php # Results UI with video player +├── header.php # Shared header +├── footer.php # Shared footer +├── assets/ +│ ├── js/home.js # Alpine.js form component + SessionManager +│ └── css/style.css # Complete styling +├── backend/ # FastAPI service +│ ├── app/ +│ │ ├── main.py # FastAPI app entry point +│ │ ├── routers/ # API endpoints (submissions, webhook, results, health) +│ │ ├── models.py # SQLAlchemy models +│ │ ├── schemas.py # Pydantic schemas +│ │ └── config.py # Settings +│ ├── tasks/ +│ │ ├── celery_app.py # Celery configuration + Beat schedule +│ │ └── workers.py # Background tasks +│ ├── video_generator/ # Video creation script +│ ├── alembic/ # Database migrations +│ └── docker-compose.yml +├── documents/ +│ └── spec.md # Full specification (1166 lines) +└── storage/ # Runtime outputs (uploads/audio/video) +``` -### Current State - -**Frontend (Partially Complete):** -- `index.php` - Form page with Alpine.js + Cropper.js (form submission implemented) -- `waiting.php` - Loading page with animation (polling NOT implemented) -- `result.php` - Results UI with rotating record (API integration NOT implemented) -- `header.php` / `footer.php` - Shared components -- `opengraph.php` - Open Graph and Twitter Card meta tags -- `assets/js/home.js` - Alpine.js form component + SessionManager module - -**Backend (Specification Only - Not Implemented):** -- Full API specification in `/documents/spec.md` (1166 lines) -- Requires: Database, API endpoints, background workers, Sonauto API integration, FFmpeg video generation - -### Data Flow +## Architecture & Data Flow 1. User submits form → POST `/api/submissions` → returns `session_id` -2. Background worker sends to Sonauto API for music generation -3. Sonauto webhook callback triggers audio download -4. Backend generates MP4 video with pet photo + audio +2. Celery Beat picks up pending submissions → sends to Sonauto API +3. Sonauto webhook callback → triggers Celery task chain +4. Task chain: fetch details → download audio → create video (FFmpeg) 5. Frontend polls `/api/submissions/{session_id}/status` until complete -6. Results page displays video with download/share options - -### Key External Dependencies - -- **Sonauto API** (`https://api.sonauto.ai/v1`) - AI music generation -- **Alpine.js v3.15.5** - Reactive form handling (loaded from CDN) -- **Cropper.js v1.6.2** - Client-side image cropping (loaded from CDN) -- **FFmpeg** - Video generation (backend requirement) - -## Frontend Patterns - -### Alpine.js Form Component (index.php + home.js) -```javascript -// Alpine.js component: petSongForm -// Three UI states for image: upload → crop → preview -// Cropper outputs 600×600px JPEG at 0.9 quality -// Base64 image stored in formData.photo -``` - -### Form Validation -- Pet name / Owner name: 2-100 chars, letters/spaces only -- Client-side: HTML5 attributes + JS input filter + Alpine.js validation -- Image: JPEG/PNG only, min 400×400px, max 5MB, cropped to 1:1 aspect ratio - -### Session Management (localStorage) -- Uses `SessionManager` module in `assets/js/home.js` -- Storage key: `submission_data` -- Stores: `{cookie_id, entries: [{session_id, timestamp}]}` -- Client-side rate limit check: 10 submissions max - -### Rate Limiting -- localStorage-based: 10 submissions per `cookie_id` -- Server also enforces limit per `cookie_id` -- 429 error should trigger "Sold Out" modal (needs implementation) - -## Backend Implementation Reference - -When implementing the backend, refer to `/documents/spec.md` for: -- Complete API endpoint specifications -- Database schema (17-column submissions table) -- Background worker logic (queue processor, credits monitor, timeout checker) -- Sonauto API integration details -- Video generation process with FFmpeg -- Error handling and retry logic - -### Required Endpoints -- `POST /api/submissions` - Create submission -- `GET /api/submissions/{session_id}/status` - Poll status -- `POST /api/webhook` - Sonauto callback -- `GET /api/results/{session_id}` - Fetch completed result +6. Results page displays video at `/api/results/{session_id}` ### Status Flow `pending` → `processing` → `success` / `fail` + +## Key Patterns + +### Frontend (Alpine.js) +- Form component `petSongForm` in `assets/js/home.js` +- `SessionManager` module handles localStorage (`submission_data` key) +- Image cropping: 600x600px JPEG at 0.9 quality +- Rate limiting: 10 submissions per `cookie_id` (client + server enforced) + +### Backend (Celery Tasks) +- `process_pending_queue`: runs every 60s, sends to Sonauto API +- `check_credits`: runs every 10min, caches in Redis +- `check_timeouts`: runs every 5min, marks stale submissions as failed +- `cleanup_old_files`: runs daily at 3 AM, deletes old files + +### Video Generation +- Uses FFmpeg, generates ~45 frames per rotation cycle +- Streams frames to FFmpeg (no temp files) +- Output: 720x720px MP4, 15fps, rotating vinyl record effect + +## External Dependencies + +- **Sonauto API** (`https://api.sonauto.ai/v1`) - AI music generation +- **FFmpeg** - Video generation (must be installed in Docker/system) + +## Environment Variables + +Copy `.env.example` to `.env` and configure: +```bash +SONAUTO_API_KEY=your_key_here +WEBHOOK_BASE_URL=https://your-domain.com +``` + +## Code Style + +- PHP/HTML: 4-space indentation, lowercase filenames +- JavaScript: 4-space indentation, semicolons +- Python: snake_case, Pydantic models, FastAPI routers in `backend/app/routers/` +- Commit style: short imperative subject, sometimes scoped (e.g., `result: add video poster`) + +## Workflow + +**Always commit and push changes immediately after making them.** Do not wait for the user to ask - after any code modification, commit with a descriptive message and push to remote. + +## Testing + +No automated test suite. Validate manually: +- Frontend: run PHP server, exercise form flow +- Backend: hit `/api/health`, simulate submission/status endpoints diff --git a/backend/tasks/workers.py b/backend/tasks/workers.py index 598ad2f..21f47d5 100644 --- a/backend/tasks/workers.py +++ b/backend/tasks/workers.py @@ -257,6 +257,10 @@ def send_to_sonauto(self, session_id: str): return {"task_id": data["task_id"]} except requests.RequestException as e: + # Log the error details for debugging + if hasattr(e, 'response') and e.response is not None: + logger.error(f"Sonauto API error for {session_id}: {e.response.status_code} - {e.response.text}") + logger.error(f"Payload sent: {payload}") submission.retry_count += 1 if submission.retry_count >= settings.MAX_RETRIES: submission.entry_status = "fail"