Rule 3 locks the odds on a week added after its own Wednesday #435

Closed
opened 2026-08-31 16:42:53 +02:00 by johnsturgeon · 1 comment
Owner

Dispatcher rule 3 flips odds_state PRELIMINARY -> LOCKED as soon as week.utc_lock_odds_at is in the past, and it is evaluated before rule 4 (fetch odds).

So a week first inserted after its own Wednesday 6am Pacific locks immediately and never fetches odds. Every game keeps the insert defaults: home favored, spread 0.0.

Normally fetch_new_week_if_exists adds a week days ahead of the lock instant, so this does not bite. It bites on a cold start against an empty week table -- which is exactly what a rebuilt production database is.

Bites: first boot on a fresh database mid-week, or any week added late.

Confirmed in production, 2026-08-31

The rebuild-and-deploy landed mid-preseason-week-4:

 week_no | season_type | game_state | odds_state
---------+-------------+------------+------------
       4 |           1 | PREGAME    | LOCKED

 with_spread | total
-------------+-------
           0 |    16

update_odds_current_week has no jobstate row at all -- it has never run. Harmless here (preseason, nobody picks), and it should self-correct for regular-season week 1, which gets created days before its Wednesday.

Note that flipping the week back to PRELIMINARY does not help: rule 3 re-locks it on the next tick before rule 4 is ever reached.

Second half: the write barrier is only in the dispatcher

update_odds_current_week does not check odds_state itself -- rule 4's guard is the only thing preventing a locked week's spreads from being overwritten. Anything that invokes the job directly (an admin button, a manual run, a future caller) bypasses the barrier entirely.

The guard belongs in the job as well as the rule.

Dispatcher rule 3 flips `odds_state` PRELIMINARY -> LOCKED as soon as `week.utc_lock_odds_at` is in the past, and it is evaluated before rule 4 (fetch odds). So a week first inserted *after* its own Wednesday 6am Pacific locks immediately and never fetches odds. Every game keeps the insert defaults: home favored, spread 0.0. Normally `fetch_new_week_if_exists` adds a week days ahead of the lock instant, so this does not bite. It bites on a cold start against an empty `week` table -- which is exactly what a rebuilt production database is. **Bites:** first boot on a fresh database mid-week, or any week added late. ## Confirmed in production, 2026-08-31 The rebuild-and-deploy landed mid-preseason-week-4: ``` week_no | season_type | game_state | odds_state ---------+-------------+------------+------------ 4 | 1 | PREGAME | LOCKED with_spread | total -------------+------- 0 | 16 ``` `update_odds_current_week` has no `jobstate` row at all -- it has never run. Harmless here (preseason, nobody picks), and it should self-correct for regular-season week 1, which gets created days before its Wednesday. Note that flipping the week back to PRELIMINARY does not help: rule 3 re-locks it on the next tick before rule 4 is ever reached. ## Second half: the write barrier is only in the dispatcher `update_odds_current_week` does not check `odds_state` itself -- rule 4's guard is the only thing preventing a locked week's spreads from being overwritten. Anything that invokes the job directly (an admin button, a manual run, a future caller) bypasses the barrier entirely. The guard belongs in the job as well as the rule.
Author
Owner

Closing: accepted risk.

The week has to first appear in the database after the Wednesday 6am Pacific
preceding its own first kickoff. That needs either a mid-week database rebuild
or fetch_new_week_if_exists being down from Tuesday through Wednesday
morning. If the week row exists before its Wednesday -- which is every normal
week -- rule 3 stays false for a day or more and rule 4 fetches odds hourly
throughout.

Observed once, on the 2026-08-31 production rebuild, against a preseason week
nobody picks.

Recovery if it ever does happen: the week has no picks yet, so setting
odds_state back to PRELIMINARY by hand is legal (see the OddsState
docstring) and rule 4 picks it up on the next tick.

Closing: accepted risk. The week has to first appear in the database *after* the Wednesday 6am Pacific preceding its own first kickoff. That needs either a mid-week database rebuild or `fetch_new_week_if_exists` being down from Tuesday through Wednesday morning. If the week row exists before its Wednesday -- which is every normal week -- rule 3 stays false for a day or more and rule 4 fetches odds hourly throughout. Observed once, on the 2026-08-31 production rebuild, against a preseason week nobody picks. Recovery if it ever does happen: the week has no picks yet, so setting `odds_state` back to `PRELIMINARY` by hand is legal (see the `OddsState` docstring) and rule 4 picks it up on the next tick.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
johnsturgeon/tgfp-web#435
No description provided.