Commit 08ed0023 by Dudás Ádám

common: make activities' result field human-readable

parent cf8b2842
...@@ -27,7 +27,8 @@ from django.core.cache import cache ...@@ -27,7 +27,8 @@ from django.core.cache import cache
from django.db.models import (CharField, DateTimeField, ForeignKey, from django.db.models import (CharField, DateTimeField, ForeignKey,
NullBooleanField, TextField) NullBooleanField, TextField)
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _, ugettext_noop
from jsonfield import JSONField
from model_utils.models import TimeStampedModel from model_utils.models import TimeStampedModel
...@@ -45,7 +46,11 @@ def activitycontextimpl(act, on_abort=None, on_commit=None): ...@@ -45,7 +46,11 @@ def activitycontextimpl(act, on_abort=None, on_commit=None):
# BaseException is the common parent of Exception and # BaseException is the common parent of Exception and
# system-exiting exceptions, e.g. KeyboardInterrupt # system-exiting exceptions, e.g. KeyboardInterrupt
handler = None if on_abort is None else lambda a: on_abort(a, e) handler = None if on_abort is None else lambda a: on_abort(a, e)
act.finish(succeeded=False, result=str(e), event_handler=handler) result = create_readable(ugettext_noop("Failure."),
ugettext_noop("Unhandled exception: "
"%(error)s"),
error=unicode(e))
act.finish(succeeded=False, result=result, event_handler=handler)
raise e raise e
else: else:
act.finish(succeeded=True, event_handler=on_commit) act.finish(succeeded=True, event_handler=on_commit)
...@@ -120,8 +125,8 @@ class ActivityModel(TimeStampedModel): ...@@ -120,8 +125,8 @@ class ActivityModel(TimeStampedModel):
succeeded = NullBooleanField(blank=True, null=True, succeeded = NullBooleanField(blank=True, null=True,
help_text=_('True, if the activity has ' help_text=_('True, if the activity has '
'finished successfully.')) 'finished successfully.'))
result = TextField(verbose_name=_('result'), blank=True, null=True, result_data = JSONField(verbose_name=_('result'), blank=True, null=True,
help_text=_('Human readable result of activity.')) help_text=_('Human readable result of activity.'))
def __unicode__(self): def __unicode__(self):
if self.parent: if self.parent:
...@@ -150,6 +155,14 @@ class ActivityModel(TimeStampedModel): ...@@ -150,6 +155,14 @@ class ActivityModel(TimeStampedModel):
def has_failed(self): def has_failed(self):
return self.finished and not self.succeeded return self.finished and not self.succeeded
@property
def result(self):
return HumanReadableObject.from_dict(self.result_data)
@result.setter
def set_result(self, value):
self.result_data = None if value is None else value.to_dict()
def method_cache(memcached_seconds=60, instance_seconds=5): # noqa def method_cache(memcached_seconds=60, instance_seconds=5): # noqa
"""Cache return value of decorated method to memcached and memory. """Cache return value of decorated method to memcached and memory.
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<span class="timeline-icon{% if a.has_failed %} timeline-icon-failed{% endif %}"> <span class="timeline-icon{% if a.has_failed %} timeline-icon-failed{% endif %}">
<i class="{% if not a.finished %} icon-refresh icon-spin {% else %}icon-plus{% endif %}"></i> <i class="{% if not a.finished %} icon-refresh icon-spin {% else %}icon-plus{% endif %}"></i>
</span> </span>
<strong{% if user.is_superuser and a.result %} title="{{ a.result }}"{% endif %}> <strong{% if user.is_superuser and a.result %} title="{{ a.result.get_admin_text }}"{% endif %}>
{% if user.is_superuser %}<a href="{{ a.get_absolute_url }}">{% endif %} {% if user.is_superuser %}<a href="{{ a.get_absolute_url }}">{% endif %}
{% if a.times > 1 %}({{ a.times }}x){% endif %} {% if a.times > 1 %}({{ a.times }}x){% endif %}
{{ a.get_readable_name }}{% if user.is_superuser %}</a>{% endif %} {{ a.get_readable_name }}{% if user.is_superuser %}</a>{% endif %}
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
<div class="sub-timeline"> <div class="sub-timeline">
{% for s in a.children.all %} {% for s in a.children.all %}
<div data-activity-id="{{ s.pk }}" class="sub-activity{% if s.has_failed %} sub-activity-failed{% endif %}{% if s.pk == active.pk %} sub-activity-active{% endif %}"> <div data-activity-id="{{ s.pk }}" class="sub-activity{% if s.has_failed %} sub-activity-failed{% endif %}{% if s.pk == active.pk %} sub-activity-active{% endif %}">
<span{% if user.is_superuser and s.result %} title="{{ s.result }}"{% endif %}> <span{% if user.is_superuser and s.result %} title="{{ s.result.get_admin_text }}"{% endif %}>
{% if user.is_superuser %}<a href="{{ s.get_absolute_url }}">{% endif %} {% if user.is_superuser %}<a href="{{ s.get_absolute_url }}">{% endif %}
{{ s.get_readable_name }}{% if user.is_superuser %}</a>{% endif %}</span> &ndash; {{ s.get_readable_name }}{% if user.is_superuser %}</a>{% endif %}</span> &ndash;
{% if s.finished %} {% if s.finished %}
......
...@@ -25,10 +25,11 @@ from celery.contrib.abortable import AbortableAsyncResult ...@@ -25,10 +25,11 @@ from celery.contrib.abortable import AbortableAsyncResult
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db.models import CharField, ForeignKey from django.db.models import CharField, ForeignKey
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _, ugettext_noop
from common.models import ( from common.models import (
ActivityModel, activitycontextimpl, join_activity_code, split_activity_code ActivityModel, activitycontextimpl, create_readable, join_activity_code,
split_activity_code
) )
from manager.mancelery import celery from manager.mancelery import celery
...@@ -232,11 +233,12 @@ def node_activity(code_suffix, node, task_uuid=None, user=None): ...@@ -232,11 +233,12 @@ def node_activity(code_suffix, node, task_uuid=None, user=None):
@worker_ready.connect() @worker_ready.connect()
def cleanup(conf=None, **kwargs): def cleanup(conf=None, **kwargs):
# TODO check if other manager workers are running # TODO check if other manager workers are running
msg_txt = ugettext_noop("Manager is restarted, activity is cleaned up. "
"You can try again now.")
message = create_readable(msg_txt, msg_txt)
for i in InstanceActivity.objects.filter(finished__isnull=True): for i in InstanceActivity.objects.filter(finished__isnull=True):
i.finish(False, "Manager is restarted, activity is cleaned up. " i.finish(False, result=message)
"You can try again now.")
logger.error('Forced finishing stale activity %s', i) logger.error('Forced finishing stale activity %s', i)
for i in NodeActivity.objects.filter(finished__isnull=True): for i in NodeActivity.objects.filter(finished__isnull=True):
i.finish(False, "Manager is restarted, activity is cleaned up. " i.finish(False, result=message)
"You can try again now.")
logger.error('Forced finishing stale activity %s', i) logger.error('Forced finishing stale activity %s', i)
...@@ -15,6 +15,7 @@ django-tables2==0.15.0 ...@@ -15,6 +15,7 @@ django-tables2==0.15.0
django-taggit==0.12 django-taggit==0.12
docutils==0.11 docutils==0.11
Jinja2==2.7.2 Jinja2==2.7.2
jsonfield==0.9.20
kombu==3.0.15 kombu==3.0.15
logutils==0.3.3 logutils==0.3.3
MarkupSafe==0.21 MarkupSafe==0.21
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment