Recently, me and my colleague Jakub have discussed problem of data consistency in client side applications.
Let's pretend we have a todo list application and we have checkboxes for each task and a button that allows us to delete marked todos. User marks 3 todos and one of them for some reason cannot be deleted and we don't want to get to the state where just 2 of 3 todos were deleted. We demand from application to do exactly what user expected or do nothing (actually for instance django-tastypie provides bulk operations for single resource but we could probably find other example which would need to use multiple resources).
In classic server side application one user action corresponds to one server request. It's trivial to lock all database operations in view / controller (depends on your framework) in one transaction (django provides setting ATOMIC_REQUESTS for this). But in client side application, using standard REST API providing CRUD operations, this situation leads to multiple requests - one request for deletion of each todo item. And obviously, there is no guarantee that each of requests will be successful. And such situations are imho quite common in client side applications.
How to solve such situations? We still didn't find fully satisfying answer. One of solutions have appeared in django-superbulk , which solve this problem quite impressively and performs like a mediator between client and REST api and guarantees atomicity. But it doesn't fully solve situation when you're saving new objects. Imagine situation, when you want to save article and images related to it. You don't know the id that will be assigned to article. Jakub came up with two solutions for this, but none of them seems ideal:
- Upgrade superbulk functionality to use some placeholder for id in data request and substitute it with real id after assignment
- Use long string primary indexes and generate them randomly on client side.
Have you experienced this issue? Have you found solution for this or have you come to the conclusion that there is actually no need to solve this?