Make check-then-hold atomic (double-booking race) #4

Closed
opened 2026-07-18 22:19:51 +00:00 by padreug · 1 comment
Owner

crud.is_available() followed by writing the held booking is a critical section. Two concurrent requests for the same nights can both pass the availability read before either writes → double booking. Marked TODO(concurrency) in views_api.py:api_request_booking.

Options

  • Wrap check + insert in a single DB transaction (db.reuse_conn / async with db.connect()), or
  • Take a per-room asyncio.Lock around the section (simpler; single-process only — fine for one castle instance).

Because the availability check counts held as occupying, once one request writes held the loser's re-check fails → 409. The fix only needs to make the read→write atomic.

Acceptance

A test firing two simultaneous requests for identical dates results in exactly one held booking and one 409.

`crud.is_available()` followed by writing the `held` booking is a critical section. Two concurrent requests for the same nights can both pass the availability read before either writes → double booking. Marked `TODO(concurrency)` in `views_api.py:api_request_booking`. ### Options - Wrap check + insert in a single DB transaction (`db.reuse_conn` / `async with db.connect()`), **or** - Take a per-room `asyncio.Lock` around the section (simpler; single-process only — fine for one castle instance). Because the availability check counts `held` as occupying, once one request writes `held` the loser's re-check fails → `409`. The fix only needs to make the read→write atomic. ### Acceptance A test firing two simultaneous requests for identical dates results in exactly one `held` booking and one `409`.
Author
Owner

Shipped in PR #9 (per-room asyncio.Lock around check-then-hold), with a real-DB concurrency regression test in #10 and the migration test in #15; released in catalog v0.1.0. Closing (auto-close phrasing never fired).

Shipped in PR #9 (per-room `asyncio.Lock` around check-then-hold), with a real-DB concurrency regression test in #10 and the migration test in #15; released in catalog v0.1.0. Closing (auto-close phrasing never fired).
Sign in to join this conversation.
No labels
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
aiolabs/chatelet#4
No description provided.