Skip to content

Commit

Permalink
feat: cp duration starts with build (#998)
Browse files Browse the repository at this point in the history
* feat: start cp timer when status changed to `PLAN_STATUS_DOING`

Signed-off-by: Guilhem Barthés <guilhem.barthes@owkin.com>

* chore: rename `ComputePlan.update_dates` to `ComputePlan.update_end_date`

Signed-off-by: Guilhem Barthés <guilhem.barthes@owkin.com>

* fix: tests

Signed-off-by: Guilhem Barthés <guilhem.barthes@owkin.com>

* doc: change fragment

Signed-off-by: Guilhem Barthés <guilhem.barthes@owkin.com>

---------

Signed-off-by: Guilhem Barthés <guilhem.barthes@owkin.com>
  • Loading branch information
guilhem-barthes authored Sep 17, 2024
1 parent 3ff7c51 commit 71dc1f2
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 35 deletions.
6 changes: 3 additions & 3 deletions backend/api/events/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def _update_computeplan(key: str, data: dict) -> None:
compute_plan.cancelation_date = data.get("cancelation_date")
compute_plan.name = data.get("name")
compute_plan.save()
compute_plan.update_dates()
compute_plan.update_end_date()
compute_plan.update_status()


Expand All @@ -167,7 +167,7 @@ def _on_create_computetask_event(event: dict) -> None:
_create_computetask(channel=event["channel"], data=task_data)

compute_plan = ComputePlan.objects.get(key=task_data["compute_plan_key"])
compute_plan.update_dates()
compute_plan.update_end_date()
compute_plan.update_status()


Expand Down Expand Up @@ -205,7 +205,7 @@ def _on_update_computetask_event(event: dict) -> None:
# update CP dates:
# - after task status, to ensure proper rules are applied
# - before CP status, to ensure dates are up-to-date when client wait on status
compute_plan.update_dates()
compute_plan.update_end_date()
compute_plan.update_status()


Expand Down
11 changes: 5 additions & 6 deletions backend/api/models/computeplan.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.db import models
from django.db.models import Count
from django.db.models import Q
from django.utils import timezone

from api.models.computetask import ComputeTask

Expand Down Expand Up @@ -112,21 +113,19 @@ def update_status(self) -> None:
**stats,
)

if compute_plan_status != self.Status.PLAN_STATUS_CREATED and not self.start_date:
self.start_date = timezone.now()

self.status = compute_plan_status

if self.status == self.Status.PLAN_STATUS_FAILED:
self._add_failed_task()

self.save()

def update_dates(self) -> None:
def update_end_date(self) -> None:
"""Update start_date, end_date"""

if not self.start_date:
first_started_task = self.compute_tasks.filter(start_date__isnull=False).order_by("start_date").first()
if first_started_task:
self.start_date = first_started_task.start_date

