from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_login import LoginManager import os import threading import time import requests import json db = SQLAlchemy() login_manager = LoginManager() def create_app(): app = Flask(__name__) app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev-secret-key-change-in-production') app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL', 'sqlite:///testarena.db') app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) login_manager.init_app(app) login_manager.login_view = 'auth.login' from app.models import User @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) # Register blueprints from app.routes.auth import auth_bp from app.routes.admin import admin_bp from app.routes.dashboard import dashboard_bp from app.routes.jobs import jobs_bp from app.routes.api import api_bp app.register_blueprint(auth_bp) app.register_blueprint(admin_bp) app.register_blueprint(dashboard_bp) app.register_blueprint(jobs_bp) app.register_blueprint(api_bp) with app.app_context(): db.create_all() # Simple migration for Phase 2 columns with retry import time max_retries = 5 for i in range(max_retries): try: from sqlalchemy import text with db.engine.connect() as conn: # Check if remote_queue_id exists result = conn.execute(text("SELECT column_name FROM information_schema.columns WHERE table_name='jobs' AND column_name='remote_queue_id'")) if not result.fetchone(): print("Running Phase 2 migrations...") conn.execute(text("ALTER TABLE jobs ADD COLUMN remote_queue_id VARCHAR(50)")) conn.execute(text("ALTER TABLE jobs ADD COLUMN remote_task_ids TEXT")) conn.execute(text("ALTER TABLE jobs ADD COLUMN remote_results TEXT")) conn.execute(text("ALTER TABLE jobs ADD COLUMN queue_log TEXT")) conn.commit() print("Phase 2 migrations completed.") break # Success except Exception as e: print(f"Migration attempt {i+1} failed: {e}") if i < max_retries - 1: time.sleep(2) else: print("Migration failed after all retries.") # Create default admin user if not exists try: from app.models import User if not User.query.filter_by(username='admin').first(): admin = User(username='admin', is_admin=True) admin.set_password('admin123') db.session.add(admin) db.session.commit() except Exception as e: # Admin user might already exist, rollback and continue db.session.rollback() # Start background polling thread def poll_jobs(): with app.app_context(): from app.models import Job from app.routes.jobs import update_job_status_internal while True: try: # Poll all jobs that are not finished unfinished_jobs = Job.query.filter(Job.status.in_(['waiting', 'in_progress'])).all() for job in unfinished_jobs: update_job_status_internal(job) except Exception as e: print(f"[ERROR] Background polling error: {e}") time.sleep(20) polling_thread = threading.Thread(target=poll_jobs, daemon=True) polling_thread.start() return app