Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store current time when TaskResult started #432

Merged
merged 3 commits into from
Jun 15, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion django_celery_results/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class TaskResultAdmin(admin.ModelAdmin):
'status', 'worker')
list_filter = ('status', 'date_done', 'periodic_task_name', 'task_name',
'worker')
readonly_fields = ('date_created', 'date_done', 'result', 'meta')
readonly_fields = ('date_created', 'date_started', 'date_done',
'result', 'meta')
search_fields = ('task_name', 'task_id', 'status', 'task_args',
'task_kwargs')
fieldsets = (
Expand All @@ -49,6 +50,7 @@ class TaskResultAdmin(admin.ModelAdmin):
'fields': (
'result',
'date_created',
'date_started',
'date_done',
'traceback',
'meta',
Expand Down
6 changes: 5 additions & 1 deletion django_celery_results/backends/database.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import binascii
import json

from celery import maybe_signature
from celery import maybe_signature, states
from celery.backends.base import BaseDictBackend, get_current_task
from celery.exceptions import ChordError
from celery.result import GroupResult, allow_join_result, result_from_tuple
from celery.utils.log import get_logger
from celery.utils.serialization import b64decode, b64encode
from django.db import connection, router, transaction
from django.db.models.functions import Now
from django.db.utils import InterfaceError
from kombu.exceptions import DecodeError

Expand Down Expand Up @@ -144,6 +145,9 @@ def _store_result(
self._get_extended_properties(request, traceback)
)

if status == states.STARTED:
task_props['date_started'] = Now()

self.TaskModel._default_manager.store_result(**task_props)
return result

Expand Down
5 changes: 4 additions & 1 deletion django_celery_results/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def store_result(self, content_type, content_encoding,
traceback=None, meta=None,
periodic_task_name=None,
task_name=None, task_args=None, task_kwargs=None,
worker=None, using=None):
worker=None, using=None, **kwargs):
"""Store the result and status of a task.

Arguments:
Expand Down Expand Up @@ -161,6 +161,9 @@ def store_result(self, content_type, content_encoding,
'task_kwargs': task_kwargs,
'worker': worker
}
if 'date_started' in kwargs:
fields['date_started'] = kwargs['date_started']

obj, created = self.using(using).get_or_create(task_id=task_id,
defaults=fields)
if not created:
Expand Down
23 changes: 23 additions & 0 deletions django_celery_results/migrations/0012_taskresult_date_started.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 4.2.13 on 2024-06-02 07:56

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('django_celery_results', '0011_taskresult_periodic_task_name'),
]

operations = [
migrations.AddField(
model_name='taskresult',
name='date_started',
field=models.DateTimeField(
default=None,
help_text='Datetime field when the task was started in UTC',
null=True,
verbose_name='Started DateTime',
),
),
]
4 changes: 4 additions & 0 deletions django_celery_results/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ class TaskResult(models.Model):
auto_now_add=True,
verbose_name=_('Created DateTime'),
help_text=_('Datetime field when the task result was created in UTC'))
date_started = models.DateTimeField(
null=True, default=None,
verbose_name=_('Started DateTime'),
help_text=_('Datetime field when the task was started in UTC'))
date_done = models.DateTimeField(
auto_now=True,
verbose_name=_('Completed DateTime'),
Expand Down
4 changes: 2 additions & 2 deletions docs/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ To use :pypi:`django-celery-results` with your project you need to follow these

CELERY_RESULT_EXTENDED = True

If you want to track the execution duration of your tasks (by comparing `date_created` and `date_done` in TaskResult), enable the :setting:`track_started` setting.
If you want to track the execution duration of your tasks (by comparing `date_started` and `date_done` in TaskResult), enable the :setting:`track_started` setting.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we think of any example, using the new feature here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@auvipy Added example. However, I'm not good at English, so I would like you to correct the sentence.

By the way, you previously asked whether this package should include the behavior of registering TaskResult at states.PENDING timing.
ref: #286 (comment)

If it is possible for me, I would like to create another PR. What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can certainly open another PR. but what are the issues with the open PR?

Copy link
Contributor Author

@yktakaha4 yktakaha4 Jun 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I'm not good at explaining. There is nothing problems with this PR.
I would like to submit a new PR for the PENDING status registration.
If there is no problem with this PR, could you please merge it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are most welcome to come with a new PR


.. code-block:: python

CELERY_TASK_TRACK_STARTED = True
34 changes: 34 additions & 0 deletions t/unit/backends/test_database.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import datetime
import json
import pickle
import re
Expand Down Expand Up @@ -549,6 +550,39 @@ def test_backend__task_result_meta_injection(self):
tr = TaskResult.objects.get(task_id=tid2)
assert json.loads(tr.meta) == {'key': 'value', 'children': []}

def test_backend__task_result_date(self):
tid2 = uuid()

self.b.store_result(tid2, None, states.PENDING)

tr = TaskResult.objects.get(task_id=tid2)
assert tr.status == states.PENDING
assert isinstance(tr.date_created, datetime.datetime)
assert tr.date_started is None
assert isinstance(tr.date_done, datetime.datetime)

date_created = tr.date_created
date_done = tr.date_done

self.b.mark_as_started(tid2)

tr = TaskResult.objects.get(task_id=tid2)
assert tr.status == states.STARTED
assert date_created == tr.date_created
assert isinstance(tr.date_started, datetime.datetime)
assert tr.date_done > date_done

date_started = tr.date_started
date_done = tr.date_done

self.b.mark_as_done(tid2, 42)

tr = TaskResult.objects.get(task_id=tid2)
assert tr.status == states.SUCCESS
assert tr.date_created == date_created
assert tr.date_started == date_started
assert tr.date_done > date_done

def xxx_backend(self):
tid = uuid()

Expand Down
Loading