diff --git a/src/sentry/taskworker/scheduler/schedules.py b/src/sentry/taskworker/scheduler/schedules.py index 145dce689faa5f..62c5d37aa430c6 100644 --- a/src/sentry/taskworker/scheduler/schedules.py +++ b/src/sentry/taskworker/scheduler/schedules.py @@ -124,7 +124,7 @@ def monitor_value(self) -> str: def is_due(self, last_run: datetime | None = None) -> bool: """Check if the schedule is due to run again based on last_run.""" if last_run is None: - return True + last_run = timezone.now() - timedelta(minutes=1) remaining = self.remaining_seconds(last_run) return remaining <= 0 @@ -135,7 +135,7 @@ def remaining_seconds(self, last_run: datetime | None = None) -> int: Use the current time to find the next schedule time """ if last_run is None: - return 0 + last_run = timezone.now() - timedelta(minutes=1) # This could result in missed beats, or increased load on redis. last_run = last_run.replace(second=0, microsecond=0) diff --git a/tests/sentry/taskworker/scheduler/test_runner.py b/tests/sentry/taskworker/scheduler/test_runner.py index 5358e4b131524f..499b5f4d46b373 100644 --- a/tests/sentry/taskworker/scheduler/test_runner.py +++ b/tests/sentry/taskworker/scheduler/test_runner.py @@ -377,7 +377,7 @@ def test_schedulerunner_tick_fast_and_slow( assert sleep_time == 30 called = extract_sent_tasks(mock_send) - assert called == ["second", "valid"] + assert called == ["valid"] run_storage.delete("test:valid") with freeze_time("2025-01-24 14:25:30"): @@ -385,34 +385,32 @@ def test_schedulerunner_tick_fast_and_slow( assert sleep_time == 30 called = extract_sent_tasks(mock_send) - assert called == ["second", "valid", "valid"] + assert called == ["valid", "valid"] run_storage.delete("test:valid") - run_storage.delete("test:second") - with freeze_time("2025-01-24 14:26:01"): + with freeze_time("2025-01-24 14:26:00"): sleep_time = schedule_set.tick() assert sleep_time == 30 called = extract_sent_tasks(mock_send) - assert called == ["second", "valid", "valid", "second", "valid"] + assert called == ["valid", "valid", "second", "valid"] run_storage.delete("test:valid") - with freeze_time("2025-01-24 14:26:31"): + with freeze_time("2025-01-24 14:26:30"): sleep_time = schedule_set.tick() assert sleep_time == 30 called = extract_sent_tasks(mock_send) - assert called == ["second", "valid", "valid", "second", "valid", "valid"] + assert called == ["valid", "valid", "second", "valid", "valid"] run_storage.delete("test:valid") - with freeze_time("2025-01-24 14:27:01"): + with freeze_time("2025-01-24 14:27:00"): sleep_time = schedule_set.tick() assert sleep_time == 30 assert run_storage.read("test:valid") called = extract_sent_tasks(mock_send) assert called == [ - "second", "valid", "valid", "second", diff --git a/tests/sentry/taskworker/scheduler/test_schedules.py b/tests/sentry/taskworker/scheduler/test_schedules.py index 3e517a0d62ba67..2540be9a90590f 100644 --- a/tests/sentry/taskworker/scheduler/test_schedules.py +++ b/tests/sentry/taskworker/scheduler/test_schedules.py @@ -80,6 +80,12 @@ def test_crontabschedule_invalid() -> None: def test_crontabschedule_is_due() -> None: schedule = CrontabSchedule("test", crontab(minute="*/5")) + # no last_run and not time to spawn + with freeze_time("2025-01-24 14:23:00"): + now = timezone.now() + assert not schedule.is_due(None) + assert not schedule.is_due(now) + with freeze_time("2025-01-24 14:25:00"): now = timezone.now() assert schedule.is_due(None) @@ -109,7 +115,15 @@ def test_crontabschedule_is_due() -> None: def test_crontabschedule_remaining_seconds() -> None: schedule = CrontabSchedule("test", crontab(minute="*/5")) - assert schedule.remaining_seconds(None) == 0 + # no last_run, but due in one minute + with freeze_time("2025-01-24 14:24:00"): + assert not schedule.is_due(None) + assert schedule.remaining_seconds(None) == 60 + + # no last_run, but due now + with freeze_time("2025-01-24 14:25:00"): + assert schedule.is_due(None) + assert schedule.remaining_seconds(None) == 0 # last run was late (14:21), next spawn is at 14:25 with freeze_time("2025-01-24 14:25:00"):