killbill-aplcache

overdue: Fixes #51. Move private overdue api getOverdueStateFor

3/17/2016 8:58:32 PM

Details

diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationBase.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationBase.java
index ab221ba..5136b19 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationBase.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationBase.java
@@ -74,7 +74,7 @@ import org.killbill.billing.lifecycle.api.Lifecycle;
 import org.killbill.billing.lifecycle.glue.BusModule;
 import org.killbill.billing.mock.MockAccountBuilder;
 import org.killbill.billing.osgi.config.OSGIConfig;
-import org.killbill.billing.overdue.OverdueInternalApi;
+import org.killbill.billing.overdue.api.OverdueApi;
 import org.killbill.billing.overdue.api.OverdueConfig;
 import org.killbill.billing.overdue.caching.OverdueConfigCache;
 import org.killbill.billing.overdue.listener.OverdueListener;
@@ -177,7 +177,7 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB {
     protected SubscriptionBaseTimelineApi repairApi;
 
     @Inject
-    protected OverdueInternalApi overdueUserApi;
+    protected OverdueApi overdueUserApi;
 
     @Inject
     protected InvoiceUserApi invoiceUserApi;
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 78e0552..692900c 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
@@ -82,7 +82,7 @@ import org.killbill.billing.jaxrs.json.PaymentTransactionJson;
 import org.killbill.billing.jaxrs.json.TagJson;
 import org.killbill.billing.jaxrs.util.Context;
 import org.killbill.billing.jaxrs.util.JaxrsUriBuilder;
-import org.killbill.billing.overdue.OverdueInternalApi;
+import org.killbill.billing.overdue.api.OverdueApi;
 import org.killbill.billing.overdue.api.OverdueApiException;
 import org.killbill.billing.overdue.api.OverdueState;
 import org.killbill.billing.overdue.config.api.OverdueException;
@@ -138,7 +138,7 @@ public class AccountResource extends JaxRsResourceBase {
     private final SubscriptionApi subscriptionApi;
     private final InvoiceUserApi invoiceApi;
     private final InvoicePaymentApi invoicePaymentApi;
-    private final OverdueInternalApi overdueApi;
+    private final OverdueApi overdueApi;
     private final PaymentConfig paymentConfig;
     private final JaxrsExecutors jaxrsExecutors;
     private final JaxrsConfig jaxrsConfig;
@@ -153,7 +153,7 @@ public class AccountResource extends JaxRsResourceBase {
                            final AuditUserApi auditUserApi,
                            final CustomFieldUserApi customFieldUserApi,
                            final SubscriptionApi subscriptionApi,
-                           final OverdueInternalApi overdueApi,
+                           final OverdueApi overdueApi,
                            final Clock clock,
                            final PaymentConfig paymentConfig,
                            final JaxrsExecutors jaxrsExecutors,
@@ -368,7 +368,6 @@ public class AccountResource extends JaxRsResourceBase {
         return Response.status(Status.INTERNAL_SERVER_ERROR).build();
     }
 
-
     @TimedResource
     @GET
     @Path("/{accountId:" + UUID_PATTERN + "}/" + TIMELINE)
@@ -792,7 +791,6 @@ public class AccountResource extends JaxRsResourceBase {
         return Response.status(Status.OK).build();
     }
 
-
     @TimedResource
     @PUT
     @Consumes(APPLICATION_JSON)
@@ -964,7 +962,7 @@ public class AccountResource extends JaxRsResourceBase {
         final TenantContext tenantContext = context.createContext(request);
 
         final Account account = accountUserApi.getAccountById(UUID.fromString(accountId), tenantContext);
-        final OverdueState overdueState = overdueApi.getOverdueStateFor(account, tenantContext);
+        final OverdueState overdueState = overdueApi.getOverdueStateFor(account.getId(), tenantContext);
 
         return Response.status(Status.OK).entity(new OverdueStateJson(overdueState, paymentConfig)).build();
     }
@@ -1059,7 +1057,6 @@ public class AccountResource extends JaxRsResourceBase {
         return createTagResponse(accountId, tags, auditMode, tenantContext);
     }
 
-
     @TimedResource
     @POST
     @Path("/{accountId:" + UUID_PATTERN + "}/" + TAGS)
@@ -1169,7 +1166,7 @@ public class AccountResource extends JaxRsResourceBase {
                                                                                }
                                                                            }
                                                                           )
-                                                    .orNull();
+                .orNull();
         if (existingEmail == null) {
             accountUserApi.addEmail(accountId, json.toAccountEmail(UUIDs.randomUUID()), callContext);
         }
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/api/DefaultOverdueApi.java b/overdue/src/main/java/org/killbill/billing/overdue/api/DefaultOverdueApi.java
index 8540b0e..580e4f9 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/api/DefaultOverdueApi.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/api/DefaultOverdueApi.java
@@ -17,10 +17,19 @@
 
 package org.killbill.billing.overdue.api;
 
+import java.util.UUID;
+
 import javax.inject.Inject;
 
 import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.entitlement.api.BlockingState;
+import org.killbill.billing.entitlement.api.BlockingStateType;
+import org.killbill.billing.junction.BlockingInternalApi;
+import org.killbill.billing.overdue.OverdueService;
 import org.killbill.billing.overdue.caching.OverdueConfigCache;
+import org.killbill.billing.overdue.config.DefaultOverdueConfig;
+import org.killbill.billing.overdue.config.api.OverdueStateSet;
+import org.killbill.billing.overdue.wrapper.OverdueWrapper;
 import org.killbill.billing.tenant.api.TenantApiException;
 import org.killbill.billing.tenant.api.TenantKV.TenantKey;
 import org.killbill.billing.tenant.api.TenantUserApi;
@@ -31,15 +40,18 @@ import org.killbill.billing.util.callcontext.TenantContext;
 public class DefaultOverdueApi implements OverdueApi {
 
     private final OverdueConfigCache overdueConfigCache;
+    private final BlockingInternalApi blockingInternalApi;
     private final InternalCallContextFactory internalCallContextFactory;
     private final TenantUserApi tenantApi;
 
     @Inject
     public DefaultOverdueApi(final OverdueConfigCache overdueConfigCache,
                              final TenantUserApi tenantApi,
+                             final BlockingInternalApi blockingInternalApi,
                              final InternalCallContextFactory internalCallContextFactory) {
         this.overdueConfigCache = overdueConfigCache;
         this.tenantApi = tenantApi;
+        this.blockingInternalApi = blockingInternalApi;
         this.internalCallContextFactory = internalCallContextFactory;
     }
 
@@ -64,6 +76,16 @@ public class DefaultOverdueApi implements OverdueApi {
         }
     }
 
+    @Override
+    public OverdueState getOverdueStateFor(final UUID accountId, final TenantContext tenantContext) throws OverdueApiException {
+        final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(accountId, tenantContext);
+        final BlockingState blockingStateForService = blockingInternalApi.getBlockingStateForService(accountId, BlockingStateType.ACCOUNT, OverdueService.OVERDUE_SERVICE_NAME, internalTenantContext);
+        final String stateName = blockingStateForService != null ? blockingStateForService.getStateName() : OverdueWrapper.CLEAR_STATE_NAME;
+        final OverdueConfig overdueConfig = overdueConfigCache.getOverdueConfig(internalTenantContext);
+        final OverdueStateSet states = ((DefaultOverdueConfig) overdueConfig).getOverdueStatesAccount();
+        return states.findState(stateName);
+    }
+
     private InternalTenantContext createInternalTenantContext(final TenantContext tenantContext) {
         // Only tenantRecordId will be populated -- this is important to always create the (ehcache) key the same way
         return internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(tenantContext);
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/glue/DefaultOverdueModule.java b/overdue/src/main/java/org/killbill/billing/overdue/glue/DefaultOverdueModule.java
index 9c613e5..930c774 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/glue/DefaultOverdueModule.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/glue/DefaultOverdueModule.java
@@ -19,11 +19,9 @@
 package org.killbill.billing.overdue.glue;
 
 import org.killbill.billing.glue.OverdueModule;
-import org.killbill.billing.overdue.OverdueInternalApi;
 import org.killbill.billing.overdue.OverdueProperties;
 import org.killbill.billing.overdue.OverdueService;
 import org.killbill.billing.overdue.api.DefaultOverdueApi;
-import org.killbill.billing.overdue.api.DefaultOverdueInternalApi;
 import org.killbill.billing.overdue.api.OverdueApi;
 import org.killbill.billing.overdue.applicator.OverdueEmailGenerator;
 import org.killbill.billing.overdue.applicator.formatters.DefaultOverdueEmailFormatterFactory;
@@ -95,7 +93,6 @@ public class DefaultOverdueModule extends KillBillModule implements OverdueModul
 
     @Override
     public void installOverdueUserApi() {
-        bind(OverdueInternalApi.class).to(DefaultOverdueInternalApi.class).asEagerSingleton();
         bind(OverdueApi.class).to(DefaultOverdueApi.class).asEagerSingleton();
     }
 
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java b/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java
index 47b4071..867b81f 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java
@@ -20,14 +20,26 @@ package org.killbill.billing.overdue.listener;
 
 import java.util.UUID;
 
+import javax.inject.Named;
+
 import org.killbill.billing.ObjectType;
 import org.killbill.billing.callcontext.InternalCallContext;
+import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.events.ControlTagCreationInternalEvent;
 import org.killbill.billing.events.ControlTagDeletionInternalEvent;
 import org.killbill.billing.events.InvoiceAdjustmentInternalEvent;
 import org.killbill.billing.events.InvoicePaymentErrorInternalEvent;
 import org.killbill.billing.events.InvoicePaymentInfoInternalEvent;
-import org.killbill.billing.overdue.OverdueInternalApi;
+import org.killbill.billing.overdue.api.OverdueApiException;
+import org.killbill.billing.overdue.api.OverdueConfig;
+import org.killbill.billing.overdue.caching.OverdueConfigCache;
+import org.killbill.billing.overdue.config.DefaultOverdueConfig;
+import org.killbill.billing.overdue.config.DefaultOverdueState;
+import org.killbill.billing.overdue.glue.DefaultOverdueModule;
+import org.killbill.billing.overdue.notification.OverdueAsyncBusNotificationKey;
+import org.killbill.billing.overdue.notification.OverdueAsyncBusNotificationKey.OverdueAsyncBusNotificationAction;
+import org.killbill.billing.overdue.notification.OverdueAsyncBusNotifier;
+import org.killbill.billing.overdue.notification.OverduePoster;
 import org.killbill.billing.util.cache.Cachable.CacheType;
 import org.killbill.billing.util.cache.CacheControllerDispatcher;
 import org.killbill.billing.util.callcontext.CallOrigin;
@@ -36,6 +48,7 @@ import org.killbill.billing.util.callcontext.UserType;
 import org.killbill.billing.util.dao.NonEntityDao;
 import org.killbill.billing.util.tag.ControlTagType;
 import org.killbill.bus.api.BusEvent;
+import org.killbill.clock.Clock;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -47,39 +60,40 @@ public class OverdueListener {
 
     private static final Logger log = LoggerFactory.getLogger(OverdueListener.class);
 
-    private final OverdueInternalApi overdueInternalApi;
     private final InternalCallContextFactory internalCallContextFactory;
     private final CacheControllerDispatcher cacheControllerDispatcher;
-
+    private final Clock clock;
+    private final OverduePoster asyncPoster;
+    private final OverdueConfigCache overdueConfigCache;
     private final NonEntityDao nonEntityDao;
 
     @Inject
-    public OverdueListener(final OverdueInternalApi overdueInternalApi,
-                           final NonEntityDao nonEntityDao,
+    public OverdueListener(final NonEntityDao nonEntityDao,
                            final CacheControllerDispatcher cacheControllerDispatcher,
+                           final Clock clock,
+                           @Named(DefaultOverdueModule.OVERDUE_NOTIFIER_ASYNC_BUS_NAMED)  final OverduePoster asyncPoster,
+                           final OverdueConfigCache overdueConfigCache,
                            final InternalCallContextFactory internalCallContextFactory) {
-        this.overdueInternalApi = overdueInternalApi;
         this.nonEntityDao = nonEntityDao;
+        this.clock = clock;
+        this.asyncPoster = asyncPoster;
+        this.overdueConfigCache = overdueConfigCache;
         this.cacheControllerDispatcher = cacheControllerDispatcher;
         this.internalCallContextFactory = internalCallContextFactory;
     }
 
-
-
-
     @AllowConcurrentEvents
     @Subscribe
     public void handleTagInsert(final ControlTagCreationInternalEvent event) {
         if (event.getTagDefinition().getName().equals(ControlTagType.OVERDUE_ENFORCEMENT_OFF.toString()) && event.getObjectType() == ObjectType.ACCOUNT) {
-            final InternalCallContext callContext = createCallContext(event.getUserToken(), event.getSearchKey1(), event.getSearchKey2());
-            overdueInternalApi.scheduleOverdueClear(event.getObjectId(), callContext);
+            final InternalCallContext internalCallContext = createCallContext(event.getUserToken(), event.getSearchKey1(), event.getSearchKey2());
+            insertBusEventIntoNotificationQueue(event.getObjectId(), OverdueAsyncBusNotificationAction.CLEAR, internalCallContext);
         } else if (event.getTagDefinition().getName().equals(ControlTagType.WRITTEN_OFF.toString()) && event.getObjectType() == ObjectType.INVOICE) {
             final UUID accountId = nonEntityDao.retrieveIdFromObject(event.getSearchKey1(), ObjectType.ACCOUNT, cacheControllerDispatcher.getCacheController(CacheType.OBJECT_ID));
             insertBusEventIntoNotificationQueue(accountId, event);
         }
     }
 
-
     @AllowConcurrentEvents
     @Subscribe
     public void handleTagRemoval(final ControlTagDeletionInternalEvent event) {
@@ -113,11 +127,42 @@ public class OverdueListener {
     }
 
     private void insertBusEventIntoNotificationQueue(final UUID accountId, final BusEvent event) {
-        final InternalCallContext callContext = createCallContext(event.getUserToken(), event.getSearchKey1(), event.getSearchKey2());
-        overdueInternalApi.scheduleOverdueRefresh(accountId, callContext);
+        final InternalCallContext internalCallContext = createCallContext(event.getUserToken(), event.getSearchKey1(), event.getSearchKey2());
+        insertBusEventIntoNotificationQueue(accountId, OverdueAsyncBusNotificationAction.REFRESH, internalCallContext);
     }
 
     private InternalCallContext createCallContext(final UUID userToken, final Long accountRecordId, final Long tenantRecordId) {
         return internalCallContextFactory.createInternalCallContext(tenantRecordId, accountRecordId, "OverdueService", CallOrigin.INTERNAL, UserType.SYSTEM, userToken);
     }
+
+    private void insertBusEventIntoNotificationQueue(final UUID accountId, final OverdueAsyncBusNotificationAction action, final InternalCallContext callContext) {
+        final boolean shouldInsertNotification = shouldInsertNotification(callContext);
+
+        if (shouldInsertNotification) {
+            final OverdueAsyncBusNotificationKey notificationKey = new OverdueAsyncBusNotificationKey(accountId, action);
+            asyncPoster.insertOverdueNotification(accountId, clock.getUTCNow(), OverdueAsyncBusNotifier.OVERDUE_ASYNC_BUS_NOTIFIER_QUEUE, notificationKey, callContext);
+        }
+    }
+
+    // Optimization: don't bother running the Overdue machinery if it's disabled
+    private boolean shouldInsertNotification(final InternalTenantContext internalTenantContext) {
+        OverdueConfig overdueConfig;
+        try {
+            overdueConfig = overdueConfigCache.getOverdueConfig(internalTenantContext);
+        } catch (final OverdueApiException e) {
+            log.warn("Failed to extract overdue config for tenant " + internalTenantContext.getTenantRecordId());
+            overdueConfig = null;
+        }
+        if (overdueConfig == null || overdueConfig.getOverdueStatesAccount() == null || overdueConfig.getOverdueStatesAccount().getStates() == null) {
+            return false;
+        }
+
+        for (final DefaultOverdueState state : ((DefaultOverdueConfig) overdueConfig).getOverdueStatesAccount().getStates()) {
+            if (state.getConditionEvaluation() != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
 }
diff --git a/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteNoDB.java b/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteNoDB.java
index 8e90891..0e1f5e5 100644
--- a/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteNoDB.java
+++ b/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteNoDB.java
@@ -25,6 +25,7 @@ import org.killbill.billing.account.api.AccountInternalApi;
 import org.killbill.billing.invoice.api.InvoiceInternalApi;
 import org.killbill.billing.junction.BlockingInternalApi;
 import org.killbill.billing.lifecycle.api.BusService;
+import org.killbill.billing.overdue.api.OverdueApi;
 import org.killbill.billing.overdue.applicator.OverdueBusListenerTester;
 import org.killbill.billing.overdue.applicator.OverdueStateApplicator;
 import org.killbill.billing.overdue.caching.OverdueCacheInvalidationCallback;
@@ -86,7 +87,7 @@ public abstract class OverdueTestSuiteNoDB extends GuicyKillbillTestSuiteNoDB {
     @Inject
     protected OverdueStateApplicator applicator;
     @Inject
-    protected OverdueInternalApi overdueApi;
+    protected OverdueApi overdueApi;
     @Inject
     protected OverdueProperties overdueProperties;
     @Inject
diff --git a/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteWithEmbeddedDB.java b/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteWithEmbeddedDB.java
index 1253410..f2b590d 100644
--- a/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteWithEmbeddedDB.java
+++ b/overdue/src/test/java/org/killbill/billing/overdue/OverdueTestSuiteWithEmbeddedDB.java
@@ -25,6 +25,7 @@ import org.killbill.billing.account.api.AccountInternalApi;
 import org.killbill.billing.invoice.api.InvoiceInternalApi;
 import org.killbill.billing.junction.BlockingInternalApi;
 import org.killbill.billing.lifecycle.api.BusService;
+import org.killbill.billing.overdue.api.OverdueApi;
 import org.killbill.billing.overdue.applicator.OverdueBusListenerTester;
 import org.killbill.billing.overdue.applicator.OverdueStateApplicator;
 import org.killbill.billing.overdue.caching.OverdueConfigCache;
@@ -87,7 +88,7 @@ public abstract class OverdueTestSuiteWithEmbeddedDB extends GuicyKillbillTestSu
     @Inject
     protected OverdueStateApplicator applicator;
     @Inject
-    protected OverdueInternalApi overdueApi;
+    protected OverdueApi overdueApi;
     @Inject
     protected OverdueProperties overdueProperties;
     @Inject
diff --git a/util/src/test/java/org/killbill/billing/mock/glue/MockOverdueModule.java b/util/src/test/java/org/killbill/billing/mock/glue/MockOverdueModule.java
index 0a88273..381bb9e 100644
--- a/util/src/test/java/org/killbill/billing/mock/glue/MockOverdueModule.java
+++ b/util/src/test/java/org/killbill/billing/mock/glue/MockOverdueModule.java
@@ -19,9 +19,7 @@
 package org.killbill.billing.mock.glue;
 
 import org.killbill.billing.glue.OverdueModule;
-import org.killbill.billing.overdue.OverdueInternalApi;
 import org.killbill.billing.overdue.api.OverdueApi;
-import org.killbill.billing.overdue.api.OverdueConfig;
 import org.killbill.billing.platform.api.KillbillConfigSource;
 import org.killbill.billing.util.glue.KillBillModule;
 import org.mockito.Mockito;
@@ -37,11 +35,9 @@ public class MockOverdueModule extends KillBillModule implements OverdueModule {
 
     @Override
     public void installOverdueUserApi() {
-        bind(OverdueInternalApi.class).toInstance(Mockito.mock(OverdueInternalApi.class));
         bind(OverdueApi.class).toInstance(Mockito.mock(OverdueApi.class));
     }
 
-
     @Override
     protected void configure() {
         installOverdueUserApi();