The goal is to design a backend service for a hospital OPD that manages doctor slots and token allocation. The core challenge is handling real-world variability such as emergencies, cancellations, and delays, while enforcing capacity limits. The system needs to be elastic (handling overflow) and fair (prioritizing urgent cases).
The solution is built using Java Spring Boot 3.x following a domain-driven, layered architecture. This ensures separation of concerns and testability.
- Language: Java 17+
- Framework: Spring Boot (Web)
- Build Tool: Maven
- Testing: JUnit 5 (Infrastructure ready)
- Data Persistence: In-Memory (ConcurrentHashMap for thread safety in simulation)
- Controller Layer (
com.medoc.opd.controller)- Handles HTTP requests and response mapping.
- Design Choice: Clean RESTful endpoints with proper status codes (200, 404, etc.).
- Service Layer (
com.medoc.opd.service)- Encapsulates business logic (Allocation, Elasticity, Reallocation).
- Design Choice:
AllocationServiceacts as the brain, orchestratingSlotandTokeninteractions.
- Model Layer (
com.medoc.opd.model)- Rich Domain Models (
Doctor,Slot,Token). - Design Choice: Logic for availability and waitlist promotion resides in the Domain models (DDD), preventing anemic models.
- Rich Domain Models (
The system uses a weighted priority score to order the waitlist:
- Emergency (Score: 100): Bypasses waitlist completely. Directly allocated to slot (Elastic Capacity).
- Paid Priority (Score: 50): High priority in waitlist.
- Follow-up (Score: 30): Medium priority.
- Online/Walk-in (Score: 10): Standard priority (First-In-First-Out within their user group).
Waitlists are automatically sorted using Comparable<Token> based on this score.
Detailed specification available in api-docs/api-spec.md
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/doctors |
Create a new doctor and default schedule |
GET |
/api/doctors |
Get all doctors and their slots |
POST |
/api/bookings |
Book a token (Elastic allocation) |
DELETE |
/api/bookings/{docId}/{tokenId} |
Cancel a token |
POST |
/api/doctors/{id}/delay |
Report a delay (shifts schedule) |
- Slot Full: Standard patients are added to a Waitlist.
- Emergency Overflow: Emergency tokens are always accepted, even if optimal capacity is reached (Capacity grows dynamically, e.g., 5 -> 6).
- Cancellation: If a booked patient cancels, the system automatically promotes the highest-priority patient from the waitlist to the allocated set.
- Delay: If a doctor reports a delay, all future slots are time-shifted to maintain the schedule structure.
- VIP Jumping: A high-priority patient added to a full slot will jump ahead of existing standard patients in the waitlist.
The application includes a SimulationRunner that executes on startup to demonstrate functionality without needing manual API calls.
Location: simulation/opd_day_simulation.txt
- Phase 1: Fills a slot with standard patients until waitlist triggers.
- Phase 2: Adds a PAID_PRIORITY patient (verifying they take top waitlist spot) and an EMERGENCY patient (verifying they bypass the limit).
- Phase 3: Cancels a booked patient, verifying that the VIP patient is promoted.
- Phase 4: Simulates a delay, shifting slot timings.
- Slots are Fixed: Slots are generated as 1-hour blocks (9-10, 10-11).
- In-Memory Volatility: Restarting the application resets all data.
- Single Doctor Mapping: Tokens are booked for a specific doctor, not a pool.
- Concurrency: Currently uses in-memory lists. In production, I would use Database Row-Locking (Pessimistic Write) or Redis Distributed Locks to prevent double-booking slots during high concurrency.
- Scalability: The current stateful memory model doesn't scale horizontally. Ideally, state should be externalized to PostgreSQL or Redis.
- Security: No Auth implemented. In production, we'd add OAuth2/JWT via Spring Security.
mvn spring-boot:run