killbill-aplcache

Details

diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/config/MultiTenantNotificationConfig.java b/profiles/killbill/src/main/java/org/killbill/billing/server/config/MultiTenantNotificationConfig.java
new file mode 100644
index 0000000..cfea29b
--- /dev/null
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/config/MultiTenantNotificationConfig.java
@@ -0,0 +1,68 @@
+/*
+ * 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
+ * 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.server.config;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.payment.glue.PaymentModule;
+import org.killbill.billing.util.config.definition.NotificationConfig;
+import org.killbill.billing.util.config.tenant.CacheConfig;
+import org.killbill.billing.util.config.tenant.MultiTenantConfigBase;
+import org.skife.config.Param;
+import org.skife.config.TimeSpan;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+public class MultiTenantNotificationConfig extends MultiTenantConfigBase implements NotificationConfig {
+
+    private final NotificationConfig staticConfig;
+
+    @Inject
+    public MultiTenantNotificationConfig(@Named(PaymentModule.STATIC_CONFIG) final NotificationConfig staticConfig, final CacheConfig cacheConfig) {
+        super(cacheConfig);
+        this.staticConfig = staticConfig;
+    }
+
+    @Override
+    protected Method getConfigStaticMethod(final String methodName) {
+        try {
+            return NotificationConfig.class.getMethod(methodName, InternalTenantContext.class);
+        } catch (final NoSuchMethodException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public List<TimeSpan> getPushNotificationsRetries() {
+        return staticConfig.getPushNotificationsRetries();
+    }
+
+    @Override
+    public List<TimeSpan> getPushNotificationsRetries(@Param("dummy") final InternalTenantContext tenantContext) {
+        final Method method = new Object() {}.getClass().getEnclosingMethod();
+
+        final String result = getStringTenantConfig(method.getName(), tenantContext);
+        if (result != null) {
+            return convertToListTimeSpan(result, method.getName());
+        }
+        return getPushNotificationsRetries();
+    }
+}
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillbillServerModule.java b/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillbillServerModule.java
index cd01301..ff6de44 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillbillServerModule.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillbillServerModule.java
@@ -58,6 +58,7 @@ import org.killbill.billing.platform.api.KillbillConfigSource;
 import org.killbill.billing.server.DefaultServerService;
 import org.killbill.billing.server.ServerService;
 import org.killbill.billing.server.config.KillbillServerConfig;
+import org.killbill.billing.server.config.MultiTenantNotificationConfig;
 import org.killbill.billing.server.filters.ResponseCorsFilter;
 import org.killbill.billing.server.notifications.PushNotificationListener;
 import org.killbill.billing.server.notifications.PushNotificationRetryService;
@@ -96,10 +97,12 @@ import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
 import ch.qos.logback.classic.helpers.MDCInsertingServletFilter;
 import com.google.inject.multibindings.Multibinder;
+import com.google.inject.name.Names;
 
 public class KillbillServerModule extends KillbillPlatformModule {
 
     public static final String SHIRO_DATA_SOURCE_ID = "shiro";
+    public static final String STATIC_CONFIG = "StaticConfig";
 
     public KillbillServerModule(final ServletContext servletContext, final KillbillServerConfig serverConfig, final KillbillConfigSource configSource) {
         super(servletContext, serverConfig, configSource);
@@ -212,7 +215,8 @@ public class KillbillServerModule extends KillbillPlatformModule {
     protected void configurePushNotification() {
         final ConfigurationObjectFactory factory = new ConfigurationObjectFactory(skifeConfigSource);
         final NotificationConfig notificationConfig = factory.build(NotificationConfig.class);
-        bind(NotificationConfig.class).toInstance(notificationConfig);
+        bind(NotificationConfig.class).annotatedWith(Names.named(STATIC_CONFIG)).toInstance(notificationConfig);
+        bind(NotificationConfig.class).to(MultiTenantNotificationConfig.class).asEagerSingleton();
         bind(PushNotificationListener.class).asEagerSingleton();
         bind(PushNotificationRetryService.class).asEagerSingleton();
         bind(ServerService.class).to(DefaultServerService.class).asEagerSingleton();
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/notifications/PushNotificationKey.java b/profiles/killbill/src/main/java/org/killbill/billing/server/notifications/PushNotificationKey.java
index f77799e..e72dec3 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/notifications/PushNotificationKey.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/notifications/PushNotificationKey.java
@@ -31,7 +31,7 @@ public class PushNotificationKey implements NotificationEvent {
     private final String eventType;
     private final String objectType;
     private final UUID objectId;
-    private Integer attemptNumber;
+    private final int attemptNumber;
     private final String url;
 
     @JsonCreator
@@ -40,7 +40,7 @@ public class PushNotificationKey implements NotificationEvent {
                                @JsonProperty("eventType") final String eventType,
                                @JsonProperty("objectType") final String objectType,
                                @JsonProperty("objectId") final UUID objectId,
-                               @JsonProperty("attemptNumber")  final Integer attemptNumber,
+                               @JsonProperty("attemptNumber")  final int attemptNumber,
                                @JsonProperty("url") final String url) {
         this.tenantId = tenantId;
         this.accountId = accountId;
@@ -51,8 +51,9 @@ public class PushNotificationKey implements NotificationEvent {
         this.url = url;
     }
 
-    public void increaseAttemptNumber() {
-        this.attemptNumber = ++attemptNumber;
+    public PushNotificationKey(final PushNotificationKey key, final int attemptNumber) {
+        this(key.getTenantId(), key.getAccountId(), key.getEventType(), key.getObjectType(), key.getObjectId(),
+             attemptNumber, key.getUrl());
     }
 
     public UUID getTenantId() {
@@ -76,7 +77,7 @@ public class PushNotificationKey implements NotificationEvent {
     }
 
     public Integer getAttemptNumber() {
-        return attemptNumber == null ? 0 : attemptNumber;
+        return attemptNumber;
     }
 
     public String getUrl() {
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/notifications/PushNotificationListener.java b/profiles/killbill/src/main/java/org/killbill/billing/server/notifications/PushNotificationListener.java
index b6e968c..afa18cf 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/notifications/PushNotificationListener.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/notifications/PushNotificationListener.java
@@ -28,7 +28,6 @@ import javax.inject.Inject;
 
 import org.joda.time.DateTime;
 import org.killbill.billing.ObjectType;
-import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.jaxrs.json.NotificationJson;
 import org.killbill.billing.notification.plugin.api.ExtBusEvent;
@@ -118,11 +117,12 @@ public class PushNotificationListener {
         final NotificationJson notification = new NotificationJson(event);
         final String body = mapper.writeValueAsString(notification);
         for (final String cur : callbacks) {
-            doPost(tenantId, cur, body, TIMEOUT_NOTIFICATION);
+            doPost(tenantId, cur, body, notification, TIMEOUT_NOTIFICATION, 0);
         }
     }
 
-    private boolean doPost(final UUID tenantId, final String url, final String body, final int timeoutSec) {
+    private boolean doPost(final UUID tenantId, final String url, final String body, final NotificationJson notification,
+                           final int timeoutSec, final int attemptRetryNumber) {
         final BoundRequestBuilder builder = httpClient.preparePost(url);
         builder.setBody(body == null ? "{}" : body);
         builder.addHeader(HTTP_HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON);
@@ -138,81 +138,48 @@ public class PushNotificationListener {
                     });
             response = futureStatus.get(timeoutSec, TimeUnit.SECONDS);
         } catch (final TimeoutException toe) {
-            saveRetryPushNotificationInQueue(tenantId, url, body);
+            saveRetryPushNotificationInQueue(tenantId, url, notification, attemptRetryNumber);
             return false;
         } catch (final Exception e) {
             log.warn("Failed to push notification url='{}', tenantId='{}'", url, tenantId, e);
             return false;
         }
 
-        if ((response.getStatusCode() == 301) || (response.getStatusCode() == 500)) {
-            saveRetryPushNotificationInQueue(tenantId, url, body);
+        if (response.getStatusCode() >= 200 && response.getStatusCode() < 300) {
+            return true;
+        } else {
+            saveRetryPushNotificationInQueue(tenantId, url, notification, attemptRetryNumber);
             return false;
         }
-
-        return response.getStatusCode() >= 200 && response.getStatusCode() < 300;
     }
 
-    public void resendPushNotification(final PushNotificationKey key, final InternalCallContext callContext) throws JsonProcessingException {
+    public void resendPushNotification(final PushNotificationKey key) throws JsonProcessingException {
 
         final NotificationJson notification = new NotificationJson(key.getEventType() != null ? key.getEventType().toString() : null,
                                                                    key.getAccountId() != null ? key.getAccountId().toString() : null,
                                                                    key.getObjectType() != null ? key.getObjectType().toString() : null,
                                                                    key.getObjectId() != null ? key.getObjectId().toString() : null);
         final String body = mapper.writeValueAsString(notification);
-
-        final BoundRequestBuilder builder = httpClient.preparePost(key.getUrl());
-        builder.setBody(body == null ? "{}" : body);
-        builder.addHeader(HTTP_HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON);
-
-        final Response response;
-        try {
-            final ListenableFuture<Response> futureStatus =
-                    builder.execute(new AsyncCompletionHandler<Response>() {
-                        @Override
-                        public Response onCompleted(final Response response) throws Exception {
-                            return response;
-                        }
-                    });
-            response = futureStatus.get(TIMEOUT_NOTIFICATION, TimeUnit.SECONDS);
-        } catch (final TimeoutException toe) {
-            saveRetryPushNotificationInQueue(key);
-            return;
-        } catch (final Exception e) {
-            log.warn("Failed to push notification url='{}', tenantId='{}'", key.getUrl(), key.getTenantId(), e);
-            return;
-        }
-
-        if ((response.getStatusCode() == 301) || (response.getStatusCode() == 500)) {
-            saveRetryPushNotificationInQueue(key);
-        }
+        doPost(key.getTenantId(), key.getUrl(), body, notification, TIMEOUT_NOTIFICATION, key.getAttemptNumber());
     }
 
-    private void saveRetryPushNotificationInQueue(final UUID tenantId, final String url, final String body) {
-        try {
-            final NotificationJson notificationJson = mapper.readValue(body, NotificationJson.class);
-            final PushNotificationKey key = new PushNotificationKey(tenantId,
-                                                                    notificationJson.getAccountId() != null ? UUID.fromString(notificationJson.getAccountId()) : null,
-                                                                    notificationJson.getEventType(),
-                                                                    notificationJson.getObjectType(),
-                                                                    notificationJson.getObjectId() != null ? UUID.fromString(notificationJson.getObjectId()) : null,
-                                                                    0, url);
-            saveRetryPushNotificationInQueue(key);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
+    private void saveRetryPushNotificationInQueue(final UUID tenantId, final String url, final NotificationJson notificationJson, final int attemptRetryNumber) {
+        final PushNotificationKey key = new PushNotificationKey(tenantId,
+                                                                notificationJson.getAccountId() != null ? UUID.fromString(notificationJson.getAccountId()) : null,
+                                                                notificationJson.getEventType(),
+                                                                notificationJson.getObjectType(),
+                                                                notificationJson.getObjectId() != null ? UUID.fromString(notificationJson.getObjectId()) : null,
+                                                                attemptRetryNumber + 1, url);
 
-    private void saveRetryPushNotificationInQueue(final PushNotificationKey key) {
-        final TenantContext tenantContext = contextFactory.createTenantContext(key.getTenantId());
-        key.increaseAttemptNumber();
+        final TenantContext tenantContext = contextFactory.createTenantContext(tenantId);
         final DateTime nextNotificationTime = getNextNotificationTime(key.getAttemptNumber(), internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(tenantContext));
 
         if (nextNotificationTime == null) {
             log.warn("Max attempt number reached for push notification url='{}', tenantId='{}'", key.getUrl(), key.getTenantId());
             return;
         }
-        log.debug("Push notification is schedule to send at {} for url='{}', tenantId='{}'", nextNotificationTime, key.getUrl(), key.getTenantId());
+        log.debug("Push notification is scheduled to send at {} for url='{}', tenantId='{}'", nextNotificationTime, key.getUrl(), key.getTenantId());
+
         final Long accountRecordId = internalCallContextFactory.getRecordIdFromObject(key.getAccountId(), ObjectType.ACCOUNT, tenantContext);
         final Long tenantRecordId = internalCallContextFactory.getRecordIdFromObject(key.getTenantId(), ObjectType.TENANT, tenantContext);
         try {
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/notifications/PushNotificationRetryService.java b/profiles/killbill/src/main/java/org/killbill/billing/server/notifications/PushNotificationRetryService.java
index 94e805d..5284a21 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/notifications/PushNotificationRetryService.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/notifications/PushNotificationRetryService.java
@@ -20,11 +20,8 @@ package org.killbill.billing.server.notifications;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
-import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.server.DefaultServerService;
-import org.killbill.billing.util.callcontext.CallOrigin;
 import org.killbill.billing.util.callcontext.InternalCallContextFactory;
-import org.killbill.billing.util.callcontext.UserType;
 import org.killbill.notificationq.api.NotificationEvent;
 import org.killbill.notificationq.api.NotificationQueue;
 import org.killbill.notificationq.api.NotificationQueueService;
@@ -69,9 +66,8 @@ public class PushNotificationRetryService {
                                                                                   return;
                                                                               }
                                                                               final PushNotificationKey key = (PushNotificationKey) notificationKey;
-                                                                              final InternalCallContext callContext = internalCallContextFactory.createInternalCallContext(tenantRecordId, accountRecordId, retryService, CallOrigin.INTERNAL, UserType.SYSTEM, userToken);
                                                                               try {
-                                                                                  pushNotificationListener.resendPushNotification(key, callContext);
+                                                                                  pushNotificationListener.resendPushNotification(key);
                                                                               } catch (JsonProcessingException e) {
                                                                                   log.error("Failed to push notification url='{}', tenantId='{}'", key.getUrl(), key.getTenantId(), e);
                                                                               }