
com.aliyun.credentials.provider.RefreshCachedSupplier Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of credentials-java Show documentation
Show all versions of credentials-java Show documentation
Alibaba Cloud Credentials for Java
Copyright (C) Alibaba Cloud Computing
All rights reserved.
版权所有 (C)阿里云计算有限公司
https://www.aliyun.com
package com.aliyun.credentials.provider;
import com.aliyun.credentials.exception.CredentialException;
import com.aliyun.tea.utils.Validate;
import java.util.Date;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static java.util.concurrent.TimeUnit.SECONDS;
public class RefreshCachedSupplier implements AutoCloseable {
/**
* Maximum time to wait for a blocking refresh lock before calling refresh again. Unit of milliseconds.
*/
private static final long REFRESH_BLOCKING_MAX_WAIT = 5 * 1000;
private final Lock refreshLock = new ReentrantLock();
private final AtomicBoolean asyncRefreshing = new AtomicBoolean(false);
private final ExecutorService executor = new ThreadPoolExecutor(0, 1, 5, SECONDS,
new LinkedBlockingQueue(1),
Executors.defaultThreadFactory());
private volatile RefreshResult cachedValue = RefreshResult.builder((T) null)
.staleTime(0)
.build();
private final Callable> refreshCallable;
private final boolean asyncUpdateEnabled;
private RefreshCachedSupplier(Builder builder) {
this.refreshCallable = Validate.notNull(builder.refreshCallable, "Refresh Callable is null.");
this.asyncUpdateEnabled = builder.asyncUpdateEnabled;
}
public static Builder builder(Callable> refreshCallable) {
return new Builder(refreshCallable);
}
public T get() {
if (cacheIsStale()) {
if (this.asyncUpdateEnabled) {
asyncRefresh();
} else {
blockingRefresh();
}
}
return null != this.cachedValue ? this.cachedValue.value() : null;
}
private void refreshCache() {
try {
this.cachedValue = refreshCallable.call();
} catch (CredentialException ex) {
throw ex;
} catch (Exception e) {
throw new CredentialException("Failed to refresh credentials.", e);
}
}
private void blockingRefresh() {
try {
if (refreshLock.tryLock(REFRESH_BLOCKING_MAX_WAIT, TimeUnit.MILLISECONDS)) {
try {
if (cacheIsStale()) {
refreshCache();
}
} finally {
refreshLock.unlock();
}
}
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
throw new IllegalStateException("Interrupted waiting to refresh the value.", ex);
} catch (Exception ex) {
throw ex;
}
}
/**
* Used to asynchronously refresh the value. Caller is never blocked.
*/
private void asyncRefresh() {
// Immediately return if refresh already in progress
if (asyncRefreshing.compareAndSet(false, true)) {
try {
executor.submit(new Runnable() {
@Override
public void run() {
try {
refreshCache();
} finally {
asyncRefreshing.set(false);
}
}
});
} catch (RuntimeException ex) {
asyncRefreshing.set(false);
throw ex;
}
}
}
@Override
public void close() {
executor.shutdown();
}
private boolean cacheIsStale() {
return this.cachedValue == null || new Date().getTime() >= this.cachedValue.staleTime();
}
public static final class Builder {
private final Callable> refreshCallable;
private boolean asyncUpdateEnabled;
private Builder(Callable> refreshCallable) {
this.refreshCallable = refreshCallable;
}
public Builder asyncUpdateEnabled(Boolean asyncUpdateEnabled) {
this.asyncUpdateEnabled = asyncUpdateEnabled;
return this;
}
public RefreshCachedSupplier build() {
return new RefreshCachedSupplier(this);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy