Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- Moved new methods from TestResource to AdminResource
- Fixed existing integration tests.
- Added new integration tests (in progress)
  • Loading branch information
Javier Gómez committed Aug 16, 2016
1 parent b100e21 commit d789274
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 27 deletions.
Expand Up @@ -23,10 +23,12 @@
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;

Expand All @@ -44,6 +46,7 @@
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;

Expand All @@ -55,6 +58,8 @@
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;

Expand All @@ -64,11 +69,13 @@
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;
}


Expand Down Expand Up @@ -104,4 +111,89 @@ public boolean apply(final PaymentTransaction input) {
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();
}
}
Expand Up @@ -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";


Expand Down
Expand Up @@ -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 {
Expand Down Expand Up @@ -210,28 +208,6 @@ public Response updateTestClockTime(@QueryParam("days") final Integer addDays,
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);
Expand Down
Expand Up @@ -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;
Expand All @@ -33,9 +35,99 @@ public void testInvalidateCacheByName() throws Exception {
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());
}
}

0 comments on commit d789274

Please sign in to comment.