Coverage for mindsdb / api / http / start.py: 0%
42 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
1import gc
2from importlib import import_module
4gc.disable()
6from flask import Flask
7from starlette.applications import Starlette
8from starlette.routing import Mount, Route
9from starlette.responses import JSONResponse
10from a2wsgi import WSGIMiddleware
11import uvicorn
13from mindsdb.api.http.initialize import initialize_app
14from mindsdb.interfaces.storage import db
15from mindsdb.utilities import log
16from mindsdb.utilities.config import config
17from mindsdb.utilities.functions import init_lexer_parsers
18from mindsdb.integrations.libs.ml_exec_base import process_cache
19from mindsdb.api.common.middleware import PATAuthMiddleware
21gc.enable()
23logger = log.getLogger(__name__)
26async def _health_check(request):
27 """Async health check that bypasses the WSGI worker pool for the mindsdb API."""
28 return JSONResponse({"status": "ok"})
31def _mount_optional_api(name: str, mount_path: str, get_app_fn, routes):
32 try:
33 optional_app = get_app_fn()
34 except ImportError as exc:
35 logger.warning(
36 "%s support is disabled (%s). To enable it, install the %s extra: pip install 'mindsdb[%s]'",
37 name,
38 exc,
39 name,
40 name.lower(),
41 )
42 return
44 optional_app.add_middleware(PATAuthMiddleware)
45 routes.append(Mount(mount_path, app=optional_app))
48def start(verbose, app: Flask = None, is_restart: bool = False):
49 db.init()
50 init_lexer_parsers()
52 if app is None:
53 app = initialize_app(is_restart)
55 port = config["api"]["http"]["port"]
56 host = config["api"]["http"]["host"]
58 process_cache.init()
60 routes = []
62 # Health check FIRST - async endpoint that bypasses WSGI worker pool
63 # This ensures health checks respond even when all workers are blocked
64 routes.append(Route("/api/util/ping", _health_check, methods=["GET"]))
66 _mount_optional_api(
67 "A2A",
68 "/a2a",
69 lambda: import_module("mindsdb.api.a2a").get_a2a_app(),
70 routes,
71 )
72 _mount_optional_api(
73 "MCP",
74 "/mcp",
75 lambda: import_module("mindsdb.api.mcp").get_mcp_app(),
76 routes,
77 )
79 # Root app LAST so it won't shadow the others
80 routes.append(
81 Mount(
82 "/",
83 app=WSGIMiddleware(
84 app,
85 workers=config["api"]["http"]["a2wsgi"]["workers"],
86 send_queue_size=config["api"]["http"]["a2wsgi"]["send_queue_size"],
87 ),
88 )
89 )
91 # Setting logging to None makes uvicorn use the existing logging configuration
92 uvicorn.run(Starlette(routes=routes, debug=verbose), host=host, port=int(port), log_level=None, log_config=None)