Finish conversion from Guava Cache to Caffeine (#1616)

* Finish conversion from Guava Cache to Caffeine
This commit is contained in:
Ben McIlwain 2022-05-04 17:43:47 -04:00 committed by GitHub
parent 1e34476899
commit adfae285df
15 changed files with 90 additions and 169 deletions

View file

@ -1448,13 +1448,13 @@ public final class RegistryConfig {
* @see google.registry.model.tld.label.ReservedList * @see google.registry.model.tld.label.ReservedList
* @see google.registry.model.tld.label.PremiumList * @see google.registry.model.tld.label.PremiumList
*/ */
public static Duration getDomainLabelListCacheDuration() { public static java.time.Duration getDomainLabelListCacheDuration() {
return Duration.standardSeconds(CONFIG_SETTINGS.get().caching.domainLabelCachingSeconds); return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.domainLabelCachingSeconds);
} }
/** Returns the amount of time a singleton should be cached in persist mode, before expiring. */ /** Returns the amount of time a singleton should be cached in persist mode, before expiring. */
public static Duration getSingletonCachePersistDuration() { public static java.time.Duration getSingletonCachePersistDuration() {
return Duration.standardSeconds(CONFIG_SETTINGS.get().caching.singletonCachePersistSeconds); return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.singletonCachePersistSeconds);
} }
/** /**
@ -1476,8 +1476,8 @@ public final class RegistryConfig {
/** /**
* Returns the amount of time an EPP resource or key should be cached in memory before expiring. * Returns the amount of time an EPP resource or key should be cached in memory before expiring.
*/ */
public static Duration getEppResourceCachingDuration() { public static java.time.Duration getEppResourceCachingDuration() {
return Duration.standardSeconds(CONFIG_SETTINGS.get().caching.eppResourceCachingSeconds); return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.eppResourceCachingSeconds);
} }
/** Returns the maximum number of EPP resources and keys to keep in in-memory cache. */ /** Returns the maximum number of EPP resources and keys to keep in in-memory cache. */

View file

