82 lines
2.7 KiB
Python
82 lines
2.7 KiB
Python
"""
|
|
MiroFish Backend - Flask application factory
|
|
"""
|
|
|
|
import os
|
|
import warnings
|
|
|
|
# Suppress multiprocessing resource_tracker warnings (from third-party libraries like transformers)
|
|
# Must be set before all other imports
|
|
warnings.filterwarnings("ignore", message=".*resource_tracker.*")
|
|
|
|
from flask import Flask, request
|
|
from flask_cors import CORS
|
|
|
|
from .config import Config
|
|
from .utils.logger import setup_logger, get_logger
|
|
|
|
|
|
def create_app(config_class=Config):
|
|
"""Flask application factory function"""
|
|
app = Flask(__name__)
|
|
app.config.from_object(config_class)
|
|
|
|
# Set JSON encoding: ensure Chinese characters display directly (instead of \uXXXX format)
|
|
# Flask >= 2.3 uses app.json.ensure_ascii, older versions use JSON_AS_ASCII config
|
|
if hasattr(app, "json") and hasattr(app.json, "ensure_ascii"):
|
|
app.json.ensure_ascii = False
|
|
|
|
# Set up logging
|
|
logger = setup_logger("mirofish")
|
|
|
|
# Only log startup info in the reloader child process (avoid duplicate logs in debug mode)
|
|
is_reloader_process = os.environ.get("WERKZEUG_RUN_MAIN") == "true"
|
|
debug_mode = app.config.get("DEBUG", False)
|
|
should_log_startup = not debug_mode or is_reloader_process
|
|
|
|
if should_log_startup:
|
|
logger.info("=" * 50)
|
|
logger.info("MiroFish Backend starting...")
|
|
logger.info("=" * 50)
|
|
|
|
# Enable CORS
|
|
CORS(app, resources={r"/api/*": {"origins": "*"}})
|
|
|
|
# Register simulation process cleanup function (ensure all simulation processes terminate on server shutdown)
|
|
from .services.simulation_runner import SimulationRunner
|
|
|
|
SimulationRunner.register_cleanup()
|
|
if should_log_startup:
|
|
logger.info("Registered simulation process cleanup function")
|
|
|
|
# Request logging middleware
|
|
@app.before_request
|
|
def log_request():
|
|
logger = get_logger("mirofish.request")
|
|
logger.debug(f"Request: {request.method} {request.path}")
|
|
if request.content_type and "json" in request.content_type:
|
|
logger.debug(f"Request body: {request.get_json(silent=True)}")
|
|
|
|
@app.after_request
|
|
def log_response(response):
|
|
logger = get_logger("mirofish.request")
|
|
logger.debug(f"Response: {response.status_code}")
|
|
return response
|
|
|
|
# Register blueprints
|
|
from .api import graph_bp, simulation_bp, report_bp
|
|
|
|
app.register_blueprint(graph_bp, url_prefix="/api/graph")
|
|
app.register_blueprint(simulation_bp, url_prefix="/api/simulation")
|
|
app.register_blueprint(report_bp, url_prefix="/api/report")
|
|
|
|
# Health check
|
|
@app.route("/health")
|
|
def health():
|
|
return {"status": "ok", "service": "MiroFish Backend"}
|
|
|
|
if should_log_startup:
|
|
logger.info("MiroFish Backend startup complete")
|
|
|
|
return app
|