ongoing_tasks = self.compute_tasks.filter(end_date__isnull=True).exists()
failed_or_canceled_tasks = self.compute_tasks.filter(
status__in=(
Expand Down
93 changes: 68 additions & 25 deletions backend/api/tests/models/test_models_computeplan.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,85 @@

@pytest.mark.django_db
@pytest.mark.parametrize(
"status,has_start_date,has_end_date",
"status,has_end_date",
(
(ComputeTask.Status.STATUS_WAITING_FOR_BUILDER_SLOT, False, False),
(ComputeTask.Status.STATUS_BUILDING, True, False),
(ComputeTask.Status.STATUS_WAITING_FOR_PARENT_TASKS, True, False),
(ComputeTask.Status.STATUS_WAITING_FOR_EXECUTOR_SLOT, True, False),
(ComputeTask.Status.STATUS_EXECUTING, True, False),
(ComputeTask.Status.STATUS_DONE, True, True),
(ComputeTask.Status.STATUS_FAILED, True, True),
(ComputeTask.Status.STATUS_CANCELED, True, True),
(ComputeTask.Status.STATUS_WAITING_FOR_BUILDER_SLOT, False),
(ComputeTask.Status.STATUS_BUILDING, False),
(ComputeTask.Status.STATUS_WAITING_FOR_PARENT_TASKS, False),
(ComputeTask.Status.STATUS_WAITING_FOR_EXECUTOR_SLOT, False),
(ComputeTask.Status.STATUS_EXECUTING, False),
(ComputeTask.Status.STATUS_DONE, True),
(ComputeTask.Status.STATUS_FAILED, True),
(ComputeTask.Status.STATUS_CANCELED, True),
),
)
def test_update_dates_single_task(status, has_start_date, has_end_date):
def test_update_end_date_single_task(status, has_end_date):
function = factory.create_function()
compute_plan = factory.create_computeplan()
compute_task = factory.create_computetask(compute_plan, function, status=status)
# validate inputs
if has_start_date:
assert compute_task.start_date is not None
else:
assert compute_task.start_date is None
if has_end_date:
assert compute_task.end_date is not None
else:
assert compute_task.end_date is None

compute_plan.update_dates()
compute_plan.update_end_date()
# validate outputs
if has_end_date:
assert compute_plan.end_date is not None
else:
assert compute_plan.end_date is None


@pytest.mark.django_db
@pytest.mark.parametrize(
"status,has_start_date",
(
(ComputeTask.Status.STATUS_WAITING_FOR_BUILDER_SLOT, False),
(ComputeTask.Status.STATUS_BUILDING, True),
(ComputeTask.Status.STATUS_WAITING_FOR_PARENT_TASKS, True),
(ComputeTask.Status.STATUS_WAITING_FOR_EXECUTOR_SLOT, True),
(ComputeTask.Status.STATUS_EXECUTING, True),
(ComputeTask.Status.STATUS_DONE, True),
(ComputeTask.Status.STATUS_FAILED, True),
(ComputeTask.Status.STATUS_CANCELED, True),
),
)
def test_update_start_date_single_task(status, has_start_date):
function = factory.create_function()
compute_plan = factory.create_computeplan()
compute_task = factory.create_computetask(compute_plan, function, status=status)
# validate inputs
if has_start_date:
assert compute_task.start_date is not None
else:
assert compute_task.start_date is None

compute_plan.update_status()
# validate outputs
if has_start_date:
assert compute_plan.start_date is not None
else:
assert compute_plan.start_date is None


@pytest.mark.django_db
@pytest.mark.parametrize(
"status,has_end_date",
(
(ComputeTask.Status.STATUS_DONE, False), # cp has restarted
(ComputeTask.Status.STATUS_FAILED, True),
(ComputeTask.Status.STATUS_CANCELED, True),
),
)
def test_update_end_date_ended_cp_with_ongoing_task(status, has_end_date):
function = factory.create_function()
compute_plan = factory.create_computeplan()
factory.create_computetask(compute_plan, function, status=status)
factory.create_computetask(compute_plan, function, status=ComputeTask.Status.STATUS_WAITING_FOR_PARENT_TASKS)

compute_plan.update_end_date()
# validate outputs
if has_end_date:
assert compute_plan.end_date is not None
else:
Expand All @@ -46,26 +93,22 @@ def test_update_dates_single_task(status, has_start_date, has_end_date):

@pytest.mark.django_db
@pytest.mark.parametrize(
"status,has_start_date,has_end_date",
"status,has_start_date",
(
(ComputeTask.Status.STATUS_DONE, True, False), # cp has restarted
(ComputeTask.Status.STATUS_FAILED, True, True),
(ComputeTask.Status.STATUS_CANCELED, True, True),
(ComputeTask.Status.STATUS_DONE, True), # cp has restarted
(ComputeTask.Status.STATUS_FAILED, True),
(ComputeTask.Status.STATUS_CANCELED, True),
),
)
def test_update_dates_ended_cp_with_ongoing_task(status, has_start_date, has_end_date):
def test_update_start_date_ended_cp_with_ongoing_task(status, has_start_date):
function = factory.create_function()
compute_plan = factory.create_computeplan()
factory.create_computetask(compute_plan, function, status=status)
factory.create_computetask(compute_plan, function, status=ComputeTask.Status.STATUS_WAITING_FOR_PARENT_TASKS)

compute_plan.update_dates()
compute_plan.update_status()
# validate outputs
if has_start_date:
assert compute_plan.start_date is not None
else:
assert compute_plan.start_date is None
if has_end_date:
assert compute_plan.end_date is not None
else:
assert compute_plan.end_date is None
2 changes: 1 addition & 1 deletion backend/api/views/computetask.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def task_bulk_create(request):
api_task_data = api_serializer.data
data.append(api_task_data)

compute_plan.update_dates()
compute_plan.update_end_date()
compute_plan.update_status()
return ApiResponse(data, status=status.HTTP_200_OK)

Expand Down
1 change: 1 addition & 0 deletions changes/998.changed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Compute plans now starts when first compute task status transition to building instead of executing.

0 comments on commit 71dc1f2

Please sign in to comment.