Convert cache expireAfterWrite to nullable Duration

Use the same Duration type throughout the stack. In particular, this
allows us to use the java.time API for doing expiry calculations in
H2CacheImpl.

Converting to Optional<Duration> is beyond the scope of this change, as
it would properly imply changing the other nullable fields in CacheDef.

Change-Id: I63a173ce1bef83fa84ccb8b8b6ea75ae198e5728
This commit is contained in:
Dave Borowitz
2018-06-05 14:35:50 -04:00
parent eaa1783b24
commit 6588a79451
15 changed files with 53 additions and 43 deletions

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.common;
import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.Instant;
import java.util.function.LongSupplier; import java.util.function.LongSupplier;
import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.storage.file.FileBasedConfig;
@@ -36,6 +37,10 @@ public class TimeUtil {
return currentMillisSupplier.getAsLong(); return currentMillisSupplier.getAsLong();
} }
public static Instant now() {
return Instant.ofEpochMilli(nowMs());
}
public static Timestamp nowTs() { public static Timestamp nowTs() {
return new Timestamp(nowMs()); return new Timestamp(nowMs());
} }

View File

@@ -44,10 +44,10 @@ import com.google.inject.Singleton;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import com.google.inject.name.Named; import com.google.inject.name.Named;
import java.io.IOException; import java.io.IOException;
import java.time.Duration;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.servlet.Filter; import javax.servlet.Filter;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
import javax.servlet.FilterConfig; import javax.servlet.FilterConfig;
@@ -119,7 +119,7 @@ public class GitOverHttpServlet extends GitServlet {
protected void configure() { protected void configure() {
cache(ID_CACHE, AdvertisedObjectsCacheKey.class, new TypeLiteral<Set<ObjectId>>() {}) cache(ID_CACHE, AdvertisedObjectsCacheKey.class, new TypeLiteral<Set<ObjectId>>() {})
.maximumWeight(4096) .maximumWeight(4096)
.expireAfterWrite(10, TimeUnit.MINUTES); .expireAfterWrite(Duration.ofMinutes(10));
} }
}); });
} }

View File

