mirror of
https://github.com/google/nomulus
synced 2026-09-20 06:54:43 +00:00
Add caches to ClaimsListDao and ClaimsList (#1731)
We cache the ClaimsList Java object for six hours (we don't expect it to change frequently, and the cron job to update it only runs every twelve hours). Subsequent calls to ClaimsListDao::get will return the cached value. Within the ClaimsList Java object itself, we cache any labels that we have retrieved. While we already have a form of a cache here in the "labelsToKeys" map, that only handles situations where we've loaded the entire map from the database. We want to have a non-guaranteed cache in order to make repeated calls to getClaimKey fast.
This commit is contained in:
@@ -41,13 +41,20 @@ import google.registry.flows.exceptions.TooManyResourceChecksException;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.tld.Registry.TldState;
|
||||
import google.registry.testing.TestCacheExtension;
|
||||
import java.time.Duration;
|
||||
import org.joda.money.Money;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link DomainClaimsCheckFlow}. */
|
||||
public class DomainClaimsCheckFlowTest extends ResourceFlowTestCase<DomainClaimsCheckFlow, Domain> {
|
||||
|
||||
@RegisterExtension
|
||||
public final TestCacheExtension testCacheExtension =
|
||||
new TestCacheExtension.Builder().withClaimsListCache(Duration.ofHours(6)).build();
|
||||
|
||||
DomainClaimsCheckFlowTest() {
|
||||
setEppInput("domain_check_claims.xml");
|
||||
}
|
||||
|
||||
@@ -15,12 +15,16 @@
|
||||
package google.registry.model.tmch;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.truth.Truth8;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationWithCoverageExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.TestCacheExtension;
|
||||
import java.time.Duration;
|
||||
import javax.persistence.PersistenceException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
@@ -37,6 +41,11 @@ public class ClaimsListDaoTest {
|
||||
.withoutCannedData()
|
||||
.buildIntegrationWithCoverageExtension();
|
||||
|
||||
// Set long persist times on the cache so it can be tested (cache times default to 0 in tests).
|
||||
@RegisterExtension
|
||||
public final TestCacheExtension testCacheExtension =
|
||||
new TestCacheExtension.Builder().withClaimsListCache(Duration.ofHours(6)).build();
|
||||
|
||||
@Test
|
||||
void save_insertsClaimsListSuccessfully() {
|
||||
ClaimsList claimsList =
|
||||
@@ -83,6 +92,40 @@ public class ClaimsListDaoTest {
|
||||
assertClaimsListEquals(newClaimsList, ClaimsListDao.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDaoCaching_savesAndUpdates() {
|
||||
assertThat(ClaimsListDao.CACHE.getIfPresent(ClaimsListDao.class)).isNull();
|
||||
ClaimsList oldList =
|
||||
ClaimsList.create(fakeClock.nowUtc(), ImmutableMap.of("label1", "key1", "label2", "key2"));
|
||||
ClaimsListDao.save(oldList);
|
||||
assertThat(ClaimsListDao.CACHE.getIfPresent(ClaimsListDao.class)).isEqualTo(oldList);
|
||||
ClaimsList newList =
|
||||
ClaimsList.create(fakeClock.nowUtc(), ImmutableMap.of("label3", "key3", "label4", "key4"));
|
||||
ClaimsListDao.save(newList);
|
||||
assertThat(ClaimsListDao.CACHE.getIfPresent(ClaimsListDao.class)).isEqualTo(newList);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEntryCaching_savesAndUpdates() {
|
||||
ClaimsList claimsList =
|
||||
ClaimsList.create(fakeClock.nowUtc(), ImmutableMap.of("label1", "key1", "label2", "key2"));
|
||||
// Bypass the DAO to avoid the cache
|
||||
jpaTm().transact(() -> jpaTm().insert(claimsList));
|
||||
ClaimsList fromDatabase = ClaimsListDao.get();
|
||||
// At first, we haven't loaded any entries
|
||||
assertThat(fromDatabase.claimKeyCache.getIfPresent("label1")).isNull();
|
||||
Truth8.assertThat(fromDatabase.getClaimKey("label1")).hasValue("key1");
|
||||
// After retrieval, the key exists
|
||||
Truth8.assertThat(fromDatabase.claimKeyCache.getIfPresent("label1")).hasValue("key1");
|
||||
assertThat(fromDatabase.claimKeyCache.getIfPresent("label2")).isNull();
|
||||
// Loading labels-to-keys should still work
|
||||
assertThat(fromDatabase.getLabelsToKeys()).containsExactly("label1", "key1", "label2", "key2");
|
||||
// We should also cache nonexistent values
|
||||
assertThat(fromDatabase.claimKeyCache.getIfPresent("nonexistent")).isNull();
|
||||
Truth8.assertThat(fromDatabase.getClaimKey("nonexistent")).isEmpty();
|
||||
Truth8.assertThat(fromDatabase.claimKeyCache.getIfPresent("nonexistent")).isEmpty();
|
||||
}
|
||||
|
||||
private void assertClaimsListEquals(ClaimsList left, ClaimsList right) {
|
||||
assertThat(left.getRevisionId()).isEqualTo(right.getRevisionId());
|
||||
assertThat(left.getTmdbGenerationTime()).isEqualTo(right.getTmdbGenerationTime());
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.google.common.collect.Maps;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.index.ForeignKeyIndex;
|
||||
import google.registry.model.tld.label.PremiumListDao;
|
||||
import google.registry.model.tmch.ClaimsListDao;
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -75,6 +76,12 @@ public class TestCacheExtension implements BeforeEachCallback, AfterEachCallback
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withClaimsListCache(Duration expiry) {
|
||||
cacheHandlerMap.put(
|
||||
"ClaimsListDao.CACHE", new TestCacheHandler(ClaimsListDao::setCacheForTest, expiry));
|
||||
return this;
|
||||
}
|
||||
|
||||
public TestCacheExtension build() {
|
||||
return new TestCacheExtension(ImmutableList.copyOf(cacheHandlerMap.values()));
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.reporting.HistoryEntry.Type;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.TestCacheExtension;
|
||||
import google.registry.util.Clock;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -44,6 +46,10 @@ class EppLifecycleToolsTest extends EppTestCase {
|
||||
final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withClock(clock).withCloudSql().withTaskQueue().build();
|
||||
|
||||
@RegisterExtension
|
||||
public final TestCacheExtension testCacheExtension =
|
||||
new TestCacheExtension.Builder().withClaimsListCache(Duration.ofHours(6)).build();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTlds("example", "tld");
|
||||
|
||||
Reference in New Issue
Block a user