From 77526149bdd53107f4306bca632c1e518374a019 Mon Sep 17 00:00:00 2001 From: Mateusz Kurek Date: Fri, 29 Jul 2016 15:08:44 +0200 Subject: [PATCH 1/2] Limit async transition to one at a time for object --- src/ralph/lib/transitions/async.py | 2 +- src/ralph/lib/transitions/models.py | 22 ++++++++++-- .../lib/transitions/tests/test_actions.py | 34 ++++++++++++++++++- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/ralph/lib/transitions/async.py b/src/ralph/lib/transitions/async.py index b95808feb9..cdf7b02bd5 100644 --- a/src/ralph/lib/transitions/async.py +++ b/src/ralph/lib/transitions/async.py @@ -58,7 +58,7 @@ def run_async_transition(job_id): def _perform_async_transition(transition_job): transition = transition_job.transition obj = transition_job.obj - _check_instances_for_transition([obj], transition) + _check_instances_for_transition([obj], transition, check_async_job=False) _check_action_with_instances([obj], transition) # check if this job isn't already finished diff --git a/src/ralph/lib/transitions/models.py b/src/ralph/lib/transitions/models.py index 5867caf7fb..f65bdc5e85 100644 --- a/src/ralph/lib/transitions/models.py +++ b/src/ralph/lib/transitions/models.py @@ -31,7 +31,7 @@ get_field_by_relation_path ) from ralph.attachments.models import Attachment -from ralph.lib.external_services.models import Job +from ralph.lib.external_services.models import Job, JobStatus from ralph.lib.mixins.models import TimeStampMixin from ralph.lib.transitions.conf import ( DEFAULT_ASYNC_TRANSITION_SERVICE_NAME, @@ -147,7 +147,9 @@ def _check_and_get_transition(obj, transition, field): return transition -def _check_instances_for_transition(instances, transition): +def _check_instances_for_transition( + instances, transition, check_async_job=True +): """Check in respect of the instances source status. Args: @@ -169,6 +171,22 @@ def _check_instances_for_transition(instances, transition): for instance, error_details in error.items(): errors[instance].append(error_details) + if transition.is_async and check_async_job: + for instance in instances: + if TransitionJob.objects.filter( + object_id=instance.id, + content_type=ContentType.objects.get_for_model(instance), + status__in=(JobStatus.STARTED, JobStatus.QUEUED) + ).exists(): + logger.warning( + 'Another async transition is already running for {}'.format( + instance, + ) + ) + errors[instance].append( + 'Another async transition for this object is already stared' + ) + if errors: raise TransitionNotAllowedError( 'Transition {} is not allowed for objects'.format(transition.name), diff --git a/src/ralph/lib/transitions/tests/test_actions.py b/src/ralph/lib/transitions/tests/test_actions.py index 275eb49f7d..91fb84d5dd 100644 --- a/src/ralph/lib/transitions/tests/test_actions.py +++ b/src/ralph/lib/transitions/tests/test_actions.py @@ -14,7 +14,11 @@ OfficeInfrastructureFactory, WarehouseFactory ) -from ralph.lib.transitions.models import TransitionsHistory +from ralph.lib.transitions.models import ( + JobStatus, + TransitionsHistory, + TransitionJob +) from ralph.lib.transitions.tests import TransitionTestCase from ralph.licences.tests.factories import LicenceFactory @@ -198,6 +202,34 @@ def test_async_gui(self): history = self.get_transition_history(bo.pk) self.assertIn(self.user.username, history.kwargs['user']) + def test_async_gui_running_new_when_another_in_progress_should_return_error(self): # noqa + # mock another async job running + TransitionJob.objects.create( + obj=self.bo, + transition=self.transition_2, + status=JobStatus.STARTED, + service_name='ASYNC', + ) + request = self.client.post( + reverse( + 'admin:back_office_backofficeasset_transition', + args=(self.bo.id, self.transition_2.id) + ), + self.prepare_gui_data(), + follow=True + ) + self.assertTrue( + request.redirect_chain[0][0], + reverse( + 'admin:back_office_backofficeasset_change', + args=(self.bo.id,) + ) + ) + self.assertIn( + 'Another async transition for this object is already stared', + str(list(request.context['messages'])[1]) + ) + def test_api_options(self): request = self.api_client.options( reverse( From 9a621aae034e7068ee0b68f3755f3b477cce6a53 Mon Sep 17 00:00:00 2001 From: Mateusz Kurek Date: Tue, 2 Aug 2016 15:34:23 +0200 Subject: [PATCH 2/2] wip --- src/ralph/lib/transitions/tests/test_actions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ralph/lib/transitions/tests/test_actions.py b/src/ralph/lib/transitions/tests/test_actions.py index 91fb84d5dd..c9539b1e1f 100644 --- a/src/ralph/lib/transitions/tests/test_actions.py +++ b/src/ralph/lib/transitions/tests/test_actions.py @@ -16,8 +16,8 @@ ) from ralph.lib.transitions.models import ( JobStatus, - TransitionsHistory, - TransitionJob + TransitionJob, + TransitionsHistory ) from ralph.lib.transitions.tests import TransitionTestCase from ralph.licences.tests.factories import LicenceFactory