RE: Proposed text on reliability in the web services architecture

> 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