So, a new session is generated for every request. Here's the code from
finish(), which gets called at the end of every request, including
ones where an error has just been thrown.

  try:
    elixir.session.commit()
  except:
    elixir.session.rollback()
    raise
  finally:
    elixir.session.remove()

So the reason I get the "Can't reconnect until ..." errors on top of
"MySQL went for a stroll ..." is because Tornado's error handler (its
try/except blanket, as you rightly pointed out) calls finish() at the
end to close the connection. That means it calls commit(), which
throws the above and creates extraneous errors.

It sounds like a better approach would be to wrap each request
handler's code as follows:

try:
  RequestHandler()
  elixir.session.commit()
except:
  elixir.session.rollback()
  raise
finally:
  elixir.session.remove()

Q1: Is this, in fact, the better approach ?
Q2: If so, I already have a whole bunch of RequestHandlers written, so
the only way I can think of making this change efficiently is by
modifying Tornado's internals, which I'd prefer not to do. Are there
other options ? I guess with_session type decorators are on the table
as well, but will be pretty repetitive since all the handlers need
sessions.


On Feb 25, 7:03 am, Michael Bayer <mike...@zzzcomputing.com> wrote:
> if your application is in some kind of loop that wants a single Session to 
> recover after an exception, part of that loop's construction should ensure 
> exceptions are handled appropriately. and the session's state is reset.   
> Like the docs mention, this is trivial for web applications, all of which 
> provide systems for init/cleanup on request.
>
> Its a little misleading to say "I need to wrap *all* DB code in a 
> try/except", since you definitely don't want ad-hoc try/excepts everywhere.   
>    If your app already has exceptions raised and keeps on going, then its a 
> given that you already have a "try/except" block somewhere in your 
> application doing that.
>
> On Feb 25, 2011, at 6:49 AM, Romy wrote:
>
>
>
>
>
>
>
> > Hey Michael,
>
> > Just had a "MySQL has gone away" that I intentionally triggered by
> > setting the pool recycle to be higher than wait_timeout. Afterwards, I
> > watched the commit() at the end of the request throw a "Can't
> > reconnect until invalid transaction is rolled back", which the catch
> > block was handling with a rollback() followed by a raise. Then it got
> > stuck in that state.
>
> > This made me realize -- do I need to wrap *all* DB code inside try/
> > catch blocks ? Because currently it's only the commit() at the end of
> > each request that gets wrapped. Outside of "gone away" errors, are
> > there other errors that will get the process stuck in the "can't
> > reconnect until rollback" state ?
>
> > If so, it might be a pain in the ass to wrap all requests without
> > modifying the framework.
>
> > R
>
> > --
> > You received this message because you are subscribed to the Google Groups 
> > "sqlalchemy" group.
> > To post to this group, send email to sqlalchemy@googlegroups.com.
> > To unsubscribe from this group, send email to 
> > sqlalchemy+unsubscr...@googlegroups.com.
> > For more options, visit this group 
> > athttp://groups.google.com/group/sqlalchemy?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to