0

Let suppose we have an API to book tickets. There are 2 controller methods, one to check if the seat is already booked or not, another to book the seat. If 2 users simultaneously try to to book the same seat, then the first method will allow to book the seats. How is it going to handle the seat bookings now, running the requests in multiple threads parallelly?

Abinash Patra
  • 55
  • 3
  • 10
  • Once a seat is booked your api would block that seat. Therefore any calls to the method would either return error/blocked or remaining if you have many left. – AliK Oct 28 '21 at 06:23
  • You may use a locking mechanism for that (e.g. optimistic locking). – jAC Oct 28 '21 at 06:33
  • 2
    sounds like some sort of race condition you got there. All the threads will in theory be fighting for the same seats. It's probably worth thinking about making the reservation system thread safe. – Jochem Van Hespen Oct 28 '21 at 07:13
  • If you want to get technical, also consider that a _single OS thread_ can still process multiple simultaneous requests with coroutines (i.e. `async await` for IO). Though yes, ASP.NET Core uses a mix of techniques including IIS's underdocumented voodoo in `HTTP.SYS`, .NET's thread-pool (IIS uses a lower default thread stack size btw so it can have more threads than normal), and async IO. – Dai Oct 28 '21 at 08:06
  • 1
    The quick, short and simple answer to your question is that your _persistence store_ (usually a SQL RDBMS) will be responsible for ensuring _transactional correctness_: it will handle the transactions by itself (provided you correctly use `BEGIN TRANSACTION` and `COMMIT`). Otherwise your database state will be corrupted (in practice all major RDBMS handle this fine, you only need to watch out if you're doing IO yourself, like if you were writing to a simple text-file or similar). – Dai Oct 28 '21 at 08:10
  • Also, you should read this: https://en.wikipedia.org/wiki/Critical_section – Dai Oct 28 '21 at 08:15
  • the simple thing you can implement is the AWS SQS (simple queueing service). it handles almost all the major headichs for you like race conditions, job queueing, job processing, call backs. – Ch Usman Oct 31 '21 at 09:03

1 Answers1

0

Let suppose we have an API to book tickets.

Okay...

There are 2 controller methods, one to check if the seat is already booked or not, another to book the seat.

So far, so normal.

If 2 users simultaneously try to to book the same seat, then the first method will allow to book the seats.

That depends entirely on how your underlying booking service's persistence store handles concurrent requests.

  • If you're using a SQL database (MS SQL, MySQL, Oracle, PostgreSQL, etc) then you need to wrap the critical section of your SQL code in TRANSACTION statements with a COMMIT at the end, that way the RDBMS will handle the ACID-compliance for you.
    • For example, all of the above RDMBS will let concurrent IO to different unrelated rows happen in parallel because there's no conflict, but they will "sequentialize" the operations if two separate SQL transactions will affect the same rows, this is how they ensure ACID-compliance.
    • If you're using Entity Framework then unfortunately it's more complicated because EF doesn't generate a single long SQL statement batch: it (usually) executes single statements and ping-pongs between C#/.NET code and SQL, so you need to be careful. For this reason it's important (and often far simpler) to use a PROCEDURE instead of having EF do it).
  • If you're using an in-process in-memory then without using lock statements to guard critical-sections - as well as using Concurrent-safe collections (like ConcurrentDictionary) appropriately.
    • The System.Collections.Concurrent types are not magic (they should be renamed "reduced-locking collections" imo), and you still need to understand how they work and what they do-and-don't-do (there's no ConcurrentList<T> type, for example - think about why that is).
  • If you're using another external service as your back-end then you don't need to worry about it because handling concurrent operations is their problem.
    • Unless you're using an external service that doesn't offer any way to be transactionally correct, in which case then you will need to restrict concurrent operations in your own code, which won't easily scale (because in-memory techniques are fast, but don't work when your application is deployed over multiple web-server boxes).

How is it going to handle the seat bookings now, running the requests in multiple threads parallelly?

That's your problem to handle, not ASP.NET's.

Dai
  • 141,631
  • 28
  • 261
  • 374
  • The transaction itself solves nothing. A reservation system is something that needs application logic, indeed either in code or in procedures. An ORM will happily first save user 1's reservation followed by that of user 2 for the same seat and date. ORMs do support concurrency in updates, such as timestamps combined with `WHERE ConcurrencyStamp = @PreviousStamp`. – CodeCaster Oct 31 '21 at 08:59