Skip to content

Commit

Permalink
Merge fac536f into edbfd52
Browse files Browse the repository at this point in the history
  • Loading branch information
mkurek committed Apr 5, 2016
2 parents edbfd52 + fac536f commit bc1d8be
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 39 deletions.
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('external_services', '0002_auto_20160325_0837'),
]

operations = [
migrations.RenameField(
model_name='job',
old_name='user',
new_name='username',
),
]
24 changes: 20 additions & 4 deletions src/ralph/lib/external_services/models.py
Expand Up @@ -3,6 +3,7 @@
import uuid

from dj.choices import Choices
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils.translation import ugettext_lazy as _
Expand Down Expand Up @@ -31,7 +32,7 @@ class JobStatus(Choices):

class Job(TimeStampMixin):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = NullableCharField(max_length=200, null=True, blank=True)
username = NullableCharField(max_length=200, null=True, blank=True)
service_name = models.CharField(max_length=200, null=False, blank=False)
_dumped_params = JSONField()
status = models.PositiveIntegerField(
Expand All @@ -47,6 +48,20 @@ class Meta:
def __str__(self):
return '{} ({})'.format(self.service_name, self.id)

@property
def user(self):
try:
return self.params['_request__user']
except KeyError:
if self.username:
try:
return get_user_model()._default_manager.get(
username=self.username
)
except get_user_model().DoesNotExist:
pass
return None

@property
def is_running(self):
"""
Expand Down Expand Up @@ -95,8 +110,9 @@ def prepare_params(cls, **kwargs):
request = kwargs.pop('request', None)
result = cls.dump_obj_to_jsonable(kwargs)
user = _get_user_from_request(request)
if user:
result['_request__user'] = cls.dump_obj_to_jsonable(user)
result['_request__user'] = (
cls.dump_obj_to_jsonable(user) if user else None
)
return result

@classmethod
Expand All @@ -108,7 +124,7 @@ def run(cls, service_name, defaults=None, **kwargs):
user = _get_user_from_request(kwargs.get('request'))
obj = cls._default_manager.create(
service_name=service_name,
user=user.username if user else None,
username=user.username if user else None,
_dumped_params=cls.prepare_params(**kwargs),
**(defaults or {})
)
Expand Down
23 changes: 20 additions & 3 deletions src/ralph/lib/transitions/async.py
Expand Up @@ -2,13 +2,16 @@
Asynchronous runner for transitions
"""
import logging
from collections import defaultdict

from django.db import transaction

from ralph.attachments.models import Attachment
from ralph.lib.transitions.models import (
_check_action_with_instances,
_check_instances_for_transition,
_order_actions_by_requirements,
_post_transition_instance_processing,
_prepare_action_data,
TransitionJob,
TransitionJobAction,
Expand Down Expand Up @@ -62,6 +65,7 @@ def run_async_transition(job_id):
transition_job.fail(str(e))


# TODO: unify this function with `ralph.lib.transitions.models.run_field_transition` # noqa
def _perform_async_transition(transition_job):
transition = transition_job.transition
obj = transition_job.obj
Expand All @@ -85,6 +89,8 @@ def _perform_async_transition(transition_job):
tja.action_name for tja in executed_actions
if tja.status != TransitionJobActionStatus.STARTED
])
attachment = None
func_history_kwargs = defaultdict(dict)
# TODO: move this to transition (sth like
# `for action in transition.get_actions(obj)`)
for action in _order_actions_by_requirements(transition.actions.all(), obj):
Expand All @@ -99,7 +105,11 @@ def _perform_async_transition(transition_job):
func = getattr(obj, action.name)
# TODO: disable save object ?
# data should be in transition_job.params dict
defaults = _prepare_action_data(action, **transition_job.params)
defaults = _prepare_action_data(
action=action,
func_history_kwargs=func_history_kwargs,
**transition_job.params
)
tja = TransitionJobAction.objects.get_or_create(
transition_job=transition_job,
action_name=action.name,
Expand All @@ -113,12 +123,15 @@ def _perform_async_transition(transition_job):
# action in transaction instead
with transaction.atomic():
try:
func(instances=[obj], **defaults)
result = func(instances=[obj], **defaults)
except RescheduleAsyncTransitionActionLater as e:
# action is not ready - reschedule this job later and
# continue when you left off
transition_job.reschedule()
return
else:
if isinstance(result, Attachment):
attachment = result
except Exception as e:
logger.exception(e)
tja.status = TransitionJobActionStatus.FAILED
Expand All @@ -129,5 +142,9 @@ def _perform_async_transition(transition_job):
tja.save()
completed_actions_names.add(action.name)

# TODO: history
# save obj and history
_post_transition_instance_processing(
obj, transition, transition_job.params, func_history_kwargs,
user=transition_job.user, attachment=attachment,
)
transition_job.success()
84 changes: 52 additions & 32 deletions src/ralph/lib/transitions/models.py
Expand Up @@ -283,6 +283,54 @@ def _prepare_action_data(action, data, func_history_kwargs=None, **kwargs):
return defaults


def _save_instance_after_transition(instance, transition, user=None):
# don't save object if any of actions have `disable_save_object` flag set
if not any([a.disable_save_object for a in transition.get_pure_actions()]):
with transaction.atomic(), reversion.create_revision():
instance.save()
reversion.set_comment('Transition {}'.format(transition))
if user:
reversion.set_user(user)


def _create_instance_history_entry(
instance, transition, data, func_history_kwargs, user=None, attachment=None
):
funcs = transition.get_pure_actions()
action_names = [str(getattr(
func,
'verbose_name',
func.__name__.replace('_', ' ').capitalize()
)) for func in funcs]
history_kwargs = _get_history_dict(data, instance, funcs)
history_kwargs.update(func_history_kwargs[instance.pk])
transition_history = _generate_transition_history(
instance=instance,
transition=transition,
user=user,
attachment=attachment,
history_kwargs=history_kwargs,
action_names=action_names,
field=transition.model.field_name
)
transition_history.save()


def _post_transition_instance_processing(
instance, transition, data, func_history_kwargs, user=None, attachment=None
):
# change transition field (ex. status) if not keeping orignial
if not int(transition.target) == TRANSITION_ORIGINAL_STATUS[0]:
setattr(instance, transition.model.field_name, int(transition.target))
_create_instance_history_entry(
instance, transition, data, func_history_kwargs,
user=user, attachment=attachment
)
_save_instance_after_transition(
instance, transition, user
)


@transaction.atomic
def run_field_transition(
instances, transition_obj_or_name, field, data={}, **kwargs
Expand All @@ -298,19 +346,14 @@ def run_field_transition(
_check_instances_for_transition(instances, transition)
_check_action_with_instances(instances, transition)
attachment = None
action_names = []
runned_funcs = []
func_history_kwargs = defaultdict(dict)
disable_save_object = False
for action in _order_actions_by_requirements(
transition.actions.all(), first_instance
):
logger.info('Performing action {} in transition {}'.format(
action, transition
))
func = getattr(first_instance, action.name)
if func.disable_save_object:
disable_save_object = True
defaults = _prepare_action_data(
action, data, func_history_kwargs, **kwargs
)
Expand All @@ -320,36 +363,13 @@ def run_field_transition(
logger.exception(e)
return False, None

runned_funcs.append(func)
action_names.append(str(getattr(
func,
'verbose_name',
func.__name__.replace('_', ' ').capitalize()
)))
if isinstance(result, Attachment):
attachment = result
history_list = []
for instance in instances:
if not int(transition.target) == TRANSITION_ORIGINAL_STATUS[0]:
setattr(instance, field, int(transition.target))
history_kwargs = _get_history_dict(data, instance, runned_funcs)
history_kwargs.update(func_history_kwargs[instance.pk])
history_list.append(_generate_transition_history(
instance=instance,
transition=transition,
user=kwargs['request'].user,
attachment=attachment,
history_kwargs=history_kwargs,
action_names=action_names,
field=field
))
if not disable_save_object:
with transaction.atomic(), reversion.create_revision():
instance.save()
reversion.set_comment('Transition {}'.format(transition))
reversion.set_user(kwargs['request'].user)
if history_list:
TransitionsHistory.objects.bulk_create(history_list)
_post_transition_instance_processing(
instance, transition, data, func_history_kwargs,
user=kwargs['request'].user, attachment=attachment,
)
return True, attachment


Expand Down

0 comments on commit bc1d8be

Please sign in to comment.