views:

58

answers:

2

I have a problem with Pylons + SQLAlchemy.

When something goes wrong (in my case it is integrity error, due to a race condition) and the database error is raised, all following requestы result in the error being raised:

InvalidRequestError: The transaction is inactive due to a rollback in a subtransaction.  Issue rollback() to cancel the transaction.

While I can prevent this original error (race condition) from happening, but I would like a more robust solution, I want to prevent a single error from crashing the entire application.

What is the best way to do this? Is there a way to tell Pylons to rollback the failed transaction?

A: 

Do you use in your controllers yoursapp.lib.base.BaseController?

You can look at http://stackoverflow.com/questions/3033234/handle-mysql-restart-in-sqlalchemy/3035882#3035882

Also you can catch SA exception in BaseController try-finally block and do session rollback()

In BaseController SA Session removed http://www.sqlalchemy.org/docs/05/session.html#lifespan-of-a-contextual-session

estin
Oh, thanks, i see now that the session is being remove()'d after each request. Then why the error arises in all the following requests then?
maksymko
This error happens on all actions dealing with SA Session?
estin
Yeah, pretty much. Selects, updates... All requests are failing.
maksymko
The SA Session object in yours controllers the same as Session object in yoursapp.lib.base? May be you have some code generating IntegrityError and handle it without rollback(). As I know after IntgerityError and others you must do rollback() or close/remove SA Session
estin
+1  A: 

The easiest thing is to make sure you are using a new SQLAlchemy Session when you start work in your controller. in /project/lib/base.py, add a method for BaseController:

def __before__(self):
    model.Session.close()

Session.close() will clear out the session and close any open transactions if there are any. You want to make sure that each time you use a session it's cleared when you're done with your work in the controller. Doing it at the start of the controller's handling of the request will make sure that it's always cleared, even if the thread's previous request had an exception and there is a rollback waiting.

Thanks, this seems to do the trick
maksymko