save start and end directly in timestamp from default_timer()

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens Langhammer 2024-01-13 22:46:31 +01:00
parent f64ce142e4
commit 4e44354680
No known key found for this signature in database
8 changed files with 42 additions and 51 deletions

View file

@ -1,4 +1,5 @@
"""Tasks API"""
from datetime import datetime, timezone
from importlib import import_module
from django.contrib import messages
@ -6,13 +7,7 @@ from django.utils.translation import gettext_lazy as _
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiResponse, extend_schema
from rest_framework.decorators import action
from rest_framework.fields import (
CharField,
ChoiceField,
DateTimeField,
ListField,
SerializerMethodField,
)
from rest_framework.fields import CharField, ChoiceField, ListField, SerializerMethodField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
@ -32,8 +27,8 @@ class SystemTaskSerializer(ModelSerializer):
full_name = SerializerMethodField()
uid = CharField(required=False)
description = CharField()
start_timestamp = DateTimeField()
finish_timestamp = DateTimeField()
start_timestamp = SerializerMethodField()
finish_timestamp = SerializerMethodField()
duration = SerializerMethodField()
status = ChoiceField(choices=[(x.value, x.name) for x in TaskStatus])
@ -45,9 +40,15 @@ class SystemTaskSerializer(ModelSerializer):
return f"{instance.name}:{instance.uid}"
return instance.name
def get_duration(self, instance: SystemTask) -> int:
def get_start_timestamp(self, instance: SystemTask) -> datetime:
return datetime.fromtimestamp(instance.start_timestamp, tz=timezone.utc)
def get_finish_timestamp(self, instance: SystemTask) -> datetime:
return datetime.fromtimestamp(instance.finish_timestamp, tz=timezone.utc)
def get_duration(self, instance: SystemTask) -> float:
"""Get the duration a task took to run"""
return max(instance.finish_timestamp.timestamp() - instance.start_timestamp.timestamp(), 0)
return max(instance.finish_timestamp - instance.start_timestamp, 0)
class Meta:
model = SystemTask
@ -74,7 +75,7 @@ class SystemTaskViewSet(ReadOnlyModelViewSet):
ordering = ["name", "uid", "status"]
search_fields = ["name", "description", "uid", "status"]
@permission_required(None, ["authentik_events.rerun_task"])
@permission_required(None, ["authentik_events.run_task"])
@extend_schema(
request=OpenApiTypes.NONE,
responses={
@ -84,21 +85,21 @@ class SystemTaskViewSet(ReadOnlyModelViewSet):
},
)
@action(detail=True, methods=["post"])
def retry(self, request: Request, pk=None) -> Response:
"""Retry task"""
task = self.get_object()
def run(self, request: Request, pk=None) -> Response:
"""Run task"""
task: SystemTask = self.get_object()
try:
task_module = import_module(task.task_call_module)
task_func = getattr(task_module, task.task_call_func)
LOGGER.debug("Running task", task=task_func)
LOGGER.info("Running task", task=task_func)
task_func.delay(*task.task_call_args, **task.task_call_kwargs)
messages.success(
self.request,
_("Successfully re-scheduled Task %(name)s!" % {"name": task.task_name}),
_("Successfully started task %(name)s." % {"name": task.name}),
)
return Response(status=204)
except (ImportError, AttributeError): # pragma: no cover
LOGGER.warning("Failed to run task, remove state", task=task)
except (ImportError, AttributeError) as exc: # pragma: no cover
LOGGER.warning("Failed to run task, remove state", task=task.name, exc=exc)
# if we get an import error, the module path has probably changed
task.delete()
return Response(status=500)

View file

@ -21,7 +21,7 @@ from authentik.core.models import (
UserSourceConnection,
)
from authentik.enterprise.providers.rac.models import ConnectionToken
from authentik.events.models import Event, EventAction, Notification
from authentik.events.models import Event, EventAction, Notification, SystemTask
from authentik.events.utils import model_to_dict
from authentik.flows.models import FlowToken, Stage
from authentik.lib.sentry import before_send
@ -56,6 +56,7 @@ IGNORED_MODELS = (
SCIMGroup,
Reputation,
ConnectionToken,
SystemTask,
)

View file

