mirror of
https://github.com/langgenius/dify.git
synced 2026-07-20 09:38:32 +08:00
82 lines
2.5 KiB
Python
82 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
# ``python -m app`` (docker DEBUG=true, or IDE debugging) serves through the
|
|
# gevent pywsgi server at the bottom of this file, so the stdlib must be
|
|
# monkey-patched BEFORE any other import pulls in sockets or locks. Without
|
|
# this, every request runs as a greenlet on one OS thread while blocking
|
|
# calls (LLM invokes, ``Future.result`` waits, DB I/O) pin that thread — the
|
|
# whole process freezes until the call returns. Gunicorn and Celery apply
|
|
# their own patching (see gunicorn.conf.py / celery_entrypoint.py), and
|
|
# ``flask run`` uses real Werkzeug threads, so both skip this branch.
|
|
if __name__ == "__main__":
|
|
from gevent import monkey
|
|
|
|
monkey.patch_all()
|
|
|
|
import psycogreen.gevent as psycogreen_gevent
|
|
from grpc.experimental import gevent as grpc_gevent
|
|
|
|
grpc_gevent.init_gevent()
|
|
psycogreen_gevent.patch_psycopg()
|
|
|
|
import logging
|
|
import sys
|
|
from typing import TYPE_CHECKING, cast
|
|
|
|
if TYPE_CHECKING:
|
|
from celery import Celery
|
|
|
|
celery: Celery
|
|
|
|
|
|
HOST = "0.0.0.0"
|
|
PORT = 5001
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def is_db_command() -> bool:
|
|
if len(sys.argv) > 1 and sys.argv[0].endswith("flask") and sys.argv[1] == "db":
|
|
return True
|
|
return False
|
|
|
|
|
|
def log_startup_banner(host: str, port: int) -> None:
|
|
debugger_attached = sys.gettrace() is not None
|
|
logger.info("Serving Dify API via gevent WebSocket server")
|
|
logger.info("Bound to http://%s:%s", host, port)
|
|
logger.info("Debugger attached: %s", "on" if debugger_attached else "off")
|
|
logger.info("Press CTRL+C to quit")
|
|
|
|
|
|
# create app
|
|
flask_app = None
|
|
socketio_app = None
|
|
|
|
if is_db_command():
|
|
from app_factory import create_migrations_app
|
|
|
|
app = create_migrations_app()
|
|
socketio_app = app
|
|
flask_app = app
|
|
else:
|
|
# Gunicorn and Celery handle monkey patching automatically in production by
|
|
# specifying the `gevent` worker class. Manual monkey patching is not required here.
|
|
#
|
|
# See `api/docker/entrypoint.sh` (lines 33 and 47) for details.
|
|
#
|
|
# For third-party library patching, refer to `gunicorn.conf.py` and `celery_entrypoint.py`.
|
|
|
|
from app_factory import create_app
|
|
|
|
socketio_app, flask_app = create_app()
|
|
app = flask_app
|
|
celery = cast("Celery", app.extensions["celery"])
|
|
|
|
if __name__ == "__main__":
|
|
from gevent import pywsgi
|
|
from geventwebsocket.handler import WebSocketHandler
|
|
|
|
log_startup_banner(HOST, PORT)
|
|
server = pywsgi.WSGIServer((HOST, PORT), socketio_app, handler_class=WebSocketHandler)
|
|
server.serve_forever()
|