Snapshot a round's timing when it opens (B-61)
round_duration_seconds was read live on every scheduler tick and every bet check, with the deadline computed as opened_at + duration. Lowering it from 600 to 60 while a round was 300s in closed that round instantly; raising it moved the closes_at clients were already counting down to. round_cooldown_seconds had the same property for the gap after a close. B-11 fixed this class of problem for the advertised jackpot; the timing fields were left live. Round now carries duration_seconds and cooldown_seconds, set from the config when it opens. round_deadline() is the single place the deadline is computed — the scheduler, place_bet's two checks and /rounds/current's closes_at all go through it — and the cooldown is read off the round that just closed, so the gap a round announced is the gap that's honoured. The config row becomes what the *next* round opens with. The migration backfills from the live config rather than leaving the column defaults: an instance running 300s rounds would otherwise see the round currently in progress jump to 600s the moment this lands, which is precisely the retroactive change being fixed. Verified against a scratch DB with a non-default config. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -82,6 +82,16 @@ class Round(Base):
|
||||
status: Mapped[str] = mapped_column(String(16), default="open")
|
||||
opened_at: Mapped[datetime] = mapped_column(default=utcnow)
|
||||
closed_at: Mapped[datetime | None] = mapped_column(default=None)
|
||||
# B-61: the round's own timing, snapshotted from RoundConfig when it opens.
|
||||
# Read live from the config, a mid-round edit applied retroactively: lowering
|
||||
# round_duration_seconds from 600 to 60 while a round was 300s in closed it
|
||||
# instantly, and raising it moved the closes_at every client was already
|
||||
# counting down to. Same class of bug B-11 fixed for the advertised jackpot.
|
||||
# The config row is now what the *next* round opens with; these are what this
|
||||
# round runs by. cooldown_seconds is read off the round that just closed, so
|
||||
# the gap it announced is the gap that's honoured.
|
||||
duration_seconds: Mapped[int] = mapped_column(default=600, server_default="600")
|
||||
cooldown_seconds: Mapped[int] = mapped_column(default=30, server_default="30")
|
||||
# Set once, when status flips to "drawing" (rounds/scheduler.py:_close_and_draw).
|
||||
# Lets both the audit log (B-36's draw_stalled entries) and GET /rounds/current
|
||||
# (draw_waiting_since) measure how long a round has been waiting on a block,
|
||||
|
||||
Reference in New Issue
Block a user