From a336af46c2b70ea997f4d0bdb9790ceb5a092e9f Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Mon, 29 Dec 2014 15:55:57 +0100 Subject: [PATCH] add taskresults app to handle celery task results --- docs/changelog.rst | 7 ++- docs/code.rst | 26 ++++++++++ gnuviechadmin/gnuviechadmin/settings/base.py | 1 + gnuviechadmin/taskresults/__init__.py | 5 ++ gnuviechadmin/taskresults/admin.py | 12 +++++ .../taskresults/management/__init__.py | 0 .../management/commands/__init__.py | 4 ++ .../management/commands/fetch_taskresults.py | 20 ++++++++ .../taskresults/migrations/0001_initial.py | 29 ++++++++++++ .../taskresults/migrations/__init__.py | 0 gnuviechadmin/taskresults/models.py | 47 +++++++++++++++++++ 11 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 gnuviechadmin/taskresults/__init__.py create mode 100644 gnuviechadmin/taskresults/admin.py create mode 100644 gnuviechadmin/taskresults/management/__init__.py create mode 100644 gnuviechadmin/taskresults/management/commands/__init__.py create mode 100644 gnuviechadmin/taskresults/management/commands/fetch_taskresults.py create mode 100644 gnuviechadmin/taskresults/migrations/0001_initial.py create mode 100644 gnuviechadmin/taskresults/migrations/__init__.py create mode 100644 gnuviechadmin/taskresults/models.py diff --git a/docs/changelog.rst b/docs/changelog.rst index 5ab9cd9..67fc19f 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,8 @@ Changelog ========= +* :feature:`-` add new app :py:mod:`taskresults` that takes care of handling + asynchronous `Celery`_ results * :feature:`-` add new task :py:func:`osusers.tasks.delete_ldap_group` (needs gvaldap >= 0.2.0 on the LDAP side) * :feature:`-` add a `customer` field to :py:class:`osusers.models.User` @@ -30,10 +32,11 @@ Changelog * :feature:`-` full test suite for osusers * :feature:`-` full test suite for managemails app * :feature:`-` full test suite for domains app -* :feature:`-` `Celery `_ integration for ldap - synchronization +* :feature:`-` `Celery`_ integration for ldap synchronization * :release:`0.1 <2014-05-25>` * :feature:`-` initial model code for os users * :feature:`-` initial model code for mail address and mailbox management * :feature:`-` initial model code for domains + +.. _Celery: http://www.celeryproject.org/ diff --git a/docs/code.rst b/docs/code.rst index db64b7f..eb4f62f 100644 --- a/docs/code.rst +++ b/docs/code.rst @@ -149,3 +149,29 @@ provides some functionality that is common to all gnuviechadmin subprojects. .. autotask:: osusers.tasks.remove_ldap_user_from_group .. autotask:: osusers.tasks.setup_file_mail_userdir .. autotask:: osusers.tasks.setup_file_sftp_userdir + + +:py:mod:`taskresults` app +========================= + +.. automodule:: taskresults + +:py:mod:`admin ` +----------------------------------- + +.. automodule:: taskresults.admin + +:py:mod:`management.commands ` +--------------------------------------------------------------- + +.. automodule:: taskresults.management.commands + +:py:mod:`fetch_taskresults ` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: taskresults.management.commands.fetch_taskresults + +:py:mod:`models ` +------------------------------------- + +.. automodule:: taskresults.models diff --git a/gnuviechadmin/gnuviechadmin/settings/base.py b/gnuviechadmin/gnuviechadmin/settings/base.py index b770e8d..e30df47 100644 --- a/gnuviechadmin/gnuviechadmin/settings/base.py +++ b/gnuviechadmin/gnuviechadmin/settings/base.py @@ -224,6 +224,7 @@ DJANGO_APPS = ( # Apps specific for this project go here. LOCAL_APPS = ( + 'taskresults', 'domains', 'osusers', 'managemails', diff --git a/gnuviechadmin/taskresults/__init__.py b/gnuviechadmin/taskresults/__init__.py new file mode 100644 index 0000000..0b3d916 --- /dev/null +++ b/gnuviechadmin/taskresults/__init__.py @@ -0,0 +1,5 @@ +""" +This is the taskresults app that is used for storing the results from +asynchronous `Celery `_ tasks. + +""" diff --git a/gnuviechadmin/taskresults/admin.py b/gnuviechadmin/taskresults/admin.py new file mode 100644 index 0000000..cd47dc8 --- /dev/null +++ b/gnuviechadmin/taskresults/admin.py @@ -0,0 +1,12 @@ +""" +This module defines the admin interface for the taskresults app. + +""" +from __future__ import absolute_import + +from django.contrib import admin + +from .models import TaskResult + + +admin.site.register(TaskResult) diff --git a/gnuviechadmin/taskresults/management/__init__.py b/gnuviechadmin/taskresults/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gnuviechadmin/taskresults/management/commands/__init__.py b/gnuviechadmin/taskresults/management/commands/__init__.py new file mode 100644 index 0000000..4e6e692 --- /dev/null +++ b/gnuviechadmin/taskresults/management/commands/__init__.py @@ -0,0 +1,4 @@ +""" +This module defines management commands for the taskresults app. + +""" diff --git a/gnuviechadmin/taskresults/management/commands/fetch_taskresults.py b/gnuviechadmin/taskresults/management/commands/fetch_taskresults.py new file mode 100644 index 0000000..8ccbd78 --- /dev/null +++ b/gnuviechadmin/taskresults/management/commands/fetch_taskresults.py @@ -0,0 +1,20 @@ +""" +This model contains the implementation of a management command to fetch the +results of all `Celery `_ tasks that are not +marked as finished yet. + +""" +from __future__ import unicode_literals + +from django.core.management.base import BaseCommand + +from taskresults.models import TaskResult + + +class Command(BaseCommand): + help = "fetch task results" + + def handle(self, *args, **options): + for taskresult in TaskResult.objects.filter(finished=False): + taskresult.fetch_result() + taskresult.save() diff --git a/gnuviechadmin/taskresults/migrations/0001_initial.py b/gnuviechadmin/taskresults/migrations/0001_initial.py new file mode 100644 index 0000000..7c405be --- /dev/null +++ b/gnuviechadmin/taskresults/migrations/0001_initial.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='TaskResult', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('task_id', models.CharField(max_length=36, verbose_name='Task id')), + ('task_name', models.CharField(max_length=64, verbose_name='Task name')), + ('result', models.TextField(verbose_name='Task result')), + ('finished', models.BooleanField(default=False)), + ('state', models.CharField(max_length=16, verbose_name='Task state')), + ], + options={ + 'verbose_name': 'Task result', + 'verbose_name_plural': 'Task results', + }, + bases=(models.Model,), + ), + ] diff --git a/gnuviechadmin/taskresults/migrations/__init__.py b/gnuviechadmin/taskresults/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gnuviechadmin/taskresults/models.py b/gnuviechadmin/taskresults/models.py new file mode 100644 index 0000000..7178c84 --- /dev/null +++ b/gnuviechadmin/taskresults/models.py @@ -0,0 +1,47 @@ +""" +This model defines the database models to handle Celery AsyncResults. + +""" +from __future__ import unicode_literals + +from django.db import models +from django.utils.encoding import python_2_unicode_compatible +from django.utils.translation import ugettext as _ + +from gnuviechadmin.celery import app + + +class TaskResultManager(models.Manager): + def create_task_result(self, asyncresult, name): + taskresult = self.create(task_id=asyncresult.id, task_name=name) + return taskresult + + +@python_2_unicode_compatible +class TaskResult(models.Model): + task_id = models.CharField(_('Task id'), max_length=36) + task_name = models.CharField(_('Task name'), max_length=64) + result = models.TextField(_('Task result')) + finished = models.BooleanField(default=False) + state = models.CharField(_('Task state'), max_length=16) + + objects = TaskResultManager() + + class Meta: + verbose_name = _('Task result') + verbose_name_plural = _('Task results') + + def __str__(self): + return "{task_name} ({task_id}): {finished}".format( + task_name=self.task_name, + task_id=self.task_id, + finished=_('yes') if self.finished else _('no') + ) + + def fetch_result(self): + if not self.finished: + ar = app.AsyncResult(self.task_id) + res = ar.get(no_ack=True, timeout=1) + self.result = str(res) + self.state = ar.state + self.finished = True