Rest – Idempotency and concurrency in a REST web service

designrestweb services

Is concurrency and idempotency mutually exclusive for a REST web service or can it be done so a service can be both concurrent and idempotent? Using a optimistic lock methodology like using Version property seem to be preventing a method to be idempotent if I'm not mistaken?

For example, let's say you have User A wanting to update Person.Name

Current Person.Version = 1

User A sets

Person.Name = "Name X"
Person.Version = 2

Now the Person.Version = 2

User A send same request, with Person.Version = 2 value. It fails because you expect the Person.Version value 3.

Best Answer

Is concurrency and idempotency mutually exclusive for a REST web service or can it be done so a service can be both concurrent and idempotent?

Yes, of course

User A send same request, with Person.Version = 2 value. It fails because you expect the Person.Version value 3.

I think you are confusing a couple different ideas.

From Gregor Hohpe

The term idempotent is used in mathematics to describe a function that produces the same result if it is applied to itself, i.e. f(x) = f(f(x)).

In Messaging this concepts translates into the a message that has the same effect whether it is received once or multiple times. This means that a message can safely be resent without causing any problems even if the receiver receives duplicates of the same message.

So the first thing to notice in your system is that the effect on the receiver of sending the same message twice is the same as sending it exactly once.

The advantage being that it is safe for the sender to repeat the message as many times as necessary to receive an ack.

Now, in your example, you seem to be expecting something beyond that, which is that the repeated message generates the same response. That's an awesome property for your system to have, but it requires a bit more work.

The basic plot is that your server receives the duplicated message, and checks to see if it has already been handled. A naive approach would be to look at the version, and check if the change applied in this version has already been applied.

Specifically, the server gets the second message, sees that it's already on version 2, sees that the name is currently equal to "Person X", and returns success!

It's not such a great answer if somebody else slips in another change between the duplicate messages.

A real implementation is more complicated - the basic form of it is to keep track of the responses you send, and when you get a duplicate message, you send back the same response that you sent before. Udi Dahan covers this approach. The persistence of the responses is in the domain model, so the messaging is still stateless, which satisfies the REST constraint.