File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 2020
2121router = APIRouter ()
2222
23+ _STALE_GRACE = timedelta (minutes = 5 )
24+
25+
26+ def close_stale_sessions (db : Session ) -> int :
27+ """Close sessions whose paid_until has been exceeded by more than 5 minutes.
28+
29+ Sets end_time = paid_until for each such session. Returns the number closed.
30+ Called from the health endpoint (periodic) and session creation (on demand).
31+ """
32+ cutoff = datetime .now (UTC ).replace (tzinfo = None ) - _STALE_GRACE
33+ stale = (
34+ db .query (MachineSession )
35+ .filter (MachineSession .end_time .is_ (None ), MachineSession .paid_until < cutoff )
36+ .all ()
37+ )
38+ for s in stale :
39+ s .end_time = s .paid_until
40+ if stale :
41+ db .commit ()
42+ return len (stale )
43+
2344
2445def _calc_max_seconds (
2546 balance : Decimal , price_per_minute : Decimal , remaining_seconds : float
@@ -43,6 +64,8 @@ def create_session(
4364 Deducts: price_per_login + price_per_minute * booking_interval
4465 Requires: balance >= that amount
4566 """
67+ close_stale_sessions (db )
68+
4669 # Lock user row for atomic balance check
4770 user = db .execute (
4871 select (User ).where (User .id == body .nfc_id ).with_for_update ()
Original file line number Diff line number Diff line change @@ -15,6 +15,7 @@ class JSONResponse(_JSONResponse):
1515from starlette .middleware .sessions import SessionMiddleware
1616
1717from app .api .v1 .router import api_router
18+ from app .api .v1 .sessions import close_stale_sessions
1819from app .config import settings
1920from app .database import get_db
2021from app .web .router import router as web_router
@@ -85,6 +86,7 @@ def health(db: Session = Depends(get_db)):
8586 """Public health check. Returns 200 when the database is reachable."""
8687 try :
8788 db .execute (text ("SELECT 1" ))
89+ close_stale_sessions (db )
8890 return {"status" : "ok" , "database" : "ok" }
8991 except Exception :
9092 return JSONResponse ({"status" : "error" , "database" : "unreachable" }, status_code = 503 )
You can’t perform that action at this time.
0 commit comments