events.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. # pool/events.py
  2. # Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: https://www.opensource.org/licenses/mit-license.php
  7. from .base import Pool
  8. from .. import event
  9. from ..engine.base import Engine
  10. class PoolEvents(event.Events):
  11. """Available events for :class:`_pool.Pool`.
  12. The methods here define the name of an event as well
  13. as the names of members that are passed to listener
  14. functions.
  15. e.g.::
  16. from sqlalchemy import event
  17. def my_on_checkout(dbapi_conn, connection_rec, connection_proxy):
  18. "handle an on checkout event"
  19. event.listen(Pool, 'checkout', my_on_checkout)
  20. In addition to accepting the :class:`_pool.Pool` class and
  21. :class:`_pool.Pool` instances, :class:`_events.PoolEvents` also accepts
  22. :class:`_engine.Engine` objects and the :class:`_engine.Engine` class as
  23. targets, which will be resolved to the ``.pool`` attribute of the
  24. given engine or the :class:`_pool.Pool` class::
  25. engine = create_engine("postgresql://scott:tiger@localhost/test")
  26. # will associate with engine.pool
  27. event.listen(engine, 'checkout', my_on_checkout)
  28. """
  29. _target_class_doc = "SomeEngineOrPool"
  30. _dispatch_target = Pool
  31. @classmethod
  32. def _accept_with(cls, target):
  33. if isinstance(target, type):
  34. if issubclass(target, Engine):
  35. return Pool
  36. elif issubclass(target, Pool):
  37. return target
  38. elif isinstance(target, Engine):
  39. return target.pool
  40. elif isinstance(target, Pool):
  41. return target
  42. elif hasattr(target, "dispatch") and hasattr(
  43. target.dispatch._events, "_no_async_engine_events"
  44. ):
  45. target.dispatch._events._no_async_engine_events()
  46. else:
  47. return None
  48. @classmethod
  49. def _listen(cls, event_key, **kw):
  50. target = event_key.dispatch_target
  51. kw.setdefault("asyncio", target._is_asyncio)
  52. event_key.base_listen(**kw)
  53. def connect(self, dbapi_connection, connection_record):
  54. """Called at the moment a particular DBAPI connection is first
  55. created for a given :class:`_pool.Pool`.
  56. This event allows one to capture the point directly after which
  57. the DBAPI module-level ``.connect()`` method has been used in order
  58. to produce a new DBAPI connection.
  59. :param dbapi_connection: a DBAPI connection.
  60. The :attr:`._ConnectionRecord.dbapi_connection` attribute.
  61. :param connection_record: the :class:`._ConnectionRecord` managing the
  62. DBAPI connection.
  63. """
  64. def first_connect(self, dbapi_connection, connection_record):
  65. """Called exactly once for the first time a DBAPI connection is
  66. checked out from a particular :class:`_pool.Pool`.
  67. The rationale for :meth:`_events.PoolEvents.first_connect`
  68. is to determine
  69. information about a particular series of database connections based
  70. on the settings used for all connections. Since a particular
  71. :class:`_pool.Pool`
  72. refers to a single "creator" function (which in terms
  73. of a :class:`_engine.Engine`
  74. refers to the URL and connection options used),
  75. it is typically valid to make observations about a single connection
  76. that can be safely assumed to be valid about all subsequent
  77. connections, such as the database version, the server and client
  78. encoding settings, collation settings, and many others.
  79. :param dbapi_connection: a DBAPI connection.
  80. The :attr:`._ConnectionRecord.dbapi_connection` attribute.
  81. :param connection_record: the :class:`._ConnectionRecord` managing the
  82. DBAPI connection.
  83. """
  84. def checkout(self, dbapi_connection, connection_record, connection_proxy):
  85. """Called when a connection is retrieved from the Pool.
  86. :param dbapi_connection: a DBAPI connection.
  87. The :attr:`._ConnectionRecord.dbapi_connection` attribute.
  88. :param connection_record: the :class:`._ConnectionRecord` managing the
  89. DBAPI connection.
  90. :param connection_proxy: the :class:`._ConnectionFairy` object which
  91. will proxy the public interface of the DBAPI connection for the
  92. lifespan of the checkout.
  93. If you raise a :class:`~sqlalchemy.exc.DisconnectionError`, the current
  94. connection will be disposed and a fresh connection retrieved.
  95. Processing of all checkout listeners will abort and restart
  96. using the new connection.
  97. .. seealso:: :meth:`_events.ConnectionEvents.engine_connect`
  98. - a similar event
  99. which occurs upon creation of a new :class:`_engine.Connection`.
  100. """
  101. def checkin(self, dbapi_connection, connection_record):
  102. """Called when a connection returns to the pool.
  103. Note that the connection may be closed, and may be None if the
  104. connection has been invalidated. ``checkin`` will not be called
  105. for detached connections. (They do not return to the pool.)
  106. :param dbapi_connection: a DBAPI connection.
  107. The :attr:`._ConnectionRecord.dbapi_connection` attribute.
  108. :param connection_record: the :class:`._ConnectionRecord` managing the
  109. DBAPI connection.
  110. """
  111. def reset(self, dbapi_connection, connection_record):
  112. """Called before the "reset" action occurs for a pooled connection.
  113. This event represents when the ``rollback()`` method is called on the
  114. DBAPI connection before it is returned to the pool or discarded. A
  115. custom "reset" strategy may be implemented using this event hook, which
  116. may also be combined with disabling the default "reset" behavior using
  117. the :paramref:`_pool.Pool.reset_on_return` parameter.
  118. The primary difference between the :meth:`_events.PoolEvents.reset` and
  119. :meth:`_events.PoolEvents.checkin` events are that
  120. :meth:`_events.PoolEvents.reset` is called not just for pooled
  121. connections that are being returned to the pool, but also for
  122. connections that were detached using the
  123. :meth:`_engine.Connection.detach` method.
  124. Note that the event **is not** invoked for connections that were
  125. invalidated using :meth:`_engine.Connection.invalidate`. These
  126. events may be intercepted using the :meth:`.PoolEvents.soft_invalidate`
  127. and :meth:`.PoolEvents.invalidate` event hooks, and all "connection
  128. close" events may be intercepted using :meth:`.PoolEvents.close`.
  129. The :meth:`_events.PoolEvents.reset` event is usually followed by the
  130. :meth:`_events.PoolEvents.checkin` event, except in those
  131. cases where the connection is discarded immediately after reset.
  132. In the 1.4 series, the event is also not invoked for asyncio
  133. connections that are being garbage collected without their being
  134. explicitly returned to the pool. This is due to the lack of an event
  135. loop which prevents "reset" operations from taking place. Version 2.0
  136. will feature an enhanced version of :meth:`.PoolEvents.reset` which is
  137. invoked in this scenario while passing additional contextual
  138. information indicating that an event loop is not guaranteed
  139. to be present.
  140. :param dbapi_connection: a DBAPI connection.
  141. The :attr:`._ConnectionRecord.dbapi_connection` attribute.
  142. :param connection_record: the :class:`._ConnectionRecord` managing the
  143. DBAPI connection.
  144. .. seealso::
  145. :meth:`_events.ConnectionEvents.rollback`
  146. :meth:`_events.ConnectionEvents.commit`
  147. """
  148. def invalidate(self, dbapi_connection, connection_record, exception):
  149. """Called when a DBAPI connection is to be "invalidated".
  150. This event is called any time the :meth:`._ConnectionRecord.invalidate`
  151. method is invoked, either from API usage or via "auto-invalidation",
  152. without the ``soft`` flag.
  153. The event occurs before a final attempt to call ``.close()`` on the
  154. connection occurs.
  155. :param dbapi_connection: a DBAPI connection.
  156. The :attr:`._ConnectionRecord.dbapi_connection` attribute.
  157. :param connection_record: the :class:`._ConnectionRecord` managing the
  158. DBAPI connection.
  159. :param exception: the exception object corresponding to the reason
  160. for this invalidation, if any. May be ``None``.
  161. .. versionadded:: 0.9.2 Added support for connection invalidation
  162. listening.
  163. .. seealso::
  164. :ref:`pool_connection_invalidation`
  165. """
  166. def soft_invalidate(self, dbapi_connection, connection_record, exception):
  167. """Called when a DBAPI connection is to be "soft invalidated".
  168. This event is called any time the :meth:`._ConnectionRecord.invalidate`
  169. method is invoked with the ``soft`` flag.
  170. Soft invalidation refers to when the connection record that tracks
  171. this connection will force a reconnect after the current connection
  172. is checked in. It does not actively close the dbapi_connection
  173. at the point at which it is called.
  174. .. versionadded:: 1.0.3
  175. :param dbapi_connection: a DBAPI connection.
  176. The :attr:`._ConnectionRecord.dbapi_connection` attribute.
  177. :param connection_record: the :class:`._ConnectionRecord` managing the
  178. DBAPI connection.
  179. :param exception: the exception object corresponding to the reason
  180. for this invalidation, if any. May be ``None``.
  181. """
  182. def close(self, dbapi_connection, connection_record):
  183. """Called when a DBAPI connection is closed.
  184. The event is emitted before the close occurs.
  185. The close of a connection can fail; typically this is because
  186. the connection is already closed. If the close operation fails,
  187. the connection is discarded.
  188. The :meth:`.close` event corresponds to a connection that's still
  189. associated with the pool. To intercept close events for detached
  190. connections use :meth:`.close_detached`.
  191. .. versionadded:: 1.1
  192. :param dbapi_connection: a DBAPI connection.
  193. The :attr:`._ConnectionRecord.dbapi_connection` attribute.
  194. :param connection_record: the :class:`._ConnectionRecord` managing the
  195. DBAPI connection.
  196. """
  197. def detach(self, dbapi_connection, connection_record):
  198. """Called when a DBAPI connection is "detached" from a pool.
  199. This event is emitted after the detach occurs. The connection
  200. is no longer associated with the given connection record.
  201. .. versionadded:: 1.1
  202. :param dbapi_connection: a DBAPI connection.
  203. The :attr:`._ConnectionRecord.dbapi_connection` attribute.
  204. :param connection_record: the :class:`._ConnectionRecord` managing the
  205. DBAPI connection.
  206. """
  207. def close_detached(self, dbapi_connection):
  208. """Called when a detached DBAPI connection is closed.
  209. The event is emitted before the close occurs.
  210. The close of a connection can fail; typically this is because
  211. the connection is already closed. If the close operation fails,
  212. the connection is discarded.
  213. .. versionadded:: 1.1
  214. :param dbapi_connection: a DBAPI connection.
  215. The :attr:`._ConnectionRecord.dbapi_connection` attribute.
  216. """