- From: Assaf Arkin <arkin@intalio.com>
- Date: Fri, 10 Jan 2003 15:06:34 -0800
- To: "Walden Mathews" <waldenm@optonline.net>, "Peter Furniss" <peter.furniss@choreology.com>, "Champion, Mike" <Mike.Champion@SoftwareAG-USA.com>, <www-ws-arch@w3.org>
> Nope. There is another way. But before getting into that, are we sure > the legacy app doesn't support idempotent operations? I hope you're not > positing that idempotence in interfaces is unusual or scarce. All > operations > that are essentially assignments fit the bill. On the contrary. I know that a lot of operations are idempotent. I just know that not all operations are idempotent. What I need is an architecture that works with both. I also know that some non-idempotent operations can be made idempotent (as you proved with a very eloquent example). And I favor idempotent operations. So given such a transformation I could make even more operations idempotent. But I still know that some operations are non-idempotent. If you can prove that every non-idempotent operation can be made idempotent without shifting the problem away, then I could devise an architecture built solely on idempotent operations. If you shift the problem away, I would have to start considering cost/benefit. Now, back to the example. Consider depositing and withdrawing funds in an account. The client wants to deposit $50. The client knows there are $100 in the account. A non-idempotent operation would let the client do a deposit, but the client must perform the deposit exactly once. An idempotent operation would let the client change the account balance to $150. But the client must guarantee that the account balance is $100 to begin with. So the client needs to send known balance, new balance. This operation if serializable would work well in a concurrent application. If the balance has changed, the operation would simply return abort, the client would read the balance again and set the new balance. That actually means more work for the client and tigher coupling between the client and the server. So for a banking application, I would prefer the non-idempotent operation over the idempotent one. It's easier to guaqrantee integrity when the bank trusts their system to get it right rather than the customer to decide what the new balance is. The non-idempotent deposit operation can be built using a sequence of idempotent operations. So it would determine the current balance, then ask for a new balance given known balance, new balance. And if it receives abort retry the operation. No need to use transactions. Looks much like your example. But now I actually have client->server->server, where the second server is both a client and a server. Now, I can always build the third server to have just idempotent operations. And I can disregard the first client, so in this model all operations are idempotent. But, while that would work inside the banking network (between any two banks), it would not work in a wider system, i.e. one including ordinary customers and banks. It shifts the problem away, but at some point we have to consider that the original client exists and propose an architecture that serves equally well both original client and server-client. There is yet another way to do it. This is how you would reconcile checks. The client would indicate a deposit from check no. XYZ. That operation is idempotent, i.e. you can repeat it any number of times you want, you would always deposit the funds exactly once. The server looks at the check number and determines whether the check has been cashed. If the check has been cashed it does nothing. If the check has not been cashed it cashes the check (one operation) and deposits the funds (another operation). Recording the fact that the check was cashed is idempotent, depositing funds is not, so the sequence is non-idempotent but it is wrapper as idempotent. So eventually, something somewhere is non-idempotent. The only question is: is that operation exposed as a service in a given architecture. If that operation is not exposed as a service (e.g. the entire thing is done in one piece of COBOL code) then the architecture could accept that only idempotent operations exists. But the architecture requires coarse granularity. If that operation is exposed as a service (e.g. a stored procedures and COBOL code that invokes them, recast into a Web service and a client application), then the architecture has to account for both possibilities. The later architecrure has broader applications. I may favor to build my application around an architecture that has less applications but is more optimal for my application, but I don't want to be constrained by choice either. arkin > > Let's say we have a legacy app that keeps track of the number of chart > windows you're allowed to run on your market data workstation, and > it only allows you, through its interface, to change that number by adding > or subtracting, never directly setting the number. > > To manufacture an idempotent web interface to this, we will wrap the > legacy app with some code that is local to and tightly coupled to the > legacy app. Being so situated, it has access to critical sections and > transactions and such. > > The existing count, in our scenario is two, but the client wants a total > of four. Via the web interface, the client says, in effect "set count to > four". > Idempotent. Note that client doesn't care what the current count is, and > more importantly, doesn't need to know in order to achieve its goal. > > Wrapper code receives "set to four" from client, then it enters a critical > section or transaction with legacy code in which it > > - reads current quantity : 2 > - computes difference: 4 - 2 = 2 > - invokes non-idempotent update: +2 > - re-reads (new) current quantity: 4. > > Finally, the wrapper code returns the appropriate response to the client, > in this case an indication of success. > > The fact that the legacy back end didn't support a "set" operation is > transparent to the client; no fiddling with sequence numbers and special > ids or any of that crap. I would also note that this is easy programming > on the server side. > > Comments? > > Walden >
Received on Friday, 10 January 2003 18:07:53 UTC