@@ -14,8 +14,6 @@
package com.google.gerrit.httpd; package com.google.gerrit.httpd;
import static java.util.concurrent.TimeUnit.MINUTES;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.gerrit.common.Nullable; import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.extensions.registration.DynamicItem;
@@ -30,6 +28,7 @@ import com.google.inject.Provider;
import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.google.inject.name.Named; import com.google.inject.name.Named;
import com.google.inject.servlet.RequestScoped; import com.google.inject.servlet.RequestScoped;
import java.time.Duration;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@@ -41,10 +40,8 @@ public class H2CacheBasedWebSession extends CacheBasedWebSession {
protected void configure() { protected void configure() {
persist(WebSessionManager.CACHE_NAME, String.class, Val.class) persist(WebSessionManager.CACHE_NAME, String.class, Val.class)
.maximumWeight(1024) // reasonable default for many sites .maximumWeight(1024) // reasonable default for many sites
.expireAfterWrite( // expire sessions if they are inactive
CacheBasedWebSession.MAX_AGE_MINUTES, .expireAfterWrite(Duration.ofMinutes(CacheBasedWebSession.MAX_AGE_MINUTES));
MINUTES) // expire sessions if they are inactive
;
install(new FactoryModuleBuilder().build(WebSessionManagerFactory.class)); install(new FactoryModuleBuilder().build(WebSessionManagerFactory.class));
DynamicItem.itemOf(binder(), WebSession.class); DynamicItem.itemOf(binder(), WebSession.class);
DynamicItem.bind(binder(), WebSession.class) DynamicItem.bind(binder(), WebSession.class)

View File

@@ -14,8 +14,6 @@
package com.google.gerrit.server.auth.ldap; package com.google.gerrit.server.auth.ldap;
import static java.util.concurrent.TimeUnit.HOURS;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
@@ -25,6 +23,7 @@ import com.google.gerrit.server.account.Realm;
import com.google.gerrit.server.cache.CacheModule; import com.google.gerrit.server.cache.CacheModule;
import com.google.inject.Scopes; import com.google.inject.Scopes;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import java.time.Duration;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
@@ -37,18 +36,18 @@ public class LdapModule extends CacheModule {
@Override @Override
protected void configure() { protected void configure() {
cache(GROUP_CACHE, String.class, new TypeLiteral<Set<AccountGroup.UUID>>() {}) cache(GROUP_CACHE, String.class, new TypeLiteral<Set<AccountGroup.UUID>>() {})
.expireAfterWrite(1, HOURS) .expireAfterWrite(Duration.ofHours(1))
.loader(LdapRealm.MemberLoader.class); .loader(LdapRealm.MemberLoader.class);
cache(USERNAME_CACHE, String.class, new TypeLiteral<Optional<Account.Id>>() {}) cache(USERNAME_CACHE, String.class, new TypeLiteral<Optional<Account.Id>>() {})
.loader(LdapRealm.UserLoader.class); .loader(LdapRealm.UserLoader.class);
cache(GROUP_EXIST_CACHE, String.class, new TypeLiteral<Boolean>() {}) cache(GROUP_EXIST_CACHE, String.class, new TypeLiteral<Boolean>() {})
.expireAfterWrite(1, HOURS) .expireAfterWrite(Duration.ofHours(1))
.loader(LdapRealm.ExistenceLoader.class); .loader(LdapRealm.ExistenceLoader.class);
cache(PARENT_GROUPS_CACHE, String.class, new TypeLiteral<ImmutableSet<String>>() {}) cache(PARENT_GROUPS_CACHE, String.class, new TypeLiteral<ImmutableSet<String>>() {})
.expireAfterWrite(1, HOURS); .expireAfterWrite(Duration.ofHours(1));
bind(Helper.class); bind(Helper.class);
bind(Realm.class).to(LdapRealm.class).in(Scopes.SINGLETON); bind(Realm.class).to(LdapRealm.class).in(Scopes.SINGLETON);

View File

@@ -16,7 +16,7 @@ package com.google.gerrit.server.cache;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.Weigher; import com.google.common.cache.Weigher;
import java.util.concurrent.TimeUnit; import java.time.Duration;
/** Configure a cache declared within a {@link CacheModule} instance. */ /** Configure a cache declared within a {@link CacheModule} instance. */
public interface CacheBinding<K, V> { public interface CacheBinding<K, V> {
@@ -24,7 +24,7 @@ public interface CacheBinding<K, V> {
CacheBinding<K, V> maximumWeight(long weight); CacheBinding<K, V> maximumWeight(long weight);
/** Set the time an element lives before being expired. */ /** Set the time an element lives before being expired. */
CacheBinding<K, V> expireAfterWrite(long duration, TimeUnit durationUnits); CacheBinding<K, V> expireAfterWrite(Duration duration);
/** Populate the cache with items from the CacheLoader. */ /** Populate the cache with items from the CacheLoader. */
CacheBinding<K, V> loader(Class<? extends CacheLoader<K, V>> clazz); CacheBinding<K, V> loader(Class<? extends CacheLoader<K, V>> clazz);

View File

@@ -18,7 +18,7 @@ import com.google.common.cache.CacheLoader;
import com.google.common.cache.Weigher; import com.google.common.cache.Weigher;
import com.google.gerrit.common.Nullable; import com.google.gerrit.common.Nullable;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import java.util.concurrent.TimeUnit; import java.time.Duration;
public interface CacheDef<K, V> { public interface CacheDef<K, V> {
/** /**
@@ -45,7 +45,7 @@ public interface CacheDef<K, V> {
long maximumWeight(); long maximumWeight();
@Nullable @Nullable
Long expireAfterWrite(TimeUnit unit); Duration expireAfterWrite();
@Nullable @Nullable
Weigher<K, V> weigher(); Weigher<K, V> weigher();

View File

@@ -16,7 +16,6 @@ package com.google.gerrit.server.cache;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
@@ -27,7 +26,7 @@ import com.google.gerrit.extensions.annotations.PluginName;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider; import com.google.inject.Provider;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import java.util.concurrent.TimeUnit; import java.time.Duration;
class CacheProvider<K, V> implements Provider<Cache<K, V>>, CacheBinding<K, V>, CacheDef<K, V> { class CacheProvider<K, V> implements Provider<Cache<K, V>>, CacheBinding<K, V>, CacheDef<K, V> {
private final CacheModule module; private final CacheModule module;
@@ -36,7 +35,7 @@ class CacheProvider<K, V> implements Provider<Cache<K, V>>, CacheBinding<K, V>,
private final TypeLiteral<V> valType; private final TypeLiteral<V> valType;
private String configKey; private String configKey;
private long maximumWeight; private long maximumWeight;
private Long expireAfterWrite; private Duration expireAfterWrite;
private Provider<CacheLoader<K, V>> loader; private Provider<CacheLoader<K, V>> loader;
private Provider<Weigher<K, V>> weigher; private Provider<Weigher<K, V>> weigher;
@@ -69,9 +68,9 @@ class CacheProvider<K, V> implements Provider<Cache<K, V>>, CacheBinding<K, V>,
} }
@Override @Override
public CacheBinding<K, V> expireAfterWrite(long duration, TimeUnit unit) { public CacheBinding<K, V> expireAfterWrite(Duration duration) {
checkNotFrozen(); checkNotFrozen();
expireAfterWrite = SECONDS.convert(duration, unit); expireAfterWrite = duration;
return this; return this;
} }
@@ -126,8 +125,8 @@ class CacheProvider<K, V> implements Provider<Cache<K, V>>, CacheBinding<K, V>,
@Override @Override
@Nullable @Nullable
public Long expireAfterWrite(TimeUnit unit) { public Duration expireAfterWrite() {
return expireAfterWrite != null ? unit.convert(expireAfterWrite, SECONDS) : null; return expireAfterWrite;
} }
@Override @Override

View File

@@ -16,7 +16,7 @@ package com.google.gerrit.server.cache;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.Weigher; import com.google.common.cache.Weigher;
import java.util.concurrent.TimeUnit; import java.time.Duration;
/** Configure a persistent cache declared within a {@link CacheModule} instance. */ /** Configure a persistent cache declared within a {@link CacheModule} instance. */
public interface PersistentCacheBinding<K, V> extends CacheBinding<K, V> { public interface PersistentCacheBinding<K, V> extends CacheBinding<K, V> {
@@ -24,7 +24,7 @@ public interface PersistentCacheBinding<K, V> extends CacheBinding<K, V> {
PersistentCacheBinding<K, V> maximumWeight(long weight); PersistentCacheBinding<K, V> maximumWeight(long weight);
@Override @Override
PersistentCacheBinding<K, V> expireAfterWrite(long duration, TimeUnit durationUnits); PersistentCacheBinding<K, V> expireAfterWrite(Duration duration);
@Override @Override
PersistentCacheBinding<K, V> loader(Class<? extends CacheLoader<K, V>> clazz); PersistentCacheBinding<K, V> loader(Class<? extends CacheLoader<K, V>> clazz);

View File

@@ -24,7 +24,7 @@ import com.google.inject.Inject;
import com.google.inject.Provider; import com.google.inject.Provider;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import java.io.Serializable; import java.io.Serializable;
import java.util.concurrent.TimeUnit; import java.time.Duration;
class PersistentCacheProvider<K, V> extends CacheProvider<K, V> class PersistentCacheProvider<K, V> extends CacheProvider<K, V>
implements Provider<Cache<K, V>>, PersistentCacheBinding<K, V>, PersistentCacheDef<K, V> { implements Provider<Cache<K, V>>, PersistentCacheBinding<K, V>, PersistentCacheDef<K, V> {
@@ -53,8 +53,8 @@ class PersistentCacheProvider<K, V> extends CacheProvider<K, V>
} }
@Override @Override
public PersistentCacheBinding<K, V> expireAfterWrite(long duration, TimeUnit durationUnits) { public PersistentCacheBinding<K, V> expireAfterWrite(Duration duration) {
return (PersistentCacheBinding<K, V>) super.expireAfterWrite(duration, durationUnits); return (PersistentCacheBinding<K, V>) super.expireAfterWrite(duration);
} }
@Override @Override

View File

@@ -3,6 +3,7 @@ java_library(
srcs = glob(["**/*.java"]), srcs = glob(["**/*.java"]),
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//java/com/google/gerrit/common:annotations",
"//java/com/google/gerrit/common:server", "//java/com/google/gerrit/common:server",
"//java/com/google/gerrit/extensions:api", "//java/com/google/gerrit/extensions:api",
"//java/com/google/gerrit/lifecycle", "//java/com/google/gerrit/lifecycle",

View File

@@ -16,11 +16,12 @@ package com.google.gerrit.server.cache.h2;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.Weigher; import com.google.common.cache.Weigher;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.server.cache.CacheSerializer; import com.google.gerrit.server.cache.CacheSerializer;
import com.google.gerrit.server.cache.PersistentCacheDef; import com.google.gerrit.server.cache.PersistentCacheDef;
import com.google.gerrit.server.cache.h2.H2CacheImpl.ValueHolder; import com.google.gerrit.server.cache.h2.H2CacheImpl.ValueHolder;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import java.util.concurrent.TimeUnit; import java.time.Duration;
class H2CacheDefProxy<K, V> implements PersistentCacheDef<K, V> { class H2CacheDefProxy<K, V> implements PersistentCacheDef<K, V> {
private final PersistentCacheDef<K, V> source; private final PersistentCacheDef<K, V> source;
@@ -30,8 +31,9 @@ class H2CacheDefProxy<K, V> implements PersistentCacheDef<K, V> {
} }
@Override @Override
public Long expireAfterWrite(TimeUnit unit) { @Nullable
return source.expireAfterWrite(unit); public Duration expireAfterWrite() {
return source.expireAfterWrite();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@@ -215,7 +215,6 @@ class H2CacheFactory implements PersistentCacheFactory, LifecycleListener {
if (h2AutoServer) { if (h2AutoServer) {
url.append(";AUTO_SERVER=TRUE"); url.append(";AUTO_SERVER=TRUE");
} }
Long expireAfterWrite = def.expireAfterWrite(TimeUnit.SECONDS);
return new SqlStore<>( return new SqlStore<>(
url.toString(), url.toString(),
def.keyType(), def.keyType(),
@@ -223,6 +222,6 @@ class H2CacheFactory implements PersistentCacheFactory, LifecycleListener {
def.valueSerializer(), def.valueSerializer(),
def.version(), def.version(),
maxSize, maxSize,
expireAfterWrite == null ? 0 : expireAfterWrite.longValue()); def.expireAfterWrite());
} }
} }

View File

@@ -23,6 +23,7 @@ import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger; import com.google.common.flogger.FluentLogger;
import com.google.common.hash.BloomFilter; import com.google.common.hash.BloomFilter;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.TimeUtil; import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.server.cache.CacheSerializer; import com.google.gerrit.server.cache.CacheSerializer;
import com.google.gerrit.server.cache.PersistentCache; import com.google.gerrit.server.cache.PersistentCache;
@@ -35,6 +36,7 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.Duration;
import java.util.Calendar; import java.util.Calendar;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
@@ -254,7 +256,7 @@ public class H2CacheImpl<K, V> extends AbstractLoadingCache<K, V> implements Per
private final CacheSerializer<V> valueSerializer; private final CacheSerializer<V> valueSerializer;
private final int version; private final int version;
private final long maxSize; private final long maxSize;
private final long expireAfterWrite; @Nullable private final Duration expireAfterWrite;
private final BlockingQueue<SqlHandle> handles; private final BlockingQueue<SqlHandle> handles;
private final AtomicLong hitCount = new AtomicLong(); private final AtomicLong hitCount = new AtomicLong();
private final AtomicLong missCount = new AtomicLong(); private final AtomicLong missCount = new AtomicLong();
@@ -268,7 +270,7 @@ public class H2CacheImpl<K, V> extends AbstractLoadingCache<K, V> implements Per
CacheSerializer<V> valueSerializer, CacheSerializer<V> valueSerializer,
int version, int version,
long maxSize, long maxSize,
long expireAfterWrite) { @Nullable Duration expireAfterWrite) {
this.url = jdbcUrl; this.url = jdbcUrl;
this.keyType = createKeyType(keyType, keySerializer); this.keyType = createKeyType(keyType, keySerializer);
this.valueSerializer = valueSerializer; this.valueSerializer = valueSerializer;
@@ -421,11 +423,11 @@ public class H2CacheImpl<K, V> extends AbstractLoadingCache<K, V> implements Per
} }
private boolean expired(Timestamp created) { private boolean expired(Timestamp created) {
if (expireAfterWrite == 0) { if (expireAfterWrite == null) {
return false; return false;
} }
long age = TimeUtil.nowMs() - created.getTime(); Duration age = Duration.between(created.toInstant(), TimeUtil.now());
return 1000 * expireAfterWrite < age; return age.compareTo(expireAfterWrite) > 0;
} }
private void touch(SqlHandle c, K key) throws IOException, SQLException { private void touch(SqlHandle c, K key) throws IOException, SQLException {

View File

@@ -26,6 +26,7 @@ import com.google.gerrit.server.cache.MemoryCacheFactory;
import com.google.gerrit.server.config.ConfigUtil; import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.time.Duration;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Config;
@@ -66,14 +67,19 @@ class DefaultMemoryCacheFactory implements MemoryCacheFactory {
} }
builder.weigher(weigher); builder.weigher(weigher);
Long age = def.expireAfterWrite(TimeUnit.SECONDS); Duration age = def.expireAfterWrite();
if (has(def.configKey(), "maxAge")) { if (has(def.configKey(), "maxAge")) {
builder.expireAfterWrite( builder.expireAfterWrite(
ConfigUtil.getTimeUnit( ConfigUtil.getTimeUnit(
cfg, "cache", def.configKey(), "maxAge", age != null ? age : 0, TimeUnit.SECONDS), cfg,
"cache",
def.configKey(),
"maxAge",
age != null ? age.getSeconds() : 0,
TimeUnit.SECONDS),
TimeUnit.SECONDS); TimeUnit.SECONDS);
} else if (age != null) { } else if (age != null) {
builder.expireAfterWrite(age, TimeUnit.SECONDS); builder.expireAfterWrite(age.toNanos(), TimeUnit.NANOSECONDS);
} }
return builder; return builder;

View File

@@ -47,7 +47,7 @@ public class H2CacheTest {
StringSerializer.INSTANCE, StringSerializer.INSTANCE,
version, version,
1 << 20, 1 << 20,
0); null);
return new H2CacheImpl<>(MoreExecutors.directExecutor(), store, KEY_TYPE, mem); return new H2CacheImpl<>(MoreExecutors.directExecutor(), store, KEY_TYPE, mem);
} }