Add a cooldown between rounds (ROUND_COOLDOWN_SECONDS)

open_new_round_if_needed now withholds opening the next round until
ROUND_COOLDOWN_SECONDS (default 30) have passed since the previous
round's closed_at, returning None in that window instead of a Round.
Without this, the next round opened within one scheduler tick (~5s) of
the previous payout confirming — not enough time for a player to
notice the round they were in actually resolved.

Callers updated: the scheduler treats None as "nothing to do this
tick", and place_bet raises a "try again shortly" BetError instead of
crashing on a None round.

Not in the original flowchart — a deliberate UX addition on top of it,
documented as such in CLAUDE.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 11:29:59 +02:00
co-authored by Claude Sonnet 5
parent abb3418669
commit f21ecbd4ee
8 changed files with 51 additions and 7 deletions
+24
View File
@@ -1,6 +1,9 @@
from datetime import datetime, timedelta, timezone
import pytest
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from app.config import settings
from app.db.base import Base
from app.db.models import Round
from app.rounds.service import get_active_round, open_new_round_if_needed
@@ -56,3 +59,24 @@ async def test_opens_new_round_after_previous_is_closed(session_factory):
async with session_factory() as session:
round_ = await open_new_round_if_needed(session)
assert round_.status == "open"
async def test_withholds_new_round_during_cooldown(session_factory):
async with session_factory() as session:
session.add(Round(status="closed", closed_at=datetime.now(timezone.utc)))
await session.commit()
async with session_factory() as session:
round_ = await open_new_round_if_needed(session)
assert round_ is None
async def test_opens_new_round_once_cooldown_elapses(session_factory):
stale_close = datetime.now(timezone.utc) - timedelta(seconds=settings.round_cooldown_seconds + 1)
async with session_factory() as session:
session.add(Round(status="closed", closed_at=stale_close))
await session.commit()
async with session_factory() as session:
round_ = await open_new_round_if_needed(session)
assert round_.status == "open"