Skip to content

Commit

Permalink
Account for clashes that arise during download/update OR whilst uploa…
Browse files Browse the repository at this point in the history
…ding the file to storage and saving
  • Loading branch information
ababic committed Jul 2, 2024
1 parent 022ebeb commit 64e471a
Showing 1 changed file with 23 additions and 17 deletions.
40 changes: 23 additions & 17 deletions src/wagtail_bynder/views/mixins.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import contextlib

from typing import TYPE_CHECKING

from django.conf import settings
Expand All @@ -13,7 +15,6 @@


class BynderAssetCopyMixin:

model = type[BynderAssetMixin]

def create_object(self, asset_id: str) -> BynderAssetMixin:
Expand All @@ -22,24 +23,29 @@ def create_object(self, asset_id: str) -> BynderAssetMixin:
data = client.asset_bank_client.media_info(asset_id)
obj.update_from_asset_data(data)
try:
obj.save()
except IntegrityError as ie:
# If the asset finished saving in a different thread during the download/update process,
# return the pre-existing object
return self.model.objects.get(bynder_id=asset_id)
except self.model.DoesNotExist:
try:
# If the 'bynder_id' is already taken, find the existing object to return
existing = self.model.objects.get(bynder_id=asset_id)
except self.model.DoesNotExist:
# The error must relate to a different field, so throw the original error
raise ie from None
else:
# If the new file was copied to media storage, ensure it is deleted
# Save the new object, triggering transfer of the file to media storage
obj.save()
except IntegrityError as integrity_error:
# It's likely the asset finished saving in a different thread while the file was
# being transferred to media storage
try:
if obj.file.path != existing.file.path:
obj.file.delete()
except (ValueError, FileNotFoundError):
pass
return existing
else:
return obj
# Lookup the existing object
pre_existing = self.model.objects.get(bynder_id=asset_id)
except self.model.DoesNotExist:
# The IntegrityError must have been caused by a custom field, so reraise
raise integrity_error from None
else:
# If the newly-downloaded file was successfully copied to storage, delete it
with contextlib.suppress(ValueError, FileNotFoundError):
if obj.file.path != pre_existing.file.path:
obj.file.delete()
return pre_existing
return obj

def update_object(self, asset_id: str, obj: BynderAssetMixin) -> BynderAssetMixin:
client = get_bynder_client()
Expand Down

0 comments on commit 64e471a

Please sign in to comment.