We (at 5apps) store metadata in Redis, and only return 200s for PUTs when the ETAGs have been written there. There is a remote chance that you could receive an outdated ETAG, but I don’t think it’s very likely.
I would rather suspect the client to queue the additional update with an old/wrong ETAG in the If-Match
request header, which is sent to ensure that you don’t overwrite something that you have not already seen locally.
Example:
- You are in a synced state for document
foo.json
, with ETAG 123 known both to the server and you - You modify the document locally
- A PUT is queued with ETAG 123 in
If-Match
, to only overwrite what you have synced - Another PUT is queued with the ETAG 123 before the previous PUT has returned a new ETAG
- The previous PUT has now updated the document on the server, and given it ETAG 456
- The second PUT is trying to update
foo.json
with ETAG 123 - The server refuses to overwrite the document, returning a 412
Warning: this is just a guess for now, as I haven’t looked into when the headers for the PUT are constructed. The Sync class is one of the most complex in the codebase, and none of the current maintainers have originally written it. The TypeScript port was actually motivated by trying to refactor that class and not being able to keep track of the types of data being moved around the many functions that are involved both inside and outside of that class. But perhaps the example is at least helpful for finding the actual bug in the end.