Batch: refactor code and allow passing deps to check against.

master
Tom Hacohen 4 years ago
parent 653341115f
commit 23b2bb3c0a

@ -316,73 +316,48 @@ class CollectionItemViewSet(BaseViewSet):
@action_decorator(detail=False, methods=['POST']) @action_decorator(detail=False, methods=['POST'])
def batch(self, request, collection_uid=None): def batch(self, request, collection_uid=None):
stoken = request.GET.get('stoken', None) return self.transaction(request, collection_uid, validate_etag=False)
collection_object = get_object_or_404(self.get_collection_queryset(Collection.objects), uid=collection_uid)
if stoken is not None and stoken != collection_object.stoken:
content = {'code': 'stale_stoken', 'detail': 'Stoken is too old'}
return Response(content, status=status.HTTP_400_BAD_REQUEST)
items = request.data.get('items')
serializer = self.get_serializer(data=items, many=True)
if serializer.is_valid():
try:
with transaction.atomic():
items = serializer.save(collection=collection_object)
except IntegrityError:
# FIXME: should return the items with a bad token (including deps) so we don't have to fetch them after
content = {'code': 'integrity_error'}
return Response(content, status=status.HTTP_400_BAD_REQUEST)
ret = {
}
return Response(ret, status=status.HTTP_200_OK)
return Response(
{
"items": serializer.errors,
},
status=status.HTTP_400_BAD_REQUEST)
@action_decorator(detail=False, methods=['POST']) @action_decorator(detail=False, methods=['POST'])
def transaction(self, request, collection_uid=None): def transaction(self, request, collection_uid=None, validate_etag=True):
stoken = request.GET.get('stoken', None) stoken = request.GET.get('stoken', None)
collection_object = get_object_or_404(self.get_collection_queryset(Collection.objects), uid=collection_uid) with transaction.atomic(): # We need this for locking on the collection object
collection_object = get_object_or_404(
if stoken is not None and stoken != collection_object.stoken: self.get_collection_queryset(Collection.objects).select_for_update(), # Lock writes on the collection
content = {'code': 'stale_stoken', 'detail': 'Stoken is too old'} uid=collection_uid)
return Response(content, status=status.HTTP_400_BAD_REQUEST)
items = request.data.get('items') if stoken is not None and stoken != collection_object.stoken:
deps = request.data.get('deps', None) content = {'code': 'stale_stoken', 'detail': 'Stoken is too old'}
# FIXME: It should just be one serializer return Response(content, status=status.HTTP_400_BAD_REQUEST)
context = self.get_serializer_context()
context.update({'validate_etag': True})
serializer = self.get_serializer_class()(data=items, context=context, many=True)
deps_serializer = CollectionItemDepSerializer(data=deps, context=context, many=True)
ser_valid = serializer.is_valid() items = request.data.get('items')
deps_ser_valid = (deps is None or deps_serializer.is_valid()) deps = request.data.get('deps', None)
if ser_valid and deps_ser_valid: # FIXME: It should just be one serializer
try: context = self.get_serializer_context()
with transaction.atomic(): context.update({'validate_etag': validate_etag})
serializer = self.get_serializer_class()(data=items, context=context, many=True)
deps_serializer = CollectionItemDepSerializer(data=deps, context=context, many=True)
ser_valid = serializer.is_valid()
deps_ser_valid = (deps is None or deps_serializer.is_valid())
if ser_valid and deps_ser_valid:
try:
items = serializer.save(collection=collection_object) items = serializer.save(collection=collection_object)
except IntegrityError: except IntegrityError:
# FIXME: should return the items with a bad token (including deps) so we don't have to fetch them after # FIXME: return the items with a bad token (including deps) so we don't have to fetch them after
content = {'code': 'integrity_error'} content = {'code': 'integrity_error'}
return Response(content, status=status.HTTP_400_BAD_REQUEST) return Response(content, status=status.HTTP_400_BAD_REQUEST)
ret = { ret = {
} }
return Response(ret, status=status.HTTP_200_OK) return Response(ret, status=status.HTTP_200_OK)
return Response( return Response(
{ {
"items": serializer.errors, "items": serializer.errors,
"deps": deps_serializer.errors if deps is not None else [], "deps": deps_serializer.errors if deps is not None else [],
}, },
status=status.HTTP_400_BAD_REQUEST) status=status.HTTP_400_BAD_REQUEST)
class CollectionItemChunkViewSet(viewsets.ViewSet): class CollectionItemChunkViewSet(viewsets.ViewSet):

Loading…
Cancel
Save