@ -27,10 +27,9 @@ import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy; import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.END_OF_TIME;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedMap;
@ -45,10 +44,10 @@ import google.registry.model.ofy.CommitLogManifest;
import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferData;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import google.registry.util.NonFinalForTesting; import google.registry.util.NonFinalForTesting;
import java.time.Duration;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.persistence.Access; import javax.persistence.Access;
import javax.persistence.AccessType; import javax.persistence.AccessType;
import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverride;
@ -57,7 +56,6 @@ import javax.persistence.Column;
import javax.persistence.MappedSuperclass; import javax.persistence.MappedSuperclass;
import javax.persistence.Transient; import javax.persistence.Transient;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Duration;
/** An EPP entity object (i.e. a domain, contact, or host). */ /** An EPP entity object (i.e. a domain, contact, or host). */
@MappedSuperclass @MappedSuperclass
@ -396,7 +394,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
@Override @Override
public Map<VKey<? extends EppResource>, EppResource> loadAll( public Map<VKey<? extends EppResource>, EppResource> loadAll(
Iterable<? extends VKey<? extends EppResource>> keys) { Set<? extends VKey<? extends EppResource>> keys) {
return replicaTm().doTransactionless(() -> replicaTm().loadByKeys(keys)); return replicaTm().doTransactionless(() -> replicaTm().loadByKeys(keys));
} }
}; };
@ -416,8 +414,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
private static LoadingCache<VKey<? extends EppResource>, EppResource> createEppResourcesCache( private static LoadingCache<VKey<? extends EppResource>, EppResource> createEppResourcesCache(
Duration expiry) { Duration expiry) {
return CacheBuilder.newBuilder() return CacheUtils.newCacheBuilder(expiry)
.expireAfterWrite(java.time.Duration.ofMillis(expiry.getMillis()))
.maximumSize(getEppResourceMaxCachedEntries()) .maximumSize(getEppResourceMaxCachedEntries())
.build(CACHE_LOADER); .build(CACHE_LOADER);
} }
@ -439,11 +436,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
if (!RegistryConfig.isEppResourceCachingEnabled()) { if (!RegistryConfig.isEppResourceCachingEnabled()) {
return tm().loadByKeys(keys); return tm().loadByKeys(keys);
} }
try { return ImmutableMap.copyOf(cacheEppResources.getAll(keys));
return cacheEppResources.getAll(keys);
} catch (ExecutionException e) {
throw new RuntimeException("Error loading cached EppResources", e.getCause());
}
} }
/** /**
@ -456,13 +449,9 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
if (!RegistryConfig.isEppResourceCachingEnabled()) { if (!RegistryConfig.isEppResourceCachingEnabled()) {
return tm().loadByKey(key); return tm().loadByKey(key);
} }
try { // Safe to cast because loading a Key<T> returns an entity of type T.
// Safe to cast because loading a Key<T> returns an entity of type T. @SuppressWarnings("unchecked")
@SuppressWarnings("unchecked") T resource = (T) cacheEppResources.get(key);
T resource = (T) cacheEppResources.get(key); return resource;
return resource;
} catch (ExecutionException e) {
throw new RuntimeException("Error loading cached EppResources", e.getCause());
}
} }
} }

View file

@ -26,23 +26,22 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
import static google.registry.util.CollectionUtils.entriesToImmutableMap; import static google.registry.util.CollectionUtils.entriesToImmutableMap;
import static google.registry.util.TypeUtils.instantiate; import static google.registry.util.TypeUtils.instantiate;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Multimaps; import com.google.common.collect.Multimaps;
import com.google.common.collect.Streams;
import com.googlecode.objectify.Key; import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Index; import com.googlecode.objectify.annotation.Index;
import google.registry.config.RegistryConfig; import google.registry.config.RegistryConfig;
import google.registry.model.BackupGroupRoot; import google.registry.model.BackupGroupRoot;
import google.registry.model.CacheUtils;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.annotations.DeleteAfterMigration; import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.ReportedOn; import google.registry.model.annotations.ReportedOn;
@ -54,14 +53,14 @@ import google.registry.persistence.VKey;
import google.registry.persistence.transaction.CriteriaQueryBuilder; import google.registry.persistence.transaction.CriteriaQueryBuilder;
import google.registry.persistence.transaction.JpaTransactionManager; import google.registry.persistence.transaction.JpaTransactionManager;
import google.registry.util.NonFinalForTesting; import google.registry.util.NonFinalForTesting;
import java.time.Duration;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ExecutionException; import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Duration;
/** /**
* Class to map a foreign key to the active instance of {@link EppResource} whose unique id matches * Class to map a foreign key to the active instance of {@link EppResource} whose unique id matches
@ -273,14 +272,14 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
@Override @Override
public Map<VKey<ForeignKeyIndex<?>>, Optional<ForeignKeyIndex<?>>> loadAll( public Map<VKey<ForeignKeyIndex<?>>, Optional<ForeignKeyIndex<?>>> loadAll(
Iterable<? extends VKey<ForeignKeyIndex<?>>> keys) { Set<? extends VKey<ForeignKeyIndex<?>>> keys) {
if (!keys.iterator().hasNext()) { if (keys.isEmpty()) {
return ImmutableMap.of(); return ImmutableMap.of();
} }
Class<? extends EppResource> resourceClass = Class<? extends EppResource> resourceClass =
RESOURCE_CLASS_TO_FKI_CLASS.inverse().get(keys.iterator().next().getKind()); RESOURCE_CLASS_TO_FKI_CLASS.inverse().get(keys.iterator().next().getKind());
ImmutableSet<String> foreignKeys = ImmutableSet<String> foreignKeys =
Streams.stream(keys).map(v -> v.getSqlKey().toString()).collect(toImmutableSet()); keys.stream().map(v -> v.getSqlKey().toString()).collect(toImmutableSet());
ImmutableSet<VKey<ForeignKeyIndex<?>>> typedKeys = ImmutableSet.copyOf(keys); ImmutableSet<VKey<ForeignKeyIndex<?>>> typedKeys = ImmutableSet.copyOf(keys);
ImmutableMap<String, ? extends ForeignKeyIndex<? extends EppResource>> existingFkis = ImmutableMap<String, ? extends ForeignKeyIndex<? extends EppResource>> existingFkis =
loadIndexesFromStore(resourceClass, foreignKeys, false, true); loadIndexesFromStore(resourceClass, foreignKeys, false, true);
@ -312,8 +311,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
private static LoadingCache<VKey<ForeignKeyIndex<?>>, Optional<ForeignKeyIndex<?>>> private static LoadingCache<VKey<ForeignKeyIndex<?>>, Optional<ForeignKeyIndex<?>>>
createForeignKeyIndexesCache(Duration expiry) { createForeignKeyIndexesCache(Duration expiry) {
return CacheBuilder.newBuilder() return CacheUtils.newCacheBuilder(expiry)
.expireAfterWrite(java.time.Duration.ofMillis(expiry.getMillis()))
.maximumSize(getEppResourceMaxCachedEntries()) .maximumSize(getEppResourceMaxCachedEntries())
.build(CACHE_LOADER); .build(CACHE_LOADER);
} }
@ -346,21 +344,17 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
foreignKeys.stream() foreignKeys.stream()
.map(fk -> (VKey<ForeignKeyIndex<?>>) VKey.create(fkiClass, fk)) .map(fk -> (VKey<ForeignKeyIndex<?>>) VKey.create(fkiClass, fk))
.collect(toImmutableList()); .collect(toImmutableList());
try { // This cast is safe because when we loaded ForeignKeyIndexes above we used type clazz, which
// This cast is safe because when we loaded ForeignKeyIndexes above we used type clazz, which // is scoped to E.
// is scoped to E. @SuppressWarnings("unchecked")
@SuppressWarnings("unchecked") ImmutableMap<String, ForeignKeyIndex<E>> fkisFromCache =
ImmutableMap<String, ForeignKeyIndex<E>> fkisFromCache = cacheForeignKeyIndexes.getAll(fkiVKeys).entrySet().stream()
cacheForeignKeyIndexes.getAll(fkiVKeys).entrySet().stream() .filter(entry -> entry.getValue().isPresent())
.filter(entry -> entry.getValue().isPresent()) .filter(entry -> now.isBefore(entry.getValue().get().getDeletionTime()))
.filter(entry -> now.isBefore(entry.getValue().get().getDeletionTime())) .collect(
.collect( toImmutableMap(
toImmutableMap( entry -> entry.getKey().getSqlKey().toString(),
entry -> entry.getKey().getSqlKey().toString(), entry -> (ForeignKeyIndex<E>) entry.getValue().get()));
entry -> (ForeignKeyIndex<E>) entry.getValue().get())); return fkisFromCache;
return fkisFromCache;
} catch (ExecutionException e) {
throw new RuntimeException("Error loading cached ForeignKeyIndexes", e.getCause());
}
} }
} }

View file

@ -29,11 +29,10 @@ import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import static org.joda.money.CurrencyUnit.USD; import static org.joda.money.CurrencyUnit.USD;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedMap;
@ -50,9 +49,11 @@ import com.googlecode.objectify.annotation.Mapify;
import com.googlecode.objectify.annotation.OnSave; import com.googlecode.objectify.annotation.OnSave;
import com.googlecode.objectify.annotation.Parent; import com.googlecode.objectify.annotation.Parent;
import google.registry.model.Buildable; import google.registry.model.Buildable;
import google.registry.model.CacheUtils;
import google.registry.model.CreateAutoTimestamp; import google.registry.model.CreateAutoTimestamp;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import google.registry.model.UnsafeSerializable; import google.registry.model.UnsafeSerializable;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.InCrossTld; import google.registry.model.annotations.InCrossTld;
import google.registry.model.annotations.ReportedOn; import google.registry.model.annotations.ReportedOn;
import google.registry.model.common.EntityGroupRoot; import google.registry.model.common.EntityGroupRoot;
@ -69,7 +70,6 @@ import google.registry.util.Idn;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -112,6 +112,7 @@ public class Registry extends ImmutableObject
/** Sets the Datastore specific field, tldStr, when the entity is loaded from Cloud SQL */ /** Sets the Datastore specific field, tldStr, when the entity is loaded from Cloud SQL */
@PostLoad @PostLoad
@DeleteAfterMigration
void postLoad() { void postLoad() {
tldStr = tldStrId; tldStr = tldStrId;
} }
@ -230,7 +231,7 @@ public class Registry extends ImmutableObject
/** Returns the registry for a given TLD, throwing if none exists. */ /** Returns the registry for a given TLD, throwing if none exists. */
public static Registry get(String tld) { public static Registry get(String tld) {
Registry registry = CACHE.getUnchecked(tld).orElse(null); Registry registry = CACHE.get(tld).orElse(null);
if (registry == null) { if (registry == null) {
throw new RegistryNotFoundException(tld); throw new RegistryNotFoundException(tld);
} }
@ -239,20 +240,16 @@ public class Registry extends ImmutableObject
/** Returns the registry entities for the given TLD strings, throwing if any don't exist. */ /** Returns the registry entities for the given TLD strings, throwing if any don't exist. */
public static ImmutableSet<Registry> get(Set<String> tlds) { public static ImmutableSet<Registry> get(Set<String> tlds) {
try { Map<String, Optional<Registry>> registries = CACHE.getAll(tlds);
ImmutableMap<String, Optional<Registry>> registries = CACHE.getAll(tlds); ImmutableSet<String> missingRegistries =
ImmutableSet<String> missingRegistries = registries.entrySet().stream()
registries.entrySet().stream() .filter(e -> !e.getValue().isPresent())
.filter(e -> !e.getValue().isPresent()) .map(Map.Entry::getKey)
.map(Map.Entry::getKey) .collect(toImmutableSet());
.collect(toImmutableSet()); if (missingRegistries.isEmpty()) {
if (missingRegistries.isEmpty()) { return registries.values().stream().map(Optional::get).collect(toImmutableSet());
return registries.values().stream().map(Optional::get).collect(toImmutableSet()); } else {
} else { throw new RegistryNotFoundException(missingRegistries);
throw new RegistryNotFoundException(missingRegistries);
}
} catch (ExecutionException e) {
throw new RuntimeException("Unexpected error retrieving TLDs " + tlds, e);
} }
} }
@ -269,8 +266,7 @@ public class Registry extends ImmutableObject
/** A cache that loads the {@link Registry} for a given tld. */ /** A cache that loads the {@link Registry} for a given tld. */
private static final LoadingCache<String, Optional<Registry>> CACHE = private static final LoadingCache<String, Optional<Registry>> CACHE =
CacheBuilder.newBuilder() CacheUtils.newCacheBuilder(getSingletonCacheRefreshDuration())
.expireAfterWrite(getSingletonCacheRefreshDuration())
.build( .build(
new CacheLoader<String, Optional<Registry>>() { new CacheLoader<String, Optional<Registry>>() {
@Override @Override
@ -281,7 +277,7 @@ public class Registry extends ImmutableObject
} }
@Override @Override
public Map<String, Optional<Registry>> loadAll(Iterable<? extends String> tlds) { public Map<String, Optional<Registry>> loadAll(Set<? extends String> tlds) {
ImmutableMap<String, VKey<Registry>> keysMap = ImmutableMap<String, VKey<Registry>> keysMap =
toMap(ImmutableSet.copyOf(tlds), Registry::createVKey); toMap(ImmutableSet.copyOf(tlds), Registry::createVKey);
Map<VKey<? extends Registry>, Registry> entities = Map<VKey<? extends Registry>, Registry> entities =

View file

@ -20,22 +20,17 @@ import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.model.tld.Registries.getTlds; import static google.registry.model.tld.Registries.getTlds;
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.HashMultiset; import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multiset; import com.google.common.collect.Multiset;
import com.google.common.util.concurrent.UncheckedExecutionException;
import google.registry.model.Buildable; import google.registry.model.Buildable;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import google.registry.model.tld.Registry; import google.registry.model.tld.Registry;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;
@ -149,16 +144,6 @@ public abstract class BaseDomainLabelList<T extends Comparable<?>, R extends Dom
protected abstract boolean refersToList(Registry registry, String name); protected abstract boolean refersToList(Registry registry, String name);
protected static <R> Optional<R> getFromCache(String listName, LoadingCache<String, R> cache) {
try {
return Optional.of(cache.get(listName));
} catch (InvalidCacheLoadException e) {
return Optional.empty();
} catch (ExecutionException e) {
throw new UncheckedExecutionException("Could not retrieve list named " + listName, e);
}
}
/** Base builder for derived classes of {@link BaseDomainLabelList}. */ /** Base builder for derived classes of {@link BaseDomainLabelList}. */
public abstract static class Builder<T extends BaseDomainLabelList<?, ?>, B extends Builder<T, ?>> public abstract static class Builder<T extends BaseDomainLabelList<?, ?>, B extends Builder<T, ?>>
extends GenericBuilder<T, B> { extends GenericBuilder<T, B> {

View file

@ -22,23 +22,20 @@ import static google.registry.config.RegistryConfig.getStaticPremiumListMaxCache
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.util.CollectionUtils.isNullOrEmpty; import static google.registry.util.CollectionUtils.isNullOrEmpty;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.auto.value.AutoValue; import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import google.registry.model.CacheUtils;
import google.registry.model.tld.label.PremiumList.PremiumEntry; import google.registry.model.tld.label.PremiumList.PremiumEntry;
import google.registry.util.NonFinalForTesting; import google.registry.util.NonFinalForTesting;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.Duration;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ExecutionException;
import org.joda.money.CurrencyUnit; import org.joda.money.CurrencyUnit;
import org.joda.money.Money; import org.joda.money.Money;
import org.joda.time.Duration;
/** /**
* Data access object class for accessing {@link PremiumList} objects from Cloud SQL. * Data access object class for accessing {@link PremiumList} objects from Cloud SQL.
@ -71,15 +68,8 @@ public class PremiumListDao {
@VisibleForTesting @VisibleForTesting
public static LoadingCache<String, Optional<PremiumList>> createPremiumListCache( public static LoadingCache<String, Optional<PremiumList>> createPremiumListCache(
Duration cachePersistDuration) { Duration cachePersistDuration) {
return CacheBuilder.newBuilder() return CacheUtils.newCacheBuilder(cachePersistDuration)
.expireAfterWrite(java.time.Duration.ofMillis(cachePersistDuration.getMillis())) .build(PremiumListDao::getLatestRevisionUncached);
.build(
new CacheLoader<String, Optional<PremiumList>>() {
@Override
public Optional<PremiumList> load(final String name) {
return jpaTm().doTransactionless(() -> getLatestRevisionUncached(name));
}
});
} }
/** /**
@ -104,16 +94,9 @@ public class PremiumListDao {
@VisibleForTesting @VisibleForTesting
static LoadingCache<RevisionIdAndLabel, Optional<BigDecimal>> createPremiumEntryCache( static LoadingCache<RevisionIdAndLabel, Optional<BigDecimal>> createPremiumEntryCache(
Duration cachePersistDuration) { Duration cachePersistDuration) {
return CacheBuilder.newBuilder() return CacheUtils.newCacheBuilder(cachePersistDuration)
.expireAfterWrite(java.time.Duration.ofMillis(cachePersistDuration.getMillis()))
.maximumSize(getStaticPremiumListMaxCachedEntries()) .maximumSize(getStaticPremiumListMaxCachedEntries())
.build( .build(PremiumListDao::getPriceForLabelUncached);
new CacheLoader<RevisionIdAndLabel, Optional<BigDecimal>>() {
@Override
public Optional<BigDecimal> load(RevisionIdAndLabel revisionIdAndLabel) {
return getPriceForLabelUncached(revisionIdAndLabel);
}
});
} }
/** /**
@ -123,7 +106,7 @@ public class PremiumListDao {
* prices, use {@link #getPremiumPrice}. * prices, use {@link #getPremiumPrice}.
*/ */
public static Optional<PremiumList> getLatestRevision(String premiumListName) { public static Optional<PremiumList> getLatestRevision(String premiumListName) {
return premiumListCache.getUnchecked(premiumListName); return premiumListCache.get(premiumListName);
} }
/** /**
@ -142,15 +125,7 @@ public class PremiumListDao {
} }
RevisionIdAndLabel revisionIdAndLabel = RevisionIdAndLabel revisionIdAndLabel =
RevisionIdAndLabel.create(loadedList.getRevisionId(), label); RevisionIdAndLabel.create(loadedList.getRevisionId(), label);
try { return premiumEntryCache.get(revisionIdAndLabel).map(loadedList::convertAmountToMoney);
return premiumEntryCache.get(revisionIdAndLabel).map(loadedList::convertAmountToMoney);
} catch (InvalidCacheLoadException | ExecutionException e) {
throw new RuntimeException(
String.format(
"Could not load premium entry %s for list %s",
revisionIdAndLabel, loadedList.getName()),
e);
}
} }
public static PremiumList save(String name, CurrencyUnit currencyUnit, List<String> inputData) { public static PremiumList save(String name, CurrencyUnit currencyUnit, List<String> inputData) {

View file

@ -26,14 +26,13 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
import static google.registry.util.CollectionUtils.nullToEmpty; import static google.registry.util.CollectionUtils.nullToEmpty;
import static org.joda.time.DateTimeZone.UTC; import static org.joda.time.DateTimeZone.UTC;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.common.util.concurrent.UncheckedExecutionException;
import google.registry.model.Buildable; import google.registry.model.Buildable;
import google.registry.model.CacheUtils;
import google.registry.model.replay.SqlOnlyEntity; import google.registry.model.replay.SqlOnlyEntity;
import google.registry.model.tld.Registry; import google.registry.model.tld.Registry;
import google.registry.model.tld.label.DomainLabelMetrics.MetricsReservedListMatch; import google.registry.model.tld.label.DomainLabelMetrics.MetricsReservedListMatch;
@ -41,7 +40,6 @@ import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Id; import javax.persistence.Id;
@ -224,7 +222,7 @@ public final class ReservedList
* ReservedList from the cache or database. * ReservedList from the cache or database.
*/ */
public static Optional<ReservedList> get(String listName) { public static Optional<ReservedList> get(String listName) {
return getFromCache(listName, cache); return cache.get(listName);
} }
/** /**
@ -270,33 +268,18 @@ public final class ReservedList
return entries; return entries;
} }
/** Loads and returns the reserved lists with the given names, skipping those that don't exist. */
private static ImmutableSet<ReservedList> loadReservedLists( private static ImmutableSet<ReservedList> loadReservedLists(
ImmutableSet<String> reservedListNames) { ImmutableSet<String> reservedListNames) {
return reservedListNames.stream() return cache.getAll(reservedListNames).values().stream()
.map( .filter(Optional::isPresent)
(listName) -> { .map(Optional::get)
try {
return cache.get(listName);
} catch (ExecutionException e) {
throw new UncheckedExecutionException(
String.format("Could not load the reserved list '%s' from the cache", listName),
e);
}
})
.collect(toImmutableSet()); .collect(toImmutableSet());
} }
private static LoadingCache<String, ReservedList> cache = private static final LoadingCache<String, Optional<ReservedList>> cache =
CacheBuilder.newBuilder() CacheUtils.newCacheBuilder(getDomainLabelListCacheDuration())
.expireAfterWrite( .build(ReservedListDao::getLatestRevision);
java.time.Duration.ofMillis(getDomainLabelListCacheDuration().getMillis()))
.build(
new CacheLoader<String, ReservedList>() {
@Override
public ReservedList load(String listName) {
return ReservedListDao.getLatestRevision(listName).orElse(null);
}
});
/** /**
* Gets the {@link ReservationType} of a label in a single ReservedList, or returns an absent * Gets the {@link ReservationType} of a label in a single ReservedList, or returns an absent
@ -337,6 +320,7 @@ public final class ReservedList
* A builder for constructing {@link ReservedList} objects, since they are immutable. * A builder for constructing {@link ReservedList} objects, since they are immutable.
*/ */
public static class Builder extends BaseDomainLabelList.Builder<ReservedList, Builder> { public static class Builder extends BaseDomainLabelList.Builder<ReservedList, Builder> {
public Builder() {} public Builder() {}
private Builder(ReservedList instance) { private Builder(ReservedList instance) {

View file

@ -17,7 +17,6 @@ package google.registry.tmch;
import static google.registry.config.RegistryConfig.ConfigModule.TmchCaMode.PILOT; import static google.registry.config.RegistryConfig.ConfigModule.TmchCaMode.PILOT;
import static google.registry.config.RegistryConfig.ConfigModule.TmchCaMode.PRODUCTION; import static google.registry.config.RegistryConfig.ConfigModule.TmchCaMode.PRODUCTION;
import static google.registry.config.RegistryConfig.getSingletonCacheRefreshDuration; import static google.registry.config.RegistryConfig.getSingletonCacheRefreshDuration;
import static google.registry.model.CacheUtils.newCacheBuilder;
import static google.registry.util.ResourceUtils.readResourceUtf8; import static google.registry.util.ResourceUtils.readResourceUtf8;
import com.github.benmanes.caffeine.cache.CacheLoader; import com.github.benmanes.caffeine.cache.CacheLoader;
@ -25,6 +24,7 @@ import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import google.registry.config.RegistryConfig.Config; import google.registry.config.RegistryConfig.Config;
import google.registry.config.RegistryConfig.ConfigModule.TmchCaMode; import google.registry.config.RegistryConfig.ConfigModule.TmchCaMode;
import google.registry.model.CacheUtils;
import google.registry.model.tmch.TmchCrl; import google.registry.model.tmch.TmchCrl;
import google.registry.util.Clock; import google.registry.util.Clock;
import google.registry.util.X509Utils; import google.registry.util.X509Utils;
@ -76,7 +76,7 @@ public final class TmchCertificateAuthority {
* persist the correct one for this given environment. * persist the correct one for this given environment.
*/ */
private static final LoadingCache<TmchCaMode, X509CRL> CRL_CACHE = private static final LoadingCache<TmchCaMode, X509CRL> CRL_CACHE =
newCacheBuilder(getSingletonCacheRefreshDuration()) CacheUtils.newCacheBuilder(getSingletonCacheRefreshDuration())
.build( .build(
new CacheLoader<TmchCaMode, X509CRL>() { new CacheLoader<TmchCaMode, X509CRL>() {
@Override @Override

View file

@ -38,7 +38,7 @@ import org.joda.time.DateTimeZone;
/** Command to update a TLD. */ /** Command to update a TLD. */
@Parameters(separators = " =", commandDescription = "Update existing TLD(s)") @Parameters(separators = " =", commandDescription = "Update existing TLD(s)")
class UpdateTldCommand extends CreateOrUpdateTldCommand { public class UpdateTldCommand extends CreateOrUpdateTldCommand {
@Nullable @Nullable
@Parameter( @Parameter(
names = "--add_reserved_lists", names = "--add_reserved_lists",

View file

@ -25,7 +25,7 @@ import com.google.common.collect.ImmutableList;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
import google.registry.model.host.HostResource; import google.registry.model.host.HostResource;
import google.registry.testing.TestCacheExtension; import google.registry.testing.TestCacheExtension;
import org.joda.time.Duration; import java.time.Duration;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
@ -34,7 +34,7 @@ public class EppResourceTest extends EntityTestCase {
@RegisterExtension @RegisterExtension
public final TestCacheExtension testCacheExtension = public final TestCacheExtension testCacheExtension =
new TestCacheExtension.Builder().withEppResourceCache(Duration.standardDays(1)).build(); new TestCacheExtension.Builder().withEppResourceCache(Duration.ofDays(1)).build();
@Test @Test
void test_loadCached_ignoresContactChange() { void test_loadCached_ignoresContactChange() {

View file

@ -38,7 +38,7 @@ import google.registry.testing.TestCacheExtension;
import google.registry.testing.TestOfyAndSql; import google.registry.testing.TestOfyAndSql;
import google.registry.testing.TestOfyOnly; import google.registry.testing.TestOfyOnly;
import google.registry.testing.TestSqlOnly; import google.registry.testing.TestSqlOnly;
import org.joda.time.Duration; import java.time.Duration;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
@ -48,7 +48,7 @@ class ForeignKeyIndexTest extends EntityTestCase {
@RegisterExtension @RegisterExtension
public final TestCacheExtension testCacheExtension = public final TestCacheExtension testCacheExtension =
new TestCacheExtension.Builder().withForeignIndexKeyCache(Duration.standardDays(1)).build(); new TestCacheExtension.Builder().withForeignIndexKeyCache(Duration.ofDays(1)).build();
@BeforeEach @BeforeEach
void setUp() { void setUp() {

View file

@ -22,7 +22,6 @@ import static google.registry.testing.DatabaseHelper.newRegistry;
import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.DatabaseHelper.persistResource;
import static org.joda.money.CurrencyUnit.JPY; import static org.joda.money.CurrencyUnit.JPY;
import static org.joda.money.CurrencyUnit.USD; import static org.joda.money.CurrencyUnit.USD;
import static org.joda.time.Duration.standardDays;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
@ -34,6 +33,7 @@ import google.registry.testing.AppEngineExtension;
import google.registry.testing.FakeClock; import google.registry.testing.FakeClock;
import google.registry.testing.TestCacheExtension; import google.registry.testing.TestCacheExtension;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.Duration;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream; import java.util.stream.IntStream;
@ -61,9 +61,7 @@ public class PremiumListDaoTest {
// Set long persist times on caches so they can be tested (cache times default to 0 in tests). // Set long persist times on caches so they can be tested (cache times default to 0 in tests).
@RegisterExtension @RegisterExtension
public final TestCacheExtension testCacheExtension = public final TestCacheExtension testCacheExtension =
new TestCacheExtension.Builder() new TestCacheExtension.Builder().withPremiumListsCache(Duration.ofDays(1)).build();
.withPremiumListsCache(standardDays(1))
.build();
private static final ImmutableMap<String, BigDecimal> TEST_PRICES = private static final ImmutableMap<String, BigDecimal> TEST_PRICES =
ImmutableMap.of( ImmutableMap.of(

View file

@ -19,9 +19,9 @@ import com.google.common.collect.Maps;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.index.ForeignKeyIndex; import google.registry.model.index.ForeignKeyIndex;
import google.registry.model.tld.label.PremiumListDao; import google.registry.model.tld.label.PremiumListDao;
import java.time.Duration;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import org.joda.time.Duration;
import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext;

View file

@ -66,8 +66,8 @@ import google.registry.whois.WhoisMetrics.WhoisMetric;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;
import java.time.Duration;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
@ -87,8 +87,8 @@ public class WhoisActionTest {
@RegisterExtension @RegisterExtension
public final TestCacheExtension testCacheExtension = public final TestCacheExtension testCacheExtension =
new TestCacheExtension.Builder() new TestCacheExtension.Builder()
.withEppResourceCache(Duration.standardDays(1)) .withEppResourceCache(Duration.ofDays(1))
.withForeignIndexKeyCache(Duration.standardDays(1)) .withForeignIndexKeyCache(Duration.ofDays(1))
.build(); .build();
private final FakeResponse response = new FakeResponse(); private final FakeResponse response = new FakeResponse();

View file

@ -34,7 +34,7 @@ import google.registry.testing.FakeClock;
import google.registry.testing.TestCacheExtension; import google.registry.testing.TestCacheExtension;
import google.registry.testing.TestOfyAndSql; import google.registry.testing.TestOfyAndSql;
import java.net.InetAddress; import java.net.InetAddress;
import org.joda.time.Duration; import java.time.Duration;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
@ -50,7 +50,7 @@ class WhoisCommandFactoryTest {
@RegisterExtension @RegisterExtension
final TestCacheExtension testCacheExtension = final TestCacheExtension testCacheExtension =
new TestCacheExtension.Builder().withEppResourceCache(Duration.millis(1000000000)).build(); new TestCacheExtension.Builder().withEppResourceCache(Duration.ofSeconds(1000000)).build();
WhoisCommandFactory noncachedFactory = WhoisCommandFactory.createNonCached(); WhoisCommandFactory noncachedFactory = WhoisCommandFactory.createNonCached();
WhoisCommandFactory cachedFactory = WhoisCommandFactory.createCached(); WhoisCommandFactory cachedFactory = WhoisCommandFactory.createCached();