Re: No validator in 200 response for conditional update

On 14/11/18 11:21 AM, Vladimir Lashchev wrote:
>> From: Amos Jeffries
>> Sent: Tuesday, November 6, 2018 5:03 PM
>> On a side note;
>>
>> My understanding of the expected behaviour is that agents doing a lot of
>> repeats are broken in some way. Probably their author misunderstood that
>> 412 is *not* an error.
>>
>> A 4xx is just a notice from the server to the agent that the requested
>> change/fetch was not enacted. Not really errors in the way we tend to think
>> of errors in software.
>>
>> So agents receiving back a 412 with ETag matching the one they tried to set
>> the resource to - should usually treat that as as much a success as any 2xx
>> they get. It is only when the 412 ETag is different that the agent needs to
>> figure whether to try again, and HTTP cannot help by specifying anything
>> about that decision.
> 
> Actually 412 is a proper error as I see it.
> Server denies modification request and indicates that request was not successfully processed (desired resulting state was not achieved).

You are assuming "state" here. Which is wrong and leading you to a wrong
conclusion.

412 states that the _preconditions_ in that individual request were not
obtainable. By itself it does not say anything about any state beyond
the individual request message being responded to.

The ETag validator is the only bit involving any higher-level state and
that has a defined meaning agnostic of the status code.



> I don't see a scenario where client can treat it as a success. It is a failed update in an optimistic concurrency flow.
> 

When the precondition fails because the Etag has already been changed to
a) the desired one, or b) something even newer than the desired one.


The exact edge-edge-case under discussion here is one situation where
the desired state *was* achieved without the preconditions being true.
It just happened to be achieved previously by an earlier change request.


> Anyway, my question is actually about 2xx response and not 412 :-)
> 

And the answer perhaps is "why 2xx when 412 conveys the desired meaning".


>>> That's why I am trying to understand the reason because that clause calls for a lot of development.
>>> Why "a lot" of development?
>>> Because the clause "... unless it can verify that the request is a duplicate of
>> an immediately prior change made by the same user agent ..." requires us to
>> persistently track previous requests from all clients which is a huge infra
>> requirement for stateless API server farms (which is a typical design for
>> servers with high performance requirements).
>>
>> I fail to see how there is any difference in overhead for a large farm than for
>> a single server. All that needs to be tracked is what the current ETag validator
>> is and which agent made it exist. Usually those would exist anyway in server
>> state as author and version IDs.
> 
> Request #2 can come to any server in the farm and spec calls that all servers should know about previous request from that agent so they can decide whether to send ETag back or not.
> It calls for state sharing among all the servers and thus they become not stateless (which we do not want to have).
> 

That is not my interpretation.

The spec is written in terms of individual request-response
transactions. Not in terms of client-service transactions - which may
span multiple request-response transactions in a stateful way.



>> In a large farm each stateless server may be tracking a different version of
>> the object (or not) with its own ETag + agent labels. That is a given implied by
>> them being stateless. The condition rules from the request are applied by
>> the individual server against its own object(s) copy regardless of what other
>> objects might be elsewhere or what might have happened in old history for
>> the relevant local object(s).
> 
> Spec is defining how a particular server in a farm should behave - it defines API endpoint contract.

Agreed.

> Endpoint is deployed at reverse proxy that is fanning out requests to a farm of identical servers.

"server" does not mean "server state". The underlying HTTP protocol /
contract is stateless. The service layer above usually has state, but
may not.


> We don't have sticky session, so modification request #2 can be processed on a different server from where request #1 was processed.
> Spec defines how client will see the response regardless of how many servers we have, so it should not matter on what worker server it was processed.

Here you assume a relationship between end-servers which is beyond
anything HTTP covers.


The spec / API contract outlines the set of valid responses to any given
request. The meanings for various parts of the message is relative to
the status and the request type.

The spec does *not* dictate statefulness between servers which would
lead to identical behaviour.


Yes there is a design problem inherent in that, but by remaining
strictly stateless HTTP pushes it up to the layer above. There are many
possible solutions to that and IIRC most if not all of them, are
actively used somewhere.


> 
>> You _can_ do sharing of updates + info between the servers. But that is up to
>> the implementation and kind of disolves the claim of being stateless.
> 
> Yes, and we don't want state sharing.
> 

Then you need the client endpoints to be robust against servers being at
different update levels with their internal state.

Such as by using the spec interpretation roughly along the lines I used
earlier to guide design decisions in the client software:

* 5xx are service errors, the client unlikely able do anything to fix
(some exceptions where it can retry).

* 4xx notices that the request did not go exactly as client intended,
with hints to the client about why. Leaving the client to decide if
retry is worth doing based on those hints.

* 2xx everything went exactly as planned. Nothing further for the client
to consider.


If you try to go beyond that to push multiple meaning into the 2xx
status is when you hit problems with whether ETag is possible to send at
all, or what value to send when the server is *more* up to date than the
client.
 Both semantically have the same "I could not do this because I have
object "a"' meaning. The client is the agent which knows best whether
that situation ignorable or needs handling.

AYJ

Received on Wednesday, 14 November 2018 05:35:46 UTC