Re: (long) improving async support in psycopg
Daniele Varrazzo <[email protected]> Wed, 24 Mar 2010 11:55:20 +0000
| Newsgroups | gmane.comp.python.db.psycopg.devel |
|---|---|
| Message-ID | <[email protected]> |
On Wed, Mar 24, 2010 at 10:56 AM, Jan Urbański <[email protected]> wrote: > Daniele Varrazzo wrote: >> On Wed, Mar 24, 2010 at 3:38 AM, Jan Urbański <[email protected]> wrote: >>> On 23/03/10 01:38, Jan Urbański wrote: >> >>> I won't bother you with the details of how an async connection building >>> procedure could look like, I just want to raise one last issue. The >>> connection class issues a couple of queries, like SHOW client_encoding or >>> SHOW default_transaction_isolation. These are issues synchronously and there >>> is no control over them. That would even be OK, hopefully an application >>> would not create and close lots of connection during it's lifetime. The bad >>> thing is the BEGIN query that gets issued synchronously and even less >>> convenient is that COMMITs are synchronous, and these could take some time >>> on systems with a certain configuration. >> >> I was wondering if it wouldn't be better to have "async" as a >> connection characteristic (a `psycopg2.connect()` parameter) instead >> of as a parameter of the single query executions. This way the driver >> could performed these steps in asynchronous fashion too. Also the >> issues arising by mixing up sync/async operation would disappear. > > That might make sense. Although then you can't use the same connection > for both sync and async things, so if in your software you sometimes > want to just execute a simple blocking query and then do na asynchronous > one you would have to open two separate connections. > > You could argue that an application that uses the async interface will > not want to block ever (that's certainly the case with my Twisted PG > module, I would never use sync execution there). But is it worth it to > impose that limit? It's easy enough to just disallow running anything > while the connection is processing an async query. I think an application with mixed needs could easily create two connections with different sync parameter to mix the call styles. Of course they couldn't be in the same transaction, but this would be a still more uncommon use case. I have a different use case for async psycopg, maybe worth mentioning for completeness and in order to see if it would be possible to have an interface useful in different async environments too. Notice that I am not working directly on these issues, so my knowledge of the issues is more from code read than from code written, so I may actually be not completely accurate. We have coroutine-based program, currently using eventlet_ and running psycopg in a thread to avoid being blocked (a service offered by eventlet itself via the db_pool module). We'd like to move to gevent_, a library built on libevent_. Both eventlet and gevent can "monkeypatch" pure python code in order to make it non-blocking, cooperatively yielding the control to another coroutine in presence of a blocking call. In a pilot program using gevent we used a different postgres adapter (pg8000, non libpq based) because, being written in pure python, gevent can replace its socket with a cooperative one (but pg8000 is rather immature, e.g. we had to patch it to avoid leaving idle transactions open, something it does by design). _eventlet: http://wiki.secondlife.com/wiki/Eventlet _gevent: http://www.gevent.org/ _libevent: http://monkey.org/~provos/libevent/ I think the optimum would be to have an async connection with the classic dbapi interface built on top, with coroutine-friendly blocking methods. A dbapi interface (thus without the extra `cursor.execute()` parameter) would also enable the async psycopg to be used with existing clients, e.g. SQLAlchemy. I haven't thought if it is possible to have this independently from the async framework used (twisted, gevent, libevent, maybe providing an hook point where the libs could install their callbacks...), I just think that having the concept of an "async connection" instead of just an "async execute" could be a better starting point (the sync/async code paths can be widely different: there could be two C classes to handle them, which could clean up a lot of code paths). I'd really like to do myself some tries in this direction, but I don't think it will be possible in the next days. I'd like to hear some feedback by people knowing twisted and/or coroutine-based libraries to hear if there would be show-stoppers I don't know about in this approach. -- Daniele _______________________________________________ Psycopg mailing list [email protected] http://lists.initd.org/mailman/listinfo/psycopg