diff --git a/payment/src/main/java/org/killbill/billing/payment/core/janitor/IncompletePaymentTransactionTask.java b/payment/src/main/java/org/killbill/billing/payment/core/janitor/IncompletePaymentTransactionTask.java
index 88fd895..6887cc5 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/janitor/IncompletePaymentTransactionTask.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/janitor/IncompletePaymentTransactionTask.java
@@ -175,7 +175,8 @@ public class IncompletePaymentTransactionTask extends CompletionTaskBase<Payment
final Boolean result = doJanitorOperationWithAccountLock(new JanitorIterationCallback() {
@Override
public Boolean doIteration() {
- return updatePaymentAndTransactionInternal(payment, null, null, paymentTransaction, paymentTransactionInfoPlugin, internalTenantContext);
+ final PaymentTransactionModelDao refreshedPaymentTransaction = paymentDao.getPaymentTransaction(paymentTransaction.getId(), internalTenantContext);
+ return updatePaymentAndTransactionInternal(payment, null, null, refreshedPaymentTransaction, paymentTransactionInfoPlugin, internalTenantContext);
}
}, internalTenantContext);
return result != null && result;
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/janitor/TestIncompletePaymentTransactionTaskWithDB.java b/payment/src/test/java/org/killbill/billing/payment/core/janitor/TestIncompletePaymentTransactionTaskWithDB.java
index 8dc40d7..1a356d0 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/janitor/TestIncompletePaymentTransactionTaskWithDB.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/janitor/TestIncompletePaymentTransactionTaskWithDB.java
@@ -21,14 +21,24 @@ import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;
+import org.joda.time.DateTime;
import org.killbill.billing.account.api.Account;
+import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.payment.PaymentTestSuiteWithEmbeddedDB;
import org.killbill.billing.payment.api.Payment;
import org.killbill.billing.payment.api.PaymentApiException;
import org.killbill.billing.payment.api.PluginProperty;
+import org.killbill.billing.payment.api.TransactionStatus;
+import org.killbill.billing.payment.api.TransactionType;
+import org.killbill.billing.payment.core.sm.PaymentStateMachineHelper;
+import org.killbill.billing.payment.dao.PaymentModelDao;
+import org.killbill.billing.payment.dao.PaymentTransactionModelDao;
import org.killbill.billing.payment.plugin.api.PaymentPluginStatus;
+import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
+import org.killbill.billing.payment.provider.DefaultNoOpPaymentInfoPlugin;
import org.killbill.billing.payment.provider.MockPaymentProviderPlugin;
+import org.killbill.billing.util.callcontext.InternalCallContextFactory;
import org.killbill.billing.util.globallocker.LockerType;
import org.killbill.commons.locker.GlobalLock;
import org.killbill.commons.locker.LockFailedException;
@@ -105,4 +115,69 @@ public class TestIncompletePaymentTransactionTaskWithDB extends PaymentTestSuite
}
}
}
+
+ @Test(groups = "slow", description = "https://github.com/killbill/killbill/issues/809")
+ public void testUpdateWithinLock() throws PaymentApiException {
+ final Payment payment = paymentApi.createAuthorization(account,
+ account.getPaymentMethodId(),
+ null,
+ BigDecimal.TEN,
+ Currency.EUR,
+ UUID.randomUUID().toString(),
+ UUID.randomUUID().toString(),
+ ImmutableList.<PluginProperty>of(new PluginProperty(MockPaymentProviderPlugin.PLUGIN_PROPERTY_PAYMENT_PLUGIN_STATUS_OVERRIDE, PaymentPluginStatus.UNDEFINED.toString(), false)),
+ callContext);
+ final PaymentModelDao paymentModel = paymentDao.getPayment(payment.getId(), internalCallContext);
+ final UUID transactionId = payment.getTransactions().get(0).getId();
+ final PaymentTransactionModelDao transactionModel = paymentDao.getPaymentTransaction(transactionId, internalCallContext);
+
+ Assert.assertEquals(paymentModel.getStateName(), "AUTH_ERRORED");
+ Assert.assertEquals(transactionModel.getTransactionStatus().toString(), "UNKNOWN");
+
+ paymentDao.updatePaymentAndTransactionOnCompletion(
+ account.getId(),
+ null,
+ payment.getId(),
+ TransactionType.AUTHORIZE,
+ "AUTH_SUCCESS",
+ "AUTH_SUCCESS",
+ transactionId,
+ TransactionStatus.SUCCESS,
+ BigDecimal.TEN,
+ Currency.EUR,
+ "200",
+ "Ok",
+ internalCallContext);
+
+ paymentApi.createCapture(account,
+ payment.getId(),
+ BigDecimal.TEN,
+ Currency.EUR,
+ UUID.randomUUID().toString(),
+ ImmutableList.<PluginProperty>of(new PluginProperty(MockPaymentProviderPlugin.PLUGIN_PROPERTY_PAYMENT_PLUGIN_STATUS_OVERRIDE, PaymentPluginStatus.PROCESSED.toString(), false)),
+ callContext);
+
+ final PaymentModelDao paymentAfterCapture = paymentDao.getPayment(payment.getId(), internalCallContext);
+ Assert.assertEquals(paymentAfterCapture.getStateName(), "CAPTURE_SUCCESS");
+
+ PaymentTransactionInfoPlugin paymentTransactionInfoPlugin = new DefaultNoOpPaymentInfoPlugin(
+ payment.getId(),
+ transactionId,
+ TransactionType.AUTHORIZE,
+ BigDecimal.TEN,
+ Currency.EUR,
+ transactionModel.getEffectiveDate(),
+ transactionModel.getCreatedDate(),
+ PaymentPluginStatus.PROCESSED,
+ "200",
+ "OK");
+ incompletePaymentTransactionTask.updatePaymentAndTransactionIfNeededWithAccountLock(
+ paymentModel,
+ transactionModel,
+ paymentTransactionInfoPlugin,
+ internalCallContext);
+
+ final PaymentModelDao paymentAfterJanitor = paymentDao.getPayment(payment.getId(), internalCallContext);
+ Assert.assertEquals(paymentAfterJanitor.getStateName(), "CAPTURE_SUCCESS");
+ }
}