mirror of
https://github.com/ansible/awx.git
synced 2026-10-30 22:16:19 -02:30
[devel][forwardport] AAP-83773 — Use unfiltered count for activity stream pagination (#16557)
* AAP-83773 — Use unfiltered count for activity stream pagination Forward-port of tower#7606 (stable-2.6). The RBAC-filtered COUNT(*) on activity_stream takes ~36 min per call on large tables (713K rows) due to the pk__in subquery shape introduced by the AAP-81860 LEFT JOIN fix. Replace with an unfiltered table count for pagination -- an approximate over-count is harmless for UI page navigation while the actual page results remain RBAC-filtered. * AAP-83773 — Add unit tests for ActivityStreamPagination Cover ActivityStreamPaginator and ActivityStreamPagination to satisfy SonarCloud coverage gate on new lines in awx/api/pagination.py. * AAP-83773 — Save/restore django_paginator_class in base Pagination Address review feedback from lallen92: use a save/restore pattern in Pagination.paginate_queryset() so subclasses only need to set the class attribute. Remove the now-redundant paginate_queryset override from ActivityStreamPagination. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Liam Allen <lallen@redhat.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
Liam Allen
parent
2a28b80ec6
commit
10f2f11fe2
+22
-1
@@ -6,12 +6,15 @@ from collections import OrderedDict
|
||||
# Django REST Framework
|
||||
from django.conf import settings
|
||||
from django.core.paginator import Paginator as DjangoPaginator
|
||||
from django.utils.functional import cached_property
|
||||
from rest_framework import pagination
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.utils.urls import replace_query_param
|
||||
from rest_framework.settings import api_settings
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from awx.main.models import ActivityStream
|
||||
|
||||
|
||||
class DisabledPaginator(DjangoPaginator):
|
||||
@property
|
||||
@@ -23,6 +26,19 @@ class DisabledPaginator(DjangoPaginator):
|
||||
return 200
|
||||
|
||||
|
||||
class ActivityStreamPaginator(DjangoPaginator):
|
||||
"""Use unfiltered table count for activity stream pagination (AAP-83773).
|
||||
|
||||
The RBAC-filtered COUNT query takes ~36 min on large tables due to the
|
||||
pk__in subquery shape from AAP-81860. An unfiltered count is acceptable
|
||||
for pagination UI -- an approximate over-count is harmless.
|
||||
"""
|
||||
|
||||
@cached_property
|
||||
def count(self):
|
||||
return ActivityStream.objects.count()
|
||||
|
||||
|
||||
class Pagination(pagination.PageNumberPagination):
|
||||
page_size_query_param = 'page_size'
|
||||
max_page_size = settings.MAX_PAGE_SIZE
|
||||
@@ -57,12 +73,13 @@ class Pagination(pagination.PageNumberPagination):
|
||||
|
||||
def paginate_queryset(self, queryset, request, **kwargs):
|
||||
self.count_disabled = 'count_disabled' in request.query_params
|
||||
original_paginator = self.django_paginator_class
|
||||
try:
|
||||
if self.count_disabled:
|
||||
self.django_paginator_class = DisabledPaginator
|
||||
return super(Pagination, self).paginate_queryset(queryset, request, **kwargs)
|
||||
finally:
|
||||
self.django_paginator_class = DjangoPaginator
|
||||
self.django_paginator_class = original_paginator
|
||||
|
||||
def get_paginated_response(self, data):
|
||||
if self.count_disabled:
|
||||
@@ -70,6 +87,10 @@ class Pagination(pagination.PageNumberPagination):
|
||||
return super(Pagination, self).get_paginated_response(data)
|
||||
|
||||
|
||||
class ActivityStreamPagination(Pagination):
|
||||
django_paginator_class = ActivityStreamPaginator
|
||||
|
||||
|
||||
class LimitPagination(pagination.BasePagination):
|
||||
default_limit = api_settings.PAGE_SIZE
|
||||
limit_query_param = 'limit'
|
||||
|
||||
@@ -129,7 +129,7 @@ from awx.api.views.mixin import (
|
||||
NoTruncateMixin,
|
||||
UnifiedJobExcludeMixin,
|
||||
)
|
||||
from awx.api.pagination import UnifiedJobEventPagination
|
||||
from awx.api.pagination import ActivityStreamPagination, UnifiedJobEventPagination
|
||||
from awx.main.utils import set_environ
|
||||
|
||||
logger = logging.getLogger('awx.api.views')
|
||||
@@ -4818,6 +4818,7 @@ class ActivityStreamList(SimpleListAPIView):
|
||||
model = models.ActivityStream
|
||||
serializer_class = serializers.ActivityStreamSerializer
|
||||
search_fields = ('changes',)
|
||||
pagination_class = ActivityStreamPagination
|
||||
resource_purpose = 'audit trail entries for tracking system changes'
|
||||
|
||||
@extend_schema_if_available(
|
||||
|
||||
Reference in New Issue
Block a user