-
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #833 from openzim/fix_periodic_scheduling
Fix periodic scheduling + most_recent_task update
- Loading branch information
Showing
7 changed files
with
274 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
dispatcher/backend/src/tests/integration/routes/business_logic/test_periodic_scheduling.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import datetime | ||
from typing import Any, Dict | ||
|
||
import sqlalchemy as sa | ||
import sqlalchemy.orm as so | ||
|
||
import db.models as dbm | ||
from common import getnow | ||
from common.enum import TaskStatus | ||
from db import Session | ||
from utils.scheduling import request_tasks_using_schedule | ||
|
||
|
||
class TestPeriodicScheduling: | ||
def get_requested_tasks_for_schedule( | ||
self, session: so.Session, schedule: Dict[str, Any] | ||
): | ||
"""return the list of requested tasks for a given schedule""" | ||
return session.execute( | ||
sa.select(dbm.RequestedTask).where( | ||
dbm.RequestedTask.schedule_id == schedule["_id"] | ||
) | ||
).all() | ||
|
||
def assert_number_of_requested_tasks_for_schedule( | ||
self, schedule: Dict[str, Any], expected: int | ||
): | ||
"""assert that the number of requested tasks for a given schedule is expected""" | ||
with Session.begin() as session: | ||
req_tasks = self.get_requested_tasks_for_schedule(session, schedule) | ||
assert len(req_tasks) == expected | ||
|
||
def test_periodic_scheduling_simple(self, temp_schedule): | ||
"""simple tests of periodic scheduling""" | ||
self.assert_number_of_requested_tasks_for_schedule(temp_schedule, 0) | ||
request_tasks_using_schedule() | ||
self.assert_number_of_requested_tasks_for_schedule(temp_schedule, 1) | ||
request_tasks_using_schedule() # request again should not duplicate requests | ||
self.assert_number_of_requested_tasks_for_schedule(temp_schedule, 1) | ||
|
||
def test_periodic_scheduling_most_recent_recent(self, temp_schedule, make_task): | ||
"""most recent task is too recent => do not request it again""" | ||
most_recent = make_task(temp_schedule["name"]) | ||
now = getnow() | ||
with Session.begin() as session: | ||
task = dbm.Task.get(session, most_recent["_id"]) | ||
task.timestamp = { | ||
TaskStatus.requested: now - datetime.timedelta(hours=4), | ||
TaskStatus.reserved: now - datetime.timedelta(hours=3, minutes=59), | ||
TaskStatus.started: now - datetime.timedelta(hours=3, minutes=58), | ||
TaskStatus.succeeded: now - datetime.timedelta(hours=1), | ||
} | ||
schedule_obj = dbm.Schedule.get(session, temp_schedule["name"]) | ||
schedule_obj.most_recent_task = task | ||
self.assert_number_of_requested_tasks_for_schedule(temp_schedule, 0) | ||
request_tasks_using_schedule() | ||
self.assert_number_of_requested_tasks_for_schedule(temp_schedule, 0) | ||
|
||
def test_periodic_scheduling_most_recent_overdue_complete( | ||
self, temp_schedule, make_task | ||
): | ||
"""most recent task is overdue and not running => request a new execution""" | ||
most_recent = make_task(temp_schedule["name"]) | ||
now = getnow() | ||
with Session.begin() as session: | ||
task = dbm.Task.get(session, most_recent["_id"]) | ||
task.timestamp = { | ||
TaskStatus.requested: now - datetime.timedelta(days=40, hours=4), | ||
TaskStatus.reserved: now | ||
- datetime.timedelta(days=40, hours=3, minutes=59), | ||
TaskStatus.started: now | ||
- datetime.timedelta(days=40, hours=3, minutes=58), | ||
TaskStatus.succeeded: now - datetime.timedelta(days=40, hours=1), | ||
} | ||
schedule_obj = dbm.Schedule.get(session, temp_schedule["name"]) | ||
schedule_obj.most_recent_task = task | ||
self.assert_number_of_requested_tasks_for_schedule(temp_schedule, 0) | ||
request_tasks_using_schedule() | ||
self.assert_number_of_requested_tasks_for_schedule(temp_schedule, 1) | ||
|
||
def test_periodic_scheduling_most_recent_overdue_running( | ||
self, temp_schedule, make_task | ||
): | ||
"""most recent task is overdue but still running => do not request it again""" | ||
most_recent = make_task(temp_schedule["name"]) | ||
now = getnow() | ||
with Session.begin() as session: | ||
task = dbm.Task.get(session, most_recent["_id"]) | ||
task.timestamp = { | ||
TaskStatus.requested: now - datetime.timedelta(days=40, hours=4), | ||
TaskStatus.reserved: now | ||
- datetime.timedelta(days=40, hours=3, minutes=59), | ||
TaskStatus.started: now | ||
- datetime.timedelta(days=40, hours=3, minutes=58), | ||
} | ||
task.status = TaskStatus.started | ||
schedule_obj = dbm.Schedule.get(session, temp_schedule["name"]) | ||
schedule_obj.most_recent_task = task | ||
self.assert_number_of_requested_tasks_for_schedule(temp_schedule, 0) | ||
request_tasks_using_schedule() | ||
self.assert_number_of_requested_tasks_for_schedule(temp_schedule, 0) |
28 changes: 28 additions & 0 deletions
28
dispatcher/backend/src/tests/integration/routes/business_logic/test_task_event_handler.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import db.models as dbm | ||
from common.enum import TaskStatus | ||
from common.utils import task_event_handler | ||
from db import Session | ||
|
||
|
||
class TestTaskEvents: | ||
def test_task_event_reserved_updates_most_recent_task( | ||
self, temp_schedule, make_task, worker | ||
): | ||
task = make_task(schedule_name=temp_schedule["name"]) | ||
with Session.begin() as session: | ||
schedule = dbm.Schedule.get(session, temp_schedule["name"]) | ||
assert schedule.most_recent_task_id is None | ||
task_event_handler( | ||
session, task["_id"], TaskStatus.reserved, {"worker": worker["name"]} | ||
) | ||
assert schedule.most_recent_task_id == task["_id"] | ||
|
||
def test_task_event_started_does_not_updates_most_recent_task( | ||
self, temp_schedule, make_task, worker | ||
): | ||
task = make_task(schedule_name=temp_schedule["name"]) | ||
with Session.begin() as session: | ||
schedule = dbm.Schedule.get(session, temp_schedule["name"]) | ||
assert schedule.most_recent_task_id is None | ||
task_event_handler(session, task["_id"], TaskStatus.started, {}) | ||
assert schedule.most_recent_task_id is None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.