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.

Reply via email to