4 ms·
This is good but not enough. You also need to be sure that you can’t charge twice if the job runs twice. When you do that same query twice, you will get the sam
by jchw 6y ago
This is good but not enough. You also need to be sure that you can’t charge twice if the job runs twice. When you do that same query twice, you will get the same list of users. This could be done by exploiting database consistency rules, like using strongly isolated transactions. One simple more general approach is to use an idempotence token. You could, say, have a table with a uniqueness constraint, and generate IDs that will match for the same user in the same month. Then add that in the same transaction that subtracts the money. The table could be cleaned up periodically.
If you’re making or using an API where repeating would be bad, consider using idempotency tokens for those too. I believe Stripe supports them. The basic idea is the same: if you pass a token into them, they will guarantee that in a certain time frame, no other requests with that ID can be duplicated. This is useful when the network flakes during the response. Is it safe to retry?
Things get trickier when you combine network and database consistency measures; that’s when you get into locks and multi stage commit and etc. and it helps to know your database’s consistency model, since it’s often not as solid as you think! (In the past, even PostgreSQL had issues with providing serializable isolation.)
- jbluepolarbear 6y agoHave you used a iterator as the token? I had data that could be accessed and mutated from multiple different sources at the same time. With just a token and blocking the data caused race condition (cross server race conditions/deadlocks are just the worst). I solved this by giving an iterator with every read and a write required the same iterator back with the changes. If 2 servers try to write at the same time the first processed will go through and the other will get rejected. The rejected server will reread the data with a new iterator, apply its mutation, then attempt to write. It worked really well for me and I never had any race/deadlock issues.
- glic3rinu 6y agovector clocks?
- jbluepolarbear 6y agoI’m not familiar with Vector clocks. If it’s the same concept it’s purely by chance.
- Izkata 6y ago> This is good but not enough. You also need to be sure that you can’t charge twice if the job runs twice. When you do that same query twice, you will get the same list of users. That's handled by the extra condition in step 1 of the altered rules: > which haven't been charged the fee this month.
- glic3rinu 6y agoOP is talking about concurrent execution of the task without serialization on the database (serializable isolation is almost never the default). Which results in 2 concurrent queries getting the same list of customers to charge.