Skip to content

Commit bc6f4dc

Browse files
refactor
1 parent 1c33555 commit bc6f4dc

6 files changed

Lines changed: 61 additions & 75 deletions

File tree

dojo/api_v2/views.py

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
from rest_framework.parsers import MultiPartParser
3636
from rest_framework.permissions import DjangoModelPermissions, IsAuthenticated
3737
from rest_framework.response import Response
38-
from rest_framework.views import APIView
3938

4039
import dojo.finding.helper as finding_helper
4140
import dojo.jira_link.helper as jira_helper
@@ -3266,20 +3265,21 @@ def get_queryset(self):
32663265
return System_Settings.objects.all().order_by("id")
32673266

32683267

3269-
@extend_schema(
3270-
responses=serializers.CeleryStatusSerializer,
3271-
summary="Get Celery worker and queue status",
3272-
description=(
3273-
"Returns Celery worker liveness, pending queue length, and the active task "
3274-
"timeout/expiry configuration. Uses the Celery control channel (pidbox) for "
3275-
"worker status so it works correctly even when the task queue is clogged."
3276-
),
3277-
)
3278-
class CeleryStatusView(APIView):
3268+
class CeleryViewSet(viewsets.ViewSet):
32793269
permission_classes = (permissions.IsSuperUser, DjangoModelPermissions)
32803270
queryset = System_Settings.objects.none()
32813271

3282-
def get(self, request):
3272+
@extend_schema(
3273+
responses=serializers.CeleryStatusSerializer,
3274+
summary="Get Celery worker and queue status",
3275+
description=(
3276+
"Returns Celery worker liveness, pending queue length, and the active task "
3277+
"timeout/expiry configuration. Uses the Celery control channel (pidbox) for "
3278+
"worker status so it works correctly even when the task queue is clogged."
3279+
),
3280+
)
3281+
@action(detail=False, methods=["get"], url_path="status")
3282+
def status(self, request):
32833283
queue_length = get_celery_queue_length()
32843284
data = {
32853285
"worker_status": get_celery_worker_status(),
@@ -3291,56 +3291,44 @@ def get(self, request):
32913291
}
32923292
return Response(serializers.CeleryStatusSerializer(data).data)
32933293

3294-
3295-
@extend_schema(
3296-
request=None,
3297-
responses={200: {"type": "object", "properties": {"purged": {"type": "integer"}}}},
3298-
summary="Purge all pending Celery tasks from the queue",
3299-
description=(
3300-
"Removes all pending tasks from the default Celery queue. Tasks already being "
3301-
"executed by workers are not affected. Note: if deduplication tasks were queued, "
3302-
"you may need to re-run deduplication manually via `python manage.py dedupe`."
3303-
),
3304-
)
3305-
class CeleryQueuePurgeView(APIView):
3306-
permission_classes = (permissions.IsSuperUser, DjangoModelPermissions)
3307-
queryset = System_Settings.objects.none()
3308-
3309-
def post(self, request):
3294+
@extend_schema(
3295+
request=None,
3296+
responses={200: {"type": "object", "properties": {"purged": {"type": "integer"}}}},
3297+
summary="Purge all pending Celery tasks from the queue",
3298+
description=(
3299+
"Removes all pending tasks from the default Celery queue. Tasks already being "
3300+
"executed by workers are not affected. Note: if deduplication tasks were queued, "
3301+
"you may need to re-run deduplication manually via `python manage.py dedupe`."
3302+
),
3303+
)
3304+
@action(detail=False, methods=["post"], url_path="queue/purge")
3305+
def queue_purge(self, request):
33103306
purged = purge_celery_queue()
33113307
return Response({"purged": purged})
33123308

3313-
3314-
@extend_schema(
3315-
responses=serializers.CeleryQueueTaskDetailSerializer(many=True),
3316-
summary="Get per-task breakdown of the Celery queue",
3317-
description=(
3318-
"Scans every message in the queue (O(N)) and returns task name, count, and "
3319-
"oldest/newest queue positions. May be slow for large queues."
3320-
),
3321-
)
3322-
class CeleryQueueDetailsView(APIView):
3323-
permission_classes = (permissions.IsSuperUser, DjangoModelPermissions)
3324-
queryset = System_Settings.objects.none()
3325-
3326-
def get(self, request):
3309+
@extend_schema(
3310+
responses=serializers.CeleryQueueTaskDetailSerializer(many=True),
3311+
summary="Get per-task breakdown of the Celery queue",
3312+
description=(
3313+
"Scans every message in the queue (O(N)) and returns task name, count, and "
3314+
"oldest/newest queue positions. May be slow for large queues."
3315+
),
3316+
)
3317+
@action(detail=False, methods=["get"], url_path="queue/details")
3318+
def queue_details(self, request):
33273319
details = get_celery_queue_details()
33283320
if details is None:
33293321
return Response({"error": "Unable to read queue details."}, status=503)
33303322
return Response(serializers.CeleryQueueTaskDetailSerializer(details, many=True).data)
33313323

3332-
3333-
@extend_schema(
3334-
request={"application/json": {"type": "object", "properties": {"task_name": {"type": "string"}}, "required": ["task_name"]}},
3335-
responses={200: {"type": "object", "properties": {"purged": {"type": "integer"}}}},
3336-
summary="Purge all queued tasks with a given task name",
3337-
description="Removes all pending tasks matching the given task name from the default Celery queue.",
3338-
)
3339-
class CeleryQueueTaskPurgeView(APIView):
3340-
permission_classes = (permissions.IsSuperUser, DjangoModelPermissions)
3341-
queryset = System_Settings.objects.none()
3342-
3343-
def post(self, request):
3324+
@extend_schema(
3325+
request={"application/json": {"type": "object", "properties": {"task_name": {"type": "string"}}, "required": ["task_name"]}},
3326+
responses={200: {"type": "object", "properties": {"purged": {"type": "integer"}}}},
3327+
summary="Purge all queued tasks with a given task name",
3328+
description="Removes all pending tasks matching the given task name from the default Celery queue.",
3329+
)
3330+
@action(detail=False, methods=["post"], url_path="queue/task/purge")
3331+
def queue_task_purge(self, request):
33443332
task_name = request.data.get("task_name", "").strip()
33453333
if not task_name:
33463334
return Response({"error": "task_name is required."}, status=400)

