killbill-memoizeit

Make IncompletePaymentTransactionTask config dynamic (System

7/10/2015 2:42:27 PM

Details

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 201eddd..1547008 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
@@ -53,7 +53,9 @@ import org.killbill.clock.Clock;
 import org.killbill.commons.locker.GlobalLocker;
 import org.killbill.notificationq.api.NotificationEvent;
 import org.killbill.notificationq.api.NotificationQueue;
+import org.skife.config.TimeSpan;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.base.Supplier;
@@ -62,21 +64,6 @@ import com.google.common.collect.Iterables;
 
 public class IncompletePaymentTransactionTask extends CompletionTaskBase<PaymentTransactionModelDao> {
 
-    private final static long MILLIS_TO_SEC = 1000L;
-    private final static long SEC_TO_HOUR = 3600L;
-    private final static long HOURS_TO_DAY = 24L;
-
-    private final static List<Long> RETRY_ATTEMPTS = ImmutableList.<Long>of((3L * MILLIS_TO_SEC), // 3 min
-                                                                            (10L * MILLIS_TO_SEC), // 10 min
-                                                                            (1L * SEC_TO_HOUR * MILLIS_TO_SEC), // 1 hour
-                                                                            (HOURS_TO_DAY * SEC_TO_HOUR * MILLIS_TO_SEC), // 7 times every day
-                                                                            (HOURS_TO_DAY * SEC_TO_HOUR * MILLIS_TO_SEC),
-                                                                            (HOURS_TO_DAY * SEC_TO_HOUR * MILLIS_TO_SEC),
-                                                                            (HOURS_TO_DAY * SEC_TO_HOUR * MILLIS_TO_SEC),
-                                                                            (HOURS_TO_DAY * SEC_TO_HOUR * MILLIS_TO_SEC),
-                                                                            (HOURS_TO_DAY * SEC_TO_HOUR * MILLIS_TO_SEC),
-                                                                            (HOURS_TO_DAY * SEC_TO_HOUR * MILLIS_TO_SEC));
-
     private static final ImmutableList<TransactionStatus> TRANSACTION_STATUSES_TO_CONSIDER = ImmutableList.<TransactionStatus>builder()
                                                                                                           .add(TransactionStatus.PENDING)
                                                                                                           .add(TransactionStatus.UNKNOWN)
@@ -250,12 +237,15 @@ public class IncompletePaymentTransactionTask extends CompletionTaskBase<Payment
         return pluginApi;
     }
 
-    private DateTime getNextNotificationTime(@Nullable final Integer attemptNumber) {
-        if (attemptNumber == null || attemptNumber > RETRY_ATTEMPTS.size()) {
+    @VisibleForTesting
+    DateTime getNextNotificationTime(@Nullable final Integer attemptNumber) {
+
+        final List<TimeSpan> retries = paymentConfig.getIncompleteTransactionsRetries();
+        if (attemptNumber == null || attemptNumber > retries.size()) {
             return null;
         }
-        final long nextDelay = RETRY_ATTEMPTS.get(attemptNumber - 1);
-        return clock.getUTCNow().plusMillis((int) nextDelay);
+        final TimeSpan nextDelay = retries.get(attemptNumber - 1);
+        return clock.getUTCNow().plusMillis((int) nextDelay.getMillis());
     }
 
     private void insertNewNotificationForUnresolvedTransactionIfNeeded(final UUID paymentTransactionId, @Nullable final Integer attemptNumber, @Nullable final UUID userToken, final Long accountRecordId, final Long tenantRecordId) {
@@ -270,14 +260,4 @@ public class IncompletePaymentTransactionTask extends CompletionTaskBase<Payment
             }
         }
     }
-
-    private DateTime getCreatedDateBefore() {
-        final long delayBeforeNowMs = paymentConfig.getIncompleteTransactionsTimeSpanDelay().getMillis();
-        return clock.getUTCNow().minusMillis((int) delayBeforeNowMs);
-    }
-
-    private DateTime getCreatedDateAfter() {
-        final long delayBeforeNowMs = paymentConfig.getIncompleteTransactionsTimeSpanGiveup().getMillis();
-        return clock.getUTCNow().minusMillis((int) delayBeforeNowMs);
-    }
 }
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/janitor/Janitor.java b/payment/src/main/java/org/killbill/billing/payment/core/janitor/Janitor.java
index 95c0be3..3b06de1 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/janitor/Janitor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/janitor/Janitor.java
@@ -17,7 +17,6 @@
 
 package org.killbill.billing.payment.core.janitor;
 
-import java.io.IOException;
 import java.util.UUID;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -26,12 +25,9 @@ import javax.inject.Inject;
 import javax.inject.Named;
 
 import org.joda.time.DateTime;
-import org.killbill.billing.events.PaymentErrorInternalEvent;
-import org.killbill.billing.events.PaymentInfoInternalEvent;
 import org.killbill.billing.events.PaymentInternalEvent;
 import org.killbill.billing.payment.glue.DefaultPaymentService;
 import org.killbill.billing.payment.glue.PaymentModule;
-import org.killbill.billing.util.callcontext.InternalCallContextFactory;
 import org.killbill.billing.util.config.PaymentConfig;
 import org.killbill.notificationq.api.NotificationEvent;
 import org.killbill.notificationq.api.NotificationQueue;
