perf: 优化任务列表执行时间 性能快了10倍

pull/12577/head^2
feng 2024-01-18 15:28:13 +08:00 committed by Bryan
parent ce94348d45
commit cd0348cca1
2 changed files with 75 additions and 9 deletions

View File

@ -2,6 +2,7 @@
#
import os
import re
from collections import defaultdict
from celery.result import AsyncResult
from django.shortcuts import get_object_or_404
@ -166,16 +167,58 @@ class CeleryTaskViewSet(
i.next_exec_time = now + next_run_at
return queryset
def generate_summary_state(self, execution_qs):
model = self.get_queryset().model
executions = execution_qs.order_by('-date_published').values('name', 'state')
summary_state_dict = defaultdict(
lambda: {
'states': [], 'state': 'green',
'summary': {'total': 0, 'success': 0}
}
)
for execution in executions:
name = execution['name']
state = execution['state']
summary = summary_state_dict[name]['summary']
summary['total'] += 1
summary['success'] += 1 if state == 'SUCCESS' else 0
states = summary_state_dict[name].get('states')
if states is not None and len(states) >= 5:
color = model.compute_state_color(states)
summary_state_dict[name]['state'] = color
summary_state_dict[name].pop('states', None)
elif isinstance(states, list):
states.append(state)
return summary_state_dict
def loading_summary_state(self, queryset):
if isinstance(queryset, list):
names = [i.name for i in queryset]
execution_qs = CeleryTaskExecution.objects.filter(name__in=names)
else:
execution_qs = CeleryTaskExecution.objects.all()
summary_state_dict = self.generate_summary_state(execution_qs)
for i in queryset:
i.summary = summary_state_dict.get(i.name, {}).get('summary', {})
i.state = summary_state_dict.get(i.name, {}).get('state', 'green')
return queryset
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
page = self.generate_execute_time(page)
page = self.loading_summary_state(page)
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
queryset = self.generate_execute_time(queryset)
queryset = self.loading_summary_state(queryset)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

View File

@ -15,6 +15,9 @@ class CeleryTask(models.Model):
name = models.CharField(max_length=1024, verbose_name=_('Name'))
date_last_publish = models.DateTimeField(null=True, verbose_name=_("Date last publish"))
__summary = None
__state = None
@property
def meta(self):
task = app.tasks.get(self.name, None)
@ -25,23 +28,43 @@ class CeleryTask(models.Model):
@property
def summary(self):
if self.__summary is not None:
return self.__summary
executions = CeleryTaskExecution.objects.filter(name=self.name)
total = executions.count()
success = executions.filter(state='SUCCESS').count()
return {'total': total, 'success': success}
@summary.setter
def summary(self, value):
self.__summary = value
@staticmethod
def compute_state_color(states: list, default_count=5):
color = 'green'
states = states[:default_count]
if not states:
return color
if states[0] == 'FAILURE':
color = 'red'
elif 'FAILURE' in states:
color = 'yellow'
return color
@property
def state(self):
last_five_executions = CeleryTaskExecution.objects.filter(name=self.name).order_by('-date_published')[:5]
if self.__state is not None:
return self.__state
last_five_executions = CeleryTaskExecution.objects.filter(
name=self.name
).order_by('-date_published').values('state')[:5]
states = [i['state'] for i in last_five_executions]
color = self.compute_state_color(states)
return color
if len(last_five_executions) > 0:
if last_five_executions[0].state == 'FAILURE':
return "red"
for execution in last_five_executions:
if execution.state == 'FAILURE':
return "yellow"
return "green"
@state.setter
def state(self, value):
self.__state = value
class Meta:
verbose_name = _("Celery Task")