A ride-hailing demo that makes distributed computing concepts tangible. The app pairs a modern React frontend with a Python/Flask backend that can run as multiple nodes. The frontend performs client‑side discovery and round‑robin load balancing across available backend instances, while the backend simulates leader election, clock synchronization, load distribution, and durable state.
- Real rider/driver flow with synchronized maps and live driver location
- Start-trip gate: rider movement begins only after driver confirms pickup
- Client-side load balancing across multiple backend nodes (failover-aware)
- Distributed systems demos:
- Leader election (Bully/Ring)
- Clock synchronization (Cristian/Berkeley)
- Load balancing and job assignment
- Data consistency with simple durable storage (SQLite rides DB + driver CSV)
- Mobile-friendly UI for drivers and riders
- Frontend: React, Vite, Tailwind CSS, Framer Motion, lucide-react
- Backend: Python, Flask, Flask-Cors, requests
- Data: SQLite (rides) plus driver CSV lookup + in-memory cache
backend/
app/
routes.py # API endpoints (rides, driver location, start-trip, etc.)
cluster.py # Distributed concepts (election, sync, logging)
storage.py # Persistence helpers (SQLite for rides)
main.py # App entrypoint (reads PORT, HOST, etc.)
requirements.txt
frontend/
src/
pages/ # Rider & driver screens
services/ # API client with node discovery & load balancing
.env # API discovery settings (host/ports)
COMPLETION_SUMMARY.md, TESTING_GUIDE.md, FLOW_DIAGRAM.md, ...
- Python 3.10+ (virtualenv recommended)
- Node.js 18+ and npm 9+
# 1) Create & activate a virtual environment
cd backend
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 2) Install dependencies
pip install -r requirements.txt
# 3) Run a single backend node (default port 5000)
HOST=0.0.0.0 PUBLIC_HOST=127.0.0.1 PORT=5000 NODE_PRIORITY=95 python main.pyBy default rides are persisted to backend/data/rides.db. Override the location by setting RIDE_DB_PATH=/absolute/path/to/rides.db before starting the server.
Run multiple nodes to showcase client-side load balancing:
# Terminal 1
cd backend && source .venv/bin/activate
HOST=0.0.0.0 PUBLIC_HOST=127.0.0.1 PORT=5000 NODE_PRIORITY=95 python main.py
# Terminal 2
cd backend && source .venv/bin/activate
HOST=0.0.0.0 PUBLIC_HOST=127.0.0.1 PORT=5001 NODE_PRIORITY=92 python main.py
# Terminal 3
cd backend && source .venv/bin/activate
HOST=0.0.0.0 PUBLIC_HOST=127.0.0.1 PORT=5002 NODE_PRIORITY=88 python main.py- HOST: Bind address
- PUBLIC_HOST: The host the frontend uses to reach APIs (typically 127.0.0.1)
- PORT: Unique port per node
- NODE_PRIORITY: Used by election algorithms
cd frontend
npm install
# Ensure API discovery vars (defaults included in .env)
# VITE_API_PROTOCOL=http
# VITE_API_HOST=localhost
# VITE_API_PORT_RANGE=5000-5003
npm run devThe frontend service will probe the port range, pick a healthy backend, and rotate across nodes for subsequent calls. If a node dies, requests automatically fail over to a surviving node.
- Book ride (rider) → driver accepts → driver navigates to pickup → driver presses “Start Trip” → both maps show route to destination → completion → rating modal.
- Driver map pushes location updates to backend; rider map shows the same location in real time.
- Load balancing: Start backends on ports 5000–5002. Observe calls rotating across nodes (DevTools network tab and console logs in
frontend/src/services/rideService.js). - Leader election & clock sync: Trigger from backend (see logs produced by
cluster.pywhen routes initialize or when you run cluster operations in code paths). - Data consistency: Rides state is cached in-memory and periodically persisted to SQLite; nodes can recover state. Driver metadata is loaded from CSV.
- CORS/Network: Ensure PUBLIC_HOST points to a hostname reachable from the browser (often 127.0.0.1).
- Port conflicts: Adjust
VITE_API_PORT_RANGEor backend PORTs if already in use. - Maps/route: Requires internet to fetch route geometry.
A helper script may exist at the repo root (test_integration.sh) to run an end‑to‑end flow; check it for current flags and usage.
For demo/educational use. Adjust and extend freely.