@@ -57,7 +53,6 @@ public class Janitor {
     private final PaymentConfig paymentConfig;
     private final IncompletePaymentAttemptTask incompletePaymentAttemptTask;
     private final IncompletePaymentTransactionTask incompletePaymentTransactionTask;
-    private final InternalCallContextFactory internalCallContextFactory;
 
     private NotificationQueue janitorQueue;
 
@@ -68,14 +63,12 @@ public class Janitor {
                    final NotificationQueueService notificationQueueService,
                    @Named(PaymentModule.JANITOR_EXECUTOR_NAMED) final ScheduledExecutorService janitorExecutor,
                    final IncompletePaymentAttemptTask incompletePaymentAttemptTask,
-                   final IncompletePaymentTransactionTask incompletePaymentTransactionTask,
-                   final InternalCallContextFactory internalCallContextFactory) {
+                   final IncompletePaymentTransactionTask incompletePaymentTransactionTask) {
         this.notificationQueueService = notificationQueueService;
         this.janitorExecutor = janitorExecutor;
         this.paymentConfig = paymentConfig;
         this.incompletePaymentAttemptTask = incompletePaymentAttemptTask;
         this.incompletePaymentTransactionTask = incompletePaymentTransactionTask;
-        this.internalCallContextFactory = internalCallContextFactory;
         this.isStopped = false;
     }
 
@@ -85,7 +78,7 @@ public class Janitor {
                                                                         new NotificationQueueHandler() {
                                                                             @Override
                                                                             public void handleReadyNotification(final NotificationEvent notificationKey, final DateTime eventDateTime, final UUID userToken, final Long accountRecordId, final Long tenantRecordId) {
-                                                                                if (! (notificationKey instanceof JanitorNotificationKey)) {
+                                                                                if (!(notificationKey instanceof JanitorNotificationKey)) {
                                                                                     log.error("Janitor service received an unexpected event type {}" + notificationKey.getClass().getName());
                                                                                     return;
 
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
new file mode 100644
index 0000000..ec7a4ee
--- /dev/null
+++ b/payment/src/test/java/org/killbill/billing/payment/core/janitor/TestIncompletePaymentTransactionTask.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.payment.core.janitor;
+
+import org.joda.time.DateTime;
+import org.killbill.billing.payment.PaymentTestSuiteNoDB;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.inject.Inject;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+public class TestIncompletePaymentTransactionTask extends PaymentTestSuiteNoDB {
+
+    @Inject
+    protected IncompletePaymentTransactionTask incompletePaymentTransactionTask;
+
+    @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"
+        for (int i = 1; i < 10; i++) {
+            final DateTime nextTime = incompletePaymentTransactionTask.getNextNotificationTime(i);
+            assertNotNull(nextTime);
+            assertTrue(nextTime.compareTo(initTime) > 0);
+            if (i == 0) {
+                assertTrue(nextTime.compareTo(initTime.plusSeconds(3).plusSeconds(1)) < 0);
+            } else if (i == 1) {
+                assertTrue(nextTime.compareTo(initTime.plusMinutes(1).plusSeconds(1)) < 0);
+            } else if (i == 2) {
+                assertTrue(nextTime.compareTo(initTime.plusMinutes(3).plusSeconds(1)) < 0);
+            } else if (i == 3) {
+                assertTrue(nextTime.compareTo(initTime.plusHours(1).plusSeconds(1)) < 0);
+            } else if (i == 4) {
+                assertTrue(nextTime.compareTo(initTime.plusDays(1).plusSeconds(1)) < 0);
+            } else if (i == 5) {
+                assertTrue(nextTime.compareTo(initTime.plusDays(1).plusSeconds(1)) < 0);
+            } else if (i == 6) {
+                assertTrue(nextTime.compareTo(initTime.plusDays(1).plusSeconds(1)) < 0);
+            } else if (i == 7) {
+                assertTrue(nextTime.compareTo(initTime.plusDays(1).plusSeconds(1)) < 0);
+            } else if (i == 8) {
+                assertTrue(nextTime.compareTo(initTime.plusDays(1).plusSeconds(1)) < 0);
+            }
+        }
+        assertNull(incompletePaymentTransactionTask.getNextNotificationTime(10));
+    }
+}
\ No newline at end of file
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 e0fb8bf..7b630c6 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
@@ -66,16 +66,10 @@ public interface PaymentConfig extends KillbillConfig {
     @Description("Delay before which unresolved attempt should be retried")
     public TimeSpan getIncompleteAttemptsTimeSpanDelay();
 
-    @Config("org.killbill.payment.janitor.transactions.delay")
-    @Default("3m")
+    @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 TimeSpan getIncompleteTransactionsTimeSpanDelay();
-
-
-    @Config("org.killbill.payment.janitor.transactions.giveup")
-    @Default("7d")
-    @Description("Delay after which unresolved transactions should be abandoned")
-    public TimeSpan getIncompleteTransactionsTimeSpanGiveup();
+    public List<TimeSpan> getIncompleteTransactionsRetries();
 
     @Config("org.killbill.payment.janitor.rate")
     @Default("1h")