import os from flask import request as flask_request, Response # Absolute path avoids relative-path confusion in Docker os.environ.setdefault("MLFLOW_TRACKING_URI", "./mlruns") os.environ.setdefault("MLFLOW_DEFAULT_ARTIFACT_ROOT", "/app/mlartifacts") # Pre-initialize the MLflow store on the main thread before Flask starts. # Without this, threaded Flask lets multiple requests race against the SQLite # migration, causing "NoneType has no len()" errors on _search_experiments. import mlflow mlflow.set_tracking_uri(os.environ["MLFLOW_TRACKING_URI"]) try: mlflow.search_experiments() except Exception: pass from mlflow.server import app # Flask app do MLflow # ── CORS ────────────────────────────────────────────────────────────────────── CORS_HEADERS = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With", "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS", } @app.before_request def handle_preflight(): """Responde imediatamente às requisições OPTIONS (preflight).""" if flask_request.method == "OPTIONS": res = Response(status=200) for k, v in CORS_HEADERS.items(): res.headers[k] = v return res @app.after_request def add_cors_headers(response): """Adiciona CORS headers em todas as respostas.""" for k, v in CORS_HEADERS.items(): response.headers[k] = v return response # ───────────────────────────────────────────────────────────────────────────── if __name__ == "__main__": # threaded=False prevents concurrent SQLite access races app.run(host="0.0.0.0", port=7860, debug=False, threaded=False)