Hello,

Your first post:

        Transaction manager receives a green light for resource chain commit
and calls every resource enlisted. Resource1 tries to commit but fails with
an exception. AbstractTransaction  cathes the exception and stores it for
later use; the transaction is also given an invalid state. Resource2 is
called now (surprisingly for commit!).

Previously this was true in the code; during commit -- even if one resource
failed, all resources' commit method was called. However, now the code is
like this:

_Sem.AtomWrite(() =>
{
        AssertState(TransactionStatus.Active);
        Status = TransactionStatus.Committed;
});

_Sem.AtomRead(() => {

        _SyncInfo.ForEach(s => _Logger.TryLogFail(s.BeforeCompletion));

        foreach (var r in _Resources)
        {
                try { r.Commit(); } 
                catch (Exception e)
                {
                        SetRollbackOnly();
                        throw new CommitResourceException("Transaction could
not commit because of a failed resource.", 
                                e, r);
                }
        }
});

try
{
        _Logger.TryLogFail(InnerCommit) // commit transaction
                .Exception(e => { throw new TransactionException("Could not
commit", e); });
}
finally
{
        _Sem.AtomRead(() => _SyncInfo.ForEach(s =>
_Logger.TryLogFail(s.AfterCompletion)));
}

So as you can see, the first resource that fails instructs the transaction
manager (transitively since rollbackonly is a property of a transaction),
that the transaction shouldn't be committed.

So indeed this has changed.

I wasn't with this project from the beginning, but in my mind this is a
wrapper around transacted resources, not a project implementing 2PC or even
1PC; in order to do so we would have to keep a log file that is flushed to
and make sure that the transaction manager can restore state after a system
restart or failure.

Instead what the project does is to call the appropriate kernel transaction
and resource managers, implemented in MS DTC, the kernel or the database of
the choice.

As such, resources aren't fulfilling the properties of ACID; but rather a
convenience for use together with transactions. They can keep track of state
changes before and after commits but shouldn't be expected to be
transactional themselves, like it seems you are trying to make them. For
example, the isolation property between a resource and its transaction
doesn't garantuee that the resource won't see transient data, so it doesn't
hold.

But looking at your initial message and what the code is now, I would say
that your specific case has been fixed for. It might be however that I have
misunderstood what you are after. If you want multiple transactions, why
can't you do:

using (var t = new TransactionScope())
{
        IoC.Resolve<Intercepted1>().Invoke();
        IoC.Resolve<Intercepted2>().Invoke();
        t.Complete()
}

...

[Transactional] class Intercepted1 { [Transaction] public virtual void
Invoke(){}}
[Transactional] class Intercepted2 { [Transaction] public virtual void
Invoke(){}}

If these use different end-point resources, e.g. different servers running
databases, or TxF + SQL Server for example, the default transaction mode
would be enlist and both would be enlisted in DTC, giving you 2PC and ACID
across Intercepted1 and Intercepted2.

If this doesn't match your requirements, could you send me some code that
demonstrates the functionality you are after? You don't have to send it on
the mailing list if it's proprietary code.

Cheers,
Henrik

-----Original Message-----
From: [email protected]
[mailto:[email protected]] On Behalf Of MoonStorm
Sent: den 15 mars 2010 12:26
To: Castle Project Users
Subject: Re: Transaction Management - The chain of resources not rolled back
if one fails

I had some time to look at the new code. Unfortunately the issue
presented in my first post is still present. Thinking about it though,
this is a case that can't be easily solved. Probably a two stage
commit would be able to handle this properly, IF the workhorse is
implemented in an aditional "prepare for commit" stage (i.e. the
resource is pushing the data in a temp remote container in the
"prepare for commit" stage and the "commit" afterwards is just
performing a switch remotely to make the data available for retrieval
by others).

I would love to hear your thoughts about this.

-- 
You received this message because you are subscribed to the Google Groups
"Castle Project Users" 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/castle-project-users?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"Castle Project Users" 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/castle-project-users?hl=en.

Reply via email to