Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: cp duration starts with build #998

Merged
merged 4 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
Loading