killbill-memoizeit

server: add more logging around exceptions when generating

11/1/2016 1:42:23 PM

Details

diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java
index b4fc7de..265a1fa 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2016 Groupon, Inc
+ * Copyright 2014-2016 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
@@ -443,52 +443,70 @@ public class AccountResource extends JaxRsResourceBase {
             final Future<List<InvoicePayment>> futureInvoicePaymentsCallable = executor.submit(invoicePaymentsCallable);
             final Future<List<Payment>> futurePaymentsCallable = executor.submit(paymentsCallable);
             final Future<AccountAuditLogs> futureAuditsCallable = executor.submit(auditsCallable);
-
-            try {
-                final long ini = System.currentTimeMillis();
-                do {
-                    bundles = (bundles == null) ? runCallableAndHandleTimeout(futureBundlesCallable, 100) : bundles;
-                    invoices = (invoices == null) ? runCallableAndHandleTimeout(futureInvoicesCallable, 100) : invoices;
-                    invoicePayments = (invoicePayments == null) ? runCallableAndHandleTimeout(futureInvoicePaymentsCallable, 100) : invoicePayments;
-                    payments = (payments == null) ? runCallableAndHandleTimeout(futurePaymentsCallable, 100) : payments;
-                    accountAuditLogs = (accountAuditLogs == null) ? runCallableAndHandleTimeout(futureAuditsCallable, 100) : accountAuditLogs;
-                } while ((System.currentTimeMillis() - ini < jaxrsConfig.getJaxrsTimeout().getMillis()) &&
-                         (bundles == null || invoices == null || invoicePayments == null || payments == null || accountAuditLogs == null));
-
-                if (bundles == null || invoices == null || invoicePayments == null || payments == null || accountAuditLogs == null) {
-                    Response.status(Status.SERVICE_UNAVAILABLE).build();
-                }
-            } catch (final InterruptedException e) {
-                handleCallableException(e, ImmutableList.<Future>of(futureBundlesCallable, futureInvoicesCallable, futureInvoicePaymentsCallable, futurePaymentsCallable, futureAuditsCallable));
-            } catch (final ExecutionException e) {
-                handleCallableException(e.getCause(), ImmutableList.<Future>of(futureBundlesCallable, futureInvoicesCallable, futureInvoicePaymentsCallable, futurePaymentsCallable, futureAuditsCallable));
+            final ImmutableList<Future> toBeCancelled = ImmutableList.<Future>of(futureBundlesCallable, futureInvoicesCallable, futureInvoicePaymentsCallable, futurePaymentsCallable, futureAuditsCallable);
+            final int timeoutMsec = 100;
+
+            final long ini = System.currentTimeMillis();
+            do {
+                bundles = (bundles == null) ? waitOnFutureAndHandleTimeout("bundles", futureBundlesCallable, timeoutMsec, toBeCancelled) : bundles;
+                invoices = (invoices == null) ? waitOnFutureAndHandleTimeout("invoices", futureInvoicesCallable, timeoutMsec, toBeCancelled) : invoices;
+                invoicePayments = (invoicePayments == null) ? waitOnFutureAndHandleTimeout("invoicePayments", futureInvoicePaymentsCallable, timeoutMsec, toBeCancelled) : invoicePayments;
+                payments = (payments == null) ? waitOnFutureAndHandleTimeout("payments", futurePaymentsCallable, timeoutMsec, toBeCancelled) : payments;
+                accountAuditLogs = (accountAuditLogs == null) ? waitOnFutureAndHandleTimeout("accountAuditLogs", futureAuditsCallable, timeoutMsec, toBeCancelled) : accountAuditLogs;
+            } while ((System.currentTimeMillis() - ini < jaxrsConfig.getJaxrsTimeout().getMillis()) &&
+                     (bundles == null || invoices == null || invoicePayments == null || payments == null || accountAuditLogs == null));
+
+            if (bundles == null || invoices == null || invoicePayments == null || payments == null || accountAuditLogs == null) {
+                Response.status(Status.SERVICE_UNAVAILABLE).build();
             }
-
         } else {
-            try {
-                invoices = invoicesCallable.call();
-                payments = paymentsCallable.call();
-                bundles = bundlesCallable.call();
-                accountAuditLogs = auditsCallable.call();
-                invoicePayments = invoicePaymentsCallable.call();
-            } catch (final Exception e) {
-                handleCallableException(e);
-            }
+            invoices = runCallable("invoices", invoicesCallable);
+            payments = runCallable("payments", paymentsCallable);
+            bundles = runCallable("bundles", bundlesCallable);
+            accountAuditLogs = runCallable("accountAuditLogs", auditsCallable);
+            invoicePayments = runCallable("invoicePayments", invoicePaymentsCallable);
         }
 
         json = new AccountTimelineJson(account, invoices, payments, invoicePayments, bundles, accountAuditLogs);
         return Response.status(Status.OK).entity(json).build();
     }
 
