Browse Source

Add Cache utilities for java8+ only

dependabot/maven/junit-junit-4.13.1
Travis Burtrum 4 years ago
parent
commit
f290187ee0
  1. 60
      common/src/main/java/com/moparisthebest/jdbc/cache/Cache.java
  2. 79
      common/src/main/java/com/moparisthebest/jdbc/cache/FunctionCache.java
  3. 14
      common/src/main/java/com/moparisthebest/jdbc/cache/FunctionSupplier.java
  4. 1
      pom.xml

60
common/src/main/java/com/moparisthebest/jdbc/cache/Cache.java vendored

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
package com.moparisthebest.jdbc.cache;
import java.time.Duration;
import java.time.Instant;
import java.util.Objects;
import java.util.function.Supplier;
/**
* This implements a simple cache, meant to be accessed concurrently from multiple threads, that is refreshed on a user
* defined interval.
*
* Most often instances of this class will be `static final` so the entire application can benefit from the cache
*
* @param <T> type of cached item
*/
public class Cache<T> implements Supplier<T> {
public static <T> Supplier<T> of(final Duration refreshInterval, final Supplier<T> supplier) {
return new Cache<>(refreshInterval, supplier);
}
private final Duration refreshInterval;
private Instant lastRefresh;
protected final Supplier<T> supplier;
protected T item;
protected Cache(final Duration refreshInterval, final Supplier<T> supplier) {
Objects.requireNonNull(refreshInterval);
// we are explicitly allowing supplier to be null, in which case get() will fail
this.refreshInterval = refreshInterval;
this.supplier = supplier;
// so refresh will be called immediately
this.lastRefresh = Instant.MIN;
}
protected boolean shouldRefresh() {
return Instant.now().isAfter(lastRefresh.plus(refreshInterval));
}
protected void markRefreshed() {
this.lastRefresh = Instant.now();
}
@Override
public T get() {
if (shouldRefresh()) {
// we want to refresh
synchronized (this) {
if (shouldRefresh()) {
// maybe another thread beat us in here and already refreshed
this.item = supplier.get();
markRefreshed();
}
}
}
return item;
}
}

79
common/src/main/java/com/moparisthebest/jdbc/cache/FunctionCache.java vendored

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
package com.moparisthebest.jdbc.cache;
import com.moparisthebest.jdbc.Factory;
import java.sql.SQLException;
import java.time.Duration;
import java.time.Instant;
import java.util.function.Function;
import java.util.function.Supplier;
import static com.moparisthebest.jdbc.TryClose.tryClose;
/**
* This implements a simple cache, meant to be accessed concurrently from multiple threads, that is refreshed on a user
* defined interval.
*
* Most often instances of this class will be `static final` so the entire application can benefit from the cache
*
* This adds a method on top of Cache that allows the caller to send in a parameter for the refreshing function to use,
* this will most often be used to send in an already-open java.sql.Connection or JdbcMapper instance
*
* @param <T> type of cached item
*/
public class FunctionCache<T, F> extends Cache<T> implements FunctionSupplier<T, F> {
public static <T, F> FunctionSupplier<T, F> ofNotCloseable(final Duration refreshInterval, final Function<F, T> function, final Supplier<F> factory) {
return of(refreshInterval, function, () -> function.apply(factory.get()));
}
public static <T, F extends AutoCloseable> FunctionSupplier<T, F> ofSupplier(final Duration refreshInterval, final Function<F, T> function, final Supplier<F> factory) {
return ofFactory(refreshInterval, function, factory::get);
}
public static <T, F extends AutoCloseable> FunctionSupplier<T, F> ofFactory(final Duration refreshInterval, final Function<F, T> function, final Factory<F> factory) {
return of(refreshInterval, function, () -> {
F f = null;
try {
try {
f = factory.create();
} catch (SQLException e) {
throw new RuntimeException(e);
}
return function.apply(f);
} finally {
tryClose(f);
}
});
}
public static <T, F> FunctionSupplier<T, F> of(final Duration refreshInterval, final Function<F, T> function, final Supplier<T> supplier) {
return new FunctionCache<>(refreshInterval, function, supplier);
}
public static <T, F> Function<F, T> of(final Duration refreshInterval, final Function<F, T> function) {
return of(refreshInterval, function, null);
}
protected final Function<F, T> function;
protected FunctionCache(final Duration refreshInterval, final Function<F, T> function, final Supplier<T> supplier) {
super(refreshInterval, supplier);
this.function = function;
}
@Override
public T get(final F f) {
if (shouldRefresh()) {
// we want to refresh
synchronized (this) {
if (shouldRefresh()) {
// maybe another thread beat us in here and already refreshed
this.item = function.apply(f);
markRefreshed();
}
}
}
return item;
}
}

14
common/src/main/java/com/moparisthebest/jdbc/cache/FunctionSupplier.java vendored

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
package com.moparisthebest.jdbc.cache;
import java.util.function.Function;
import java.util.function.Supplier;
public interface FunctionSupplier<T, F> extends Supplier<T>, Function<F, T> {
T get(F f);
@Override
default T apply(final F f) {
return get(f);
}
}

1
pom.xml

@ -246,6 +246,7 @@ @@ -246,6 +246,7 @@
<excludes>
<exclude>**/module-info.java</exclude>
<exclude>**/PrestoPersonDAO.java</exclude>
<exclude>**/com/moparisthebest/jdbc/cache/*</exclude>
</excludes>
<compilerArgs>
<compilerArg>-Xlint:unchecked</compilerArg>

Loading…
Cancel
Save