RESTful library management API handling edge cases like race conditions, conflict resolution, and built-in bulk operations.
When I was tasked to make a library management system, the first thing that came into my mind was “Seriously? It’s a cliche project!” but since it was the requirement for my college’s tech society - as a token of test, I decided to make it but not the usual way. Mostly, a library management system is primarily about basic CRUD operations, no place for handling edge cases like “What if two users try to borrow the same book in milliseconds of interval? Who will get the book then?” or “What if there is conflicting data in the database?” These questions made me think not just about CRUD but also about the architecture of the system.
After rigorous scribbles on paper, I’ve made the following database schema which I found to be robust enough to handle the edge cases.
The schema prior to the current one was a mess, not because it couldn’t handle the edge cases but because it was not even able to handle the foreign key constraints properly. Notice the current schema, it implements soft deletes for users, inventory (which is an additional layer) between books and book loans, and the books table itself made independent and restricted any delete operation on it - it behaves like a central lobby or an attic of books where books are kept and never thrown away, only their status is updated. Why? because I wanted to build a system where the librarian simply adds list of ISBNs and the system automatically fetches the book details from the central repository of books (for speed) and if not found then from Google Books API and adds them to the database. this feature is not implemented yet but the books table acts as a central repository for books as of now.
The simple case where user-1 tries to update his/her email but the provided email is already taken by some user-x, in that case I need to handle the conflicting case and prompt that the email is already taken by some user-x. To achieve this I came up with the idea of making a separate utility “conflict_handler” which would scan the database for conflicts before any write operation.
This is the utility function that I created to handle the conflict resolution in the database. similarly the whole of the project is built with the same level of care and attention to detail.
You can explore more and can even play with it on litengine or check out its documentation on litengine docs or the code on github. That’s a wrap, there is more in it than I could write in a single blog post. Stay tuned :) Bye