Skip to main content

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:

  • AVAILABLE
  • LOCKED
  • BOOKED

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:

  1. The engine checks if the seat exists
  2. If the seat is BOOKED → reject
  3. If the seat is LOCKED → reject
  4. 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:

  1. Seat must exist
  2. Seat must be LOCKED
  3. 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 identifier
  • is_available() → Returns True if the seat is free
  • is_locked() → Returns True if the seat is temporarily reserved
  • is_booked() → Returns True if 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

seatlock-0.2.0.tar.gz (6.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

seatlock-0.2.0-py3-none-any.whl (7.0 kB view details)

Uploaded Python 3

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

Hashes for seatlock-0.2.0.tar.gz
Algorithm Hash digest
SHA256 6611abf0f396e6cf041f650bc132844d650a5fca6f26add370e4d9b5cbbf291c
MD5 f0ed8b0530e9bec9def3eae1d1babcb0
BLAKE2b-256 d5a066b136cb6c9abf3861c142a6223581f3999df101db3ad5777ee3772f9d57

See more details on using hashes here.

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

Hashes for seatlock-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dc5c2728164940128a19771b007936ccd780bb983baa338b18fc0e469741f1cc
MD5 ce83eb9ef24976f656090096e8c0c0c3
BLAKE2b-256 c191089160e5bbfc720d2d2b3114414b2c743966b14f72afe42ac41c2b41eb49

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page