mirror of https://github.com/jumpserver/jumpserver
perf: 优化任务列表执行时间 性能快了10倍
parent
ce94348d45
commit
cd0348cca1
|
@ -2,6 +2,7 @@
|
||||||
#
|
#
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
from celery.result import AsyncResult
|
from celery.result import AsyncResult
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
|
@ -166,16 +167,58 @@ class CeleryTaskViewSet(
|
||||||
i.next_exec_time = now + next_run_at
|
i.next_exec_time = now + next_run_at
|
||||||
return queryset
|
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):
|
def list(self, request, *args, **kwargs):
|
||||||
queryset = self.filter_queryset(self.get_queryset())
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
|
|
||||||
page = self.paginate_queryset(queryset)
|
page = self.paginate_queryset(queryset)
|
||||||
if page is not None:
|
if page is not None:
|
||||||
page = self.generate_execute_time(page)
|
page = self.generate_execute_time(page)
|
||||||
|
page = self.loading_summary_state(page)
|
||||||
serializer = self.get_serializer(page, many=True)
|
serializer = self.get_serializer(page, many=True)
|
||||||
return self.get_paginated_response(serializer.data)
|
return self.get_paginated_response(serializer.data)
|
||||||
|
|
||||||
queryset = self.generate_execute_time(queryset)
|
queryset = self.generate_execute_time(queryset)
|
||||||
|
queryset = self.loading_summary_state(queryset)
|
||||||
serializer = self.get_serializer(queryset, many=True)
|
serializer = self.get_serializer(queryset, many=True)
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,9 @@ class CeleryTask(models.Model):
|
||||||
name = models.CharField(max_length=1024, verbose_name=_('Name'))
|
name = models.CharField(max_length=1024, verbose_name=_('Name'))
|
||||||
date_last_publish = models.DateTimeField(null=True, verbose_name=_("Date last publish"))
|
date_last_publish = models.DateTimeField(null=True, verbose_name=_("Date last publish"))
|
||||||
|
|
||||||
|
__summary = None
|
||||||
|
__state = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def meta(self):
|
def meta(self):
|
||||||
task = app.tasks.get(self.name, None)
|
task = app.tasks.get(self.name, None)
|
||||||
|
@ -25,23 +28,43 @@ class CeleryTask(models.Model):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def summary(self):
|
def summary(self):
|
||||||
|
if self.__summary is not None:
|
||||||
|
return self.__summary
|
||||||
executions = CeleryTaskExecution.objects.filter(name=self.name)
|
executions = CeleryTaskExecution.objects.filter(name=self.name)
|
||||||
total = executions.count()
|
total = executions.count()
|
||||||
success = executions.filter(state='SUCCESS').count()
|
success = executions.filter(state='SUCCESS').count()
|
||||||
return {'total': total, 'success': success}
|
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
|
@property
|
||||||
def state(self):
|
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:
|
@state.setter
|
||||||
if last_five_executions[0].state == 'FAILURE':
|
def state(self, value):
|
||||||
return "red"
|
self.__state = value
|
||||||
|
|
||||||
for execution in last_five_executions:
|
|
||||||
if execution.state == 'FAILURE':
|
|
||||||
return "yellow"
|
|
||||||
return "green"
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Celery Task")
|
verbose_name = _("Celery Task")
|
||||||
|
|
Loading…
Reference in New Issue