mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-03-03 15:45:46 +03:00
Added documentation for the green features.
This commit is contained in:
parent
127f92f9db
commit
a54932ee9c
|
@ -362,6 +362,75 @@ this will be probably implemented in a future release.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.. index::
|
||||||
|
single: Greenlet, Coroutine, eventlet, gevent, Wait callback
|
||||||
|
|
||||||
|
.. _green-support:
|
||||||
|
|
||||||
|
Support to coroutine libraries
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 2.2.0
|
||||||
|
|
||||||
|
Psycopg can be used together with coroutine_\-based libraries, and participate
|
||||||
|
to cooperative multithread.
|
||||||
|
|
||||||
|
Coroutine-based libraries (such as Eventlet_ or gevent_) can usually patch the
|
||||||
|
Python standard library in order to enable a coroutine switch in presence of
|
||||||
|
blocking I/O: the process is usually referred as making the system *green*, in
|
||||||
|
reference to greenlet_, the basic Python micro-thread library.
|
||||||
|
|
||||||
|
Because Psycopg is a C extension module, it is not possible for coroutine
|
||||||
|
libraries to patch it: Psycopg instead enables cooperative multithreading by
|
||||||
|
allowing the registration of a *wait callback* using the
|
||||||
|
`psycopg2.extensions.set_wait_callback()` function. When a wait callback is
|
||||||
|
registered, Psycopg will use `libpq non-blocking calls`__ instead of the regular
|
||||||
|
blocking ones, and will delegate to the callback the responsibility to wait
|
||||||
|
for available data.
|
||||||
|
|
||||||
|
This way of working is less flexible of complete asynchronous I/O, but has the
|
||||||
|
advantage of maintaining a complete |DBAPI| semantics: from the point of view
|
||||||
|
of the end user, all Psycopg functions and objects will work transparently
|
||||||
|
in the coroutine environment (the calling coroutine will be blocked while
|
||||||
|
other coroutines can be scheduled to run), allowing non modified code and
|
||||||
|
third party libraries (such as SQLAlchemy_) to be used in coroutine-based
|
||||||
|
programs.
|
||||||
|
|
||||||
|
Notice that, while I/O correctly yields control to other coroutines, each
|
||||||
|
connection has a lock allowing a single cursor at time to communicate with the
|
||||||
|
backend: such lock is not *green*, so blocking against it would block the
|
||||||
|
entire program waiting for data, not the single coroutine. Therefore,
|
||||||
|
programmers are advised to either avoid to share connections between coroutines
|
||||||
|
or to use a library-friendly lock to synchronize shares connections, e.g. for
|
||||||
|
pooling.
|
||||||
|
|
||||||
|
Coroutine libraries authors should provide a callback implementation (and
|
||||||
|
probably register it) to make Psycopg as green as they want. An example
|
||||||
|
callback (using `!select()` to block) is provided as
|
||||||
|
`psycopg2.extras.wait_select()`: it boils down to something similar to::
|
||||||
|
|
||||||
|
def wait_select(conn):
|
||||||
|
while 1:
|
||||||
|
state = conn.poll()
|
||||||
|
if state == extensions.POLL_OK:
|
||||||
|
break
|
||||||
|
elif state == extensions.POLL_READ:
|
||||||
|
select.select([conn.fileno()], [], [])
|
||||||
|
elif state == extensions.POLL_WRITE:
|
||||||
|
select.select([], [conn.fileno()], [])
|
||||||
|
else:
|
||||||
|
raise OperationalError("bad state from poll: %s" % state)
|
||||||
|
|
||||||
|
.. _coroutine: http://en.wikipedia.org/wiki/Coroutine
|
||||||
|
.. _greenlet: http://pypi.python.org/pypi/greenlet
|
||||||
|
.. _Eventlet: http://eventlet.net/
|
||||||
|
.. _gevent: http://www.gevent.org/
|
||||||
|
.. _SQLAlchemy: http://www.sqlalchemy.org/
|
||||||
|
.. __: http://www.postgresql.org/docs/8.4/static/libpq-async.html
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. testcode::
|
.. testcode::
|
||||||
:hide:
|
:hide:
|
||||||
|
|
||||||
|
|
|
@ -321,7 +321,7 @@ The ``connection`` class
|
||||||
|
|
||||||
.. versionadded:: 2.2.0
|
.. versionadded:: 2.2.0
|
||||||
|
|
||||||
.. seealso:: :ref:`Asynchronous support <async-support>`.
|
.. seealso:: :ref:`async-support` and :ref:`green-support`.
|
||||||
|
|
||||||
|
|
||||||
.. attribute:: async
|
.. attribute:: async
|
||||||
|
@ -338,9 +338,11 @@ The ``connection`` class
|
||||||
Return one of the constants defined in :ref:`poll-constants`. If it
|
Return one of the constants defined in :ref:`poll-constants`. If it
|
||||||
returns `~psycopg2.extensions.POLL_OK` then the connection has been
|
returns `~psycopg2.extensions.POLL_OK` then the connection has been
|
||||||
estabilished or the query results are available on the client.
|
estabilished or the query results are available on the client.
|
||||||
Otherwise wait until the file descriptor returned by
|
Otherwise wait until the file descriptor returned by `fileno()` is
|
||||||
`~connection.fileno()` is ready to read or to write, as explained in
|
ready to read or to write, as explained in :ref:`async-support`.
|
||||||
:ref:`async-support`.
|
`poll()` should be also used by the function installed by
|
||||||
|
`~psycopg2.extensions.set_wait_callback()` as explained in
|
||||||
|
:ref:`green-support`.
|
||||||
|
|
||||||
`poll()` is also used to receive asynchronous notifications from the
|
`poll()` is also used to receive asynchronous notifications from the
|
||||||
database: see :ref:`async-notify` from further details.
|
database: see :ref:`async-notify` from further details.
|
||||||
|
|
|
@ -106,6 +106,14 @@ functionalities defined by the |DBAPI|_.
|
||||||
Close the object and remove it from the database.
|
Close the object and remove it from the database.
|
||||||
|
|
||||||
|
|
||||||
|
.. autofunction:: set_wait_callback(f)
|
||||||
|
|
||||||
|
.. versionadded:: 2.2.0
|
||||||
|
|
||||||
|
.. autofunction:: get_wait_callback()
|
||||||
|
|
||||||
|
.. versionadded:: 2.2.0
|
||||||
|
|
||||||
|
|
||||||
.. _sql-adaptation-objects:
|
.. _sql-adaptation-objects:
|
||||||
|
|
||||||
|
@ -456,7 +464,9 @@ Poll constants
|
||||||
.. versionadded:: 2.2.0
|
.. versionadded:: 2.2.0
|
||||||
|
|
||||||
These values can be returned by `connection.poll()` during asynchronous
|
These values can be returned by `connection.poll()` during asynchronous
|
||||||
connection and communication. See :ref:`async-support`.
|
connection and communication. They match the values in the libpq enum
|
||||||
|
`!PostgresPollingStatusType`. See :ref:`async-support` and
|
||||||
|
:ref:`green-support`.
|
||||||
|
|
||||||
.. data:: POLL_OK
|
.. data:: POLL_OK
|
||||||
|
|
||||||
|
@ -481,6 +491,12 @@ connection and communication. See :ref:`async-support`.
|
||||||
|
|
||||||
select.select([], [conn.fileno()], [])
|
select.select([], [conn.fileno()], [])
|
||||||
|
|
||||||
|
.. data:: POLL_ERROR
|
||||||
|
|
||||||
|
There was a problem during connection polling. This value should actually
|
||||||
|
never be returned: in case of poll error usually an exception containing
|
||||||
|
the relevant details is raised.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Additional database types
|
Additional database types
|
||||||
|
|
|
@ -155,3 +155,11 @@ Fractional time zones
|
||||||
|
|
||||||
.. versionadded:: 2.0.9
|
.. versionadded:: 2.0.9
|
||||||
|
|
||||||
|
.. index::
|
||||||
|
pair: Example; Coroutine;
|
||||||
|
|
||||||
|
Coroutine support
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. autofunction:: wait_select(conn)
|
||||||
|
|
||||||
|
|
|
@ -34,23 +34,26 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define psyco_set_wait_callback_doc \
|
#define psyco_set_wait_callback_doc \
|
||||||
"set_wait_callback(f) -- Register a callback function to block waiting for data.\n" \
|
"Register a callback function to block waiting for data.\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"The callback should have signature :samp:`fun({conn})` and\n" \
|
"The callback should have signature :samp:`fun({conn})` and\n" \
|
||||||
"is called to wait for data available whenever a blocking function from the\n" \
|
"is called to wait for data available whenever a blocking function from the\n" \
|
||||||
"libpq is called. Use `!register_wait_function(None)` to revert to the\n" \
|
"libpq is called. Use `!set_wait_callback(None)` to revert to the\n" \
|
||||||
"original behaviour (using blocking libpq functions).\n" \
|
"original behaviour (i.e. using blocking libpq functions).\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"The function is an hook to allow coroutine-based libraries (such as\n" \
|
"The function is an hook to allow coroutine-based libraries (such as\n" \
|
||||||
"eventlet_ or gevent_) to switch when Psycopg is blocked, allowing\n" \
|
"Eventlet_ or gevent_) to switch when Psycopg is blocked, allowing\n" \
|
||||||
"other coroutines to run concurrently.\n" \
|
"other coroutines to run concurrently.\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"See `~psycopg2.extras.wait_select()` for an example of a wait callback\n" \
|
"See `~psycopg2.extras.wait_select()` for an example of a wait callback\n" \
|
||||||
"implementation.\n"
|
"implementation.\n" \
|
||||||
|
"\n" \
|
||||||
|
".. _Eventlet: http://eventlet.net/\n" \
|
||||||
|
".. _gevent: http://www.gevent.org/\n"
|
||||||
HIDDEN PyObject *psyco_set_wait_callback(PyObject *self, PyObject *obj);
|
HIDDEN PyObject *psyco_set_wait_callback(PyObject *self, PyObject *obj);
|
||||||
|
|
||||||
#define psyco_get_wait_callback_doc \
|
#define psyco_get_wait_callback_doc \
|
||||||
"get_wait_callback() -- Return the currently registered wait callback.\n" \
|
"Return the currently registered wait callback.\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"Return `None` if no callback is currently registered.\n"
|
"Return `None` if no callback is currently registered.\n"
|
||||||
HIDDEN PyObject *psyco_get_wait_callback(PyObject *self, PyObject *obj);
|
HIDDEN PyObject *psyco_get_wait_callback(PyObject *self, PyObject *obj);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user