diff --git a/moto/swf/models/decision_task.py b/moto/swf/models/decision_task.py index 60d0f7131..e9c3c00f6 100644 --- a/moto/swf/models/decision_task.py +++ b/moto/swf/models/decision_task.py @@ -16,10 +16,11 @@ class DecisionTask(object): # but that shouldn't be a problem for tests self.scheduled_at = datetime.now() - def to_full_dict(self): + def to_full_dict(self, reverse_order=False): + events = self.workflow_execution.events(reverse_order=reverse_order) hsh = { "events": [ - evt.to_dict() for evt in self.workflow_execution.events + evt.to_dict() for evt in events ], "taskToken": self.task_token, "previousStartedEventId": self.previous_started_event_id, diff --git a/moto/swf/models/workflow_execution.py b/moto/swf/models/workflow_execution.py index 110001641..8a719f354 100644 --- a/moto/swf/models/workflow_execution.py +++ b/moto/swf/models/workflow_execution.py @@ -32,7 +32,7 @@ class WorkflowExecution(object): "openChildWorkflowExecutions": 0, } # events - self.events = [] + self._events = [] # tasks self.decision_tasks = [] self.activity_tasks = [] @@ -97,13 +97,19 @@ class WorkflowExecution(object): hsh["openCounts"] = self.open_counts return hsh + def events(self, reverse_order=False): + if reverse_order: + return reversed(self._events) + else: + return self._events + def next_event_id(self): - event_ids = [evt.event_id for evt in self.events] + event_ids = [evt.event_id for evt in self._events] return max(event_ids or [0]) def _add_event(self, *args, **kwargs): evt = HistoryEvent(self.next_event_id(), *args, **kwargs) - self.events.append(evt) + self._events.append(evt) return evt def start(self): diff --git a/moto/swf/responses.py b/moto/swf/responses.py index cd2b99d6c..8f8e86747 100644 --- a/moto/swf/responses.py +++ b/moto/swf/responses.py @@ -215,22 +215,24 @@ class SWFResponse(BaseResponse): _workflow_execution = self._params["execution"] run_id = _workflow_execution["runId"] workflow_id = _workflow_execution["workflowId"] - # TODO: implement reverseOrder - + reverse_order = self._params.get("reverseOrder", None) wfe = self.swf_backend.describe_workflow_execution(domain_name, run_id, workflow_id) + events = wfe.events(reverse_order=reverse_order) return json.dumps({ - "events": [evt.to_dict() for evt in wfe.events] + "events": [evt.to_dict() for evt in events] }) def poll_for_decision_task(self): domain_name = self._params["domain"] task_list = self._params["taskList"]["name"] identity = self._params.get("identity") - # TODO: implement reverseOrder + reverse_order = self._params.get("reverseOrder", None) decision = self.swf_backend.poll_for_decision_task( domain_name, task_list, identity=identity ) if decision: - return json.dumps(decision.to_full_dict()) + return json.dumps( + decision.to_full_dict(reverse_order=reverse_order) + ) else: return json.dumps({"previousStartedEventId": 0, "startedEventId": 0}) diff --git a/tests/test_swf/test_decision_tasks.py b/tests/test_swf/test_decision_tasks.py index 133b830ab..2ff1f7625 100644 --- a/tests/test_swf/test_decision_tasks.py +++ b/tests/test_swf/test_decision_tasks.py @@ -44,3 +44,10 @@ def test_poll_for_decision_task_when_none(): # this is the DecisionTask representation you get from the real SWF # after waiting 60s when there's no decision to be taken resp.should.equal({"previousStartedEventId": 0, "startedEventId": 0}) + +@mock_swf +def test_poll_for_decision_task_with_reverse_order(): + conn = setup_workflow() + resp = conn.poll_for_decision_task("test-domain", "queue", reverse_order=True) + types = [evt["eventType"] for evt in resp["events"]] + types.should.equal(["DecisionTaskStarted", "DecisionTaskScheduled", "WorkflowExecutionStarted"]) diff --git a/tests/test_swf/test_models.py b/tests/test_swf/test_models.py index e7153898f..92be04935 100644 --- a/tests/test_swf/test_models.py +++ b/tests/test_swf/test_models.py @@ -197,8 +197,8 @@ def test_workflow_execution_start_decision_task(): wfe.start_decision_task(dt.task_token, identity="srv01") dt = wfe.decision_tasks[0] dt.state.should.equal("STARTED") - wfe.events[-1].event_type.should.equal("DecisionTaskStarted") - wfe.events[-1].identity.should.equal("srv01") + wfe.events()[-1].event_type.should.equal("DecisionTaskStarted") + wfe.events()[-1].identity.should.equal("srv01") # HistoryEvent diff --git a/tests/test_swf/test_workflow_executions.py b/tests/test_swf/test_workflow_executions.py index 07aea90fb..1b8d599f9 100644 --- a/tests/test_swf/test_workflow_executions.py +++ b/tests/test_swf/test_workflow_executions.py @@ -79,10 +79,19 @@ def test_get_workflow_execution_history(): run_id = hsh["runId"] resp = conn.get_workflow_execution_history("test-domain", run_id, "uid-abcd1234") - resp["events"].should.be.a("list") - evt = resp["events"][0] - evt["eventType"].should.equal("WorkflowExecutionStarted") + types = [evt["eventType"] for evt in resp["events"]] + types.should.equal(["WorkflowExecutionStarted", "DecisionTaskScheduled"]) +@mock_swf +def test_get_workflow_execution_history_with_reverse_order(): + conn = setup_swf_environment() + hsh = conn.start_workflow_execution("test-domain", "uid-abcd1234", "test-workflow", "v1.0") + run_id = hsh["runId"] + + resp = conn.get_workflow_execution_history("test-domain", run_id, "uid-abcd1234", + reverse_order=True) + types = [evt["eventType"] for evt in resp["events"]] + types.should.equal(["DecisionTaskScheduled", "WorkflowExecutionStarted"]) @mock_swf def test_get_workflow_execution_history_on_non_existent_workflow_execution():