- From: Assaf Arkin <arkin@intalio.com>
- Date: Wed, 21 May 2003 21:58:55 -0700
- To: Ricky Ho <riho@cisco.com>
- CC: public-ws-chor@w3.org
Ricky Ho wrote: > > There are a couple of issues .... > > Lets say in the following process > > <process> > <sequence> > .... > <receive/> > .... > <reply/> > .... > <receive/> > .... > <reply/> > .... > </sequence> > </process> > > 1) Lets say the first <receive> pass in a transaction context. What > is the "scope of work" ? Between the first request and first reply ? > or everything after the first receive ? That depends on how you define the importing of the context. If you define the scope as the entire sequence then it will start with the first receive but it will end all the work after the last activity has occurred (i.e. after the second reply). The sender is not just waiting for a reply, the sender is also waiting to later on either receive a completed, exited, or failed message indicating that all further work done after the reply has completed/failed. If the scope is for a single activity than only that activity is performed, but again after the reply is sent you still need to send completed/exited/failed which you could potentially piggyback on the reply message (though not allowed in WS-TX currently). > 2) Lets say after receiving the first <reply>, the caller want to > commit the transaction. What scope of work has been committed ? Does > the caller wait for this whole process to be completed before the > caller's transaction can commit successfully ? If we are talking BA then there are two modes: either you tell the process when all work has been completed so it can wrap up things on its side and send a completed/exited message, or you wait for it to tell you when it completes and then wait for all others to tell you they completed. In case of aborting, you would just tell working scopes to cancel and completed scopes to compensate. The important thing here is that you should say what you mean and mean what you say. If what you meant is that no work could be completed unless you received two requests, then that's what should happen. If someone tries to commit before you completed all the work you consider this to be an inconsistent state and vote to rollback. This means that you will never do part of the work - either all or nothing. If what you meant is that only some work needs to be done and the rest is optional, you should write it as such, perhaps by using an event handler. > 3) If instead the caller want to cancel the transaction. How does the > process cancel its work ? Where is the compensation handler defined ? Since you haven't yet completed the sequence you can't compensate for it. Instead you get a terminate fault and handle it. However, since you already did some activities you may have nested scopes with their own compensation handlers which you would invoke from the event handler of the sequence. > 4) What if the second <receive> pass in a different context ? (the > only way to prevent this happening is to use the context itself as the > correlation set) Good question. In EJB if you have a session bean and you call it twice in two different transactions then the access would be serialized or you would get an error. I don't exactly remember which case is true, but you won't get two invocations from two transactions for the same bean if one transaction has not completed yet. So I would tend to believe that the rule should be that all incoming messages should either be part of the same scope, part of a child scope (if that activity is defined as part of a child scope), or not associated with any scope. But it can't be part of a different scope unless it observes a parent-child relationship. >> So it would work like the transaction attribute requires in an EJB >> bean. Either you start a new transaction if none was started by the >> caller, or you participate in the caller's transaction. > > > BPEL <Receive> is quite different from the EJB scenario. The EJB > doesn't have a pre-establish transaction context, it either starts a > new context or inherit the caller's context. In EJB, you never run > into the situation of the above question 4. I think you do. If you think of a session bean, once you access it from a transaction it is owned by that transaction until it commits. You can keep calling it from that transaction, but you can't call it from another transaction at the same time. That would just confuse the hell out of it ;-) The case here is of course more complex because you have more explicit sequencing rules, a problem you also have with EJB but don't notice because there is no language to write the behavior, and because you have nesting. >> For atomic transactions you don't need prepare or commit, you are >> working at a higher level than the code and all that needs to be >> prepared or committed should be done by the engine for you. For BA >> transactions you don't have prepare or commit, every response is an >> indication that all previous steps have been completed (prepared and >> committed). You do need a way to cancel, but this can be done by a >> fault handler (the terminate fault). And you do need a way to >> compensate and this is done by a compensation handler. > > > I'm talking about BA, not atomic. Effectively, you restrict the > choices by forcing every scope of work must be compensatable. > Lets say I'm an airline company. I don't want to reserve the seat for > a lengthy period and later cancel it when the passenger change his > mind. So my strategy is to only book the seat when the customer > commits its purchase. After that, I don't refund (so not > compensatable from the passenger's perspective). > The original state of the seat is "available". When the passenger > invoke my "TicketBookingService", the seat is marked > "potentially-booked". When the transaction commit successfully, the > seat status to be "booked". After that, it is non-compensatable. > > How do I achieve this if I only have the CompensationHandler ? You have one activity (possibly a sequence) that changes the seat assignment to "reserved". Afterwards it can be cancelled by the customer or it can be cancelled because the customer did not send a booking request within a well defined time frame (e.g. use a switch with message event and time-out event). If it gets cancelled then you invoke the compensation of the first activity changing it back to "available". If you do receive a request to book the seat you proceed to the next step. At this point the state is "booked" and there is no compensation associated with the previous state. I think as a basic shell you would have to write something like: process compensationHandler empty (note: very important to write something here so it doesn't automatically compensate reserveToBook) receive reservation request scope name=reserveToBook invoke name=reserve compensationHandler ... change back to available ... this is where we talk to a service that changes state to reserved pick branch 1: booking request change to booked branch 2: alarm throw a fault do anything else after reservation arkin > > > Rgds, Ricky -- "Those who can, do; those who can't, make screenshots"
Received on Thursday, 22 May 2003 01:01:47 UTC