[ZPatterns] TransactionAgents question

Steve Alexander steve@cat-box.net
Fri, 14 Dec 2001 09:27:44 +0000


John Eikenberry wrote:

> John Eikenberry wrote:
> 
> 
>>A quick hack, but it shows the problem. The code in cause_error gets run
>>twice. This would succeed if it was pop'd from the queue when run the first
>>time.
>>
> 
> It seems that this wasn't quite right... as just popping the erroring agent
> off the queue will leave all the others to run. The correct behaviour (I
> think) would be to remove all agents left in any queue's and re-raise the
> error. 



Hmm... revisiting the code in TransactionAgents, I see that I left this 
comment in the new_commit method:

    # on an error, put the state back the way it was
    # not important for Zope use, but probably useful for ZODB


My thinking here (IIRC) is that for use in Zope, any exception raised by 
  the transaction machinery means that the transaction will be aborted, 
and the request retried. Therefore, it really doesn't matter what state 
the queues are in after an error.

I haven't really thought about the ZODB case, but it looked like a good 
idea to restore the original state of the queues on an error, so that 
the application can change its state and try commiting again.

You can read this in the try: except: clauses of the new_commit method.

In retrospect, this probably isn't such good behaviour, and as you've 
found, it doesn't take account of using subtransactions to "test the water".


I wonder what behaviour would be reasonable...


When an operation in an application adds an agent to the rule agents 
queue or the indexing agents queue, the successful execution of that 
agent is part of the same contract as the successful execution of the 
operation.

The only difference between having an operation + the agents it 
enqueues, and having the operation immediately execute the agents code 
is that the agents get to run at a more appropriate time: the end of the 
transaction.

We can split the fulfilment of the contract because it is all wrapped up 
in an atomic transaction, and so the rest of the world outside that 
transaction will not care whether we are using operation+agents or just 
bigger-operation.


If I understand correctly what you're doing, you want to use agents + 
subtransactions as a sort of "dummy run" to see if the agents are likely 
to run sucessfully when a "true" transaction or subtransaction comes 
along. Do I have that correct?

In which case, perhaps you don't really want to be commiting a 
subtransaction at all: you really want to just run the agents when you 
want, independently of commiting a transaction.

And... if these agents were to run in their own subtransaction, which 
gets aborted after they are run, you could re-run the agents later, when 
the transaction properly commits.


Of course, TransactionAgents doesn't do this at the moment -- but it 
shouldn't be too hard to add.

On the other hand, I might have misunderstood your requirements.

--
Steve Alexander