summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2013-01-15 21:27:37 -0600
committerDan McGee <dan@archlinux.org>2013-01-15 21:27:37 -0600
commit3a6398f42d04ea6a677bf7b6d5115175e9011432 (patch)
treeff9b93bd252698c2f8ddc9aa79491f4317418957
parentaf32c23768c7537f19e0613525579208b4f44eb4 (diff)
Add new AlwaysCommitMiddleware to the stack
The reason for this is documented in the middleware itself. Without this, pgbouncer is of little use to us since it has to throw away every connection we try to route through it because of unclean disconnects. In theory, with the switch to using pgbouncer for all WSGI originating connections and adding this middleware, we should see a notable decrease in connection time to the database. Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r--main/middleware.py40
-rw-r--r--settings.py1
2 files changed, 41 insertions, 0 deletions
diff --git a/main/middleware.py b/main/middleware.py
new file mode 100644
index 00000000..a698b13c
--- /dev/null
+++ b/main/middleware.py
@@ -0,0 +1,40 @@
+from django.core.exceptions import MiddlewareNotUsed
+from django.db import connections
+
+
+class AlwaysCommitMiddleware(object):
+ """
+ Ensure we always commit any possibly open transaction so we leave the
+ database in a clean state. Without this, pgbouncer et al. always gives
+ error messages like this for every single request:
+
+ LOG S-0x1accfd0: db/user@unix:5432 new connection to server
+ LOG C-0x1aaf620: db/user@unix:6432 closing because: client close request (age=0)
+ LOG S-0x1accfd0: db/user@unix:5432 closing because: unclean server (age=0)
+
+ We only let this middleware apply for PostgreSQL backends; other databases
+ don't really require connection pooling and thus the reason for this
+ middleware's use is non-existent.
+
+ The best location of this in your middleware stack is likely the top, as
+ you want to ensure it happens after any and all database activity has
+ completed.
+ """
+ def __init__(self):
+ for conn in connections.all():
+ if conn.vendor == 'postgresql':
+ return
+ raise MiddlewareNotUsed()
+
+ def process_response(self, request, response):
+ """Commits any potentially open transactions at the underlying
+ PostgreSQL database connection level."""
+ for conn in connections.all():
+ if conn.vendor != 'postgresql':
+ continue
+ db_conn = getattr(conn, 'connection', None)
+ if db_conn is not None:
+ db_conn.commit()
+ return response
+
+# vim: set ts=4 sw=4 et:
diff --git a/settings.py b/settings.py
index 8ed5cb61..cdc56e3e 100644
--- a/settings.py
+++ b/settings.py
@@ -66,6 +66,7 @@ TEMPLATE_LOADERS = (
)
MIDDLEWARE_CLASSES = (
+ 'main.middleware.AlwaysCommitMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',