Skip to content

Commit

Permalink
feat: add shutdown() to ConnectorRegistry (#335)
Browse files Browse the repository at this point in the history
  • Loading branch information
ttosta-google committed Dec 11, 2023
1 parent ac3ee73 commit ce4de4e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,12 @@ public static void close(String name) {
public static void reset() {
InternalConnectorRegistry.INSTANCE.resetInstance();
}

/**
* Shutdown the entire AlloyDB JDBC Connector. This will stop all background threads. All future
* attempts to connect to the database will fail.
*/
public static void shutdown() {
InternalConnectorRegistry.INSTANCE.shutdownInstance();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.errorprone.annotations.concurrent.GuardedBy;
import java.io.Closeable;
import java.io.IOException;
import java.net.Socket;
Expand All @@ -45,6 +46,13 @@ enum InternalConnectorRegistry implements Closeable {
@SuppressWarnings("ImmutableEnumChecker")
private ConcurrentHashMap<String, Connector> namedConnectors;

@SuppressWarnings("ImmutableEnumChecker")
private final Object shutdownGuard = new Object();

@SuppressWarnings("ImmutableEnumChecker")
@GuardedBy("shutdownGuard")
private boolean shutdown = false;

InternalConnectorRegistry() {
// During refresh, each instance consumes 2 threads from the thread pool. By using 8 threads,
// there should be enough free threads so that there will not be a deadlock. Most users
Expand All @@ -70,6 +78,12 @@ void setCredentialFactoryProvider(CredentialFactoryProvider credentialFactoryPro
* @throws IOException if error occurs during socket creation.
*/
public Socket connect(ConnectionConfig config) throws IOException {
synchronized (shutdownGuard) {
if (shutdown) {
throw new IllegalStateException("ConnectorRegistry was shut down.");
}
}

if (config.getNamedConnector() != null) {
Connector connector = getNamedConnector(config.getNamedConnector());
return connector.connect(config.withConnectorConfig(connector.getConfig()));
Expand All @@ -86,6 +100,12 @@ public Socket connect(ConnectionConfig config) throws IOException {

/** Register the configuration for a named connector. */
public void register(String name, ConnectorConfig config) {
synchronized (shutdownGuard) {
if (shutdown) {
throw new IllegalStateException("ConnectorRegistry was shut down.");
}
}

if (this.namedConnectors.containsKey(name)) {
throw new IllegalArgumentException("Named connection " + name + " exists.");
}
Expand All @@ -94,15 +114,21 @@ public void register(String name, ConnectorConfig config) {

/** Close a named connector, stopping the refresh process and removing it from the registry. */
public void close(String name) {
synchronized (shutdownGuard) {
if (shutdown) {
throw new IllegalStateException("ConnectorRegistry was shut down.");
}
}

Connector connector = namedConnectors.remove(name);
if (connector == null) {
throw new IllegalArgumentException("Named connection " + name + " does not exist.");
}
connector.close();
}

/** Shutdown all connectors and remove the singleton instance. */
private void shutdown() {
/** Shutdown all connectors. */
private void shutdownConnectors() {
this.unnamedConnectors.forEach((key, c) -> c.close());
this.unnamedConnectors.clear();
this.namedConnectors.forEach((key, c) -> c.close());
Expand All @@ -111,13 +137,21 @@ private void shutdown() {

@Override
public void close() {
shutdown();
this.executor.shutdown();
shutdownInstance();
}

/** Calls shutdown on the singleton. */
public void resetInstance() {
shutdown();
shutdownConnectors();
}

/** Calls shutdown on the singleton. */
public void shutdownInstance() {
synchronized (shutdownGuard) {
shutdown = true;
shutdownConnectors();
this.executor.shutdown();
}
}

private Connector getConnector(ConnectionConfig config) {
Expand Down
18 changes: 15 additions & 3 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,21 @@ ConnectorRegistry.reset();
```

After calling `ConnectorRegistry.reset()`, the next attempt to connect to a
database using a SocketFactory or R2DBC ConnectionFactory, or
to `ConnectorRegistry.register()` will start a new connector registry, restart
the background threads, and create a new connector.
database, or to `ConnectorRegistry.register()` will start a new connector
registry, restart the background threads, and create a new connector.

### Shutdown The Connector Registry

The application may shut down the ConnectorRegistry. This closes all existing
named and unnamed connectors, and stops internal background threads.

```java
ConnectorRegistry.shutdown();
```

After calling `ConnectorRegistry.shutdown()`, subsequent attempts to connect to
a database, or to `ConnectorRegistry.register()` will fail,
throwing `IllegalStateException`.

## Configuring Google Credentials

Expand Down

0 comments on commit ce4de4e

Please sign in to comment.