asynchronous refactoring

- don't execute celery tasks directly
- introduce optional parameters to fileserver tasks to allow chaining
- handle user/group/key create and delete tasks in new osusers.signals
  class
- adapt unit tests
- change TaskResults model to store the task signatures
- generalize the local settings' logging configuration
This commit is contained in:
Jan Dittberner 2015-10-12 00:23:31 +02:00
parent bcfea10e6f
commit d5bba7a22d
12 changed files with 290 additions and 170 deletions

View file

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('taskresults', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='taskresult',
name='task_name',
),
migrations.AddField(
model_name='taskresult',
name='creator',
field=models.TextField(default='migrated', verbose_name='Task creator'),
preserve_default=False,
),
migrations.AddField(
model_name='taskresult',
name='notes',
field=models.TextField(default='', verbose_name='Task notes'),
preserve_default=False,
),
migrations.AddField(
model_name='taskresult',
name='signature',
field=models.TextField(default='', verbose_name='Task signature'),
preserve_default=False,
),
]

View file

@ -12,15 +12,21 @@ 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)
def create_task_result(self, creator, signature, notes=''):
sigstr = str(signature)
result = signature.apply_async()
taskresult = self.create(
task_id=result.task_id, creator=creator, signature=sigstr,
notes=notes)
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)
signature = models.TextField(_('Task signature'))
creator = models.TextField(_('Task creator'))
notes = models.TextField(_('Task notes'))
result = models.TextField(_('Task result'))
finished = models.BooleanField(default=False)
state = models.CharField(_('Task state'), max_length=16)
@ -32,8 +38,8 @@ class TaskResult(models.Model):
verbose_name_plural = _('Task results')
def __str__(self):
return "{task_name} ({task_id}): {finished}".format(
task_name=self.task_name,
return "{creator} ({task_id}): {finished}".format(
creator=self.creator,
task_id=self.task_id,
finished=_('yes') if self.finished else _('no')
)
@ -41,7 +47,8 @@ class TaskResult(models.Model):
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
if ar.ready():
res = ar.get()
self.result = str(res)
self.finished = True

View file

@ -13,24 +13,30 @@ TEST_TASK_RESULT = '4ll y0ur b453 4r3 b3l0ng t0 u5'
class TaskResultTest(TestCase):
@patch('taskresults.models.app')
def test_update_taskstatus_unfinished(self, app):
mock = MagicMock(id=TEST_TASK_UUID, task_name=TEST_TASK_NAME)
mock.ready.return_value = False
tr = TaskResult.objects.create_task_result(mock, TEST_TASK_NAME)
resultmock = MagicMock(task_id=TEST_TASK_UUID)
resultmock.ready.return_value = False
mock = MagicMock()
mock.apply_async.return_value = resultmock
tr = TaskResult.objects.create_task_result(TEST_TASK_NAME, mock)
self.assertFalse(tr.finished)
mymock = app.AsyncResult(TEST_TASK_UUID)
mymock.state = 'SUCCESS'
mymock.get.return_value = TEST_RESULT
tr.fetch_result()
mymock.get.assert_called_with(no_ack=True, timeout=1)
mymock.get.assert_called_with()
self.assertTrue(tr.finished)
@patch('taskresults.models.app')
def test_update_taskstatus_finished(self, app):
mock = MagicMock(id=TEST_TASK_UUID, task_name=TEST_TASK_NAME)
mock.ready.return_value = True
resultmock = MagicMock(task_id=TEST_TASK_UUID)
resultmock.ready.return_value = True
resultmock.state = 'SUCCESS'
resultmock.result = TEST_RESULT
mock = MagicMock()
mock.apply_async.return_value = resultmock
mock.state = 'SUCCESS'
mock.result = TEST_RESULT
tr = TaskResult.objects.create_task_result(mock, TEST_TASK_NAME)
tr = TaskResult.objects.create_task_result(TEST_TASK_NAME, mock)
tr.fetch_result()
self.assertTrue(tr.finished)
mymock = app.AsyncResult(TEST_TASK_UUID)
@ -47,8 +53,10 @@ TEST_RESULT.ready.return_value = False
class TaskResultManagerTest(TestCase):
def test_create_task_result(self):
mock = MagicMock(id=TEST_TASK_UUID)
tr = TaskResult.objects.create_task_result(mock, TEST_TASK_NAME)
resultmock = MagicMock(task_id=TEST_TASK_UUID)
mock = MagicMock()
mock.apply_async.return_value = resultmock
tr = TaskResult.objects.create_task_result(TEST_TASK_NAME, mock)
self.assertIsInstance(tr, TaskResult)
self.assertEqual(tr.task_id, TEST_TASK_UUID)
self.assertEqual(tr.task_name, TEST_TASK_NAME)
self.assertEqual(tr.creator, TEST_TASK_NAME)