#!/usr/bin/env python3 """ Fix processor_results statistics (frames_processed, output_size_bytes) for all jobs that have missing data due to Worker crash. """ import os import sys import re import psycopg2 def fix_processor_stats(): conn = psycopg2.connect(os.environ.get('DATABASE_URL', 'postgres://accusys@localhost:5432/momentry')) cur = conn.cursor() # Find jobs with missing frames_processed cur.execute(""" SELECT DISTINCT mj.uuid, mj.id FROM public.monitor_jobs mj JOIN public.processor_results pr ON pr.job_id = mj.id WHERE pr.frames_processed = 0 AND pr.status = 'completed' ORDER BY mj.created_at DESC """) jobs = cur.fetchall() print(f"Found {len(jobs)} jobs with missing statistics") for uuid, job_id in jobs: print(f"\nProcessing UUID: {uuid}") # Get total_frames from YOLO output yolo_file = f'/Users/accusys/momentry/output/{uuid}.yolo.json' total_frames = 0 if os.path.exists(yolo_file): with open(yolo_file, 'r') as f: content = f.read(5000) match = re.search(r'"total_frames": (\d+)', content) if match: total_frames = int(match.group(1)) print(f" total_frames: {total_frames}") if total_frames > 0: # Update frames_processed cur.execute(""" UPDATE public.processor_results SET frames_processed = %s WHERE job_id = %s """, (total_frames, job_id)) # Update output_size_bytes for each processor processors = ['asr', 'yolo', 'face', 'ocr', 'pose', 'cut', 'appearance', 'asrx'] for proc in processors: file_path = f'/Users/accusys/momentry/output/{uuid}.{proc}.json' if os.path.exists(file_path): size = os.path.getsize(file_path) cur.execute(""" UPDATE public.processor_results SET output_size_bytes = %s WHERE job_id = %s AND processor_type = %s """, (size, job_id, proc)) print(f" {proc}: {size} bytes") conn.commit() print(f" ✓ Updated") else: print(f" ⚠ Skipped (no total_frames)") conn.close() print(f"\nCompleted: {len(jobs)} jobs processed") if __name__ == '__main__': fix_processor_stats()