Dual device on weekend feature

This commit is contained in:
2026-07-12 18:34:28 -04:00
parent 9e100d60d0
commit 31caa13c3d
6 changed files with 214 additions and 39 deletions
+33 -4
View File
@@ -2,8 +2,8 @@ from __future__ import annotations
import os
from dataclasses import dataclass
from datetime import date
from test_window import get_shift_sequence_with_capacity, next_window_start_date
from datetime import date, timedelta
from test_window import get_shift_sequence_with_capacity, is_off_day, next_window_start_date
from test_bundle import Test, TestBundle, build_test_bundles, bundle_pair_lookup
DUT = (os.getenv("DUT") or "DUT").strip()
@@ -36,6 +36,8 @@ class Scheduler:
start_date: str | None = None,
holiday_dates: set[str] = set(),
daytime_testing_today: bool = False,
dual_device_weekend_start_enabled: bool = False,
dual_device_window_start_dates: set[str] | None = None,
priority_weight: int = 100,
):
self.top_priority_tests = top_priority_tests
@@ -45,6 +47,8 @@ class Scheduler:
self.start_date = date.fromisoformat(start_date) if start_date else date.today()
self.holiday_dates = holiday_dates
self.daytime_testing_today = daytime_testing_today
self.dual_device_weekend_start_enabled = dual_device_weekend_start_enabled
self.dual_device_window_start_dates = dual_device_window_start_dates or set()
self.priority_weight = priority_weight
self.pending_dut_mirror: list[TestBundle] = []
self.pending_ref_mirror: list[TestBundle] = []
@@ -102,6 +106,10 @@ class Scheduler:
active_unscheduled = dut_unscheduled if window_device == DUT else ref_unscheduled
shifts, capacity = get_shift_sequence_with_capacity(cursor_date, self.holiday_dates, self.daytime_testing_today)
cursor_date_key = cursor_date.isoformat()
dual_device_window = cursor_date_key in self.dual_device_window_start_dates
if not dual_device_window and self.dual_device_weekend_start_enabled:
dual_device_window = self._is_weekend_start_day(cursor_date)
# Evaluate both devices without mutating queue state, then commit once.
mirrored_bundles, knapsack_bundles, remaining_time = self._select_bundles(
@@ -114,6 +122,7 @@ class Scheduler:
selected_bundles = mirrored_bundles + knapsack_bundles
if len(selected_bundles) == 0:
window_device = REF if window_device == DUT else DUT
active_unscheduled = dut_unscheduled if window_device == DUT else ref_unscheduled
mirrored_bundles, knapsack_bundles, remaining_time = self._select_bundles(
window_device,
capacity,
@@ -125,6 +134,20 @@ class Scheduler:
if len(selected_bundles) == 0:
break
primary_device = window_device
if dual_device_window and remaining_time > 0:
secondary_device = REF if primary_device == DUT else DUT
secondary_unscheduled = dut_unscheduled if secondary_device == DUT else ref_unscheduled
secondary_mirrored, secondary_knapsack, remaining_time = self._select_bundles(
secondary_device,
remaining_time,
secondary_unscheduled,
tc,
mutate=True,
)
selected_bundles.extend(secondary_mirrored + secondary_knapsack)
# Create a mirror of the other device for the next window
bundle_pairs = bundle_pair_lookup(knapsack_bundles, dut_unscheduled, ref_unscheduled)
@@ -134,9 +157,10 @@ class Scheduler:
pending_target = self.pending_dut_mirror
existing_pending = {(b.index, b.device) for b in pending_target}
selected_bundle_keys = {(b.index, b.device) for b in selected_bundles}
for pair_bundle in bundle_pairs:
pair_key = (pair_bundle.index, pair_bundle.device)
if pair_key in self.scheduled_bundle_keys or pair_key in existing_pending:
if pair_key in self.scheduled_bundle_keys or pair_key in existing_pending or pair_key in selected_bundle_keys:
continue
pending_target.append(pair_bundle)
existing_pending.add(pair_key)
@@ -148,7 +172,7 @@ class Scheduler:
capacity_minutes=capacity,
remaining_minutes=remaining_time,
assigned_config=tc,
assigned_device=window_device,
assigned_device=primary_device,
)
self._place_bundles_in_window(window, selected_bundles)
@@ -170,6 +194,11 @@ class Scheduler:
return None
def _is_weekend_start_day(self, current_date: date) -> bool:
if is_off_day(current_date, self.holiday_dates):
return False
return is_off_day(current_date + timedelta(days=1), self.holiday_dates)
def _select_bundles(
self,
device: str,