-    private <T> T runCallableAndHandleTimeout(final Future<T> future, final long timeoutMsec) throws ExecutionException, InterruptedException {
+    private <T> T waitOnFutureAndHandleTimeout(final String logSuffix, final Future<T> future, final long timeoutMsec, final Iterable<Future> toBeCancelled) throws PaymentApiException, AccountApiException, InvoiceApiException, SubscriptionApiException {
+        try {
+            return waitOnFutureAndHandleTimeout(future, timeoutMsec);
+        } catch (final InterruptedException e) {
+            log.warn("InterruptedException while retrieving {}", logSuffix, e);
+            handleCallableException(e, toBeCancelled);
+        } catch (final ExecutionException e) {
+            log.warn("ExecutionException while retrieving {}", logSuffix, e);
+            handleCallableException(e.getCause(), toBeCancelled);
+        }
+
+        // Never reached
+        return null;
+    }
+
+    private <T> T waitOnFutureAndHandleTimeout(final Future<T> future, final long timeoutMsec) throws ExecutionException, InterruptedException {
         try {
             return future.get(timeoutMsec, TimeUnit.MILLISECONDS);
-        } catch (TimeoutException e) {
+        } catch (final TimeoutException e) {
             return null;
         }
     }
 
-    private void handleCallableException(final Throwable causeOrException, final List<Future> toBeCancelled) throws AccountApiException, SubscriptionApiException, PaymentApiException, InvoiceApiException {
+    private <T> T runCallable(final String logSuffix, final Callable<T> callable) throws PaymentApiException, AccountApiException, InvoiceApiException, SubscriptionApiException {
+        try {
+            return callable.call();
+        } catch (final Exception e) {
+            log.warn("InterruptedException while retrieving {}", logSuffix, e);
+            handleCallableException(e);
+        }
+
+        // Never reached
+        return null;
+    }
+
+    private void handleCallableException(final Throwable causeOrException, final Iterable<Future> toBeCancelled) throws AccountApiException, SubscriptionApiException, PaymentApiException, InvoiceApiException {
         for (final Future f : toBeCancelled) {
             f.cancel(true);
         }
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccountTimeline.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccountTimeline.java
index 66eb996..b0a42f3 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccountTimeline.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccountTimeline.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2016 Groupon, Inc
+ * Copyright 2014-2016 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
@@ -26,6 +26,8 @@ import javax.annotation.Nullable;
 
 import org.joda.time.DateTime;
 import org.joda.time.LocalDate;
+import org.killbill.billing.client.KillBillClientException;
+import org.killbill.billing.client.RequestOptions;
 import org.killbill.billing.client.model.Account;
 import org.killbill.billing.client.model.AccountTimeline;
 import org.killbill.billing.client.model.AuditLog;
@@ -42,6 +44,10 @@ import org.killbill.billing.util.audit.ChangeType;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.HashMultimap;
+
+import static org.killbill.billing.jaxrs.resources.JaxrsResource.QUERY_PARALLEL;
+
 public class TestAccountTimeline extends TestJaxrsBase {
 
     private static final String PAYMENT_REQUEST_PROCESSOR = "PaymentRequestProcessor";
@@ -53,7 +59,7 @@ public class TestAccountTimeline extends TestJaxrsBase {
 
         final Account accountJson = createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
 
-        final AccountTimeline timeline = killBillClient.getAccountTimeline(accountJson.getAccountId());
+        final AccountTimeline timeline = getAccountTimeline(accountJson.getAccountId(), AuditLevel.NONE);
         Assert.assertEquals(timeline.getPayments().size(), 1);
         Assert.assertEquals(timeline.getInvoices().size(), 2);
         Assert.assertEquals(timeline.getBundles().size(), 1);
@@ -113,7 +119,7 @@ public class TestAccountTimeline extends TestJaxrsBase {
     private void verifyPayments(final UUID accountId, final DateTime startTime, final DateTime endTime,
                                 final BigDecimal refundAmount, final BigDecimal chargebackAmount) throws Exception {
         for (final AuditLevel auditLevel : AuditLevel.values()) {
-            final AccountTimeline timeline = killBillClient.getAccountTimeline(accountId, auditLevel);
+            final AccountTimeline timeline = getAccountTimeline(accountId, auditLevel);
 
             Assert.assertEquals(timeline.getPayments().size(), 1);
             final InvoicePayment payment = timeline.getPayments().get(0);
@@ -183,7 +189,7 @@ public class TestAccountTimeline extends TestJaxrsBase {
 
     private void verifyInvoices(final UUID accountId, final DateTime startTime, final DateTime endTime) throws Exception {
         for (final AuditLevel auditLevel : AuditLevel.values()) {
-            final AccountTimeline timeline = killBillClient.getAccountTimeline(accountId, auditLevel);
+            final AccountTimeline timeline = getAccountTimeline(accountId, auditLevel);
 
             // Verify invoices
             Assert.assertEquals(timeline.getInvoices().size(), 3);
@@ -209,7 +215,7 @@ public class TestAccountTimeline extends TestJaxrsBase {
 
     private void verifyCredits(final UUID accountId, final DateTime startTime, final DateTime endTime, final BigDecimal creditAmount) throws Exception {
         for (final AuditLevel auditLevel : AuditLevel.values()) {
-            final AccountTimeline timeline = killBillClient.getAccountTimeline(accountId, auditLevel);
+            final AccountTimeline timeline = getAccountTimeline(accountId, auditLevel);
 
             // Verify credits
             final List<Credit> credits = timeline.getInvoices().get(1).getCredits();
@@ -229,7 +235,7 @@ public class TestAccountTimeline extends TestJaxrsBase {
 
     private void verifyBundles(final UUID accountId, final DateTime startTime, final DateTime endTime) throws Exception {
         for (final AuditLevel auditLevel : AuditLevel.values()) {
-            final AccountTimeline timeline = killBillClient.getAccountTimeline(accountId, auditLevel);
+            final AccountTimeline timeline = getAccountTimeline(accountId, auditLevel);
 
             // Verify bundles
             Assert.assertEquals(timeline.getBundles().size(), 1);
@@ -298,4 +304,17 @@ public class TestAccountTimeline extends TestJaxrsBase {
         Assert.assertEquals(auditLogJson.getComments(), comments);
         Assert.assertEquals(auditLogJson.getChangedBy(), changedBy);
     }
+
+    private AccountTimeline getAccountTimeline(final UUID accountId, final AuditLevel auditLevel) throws KillBillClientException {
+        final AccountTimeline accountTimeline = killBillClient.getAccountTimeline(accountId, auditLevel, RequestOptions.empty());
+
+        // Verify also the parallel path
+        final HashMultimap<String, String> queryParams = HashMultimap.<String, String>create();
+        queryParams.put(QUERY_PARALLEL, "true");
+        final RequestOptions requestOptions = RequestOptions.builder().withQueryParams(queryParams).build();
+        final AccountTimeline accountTimelineInParallel = killBillClient.getAccountTimeline(accountId, auditLevel, requestOptions);
+        Assert.assertEquals(accountTimelineInParallel, accountTimeline);
+
+        return accountTimeline;
+    }
 }