On Sat, Apr 14, 2007 at 12:41:55AM -0400, Perrin Harkins wrote:
> > If you have one sub:
> >
> >     do_stuff_and_send_mail {
> >
> >         {
> >             local $dbh->{AutoCommit} = 0;
> >             $object->do_stuff;
> >         } # commit (unless nested)
> >
> >         send_mail( "do_stuff happened!" );
> >     }
> >
> > Obviously, the mail won't be sent if there's an exception.  But, if
> > do_stuff_and_sent_mail() is called from code that's in a transaction
> > (nested transaction) then send_mail can happen, and after the sub
> > above returns an exception would roll back the entire transaction.
> > But send_mail() still already sent the mail.
> 
> I think I'm starting to see the problem.  It's not nested transactions
> that are an issue for you, it's nested exception handling.

> In my system, the code above will never run send_mail() if there's an
> exception.  It will throw the exception, nothing will catch it, and
<snip>

I'm very sorry for not making my self clear.  I originally named the above
"inner_sub", but sticking with its name above, now say I have an
outer sub:

    sub outer {

        {
            local $dbh->{AutoCommit} = 0;  # does a real begin

            $foo_object->save;



            # call the inner sub
            # does not do a begin or commit because it is nested

            do_stuff_and_send_mail();

            # do stuff completed and sent the mail
            # but the transaction is still active



            $foo_object->bad_action;  # database throws exception!

            # never gets here due to error

        } # commit would happen here if no exception

        # this code never happens.

    } # /outer()

So when that die is called the transaction is rolled back and nothing
sub outer() or do_stuff_and_send_mail() did is in the database.  But,
the mail still got sent (probably saying something happened that
didn't.)

That's why it might make sense to stuff things like sending mail onto
an array in the stash to run if there's no exceptions.

Catalyst has an end() action which is called regardless of the
exception:

sub end : Private {
    my ( $self, $c ) [EMAIL PROTECTED];

    if ( $c->exception_was_thrown ) {
        $c->log_excption;
        $c->status( 500 );
    } else {
        $c->run_delayed_subs;
    }

    [...]
}

Just need to be careful that nobody catches the exception before hand and
doesn't also clear the delayed subs.  Not very likely in Catalyst
since the controller actions tend to be small.


-- 
Bill Moseley
[EMAIL PROTECTED]


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Rose-db-object mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/rose-db-object

Reply via email to