I am trying to build a movie ticket booking application just to practice for interview low level design perspective.
A theater can have multiple screens and each screen as some seats capacity. A show is a movie which will be shown in a screen.
Below are model/entity classes that I have created.
public class Booking {
private final String id;
private final Show show;
private final List<Seat> seatsBooked;
private final String user;
private BookingStatus bookingStatus;
}
public enum BookingStatus {
Created,
Confirmed,
Expired
}
public class Movie {
private final String id;
private final String name;
//Other metadata
}
public class Screen {
private final String id;
private final String name;
private final Theatre theatre;
//Other screen metadata.
private final List<Seat> seats;
}
public class Seat {
private final String id;
private final int rowNo;
private final int seatNo;
}
public class Show {
private final String id;
private final Movie movie;
private final Screen screen;
private final Date startTime;
private final Integer durationInSeconds;
}
public class Theatre {
private final String id;
private final String name;
private final List<Screen> screens;
//Other theatre metadata.
}
Refer link for full code and reference - Movie Ticket Booking App
I have not included the getters, setters and some methods in my classes. Here, when a user searches a movie name in the application, then it will be handled by a ShowController.java and it will show some movie shows present in the theaters to the user. And then if a user select a show for a particular theater screen. Then the user will select some seats as per his choice. Now the problem comes, when one user selects a list of seats then I want to change those seats status to CREATED (enum BookingStatus) and those selected seats must be unavailable to other users. So, how can I mark those seats as occupied or unavailable to other users as it is a multi-threaded application. And also if the user payment fails or got logged out, how can I unlock those seats so that they got available for other users.
Please provide some code or any useful link how it can be done?. Is it a good approach to save the status of seats when changed to CREATED in a memory storage like Redis and for seats selected by users we check the status of each seat in Redis whether it is reserved or not. And if booking is successfully done by user then we can mark those seats as permanently reserved in a database.
CodePudding user response:
This is not really an answer because I'm not a database guy, but here's a rough sketch of what I would try:
Application locks the table of available seats, takes a snapshot of the table, unlocks it, and then shows the snapshot to the user.
User makes their selection and presses a button labelled "Reserve Seats."
Application locks the table and checks whether the selected seats still are available. There's two possible outcomes:
A. If one or more of the seats has been reserved by some other, quicker user, the application will; unlock the table, display a dialog that says, "Sorry, somebody else snagged those, please try again," and then it goes back to step 1.
B. Otherwise, the application marks those seats as
on_hold
, it timestamps them, and it unlocks the table.on_hold
prevents other users from reserving those same seats, but only for a limited time—maybe five minutes. The seats also are associated with a "shopping cart."Now, the user has some number of reserved seats in their shopping cart, but has not yet paid for them. User has the option to go back and reserve more seats, but let's say they press the "Checkout" button.
Application presents user with forms to fill out with credit card information, etc. But meanwhile, other users also are looking for seats. If, during some other user's step 1 (remember step 1?) any seat shows up as having been
on_hold
for more than five minutes, the application will;A. change the status of the seat to
available
, andB. Cancel the shopping cart that contains that seat. (Owner of the shopping cart sees a dialog that says "Ooh! Too bad! So sad! You waited too long," and they're sent back to step 1.)
But, if the user completes the transaction before their shopping cart is cancelled, then the application will lock the seat table, change the status of the seats to
sold
, unlock the seat table, and send the user their tickets.
CodePudding user response:
Rough and rushed brain dump: Agree with Uldall, create your data model and SQL DDL first, normalize and validate it. You need a Customer entity/table. I think you need an associative entity between Show and Seat, like ShowSeat with references to Show, Seat and Customer. ShowSeat also has isConfirmed boolean flag and lockExpirationTimestamp. Primary key on show_seat table is composite of show_id and seat_id (requires @Embeddable class to represent). When a customer selects the seat for the show, insert the row into show_seat but do NOT set confirmed='Y' until it IS confirmed. Any row in show_seat table with lock_expiration_timestamp < now() and confirmed='N' is fair game to be given to another customer.