[ZPatterns] TransactionAgents question
Steve Alexander
[email protected]
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