1
0
mirror of https://github.com/etesync/server synced 2024-12-29 10:48:07 +00:00

Gracefully handle uploading the same revision

This is needed so that immediately re-played requests don't fail.

Consider for example the following scenario: a client makes a batch
request that registers correctly on the server, but fails to return
(e.g. a networking error after the request has been processed). The
client would think that the request failed, but the server will already
have the up to date information. This commit just returns a successful
status if this request is sent again (by the client retrying the
request) instead of returning a conflict.

This however doesn't handle the case of a request failing, a
modification being made by another client, and then the request being
retried. This case will stay fail.
This commit is contained in:
Tom Hacohen 2020-12-27 10:53:01 +02:00
parent 2de51b978a
commit 5a6c8a1d05

View File

@ -239,6 +239,11 @@ class CollectionItemSerializer(BetterErrorsMixin, serializers.ModelSerializer):
# We don't have to use select_for_update here because the unique constraint on current guards against # We don't have to use select_for_update here because the unique constraint on current guards against
# the race condition. But it's a good idea because it'll lock and wait rather than fail. # the race condition. But it's a good idea because it'll lock and wait rather than fail.
current_revision = instance.revisions.filter(current=True).select_for_update().first() current_revision = instance.revisions.filter(current=True).select_for_update().first()
# If we are just re-uploading the same revision, consider it a succes and return.
if current_revision.uid == revision_data.get("uid"):
return instance
current_revision.current = None current_revision.current = None
current_revision.save() current_revision.save()