@ -1,4 +1,4 @@
# Generated by Django 5.0.1 on 2024-01-13 20:14
# Generated by Django 5.0.1 on 2024-01-13 21:42
import uuid
@ -29,8 +29,8 @@ class Migration(migrations.Migration):
),
("name", models.TextField()),
("uid", models.TextField(null=True)),
("start_timestamp", models.DateTimeField(auto_now_add=True)),
("finish_timestamp", models.DateTimeField(auto_now=True)),
("start_timestamp", models.FloatField()),
("finish_timestamp", models.FloatField()),
(
"status",
models.TextField(
@ -52,7 +52,7 @@ class Migration(migrations.Migration):
options={
"verbose_name": "System Task",
"verbose_name_plural": "System Tasks",
"permissions": [("rerun_task", "Rerun task")],
"permissions": [("run_task", "Run task")],
"default_permissions": ["view"],
"unique_together": {("name", "uid")},
},

View file

@ -601,8 +601,8 @@ class SystemTask(SerializerModel, ExpiringModel):
name = models.TextField()
uid = models.TextField(null=True)
start_timestamp = models.DateTimeField(auto_now_add=True)
finish_timestamp = models.DateTimeField(auto_now=True)
start_timestamp = models.FloatField()
finish_timestamp = models.FloatField()
status = models.TextField(choices=TaskStatus.choices)
@ -636,6 +636,6 @@ class SystemTask(SerializerModel, ExpiringModel):
unique_together = (("name", "uid"),)
# Remove "add", "change" and "delete" permissions as those are not used
default_permissions = ["view"]
permissions = [("rerun_task", _("Rerun task"))]
permissions = [("run_task", _("Run task"))]
verbose_name = _("System Task")
verbose_name_plural = _("System Tasks")

View file

@ -1,5 +1,5 @@
"""Monitored tasks"""
from datetime import datetime, timedelta, timezone
from datetime import timedelta
from timeit import default_timer
from typing import Any, Optional
@ -69,10 +69,8 @@ class MonitoredTask(Task):
uid=self._uid,
defaults={
"description": self.__doc__,
"start_timestamp": datetime.fromtimestamp(
self._start or default_timer(), tz=timezone.utc
),
"finish_timestamp": datetime.fromtimestamp(default_timer(), tz=timezone.utc),
"start_timestamp": self._start or default_timer(),
"finish_timestamp": default_timer(),
"task_call_module": self.__module__,
"task_call_func": self.__name__,
"task_call_args": args,
@ -95,10 +93,8 @@ class MonitoredTask(Task):
uid=self._uid,
defaults={
"description": self.__doc__,
"start_timestamp": datetime.fromtimestamp(
self._start or default_timer(), tz=timezone.utc
),
"finish_timestamp": datetime.fromtimestamp(default_timer(), tz=timezone.utc),
"start_timestamp": self._start or default_timer(),
"finish_timestamp": default_timer(),
"task_call_module": self.__module__,
"task_call_func": self.__name__,
"task_call_args": args,

View file

@ -3252,16 +3252,6 @@
"minLength": 1,
"title": "Description"
},
"start_timestamp": {
"type": "string",
"format": "date-time",
"title": "Start timestamp"
},
"finish_timestamp": {
"type": "string",
"format": "date-time",
"title": "Finish timestamp"
},
"status": {
"type": "string",
"enum": [

View file

@ -6944,10 +6944,10 @@ paths:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/events/system_tasks/{uuid}/retry/:
/events/system_tasks/{uuid}/run/:
post:
operationId: events_system_tasks_retry_create
description: Retry task
operationId: events_system_tasks_run_create
description: Run task
parameters:
- in: path
name: uuid
@ -42719,11 +42719,14 @@ components:
start_timestamp:
type: string
format: date-time
readOnly: true
finish_timestamp:
type: string
format: date-time
readOnly: true
duration:
type: integer
type: number
format: double
description: Get the duration a task took to run
readOnly: true
status:

View file

@ -113,7 +113,7 @@ export class SystemTaskListPage extends TablePage<SystemTask> {
class="pf-m-plain"
.apiRequest=${() => {
return new EventsApi(DEFAULT_CONFIG)
.eventsSystemTasksRetryCreate({
.eventsSystemTasksRunCreate({
uuid: item.uuid,
})
.then(() => {