A concurrency-safe seat allocation and booking engine
Project description
Seat Allocation Engine – Working Cycle
This document explains how the Seat Allocation Engine works internally, step by step. It focuses on the lifecycle of a seat, locking rules, bulk operations, and cleanup mechanics. No UI, API, or framework concepts are involved here—this is purely the domain engine.
1. Core Purpose
The engine is designed to solve one problem correctly:
Allocate seats to users in a safe, fair, and deterministic way.
It guarantees:
- No double booking
- No permanent locks
- No partial group bookings
- No lock stealing
2. Core Concepts
2.1 Seat as a Resource
Each seat is treated as an independent resource.
A seat has exactly one of three states:
AVAILABLELOCKEDBOOKED
Once a seat is BOOKED, it is terminal and cannot change state.
2.2 Seat Ownership
When a seat is locked:
- It is owned by exactly one user
- Only that user can book it
- Other users are rejected
Ownership is enforced strictly at all times.
3. Seat Lifecycle
The lifecycle of a seat follows this strict state machine:
AVAILABLE → LOCKED → BOOKED
↑ |
└────────┘ (lock expiry)
Invalid transitions are never allowed.
4. Locking Mechanism
4.1 Single Seat Locking
When a user requests to lock a seat:
- The engine checks if the seat exists
- If the seat is
BOOKED→ reject - If the seat is
LOCKED→ reject - If the seat is
AVAILABLE→ lock it
A successful lock records:
locked_by(user id)lock_time(timestamp)
4.2 Bulk Seat Locking (Group Selection)
Bulk locking is atomic.
This means:
Either all seats are locked, or none are.
Working cycle:
Phase 1 – Validation (read-only)
- All seats must exist
- All seats must be
AVAILABLE - If any seat fails → abort immediately
Phase 2 – Commit (write)
- All seats are locked together
- Same user
- Same lock timestamp
No partial locking is ever possible.
5. Booking Mechanism
5.1 Single Seat Booking
To book a seat:
- Seat must exist
- Seat must be
LOCKED - Seat must be locked by the same user
If all checks pass:
- Seat transitions to
BOOKED - Lock metadata is cleared
5.2 Bulk Seat Booking
Bulk booking follows the same atomic principle as bulk locking.
Validation phase:
- All seats must exist
- All seats must be
LOCKED - All seats must be locked by the same user
Commit phase:
- All seats transition to
BOOKED
If any seat fails validation → no seat is booked.
6. Lock Expiry (Auto Release)
Locks are temporary by design.
6.1 Timeout Rule
- Each lock has a maximum lifetime (
LOCK_TIMEOUT) - Default: 10 seconds
6.2 Cleanup Mechanism
Lock expiry is handled by a system-level cleanup function:
cleanup_expired_locks()
This function:
- Iterates over all seats
- Releases locks that exceeded the timeout
- Never depends on user actions
Important rule:
A lock may expire, but it is never stolen by another user.
7. Concurrency Safety
All operations run inside a global lock.
This guarantees:
- Atomic operations
- No race conditions
- Deterministic behavior
The engine prioritizes correctness over performance.
8. Separation of Responsibilities
| Layer | Responsibility |
|---|---|
| Seat | State + truth checks |
| SeatManager | Transitions + rules |
| Cleanup | Time-based expiry |
| UI / API | Input & presentation only |
The engine does not know about:
- Clicks
- HTTP
- UI state
- Databases
9. What This Engine Guarantees
✔ No double booking ✔ No permanent locks ✔ No partial group bookings ✔ Strong ownership enforcement ✔ Deterministic outcomes
10. What This Engine Intentionally Does NOT Do
- No UI rendering
- No HTTP / REST handling
- No persistence
- No background threads
These are integration concerns and belong outside the engine.
11. Intended Usage
This engine is designed to be:
- Packaged as a reusable library
- Called from event-driven systems
- Used under web, desktop, or CLI interfaces
The engine remains unchanged while integrations evolve.
12. Final Note
This is a domain-correct seat allocation engine.
All future work (UI, APIs, persistence, scaling) should be built on top of this logic, not mixed into it.
This separation is intentional and fundamental.
Public API Reference
This section lists all public methods exposed by the SeatLock engine, with a one-line explanation of what each does. These are the only methods consumers should rely on.
Importing the Engine
from seatlock import Seat, SeatManager
Core Classes
Seat
Represents a single seat as an independent resource.
Seat(seat_id)→ Create a new seat with a unique identifieris_available()→ ReturnsTrueif the seat is freeis_locked()→ ReturnsTrueif the seat is temporarily reservedis_booked()→ ReturnsTrueif the seat is permanently booked
SeatManager
Central engine that enforces all locking, booking, cancellation, and cleanup rules.
Locking Methods
-
lock_seat(seat_id, user_id)
Locks a single available seat for a user -
lock_seats_bulk(seat_ids, user_id)
Atomically locks multiple seats for a user (all-or-nothing)
Booking Methods
-
book_a_seat(seat_id, user_id)
Permanently books a single seat previously locked by the same user -
book_seats_bulk(seat_ids, user_id)
Atomically books multiple seats previously locked by the same user
Cancellation Methods
-
cancel_lock(seat_id, user_id)
Releases a lock held by the user on a single seat -
cancel_locks_bulk(seat_ids, user_id)
Atomically releases locks held by the user on multiple seats
Cleanup / System Methods
cleanup_expired_locks()
System-level method that releases all locks exceeding the configured timeout
Code Example
#Base Case
from seatlock import SeatManager, Seat
# Create seats
seats = [Seat(i) for i in range(1, 6)]
# Initialize manager with custom timeout (in seconds)
manager = SeatManager(seats, lock_timeout=60)
# Lock a seat
print(manager.lock_seat(1, "user1"))
# Book the seat
print(manager.book_a_seat(1, "user1"))
#Bulk Use Case
from seatlock import SeatManager, Seat
seats = [Seat(i) for i in range(1, 6)]
manager = SeatManager(seats, lock_timeout=120)
# Lock multiple seats
print(manager.lock_seats_bulk([2, 3], "user2"))
# Book them
print(manager.book_seats_bulk([2, 3], "user2"))
#Handling Conflicts
# Another user tries to book without lock
print(manager.book_a_seat(4, "user3"))
# → Seat 4 is not locked
# Lock by one user
manager.lock_seat(4, "user1")
# Another user tries to lock same seat
print(manager.lock_seat(4, "user2"))
# → Seat 4 is currently locked by user1
Update
In seatock v0.2.0, a new parameter has been added called lock_timeout. You can now provide the time out for a lock. This timeout will have base unit in seconds.
Previous Version
In seatlock v0.1.0, lock_timeout was present but was set to 10 during developement and was constant and hence was creating a problem. The bug is now fixed with proper parameter availibility.
Notes on Usage
- All methods are thread-safe
- All bulk operations are atomic
- Only the lock owner may book or cancel seats
- Booked seats are final and immutable
- Time-based lock expiry is handled only by
cleanup_expired_locks
This API is intentionally minimal and stable. All UI, event handling, persistence, and networking should be built on top of these methods, not mixe
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file seatlock-0.2.0.tar.gz.
File metadata
- Download URL: seatlock-0.2.0.tar.gz
- Upload date:
- Size: 6.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6611abf0f396e6cf041f650bc132844d650a5fca6f26add370e4d9b5cbbf291c
|
|
| MD5 |
f0ed8b0530e9bec9def3eae1d1babcb0
|
|
| BLAKE2b-256 |
d5a066b136cb6c9abf3861c142a6223581f3999df101db3ad5777ee3772f9d57
|
File details
Details for the file seatlock-0.2.0-py3-none-any.whl.
File metadata
- Download URL: seatlock-0.2.0-py3-none-any.whl
- Upload date:
- Size: 7.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc5c2728164940128a19771b007936ccd780bb983baa338b18fc0e469741f1cc
|
|
| MD5 |
ce83eb9ef24976f656090096e8c0c0c3
|
|
| BLAKE2b-256 |
c191089160e5bbfc720d2d2b3114414b2c743966b14f72afe42ac41c2b41eb49
|