dojo/system_settings/urls.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
name="system_settings",
1010
),
1111
re_path(
12-
r"^system_status$",
13-
views.SystemStatusView.as_view(),
14-
name="system_status",
12+
r"^celery_status$",
13+
views.CeleryStatusView.as_view(),
14+
name="celery_status",
1515
),
1616
]

dojo/system_settings/views.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,12 @@ def post(
120120
return render(request, self.get_template(), context)
121121

122122

123-
class SystemStatusView(View):
123+
class CeleryStatusView(View):
124124
def get(
125125
self,
126126
request: HttpRequest,
127127
) -> HttpResponse:
128128
if not request.user.is_superuser:
129129
raise PermissionDenied
130-
add_breadcrumb(title="System status", top_level=False, request=request)
131-
return render(request, "dojo/system_status.html")
130+
add_breadcrumb(title="Celery status", top_level=False, request=request)
131+
return render(request, "dojo/celery_status.html")

dojo/templates/base.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -614,8 +614,8 @@
614614
</a>
615615
</li>
616616
<li>
617-
<a href="{% url 'system_status' %}">
618-
{% trans "System Status" %}
617+
<a href="{% url 'celery_status' %}">
618+
{% trans "Celery Status" %}
619619
</a>
620620
</li>
621621
{% endif %}
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
{% block content %}
55
{{ block.super }}
66
<div class="row">
7-
<h3>System Status</h3>
7+
<h3>Celery Status</h3>
88
<br>
9+
{% if show_celery_status %}
910
<div id="celery-status-panel" class="col-md-5">
1011
<div class="panel panel-default">
1112
<div class="panel-heading">
@@ -103,17 +104,19 @@ <h4>Celery Settings</h4>
103104
</div>
104105
</div>
105106
</div>
107+
{% endif %}
106108
</div>
107109
{% endblock content %}
108110

109111
{% block postscript %}
110112
{{ block.super }}
113+
{% if show_celery_status %}
111114
<script>
112115
(function() {
113-
var purgeUrl = "{% url 'celery_queue_purge_api' %}";
114-
var statusUrl = "{% url 'celery_status_api' %}";
115-
var detailsUrl = "{% url 'celery_queue_details_api' %}";
116-
var taskPurgeUrl = "{% url 'celery_queue_task_purge_api' %}";
116+
var purgeUrl = "{% url 'celery-queue-purge' %}";
117+
var statusUrl = "{% url 'celery-status' %}";
118+
var detailsUrl = "{% url 'celery-queue-details' %}";
119+
var taskPurgeUrl = "{% url 'celery-queue-task-purge' %}";
117120

118121
function setStatusBadge(loadingId, badgeId, isOk, okText, failText) {
119122
$('#' + loadingId).hide();
@@ -302,4 +305,5 @@ <h4>Celery Settings</h4>
302305
});
303306
})();
304307
</script>
308+
{% endif %}
305309
{% endblock %}

dojo/urls.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@
1515
AnnouncementViewSet,
1616
AppAnalysisViewSet,
1717
BurpRawRequestResponseViewSet,
18-
CeleryQueueDetailsView,
19-
CeleryQueuePurgeView,
20-
CeleryQueueTaskPurgeView,
21-
CeleryStatusView,
18+
CeleryViewSet,
2219
ConfigurationPermissionViewSet,
2320
CredentialsMappingViewSet,
2421
CredentialsViewSet,
@@ -198,6 +195,7 @@
198195
else:
199196
v2_api.register(r"endpoints", EndPointViewSet, basename="endpoint")
200197
v2_api.register(r"endpoint_status", EndpointStatusViewSet, basename="endpoint_status")
198+
v2_api.register(r"celery", CeleryViewSet, basename="celery")
201199
# V3
202200
add_asset_urls(v2_api)
203201
add_organization_urls(v2_api)
@@ -246,10 +244,6 @@
246244
# Django Rest Framework API v2
247245
re_path(r"^{}api/v2/".format(get_system_setting("url_prefix")), include(v2_api.urls)),
248246
re_path(r"^{}api/v2/user_profile/".format(get_system_setting("url_prefix")), UserProfileView.as_view(), name="user_profile"),
249-
re_path(r"^{}api/v2/celery/status/$".format(get_system_setting("url_prefix")), CeleryStatusView.as_view(), name="celery_status_api"),
250-
re_path(r"^{}api/v2/celery/queue/purge/$".format(get_system_setting("url_prefix")), CeleryQueuePurgeView.as_view(), name="celery_queue_purge_api"),
251-
re_path(r"^{}api/v2/celery/queue/details/$".format(get_system_setting("url_prefix")), CeleryQueueDetailsView.as_view(), name="celery_queue_details_api"),
252-
re_path(r"^{}api/v2/celery/queue/task/purge/$".format(get_system_setting("url_prefix")), CeleryQueueTaskPurgeView.as_view(), name="celery_queue_task_purge_api"),
253247
]
254248

255249
if hasattr(settings, "API_TOKENS_ENABLED") and hasattr(settings, "API_TOKEN_AUTH_ENDPOINT_ENABLED"):

0 commit comments

Comments
 (0)