killbill-memoizeit
Changes
invoice/src/test/java/org/killbill/billing/invoice/generator/TestDefaultInvoiceGenerator.java 5(+5 -0)
payment/src/main/java/org/killbill/billing/payment/core/janitor/IncompletePaymentTransactionTask.java 35(+23 -12)
payment/src/main/java/org/killbill/billing/payment/core/sm/control/AuthorizeControlOperation.java 10(+8 -2)
payment/src/main/java/org/killbill/billing/payment/core/sm/control/CaptureControlOperation.java 10(+8 -2)
payment/src/main/java/org/killbill/billing/payment/core/sm/control/ChargebackControlOperation.java 10(+8 -2)
payment/src/main/java/org/killbill/billing/payment/core/sm/control/CompletionControlOperation.java 13(+7 -6)
payment/src/main/java/org/killbill/billing/payment/core/sm/control/CreditControlOperation.java 10(+8 -2)
payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java 8(+5 -3)
payment/src/main/java/org/killbill/billing/payment/core/sm/control/PurchaseControlOperation.java 10(+8 -2)
payment/src/main/java/org/killbill/billing/payment/core/sm/control/RefundControlOperation.java 10(+8 -2)
payment/src/main/java/org/killbill/billing/payment/core/sm/control/VoidControlOperation.java 10(+8 -2)
payment/src/main/java/org/killbill/billing/payment/core/sm/payments/AuthorizeOperation.java 7(+5 -2)
payment/src/main/java/org/killbill/billing/payment/core/sm/payments/ChargebackOperation.java 7(+5 -2)
payment/src/main/java/org/killbill/billing/payment/core/sm/PluginControlPaymentAutomatonRunner.java 18(+10 -8)
payment/src/main/java/org/killbill/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java 5(+5 -0)
payment/src/test/java/org/killbill/billing/payment/core/janitor/TestIncompletePaymentTransactionTask.java 1(+0 -1)
Details
diff --git a/api/src/main/java/org/killbill/billing/payment/plugin/api/NoOpPaymentPluginApi.java b/api/src/main/java/org/killbill/billing/payment/plugin/api/NoOpPaymentPluginApi.java
index bab9f06..40eee4f 100644
--- a/api/src/main/java/org/killbill/billing/payment/plugin/api/NoOpPaymentPluginApi.java
+++ b/api/src/main/java/org/killbill/billing/payment/plugin/api/NoOpPaymentPluginApi.java
@@ -16,13 +16,18 @@
package org.killbill.billing.payment.plugin.api;
+import java.util.List;
+import java.util.UUID;
+
public interface NoOpPaymentPluginApi extends PaymentPluginApi {
- public void clear();
+ void clear();
+
+ void makeNextPaymentFailWithError();
- public void makeNextPaymentFailWithError();
+ void makeNextPaymentFailWithException();
- public void makeNextPaymentFailWithException();
+ void makeAllInvoicesFailWithError(boolean failure);
- public void makeAllInvoicesFailWithError(boolean failure);
+ void updatePaymentTransactions(UUID paymentId, List<PaymentTransactionInfoPlugin> newTransactions);
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/api/InvoiceApiHelper.java b/invoice/src/main/java/org/killbill/billing/invoice/api/InvoiceApiHelper.java
index b56af28..30b968e 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/api/InvoiceApiHelper.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/api/InvoiceApiHelper.java
@@ -39,6 +39,7 @@ import org.killbill.billing.invoice.model.ItemAdjInvoiceItem;
import org.killbill.billing.util.UUIDs;
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
+import org.killbill.billing.util.config.InvoiceConfig;
import org.killbill.billing.util.globallocker.LockerType;
import org.killbill.commons.locker.GlobalLock;
import org.killbill.commons.locker.GlobalLocker;
@@ -57,26 +58,25 @@ public class InvoiceApiHelper {
private static final Logger log = LoggerFactory.getLogger(InvoiceApiHelper.class);
- // 50 * 100ms = 5sec
- private static final int NB_LOCK_TRY = 50;
-
private final InvoicePluginDispatcher invoicePluginDispatcher;
private final InvoiceDao dao;
private final GlobalLocker locker;
private final InternalCallContextFactory internalCallContextFactory;
+ private final InvoiceConfig invoiceConfig;
@Inject
- public InvoiceApiHelper(final InvoicePluginDispatcher invoicePluginDispatcher, final InvoiceDao dao, final GlobalLocker locker, final InternalCallContextFactory internalCallContextFactory) {
+ public InvoiceApiHelper(final InvoicePluginDispatcher invoicePluginDispatcher, final InvoiceDao dao, final GlobalLocker locker, final InvoiceConfig invoiceConfig, final InternalCallContextFactory internalCallContextFactory) {
this.invoicePluginDispatcher = invoicePluginDispatcher;
this.dao = dao;
this.locker = locker;
+ this.invoiceConfig = invoiceConfig;
this.internalCallContextFactory = internalCallContextFactory;
}
public List<InvoiceItem> dispatchToInvoicePluginsAndInsertItems(final UUID accountId, final WithAccountLock withAccountLock, final CallContext context) throws InvoiceApiException {
GlobalLock lock = null;
try {
- lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), accountId.toString(), NB_LOCK_TRY);
+ lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), accountId.toString(), invoiceConfig.getMaxGlobalLockRetries());
final Iterable<Invoice> invoicesForPlugins = withAccountLock.prepareInvoices();
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
index 859d106..4460632 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
@@ -113,9 +113,6 @@ public class InvoiceDispatcher {
private static final Logger log = LoggerFactory.getLogger(InvoiceDispatcher.class);
- // 50 * 100ms = 5sec
- private static final int NB_LOCK_TRY = 50;
-
private static final Ordering<DateTime> UPCOMING_NOTIFICATION_DATE_ORDERING = Ordering.natural();
private final static Joiner JOINER_COMMA = Joiner.on(",");
private static final NullDryRunArguments NULL_DRY_RUN_ARGUMENTS = new NullDryRunArguments();
@@ -208,7 +205,7 @@ public class InvoiceDispatcher {
@Nullable final DryRunArguments dryRunArguments, final InternalCallContext context) throws InvoiceApiException {
GlobalLock lock = null;
try {
- lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), accountId.toString(), NB_LOCK_TRY);
+ lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), accountId.toString(), invoiceConfig.getMaxGlobalLockRetries());
return processAccountWithLock(accountId, targetDate, dryRunArguments, context);
} catch (final LockFailedException e) {
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/generator/TestDefaultInvoiceGenerator.java b/invoice/src/test/java/org/killbill/billing/invoice/generator/TestDefaultInvoiceGenerator.java
index cadda9d..9c5ec23 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/generator/TestDefaultInvoiceGenerator.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/generator/TestDefaultInvoiceGenerator.java
@@ -127,6 +127,11 @@ public class TestDefaultInvoiceGenerator extends InvoiceTestSuiteNoDB {
public int getMaxRawUsagePreviousPeriod() {
return -1;
}
+
+ @Override
+ public int getMaxGlobalLockRetries() {
+ return 10;
+ }
};
this.generator = new DefaultInvoiceGenerator(clock, invoiceConfig, null);
this.account = new MockAccountBuilder().name(UUID.randomUUID().toString().substring(1, 8))
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/janitor/CompletionTaskBase.java b/payment/src/main/java/org/killbill/billing/payment/core/janitor/CompletionTaskBase.java
index 60281b4..2d4a157 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/janitor/CompletionTaskBase.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/janitor/CompletionTaskBase.java
@@ -124,7 +124,7 @@ abstract class CompletionTaskBase<T> implements Runnable {
GlobalLock lock = null;
try {
final Account account = accountInternalApi.getAccountByRecordId(internalTenantContext.getAccountRecordId(), internalTenantContext);
- lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), account.getExternalKey(), ProcessorBase.NB_LOCK_TRY);
+ lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), account.getExternalKey(), paymentConfig.getMaxGlobalLockRetries());
return callback.doIteration();
} catch (AccountApiException e) {
log.warn(String.format("Janitor failed to retrieve account with recordId %s", internalTenantContext.getAccountRecordId()), e);
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 8c013d4..94d318b 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
@@ -142,7 +142,7 @@ public class IncompletePaymentTransactionTask extends CompletionTaskBase<Payment
if (!TRANSACTION_STATUSES_TO_CONSIDER.contains(event.getStatus())) {
return;
}
- insertNewNotificationForUnresolvedTransactionIfNeeded(event.getPaymentTransactionId(), 1, event.getUserToken(), event.getSearchKey1(), event.getSearchKey2());
+ insertNewNotificationForUnresolvedTransactionIfNeeded(event.getPaymentTransactionId(), 0, event.getUserToken(), event.getSearchKey1(), event.getSearchKey2());
}
public boolean updatePaymentAndTransactionIfNeededWithAccountLock(final PaymentModelDao payment, final PaymentTransactionModelDao paymentTransaction, final PaymentTransactionInfoPlugin paymentTransactionInfoPlugin, final InternalTenantContext internalTenantContext) {
@@ -200,6 +200,14 @@ public class IncompletePaymentTransactionTask extends CompletionTaskBase<Payment
return false;
}
+ // Our status did not change, so we just insert a new notification (attemptNumber will be incremented)
+ if (transactionStatus == paymentTransaction.getTransactionStatus()) {
+ log.debug("Janitor IncompletePaymentTransactionTask repairing payment {}, transaction {}, transitioning transactionStatus from {} -> {}",
+ payment.getId(), paymentTransaction.getId(), paymentTransaction.getTransactionStatus(), transactionStatus);
+ insertNewNotificationForUnresolvedTransactionIfNeeded(paymentTransaction.getId(), attemptNumber, userToken, internalTenantContext.getAccountRecordId(), internalTenantContext.getTenantRecordId());
+ return false;
+ }
+
// Recompute new lastSuccessPaymentState. This is important to be able to allow new operations on the state machine (for e.g an AUTH_SUCCESS would now allow a CAPTURE operation)
final String lastSuccessPaymentState = paymentStateMachineHelper.isSuccessState(newPaymentState) ? newPaymentState : null;
@@ -213,13 +221,9 @@ public class IncompletePaymentTransactionTask extends CompletionTaskBase<Payment
final String gatewayErrorCode = paymentTransactionInfoPlugin != null ? paymentTransactionInfoPlugin.getGatewayErrorCode() : paymentTransaction.getGatewayErrorCode();
final String gatewayError = paymentTransactionInfoPlugin != null ? paymentTransactionInfoPlugin.getGatewayError() : paymentTransaction.getGatewayErrorMsg();
- if (transactionStatus == paymentTransaction.getTransactionStatus()) {
- log.debug("Janitor IncompletePaymentTransactionTask repairing payment {}, transaction {}, transitioning transactionStatus from {} -> {}",
- payment.getId(), paymentTransaction.getId(), paymentTransaction.getTransactionStatus(), transactionStatus);
- } else {
- log.info("Janitor IncompletePaymentTransactionTask repairing payment {}, transaction {}, transitioning transactionStatus from {} -> {}",
- payment.getId(), paymentTransaction.getId(), paymentTransaction.getTransactionStatus(), transactionStatus);
- }
+
+ log.info("Janitor IncompletePaymentTransactionTask repairing payment {}, transaction {}, transitioning transactionStatus from {} -> {}",
+ payment.getId(), paymentTransaction.getId(), paymentTransaction.getTransactionStatus(), transactionStatus);
final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(payment.getAccountId(), callContext);
paymentDao.updatePaymentAndTransactionOnCompletion(payment.getAccountId(), payment.getId(), paymentTransaction.getTransactionType(), newPaymentState, lastSuccessPaymentState,
@@ -248,10 +252,10 @@ public class IncompletePaymentTransactionTask extends CompletionTaskBase<Payment
}
@VisibleForTesting
- DateTime getNextNotificationTime(@Nullable final Integer attemptNumber) {
+ DateTime getNextNotificationTime(final Integer attemptNumber) {
final List<TimeSpan> retries = paymentConfig.getIncompleteTransactionsRetries();
- if (attemptNumber == null || attemptNumber > retries.size()) {
+ if (attemptNumber > retries.size()) {
return null;
}
final TimeSpan nextDelay = retries.get(attemptNumber - 1);
@@ -259,8 +263,15 @@ public class IncompletePaymentTransactionTask extends CompletionTaskBase<Payment
}
private void insertNewNotificationForUnresolvedTransactionIfNeeded(final UUID paymentTransactionId, @Nullable final Integer attemptNumber, @Nullable final UUID userToken, final Long accountRecordId, final Long tenantRecordId) {
- final NotificationEvent key = new JanitorNotificationKey(paymentTransactionId, IncompletePaymentTransactionTask.class.toString(), attemptNumber);
- final DateTime notificationTime = getNextNotificationTime(attemptNumber);
+ // When we come from a GET path, we don't want to insert a new notification
+ if (attemptNumber == null) {
+ return;
+ }
+
+ // Increment value before we insert
+ final Integer newAttemptNumber = attemptNumber.intValue() + 1;
+ final NotificationEvent key = new JanitorNotificationKey(paymentTransactionId, IncompletePaymentTransactionTask.class.toString(), newAttemptNumber);
+ final DateTime notificationTime = getNextNotificationTime(newAttemptNumber);
// Will be null in the GET path or when we run out opf attempts..
if (notificationTime != null) {
try {
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java
index 102c3d2..6368518 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java
@@ -79,6 +79,8 @@ public class PaymentMethodProcessor extends ProcessorBase {
private final PluginDispatcher<UUID> uuidPluginNotificationDispatcher;
+ private final PaymentConfig paymentConfig;
+
@Inject
public PaymentMethodProcessor(final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry,
final AccountInternalApi accountInternalApi,
@@ -92,6 +94,7 @@ public class PaymentMethodProcessor extends ProcessorBase {
final Clock clock) {
super(pluginRegistry, accountInternalApi, paymentDao, tagUserApi, locker, internalCallContextFactory, invoiceApi, clock);
final long paymentPluginTimeoutSec = TimeUnit.SECONDS.convert(paymentConfig.getPaymentPluginTimeout().getPeriod(), paymentConfig.getPaymentPluginTimeout().getUnit());
+ this.paymentConfig = paymentConfig;
this.uuidPluginNotificationDispatcher = new PluginDispatcher<UUID>(paymentPluginTimeoutSec, executors);
}
@@ -102,7 +105,8 @@ public class PaymentMethodProcessor extends ProcessorBase {
return dispatchWithExceptionHandling(account,
new CallableWithAccountLock<UUID, PaymentApiException>(locker,
account.getExternalKey(),
- new WithAccountLockCallback<PluginDispatcherReturnType<UUID>, PaymentApiException>() {
+ paymentConfig,
+ new DispatcherCallback<PluginDispatcherReturnType<UUID>, PaymentApiException>() {
@Override
public PluginDispatcherReturnType<UUID> doOperation() throws PaymentApiException {
@@ -331,7 +335,7 @@ public class PaymentMethodProcessor extends ProcessorBase {
final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext context)
throws PaymentApiException {
try {
- new WithAccountLock<Void, PaymentApiException>().processAccountWithLock(locker, account.getExternalKey(), new WithAccountLockCallback<PluginDispatcherReturnType<Void>, PaymentApiException>() {
+ new WithAccountLock<Void, PaymentApiException>(paymentConfig).processAccountWithLock(locker, account.getExternalKey(), new DispatcherCallback<PluginDispatcherReturnType<Void>, PaymentApiException>() {
@Override
public PluginDispatcherReturnType<Void> doOperation() throws PaymentApiException {
@@ -374,7 +378,7 @@ public class PaymentMethodProcessor extends ProcessorBase {
public void setDefaultPaymentMethod(final Account account, final UUID paymentMethodId, final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext context)
throws PaymentApiException {
try {
- new WithAccountLock<Void, PaymentApiException>().processAccountWithLock(locker, account.getExternalKey(), new WithAccountLockCallback<PluginDispatcherReturnType<Void>, PaymentApiException>() {
+ new WithAccountLock<Void, PaymentApiException>(paymentConfig).processAccountWithLock(locker, account.getExternalKey(), new DispatcherCallback<PluginDispatcherReturnType<Void>, PaymentApiException>() {
@Override
public PluginDispatcherReturnType<Void> doOperation() throws PaymentApiException {
@@ -438,7 +442,7 @@ public class PaymentMethodProcessor extends ProcessorBase {
}
try {
- final PluginDispatcherReturnType<List<PaymentMethod>> result = new WithAccountLock<List<PaymentMethod>, PaymentApiException>().processAccountWithLock(locker, account.getExternalKey(), new WithAccountLockCallback<PluginDispatcherReturnType<List<PaymentMethod>>, PaymentApiException>() {
+ final PluginDispatcherReturnType<List<PaymentMethod>> result = new WithAccountLock<List<PaymentMethod>, PaymentApiException>(paymentConfig).processAccountWithLock(locker, account.getExternalKey(), new DispatcherCallback<PluginDispatcherReturnType<List<PaymentMethod>>, PaymentApiException>() {
@Override
public PluginDispatcherReturnType<List<PaymentMethod>> doOperation() throws PaymentApiException {
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/ProcessorBase.java b/payment/src/main/java/org/killbill/billing/payment/core/ProcessorBase.java
index 3b76d67..1e8be54 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/ProcessorBase.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/ProcessorBase.java
@@ -23,7 +23,6 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeoutException;
import javax.annotation.Nullable;
@@ -47,6 +46,7 @@ import org.killbill.billing.util.api.TagApiException;
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
import org.killbill.billing.util.callcontext.TenantContext;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.billing.util.globallocker.LockerType;
import org.killbill.billing.util.tag.ControlTagType;
import org.killbill.billing.util.tag.Tag;
@@ -63,9 +63,6 @@ import com.google.common.collect.Collections2;
public abstract class ProcessorBase {
- // 50 * 100ms = 5sec
- public static final int NB_LOCK_TRY = 50;
-
protected final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry;
protected final AccountInternalApi accountInternalApi;
protected final GlobalLocker locker;
@@ -158,9 +155,7 @@ public abstract class ProcessorBase {
return internalCallContextFactory.createCallContext(context);
}
- // TODO Rename - there is no lock!
- public interface WithAccountLockCallback<PluginDispatcherReturnType, ExceptionType extends Exception> {
-
+ public interface DispatcherCallback<PluginDispatcherReturnType, ExceptionType extends Exception> {
public PluginDispatcherReturnType doOperation() throws ExceptionType;
}
@@ -168,29 +163,38 @@ public abstract class ProcessorBase {
private final GlobalLocker locker;
private final String accountExternalKey;
- private final WithAccountLockCallback<PluginDispatcherReturnType<ReturnType>, ExceptionType> callback;
+ private final DispatcherCallback<PluginDispatcherReturnType<ReturnType>, ExceptionType> callback;
+ private final PaymentConfig paymentConfig;
public CallableWithAccountLock(final GlobalLocker locker,
final String accountExternalKey,
- final WithAccountLockCallback<PluginDispatcherReturnType<ReturnType>, ExceptionType> callback) {
+ final PaymentConfig paymentConfig,
+ final DispatcherCallback<PluginDispatcherReturnType<ReturnType>, ExceptionType> callback) {
this.locker = locker;
this.accountExternalKey = accountExternalKey;
this.callback = callback;
+ this.paymentConfig = paymentConfig;
}
@Override
public PluginDispatcherReturnType<ReturnType> call() throws ExceptionType, LockFailedException {
- return new WithAccountLock<ReturnType, ExceptionType>().processAccountWithLock(locker, accountExternalKey, callback);
+ return new WithAccountLock<ReturnType, ExceptionType>(paymentConfig).processAccountWithLock(locker, accountExternalKey, callback);
}
}
public static class WithAccountLock<ReturnType, ExceptionType extends Exception> {
- public PluginDispatcherReturnType<ReturnType> processAccountWithLock(final GlobalLocker locker, final String accountExternalKey, final WithAccountLockCallback<PluginDispatcherReturnType<ReturnType>, ExceptionType> callback)
+ private final PaymentConfig paymentConfig;
+
+ public WithAccountLock(final PaymentConfig paymentConfig) {
+ this.paymentConfig = paymentConfig;
+ }
+
+ public PluginDispatcherReturnType<ReturnType> processAccountWithLock(final GlobalLocker locker, final String accountExternalKey, final DispatcherCallback<PluginDispatcherReturnType<ReturnType>, ExceptionType> callback)
throws ExceptionType, LockFailedException {
GlobalLock lock = null;
try {
- lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), accountExternalKey, NB_LOCK_TRY);
+ lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), accountExternalKey, paymentConfig.getMaxGlobalLockRetries());
return callback.doOperation();
} finally {
if (lock != null) {
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/AuthorizeControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/AuthorizeControlOperation.java
index 0459ad2..4f05f5e 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/AuthorizeControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/AuthorizeControlOperation.java
@@ -23,12 +23,18 @@ import org.killbill.billing.payment.api.PaymentApiException;
import org.killbill.billing.payment.core.PaymentProcessor;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
public class AuthorizeControlOperation extends OperationControlCallback {
- public AuthorizeControlOperation(final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher, final PaymentStateControlContext paymentStateContext, final PaymentProcessor paymentProcessor, final ControlPluginRunner controlPluginRunner) {
- super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ public AuthorizeControlOperation(final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
+ final PaymentStateControlContext paymentStateContext,
+ final PaymentProcessor paymentProcessor,
+ final ControlPluginRunner controlPluginRunner) {
+ super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, paymentConfig, controlPluginRunner);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CaptureControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CaptureControlOperation.java
index 2b76885..54f133f 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CaptureControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CaptureControlOperation.java
@@ -23,12 +23,18 @@ import org.killbill.billing.payment.api.PaymentApiException;
import org.killbill.billing.payment.core.PaymentProcessor;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
public class CaptureControlOperation extends OperationControlCallback {
- public CaptureControlOperation(final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher, final PaymentStateControlContext paymentStateContext, final PaymentProcessor paymentProcessor, final ControlPluginRunner controlPluginRunner) {
- super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ public CaptureControlOperation(final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
+ final PaymentStateControlContext paymentStateContext,
+ final PaymentProcessor paymentProcessor,
+ final ControlPluginRunner controlPluginRunner) {
+ super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, paymentConfig, controlPluginRunner);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/ChargebackControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/ChargebackControlOperation.java
index 07b5344..4836a2b 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/ChargebackControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/ChargebackControlOperation.java
@@ -24,12 +24,18 @@ import org.killbill.billing.payment.api.PaymentApiException;
import org.killbill.billing.payment.core.PaymentProcessor;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
public class ChargebackControlOperation extends OperationControlCallback {
- public ChargebackControlOperation(final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher, final PaymentStateControlContext paymentStateContext, final PaymentProcessor paymentProcessor, final ControlPluginRunner controlPluginRunner) {
- super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ public ChargebackControlOperation(final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
+ final PaymentStateControlContext paymentStateContext,
+ final PaymentProcessor paymentProcessor,
+ final ControlPluginRunner controlPluginRunner) {
+ super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, paymentConfig, controlPluginRunner);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CompletionControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CompletionControlOperation.java
index 6f3e300..d7cdac9 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CompletionControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CompletionControlOperation.java
@@ -20,17 +20,16 @@ package org.killbill.billing.payment.core.sm.control;
import org.killbill.automaton.OperationException;
import org.killbill.automaton.OperationResult;
import org.killbill.billing.control.plugin.api.PaymentApiType;
-import org.killbill.billing.osgi.api.OSGIServiceRegistration;
import org.killbill.billing.payment.api.Payment;
import org.killbill.billing.payment.api.PaymentApiException;
import org.killbill.billing.payment.core.PaymentProcessor;
-import org.killbill.billing.payment.core.ProcessorBase.WithAccountLockCallback;
+import org.killbill.billing.payment.core.ProcessorBase.DispatcherCallback;
import org.killbill.billing.payment.core.sm.control.ControlPluginRunner.DefaultPaymentControlContext;
import org.killbill.billing.payment.dao.PaymentTransactionModelDao;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.payment.dispatcher.PluginDispatcher.PluginDispatcherReturnType;
import org.killbill.billing.control.plugin.api.PaymentControlContext;
-import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
//
@@ -38,17 +37,19 @@ import org.killbill.commons.locker.GlobalLocker;
//
public class CompletionControlOperation extends OperationControlCallback {
- public CompletionControlOperation(final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ public CompletionControlOperation(final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
final PaymentStateControlContext paymentStateContext,
final PaymentProcessor paymentProcessor,
final ControlPluginRunner controlPluginRunner) {
- super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, paymentConfig, controlPluginRunner);
}
@Override
public OperationResult doOperationCallback() throws OperationException {
- return dispatchWithAccountLockAndTimeout(new WithAccountLockCallback<PluginDispatcherReturnType<OperationResult>, OperationException>() {
+ return dispatchWithAccountLockAndTimeout(new DispatcherCallback<PluginDispatcherReturnType<OperationResult>, OperationException>() {
@Override
public PluginDispatcherReturnType<OperationResult> doOperation() throws OperationException {
final PaymentTransactionModelDao transaction = paymentStateContext.getPaymentTransactionModelDao();
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CreditControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CreditControlOperation.java
index 1a071fa..5d2c643 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CreditControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CreditControlOperation.java
@@ -23,12 +23,18 @@ import org.killbill.billing.payment.api.PaymentApiException;
import org.killbill.billing.payment.core.PaymentProcessor;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
public class CreditControlOperation extends OperationControlCallback {
- public CreditControlOperation(final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher, final PaymentStateControlContext paymentStateContext, final PaymentProcessor paymentProcessor, final ControlPluginRunner controlPluginRunner) {
- super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ public CreditControlOperation(final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
+ final PaymentStateControlContext paymentStateContext,
+ final PaymentProcessor paymentProcessor,
+ final ControlPluginRunner controlPluginRunner) {
+ super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, paymentConfig, controlPluginRunner);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java
index a1e8928..add2adf 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java
@@ -39,12 +39,13 @@ import org.killbill.billing.payment.api.PaymentTransaction;
import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.payment.api.TransactionStatus;
import org.killbill.billing.payment.core.PaymentProcessor;
-import org.killbill.billing.payment.core.ProcessorBase.WithAccountLockCallback;
+import org.killbill.billing.payment.core.ProcessorBase.DispatcherCallback;
import org.killbill.billing.payment.core.sm.OperationCallbackBase;
import org.killbill.billing.payment.core.sm.PaymentStateContext;
import org.killbill.billing.payment.core.sm.control.ControlPluginRunner.DefaultPaymentControlContext;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.payment.dispatcher.PluginDispatcher.PluginDispatcherReturnType;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
import org.killbill.commons.locker.LockFailedException;
import org.slf4j.Logger;
@@ -64,8 +65,9 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
final PluginDispatcher<OperationResult> paymentPluginDispatcher,
final PaymentStateControlContext paymentStateContext,
final PaymentProcessor paymentProcessor,
+ final PaymentConfig paymentConfig,
final ControlPluginRunner controlPluginRunner) {
- super(locker, paymentPluginDispatcher, paymentStateContext);
+ super(locker, paymentPluginDispatcher, paymentConfig, paymentStateContext);
this.paymentProcessor = paymentProcessor;
this.controlPluginRunner = controlPluginRunner;
this.paymentStateControlContext = paymentStateContext;
@@ -77,7 +79,7 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
@Override
public OperationResult doOperationCallback() throws OperationException {
- return dispatchWithAccountLockAndTimeout(new WithAccountLockCallback<PluginDispatcherReturnType<OperationResult>, OperationException>() {
+ return dispatchWithAccountLockAndTimeout(new DispatcherCallback<PluginDispatcherReturnType<OperationResult>, OperationException>() {
@Override
public PluginDispatcherReturnType<OperationResult> doOperation() throws OperationException {
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/PurchaseControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/PurchaseControlOperation.java
index 7ad848f..4a766c7 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/PurchaseControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/PurchaseControlOperation.java
@@ -23,12 +23,18 @@ import org.killbill.billing.payment.api.PaymentApiException;
import org.killbill.billing.payment.core.PaymentProcessor;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
public class PurchaseControlOperation extends OperationControlCallback {
- public PurchaseControlOperation(final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher, final PaymentStateControlContext paymentStateContext, final PaymentProcessor paymentProcessor, final ControlPluginRunner controlPluginRunner) {
- super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ public PurchaseControlOperation(final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
+ final PaymentStateControlContext paymentStateContext,
+ final PaymentProcessor paymentProcessor,
+ final ControlPluginRunner controlPluginRunner) {
+ super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, paymentConfig, controlPluginRunner);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/RefundControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/RefundControlOperation.java
index 5f4d7cd..4c60dd3 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/RefundControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/RefundControlOperation.java
@@ -23,12 +23,18 @@ import org.killbill.billing.payment.api.PaymentApiException;
import org.killbill.billing.payment.core.PaymentProcessor;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
public class RefundControlOperation extends OperationControlCallback {
- public RefundControlOperation(final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher, final PaymentStateControlContext paymentStateContext, final PaymentProcessor paymentProcessor, final ControlPluginRunner controlPluginRunner) {
- super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ public RefundControlOperation(final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
+ final PaymentStateControlContext paymentStateContext,
+ final PaymentProcessor paymentProcessor,
+ final ControlPluginRunner controlPluginRunner) {
+ super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, paymentConfig, controlPluginRunner);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/VoidControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/VoidControlOperation.java
index 00200d1..db74fa9 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/VoidControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/VoidControlOperation.java
@@ -23,12 +23,18 @@ import org.killbill.billing.payment.api.PaymentApiException;
import org.killbill.billing.payment.core.PaymentProcessor;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
public class VoidControlOperation extends OperationControlCallback {
- public VoidControlOperation(final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher, final PaymentStateControlContext paymentStateContext, final PaymentProcessor paymentProcessor, final ControlPluginRunner controlPluginRunner) {
- super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ public VoidControlOperation(final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
+ final PaymentStateControlContext paymentStateContext,
+ final PaymentProcessor paymentProcessor,
+ final ControlPluginRunner controlPluginRunner) {
+ super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, paymentConfig, controlPluginRunner);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/OperationCallbackBase.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/OperationCallbackBase.java
index 8ab58ff..34c8c1b 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/OperationCallbackBase.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/OperationCallbackBase.java
@@ -25,9 +25,10 @@ import org.killbill.automaton.OperationException;
import org.killbill.automaton.OperationResult;
import org.killbill.billing.account.api.Account;
import org.killbill.billing.payment.core.ProcessorBase.CallableWithAccountLock;
-import org.killbill.billing.payment.core.ProcessorBase.WithAccountLockCallback;
+import org.killbill.billing.payment.core.ProcessorBase.DispatcherCallback;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.payment.dispatcher.PluginDispatcher.PluginDispatcherReturnType;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,15 +39,18 @@ public abstract class OperationCallbackBase<CallbackOperationResult, CallbackOpe
private final GlobalLocker locker;
private final PluginDispatcher<OperationResult> paymentPluginDispatcher;
+ private final PaymentConfig paymentConfig;
protected final PaymentStateContext paymentStateContext;
protected OperationCallbackBase(final GlobalLocker locker,
final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
final PaymentStateContext paymentStateContext) {
this.locker = locker;
this.paymentPluginDispatcher = paymentPluginDispatcher;
this.paymentStateContext = paymentStateContext;
+ this.paymentConfig = paymentConfig;
}
//
@@ -54,13 +58,14 @@ public abstract class OperationCallbackBase<CallbackOperationResult, CallbackOpe
// The dispatcher may throw a TimeoutException, ExecutionException, or InterruptedException; those will be handled in specific
// callback to eventually throw a OperationException, that will be used to drive the state machine in the right direction.
//
- protected <ExceptionType extends Exception> OperationResult dispatchWithAccountLockAndTimeout(final WithAccountLockCallback<PluginDispatcherReturnType<OperationResult>, ExceptionType> callback) throws OperationException {
+ protected <ExceptionType extends Exception> OperationResult dispatchWithAccountLockAndTimeout(final DispatcherCallback<PluginDispatcherReturnType<OperationResult>, ExceptionType> callback) throws OperationException {
final Account account = paymentStateContext.getAccount();
logger.debug("Dispatching plugin call for account {}", account.getExternalKey());
try {
final Callable<PluginDispatcherReturnType<OperationResult>> task = new CallableWithAccountLock<OperationResult, ExceptionType>(locker,
account.getExternalKey(),
+ paymentConfig,
callback);
final OperationResult operationResult = paymentPluginDispatcher.dispatchWithTimeout(task);
logger.debug("Successful plugin call for account {} with result {}", account.getExternalKey(), operationResult);
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentAutomatonRunner.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentAutomatonRunner.java
index d0f56a0..49702f5 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentAutomatonRunner.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentAutomatonRunner.java
@@ -90,6 +90,7 @@ public class PaymentAutomatonRunner {
protected final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry;
protected final Clock clock;
private final PersistentBus eventBus;
+ private final PaymentConfig paymentConfig;
@Inject
public PaymentAutomatonRunner(final PaymentConfig paymentConfig,
@@ -106,7 +107,7 @@ public class PaymentAutomatonRunner {
this.pluginRegistry = pluginRegistry;
this.clock = clock;
this.eventBus = eventBus;
-
+ this.paymentConfig = paymentConfig;
final long paymentPluginTimeoutSec = TimeUnit.SECONDS.convert(paymentConfig.getPaymentPluginTimeout().getPeriod(), paymentConfig.getPaymentPluginTimeout().getUnit());
this.paymentPluginDispatcher = new PluginDispatcher<OperationResult>(paymentPluginTimeoutSec, executors);
@@ -151,37 +152,37 @@ public class PaymentAutomatonRunner {
final EnteringStateCallback enteringStateCallback;
switch (transactionType) {
case PURCHASE:
- operationCallback = new PurchaseOperation(daoHelper, locker, paymentPluginDispatcher, paymentStateContext);
+ operationCallback = new PurchaseOperation(daoHelper, locker, paymentPluginDispatcher, paymentConfig, paymentStateContext);
leavingStateCallback = new PurchaseInitiated(daoHelper, paymentStateContext);
enteringStateCallback = new PurchaseCompleted(daoHelper, paymentStateContext);
break;
case AUTHORIZE:
- operationCallback = new AuthorizeOperation(daoHelper, locker, paymentPluginDispatcher, paymentStateContext);
+ operationCallback = new AuthorizeOperation(daoHelper, locker, paymentPluginDispatcher, paymentConfig, paymentStateContext);
leavingStateCallback = new AuthorizeInitiated(daoHelper, paymentStateContext);
enteringStateCallback = new AuthorizeCompleted(daoHelper, paymentStateContext);
break;
case CAPTURE:
- operationCallback = new CaptureOperation(daoHelper, locker, paymentPluginDispatcher, paymentStateContext);
+ operationCallback = new CaptureOperation(daoHelper, locker, paymentPluginDispatcher, paymentConfig, paymentStateContext);
leavingStateCallback = new CaptureInitiated(daoHelper, paymentStateContext);
enteringStateCallback = new CaptureCompleted(daoHelper, paymentStateContext);
break;
case VOID:
- operationCallback = new VoidOperation(daoHelper, locker, paymentPluginDispatcher, paymentStateContext);
+ operationCallback = new VoidOperation(daoHelper, locker, paymentPluginDispatcher, paymentConfig, paymentStateContext);
leavingStateCallback = new VoidInitiated(daoHelper, paymentStateContext);
enteringStateCallback = new VoidCompleted(daoHelper, paymentStateContext);
break;
case REFUND:
- operationCallback = new RefundOperation(daoHelper, locker, paymentPluginDispatcher, paymentStateContext);
+ operationCallback = new RefundOperation(daoHelper, locker, paymentPluginDispatcher, paymentConfig, paymentStateContext);
leavingStateCallback = new RefundInitiated(daoHelper, paymentStateContext);
enteringStateCallback = new RefundCompleted(daoHelper, paymentStateContext);
break;
case CREDIT:
- operationCallback = new CreditOperation(daoHelper, locker, paymentPluginDispatcher, paymentStateContext);
+ operationCallback = new CreditOperation(daoHelper, locker, paymentPluginDispatcher, paymentConfig, paymentStateContext);
leavingStateCallback = new CreditInitiated(daoHelper, paymentStateContext);
enteringStateCallback = new CreditCompleted(daoHelper, paymentStateContext);
break;
case CHARGEBACK:
- operationCallback = new ChargebackOperation(daoHelper, locker, paymentPluginDispatcher, paymentStateContext);
+ operationCallback = new ChargebackOperation(daoHelper, locker, paymentPluginDispatcher, paymentConfig, paymentStateContext);
leavingStateCallback = new ChargebackInitiated(daoHelper, paymentStateContext);
enteringStateCallback = new ChargebackCompleted(daoHelper, paymentStateContext);
break;
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/AuthorizeOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/AuthorizeOperation.java
index 2919089..d8eb405 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/AuthorizeOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/AuthorizeOperation.java
@@ -24,6 +24,7 @@ import org.killbill.billing.payment.core.sm.PaymentStateContext;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,9 +34,11 @@ public class AuthorizeOperation extends PaymentOperation {
private final Logger logger = LoggerFactory.getLogger(AuthorizeOperation.class);
public AuthorizeOperation(final PaymentAutomatonDAOHelper daoHelper,
- final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
final PaymentStateContext paymentStateContext) throws PaymentApiException {
- super(locker, daoHelper, paymentPluginDispatcher, paymentStateContext);
+ super(locker, daoHelper, paymentPluginDispatcher, paymentConfig, paymentStateContext);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/CaptureOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/CaptureOperation.java
index 43903b8..e6b67c5 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/CaptureOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/CaptureOperation.java
@@ -24,6 +24,7 @@ import org.killbill.billing.payment.core.sm.PaymentStateContext;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,9 +34,11 @@ public class CaptureOperation extends PaymentOperation {
private final Logger logger = LoggerFactory.getLogger(CaptureOperation.class);
public CaptureOperation(final PaymentAutomatonDAOHelper daoHelper,
- final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
final PaymentStateContext paymentStateContext) throws PaymentApiException {
- super(locker, daoHelper, paymentPluginDispatcher, paymentStateContext);
+ super(locker, daoHelper, paymentPluginDispatcher, paymentConfig, paymentStateContext);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/ChargebackOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/ChargebackOperation.java
index 0585c0f..7193ab1 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/ChargebackOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/ChargebackOperation.java
@@ -30,6 +30,7 @@ import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
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.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,9 +40,11 @@ public class ChargebackOperation extends PaymentOperation {
private final Logger logger = LoggerFactory.getLogger(ChargebackOperation.class);
public ChargebackOperation(final PaymentAutomatonDAOHelper daoHelper,
- final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
final PaymentStateContext paymentStateContext) throws PaymentApiException {
- super(locker, daoHelper, paymentPluginDispatcher, paymentStateContext);
+ super(locker, daoHelper, paymentPluginDispatcher, paymentConfig, paymentStateContext);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/CreditOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/CreditOperation.java
index c206625..53b5634 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/CreditOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/CreditOperation.java
@@ -24,6 +24,7 @@ import org.killbill.billing.payment.core.sm.PaymentStateContext;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,9 +34,11 @@ public class CreditOperation extends PaymentOperation {
private final Logger logger = LoggerFactory.getLogger(CreditOperation.class);
public CreditOperation(final PaymentAutomatonDAOHelper daoHelper,
- final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
final PaymentStateContext paymentStateContext) throws PaymentApiException {
- super(locker, daoHelper, paymentPluginDispatcher, paymentStateContext);
+ super(locker, daoHelper, paymentPluginDispatcher, paymentConfig, paymentStateContext);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentOperation.java
index ba6e48d..4896409 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentOperation.java
@@ -30,7 +30,7 @@ import org.killbill.billing.payment.api.PaymentApiException;
import org.killbill.billing.payment.api.TransactionStatus;
import org.killbill.billing.payment.api.TransactionType;
import org.killbill.billing.payment.core.PaymentTransactionInfoPluginConverter;
-import org.killbill.billing.payment.core.ProcessorBase.WithAccountLockCallback;
+import org.killbill.billing.payment.core.ProcessorBase.DispatcherCallback;
import org.killbill.billing.payment.core.sm.OperationCallbackBase;
import org.killbill.billing.payment.core.sm.PaymentAutomatonDAOHelper;
import org.killbill.billing.payment.core.sm.PaymentStateContext;
@@ -42,6 +42,7 @@ import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
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.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
import org.killbill.commons.locker.LockFailedException;
@@ -59,8 +60,9 @@ public abstract class PaymentOperation extends OperationCallbackBase<PaymentTran
protected PaymentOperation(final GlobalLocker locker,
final PaymentAutomatonDAOHelper daoHelper,
final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
final PaymentStateContext paymentStateContext) {
- super(locker, paymentPluginDispatcher, paymentStateContext);
+ super(locker, paymentPluginDispatcher, paymentConfig, paymentStateContext);
this.daoHelper = daoHelper;
}
@@ -154,7 +156,7 @@ public abstract class PaymentOperation extends OperationCallbackBase<PaymentTran
}
private OperationResult doOperationCallbackWithDispatchAndAccountLock() throws OperationException {
- return dispatchWithAccountLockAndTimeout(new WithAccountLockCallback<PluginDispatcherReturnType<OperationResult>, OperationException>() {
+ return dispatchWithAccountLockAndTimeout(new DispatcherCallback<PluginDispatcherReturnType<OperationResult>, OperationException>() {
@Override
public PluginDispatcherReturnType<OperationResult> doOperation() throws OperationException {
final OperationResult result = doSimpleOperationCallback();
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PurchaseOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PurchaseOperation.java
index 7c9aabb..1ddf4b1 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PurchaseOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PurchaseOperation.java
@@ -24,6 +24,7 @@ import org.killbill.billing.payment.core.sm.PaymentStateContext;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,9 +34,11 @@ public class PurchaseOperation extends PaymentOperation {
private final Logger logger = LoggerFactory.getLogger(PurchaseOperation.class);
public PurchaseOperation(final PaymentAutomatonDAOHelper daoHelper,
- final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
final PaymentStateContext paymentStateContext) throws PaymentApiException {
- super(locker, daoHelper, paymentPluginDispatcher, paymentStateContext);
+ super(locker, daoHelper, paymentPluginDispatcher, paymentConfig, paymentStateContext);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/RefundOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/RefundOperation.java
index 77534c5..22d9239 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/RefundOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/RefundOperation.java
@@ -24,6 +24,7 @@ import org.killbill.billing.payment.core.sm.PaymentStateContext;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,9 +34,11 @@ public class RefundOperation extends PaymentOperation {
private final Logger logger = LoggerFactory.getLogger(RefundOperation.class);
public RefundOperation(final PaymentAutomatonDAOHelper daoHelper,
- final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
final PaymentStateContext paymentStateContext) throws PaymentApiException {
- super(locker, daoHelper, paymentPluginDispatcher, paymentStateContext);
+ super(locker, daoHelper, paymentPluginDispatcher, paymentConfig, paymentStateContext);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/VoidOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/VoidOperation.java
index a188a43..0d776b6 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/VoidOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/VoidOperation.java
@@ -24,6 +24,7 @@ import org.killbill.billing.payment.core.sm.PaymentStateContext;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,9 +34,11 @@ public class VoidOperation extends PaymentOperation {
private final Logger logger = LoggerFactory.getLogger(VoidOperation.class);
public VoidOperation(final PaymentAutomatonDAOHelper daoHelper,
- final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
final PaymentStateContext paymentStateContext) throws PaymentApiException {
- super(locker, daoHelper, paymentPluginDispatcher, paymentStateContext);
+ super(locker, daoHelper, paymentPluginDispatcher, paymentConfig, paymentStateContext);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/PluginControlPaymentAutomatonRunner.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/PluginControlPaymentAutomatonRunner.java
index 4f58817..b15dcdb 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/PluginControlPaymentAutomatonRunner.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/PluginControlPaymentAutomatonRunner.java
@@ -77,6 +77,7 @@ public class PluginControlPaymentAutomatonRunner extends PaymentAutomatonRunner
private final RetryServiceScheduler retryServiceScheduler;
private final PaymentControlStateMachineHelper paymentControlStateMachineHelper;
private final ControlPluginRunner controlPluginRunner;
+ private final PaymentConfig paymentConfig;
@Inject
public PluginControlPaymentAutomatonRunner(final PaymentDao paymentDao, final GlobalLocker locker, final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry,
@@ -89,6 +90,7 @@ public class PluginControlPaymentAutomatonRunner extends PaymentAutomatonRunner
this.retryServiceScheduler = retryServiceScheduler;
this.paymentControlStateMachineHelper = paymentControlStateMachineHelper;
this.controlPluginRunner = controlPluginRunner;
+ this.paymentConfig = paymentConfig;
}
public Payment run(final boolean isApiPayment, final TransactionType transactionType, final Account account, @Nullable final UUID paymentMethodId,
@@ -133,7 +135,7 @@ public class PluginControlPaymentAutomatonRunner extends PaymentAutomatonRunner
public Payment completeRun(final PaymentStateControlContext paymentStateContext) throws PaymentApiException {
try {
- final OperationCallback callback = new CompletionControlOperation(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ final OperationCallback callback = new CompletionControlOperation(locker, paymentPluginDispatcher, paymentConfig, paymentStateContext, paymentProcessor, controlPluginRunner);
final LeavingStateCallback leavingStateCallback = new NoopControlInitiated();
final EnteringStateCallback enteringStateCallback = new DefaultControlCompleted(this, paymentStateContext, paymentControlStateMachineHelper.getRetriedState(), retryServiceScheduler);
@@ -166,25 +168,25 @@ public class PluginControlPaymentAutomatonRunner extends PaymentAutomatonRunner
final OperationCallback callback;
switch (transactionType) {
case AUTHORIZE:
- callback = new AuthorizeControlOperation(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ callback = new AuthorizeControlOperation(locker, paymentPluginDispatcher, paymentConfig, paymentStateContext, paymentProcessor, controlPluginRunner);
break;
case CAPTURE:
- callback = new CaptureControlOperation(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ callback = new CaptureControlOperation(locker, paymentPluginDispatcher, paymentConfig, paymentStateContext, paymentProcessor, controlPluginRunner);
break;
case PURCHASE:
- callback = new PurchaseControlOperation(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ callback = new PurchaseControlOperation(locker, paymentPluginDispatcher, paymentConfig, paymentStateContext, paymentProcessor, controlPluginRunner);
break;
case VOID:
- callback = new VoidControlOperation(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ callback = new VoidControlOperation(locker, paymentPluginDispatcher, paymentConfig, paymentStateContext, paymentProcessor, controlPluginRunner);
break;
case CREDIT:
- callback = new CreditControlOperation(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ callback = new CreditControlOperation(locker, paymentPluginDispatcher, paymentConfig, paymentStateContext, paymentProcessor, controlPluginRunner);
break;
case REFUND:
- callback = new RefundControlOperation(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ callback = new RefundControlOperation(locker, paymentPluginDispatcher, paymentConfig, paymentStateContext, paymentProcessor, controlPluginRunner);
break;
case CHARGEBACK:
- callback = new ChargebackControlOperation(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ callback = new ChargebackControlOperation(locker, paymentPluginDispatcher, paymentConfig, paymentStateContext, paymentProcessor, controlPluginRunner);
break;
default:
throw new IllegalStateException("Unsupported transaction type " + transactionType);
diff --git a/payment/src/main/java/org/killbill/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java b/payment/src/main/java/org/killbill/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java
index 2908799..a194300 100644
--- a/payment/src/main/java/org/killbill/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java
+++ b/payment/src/main/java/org/killbill/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java
@@ -93,6 +93,11 @@ public class DefaultNoOpPaymentProviderPlugin implements NoOpPaymentPluginApi {
}
@Override
+ public void updatePaymentTransactions(final UUID paymentId, final List<PaymentTransactionInfoPlugin> newTransactions) {
+ throw new IllegalStateException("Not implemented");
+ }
+
+ @Override
public PaymentTransactionInfoPlugin authorizePayment(final UUID kbAccountId, final UUID kbPaymentId, final UUID kbTransactionId, final UUID kbPaymentMethodId, final BigDecimal amount, final Currency currency, final Iterable<PluginProperty> properties, final CallContext context)
throws PaymentPluginApiException {
return getInternalNoopPaymentInfoResult(kbPaymentId, kbTransactionId, TransactionType.AUTHORIZE, amount, currency);
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/janitor/TestIncompletePaymentTransactionTask.java b/payment/src/test/java/org/killbill/billing/payment/core/janitor/TestIncompletePaymentTransactionTask.java
index 569070f..9e81218 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/janitor/TestIncompletePaymentTransactionTask.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/janitor/TestIncompletePaymentTransactionTask.java
@@ -35,7 +35,6 @@ public class TestIncompletePaymentTransactionTask extends PaymentTestSuiteNoDB {
@Test(groups = "fast")
public void testGetNextNotificationTime() {
- assertNull(incompletePaymentTransactionTask.getNextNotificationTime(null));
final DateTime initTime = clock.getUTCNow();
// Based on config "15s,1m,3m,1h,1d,1d,1d,1d,1d"
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/MockRetryAuthorizeOperationCallback.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/MockRetryAuthorizeOperationCallback.java
index 3dd00a4..1a8f812 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/MockRetryAuthorizeOperationCallback.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/MockRetryAuthorizeOperationCallback.java
@@ -35,6 +35,7 @@ import org.killbill.billing.payment.dao.PaymentModelDao;
import org.killbill.billing.payment.dao.PaymentTransactionModelDao;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.clock.Clock;
import org.killbill.commons.locker.GlobalLocker;
@@ -46,8 +47,15 @@ public class MockRetryAuthorizeOperationCallback extends AuthorizeControlOperati
private Exception exception;
private OperationResult result;
- public MockRetryAuthorizeOperationCallback(final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher, final PaymentStateControlContext paymentStateContext, final PaymentProcessor paymentProcessor, final ControlPluginRunner controlPluginRunner, final PaymentDao paymentDao, final Clock clock) {
- super(locker, paymentPluginDispatcher, paymentStateContext, paymentProcessor, controlPluginRunner);
+ public MockRetryAuthorizeOperationCallback(final GlobalLocker locker,
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
+ final PaymentStateControlContext paymentStateContext,
+ final PaymentProcessor paymentProcessor,
+ final ControlPluginRunner controlPluginRunner,
+ final PaymentDao paymentDao,
+ final Clock clock) {
+ super(locker, paymentPluginDispatcher, paymentConfig, paymentStateContext, paymentProcessor, controlPluginRunner);
this.paymentDao = paymentDao;
this.clock = clock;
}
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentOperation.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentOperation.java
index 7e4e1b6..1765bef 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentOperation.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentOperation.java
@@ -38,6 +38,7 @@ import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
import org.killbill.billing.payment.plugin.api.PaymentPluginStatus;
import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
import org.killbill.billing.payment.provider.MockPaymentProviderPlugin;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
import org.killbill.commons.locker.memory.MemoryGlobalLocker;
import org.mockito.Mockito;
@@ -125,7 +126,7 @@ public class TestPaymentOperation extends PaymentTestSuiteNoDB {
Mockito.when(paymentDao.getPaymentMethodIncludedDeleted(paymentStateContext.getPaymentMethodId(), internalCallContext)).thenReturn(paymentMethodModelDao);
final PaymentAutomatonDAOHelper daoHelper = new PaymentAutomatonDAOHelper(paymentStateContext, clock.getUTCNow(), paymentDao, registry, internalCallContext, eventBus, paymentSMHelper);
- paymentOperation = new PaymentOperationTest(paymentPluginStatus, daoHelper, locker, paymentPluginDispatcher, paymentStateContext);
+ paymentOperation = new PaymentOperationTest(paymentPluginStatus, daoHelper, locker, paymentPluginDispatcher, paymentConfig, paymentStateContext);
}
private static final class PaymentOperationTest extends PaymentOperation {
@@ -134,8 +135,10 @@ public class TestPaymentOperation extends PaymentTestSuiteNoDB {
public PaymentOperationTest(@Nullable final PaymentPluginStatus paymentPluginStatus,
final PaymentAutomatonDAOHelper daoHelper, final GlobalLocker locker,
- final PluginDispatcher<OperationResult> paymentPluginDispatcher, final PaymentStateContext paymentStateContext) throws PaymentApiException {
- super(locker, daoHelper, paymentPluginDispatcher, paymentStateContext);
+ final PluginDispatcher<OperationResult> paymentPluginDispatcher,
+ final PaymentConfig paymentConfig,
+ final PaymentStateContext paymentStateContext) throws PaymentApiException {
+ super(locker, daoHelper, paymentPluginDispatcher, paymentConfig, paymentStateContext);
this.paymentInfoPlugin = (paymentPluginStatus == null ? null : getPaymentInfoPlugin(paymentPluginStatus));
}
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPluginOperation.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPluginOperation.java
index 9c73489..75e39c3 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPluginOperation.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPluginOperation.java
@@ -20,7 +20,6 @@ package org.killbill.billing.payment.core.sm;
import java.math.BigDecimal;
import java.util.UUID;
import java.util.concurrent.Callable;
-import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -36,12 +35,13 @@ import org.killbill.billing.payment.PaymentTestSuiteNoDB;
import org.killbill.billing.payment.api.PaymentApiException;
import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.payment.api.TransactionType;
-import org.killbill.billing.payment.core.ProcessorBase.WithAccountLockCallback;
+import org.killbill.billing.payment.core.ProcessorBase.DispatcherCallback;
import org.killbill.billing.payment.core.sm.payments.PaymentOperation;
import org.killbill.billing.payment.dispatcher.PluginDispatcher;
import org.killbill.billing.payment.dispatcher.PluginDispatcher.PluginDispatcherReturnType;
import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
+import org.killbill.billing.util.config.PaymentConfig;
import org.killbill.commons.locker.GlobalLocker;
import org.killbill.commons.locker.memory.MemoryGlobalLocker;
import org.mockito.Mockito;
@@ -202,10 +202,10 @@ public class TestPluginOperation extends PaymentTestSuiteNoDB {
final PaymentAutomatonDAOHelper daoHelper = Mockito.mock(PaymentAutomatonDAOHelper.class);
Mockito.when(daoHelper.getPaymentProviderPlugin()).thenReturn(null);
- return new PluginOperationTest(daoHelper, locker, paymentPluginDispatcher, paymentStateContext);
+ return new PluginOperationTest(daoHelper, locker, paymentPluginDispatcher, paymentConfig, paymentStateContext);
}
- private static final class CallbackTest implements WithAccountLockCallback<PluginDispatcherReturnType<OperationResult>, PaymentApiException> {
+ private static final class CallbackTest implements DispatcherCallback<PluginDispatcherReturnType<OperationResult>, PaymentApiException> {
private final AtomicInteger runCount = new AtomicInteger(0);
@@ -274,8 +274,8 @@ public class TestPluginOperation extends PaymentTestSuiteNoDB {
private static final class PluginOperationTest extends PaymentOperation {
- protected PluginOperationTest(final PaymentAutomatonDAOHelper daoHelper, final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher, final PaymentStateContext paymentStateContext) throws PaymentApiException {
- super(locker, daoHelper, paymentPluginDispatcher, paymentStateContext);
+ protected PluginOperationTest(final PaymentAutomatonDAOHelper daoHelper, final GlobalLocker locker, final PluginDispatcher<OperationResult> paymentPluginDispatcher, final PaymentConfig paymentConfig, final PaymentStateContext paymentStateContext) throws PaymentApiException {
+ super(locker, daoHelper, paymentPluginDispatcher, paymentConfig, paymentStateContext);
}
@Override
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestRetryablePayment.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestRetryablePayment.java
index b796607..a64c15a 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestRetryablePayment.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestRetryablePayment.java
@@ -189,6 +189,7 @@ public class TestRetryablePayment extends PaymentTestSuiteNoDB {
mockRetryAuthorizeOperationCallback =
new MockRetryAuthorizeOperationCallback(locker,
runner.getPaymentPluginDispatcher(),
+ paymentConfig,
paymentStateContext,
null,
controlPluginRunner,
diff --git a/payment/src/test/java/org/killbill/billing/payment/provider/MockPaymentProviderPlugin.java b/payment/src/test/java/org/killbill/billing/payment/provider/MockPaymentProviderPlugin.java
index 9e8243d..f3b7088 100644
--- a/payment/src/test/java/org/killbill/billing/payment/provider/MockPaymentProviderPlugin.java
+++ b/payment/src/test/java/org/killbill/billing/payment/provider/MockPaymentProviderPlugin.java
@@ -209,6 +209,13 @@ public class MockPaymentProviderPlugin implements NoOpPaymentPluginApi {
}
@Override
+ public void updatePaymentTransactions(final UUID paymentId, final List<PaymentTransactionInfoPlugin> newTransactions) {
+ if (paymentTransactions.containsKey(paymentId.toString())) {
+ paymentTransactions.put (paymentId.toString(), newTransactions);
+ }
+ }
+
+ @Override
public PaymentTransactionInfoPlugin authorizePayment(final UUID kbAccountId, final UUID kbPaymentId, final UUID kbTransactionId, final UUID kbPaymentMethodId, final BigDecimal amount, final Currency currency, final Iterable<PluginProperty> properties, final CallContext context)
throws PaymentPluginApiException {
return getPaymentTransactionInfoPluginResult(kbPaymentId, kbTransactionId, TransactionType.AUTHORIZE, amount, currency, properties);
diff --git a/payment/src/test/java/org/killbill/billing/payment/TestJanitor.java b/payment/src/test/java/org/killbill/billing/payment/TestJanitor.java
index 1753af8..e99ccaa 100644
--- a/payment/src/test/java/org/killbill/billing/payment/TestJanitor.java
+++ b/payment/src/test/java/org/killbill/billing/payment/TestJanitor.java
@@ -47,6 +47,10 @@ import org.killbill.billing.payment.dao.PaymentAttemptModelDao;
import org.killbill.billing.payment.dao.PaymentTransactionModelDao;
import org.killbill.billing.payment.glue.DefaultPaymentService;
import org.killbill.billing.payment.invoice.InvoicePaymentControlPluginApi;
+import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
+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.platform.api.KillbillConfigSource;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
@@ -55,6 +59,7 @@ import org.killbill.notificationq.api.NotificationEvent;
import org.killbill.notificationq.api.NotificationEventWithMetadata;
import org.killbill.notificationq.api.NotificationQueueService;
import org.killbill.notificationq.api.NotificationQueueService.NoSuchNotificationQueue;
+import org.skife.config.TimeSpan;
import org.skife.jdbi.v2.Handle;
import org.skife.jdbi.v2.tweak.HandleCallback;
import org.testng.Assert;
@@ -393,6 +398,58 @@ public class TestJanitor extends PaymentTestSuiteWithEmbeddedDB {
Assert.assertEquals(updatedPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS);
}
+ // The test will check that when a PENDING entry stays PENDING, we go through all our retries and evebtually give up (no infinite loop of retries)
+ @Test(groups = "slow")
+ public void testPendingEntriesThatDontMove() throws PaymentApiException, EventBusException, NoSuchNotificationQueue, PaymentPluginApiException, InterruptedException {
+
+ final BigDecimal requestedAmount = BigDecimal.TEN;
+ final String paymentExternalKey = "haha";
+ final String transactionExternalKey = "hoho!";
+
+ testListener.pushExpectedEvent(NextEvent.PAYMENT);
+ final Payment payment = paymentApi.createAuthorization(account, account.getPaymentMethodId(), null, requestedAmount, account.getCurrency(), paymentExternalKey,
+ transactionExternalKey, ImmutableList.<PluginProperty>of(), callContext);
+ testListener.assertListenerStatus();
+
+ final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
+
+ // Artificially move the transaction status to PENDING AND update state on the plugin as well
+ final List<PaymentTransactionInfoPlugin> paymentTransactions = mockPaymentProviderPlugin.getPaymentInfo(account.getId(), payment.getId(), ImmutableList.<PluginProperty>of(), callContext);
+ final PaymentTransactionInfoPlugin oTx = paymentTransactions.remove(0);
+ final PaymentTransactionInfoPlugin updatePaymentTransaction = new DefaultNoOpPaymentInfoPlugin(oTx.getKbPaymentId(), oTx.getKbTransactionPaymentId(), oTx.getTransactionType(), oTx.getAmount(), oTx.getCurrency(), oTx.getCreatedDate(), oTx.getCreatedDate(), PaymentPluginStatus.PENDING, null);
+ paymentTransactions.add(updatePaymentTransaction);
+ mockPaymentProviderPlugin.updatePaymentTransactions(payment.getId(), paymentTransactions);
+
+ final String paymentStateName = paymentSMHelper.getPendingStateForTransaction(TransactionType.AUTHORIZE).toString();
+
+
+ testListener.pushExpectedEvent(NextEvent.PAYMENT);
+ paymentDao.updatePaymentAndTransactionOnCompletion(account.getId(), payment.getId(), TransactionType.AUTHORIZE, paymentStateName, paymentStateName,
+ payment.getTransactions().get(0).getId(), TransactionStatus.PENDING, requestedAmount, account.getCurrency(),
+ "loup", "chat", internalCallContext);
+ testListener.assertListenerStatus();
+
+ // 15s,1m,3m,1h,1d,1d,1d,1d,1d
+ for (TimeSpan cur : paymentConfig.getIncompleteTransactionsRetries()) {
+ // Verify there is a notification to retry updating the value
+ assertEquals(getPendingNotificationCnt(internalCallContext), 1);
+
+ clock.addDeltaFromReality(cur.getMillis() + 1);
+
+ // We add a sleep here to make sure the notification gets processed. Note that calling assertNotificationsCompleted would not work
+ // because there is a point in time where the notification queue is empty (showing notification was processed), but the processing of the notification
+ // will itself enter a new notification, and so the synchronization is difficult without writing *too much code*.
+ Thread.sleep(1000);
+
+ //assertNotificationsCompleted(internalCallContext, 5);
+ final Payment updatedPayment = paymentApi.getPayment(payment.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ Assert.assertEquals(updatedPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.PENDING);
+ }
+
+ assertEquals(getPendingNotificationCnt(internalCallContext), 0);
+ }
+
+
private List<PluginProperty> createPropertiesForInvoice(final Invoice invoice) {
final List<PluginProperty> result = new ArrayList<PluginProperty>();
result.add(new PluginProperty(InvoicePaymentControlPluginApi.PROP_IPCD_INVOICE_ID, invoice.getId().toString(), false));
@@ -441,5 +498,15 @@ public class TestJanitor extends PaymentTestSuiteWithEmbeddedDB {
fail("Test failed ", e);
}
}
+
+ private int getPendingNotificationCnt(final InternalCallContext internalCallContext) {
+ try {
+ return notificationQueueService.getNotificationQueue(DefaultPaymentService.SERVICE_NAME, Janitor.QUEUE_NAME).getFutureOrInProcessingNotificationForSearchKeys(internalCallContext.getAccountRecordId(), internalCallContext.getTenantRecordId()).size();
+ } catch (final Exception e) {
+ fail("Test failed ", e);
+ }
+ // Not reached..
+ return -1;
+ }
}
diff --git a/util/src/main/java/org/killbill/billing/util/config/InvoiceConfig.java b/util/src/main/java/org/killbill/billing/util/config/InvoiceConfig.java
index f42a635..19b3368 100644
--- a/util/src/main/java/org/killbill/billing/util/config/InvoiceConfig.java
+++ b/util/src/main/java/org/killbill/billing/util/config/InvoiceConfig.java
@@ -26,22 +26,27 @@ public interface InvoiceConfig extends KillbillConfig {
@Config("org.killbill.invoice.maxNumberOfMonthsInFuture")
@Default("36")
@Description("Maximum target date to consider when generating an invoice")
- public int getNumberOfMonthsInFuture();
+ int getNumberOfMonthsInFuture();
@Config("org.killbill.invoice.emailNotificationsEnabled")
@Default("false")
@Description("Whether to send email notifications on invoice creation (for configured accounts)")
- public boolean isEmailNotificationsEnabled();
+ boolean isEmailNotificationsEnabled();
@Config("org.killbill.invoice.dryRunNotificationSchedule")
@Default("0s")
@Description("DryRun invoice notification time before targetDate (ignored if set to 0s)")
- public TimeSpan getDryRunNotificationSchedule();
+ TimeSpan getDryRunNotificationSchedule();
@Config("org.killbill.invoice.readMaxRawUsagePreviousPeriod")
@Default("2")
@Description("Maximum number of past billing periods we use to fetch raw usage data (usage optimization)")
- public int getMaxRawUsagePreviousPeriod();
+ int getMaxRawUsagePreviousPeriod();
+
+ @Config("org.killbill.invoice.globalLock.retries")
+ @Default("50")
+ @Description("Maximum number of times the system will retry to grab global lock (with a 100ms wait each time)")
+ int getMaxGlobalLockRetries();
}
diff --git a/util/src/main/java/org/killbill/billing/util/config/PaymentConfig.java b/util/src/main/java/org/killbill/billing/util/config/PaymentConfig.java
index 7b630c6..9eadf60 100644
--- a/util/src/main/java/org/killbill/billing/util/config/PaymentConfig.java
+++ b/util/src/main/java/org/killbill/billing/util/config/PaymentConfig.java
@@ -29,60 +29,65 @@ public interface PaymentConfig extends KillbillConfig {
// See ExternalPaymentProviderPlugin.PLUGIN_NAME
@Default("__external_payment__")
@Description("Default payment provider to use")
- public String getDefaultPaymentProvider();
+ String getDefaultPaymentProvider();
@Config("org.killbill.payment.retry.days")
@Default("8,8,8")
@Description("Specify the number of payment retries along with the interval in days between payment retries when payment failures occur")
- public List<Integer> getPaymentFailureRetryDays();
+ List<Integer> getPaymentFailureRetryDays();
@Config("org.killbill.payment.failure.retry.start.sec")
@Default("300")
@Description("Specify the interval of time in seconds before retrying a payment that failed due to a plugin failure (gateway is down, transient error, ...")
- public int getPluginFailureInitialRetryInSec();
+ int getPluginFailureInitialRetryInSec();
@Config("org.killbill.payment.failure.retry.multiplier")
@Default("2")
@Description("Specify the multiplier to apply between in retry before retrying a payment that failed due to a plugin failure (gateway is down, transient error, ...")
- public int getPluginFailureRetryMultiplier();
+ int getPluginFailureRetryMultiplier();
@Config("org.killbill.payment.failure.retry.max.attempts")
@Default("8")
@Description("Specify the max number of attempts before retrying a payment that failed due to a plugin failure (gateway is down, transient error, ...\"")
- public int getPluginFailureRetryMaxAttempts();
+ int getPluginFailureRetryMaxAttempts();
@Config("org.killbill.payment.plugin.timeout")
@Default("30s")
@Description("Timeout for each payment attempt")
- public TimeSpan getPaymentPluginTimeout();
+ TimeSpan getPaymentPluginTimeout();
@Config("org.killbill.payment.plugin.threads.nb")
@Default("10")
@Description("Number of threads for plugin executor dispatcher")
- public int getPaymentPluginThreadNb();
+ int getPaymentPluginThreadNb();
@Config("org.killbill.payment.janitor.attempts.delay")
@Default("12h")
@Description("Delay before which unresolved attempt should be retried")
- public TimeSpan getIncompleteAttemptsTimeSpanDelay();
+ TimeSpan getIncompleteAttemptsTimeSpanDelay();
@Config("org.killbill.payment.janitor.transactions.retries")
@Default("15s,1m,3m,1h,1d,1d,1d,1d,1d")
@Description("Delay before which unresolved transactions should be retried")
- public List<TimeSpan> getIncompleteTransactionsRetries();
+ List<TimeSpan> getIncompleteTransactionsRetries();
@Config("org.killbill.payment.janitor.rate")
@Default("1h")
@Description("Rate at which janitor tasks are scheduled")
- public TimeSpan getJanitorRunningRate();
+ TimeSpan getJanitorRunningRate();
@Config("org.killbill.payment.invoice.plugin")
@Default("")
@Description("Default payment control plugin names")
- public List<String> getPaymentControlPluginNames();
+ List<String> getPaymentControlPluginNames();
+
+ @Config("org.killbill.payment.globalLock.retries")
+ @Default("50")
+ @Description("Maximum number of times the system will retry to grab global lock (with a 100ms wait each time)")
+ int getMaxGlobalLockRetries();
@Config("org.killbill.payment.off")
@Default("false")
@Description("Whether the payment subsystem is off")
- public boolean isPaymentOff();
+ boolean isPaymentOff();
}