mirror of
https://github.com/moparisthebest/JdbcMapper
synced 2025-02-16 07:00:16 -05:00
Add Cache utilities for java8+ only
This commit is contained in:
parent
d6d77c9528
commit
f290187ee0
60
common/src/main/java/com/moparisthebest/jdbc/cache/Cache.java
vendored
Normal file
60
common/src/main/java/com/moparisthebest/jdbc/cache/Cache.java
vendored
Normal file
@ -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
Normal file
79
common/src/main/java/com/moparisthebest/jdbc/cache/FunctionCache.java
vendored
Normal file
@ -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
Normal file
14
common/src/main/java/com/moparisthebest/jdbc/cache/FunctionSupplier.java
vendored
Normal file
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user