Skip to content
ronitgupta138Public

Latest commit

Β 

History

76 Commits

Folders and files

Repository files navigation

β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—    β–ˆβ–ˆβ•—     β–ˆβ–ˆβ•—   β–ˆβ–ˆβ•—β–ˆβ–ˆβ•—  β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β•    β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•”β•β•β•β•β•
β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—      β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  
β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•      β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•”β•β•β•  
β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—    β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
β•šβ•β•β•β•β•β• β•šβ•β•β•šβ•β•  β•šβ•β•β•β•β•šβ•β•β•β•β•β•β•    β•šβ•β•β•β•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β•  β•šβ•β•β•šβ•β•β•β•β•β•β•

Dine Luxe β€” Full-Stack Restaurant Operating System & Real-Time Booking Platform

With Redis Distributed Mutex Locking & PostgreSQL Concurrency Defense

GitHub Stars Node.js Express.js Next.js TypeScript PostgreSQL Redis Tailwind CSS CI Production App Live Backend License: MIT


πŸ“Œ Architectural Highlights

  • Distributed Mutex Concurrency Protection: High-velocity table reservation endpoints are guarded by Redis distributed key locks (SET lock:table:{id}:{slot} token NX EX 10) paired with atomic Lua scripts, eliminating race-condition double-bookings during peak dining rushes.
  • Dual-Tier Concurrency Defense: Enforces PostgreSQL row-level locks (SELECT FOR UPDATE) and composite unique constraints on (table_id, time_slot) to guarantee zero double-allocations even during cache failover or network partitions.
  • Full-Stack Monorepo Architecture: Clean separation of concerns across Express.js backend services, shared TypeScript domain types, and a Next.js 14 App Router customer portal and staff Kitchen Display System (KDS).
  • 25 Production Business Modules: Complete lifecycle coverage including bookings, tables, floor-layout, kitchen, orders, menu, inventory, delivery, payments, analytics, and staff.
  • Resilient Cache Failover: Custom ResilientRedis client featuring automatic in-memory fallback stores to guarantee zero API process crashes during transient network disconnects or Redis maintenance.
  • Zod-Powered Schema Validation: Strict payload sanitation and type safety on all reservation times, party sizes (1–20), item selections, and status transitions before touching persistence layers.

πŸ›οΈ System Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        CLIENT / USER PORTALS                           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ Customer Web & POS UI β”‚              β”‚ Kitchen Display / Waiters β”‚  β”‚
β”‚  β”‚   (Next.js 14 App)    β”‚              β”‚   (Real-Time Order View)  β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚ HTTP / JSON API                        β”‚
               β–Ό                                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   DINE LUXE REST API GATEWAY (Express)                 β”‚
