You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ext_database.py 1.5KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import logging
  2. import gevent
  3. from sqlalchemy import event
  4. from sqlalchemy.pool import Pool
  5. from dify_app import DifyApp
  6. from models import db
  7. logger = logging.getLogger(__name__)
  8. # Global flag to avoid duplicate registration of event listener
  9. _GEVENT_COMPATIBILITY_SETUP: bool = False
  10. def _safe_rollback(connection) -> None:
  11. """Safely rollback database connection.
  12. Args:
  13. connection: Database connection object
  14. """
  15. try:
  16. connection.rollback()
  17. except Exception: # pylint: disable=broad-exception-caught
  18. logger.exception("Failed to rollback connection")
  19. def _setup_gevent_compatibility() -> None:
  20. global _GEVENT_COMPATIBILITY_SETUP # pylint: disable=global-statement
  21. # Avoid duplicate registration
  22. if _GEVENT_COMPATIBILITY_SETUP:
  23. return
  24. @event.listens_for(Pool, "reset")
  25. def _safe_reset(dbapi_connection, connection_record, reset_state) -> None: # pylint: disable=unused-argument
  26. if reset_state.terminate_only:
  27. return
  28. # Safe rollback for connection
  29. try:
  30. hub = gevent.get_hub()
  31. if hasattr(hub, "loop") and getattr(hub.loop, "in_callback", False):
  32. gevent.spawn_later(0, lambda: _safe_rollback(dbapi_connection))
  33. else:
  34. _safe_rollback(dbapi_connection)
  35. except (AttributeError, ImportError):
  36. _safe_rollback(dbapi_connection)
  37. _GEVENT_COMPATIBILITY_SETUP = True
  38. def init_app(app: DifyApp):
  39. db.init_app(app)
  40. _setup_gevent_compatibility()