You've made it non-optional, which isn't ideal. The connection pooling
in psycopg2 is purely manual, in-memory stuff that shares connections
within the same process (so, for multi-threaded operations). Once you
switch to multi process operations, it's time to graduate to the "real
stuff" and use, e.g., pgpool to the connection pooling. At that point,
the extra overhead from the psycopg2 classes is probably not helping.
A different approach would be to work out which hooks are really needed
to support this (i.e. where we might need to call a function in a
subclass where the subclass is the thing that supports psycopg2's
pooling, for example) and we can write those in. Then, as hinted, we can
put the pooling in a subclass and provide it that way (maybe).
A couple of comments on the patch inline below...
You're making this sort of change all throughout this function, which
suggests there's an easier way: put a single line at the end that says
self.conn_string = conn_string
Less changes, shorter lines in the function and it's also slightly more
efficient (since local variable lookups are faster than having to
dereference the attribute all the time). All of which are extremely
minor, but it simultaneously helps cut down on the code churn.
> if settings.DATABASE_USER:
> - conn_string = "user=%s %s" % (settings.DATABASE_USER,
> conn_string)
> + self.conn_string = "user=%s %s" %
> (settings.DATABASE_USER, self.conn_string)
> if settings.DATABASE_PASSWORD:
> - conn_string += " password='%s'" %
> settings.DATABASE_PASSWORD
> + self.conn_string += " password='%s'" %
> settings.DATABASE_PASSWORD
> if settings.DATABASE_HOST:
> - conn_string += " host=%s" % settings.DATABASE_HOST
> + self.conn_string += " host=%s" %
> settings.DATABASE_HOST
> if settings.DATABASE_PORT:
> - conn_string += " port=%s" % settings.DATABASE_PORT
> - self.connection = Database.connect(conn_string,
> **self.options)
> + self.conn_string += " port=%s" %
> settings.DATABASE_PORT
> + self.connection = getconn(self.conn_string, self.options)
This would seem to be the place for a hook. We call, for example, a
"connect()" function on the current class which is normally aliased to
Database.connect, but can be overridden in the pooling subclass.
> self.connection.set_isolation_level(1) # make
> transactions transparent to all cursors
> self.connection.set_client_encoding('UTF8')
> cursor = self.connection.cursor()
> @@ -94,3 +112,8 @@ class DatabaseWrapper(BaseDatabaseWrappe
> # No savepoint support for earlier version of
> PostgreSQL.
> self.features.uses_savepoints = False
> return cursor
> +
> + def close(self):
> + if self.connection is not None:
> + putconn(self.conn_string, self.connection)
> + self.connection = None
Similarly, could be a no-op in the main class and overridden in the
subclass.
Regards,
Malcolm