com.aliyun.auth.credentials.utils.RefreshCachedSupplier Maven / Gradle / Ivy
The newest version!
package com.aliyun.auth.credentials.utils;
import com.aliyun.core.utils.SdkAutoCloseable;
import com.aliyun.core.utils.Validate;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;
public final class RefreshCachedSupplier implements Supplier, SdkAutoCloseable {
private static final Duration REFRESH_BLOCKING_MAX_WAIT = Duration.ofSeconds(5);
private final Lock refreshLock = new ReentrantLock();
private final PrefetchStrategy prefetchStrategy;
private volatile RefreshResult cachedValue = RefreshResult.builder((T) null)
.staleTime(Instant.MIN)
.prefetchTime(Instant.MIN)
.build();
private final Supplier> valueSupplier;
private RefreshCachedSupplier(Builder builder) {
this.valueSupplier = Validate.notNull(builder.supplier, "CachedSupplier.supplier is null.");
this.prefetchStrategy = Validate.notNull(builder.prefetchStrategy, "CachedSupplier.prefetchStrategy is null.");
}
public static Builder builder(Supplier> valueSupplier) {
return new Builder<>(valueSupplier);
}
@Override
public T get() {
if (cacheIsStale()) {
refreshCache();
} else if (shouldInitiateCachePrefetch()) {
prefetchCache();
}
return this.cachedValue.value();
}
private boolean cacheIsStale() {
return Instant.now().isAfter(cachedValue.staleTime());
}
private boolean shouldInitiateCachePrefetch() {
return Instant.now().isAfter(cachedValue.prefetchTime());
}
private void prefetchCache() {
prefetchStrategy.prefetch(this::refreshCache);
}
private void refreshCache() {
try {
boolean lockAcquired = refreshLock.tryLock(REFRESH_BLOCKING_MAX_WAIT.getSeconds(), TimeUnit.SECONDS);
try {
if (cacheIsStale() || shouldInitiateCachePrefetch()) {
cachedValue = valueSupplier.get();
}
} finally {
if (lockAcquired) {
refreshLock.unlock();
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException("Interrupted waiting to refresh the value.", e);
}
}
@Override
public void close() {
prefetchStrategy.close();
}
public static final class Builder {
private final Supplier> supplier;
private PrefetchStrategy prefetchStrategy = new OneCallerBlocks();
private Builder(Supplier> supplier) {
this.supplier = supplier;
}
public Builder prefetchStrategy(PrefetchStrategy prefetchStrategy) {
this.prefetchStrategy = prefetchStrategy;
return this;
}
public RefreshCachedSupplier build() {
return new RefreshCachedSupplier<>(this);
}
}
@FunctionalInterface
public interface PrefetchStrategy extends SdkAutoCloseable {
void prefetch(Runnable valueUpdater);
default void close() {
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy