in alloydb-jdbc-connector/src/main/java/com/google/cloud/alloydb/Refresher.java [222:285]
private ListenableFuture<ConnectionInfo> handleRefreshResult(
ListenableFuture<ConnectionInfo> connectionInfoFuture) {
try {
// This does not block, because it only gets called when connectionInfoFuture has completed.
// This will throw an exception if the refresh attempt has failed.
ConnectionInfo info = connectionInfoFuture.get();
logger.debug(
String.format(
"[%s] Refresh Operation: Completed refresh with new certificate expiration at %s.",
name, info.getExpiration().toString()));
long secondsToRefresh =
refreshCalculator.calculateSecondsUntilNextRefresh(Instant.now(), info.getExpiration());
synchronized (connectionInfoGuard) {
// Refresh completed successfully, reset forceRefreshRunning.
refreshRunning = false;
currentRefreshFailure = null;
current = Futures.immediateFuture(info);
// Now update nextInstanceData to perform a refresh after the
// scheduled delay
if (!closed && triggerNextRefresh) {
logger.debug(
String.format(
"[%s] Refresh Operation: Next operation scheduled at %s.",
name,
Instant.now()
.plus(secondsToRefresh, ChronoUnit.SECONDS)
.truncatedTo(ChronoUnit.SECONDS)
.toString()));
next =
Futures.scheduleAsync(
this::startRefreshAttempt, secondsToRefresh, TimeUnit.SECONDS, executor);
}
// Resolves to an T immediately
return current;
}
} catch (ExecutionException | InterruptedException e) {
// No refresh retry when the TerminalException is raised.
final Throwable cause = e.getCause();
if (cause instanceof TerminalException) {
logger.debug(String.format("[%s] Refresh Operation: Failed! No retry.", name), e);
throw (TerminalException) cause;
}
logger.debug(
String.format(
"[%s] Refresh Operation: Failed! Starting next refresh operation immediately.", name),
e);
synchronized (connectionInfoGuard) {
currentRefreshFailure = e;
if (!closed) {
next = this.startRefreshAttempt();
}
// Resolves after the next successful refresh attempt.
return next;
}
}
}