Filter by stoken: cleanup and fix the done implementation

The done implementation wasn't great because it would indicate we are
not done even when we are when the last chunk returned is exactly the
size of limit.
This commit is contained in:
Tom Hacohen 2020-06-24 14:34:03 +03:00
parent 61383b9896
commit 0ce2e8d996

View File

@ -119,7 +119,7 @@ class BaseViewSet(viewsets.ModelViewSet):
maxid = max(maxid, rowmaxid) maxid = max(maxid, rowmaxid)
new_stoken = (maxid >= 0) and Stoken.objects.get(id=maxid).uid new_stoken = (maxid >= 0) and Stoken.objects.get(id=maxid).uid
return queryset, new_stoken return new_stoken
def filter_by_stoken_and_limit(self, request, queryset): def filter_by_stoken_and_limit(self, request, queryset):
limit = int(request.GET.get('limit', 50)) limit = int(request.GET.get('limit', 50))
@ -127,13 +127,16 @@ class BaseViewSet(viewsets.ModelViewSet):
queryset, stoken_rev = self.filter_by_stoken(request, queryset) queryset, stoken_rev = self.filter_by_stoken(request, queryset)
stoken = stoken_rev.uid if stoken_rev is not None else None stoken = stoken_rev.uid if stoken_rev is not None else None
queryset = queryset[:limit] result = list(queryset[:limit + 1])
queryset, new_stoken = self.get_queryset_stoken(queryset) if len(result) < limit + 1:
new_stoken = new_stoken or stoken done = True
# This is not the most efficient way of implementing this, but it's good enough else:
done = len(queryset) < limit done = False
result = result[:-1]
return queryset, new_stoken, done new_stoken = self.get_queryset_stoken(result) or stoken
return result, new_stoken, done
# Change how our list works by default # Change how our list works by default
def list(self, request, collection_uid=None): def list(self, request, collection_uid=None):
@ -193,9 +196,9 @@ class CollectionViewSet(BaseViewSet):
def list(self, request): def list(self, request):
queryset = self.get_queryset() queryset = self.get_queryset()
queryset, new_stoken, done = self.filter_by_stoken_and_limit(request, queryset) result, new_stoken, done = self.filter_by_stoken_and_limit(request, queryset)
serializer = self.get_serializer(queryset, many=True) serializer = self.get_serializer(result, many=True)
ret = { ret = {
'data': serializer.data, 'data': serializer.data,
@ -260,9 +263,9 @@ class CollectionItemViewSet(BaseViewSet):
if not self.request.query_params.get('withCollection', False): if not self.request.query_params.get('withCollection', False):
queryset = queryset.filter(parent__isnull=True) queryset = queryset.filter(parent__isnull=True)
queryset, new_stoken, done = self.filter_by_stoken_and_limit(request, queryset) result, new_stoken, done = self.filter_by_stoken_and_limit(request, queryset)
serializer = self.get_serializer(queryset, many=True) serializer = self.get_serializer(result, many=True)
ret = { ret = {
'data': serializer.data, 'data': serializer.data,
@ -321,7 +324,7 @@ class CollectionItemViewSet(BaseViewSet):
revs = CollectionItemRevision.objects.filter(uid__in=etags, current=True) revs = CollectionItemRevision.objects.filter(uid__in=etags, current=True)
queryset = queryset.filter(uid__in=uids).exclude(revisions__in=revs) queryset = queryset.filter(uid__in=uids).exclude(revisions__in=revs)
queryset, new_stoken = self.get_queryset_stoken(queryset) new_stoken = self.get_queryset_stoken(queryset)
stoken = stoken_rev and stoken_rev.uid stoken = stoken_rev and stoken_rev.uid
new_stoken = new_stoken or stoken new_stoken = new_stoken or stoken
@ -461,8 +464,8 @@ class CollectionMemberViewSet(BaseViewSet):
def list(self, request, collection_uid=None): def list(self, request, collection_uid=None):
queryset = self.get_queryset().order_by('id') queryset = self.get_queryset().order_by('id')
queryset, new_stoken, done = self.filter_by_stoken_and_limit(request, queryset) result, new_stoken, done = self.filter_by_stoken_and_limit(request, queryset)
serializer = self.get_serializer(queryset, many=True) serializer = self.get_serializer(result, many=True)
ret = { ret = {
'data': serializer.data, 'data': serializer.data,