β”‚                                                                        β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚   Auth & RBAC      β”‚   β”‚ Payload Validation β”‚   β”‚ Rate Limiter β”‚   β”‚
β”‚   β”‚ (JWT / Bearer)     β”‚   β”‚     (Zod / CJS)    β”‚   β”‚ (Redis-backedβ”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚             β”‚                        β”‚                     β”‚           β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚                        BUSINESS CONTROLLERS                    β”‚   β”‚
β”‚   β”‚  β€’ Bookings / Table Allocator   β€’ Orders & KDS Dispatcher      β”‚   β”‚
β”‚   β”‚  β€’ Menu & Dynamic Pricing       β€’ Inventory & Stock Depletion  β”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚                                              β”‚
              β–Ό [SET NX EX 10 / Lua Release]                 β–Ό [SQL / Prisma]
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     REDIS DISTRIBUTED LOCK    β”‚              β”‚  POSTGRESQL 16 DATABASE β”‚
β”‚   β€’ Mutex key per table/slot  β”‚              β”‚  β€’ Row-lock FOR UPDATE  β”‚
β”‚   β€’ Sorted-set reminders      β”‚              β”‚  β€’ Relational integrity β”‚
β”‚   β€’ In-memory safe fallback   β”‚              β”‚  β€’ B-Tree index lookups β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”’ Concurrency & Double-Booking Prevention

During peak reservation windows (e.g., Valentine's Day or Friday evening dining), simultaneous requests for the same table at the identical time slot must never result in an overbooked table.

1. Redis Mutual Exclusion (SET NX EX)

Before executing any database write, the service attempts to acquire an exclusive lock:

const lockKey = `lock:table:${tableId}:${slot}`;
const lockAcquired = await redis.set(lockKey, token, 'PX', 10000, 'NX');

if (!lockAcquired) {
  throw { statusCode: 409, message: 'Table is currently being reserved by another guest' };
}

2. Atomic Lua Unlock Script

Releasing the lock requires cryptographic token verification to prevent a slow transaction from accidentally deleting a lock re-acquired by another client:

if redis.call("get", KEYS[1]) == ARGV[1] then
    return redis.call("del", KEYS[1])
else
    return 0
end

3. Database Pessimistic Row Lock (SELECT FOR UPDATE)

SELECT id, status, capacity 
FROM tables 
WHERE id = p_table_id 
FOR UPDATE;

πŸ—„οΈ Relational Data Model (PostgreSQL)

The system is normalized across 8 core relational entities:

Table Primary Key Key Foreign Keys & Indexes Description
users id (UUID) email (UNIQUE) Customer and staff profiles with hashed credentials
tables id (UUID) branch_id, status, capacity Floor tables with seating capacity and physical status
menu_items id (UUID) category_id, is_available Menu catalog with item descriptions and pricing
orders id (UUID) table_id, user_id, status Active dining orders and payment totals
order_items id (UUID) order_id, menu_item_id Individual order line items with customization notes
reservations id (UUID) (table_id, time_slot) UNIQUE, user_id Booked dining slots with state tracking
payments id (UUID) order_id, transaction_ref Payment records, payment method, and receipts
audit_logs id (UUID) user_id, action, created_at Immutable security audit trail of staff actions

πŸš€ REST API Reference

Reservations (/api/reservations)

  • POST /api/reservations β€” Create a table booking (guarded by Redis distributed lock).
  • GET /api/reservations β€” List reservations with pagination and status filters.
  • GET /api/reservations/:id β€” Retrieve reservation status and assigned table details.
  • DELETE /api/reservations/:id β€” Cancel a confirmed booking and release the table.

Orders & Kitchen (/api/orders)

  • POST /api/orders β€” Create a customer order for an occupied table.
  • GET /api/orders/:id β€” Get full order receipt and kitchen preparation progress.
  • PATCH /api/orders/:id/status β€” Advance KDS workflow (PENDING βž” PREPARING βž” READY βž” SERVED).

Menu & Catalog (/api/menu)

  • GET /api/menu β€” Retrieve full menu items filtered by category and dietary flags.
  • POST /api/menu β€” Add a new menu item (admin / manager only).

πŸ§ͺ Automated Testing

Dine Luxe includes automated unit and integration tests covering reservation locking, schema validation, conflicting slot detection, and status workflows:

# Run the test suite
npm test

Test Execution Output:

β–Ά Dine Luxe API Test Suite
  βœ” 1. Valid reservation creation succeeds with 201 Created (18.3ms)
  βœ” 2. Reservation with invalid party size returns 400 Bad Request (2.8ms)
  βœ” 3. Reservation with missing customerName returns 400 Bad Request (2.6ms)
  βœ” 4. Duplicate reservation for identical table and timeSlot returns 409 Conflict (3.4ms)
  βœ” 5. Redis Lock: client cannot release lock owned by different token (0.5ms)
  βœ” 6. Reservation cancellation updates status to CANCELLED (3.5ms)
  βœ” 7. Menu listing and category filtering works (3.7ms)
  βœ” 8. Order creation and Kitchen Display status updates succeed (3.4ms)
βœ” Dine Luxe API Test Suite (42.3ms)
β„Ή tests 9
β„Ή suites 0
β„Ή pass 9
β„Ή fail 0

⚑ Quickstart & Local Setup

Prerequisites

  • Node.js: v18.0.0 or higher
  • pnpm or npm
  • PostgreSQL 16 (or Supabase project)
  • Redis (optional; in-memory fallback enabled automatically if offline)

1. Clone & Install

git clone https://github.com/ronitgupta138/dine-luxe.git
cd dine-luxe
pnpm install # or npm install

2. Configure Environment

cp .env.example .env
cp backend/.env.example backend/.env

3. Run Development Servers

# Start backend and frontend simultaneously via Turborepo
npm run dev

# Or run tests
npm test

🌐 Live Production Deployment

  • πŸš€ Frontend Web Application (Vercel):
    πŸ‘‰ https://dine-luxe.vercel.app β€” Production restaurant operating system featuring customer table reservation, staff kitchen display system (KDS), cashier billing, and floor maps.
  • ⚑ Backend REST API (Render):
    πŸ‘‰ https://dineluxe-backend.onrender.com/health β€” High-throughput Node.js/Express REST API connected to managed PostgreSQL 16 (dineluxe_db).

βš–οΈ License

Distributed under the MIT License. See LICENSE for full details.


Crafted with precision by Ronit Gupta
Computer Science & Business Systems Undergraduate β€’ SDE-1 / Backend Engineer

Releases

Sponsor this project

Packages

Contributors

Languages