This is kind of similar to the Two Generals problemTwo Generals' Problem, but not quite. I think there is a name for it, but I just can't remember it right now.
I am working on my website's payment flow.
Scenario
- Alice wants to pay Bob for a service. Bob has quoted her $10US$10.
- Alice clicks pay.
- Whilst Alice's request is flying through the ether, Bob edits his quote. He now wants $20US$20.
- Bob's request finishes before Alice's has reached the server.
- Alice's request reaches the server and her payment is authorized for $20US$20 instead of $10US$10.
- Alice is unhappy.
Whilst the chances of this are very low in practice, it is a possible scenario. Sometimes requests can hang due to network issues, etc...
Possible Mitigations
I don't think this problem is solvable. But we can do things to mitigate it.
This is not exactly an idempotency issue, so I don't think the answer is "idempotency token".
Option 1
Let's define:
t_0as the time Alice click pay.t_editas the time Bob's edit request succeedst_1as the time Alice's request reaches the server
Since we cannot know t_0 unless we send it as part of the request data, and because we cannot trust what the client sends, we will ignore t_0.
At the time Alice's request arrives in the server, we check:
if t_1 - t_edit < 1 minute: return "409 Conflict" (or some other code)
Would this approach work? 1 minute is an arbitrary choice, and it doesn't solve the problem entirely. If Alice's request takes 1 minute or more to reach the server, the issue persists.
This must be an extremely common problem to deal with, noright?