fix(seer): Deduplicate night shift cron runs#120609
Conversation
Make cron-triggered runs idempotent per organization, workflow configuration, and schedule window so task redelivery cannot repeat triage work. Manual runs remain independent. Refs AIML-3137
|
This PR has a migration; here is the generated SQL for for --
-- Add field schedule_id to seernightshiftrun
--
ALTER TABLE "seer_nightshiftrun" ADD COLUMN "schedule_id" varchar(256) NULL;
--
-- Add field date_completed to seernightshiftrun
--
ALTER TABLE "seer_nightshiftrun" ADD COLUMN "date_completed" timestamp with time zone NULL;
--
-- Create constraint seer_nightshiftrun_unique_org_config_schedule on model seernightshiftrun
--
CREATE UNIQUE INDEX CONCURRENTLY "seer_nightshiftrun_unique_org_config_schedule" ON "seer_nightshiftrun" ("organization_id", "workflow_config_id", "schedule_id") WHERE "schedule_id" IS NOT NULL; |
Use the standard bounded text capacity while documenting the current cron-derived schedule window format.
Persist shard plans before dispatching feature runs so redelivered schedule tasks resume only missing shards without repeating existing work.
Leave quota, eligibility, access, and shard dispatch failures resumable, and clear recovered errors when a run completes.
Refetch state after recovery so backend typing does not retain stale nullability assumptions.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f73d70b. Configure here.
|
|
||
| if not eligible: | ||
| logger.info("night_shift.no_eligible_projects", extra=log_extra) | ||
| _complete_run(run) |
There was a problem hiding this comment.
Stale extras clobber completed runs
Medium Severity
Deduped cron redelivery can run concurrent workers on the same SeerNightShiftRun. Those workers still do unlocked read-modify-write run.update(extras=...) for num_eligible_projects / num_candidates from a stale in-memory extras snapshot. If another worker finishes first and _complete_run clears error_message and sets date_completed, a later stale extras write can put error_message back. A crash before that worker’s own _complete_run leaves a completed window permanently showing an error, because later redeliveries no-op on date_completed.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit f73d70b. Configure here.
| run, created = SeerNightShiftRun.objects.get_or_create( | ||
| organization=organization, | ||
| workflow_config=workflow_config, | ||
| schedule_id=schedule_id, | ||
| defaults={"extras": extras}, | ||
| ) |
There was a problem hiding this comment.
get_or_create on partial unique constraint without IntegrityError handling
Concurrent cron redeliveries for the same (organization, workflow_config, schedule_id) can race inside get_or_create and raise IntegrityError, crashing the task. Wrap the call in try/except IntegrityError and fall back to fetching the existing row, or switch to an insert-or-fetch pattern.
Evidence
run_night_shift_for_orgis an@instrumented_taskwithprocessing_deadline_duration=5 * 60; cron-beat redelivery can enqueue duplicate tasks for the same window.- The PR description explicitly calls out "Cron-task redelivery could recreate and execute Night Shift runs for organizations already covered by the same scheduler window."
- The changed code uses
SeerNightShiftRun.objects.get_or_create(organization=organization, workflow_config=workflow_config, schedule_id=schedule_id)whenschedule_idis not None. - Both the migration (
0030_add_night_shift_run_schedule_id.py) and the model (SeerNightShiftRun.Meta) enforce a partial unique constraint on(organization, workflow_config, schedule_id)whereschedule_id__isnull=False. - Django’s
get_or_createis not atomic across concurrent transactions for the same unique fields; both callers can miss the.get(), then both.create(), causingIntegrityErroron the second insert. - The code does not catch
IntegrityErroraround theget_or_create, so the task will crash and likely be retried, matching the production pattern of concurrentget_or_createraces documented in the database-integrity reference.
Identified by Warden · sentry-backend-bugs · VYP-T3V


Cron-task redelivery could recreate and execute Night Shift runs for organizations already covered by the same scheduler window. Cron dispatches now carry an identifier derived from the deployed beat crontab; a partial unique constraint creates one durable run per
(organization, workflow configuration, schedule window).Each run persists its complete shard plan before creating feature runs. Redelivery resumes only planned shards that have not yet been linked to a
SeerRun, while completed windows no-op; this prevents both gaps after interruption and duplicate feature-run dispatches. The new nullable fields leave manual and historical runs unchanged, so no backfill is required. Refs AIML-3137.