Here's my problem. I want to make fast, subsequent requests to a REST API endpoint (/todos/:id/position) that have side effects on other resources.
As an example of 5 fast subsequent requests:
PATCH /todos/2/position {"position": 2}
PATCH /todos/2/position {"position": 3}
PATCH /todos/2/position {"position": 4}
PATCH /todos/2/position {"position": 5}
PATCH /todos/2/position {"position": 6}
As you can see, I am moving todo #2 from position 2 to position 6, one request at a time. Now of course, those calls have side effects on other todos. When todo #2 changes from position 2 to 3, the position that had position #3 goes from 3 to 2, etc. This provides some sort of race conditions, as the 5 calls are modifying data in the DB at the same time.
I have implemented transactions and ETags on this service, because at first I thought I was having concurrency/optimistic locking problem, but it seems like my problem is bigger than this. With ETAGs and transactions in place, request 1, 3 and 4 might works, but requests 2, 5 might fail, resulting my todo to only reach position 5 (and also awkwardly skipping over certain other positions). This is because request 2 does not have the right etag, because request 1 has not responded yet, etc.
How can I make sure all requests are successful and execute in the right order? Is this even possible?
Here are two solutions I have thought of and that I consider weak, since they do not resolve the root problem on the server.
- On the front-end, have a queue of requests. Request 2 is not initiated until request 1 has resolved. Request 3 is not initiated until request 2 has resolved, etc
- Throttle the requests. Instead of sendin 5 fast, subsequent requests, throttle them to only send the last one, i.e with a timer of 500ms.
then
ed onto a previous promise, ensuring execution sequence. Illustrates the difference from athen
chain all taking the same argument as returned by the initial Promise that does not guarantee sequence.