Let’s consider a scenario in an e-commerce application where a user makes a payment for their order. If the payment service doesn’t respond within a certain time limit, the system should automatically cancel the order and refund the payment if it was charged. This is a timeout scenario.
Here’s how you could implement this with a compensating transaction:
- Initiate Payment: When a user confirms their order, you send a request to the payment service to charge the user’s credit card. You also start a timer (this could be implemented using a background job or a scheduled task).
function initiatePayment(orderId, creditCardInfo, amount) {
// Start a timer
setTimeout(() => {
checkPaymentStatus(orderId);
}, PAYMENT_TIMEOUT);
// Send a request to the payment service to charge the credit card
paymentService.chargeCreditCard(orderId, creditCardInfo, amount);
}
- Timeout: If the payment service doesn’t respond within the timeout period (say, 15 minutes), the
checkPaymentStatus
function is called. This function checks if the payment has been processed. If not, it cancels the order and refunds the payment if it was charged.
function checkPaymentStatus(orderId) {
// Check the status of the payment
const paymentStatus = paymentService.getPaymentStatus(orderId);
// If the payment is not processed, cancel the order and refund the payment
if (paymentStatus !== 'processed') {
orderService.cancelOrder(orderId);
if (paymentStatus === 'charged') {
paymentService.refundPayment(orderId);
}
}
}
This is a compensating transaction because it undoes the changes made by the initiatePayment
function if the payment service doesn’t respond within the timeout period.
Please note that this is a simplified example and might need to be adjusted based on your specific use case. For example, you might want to handle cases where the payment service responds just after the timeout period. You might also want to consider using a more robust queuing or messaging system to handle the timeouts. Remember to always test your code thoroughly to ensure it behaves correctly under various scenarios. Also, the actual implementation of paymentService.chargeCreditCard
, paymentService.getPaymentStatus
, paymentService.refundPayment
, and orderService.cancelOrder
would depend on your specific application and infrastructure. This example assumes that these methods are available and correctly implemented.