Re: No validator in 200 response for conditional update

As you have said, we are talking about an "edge case of an edge case":
1. If precondition is satisfied, then process; otherwise
2.1. Respond with 412 Precondition Failed, or
2.2. If the proposed change has been reflected, MAY respond with 2xx
(Success), and
2.2.1. If current request is a duplicate of an immediately prior change
made by the same user agent, MAY send etag, otherwise
2.2.2. MUST NOT include etag in the response.

Why do we specify 2.2.1 and 2.2.2? I believe Vladimir has some traffic
pattern that match 2.2, where 2xx Success is more informative than 412
Precondition failed, but determining whether to send an etag or not leads
to extra development effort.

Yishuai

Julian Reschke <julian.reschke@gmx.de> 于2018年11月7日周三 上午2:51写道:

> On 2018-11-06 23:35, Vladimir Lashchev wrote:
> > Thanks for your replies!
> >
> > In general, since the spec says that server "MUST NOT" send an ETag in
> some case so in order to comply with the spec we must implement that logic
> and it does not matter if it is a corner case or if it may happen only once
> in our API. In reality it is actually not an edge case and happens quite
> often (up to single digit % of all requests in high volume concurrent
> scenarios).
>
> Are we talking about the same thing?
>
> 1) It needs to be a state-modifying request,
>
> 2) That comes with a validator,
>
> 3) The validator doesn't match, but the current state of the resource does.
>
> So this only happens when multiple clients do concurrent updates of a
> resource, and write the same content.
>
> It would be interesting to understand why this happens so frequently -
> can you provide more information about the type of the server/service?
>
> > 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).
> >
> > Actually, scenario of that 2xx clause (as I read it) is a bit more
> complicated - it applies in the case when 2 agents (A1 and A2) are talking
> to the sever and trying to apply semantically same changes or same agent
> asks for the same change in non-consecutive requests. Here is my
> understanding:
> > 1) "state change is being requested and the final state is already
> reflected in the current state" ==> means that requests may not be
> identical, as long as they ask for the same end-result state.
> > 2) "server MUST NOT send a validator header field in the response unless
> it can verify that the request is a duplicate of an immediately prior
> change made by the same user agent " ==> means that:
> > a) server MUST NOT send ETag to A2 if state change was done by A1, but
> similar change is requested by A2
> > b) server MUST NOT send ETag to A1 if state change was done by A1 but
> there was some other request (even GET without any side-effects) between
> that original change request and a new, semantically-identical change
> request.
>
> In-between GET requests may be covered by "duplicate of an immediately
> prior change made by the same user agent" -  but maybe this could be
> made more clearer.
>
> > So expanding on Yishuai's example to include all cases it would be
> something like:
> >
> > (step 1) A1 --> S : PUT "a" (unconditional)
> > (step 2) S --> A1 : 204 No Content, ETag: "a"
> > (step 3) A1 --> S : PUT "a", If-Match: "b" (not satisfied)
> > (step 4) S --> A1 : 204 No Content, ETag: "a" (same change-originating
> agent, same end-result requested in the immediate prior request)
> > (step 5) A2 --> S : PUT "a", If-Match: "b" (not satisfied)
> > (step 6) S --> A1 : 204 No Content (No ETag) (not a change-originating
> agent, same end-result requested)
> > (step 7) A1 --> S : GET ... (unconditional, no side-effects)
> > (step 8) S-> A1 (doesn't matter what is replied here)
> > (step 9) A1 --> S : PUT "a", If-Match: "b" (not satisfied)
> > (step 10) S --> A1 : 204 No Content (No ETag) (same change-originating
> agent, same end-result requested, but not in the immediate prior request)
> > (step 11) A3 --> S : PUT "zzz", If-Match: "b" (not satisfied)
> > (step 12) S --> A1 : 412 No Content (No ETag) (any agent, different
> end-result requested)
> >
> > My question is about (step 6) and (step 10) where server MUST NOT send a
> ETag value back.
> > Above is quite complicated logic required without explanation and it is
> not clear of how it is better/safer than simple and stateless:
> > (step 1) A1 --> S : PUT "a" (unconditional)
> > (step 2) S --> A1 : 204 No Content, ETag: "a"
> > (step 3) A1 --> S : PUT "a", If-Match: "b" (not satisfied)
> > (step 4) S --> A1 : 204 No Content, ETag: "a" (any agent, same
> end-result requested)
> >   (step 11) A3 --> S : PUT "zzz", If-Match: "b" (not satisfied)
> > (step 12) S --> A1 : 412 No Content (No ETag) (any agent, different
> end-result requested)
> > ...
>
> You always have the choice of not replying with 204 but with 412, in
> which case the server logic would be simpler, but clients would need to
> do more work.
>
> Which brings me back to my question about what kind of server this is
> that shows this type of traffic pattern.
>
> Best regards, Julian
>

Received on Wednesday, 7 November 2018 12:54:44 UTC