Skip to content
Snippets Groups Projects
Commit 4c34b513 authored by Valentin Rigal's avatar Valentin Rigal Committed by Erwan Rouchet
Browse files

Remove old task retry mechanism

parent 47a31812
No related branches found
No related tags found
1 merge request!2273Remove old task retry mechanism
......@@ -165,15 +165,7 @@ class TaskTinySerializer(TaskSerializer):
state = EnumField(
State,
help_text=dedent("""
Allowed transitions for the state of a task by a user are defined below:
Completed ⟶ Pending
Failed ⟶ Pending
Error ⟶ Pending
Stopped ⟶ Pending
Running ⟶ Stopping
""").strip(),
help_text="The state can only be updated from `running` to `stopping`, to manually stop a task.",
)
class Meta:
......@@ -183,32 +175,19 @@ class TaskTinySerializer(TaskSerializer):
def validate_state(self, state):
"""
Only allow a user to manually stop or retry a task
Only allow a user to manually stop a task
"""
allowed_transitions = {
state: [State.Pending] for state in FINAL_STATES
}
allowed_transitions.update({State.Running: [State.Stopping]})
if self.instance and state not in allowed_transitions.get(self.instance.state, []):
raise ValidationError(f"Transition from state {self.instance.state} to state {state} is forbidden.")
if (
self.instance
and self.instance.state != state
and (self.instance.state != State.Running or state != State.Stopping)
):
raise ValidationError("State can only be updated from running to stopping")
return state
def update(self, instance: Task, validated_data) -> Task:
new_state = validated_data.get("state")
if new_state == State.Pending:
if instance.state == State.Unscheduled:
# Prevent a user from restarting a task that was never assigned to an agent.
raise ValidationError({
"state": [f"Transition from state {State.Unscheduled} to state {State.Pending} is forbidden."]
})
# Restart the task
instance.agent = None
instance.gpu = None
# Un-finish the process since a task will run again
instance.process.finished = None
instance.process.save()
if new_state in FINAL_STATES and new_state != State.Completed:
task_failure.send_robust(self.__class__, task=instance)
......
......@@ -9,7 +9,7 @@ from django.urls import reverse
from rest_framework import status
from arkindex.documents.models import Corpus
from arkindex.ponos.models import FINAL_STATES, State, Task
from arkindex.ponos.models import State, Task
from arkindex.process.models import Process, ProcessMode, Revision, WorkerVersion
from arkindex.project.tests import FixtureAPITestCase
from arkindex.users.models import Right, Role, User
......@@ -287,6 +287,7 @@ class TestAPI(FixtureAPITestCase):
def test_update_non_running_task_state_stopping(self):
states = list(State)
states.remove(State.Running)
states.remove(State.Stopping)
self.client.force_login(self.superuser)
for state in states:
......@@ -302,51 +303,46 @@ class TestAPI(FixtureAPITestCase):
self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(
resp.json(),
{"state": [f"Transition from state {state} to state Stopping is forbidden."]},
{"state": ["State can only be updated from running to stopping"]},
)
self.task1.refresh_from_db()
self.assertEqual(self.task1.state, state)
def test_update_final_task_state_pending(self):
self.task1.state = State.Completed
def test_update_running_task_non_pending(self):
states = list(State)
states.remove(State.Running)
states.remove(State.Stopping)
self.task1.state = State.Running
self.task1.save()
self.client.force_login(self.superuser)
with self.assertNumQueries(5):
resp = self.client.put(
reverse("api:task-update", args=[self.task1.id]),
data={"state": State.Pending.value},
)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.task1.refresh_from_db()
self.assertEqual(self.task1.state, State.Pending)
self.assertIsNone(self.task1.agent)
self.assertIsNone(self.task1.gpu)
def test_update_non_final_task_state_pending(self):
states = set(State) - set(FINAL_STATES)
self.client.force_login(self.superuser)
for state in states:
with self.subTest(state=state):
self.task1.state = state
self.task1.save()
with self.assertNumQueries(3):
resp = self.client.put(
reverse("api:task-update", args=[self.task1.id]),
data={"state": State.Pending.value},
data={"state": state.value},
)
self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(
resp.json(),
{"state": [f"Transition from state {state} to state Pending is forbidden."]}
{"state": ["State can only be updated from running to stopping"]},
)
self.task1.refresh_from_db()
self.assertEqual(self.task1.state, state)
def test_update_same_state(self):
states = list(State)
self.client.force_login(self.superuser)
for state in states:
with self.subTest(state=state):
self.task1.state = state
self.task1.save()
resp = self.client.put(
reverse("api:task-update", args=[self.task1.id]),
data={"state": state.value},
)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
def test_partial_update_task_from_agent_requires_login(self):
with self.assertNumQueries(0):
......@@ -424,29 +420,10 @@ class TestAPI(FixtureAPITestCase):
)
self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)
def test_partial_update_running_task_state_stopping(self):
self.task1.state = State.Running
self.task1.save()
self.client.force_login(self.superuser)
with self.assertNumQueries(4):
resp = self.client.patch(
reverse("api:task-update", args=[self.task1.id]),
data={"state": State.Stopping.value},
)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertDictEqual(resp.json(), {
"id": str(self.task1.id),
"state": State.Stopping.value,
})
self.task1.refresh_from_db()
self.assertEqual(self.task1.state, State.Stopping)
def test_partial_update_non_running_task_state_stopping(self):
states = list(State)
states.remove(State.Running)
self.task1.save()
states.remove(State.Stopping)
self.client.force_login(self.superuser)
for state in states:
......@@ -462,51 +439,46 @@ class TestAPI(FixtureAPITestCase):
self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(
resp.json(),
{"state": [f"Transition from state {state} to state Stopping is forbidden."]}
{"state": ["State can only be updated from running to stopping"]},
)
self.task1.refresh_from_db()
self.assertEqual(self.task1.state, state)
def test_partial_update_final_task_state_pending(self):
self.task1.state = State.Completed
def test_partial_update_running_task_non_pending(self):
states = list(State)
states.remove(State.Running)
states.remove(State.Stopping)
self.task1.state = State.Running
self.task1.save()
self.client.force_login(self.superuser)
with self.assertNumQueries(5):
resp = self.client.patch(
reverse("api:task-update", args=[self.task1.id]),
data={"state": State.Pending.value},
)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.task1.refresh_from_db()
self.assertEqual(self.task1.state, State.Pending)
self.assertIsNone(self.task1.agent)
def test_partial_update_non_final_task_state_pending(self):
states = set(State) - set(FINAL_STATES)
self.task1.save()
self.client.force_login(self.superuser)
for state in states:
with self.subTest(state=state):
self.task1.state = state
self.task1.save()
with self.assertNumQueries(3):
resp = self.client.patch(
reverse("api:task-update", args=[self.task1.id]),
data={"state": State.Pending.value},
data={"state": state.value},
)
self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(
resp.json(),
{"state": [f"Transition from state {state} to state Pending is forbidden."]}
{"state": ["State can only be updated from running to stopping"]},
)
self.task1.refresh_from_db()
self.assertEqual(self.task1.state, state)
def test_partial_update_same_state(self):
states = list(State)
self.client.force_login(self.superuser)
for state in states:
with self.subTest(state=state):
self.task1.state = state
self.task1.save()
resp = self.client.patch(
reverse("api:task-update", args=[self.task1.id]),
data={"state": state.value},
)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
@patch("arkindex.project.aws.s3")
def test_task_logs_unicode_error(self, s3_mock):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment