2023-08-12 07:59:33 +00:00
|
|
|
import re
|
|
|
|
|
|
|
|
import pytest
|
2023-11-30 15:55:51 +00:00
|
|
|
from freezegun import freeze_time
|
2015-10-26 05:31:00 +00:00
|
|
|
|
2015-11-05 00:12:51 +00:00
|
|
|
from moto.swf.exceptions import SWFWorkflowExecutionClosedError
|
2015-10-26 22:16:59 +00:00
|
|
|
from moto.swf.models import ActivityTask, ActivityType, Timeout
|
2015-10-26 05:31:00 +00:00
|
|
|
|
2015-11-05 01:47:05 +00:00
|
|
|
from ..utils import (
|
|
|
|
ACTIVITY_TASK_TIMEOUTS,
|
|
|
|
make_workflow_execution,
|
|
|
|
process_first_timeout,
|
|
|
|
)
|
2015-10-26 05:31:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_activity_task_creation():
|
|
|
|
wfe = make_workflow_execution()
|
|
|
|
task = ActivityTask(
|
|
|
|
activity_id="my-activity-123",
|
|
|
|
activity_type="foo",
|
2022-01-14 19:51:49 +00:00
|
|
|
workflow_input="optional",
|
2015-10-26 22:16:59 +00:00
|
|
|
scheduled_event_id=117,
|
2015-10-26 05:31:00 +00:00
|
|
|
workflow_execution=wfe,
|
2015-11-02 23:28:13 +00:00
|
|
|
timeouts=ACTIVITY_TASK_TIMEOUTS,
|
2015-10-26 05:31:00 +00:00
|
|
|
)
|
2023-08-12 07:59:33 +00:00
|
|
|
assert task.workflow_execution == wfe
|
|
|
|
assert task.state == "SCHEDULED"
|
|
|
|
assert re.match("[-a-z0-9]+", task.task_token)
|
|
|
|
assert task.started_event_id is None
|
2015-10-26 05:31:00 +00:00
|
|
|
|
|
|
|
task.start(123)
|
2023-08-12 07:59:33 +00:00
|
|
|
assert task.state == "STARTED"
|
|
|
|
assert task.started_event_id == 123
|
2015-10-26 05:31:00 +00:00
|
|
|
|
|
|
|
task.complete()
|
2023-08-12 07:59:33 +00:00
|
|
|
assert task.state == "COMPLETED"
|
2015-10-26 22:16:59 +00:00
|
|
|
|
2015-10-28 11:29:57 +00:00
|
|
|
# NB: this doesn't make any sense for SWF, a task shouldn't go from a
|
|
|
|
# "COMPLETED" state to a "FAILED" one, but this is an internal state on our
|
|
|
|
# side and we don't care about invalid state transitions for now.
|
|
|
|
task.fail()
|
2023-08-12 07:59:33 +00:00
|
|
|
assert task.state == "FAILED"
|
2015-10-28 11:29:57 +00:00
|
|
|
|
2016-02-02 19:02:37 +00:00
|
|
|
|
2015-10-26 22:16:59 +00:00
|
|
|
def test_activity_task_full_dict_representation():
|
|
|
|
wfe = make_workflow_execution()
|
|
|
|
at = ActivityTask(
|
|
|
|
activity_id="my-activity-123",
|
|
|
|
activity_type=ActivityType("foo", "v1.0"),
|
2022-01-14 19:51:49 +00:00
|
|
|
workflow_input="optional",
|
2015-10-26 22:16:59 +00:00
|
|
|
scheduled_event_id=117,
|
2015-11-02 23:28:13 +00:00
|
|
|
timeouts=ACTIVITY_TASK_TIMEOUTS,
|
2015-10-26 22:16:59 +00:00
|
|
|
workflow_execution=wfe,
|
|
|
|
)
|
|
|
|
at.start(1234)
|
|
|
|
|
|
|
|
fd = at.to_full_dict()
|
2023-08-12 07:59:33 +00:00
|
|
|
assert fd["activityId"] == "my-activity-123"
|
|
|
|
assert fd["activityType"]["version"] == "v1.0"
|
|
|
|
assert fd["input"] == "optional"
|
|
|
|
assert fd["startedEventId"] == 1234
|
|
|
|
assert "taskToken" in fd
|
|
|
|
assert fd["workflowExecution"] == wfe.to_short_dict()
|
2015-10-26 22:16:59 +00:00
|
|
|
|
|
|
|
at.start(1234)
|
|
|
|
fd = at.to_full_dict()
|
2023-08-12 07:59:33 +00:00
|
|
|
assert fd["startedEventId"] == 1234
|
2015-11-02 09:26:40 +00:00
|
|
|
|
2016-02-02 19:02:37 +00:00
|
|
|
|
2015-11-02 09:26:40 +00:00
|
|
|
def test_activity_task_reset_heartbeat_clock():
|
|
|
|
wfe = make_workflow_execution()
|
|
|
|
|
|
|
|
with freeze_time("2015-01-01 12:00:00"):
|
|
|
|
task = ActivityTask(
|
|
|
|
activity_id="my-activity-123",
|
|
|
|
activity_type="foo",
|
2022-01-14 19:51:49 +00:00
|
|
|
workflow_input="optional",
|
2015-11-02 09:26:40 +00:00
|
|
|
scheduled_event_id=117,
|
2015-11-02 23:28:13 +00:00
|
|
|
timeouts=ACTIVITY_TASK_TIMEOUTS,
|
2015-11-02 09:26:40 +00:00
|
|
|
workflow_execution=wfe,
|
|
|
|
)
|
|
|
|
|
2023-08-12 07:59:33 +00:00
|
|
|
assert task.last_heartbeat_timestamp == 1420113600.0
|
2015-11-02 09:26:40 +00:00
|
|
|
|
|
|
|
with freeze_time("2015-01-01 13:00:00"):
|
|
|
|
task.reset_heartbeat_clock()
|
|
|
|
|
2023-08-12 07:59:33 +00:00
|
|
|
assert task.last_heartbeat_timestamp == 1420117200.0
|
2015-11-02 23:28:13 +00:00
|
|
|
|
2016-02-02 19:02:37 +00:00
|
|
|
|
2015-11-05 01:22:02 +00:00
|
|
|
def test_activity_task_first_timeout():
|
2015-11-02 23:28:13 +00:00
|
|
|
wfe = make_workflow_execution()
|
|
|
|
|
|
|
|
with freeze_time("2015-01-01 12:00:00"):
|
|
|
|
task = ActivityTask(
|
|
|
|
activity_id="my-activity-123",
|
|
|
|
activity_type="foo",
|
2022-01-14 19:51:49 +00:00
|
|
|
workflow_input="optional",
|
2015-11-02 23:28:13 +00:00
|
|
|
scheduled_event_id=117,
|
|
|
|
timeouts=ACTIVITY_TASK_TIMEOUTS,
|
|
|
|
workflow_execution=wfe,
|
|
|
|
)
|
2023-08-12 07:59:33 +00:00
|
|
|
assert task.first_timeout() is None
|
2015-11-02 23:28:13 +00:00
|
|
|
|
|
|
|
# activity task timeout is 300s == 5mins
|
|
|
|
with freeze_time("2015-01-01 12:06:00"):
|
2023-08-12 07:59:33 +00:00
|
|
|
assert isinstance(task.first_timeout(), Timeout)
|
2015-11-05 01:47:05 +00:00
|
|
|
process_first_timeout(task)
|
2023-08-12 07:59:33 +00:00
|
|
|
assert task.state == "TIMED_OUT"
|
|
|
|
assert task.timeout_type == "HEARTBEAT"
|
2015-11-04 21:35:45 +00:00
|
|
|
|
2016-02-02 19:02:37 +00:00
|
|
|
|
2021-02-12 13:01:42 +00:00
|
|
|
def test_activity_task_first_timeout_with_heartbeat_timeout_none():
|
|
|
|
wfe = make_workflow_execution()
|
|
|
|
|
|
|
|
activity_task_timeouts = ACTIVITY_TASK_TIMEOUTS.copy()
|
|
|
|
activity_task_timeouts["heartbeatTimeout"] = "NONE"
|
|
|
|
|
|
|
|
with freeze_time("2015-01-01 12:00:00"):
|
|
|
|
task = ActivityTask(
|
|
|
|
activity_id="my-activity-123",
|
|
|
|
activity_type="foo",
|
2022-01-14 19:51:49 +00:00
|
|
|
workflow_input="optional",
|
2021-02-12 13:01:42 +00:00
|
|
|
scheduled_event_id=117,
|
|
|
|
timeouts=activity_task_timeouts,
|
|
|
|
workflow_execution=wfe,
|
|
|
|
)
|
2023-08-12 07:59:33 +00:00
|
|
|
assert task.first_timeout() is None
|
2021-02-12 13:01:42 +00:00
|
|
|
|
|
|
|
|
2015-11-04 21:35:45 +00:00
|
|
|
def test_activity_task_cannot_timeout_on_closed_workflow_execution():
|
|
|
|
with freeze_time("2015-01-01 12:00:00"):
|
|
|
|
wfe = make_workflow_execution()
|
|
|
|
wfe.start()
|
|
|
|
|
|
|
|
with freeze_time("2015-01-01 13:58:00"):
|
|
|
|
task = ActivityTask(
|
|
|
|
activity_id="my-activity-123",
|
|
|
|
activity_type="foo",
|
2022-01-14 19:51:49 +00:00
|
|
|
workflow_input="optional",
|
2015-11-04 21:35:45 +00:00
|
|
|
scheduled_event_id=117,
|
|
|
|
timeouts=ACTIVITY_TASK_TIMEOUTS,
|
|
|
|
workflow_execution=wfe,
|
|
|
|
)
|
|
|
|
|
|
|
|
with freeze_time("2015-01-01 14:10:00"):
|
2023-08-12 07:59:33 +00:00
|
|
|
assert isinstance(task.first_timeout(), Timeout)
|
|
|
|
assert isinstance(wfe.first_timeout(), Timeout)
|
2015-11-05 01:47:05 +00:00
|
|
|
process_first_timeout(wfe)
|
2023-08-12 07:59:33 +00:00
|
|
|
assert task.first_timeout() is None
|
2015-11-05 00:12:51 +00:00
|
|
|
|
2016-02-02 19:02:37 +00:00
|
|
|
|
2015-11-05 00:12:51 +00:00
|
|
|
def test_activity_task_cannot_change_state_on_closed_workflow_execution():
|
|
|
|
wfe = make_workflow_execution()
|
|
|
|
wfe.start()
|
|
|
|
|
|
|
|
task = ActivityTask(
|
|
|
|
activity_id="my-activity-123",
|
|
|
|
activity_type="foo",
|
2022-01-14 19:51:49 +00:00
|
|
|
workflow_input="optional",
|
2015-11-05 00:12:51 +00:00
|
|
|
scheduled_event_id=117,
|
|
|
|
timeouts=ACTIVITY_TASK_TIMEOUTS,
|
|
|
|
workflow_execution=wfe,
|
|
|
|
)
|
|
|
|
wfe.complete(123)
|
|
|
|
|
2023-08-12 07:59:33 +00:00
|
|
|
with pytest.raises(SWFWorkflowExecutionClosedError):
|
|
|
|
task.timeout(Timeout(task, 0, "foo"))
|
|
|
|
with pytest.raises(SWFWorkflowExecutionClosedError):
|
|
|
|
task.complete()
|
|
|
|
with pytest.raises(SWFWorkflowExecutionClosedError):
|
|
|
|
task.fail()
|