diff --git a/edbob/pyramid/tweens.py b/edbob/pyramid/tweens.py
new file mode 100644
index 0000000..8039efa
--- /dev/null
+++ b/edbob/pyramid/tweens.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+################################################################################
+#
+# edbob -- Pythonic Software Framework
+# Copyright © 2010-2012 Lance Edgar
+#
+# This file is part of edbob.
+#
+# edbob is free software: you can redistribute it and/or modify it under the
+# terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# edbob is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
+# more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with edbob. If not, see .
+#
+################################################################################
+
+"""
+``edbob.pyramid.tweens`` -- Tween Factories
+"""
+
+import sqlalchemy.exc
+
+from transaction.interfaces import TransientError
+
+
+def sqlerror_tween_factory(handler, registry):
+ """
+ Produces a tween which will convert ``sqlalchemy.exc.OperationalError``
+ instances (caused by database server restart) into a retryable
+ ``transaction.interfaces.TransientError`` instance, so that a second
+ attempt may be made to connect to the database before really giving up.
+
+ .. note::
+ This tween alone is not enough to cause the transaction to be retried;
+ it only marks the error as being *retryable*. If you wish more than one
+ attempt to be made, you must define the ``tm.attempts`` setting within
+ your Pyramid app configuration. See `Retrying
+ `_
+ for more information.
+ """
+
+ def sqlerror_tween(request):
+ try:
+ response = handler(request)
+ except sqlalchemy.exc.OperationalError, error:
+ if error.connection_invalidated:
+ raise TransientError(str(error))
+ raise
+ return response
+
+ return sqlerror_tween
diff --git a/edbob/scaffolds/edbob/+package+/pyramid/__init__.py_tmpl b/edbob/scaffolds/edbob/+package+/pyramid/__init__.py_tmpl
index efdc27d..155371b 100644
--- a/edbob/scaffolds/edbob/+package+/pyramid/__init__.py_tmpl
+++ b/edbob/scaffolds/edbob/+package+/pyramid/__init__.py_tmpl
@@ -7,10 +7,8 @@
import os.path
from pyramid.config import Configurator
-from pyramid.authentication import SessionAuthenticationPolicy
import edbob
-from edbob.pyramid.auth import EdbobAuthorizationPolicy
def main(global_config, **settings):
@@ -27,24 +25,18 @@ def main(global_config, **settings):
# * Raise an exception if a setting is missing or invalid.
# * Convert values from strings to their intended type.
- settings['mako.directories'] = [
- '{{package}}.pyramid:templates',
- 'edbob.pyramid:templates',
- ]
+ settings.setdefault('mako.directories', [
+ '{{package}}.pyramid:templates',
+ 'edbob.pyramid:templates',
+ ])
+
+ # Make two attempts when "retryable" errors happen during transactions.
+ settings.setdefault('tm.attempts', 2)
config = Configurator(settings=settings)
# Configure edbob
edbob.init('{{package}}', os.path.abspath(settings['edbob.config']))
-
- # Configure session
- config.include('pyramid_beaker')
-
- # Configure auth
- config.set_authentication_policy(SessionAuthenticationPolicy())
- config.set_authorization_policy(EdbobAuthorizationPolicy())
-
- # Include "core" stuff provided by edbob.
config.include('edbob.pyramid')
# Additional config is defined elsewhere within {{project}}. This includes
@@ -53,4 +45,8 @@ def main(global_config, **settings):
config.include('{{package}}.pyramid.subscribers')
config.include('{{package}}.pyramid.views')
+ # Consider PostgreSQL server restart errors to be "retryable."
+ config.add_tween('edbob.pyramid.tweens.sqlerror_tween_factory',
+ under='pyramid_tm.tm_tween_factory')
+
return config.make_wsgi_app()