What is a standard retry algorithm for handling server errors?
I'm using Amazon Web Services' PHP SDK for their Flexible Payments System. Somewhere in their API documentation they essentially point out that there may, from time to time, be errors on their end that should be handled on your end with a "standard retry algorithm".
In my particular use case, we're talking about canceling a user's payment token only after a new payment token has been successful. That is, someone wants to change a donation amount from $5 to $10. After completing the pipeline, the user is redirected to a callback URL. This script will attempt to cancel the previous token, and then updat开发者_开发技巧e the new token to show that it has been authorized.
However, if an error occurs when canceling the user's earlier transaction, the new transaction still needs to be updated. And then we arrive at our problem: the user now has TWO payment tokens and will be charged $15 total, unless the first token is successfully canceled.
So what kind of "standard retry algorithm" is there for handling something of this nature? I was thinking about running a cron job that just looks for duplicate tokens and cancels the earlier ones, but that's a bit of a hack IMHO.
Any thoughts?
The usual approach is exponential backoff - if you fail, retry in one second, then two, then four, etc etc, with some reasonable cap (several hours) to ensure you don't end up spending hours waiting. This does not need to happen synchronously. You can use a task queue server of some sort (RabbitMQ, Celery, etc etc) to launch such a task in the background, for example. You should probably be doing payment operations asynchronously anyway, though, as it's possible that they may take a long time.
However, from my read of the Amazon Flexible Payments API, this isn't a very time critical operation - leaving a sender token uncancelled just gives you the option to initiate a payment, but doesn't automatically do so. As such, a simpler approach, can work. For example, try to cancel it immediately after acquiring the new token. If this fails, then try again in an hourly cron job.
Note, of course, that it's important to keep track of which payment token to use. Assuming you're using a ACID-compliant database (and you really, REALLY should be when working with money) this is simple enough to do - keep the most recent payment token on the user itself, then create a separate table to hold a list of to-be-expired tokens. Then just update the user token and add the old token to the purge table in a single transaction.
精彩评论