killbill-memoizeit

#304 - Moved new methods from TestResource to AdminResource -

8/16/2016 2:11:52 PM

Details

diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
index 979d223..be7a776 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
@@ -23,10 +23,12 @@ import javax.inject.Inject;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 
@@ -44,6 +46,7 @@ import org.killbill.billing.payment.api.TransactionStatus;
 import org.killbill.billing.util.api.AuditUserApi;
 import org.killbill.billing.util.api.CustomFieldUserApi;
 import org.killbill.billing.util.api.TagUserApi;
+import org.killbill.billing.util.cache.Cachable.CacheType;
 import org.killbill.billing.util.callcontext.CallContext;
 import org.killbill.clock.Clock;
 
@@ -55,6 +58,8 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Ehcache;
 
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 
@@ -64,11 +69,13 @@ import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 public class AdminResource extends JaxRsResourceBase {
 
     private final AdminPaymentApi adminPaymentApi;
+    private final CacheManager cacheManager;
 
     @Inject
-    public AdminResource(final JaxrsUriBuilder uriBuilder, final TagUserApi tagUserApi, final CustomFieldUserApi customFieldUserApi, final AuditUserApi auditUserApi, final AccountUserApi accountUserApi, final PaymentApi paymentApi, final AdminPaymentApi adminPaymentApi, final Clock clock, final Context context) {
+    public AdminResource(final JaxrsUriBuilder uriBuilder, final TagUserApi tagUserApi, final CustomFieldUserApi customFieldUserApi, final AuditUserApi auditUserApi, final AccountUserApi accountUserApi, final PaymentApi paymentApi, final AdminPaymentApi adminPaymentApi, final CacheManager cacheManager, final Clock clock, final Context context) {
         super(uriBuilder, tagUserApi, customFieldUserApi, auditUserApi, accountUserApi, paymentApi, null, clock, context);
         this.adminPaymentApi = adminPaymentApi;
+        this.cacheManager = cacheManager;
     }
 
 
@@ -104,4 +111,89 @@ public class AdminResource extends JaxRsResourceBase {
         return Response.status(Status.OK).build();
     }
 
+    @POST
+    @Path("/" + CACHE)
+    @Produces(APPLICATION_JSON)
+    @ApiOperation(value = "Invalidates the given Cache if specified, otherwise invalidates all caches")
+    @ApiResponses(value = {@ApiResponse(code = 400, message = "Cache name does not exist or is not alive")})
+    public Response invalidatesCache(@QueryParam("cacheName") final String cacheName,
+                                    @javax.ws.rs.core.Context final HttpServletRequest request) {
+        if (null != cacheName && !cacheName.isEmpty()) {
+            final Ehcache cache = cacheManager.getEhcache(cacheName);
+            // check if cache is null
+            if (cache == null) {
+                log.warn("Cache for specified cacheName='{}' does not exist or is not alive", cacheName);
+                return Response.status(Status.BAD_REQUEST).build();
+            }
+            // Clear given cache
+            cache.removeAll();
+        }
+        else {
+            // if not given a specific cacheName, clear all
+            cacheManager.clearAll();
+        }
+        return Response.status(Status.OK).build();
+    }
+
+    @POST
+    @Path("/" + CACHE + "/" + ACCOUNTS + "/{accountId:" + UUID_PATTERN + "}/")
+    @Produces(APPLICATION_JSON)
+    @ApiOperation(value = "Invalidates Caches per account level")
+    @ApiResponses(value = {})
+    public Response invalidatesCacheByAccount(@PathParam("accountId") final String accountId,
+                                              @javax.ws.rs.core.Context final HttpServletRequest request) {
+
+        // clear account-record-id cache by accountId
+        final Ehcache accountRecordIdCache = cacheManager.getEhcache(CacheType.ACCOUNT_RECORD_ID.getCacheName());
+        accountRecordIdCache.remove(accountId);
+
+        // clear account-immutable cache by accountId
+        final Ehcache accountImmutableCache = cacheManager.getEhcache(CacheType.ACCOUNT_IMMUTABLE.getCacheName());
+        accountImmutableCache.remove(UUID.fromString(accountId));
+
+        // clear account-bcd cache by accountId
+        final Ehcache accountBcdCache = cacheManager.getEhcache(CacheType.ACCOUNT_BCD.getCacheName());
+        accountBcdCache.remove(UUID.fromString(accountId));
+
+        return Response.status(Status.OK).build();
+    }
+
+    @POST
+    @Path("/" + CACHE + "/" + TENANTS + "/{tenantId:" + UUID_PATTERN + "}/")
+    @Produces(APPLICATION_JSON)
+    @ApiOperation(value = "Invalidates Caches per tenant level")
+    @ApiResponses(value = {})
+    public Response invalidatesCacheByTenant(@PathParam("tenantId") final String tenantId,
+                                              @javax.ws.rs.core.Context final HttpServletRequest request) {
+
+        // clear tenant-record-id cache by tenantId
+        final Ehcache tenantRecordIdCache = cacheManager.getEhcache(CacheType.TENANT_RECORD_ID.getCacheName());
+        tenantRecordIdCache.remove(tenantId);
+
+        // clear tenant-payment-state-machine-config cache by tenantId
+        final Ehcache tenantPaymentStateMachineConfigCache = cacheManager.getEhcache(CacheType.TENANT_PAYMENT_STATE_MACHINE_CONFIG.getCacheName());
+        tenantPaymentStateMachineConfigCache.remove(tenantId);
+
+        // clear tenant cache by tenantId
+        final Ehcache tenantCache = cacheManager.getEhcache(CacheType.TENANT.getCacheName());
+        tenantCache.remove(tenantId);
+
+        // clear tenant-kv cache by tenantId
+        final Ehcache tenantKvCache = cacheManager.getEhcache(CacheType.TENANT_KV.getCacheName());
+        tenantKvCache.remove(tenantId);
+
+        // clear tenant-config cache by tenantId
+        final Ehcache tenantConfigCache = cacheManager.getEhcache(CacheType.TENANT_CONFIG.getCacheName());
+        tenantConfigCache.remove(tenantId);
+
+        // clear tenant-overdue-config cache by tenantId
+        final Ehcache tenantOverdueConfigCache = cacheManager.getEhcache(CacheType.TENANT_OVERDUE_CONFIG.getCacheName());
+        tenantOverdueConfigCache.remove(tenantId);
+
+        // clear tenant-catalog cache by tenantId
+        final Ehcache tenantCatalogCache = cacheManager.getEhcache(CacheType.TENANT_CATALOG.getCacheName());
+        tenantCatalogCache.remove(tenantId);
+
+        return Response.status(Status.OK).build();
+    }
 }
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
index 89473ac..57929fa 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
@@ -270,6 +270,8 @@ public interface JaxrsResource {
     public static final String BCD = "bcd";
     public static final String TRANSFER_CREDIT = "transferCredit";
 
+    public static final String CACHE = "cache";
+
     public static final String QUERY_INCLUDED_DELETED = "includedDeleted";
 
 
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TestResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TestResource.java
index 1becceb..66f4d51 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TestResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TestResource.java
@@ -92,18 +92,16 @@ public class TestResource extends JaxRsResourceBase {
     private final PersistentBus persistentBus;
     private final NotificationQueueService notificationQueueService;
     private final RecordIdApi recordIdApi;
-    private final CacheManager cacheManager;
 
     @Inject
     public TestResource(final JaxrsUriBuilder uriBuilder, final TagUserApi tagUserApi, final CustomFieldUserApi customFieldUserApi,
                         final AuditUserApi auditUserApi, final AccountUserApi accountUserApi, final RecordIdApi recordIdApi,
                         final PersistentBus persistentBus, final NotificationQueueService notificationQueueService, final PaymentApi paymentApi,
-                        final CacheManager cacheManager, final Clock clock, final Context context) {
+                        final Clock clock, final Context context) {
         super(uriBuilder, tagUserApi, customFieldUserApi, auditUserApi, accountUserApi, paymentApi, null, clock, context);
         this.persistentBus = persistentBus;
         this.notificationQueueService = notificationQueueService;
         this.recordIdApi = recordIdApi;
-        this.cacheManager = cacheManager;
     }
 
     public final class ClockResource {
@@ -210,28 +208,6 @@ public class TestResource extends JaxRsResourceBase {
         return getCurrentTime(timeZoneStr);
     }
 
-    @POST
-    @Path("/cache")
-    @Produces(APPLICATION_JSON)
-    @ApiOperation(value = "Invalidates the given Cache")
-    @ApiResponses(value = {@ApiResponse(code = 400, message = "Cache name does not exist or is not alive")})
-    public Response invalidateCache(@QueryParam("cacheName") final String cacheName,
-                                                  @javax.ws.rs.core.Context final HttpServletRequest request) {
-
-        final Ehcache cache = cacheManager.getEhcache(cacheName);
-
-        // check if cache is null
-        if (cache == null) {
-            log.warn("Cache for cacheName='{}' does not exist or is not alive", cacheName);
-            return Response.status(Status.BAD_REQUEST).build();
-        }
-
-        // Clear given cache
-        cache.removeAll();
-
-        return Response.status(Status.OK).build();
-    }
-
     private boolean waitForNotificationToComplete(final ServletRequest request, final Long timeoutSec) {
         final TenantContext tenantContext = context.createContext(request);
         final Long tenantRecordId = recordIdApi.getRecordId(tenantContext.getTenantId(), ObjectType.TENANT, tenantContext);
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCache.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCache.java
index ac13ab8..583fbeb 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCache.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCache.java
@@ -16,6 +16,8 @@
 
 package org.killbill.billing.jaxrs;
 
+import org.killbill.billing.client.model.Account;
+import org.killbill.billing.client.model.Tenant;
 import org.killbill.billing.util.cache.Cachable.CacheType;
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -33,9 +35,99 @@ public class TestCache extends TestJaxrsBase {
         Assert.assertEquals(cache.getSize(), 1);
 
         // invalidate the specified cache
-        killBillClient.invalidateCache(cache.getName(), requestOptions);
+        killBillClient.invalidatesCacheByName(cache.getName(), requestOptions);
 
         // verify that now the cache is empty and has no keys stored
         Assert.assertEquals(cache.getSize(), 0);
     }
+
+    @Test(groups = "slow", description = "Can Invalidate (clear) all available Caches")
+    public void testInvalidateAllCaches() throws Exception {
+        // get Ehcache item with name "record-id"
+        final Ehcache cache = cacheManager.getEhcache(CacheType.RECORD_ID.getCacheName());
+        // verify that it is not null and has one stored key (the default tenant created for all integration tests)
+        Assert.assertNotNull(cache);
+        Assert.assertEquals(cache.getSize(), 1);
+
+        // invalidate all caches
+        killBillClient.invalidatesAllCaches(requestOptions);
+
+        // verify that now the cache is empty and has no keys stored
+        Assert.assertEquals(cache.getSize(), 0);
+    }
+
+    @Test(groups = "slow", description = "Can Invalidate (clear) all Account Caches by accountId")
+    public void testInvalidateCacheByAccount() throws Exception {
+        final Account input = createAccountNoPMBundleAndSubscription();
+
+        // get all caches per account level
+        final Ehcache accountRecordIdCache = cacheManager.getEhcache(CacheType.ACCOUNT_RECORD_ID.getCacheName());
+        final Ehcache accountImmutableCache = cacheManager.getEhcache(CacheType.ACCOUNT_IMMUTABLE.getCacheName());
+        final Ehcache accountBcdCache = cacheManager.getEhcache(CacheType.ACCOUNT_BCD.getCacheName());
+
+        // verify that they are not null and have the accountId stored as a key (the account created before)
+        Assert.assertNotNull(accountRecordIdCache);
+        Assert.assertNotNull(accountRecordIdCache.get(input.getAccountId().toString()));
+        Assert.assertNotNull(accountImmutableCache);
+        Assert.assertNotNull(accountImmutableCache.get(input.getAccountId()));
+        Assert.assertNotNull(accountBcdCache);
+        Assert.assertNotNull(accountBcdCache.get(input.getAccountId()));
+
+        // invalidate caches per account level by accountId
+        killBillClient.invalidatesCacheByAccount(input.getAccountId().toString(), requestOptions);
+
+        // verify that now the caches don't have the accountId key stored
+        Assert.assertNull(accountRecordIdCache.get(input.getAccountId().toString()));
+        Assert.assertNull(accountImmutableCache.get(input.getAccountId()));
+        Assert.assertNull(accountBcdCache.get(input.getAccountId()));
+    }
+
+    @Test(groups = "slow", description = "Can Invalidate (clear) all Tenant Caches by tenantId")
+    public void testInvalidateCacheByTenant() throws Exception {
+
+        // create a new tenant so it can be stored in the cache
+        final Tenant tenant = new Tenant();
+        tenant.setApiKey("testApiKey");
+        tenant.setApiSecret("testApiSecret");
+        final Tenant input = killBillClient.createTenant(tenant, false, requestOptions);
+
+        createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
+
+        // get all caches per tenant level
+        final Ehcache tenantRecordIdCache = cacheManager.getEhcache(CacheType.TENANT_RECORD_ID.getCacheName());
+        final Ehcache tenantPaymentStateMachineConfigCache = cacheManager.getEhcache(CacheType.TENANT_PAYMENT_STATE_MACHINE_CONFIG.getCacheName());
+        final Ehcache tenantCache = cacheManager.getEhcache(CacheType.TENANT.getCacheName());
+        final Ehcache tenantKvCache = cacheManager.getEhcache(CacheType.TENANT_KV.getCacheName());
+        final Ehcache tenantConfigCache = cacheManager.getEhcache(CacheType.TENANT_CONFIG.getCacheName());
+        final Ehcache tenantOverdueConfigCache = cacheManager.getEhcache(CacheType.TENANT_OVERDUE_CONFIG.getCacheName());
+        final Ehcache tenantCatalogCache = cacheManager.getEhcache(CacheType.TENANT_CATALOG.getCacheName());
+
+        // verify that they are not null and empty
+        Assert.assertNotNull(tenantRecordIdCache);
+        Assert.assertFalse(tenantRecordIdCache.getKeys().isEmpty());
+        Assert.assertNotNull(tenantPaymentStateMachineConfigCache);
+        Assert.assertFalse(tenantPaymentStateMachineConfigCache.getKeys().isEmpty());
+        Assert.assertNotNull(tenantCache);
+        Assert.assertFalse(tenantCache.getKeys().isEmpty());
+        Assert.assertNotNull(tenantKvCache);
+        Assert.assertFalse(tenantKvCache.getKeys().isEmpty());
+        Assert.assertNotNull(tenantConfigCache);
+        Assert.assertFalse(tenantConfigCache.getKeys().isEmpty());
+        Assert.assertNotNull(tenantOverdueConfigCache);
+        Assert.assertFalse(tenantOverdueConfigCache.getKeys().isEmpty());
+        Assert.assertNotNull(tenantCatalogCache);
+        Assert.assertFalse(tenantCatalogCache.getKeys().isEmpty());
+
+        // invalidate caches per tenant level by tenantId
+        killBillClient.invalidatesCacheByTenant(input.getTenantId().toString(), requestOptions);
+
+        // TODO: verify that now the caches are empty
+//        Assert.assertTrue(tenantRecordIdCache.getKeys().isEmpty());
+//        Assert.assertTrue(tenantPaymentStateMachineConfigCache.getKeys().isEmpty());
+//        Assert.assertTrue(tenantCache.getKeys().isEmpty());
+//        Assert.assertTrue(tenantKvCache.getKeys().isEmpty());
+//        Assert.assertTrue(tenantConfigCache.getKeys().isEmpty());
+//        Assert.assertTrue(tenantOverdueConfigCache.getKeys().isEmpty());
+//        Assert.assertTrue(tenantCatalogCache.getKeys().isEmpty());
+    }
 }