killbill-aplcache

Details

diff --git a/api/src/main/java/org/killbill/billing/tenant/api/TenantInternalApi.java b/api/src/main/java/org/killbill/billing/tenant/api/TenantInternalApi.java
index cf29529..3a39d4f 100644
--- a/api/src/main/java/org/killbill/billing/tenant/api/TenantInternalApi.java
+++ b/api/src/main/java/org/killbill/billing/tenant/api/TenantInternalApi.java
@@ -22,7 +22,6 @@ import java.util.Locale;
 
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.tenant.api.TenantKV.TenantKey;
-import org.killbill.billing.util.callcontext.TenantContext;
 
 public interface TenantInternalApi {
 
@@ -53,4 +52,7 @@ public interface TenantInternalApi {
     public String getPluginConfig(String pluginName, InternalTenantContext tenantContext);
 
     public List<String> getTenantValuesForKey(final String key, final InternalTenantContext tenantContext);
+
+    public Tenant getTenantByApiKey(final String key) throws TenantApiException;
+
 }
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/api/DefaultTenantInternalApi.java b/tenant/src/main/java/org/killbill/billing/tenant/api/DefaultTenantInternalApi.java
index 9b12658..be25ccd 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/api/DefaultTenantInternalApi.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/api/DefaultTenantInternalApi.java
@@ -23,9 +23,11 @@ import java.util.Locale;
 import javax.inject.Inject;
 import javax.inject.Named;
 
+import org.killbill.billing.ErrorCode;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.tenant.api.TenantKV.TenantKey;
 import org.killbill.billing.tenant.dao.TenantDao;
+import org.killbill.billing.tenant.dao.TenantModelDao;
 import org.killbill.billing.tenant.glue.DefaultTenantModule;
 import org.killbill.billing.util.LocaleUtils;
 
@@ -106,6 +108,16 @@ public class DefaultTenantInternalApi implements TenantInternalApi {
     }
 
 
+    @Override
+    public Tenant getTenantByApiKey(final String key) throws TenantApiException {
+        final TenantModelDao tenant = tenantDao.getTenantByApiKey(key);
+        if (tenant == null) {
+            throw new TenantApiException(ErrorCode.TENANT_DOES_NOT_EXIST_FOR_API_KEY, key);
+        }
+        return new DefaultTenant(tenant);
+    }
+
+
 
     private String getUniqueValue(final List<String> values, final String msg, final InternalTenantContext tenantContext) {
         if (values.isEmpty()) {
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java b/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java
index f1fe45c..3c1c575 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java
@@ -67,12 +67,15 @@ public class DefaultTenantUserApi implements TenantUserApi {
     private final TenantDao tenantDao;
     private final InternalCallContextFactory internalCallContextFactory;
     private final CacheController<Object, Object> tenantKVCache;
+    private final CacheController<Object, Object> tenantCache;
+
 
     @Inject
     public DefaultTenantUserApi(final TenantDao tenantDao, final InternalCallContextFactory internalCallContextFactory, final CacheControllerDispatcher cacheControllerDispatcher) {
         this.tenantDao = tenantDao;
         this.internalCallContextFactory = internalCallContextFactory;
         this.tenantKVCache = cacheControllerDispatcher.getCacheController(CacheType.TENANT_KV);
+        this.tenantCache = cacheControllerDispatcher.getCacheController(CacheType.TENANT);
     }
 
     @Override
@@ -84,17 +87,16 @@ public class DefaultTenantUserApi implements TenantUserApi {
         } catch (final TenantApiException e) {
             throw new TenantApiException(e, ErrorCode.TENANT_CREATION_FAILED);
         }
-
         return tenant;
     }
 
     @Override
     public Tenant getTenantByApiKey(final String key) throws TenantApiException {
-        final TenantModelDao tenant = tenantDao.getTenantByApiKey(key);
+        final Tenant tenant = (Tenant) tenantCache.get(key, new CacheLoaderArgument(ObjectType.TENANT));
         if (tenant == null) {
             throw new TenantApiException(ErrorCode.TENANT_DOES_NOT_EXIST_FOR_API_KEY, key);
         }
-        return new DefaultTenant(tenant);
+        return tenant;
     }
 
     @Override
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/dao/NoCachingTenantDao.java b/tenant/src/main/java/org/killbill/billing/tenant/dao/NoCachingTenantDao.java
index d7cb4d5..a491f09 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/dao/NoCachingTenantDao.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/dao/NoCachingTenantDao.java
@@ -56,8 +56,13 @@ public class NoCachingTenantDao extends EntityDaoBase<TenantModelDao, Tenant, Te
     }
 
     @Override
-    public TenantModelDao getTenantByApiKey(final String key) {
-        throw new IllegalStateException("Not implemented by NoCachingTenantDao");
+    public TenantModelDao getTenantByApiKey(final String apiKey) {
+        return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<TenantModelDao>() {
+            @Override
+            public TenantModelDao inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
+                return entitySqlDaoWrapperFactory.become(TenantSqlDao.class).getByApiKey(apiKey);
+            }
+        });
     }
 
     @Override
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/dao/TenantSqlDao.java b/tenant/src/main/java/org/killbill/billing/tenant/dao/TenantSqlDao.java
index 1f71b00..cf97271 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/dao/TenantSqlDao.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/dao/TenantSqlDao.java
@@ -16,6 +16,9 @@
 
 package org.killbill.billing.tenant.dao;
 
+import org.killbill.billing.util.cache.Cachable;
+import org.killbill.billing.util.cache.Cachable.CacheType;
+import org.killbill.billing.util.cache.CachableKey;
 import org.skife.jdbi.v2.sqlobject.Bind;
 import org.skife.jdbi.v2.sqlobject.SqlQuery;
 
diff --git a/tenant/src/test/java/org/killbill/billing/tenant/api/user/TestDefaultTenantUserApi.java b/tenant/src/test/java/org/killbill/billing/tenant/api/user/TestDefaultTenantUserApi.java
index 9d70464..2d4faa4 100644
--- a/tenant/src/test/java/org/killbill/billing/tenant/api/user/TestDefaultTenantUserApi.java
+++ b/tenant/src/test/java/org/killbill/billing/tenant/api/user/TestDefaultTenantUserApi.java
@@ -18,14 +18,37 @@
 package org.killbill.billing.tenant.api.user;
 
 import java.util.List;
+import java.util.UUID;
 
 import org.killbill.billing.tenant.TenantTestSuiteWithEmbeddedDb;
+import org.killbill.billing.tenant.api.DefaultTenant;
+import org.killbill.billing.tenant.api.Tenant;
+import org.killbill.billing.tenant.api.TenantData;
 import org.killbill.billing.tenant.api.TenantKV.TenantKey;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 public class TestDefaultTenantUserApi extends TenantTestSuiteWithEmbeddedDb {
 
+
+    @Test(groups = "slow")
+    public void testTenant() throws Exception {
+        final TenantData tenantdata = new DefaultTenant(UUID.randomUUID(), clock.getUTCNow(), clock.getUTCNow(), "er44TT-yy4r", "TTR445ee2", "dskjhfs^^54R");
+        tenantUserApi.createTenant(tenantdata, callContext);
+
+        final Tenant tenant = tenantUserApi.getTenantByApiKey(tenantdata.getApiKey());
+
+        Assert.assertEquals(tenant.getApiKey(), tenantdata.getApiKey());
+        Assert.assertEquals(tenant.getExternalKey(), tenantdata.getExternalKey());
+
+
+        // The second time, the value is already in the cache so the TenantCacheLoader is not invoked
+        final Tenant tenant2 = tenantUserApi.getTenantByApiKey(tenantdata.getApiKey());
+
+        Assert.assertEquals(tenant2.getApiKey(), tenantdata.getApiKey());
+        Assert.assertEquals(tenant2.getExternalKey(), tenantdata.getExternalKey());
+    }
+
     @Test(groups = "slow")
     public void testUserKey() throws Exception {
         tenantUserApi.addTenantKeyValue("THE_KEY", "TheValue", callContext);
diff --git a/util/src/main/java/org/killbill/billing/util/cache/Cachable.java b/util/src/main/java/org/killbill/billing/util/cache/Cachable.java
index bfc0b27..6035ff3 100644
--- a/util/src/main/java/org/killbill/billing/util/cache/Cachable.java
+++ b/util/src/main/java/org/killbill/billing/util/cache/Cachable.java
@@ -34,6 +34,7 @@ public @interface Cachable {
     String TENANT_CATALOG_CACHE_NAME = "tenant-catalog";
     String TENANT_OVERDUE_CONFIG_CACHE_NAME = "tenant-overdue-config";
     String TENANT_KV_CACHE_NAME = "tenant-kv";
+    String TENANT_CACHE_NAME = "tenant";
     String OVERRIDDEN_PLAN_CACHE_NAME = "overridden-plan";
     String ACCOUNT_IMMUTABLE_CACHE_NAME = "account-immutable";
     String ACCOUNT_BCD_CACHE_NAME = "account-bcd";
@@ -66,9 +67,12 @@ public @interface Cachable {
         /* Tenant overdue config cache */
         TENANT_OVERDUE_CONFIG(TENANT_OVERDUE_CONFIG_CACHE_NAME, false),
 
-        /* Tenant overdue config cache */
+        /* Tenant config cache */
         TENANT_KV(TENANT_KV_CACHE_NAME, false),
 
+        /* Tenant config cache */
+        TENANT(TENANT_CACHE_NAME, false),
+
         /* Overwritten plans  */
         OVERRIDDEN_PLAN(OVERRIDDEN_PLAN_CACHE_NAME, false),
 
diff --git a/util/src/main/java/org/killbill/billing/util/cache/EhCacheCacheManagerProvider.java b/util/src/main/java/org/killbill/billing/util/cache/EhCacheCacheManagerProvider.java
index 269ff66..f90b1d1 100644
--- a/util/src/main/java/org/killbill/billing/util/cache/EhCacheCacheManagerProvider.java
+++ b/util/src/main/java/org/killbill/billing/util/cache/EhCacheCacheManagerProvider.java
@@ -62,6 +62,7 @@ public class EhCacheCacheManagerProvider implements Provider<CacheManager> {
                                        final TenantCatalogCacheLoader tenantCatalogCacheLoader,
                                        final TenantOverdueConfigCacheLoader tenantOverdueConfigCacheLoader,
                                        final TenantKVCacheLoader tenantKVCacheLoader,
+                                       final TenantCacheLoader tenantCacheLoader,
                                        final OverriddenPlanCacheLoader overriddenPlanCacheLoader) {
         this.metricRegistry = metricRegistry;
         this.cacheConfig = cacheConfig;
@@ -76,6 +77,7 @@ public class EhCacheCacheManagerProvider implements Provider<CacheManager> {
         cacheLoaders.add(tenantCatalogCacheLoader);
         cacheLoaders.add(tenantOverdueConfigCacheLoader);
         cacheLoaders.add(tenantKVCacheLoader);
+        cacheLoaders.add(tenantCacheLoader);
         cacheLoaders.add(overriddenPlanCacheLoader);
     }
 
diff --git a/util/src/main/java/org/killbill/billing/util/cache/TenantCacheLoader.java b/util/src/main/java/org/killbill/billing/util/cache/TenantCacheLoader.java
new file mode 100644
index 0000000..bacafa8
--- /dev/null
+++ b/util/src/main/java/org/killbill/billing/util/cache/TenantCacheLoader.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 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.util.cache;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.killbill.billing.tenant.api.Tenant;
+import org.killbill.billing.tenant.api.TenantApiException;
+import org.killbill.billing.tenant.api.TenantInternalApi;
+import org.killbill.billing.util.cache.Cachable.CacheType;
+
+@Singleton
+public class TenantCacheLoader extends BaseCacheLoader {
+
+    private final TenantInternalApi tenantApi;
+
+    @Inject
+    public TenantCacheLoader(final TenantInternalApi tenantApi) {
+        super();
+        this.tenantApi = tenantApi;
+    }
+
+    @Override
+    public CacheType getCacheType() {
+        return CacheType.TENANT;
+    }
+
+    @Override
+    public Object load(final Object key, final Object argument) {
+        checkCacheLoaderStatus();
+
+        if (!(key instanceof String)) {
+            throw new IllegalArgumentException("Unexpected key type of " + key.getClass().getName());
+        }
+        if (!(argument instanceof CacheLoaderArgument)) {
+            throw new IllegalArgumentException("Unexpected key type of " + argument.getClass().getName());
+        }
+
+        try {
+            return tenantApi.getTenantByApiKey((String) key);
+        } catch (TenantApiException e) {
+            throw new IllegalStateException("TenantCacheLoader cannot find value for key " + key);
+        }
+    }
+}
diff --git a/util/src/main/resources/ehcache.xml b/util/src/main/resources/ehcache.xml
index d172871..ced3336 100644
--- a/util/src/main/resources/ehcache.xml
+++ b/util/src/main/resources/ehcache.xml
@@ -195,5 +195,19 @@
     </cache>
 
 
+    <cache name="tenant"
+           maxElementsInMemory="100"
+           maxElementsOnDisk="0"
+           overflowToDisk="false"
+           diskPersistent="false"
+           memoryStoreEvictionPolicy="LFU"
+           statistics="true"
+            >
+        <cacheEventListenerFactory
+                class="org.killbill.billing.util.cache.ExpirationListenerFactory"
+                properties=""/>
+    </cache>
+
+
 </ehcache>