On Wed, Aug 3, 2011 at 11:06 PM, Chris McDonough <[email protected]> wrote: > On Wed, 2011-08-03 at 22:44 -0700, Mike Orr wrote: >> On Wed, Aug 3, 2011 at 12:34 PM, Matt Feifarek <[email protected]> >> wrote: >> > On Wed, Aug 3, 2011 at 1:12 PM, Chris McDonough <[email protected]> wrote: >> >> >> >> > In fact, an argument could be made that if a transaction fails, the >> >> > entire contents of the view callable should not execute... >> >> >> >> We don't know whether the "transaction failed" until the view callable >> >> is called. The definition of a transaction "failing" is either an >> >> exception is raised by view code or the view response code is 4XX/5XX. >> > >> > And by the time it fails, our view callable is finished (or has thrown an >> > exception), so we can't branch code based on failure. >> > But, back down to earth, doing something like setting a value in session >> > when there is a transaction failure could lead to inconsistent state. Say a >> > view callable is supposed to log someone in... but a database transaction >> > fails. Meanwhile, our view callable has turned on "authenticated" in the >> > session, but they didn't actually login successfully... >> > It might be far-fetched, but I found it already ;-) Thankfully, not a >> > security breach, just a bad UI message, but still... >> >> The transaction should fail when the update query is run, not when it >> commits. So you shouldn't set the 'authenticated' flag until the query >> finishes without error. >> >> If there's an unrelated write later in the transaction and it fails... >> then you have to consider whether you should have committed the login >> immediately rather than waiting for the transaction manager to commit >> it later. I think the syntax is 'transaction.commit()'. You might also >> question whether two unrelated writes should be in the same >> transaction anyway, because of this very problem. Sometimes you have >> to commit each part separately rather than waiting for the transaction >> manager to commit it all. Other times you have to use a separate >> connection not managed by the transaction manager (for instance, to >> log the request to a logging database, which should commit even if the >> main transaction aborts). > > FWIW, I think the only 100% sensible solution is to use a transactional > storage for session data too. Partially committing "by hand" (or even > completely committing by hand) at various likely points to work around > the fact that a storage isn't transactional is always a guessing game > that you'll eventually lose. But when all of the storages are > transactional, and they're all managed by the transaction manager, you > don't need to think very hard, you just write the code as if it will > succeed, without paying attention to ordering or committing, and if > there's any error, the storages will all just be rolled back then.
I wasn't talking about sessions; I was talking about some random external resource. For sessions, well, Pylons doesn't have a transaction manager, and the issue of the database and session being inconsistent never came up. I think that's because Beaker has `session.save()` which acts like commit, and I probably tended to put my session writes at the very end of the view after the db transaction had succeeded. > > - C > > > -- > You received this message because you are subscribed to the Google Groups > "pylons-discuss" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/pylons-discuss?hl=en. > > -- Mike Orr <[email protected]> -- You received this message because you are subscribed to the Google Groups "pylons-discuss" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
