From bffdccedf8277abbe16fb2df6161fb4fce655067 Mon Sep 17 00:00:00 2001 From: Crystal Liang Date: Wed, 23 Aug 2023 20:04:45 -0700 Subject: [PATCH] refactor: change getHostSpecByStrategy and getHost methods to pass properties --- .../amazon/jdbc/ConnectionPlugin.java | 2 +- .../amazon/jdbc/ConnectionPluginManager.java | 4 +- .../amazon/jdbc/ConnectionProvider.java | 2 +- .../jdbc/ConnectionProviderManager.java | 6 +- .../jdbc/DataSourceConnectionProvider.java | 13 +- .../amazon/jdbc/DriverConnectionProvider.java | 13 +- .../jdbc/HikariPooledConnectionProvider.java | 33 +--- .../software/amazon/jdbc/HostSelector.java | 4 +- .../jdbc/LeastConnectionsHostSelector.java | 8 +- .../software/amazon/jdbc/PluginService.java | 2 +- .../amazon/jdbc/PluginServiceImpl.java | 4 +- .../amazon/jdbc/RandomHostSelector.java | 3 +- .../amazon/jdbc/RoundRobinHostSelector.java | 158 +++++++++-------- .../jdbc/plugin/AbstractConnectionPlugin.java | 2 +- .../jdbc/plugin/DefaultConnectionPlugin.java | 4 +- .../ReadWriteSplittingPlugin.java | 5 +- .../HikariPooledConnectionProviderTest.java | 4 +- .../amazon/jdbc/mock/TestPluginOne.java | 2 +- .../plugin/RoundRobinHostSelectorTest.java | 160 ++++++------------ .../jdbc/plugin/efm/ConcurrencyTests.java | 2 +- .../ReadWriteSplittingPluginTest.java | 2 +- 21 files changed, 177 insertions(+), 256 deletions(-) diff --git a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPlugin.java index 95b51d664..adac9d673 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPlugin.java @@ -128,7 +128,7 @@ Connection forceConnect( * @throws UnsupportedOperationException if this {@link ConnectionPlugin} does not support the * requested strategy */ - HostSpec getHostSpecByStrategy(final HostRole role, final String strategy) + HostSpec getHostSpecByStrategy(final HostRole role, final String strategy, final Properties props) throws SQLException, UnsupportedOperationException; void initHostProvider( diff --git a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginManager.java b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginManager.java index 8854fa381..a9c76dde2 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginManager.java +++ b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginManager.java @@ -381,7 +381,7 @@ public boolean acceptsStrategy(HostRole role, String strategy) throws SQLExcepti * {@link ConnectionPlugin} instances do not support the * requested strategy */ - public HostSpec getHostSpecByStrategy(HostRole role, String strategy) + public HostSpec getHostSpecByStrategy(HostRole role, String strategy, Properties props) throws SQLException, UnsupportedOperationException { try { for (ConnectionPlugin plugin : this.plugins) { @@ -392,7 +392,7 @@ public HostSpec getHostSpecByStrategy(HostRole role, String strategy) if (isSubscribed) { try { - final HostSpec host = plugin.getHostSpecByStrategy(role, strategy); + final HostSpec host = plugin.getHostSpecByStrategy(role, strategy, props); if (host != null) { return host; } diff --git a/wrapper/src/main/java/software/amazon/jdbc/ConnectionProvider.java b/wrapper/src/main/java/software/amazon/jdbc/ConnectionProvider.java index b7c413f6f..03a5230ed 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/ConnectionProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/ConnectionProvider.java @@ -64,7 +64,7 @@ boolean acceptsUrl( * @throws UnsupportedOperationException if the strategy is unsupported by the provider */ HostSpec getHostSpecByStrategy( - @NonNull List hosts, @NonNull HostRole role, @NonNull String strategy) + @NonNull List hosts, @NonNull HostRole role, @NonNull String strategy, @NonNull Properties props) throws SQLException, UnsupportedOperationException; /** diff --git a/wrapper/src/main/java/software/amazon/jdbc/ConnectionProviderManager.java b/wrapper/src/main/java/software/amazon/jdbc/ConnectionProviderManager.java index 74cadf021..9e10919c0 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/ConnectionProviderManager.java +++ b/wrapper/src/main/java/software/amazon/jdbc/ConnectionProviderManager.java @@ -141,14 +141,14 @@ public boolean acceptsStrategy(HostRole role, String strategy) { * @throws UnsupportedOperationException if the available {@link ConnectionProvider} instances do * not support the requested strategy */ - public HostSpec getHostSpecByStrategy(List hosts, HostRole role, String strategy) + public HostSpec getHostSpecByStrategy(List hosts, HostRole role, String strategy, Properties props) throws SQLException, UnsupportedOperationException { HostSpec host = null; if (connProvider != null) { connProviderLock.readLock().lock(); try { if (connProvider != null && connProvider.acceptsStrategy(role, strategy)) { - host = connProvider.getHostSpecByStrategy(hosts, role, strategy); + host = connProvider.getHostSpecByStrategy(hosts, role, strategy, props); } } catch (UnsupportedOperationException e) { // The custom provider does not support the provided strategy, ignore it and try with the default provider. @@ -158,7 +158,7 @@ public HostSpec getHostSpecByStrategy(List hosts, HostRole role, Strin } if (host == null) { - host = defaultProvider.getHostSpecByStrategy(hosts, role, strategy); + host = defaultProvider.getHostSpecByStrategy(hosts, role, strategy, props); } return host; diff --git a/wrapper/src/main/java/software/amazon/jdbc/DataSourceConnectionProvider.java b/wrapper/src/main/java/software/amazon/jdbc/DataSourceConnectionProvider.java index 3433fa092..95889f849 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/DataSourceConnectionProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/DataSourceConnectionProvider.java @@ -29,7 +29,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.exceptions.SQLLoginException; -import software.amazon.jdbc.plugin.readwritesplitting.ReadWriteSplittingPlugin; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; @@ -88,7 +87,7 @@ public boolean acceptsStrategy(@NonNull HostRole role, @NonNull String strategy) @Override public HostSpec getHostSpecByStrategy( - @NonNull List hosts, @NonNull HostRole role, @NonNull String strategy) + @NonNull List hosts, @NonNull HostRole role, @NonNull String strategy, @NonNull Properties props) throws SQLException { if (!acceptedStrategies.containsKey(strategy)) { throw new UnsupportedOperationException( @@ -97,7 +96,7 @@ public HostSpec getHostSpecByStrategy( new Object[] {strategy, DataSourceConnectionProvider.class})); } - return acceptedStrategies.get(strategy).getHost(hosts, role); + return acceptedStrategies.get(strategy).getHost(hosts, role, props); } /** @@ -116,14 +115,6 @@ public Connection connect( final @NonNull HostSpec hostSpec, final @NonNull Properties props) throws SQLException { - final String strategy = ReadWriteSplittingPlugin.READER_HOST_SELECTOR_STRATEGY.getString(props); - if (RoundRobinHostSelector.STRATEGY_ROUND_ROBIN.equals(strategy)) { - final RoundRobinHostSelector roundRobinHostSelector = - (RoundRobinHostSelector) acceptedStrategies.get(RoundRobinHostSelector.STRATEGY_ROUND_ROBIN); - if (roundRobinHostSelector.getHostCacheEntry(hostSpec) != null) { - roundRobinHostSelector.updateCachePropertiesForHost(hostSpec, props); - } - } final Properties copy = PropertyUtils.copyProperties(props); diff --git a/wrapper/src/main/java/software/amazon/jdbc/DriverConnectionProvider.java b/wrapper/src/main/java/software/amazon/jdbc/DriverConnectionProvider.java index 2dd7f5027..1c1be9faa 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/DriverConnectionProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/DriverConnectionProvider.java @@ -27,7 +27,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.exceptions.SQLLoginException; -import software.amazon.jdbc.plugin.readwritesplitting.ReadWriteSplittingPlugin; import software.amazon.jdbc.targetdriverdialect.ConnectInfo; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.Messages; @@ -83,7 +82,7 @@ public boolean acceptsStrategy(@NonNull HostRole role, @NonNull String strategy) @Override public HostSpec getHostSpecByStrategy( - @NonNull List hosts, @NonNull HostRole role, @NonNull String strategy) + @NonNull List hosts, @NonNull HostRole role, @NonNull String strategy, @NonNull Properties props) throws SQLException { if (!acceptedStrategies.containsKey(strategy)) { throw new UnsupportedOperationException( @@ -92,7 +91,7 @@ public HostSpec getHostSpecByStrategy( new Object[] {strategy, DriverConnectionProvider.class})); } - return acceptedStrategies.get(strategy).getHost(hosts, role); + return acceptedStrategies.get(strategy).getHost(hosts, role, props); } /** @@ -111,14 +110,6 @@ public Connection connect( final @NonNull HostSpec hostSpec, final @NonNull Properties props) throws SQLException { - final String strategy = ReadWriteSplittingPlugin.READER_HOST_SELECTOR_STRATEGY.getString(props); - if (RoundRobinHostSelector.STRATEGY_ROUND_ROBIN.equals(strategy)) { - final RoundRobinHostSelector roundRobinHostSelector = - (RoundRobinHostSelector) acceptedStrategies.get(RoundRobinHostSelector.STRATEGY_ROUND_ROBIN); - if (roundRobinHostSelector.getHostCacheEntry(hostSpec) != null) { - roundRobinHostSelector.updateCachePropertiesForHost(hostSpec, props); - } - } final Properties copy = PropertyUtils.copyProperties(props); final ConnectInfo connectInfo = diff --git a/wrapper/src/main/java/software/amazon/jdbc/HikariPooledConnectionProvider.java b/wrapper/src/main/java/software/amazon/jdbc/HikariPooledConnectionProvider.java index a5d6875ab..638b3ce9a 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/HikariPooledConnectionProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/HikariPooledConnectionProvider.java @@ -33,7 +33,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.cleanup.CanReleaseResources; import software.amazon.jdbc.dialect.Dialect; -import software.amazon.jdbc.plugin.readwritesplitting.ReadWriteSplittingPlugin; import software.amazon.jdbc.util.HikariCPSQLException; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.RdsUrlType; @@ -47,12 +46,11 @@ public class HikariPooledConnectionProvider implements PooledConnectionProvider, private static final Logger LOGGER = Logger.getLogger(HikariPooledConnectionProvider.class.getName()); private static final Map acceptedStrategies = - Collections.unmodifiableMap(new HashMap() { + new HashMap() { { - put(LeastConnectionsHostSelector.STRATEGY_LEAST_CONNECTIONS, new LeastConnectionsHostSelector()); put(RoundRobinHostSelector.STRATEGY_ROUND_ROBIN, new RoundRobinHostSelector()); } - }); + }; private static final RdsUtils rdsUtils = new RdsUtils(); private static SlidingExpirationCache databasePools = new SlidingExpirationCache<>( @@ -104,10 +102,8 @@ public HikariPooledConnectionProvider( HikariPoolConfigurator hikariPoolConfigurator, HikariPoolMapping mapping) { this.poolConfigurator = hikariPoolConfigurator; this.poolMapping = mapping; - final LeastConnectionsHostSelector hostSelector = - (LeastConnectionsHostSelector) acceptedStrategies - .get(LeastConnectionsHostSelector.STRATEGY_LEAST_CONNECTIONS); - hostSelector.setDatabasePools(databasePools); + final LeastConnectionsHostSelector hostSelector = new LeastConnectionsHostSelector(databasePools); + acceptedStrategies.put(LeastConnectionsHostSelector.STRATEGY_LEAST_CONNECTIONS, hostSelector); } /** @@ -144,10 +140,8 @@ public HikariPooledConnectionProvider( this.poolMapping = mapping; poolExpirationCheckNanos = poolExpirationNanos; databasePools.setCleanupIntervalNanos(poolCleanupNanos); - final LeastConnectionsHostSelector hostSelector = - (LeastConnectionsHostSelector) acceptedStrategies - .get(LeastConnectionsHostSelector.STRATEGY_LEAST_CONNECTIONS); - hostSelector.setDatabasePools(databasePools); + final LeastConnectionsHostSelector hostSelector = new LeastConnectionsHostSelector(databasePools); + acceptedStrategies.put(LeastConnectionsHostSelector.STRATEGY_LEAST_CONNECTIONS, hostSelector); } @Override @@ -164,17 +158,17 @@ public boolean acceptsStrategy(@NonNull HostRole role, @NonNull String strategy) @Override public HostSpec getHostSpecByStrategy( - @NonNull List hosts, @NonNull HostRole role, @NonNull String strategy) + @NonNull List hosts, @NonNull HostRole role, @NonNull String strategy, Properties props) throws SQLException { final HostSpec selectedHost; switch (strategy) { case LeastConnectionsHostSelector.STRATEGY_LEAST_CONNECTIONS: selectedHost = - acceptedStrategies.get(LeastConnectionsHostSelector.STRATEGY_LEAST_CONNECTIONS).getHost(hosts, role); + acceptedStrategies.get(LeastConnectionsHostSelector.STRATEGY_LEAST_CONNECTIONS).getHost(hosts, role, props); break; case RoundRobinHostSelector.STRATEGY_ROUND_ROBIN: - selectedHost = acceptedStrategies.get(RoundRobinHostSelector.STRATEGY_ROUND_ROBIN).getHost(hosts, role); + selectedHost = acceptedStrategies.get(RoundRobinHostSelector.STRATEGY_ROUND_ROBIN).getHost(hosts, role, props); break; default: @@ -203,15 +197,6 @@ public Connection connect( ds.setPassword(props.getProperty(PropertyDefinition.PASSWORD.name)); - final String strategy = ReadWriteSplittingPlugin.READER_HOST_SELECTOR_STRATEGY.getString(props); - if (RoundRobinHostSelector.STRATEGY_ROUND_ROBIN.equals(strategy)) { - final RoundRobinHostSelector roundRobinHostSelector = - (RoundRobinHostSelector) acceptedStrategies.get(RoundRobinHostSelector.STRATEGY_ROUND_ROBIN); - if (roundRobinHostSelector.getHostCacheEntry(hostSpec) != null) { - roundRobinHostSelector.updateCachePropertiesForHost(hostSpec, props); - } - } - return ds.getConnection(); } diff --git a/wrapper/src/main/java/software/amazon/jdbc/HostSelector.java b/wrapper/src/main/java/software/amazon/jdbc/HostSelector.java index 40dcc520f..248b8d9b6 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/HostSelector.java +++ b/wrapper/src/main/java/software/amazon/jdbc/HostSelector.java @@ -18,6 +18,7 @@ import java.sql.SQLException; import java.util.List; +import java.util.Properties; public interface HostSelector { @@ -26,9 +27,10 @@ public interface HostSelector { * * @param hosts a list of available hosts to pick from * @param role the desired host role - either a writer or a reader + * @param props a properties object containing any necessary parameters * @return a host matching the requested role * @throws SQLException if the host list does not contain any hosts matching the requested role or * an error occurs while selecting a host */ - HostSpec getHost(List hosts, HostRole role) throws SQLException; + HostSpec getHost(List hosts, HostRole role, Properties props) throws SQLException; } diff --git a/wrapper/src/main/java/software/amazon/jdbc/LeastConnectionsHostSelector.java b/wrapper/src/main/java/software/amazon/jdbc/LeastConnectionsHostSelector.java index 6657f2573..9549be6c6 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/LeastConnectionsHostSelector.java +++ b/wrapper/src/main/java/software/amazon/jdbc/LeastConnectionsHostSelector.java @@ -20,20 +20,22 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.stream.Collectors; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.SlidingExpirationCache; public class LeastConnectionsHostSelector implements HostSelector { public static final String STRATEGY_LEAST_CONNECTIONS = "leastConnections"; - private SlidingExpirationCache databasePools; + private final SlidingExpirationCache databasePools; - public void setDatabasePools( + public LeastConnectionsHostSelector( SlidingExpirationCache databasePools) { this.databasePools = databasePools; } - public HostSpec getHost(List hosts, HostRole role) throws SQLException { + @Override + public HostSpec getHost(List hosts, HostRole role, Properties props) throws SQLException { List eligibleHosts = hosts.stream() .filter(hostSpec -> role.equals(hostSpec.getRole())) .sorted((hostSpec1, hostSpec2) -> diff --git a/wrapper/src/main/java/software/amazon/jdbc/PluginService.java b/wrapper/src/main/java/software/amazon/jdbc/PluginService.java index 4a9aa7684..91e75c737 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/PluginService.java +++ b/wrapper/src/main/java/software/amazon/jdbc/PluginService.java @@ -81,7 +81,7 @@ EnumSet setCurrentConnection( * {@link ConnectionPlugin} instances do not support the * requested strategy */ - HostSpec getHostSpecByStrategy(HostRole role, String strategy) + HostSpec getHostSpecByStrategy(HostRole role, String strategy, Properties props) throws SQLException, UnsupportedOperationException; /** diff --git a/wrapper/src/main/java/software/amazon/jdbc/PluginServiceImpl.java b/wrapper/src/main/java/software/amazon/jdbc/PluginServiceImpl.java index c7b6c07e5..9eeddf8dc 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/PluginServiceImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/PluginServiceImpl.java @@ -135,8 +135,8 @@ public boolean acceptsStrategy(HostRole role, String strategy) throws SQLExcepti } @Override - public HostSpec getHostSpecByStrategy(HostRole role, String strategy) throws SQLException { - return this.pluginManager.getHostSpecByStrategy(role, strategy); + public HostSpec getHostSpecByStrategy(HostRole role, String strategy, Properties props) throws SQLException { + return this.pluginManager.getHostSpecByStrategy(role, strategy, props); } @Override diff --git a/wrapper/src/main/java/software/amazon/jdbc/RandomHostSelector.java b/wrapper/src/main/java/software/amazon/jdbc/RandomHostSelector.java index cf408be0b..bde247d53 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/RandomHostSelector.java +++ b/wrapper/src/main/java/software/amazon/jdbc/RandomHostSelector.java @@ -18,6 +18,7 @@ import java.sql.SQLException; import java.util.List; +import java.util.Properties; import java.util.Random; import java.util.stream.Collectors; import software.amazon.jdbc.util.Messages; @@ -27,7 +28,7 @@ public class RandomHostSelector implements HostSelector { public static final String STRATEGY_RANDOM = "random"; @Override - public HostSpec getHost(List hosts, HostRole role) throws SQLException { + public HostSpec getHost(List hosts, HostRole role, Properties props) throws SQLException { List eligibleHosts = hosts.stream() .filter(hostSpec -> role.equals(hostSpec.getRole())).collect(Collectors.toList()); if (eligibleHosts.size() == 0) { diff --git a/wrapper/src/main/java/software/amazon/jdbc/RoundRobinHostSelector.java b/wrapper/src/main/java/software/amazon/jdbc/RoundRobinHostSelector.java index 86625fdf1..f38904ce1 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/RoundRobinHostSelector.java +++ b/wrapper/src/main/java/software/amazon/jdbc/RoundRobinHostSelector.java @@ -23,6 +23,8 @@ import java.util.List; import java.util.Properties; import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.util.CacheMap; @@ -38,78 +40,20 @@ public class RoundRobinHostSelector implements HostSelector { "The default weight for any hosts that have not been configured with the `roundRobinHostWeightPairs` parameter."); public static final String STRATEGY_ROUND_ROBIN = "roundRobin"; private static final long DEFAULT_ROUND_ROBIN_CACHE_EXPIRE_NANO = TimeUnit.MINUTES.toNanos(10); + static final Pattern HOST_WEIGHT_PAIRS_PATTERN = + Pattern.compile( + "((?[^:/?#]*):(?[0-9]*))"); private static final CacheMap roundRobinCache = new CacheMap<>(); - public RoundRobinClusterInfo getHostCacheEntry(@NonNull HostSpec host) { - return roundRobinCache.get(host.getHost()); - } - - public synchronized void updateCachePropertiesForHost( - @NonNull HostSpec host, - @NonNull Properties props) throws SQLException { - final RoundRobinClusterInfo clusterInfo = roundRobinCache.get(host.getHost()); - - final String defaultWeightString = ROUND_ROBIN_DEFAULT_WEIGHT.getString(props); - if (!StringUtils.isNullOrEmpty(defaultWeightString)) { - final Integer defaultWeight = Integer.getInteger(defaultWeightString); - clusterInfo.defaultWeight = (defaultWeight == null || defaultWeight < 1) ? 1 : defaultWeight; - } - - final String hostWeights = ROUND_ROBIN_HOST_WEIGHT_PAIRS.getString(props); - if (!StringUtils.isNullOrEmpty(hostWeights)) { - final String[] hostWeightPairs = hostWeights.split(","); - for (String pair : hostWeightPairs) { - final String[] hostWeightPair = pair.split(":"); - if (hostWeightPair.length != 2 - || hostWeightPair[0].isEmpty() - || hostWeightPair[1].isEmpty()) { - throw new SQLException(Messages.get("HostSelector.roundRobinWeightsConfigurationError")); - } - try { - final Integer weight = Integer.valueOf(hostWeightPair[1]); - clusterInfo.clusterWeightsMap.put(hostWeightPair[0], weight); - } catch (NumberFormatException e) { - throw new SQLException(Messages.get("HostSelector.roundRobinInvalidWeight")); - } - } - } - } - - private synchronized boolean createCacheEntryForHosts(@NonNull List hosts) { - final List hostsMissingCacheEntry = new ArrayList<>(); - final List hostsWithCacheEntry = new ArrayList<>(); - for (HostSpec host : hosts) { - if (roundRobinCache.get(host.getHost()) != null) { - hostsWithCacheEntry.add(host); - } else { - hostsMissingCacheEntry.add(host); - } - } - - if (hostsMissingCacheEntry.size() > 0 && hostsWithCacheEntry.size() > 0) { - for (HostSpec host : hostsMissingCacheEntry) { - roundRobinCache.put( - host.getHost(), - roundRobinCache.get(hostsWithCacheEntry.get(0).getHost()), - DEFAULT_ROUND_ROBIN_CACHE_EXPIRE_NANO); - } - return false; - } else if (hostsWithCacheEntry.size() == 0) { - final RoundRobinClusterInfo roundRobinClusterInfo = new RoundRobinClusterInfo(); - for (HostSpec host : hostsMissingCacheEntry) { - roundRobinCache.put( - host.getHost(), - roundRobinClusterInfo, - DEFAULT_ROUND_ROBIN_CACHE_EXPIRE_NANO); - } - return true; - } - - return false; + static { + PropertyDefinition.registerPluginProperties(RoundRobinHostSelector.class); } @Override - public synchronized HostSpec getHost(@NonNull List hosts, @NonNull HostRole role) throws SQLException { + public synchronized HostSpec getHost( + @NonNull List hosts, + @NonNull HostRole role, + @NonNull Properties props) throws SQLException { final List eligibleHosts = hosts.stream() .filter(hostSpec -> role.equals(hostSpec.getRole())) .sorted(Comparator.comparing(HostSpec::getHost)) @@ -119,8 +63,8 @@ public synchronized HostSpec getHost(@NonNull List hosts, @NonNull Hos throw new SQLException(Messages.get("HostSelector.noHostsMatchingRole", new Object[]{role})); } - // Create new cache entries for provided hosts where necessary. - final boolean createdNewCacheEntries = createCacheEntryForHosts(eligibleHosts); + // Create new cache entries for provided hosts if necessary. All hosts point to the same cluster info. + createCacheEntryForHosts(eligibleHosts, props); final String currentClusterInfoKey = eligibleHosts.get(0).getHost(); RoundRobinClusterInfo clusterInfo = roundRobinCache.get(currentClusterInfoKey); @@ -137,16 +81,6 @@ public synchronized HostSpec getHost(@NonNull List hosts, @NonNull Hos } } - // If the last host was selected without considering weights, the weightCounter should be adjusted after properties - // have been updated. - if (!createdNewCacheEntries && clusterInfo.isResetWeightRequired) { - final Integer currentWeight = - roundRobinCache.get(currentClusterInfoKey).clusterWeightsMap.get(currentClusterInfoKey); - clusterInfo.weightCounter = currentWeight == null ? clusterInfo.defaultWeight : currentWeight; - clusterInfo.weightCounter--; - clusterInfo.isResetWeightRequired = false; - } - // If the host is weighted and the lastHost is in the eligibleHosts list. if (clusterInfo.weightCounter > 0 && lastHostIndex != -1) { targetHostIndex = lastHostIndex; @@ -167,6 +101,71 @@ public synchronized HostSpec getHost(@NonNull List hosts, @NonNull Hos return eligibleHosts.get(targetHostIndex); } + private synchronized void createCacheEntryForHosts(@NonNull List hosts, @NonNull Properties props) + throws SQLException { + final List hostsMissingCacheEntry = new ArrayList<>(); + final List hostsWithCacheEntry = new ArrayList<>(); + for (HostSpec host : hosts) { + if (roundRobinCache.get(host.getHost()) != null) { + hostsWithCacheEntry.add(host); + } else { + hostsMissingCacheEntry.add(host); + } + } + + if ((hostsMissingCacheEntry.size() > 0 && hostsWithCacheEntry.size() > 0)) { + for (HostSpec host : hosts) { + roundRobinCache.put( + host.getHost(), + roundRobinCache.get(hostsWithCacheEntry.get(0).getHost()), + DEFAULT_ROUND_ROBIN_CACHE_EXPIRE_NANO); + } + } else if (hostsWithCacheEntry.size() == 0) { + final RoundRobinClusterInfo roundRobinClusterInfo = new RoundRobinClusterInfo(); + updateCachePropertiesForRoundRobinClusterInfo(roundRobinClusterInfo, props); + for (HostSpec host : hostsMissingCacheEntry) { + roundRobinCache.put( + host.getHost(), + roundRobinClusterInfo, + DEFAULT_ROUND_ROBIN_CACHE_EXPIRE_NANO); + } + } + } + + private synchronized void updateCachePropertiesForRoundRobinClusterInfo( + @NonNull RoundRobinClusterInfo roundRobinClusterInfo, + @NonNull Properties props) throws SQLException { + final String defaultWeightString = ROUND_ROBIN_DEFAULT_WEIGHT.getString(props); + if (!StringUtils.isNullOrEmpty(defaultWeightString)) { + final Integer defaultWeight = Integer.getInteger(defaultWeightString); + roundRobinClusterInfo.defaultWeight = (defaultWeight == null || defaultWeight < 1) ? 1 : defaultWeight; + } + + final String hostWeights = ROUND_ROBIN_HOST_WEIGHT_PAIRS.getString(props); + if (!StringUtils.isNullOrEmpty(hostWeights)) { + final String[] hostWeightPairs = hostWeights.split(","); + for (String pair : hostWeightPairs) { + final Matcher matcher = HOST_WEIGHT_PAIRS_PATTERN.matcher(pair); + if (!matcher.matches()) { + throw new SQLException(Messages.get("HostSelector.roundRobinWeightsConfigurationError")); + } + + final String hostName = matcher.group("host").trim(); + final String hostWeight = matcher.group("weight").trim(); + if (hostName.isEmpty() || hostWeight.isEmpty()) { + throw new SQLException(Messages.get("HostSelector.roundRobinWeightsConfigurationError")); + } + + try { + roundRobinClusterInfo.clusterWeightsMap.put(hostName, Integer.valueOf(hostWeight)); + } catch (NumberFormatException e) { + throw new SQLException(Messages.get("HostSelector.roundRobinInvalidWeight")); + } + } + } + } + + // For testing purposes only public void clearCache() { roundRobinCache.clear(); @@ -177,6 +176,5 @@ public static class RoundRobinClusterInfo { public HashMap clusterWeightsMap = new HashMap<>(); public int defaultWeight = 1; public int weightCounter = 0; - public boolean isResetWeightRequired = true; } } diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/AbstractConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/AbstractConnectionPlugin.java index 61efd6344..1feca61e1 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/AbstractConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/AbstractConnectionPlugin.java @@ -75,7 +75,7 @@ public boolean acceptsStrategy(HostRole role, String strategy) { } @Override - public HostSpec getHostSpecByStrategy(final HostRole role, final String strategy) + public HostSpec getHostSpecByStrategy(final HostRole role, final String strategy, final Properties props) throws UnsupportedOperationException { throw new UnsupportedOperationException("getHostSpecByStrategy is not supported by this plugin."); } diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/DefaultConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/DefaultConnectionPlugin.java index 48989d73c..385315965 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/DefaultConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/DefaultConnectionPlugin.java @@ -185,7 +185,7 @@ public boolean acceptsStrategy(HostRole role, String strategy) { } @Override - public HostSpec getHostSpecByStrategy(HostRole role, String strategy) + public HostSpec getHostSpecByStrategy(HostRole role, String strategy, Properties props) throws SQLException { if (HostRole.UNKNOWN.equals(role)) { // Users must request either a writer or a reader role. @@ -197,7 +197,7 @@ public HostSpec getHostSpecByStrategy(HostRole role, String strategy) throw new SQLException(Messages.get("DefaultConnectionPlugin.noHostsAvailable")); } - return this.connProviderManager.getHostSpecByStrategy(hosts, role, strategy); + return this.connProviderManager.getHostSpecByStrategy(hosts, role, strategy, props); } @Override diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPlugin.java index d79dfd776..488f863c3 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPlugin.java @@ -511,7 +511,10 @@ private void getNewReaderConnection() throws SQLException { int connAttempts = this.pluginService.getHosts().size() * 2; for (int i = 0; i < connAttempts; i++) { - HostSpec hostSpec = this.pluginService.getHostSpecByStrategy(HostRole.READER, this.readerSelectorStrategy); + HostSpec hostSpec = this.pluginService.getHostSpecByStrategy( + HostRole.READER, + this.readerSelectorStrategy, + this.properties); try { conn = this.pluginService.connect(hostSpec, this.properties); this.isReaderConnFromInternalPool = this.connProviderManager.getConnectionProvider( diff --git a/wrapper/src/test/java/software/amazon/jdbc/HikariPooledConnectionProviderTest.java b/wrapper/src/test/java/software/amazon/jdbc/HikariPooledConnectionProviderTest.java index ca94e5b72..eb9c0fd56 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/HikariPooledConnectionProviderTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/HikariPooledConnectionProviderTest.java @@ -188,8 +188,8 @@ public void testLeastConnectionsStrategy() throws SQLException { provider.setDatabasePools(getTestPoolMap()); assertThrows(UnsupportedOperationException.class, () -> - provider.getHostSpecByStrategy(testHosts, HostRole.READER, "random")); - HostSpec selectedHost = provider.getHostSpecByStrategy(testHosts, HostRole.READER, LEAST_CONNECTIONS); + provider.getHostSpecByStrategy(testHosts, HostRole.READER, "random", defaultProps)); + HostSpec selectedHost = provider.getHostSpecByStrategy(testHosts, HostRole.READER, LEAST_CONNECTIONS, defaultProps); // Other reader has 2 connections assertEquals(readerUrl1Connection, selectedHost.getHost()); } diff --git a/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginOne.java b/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginOne.java index 60c5c3575..30372c9c0 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginOne.java +++ b/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginOne.java @@ -118,7 +118,7 @@ public boolean acceptsStrategy(HostRole role, String strategy) { } @Override - public HostSpec getHostSpecByStrategy(HostRole role, String strategy) { + public HostSpec getHostSpecByStrategy(HostRole role, String strategy, Properties props) { this.calls.add(this.getClass().getSimpleName() + ":before getHostSpecByStrategy"); HostSpec result = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) .host("host").port(1234).role(role).build(); diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/RoundRobinHostSelectorTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/RoundRobinHostSelectorTest.java index 4008fc6d3..55fb29af1 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/RoundRobinHostSelectorTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/RoundRobinHostSelectorTest.java @@ -17,7 +17,6 @@ package software.amazon.jdbc.plugin; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.sql.SQLException; @@ -49,26 +48,30 @@ public class RoundRobinHostSelectorTest { .host("instance-3").port(TEST_PORT).role(HostRole.READER).build(); private final HostSpec readerHostSpec4 = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) .host("instance-4").port(TEST_PORT).role(HostRole.READER).build(); - private final List defaultHostsList = Arrays.asList( + private final List hostsList123 = Arrays.asList( writerHostSpec, readerHostSpec2, readerHostSpec3, readerHostSpec1); - private final List scaledUpHostsList = Arrays.asList( + private final List hostsList1234 = Arrays.asList( writerHostSpec, readerHostSpec4, readerHostSpec2, readerHostSpec3, readerHostSpec1); - private final List scaledDownHostsList = Arrays.asList( + private final List hostsList13 = Arrays.asList( writerHostSpec, readerHostSpec3, readerHostSpec1); - private final List topologyChangedHostsList = Arrays.asList( + private final List hostsList14 = Arrays.asList( writerHostSpec, readerHostSpec4, readerHostSpec1); + private final List hostsList23 = Arrays.asList( + writerHostSpec, + readerHostSpec3, + readerHostSpec2); private final List writerHostsList = Collections.singletonList(writerHostSpec); private static RoundRobinHostSelector roundRobinHostSelector; @@ -92,7 +95,7 @@ public void cleanUp() { } @Test - public void testSetup_EmptyHost() throws SQLException { + public void testSetup_EmptyHost() { final String hostWeights = "instance-0:1," + ":3," @@ -100,15 +103,13 @@ public void testSetup_EmptyHost() throws SQLException { + "instance-3:3"; defaultProps.put(RoundRobinHostSelector.ROUND_ROBIN_HOST_WEIGHT_PAIRS.name, hostWeights); defaultProps.put(RoundRobinHostSelector.ROUND_ROBIN_DEFAULT_WEIGHT.name, 4); - // getHost must be called before updateCachePropertiesForHost - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost(); assertThrows( SQLException.class, - () -> roundRobinHostSelector.updateCachePropertiesForHost(readerHostSpec1, defaultProps)); + () -> roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); } @Test - public void testSetup_EmptyWeight() throws SQLException { + public void testSetup_EmptyWeight() { final String hostWeights = "instance-0:1," + "instance-1:," @@ -117,15 +118,13 @@ public void testSetup_EmptyWeight() throws SQLException { defaultProps.put(RoundRobinHostSelector.ROUND_ROBIN_HOST_WEIGHT_PAIRS.name, hostWeights); defaultProps.put(RoundRobinHostSelector.ROUND_ROBIN_DEFAULT_WEIGHT.name, 4); System.out.println("?? " + hostWeights); - // getHost must be called before updateCachePropertiesForHost - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost(); assertThrows( SQLException.class, - () -> roundRobinHostSelector.updateCachePropertiesForHost(readerHostSpec1, defaultProps)); + () -> roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); } @Test - public void testSetup_BadWeightFormat() throws SQLException { + public void testSetup_BadWeightFormat() { final String hostWeights = "instance-0:1," + "instance-1:1:3," @@ -133,23 +132,19 @@ public void testSetup_BadWeightFormat() throws SQLException { + "instance-3:3"; defaultProps.put(RoundRobinHostSelector.ROUND_ROBIN_HOST_WEIGHT_PAIRS.name, hostWeights); defaultProps.put(RoundRobinHostSelector.ROUND_ROBIN_DEFAULT_WEIGHT.name, 4); - // getHost must be called before updateCachePropertiesForHost - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost(); assertThrows( SQLException.class, - () -> roundRobinHostSelector.updateCachePropertiesForHost(readerHostSpec1, defaultProps)); + () -> roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); } @Test - public void testSetup_ParseWeightError() throws SQLException { + public void testSetup_ParseWeightError() { final String hostWeights = "instance-0:1,instance-1:1a"; defaultProps.put(RoundRobinHostSelector.ROUND_ROBIN_HOST_WEIGHT_PAIRS.name, hostWeights); defaultProps.put(RoundRobinHostSelector.ROUND_ROBIN_DEFAULT_WEIGHT.name, 4); - // getHost must be called before updateCachePropertiesForHost - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost(); assertThrows( SQLException.class, - () -> roundRobinHostSelector.updateCachePropertiesForHost(readerHostSpec1, defaultProps)); + () -> roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); } @Test @@ -157,187 +152,140 @@ public void testSetup_NegativeDefaultWeight() throws SQLException { defaultProps.put(RoundRobinHostSelector.ROUND_ROBIN_DEFAULT_WEIGHT.name, -1); assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); - - // getHost must be called before updateCachePropertiesForHost - roundRobinHostSelector.updateCachePropertiesForHost(readerHostSpec1, weightedProps); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); assertEquals( - readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(topologyChangedHostsList, HostRole.READER).getHost()); + readerHostSpec4.getHost(), + roundRobinHostSelector.getHost(hostsList14, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(topologyChangedHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList14, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec4.getHost(), - roundRobinHostSelector.getHost(topologyChangedHostsList, HostRole.READER).getHost()); - assertEquals( - readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(topologyChangedHostsList, HostRole.READER).getHost()); - - RoundRobinHostSelector.RoundRobinClusterInfo clusterInfo = - roundRobinHostSelector.getHostCacheEntry(readerHostSpec1); - assertEquals(clusterInfo.defaultWeight, 1); + roundRobinHostSelector.getHost(hostsList14, HostRole.READER, defaultProps).getHost()); } @Test public void testGetHost_NoReaders() { assertThrows(SQLException.class, - () -> roundRobinHostSelector.getHost(writerHostsList, HostRole.READER)); + () -> roundRobinHostSelector.getHost(writerHostsList, HostRole.READER, defaultProps)); } @Test public void testGetHost() throws SQLException { assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec2.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec3.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); } @Test public void testGetHost_Weighted() throws SQLException { assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); - - // getHost must be called before updateCachePropertiesForHost - roundRobinHostSelector.updateCachePropertiesForHost(readerHostSpec1, weightedProps); - + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, weightedProps).getHost()); assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, weightedProps).getHost()); assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, weightedProps).getHost()); assertEquals( readerHostSpec2.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, weightedProps).getHost()); assertEquals( readerHostSpec2.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, weightedProps).getHost()); assertEquals( readerHostSpec3.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, weightedProps).getHost()); assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, weightedProps).getHost()); } @Test public void testGetHost_CacheEntryExpired() throws SQLException { assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec2.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); roundRobinHostSelector.clearCache(); assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec2.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); } @Test public void testGetHost_ScaleUp() throws SQLException { assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec2.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec3.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec4.getHost(), - roundRobinHostSelector.getHost(scaledUpHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList1234, HostRole.READER, defaultProps).getHost()); } @Test public void testGetHost_ScaleDown() throws SQLException { assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec3.getHost(), - roundRobinHostSelector.getHost(scaledDownHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList13, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(scaledDownHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList13, HostRole.READER, defaultProps).getHost()); } @Test public void testGetHost_LastHostNotInHostsList() throws SQLException { assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec2.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList123, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(scaledDownHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList13, HostRole.READER, defaultProps).getHost()); assertEquals( readerHostSpec3.getHost(), - roundRobinHostSelector.getHost(scaledDownHostsList, HostRole.READER).getHost()); + roundRobinHostSelector.getHost(hostsList13, HostRole.READER, defaultProps).getHost()); } @Test - public void testUpdateProperties() throws SQLException { + public void testGetHost_AllHostsChanged() throws SQLException { assertEquals( readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); - - assertEquals( - roundRobinHostSelector.getHostCacheEntry(readerHostSpec1), - roundRobinHostSelector.getHostCacheEntry(readerHostSpec2)); + roundRobinHostSelector.getHost(hostsList14, HostRole.READER, defaultProps).getHost()); assertEquals( - roundRobinHostSelector.getHostCacheEntry(readerHostSpec1), - roundRobinHostSelector.getHostCacheEntry(readerHostSpec3)); - - // getHost must be called before updateCachePropertiesForHost - roundRobinHostSelector.updateCachePropertiesForHost(readerHostSpec1, defaultProps); - - RoundRobinHostSelector.RoundRobinClusterInfo clusterInfo = - roundRobinHostSelector.getHostCacheEntry(readerHostSpec1); - assertNull(clusterInfo.clusterWeightsMap.get(readerHostSpec1.getHost())); - assertNull(clusterInfo.clusterWeightsMap.get(readerHostSpec2.getHost())); - assertNull(clusterInfo.clusterWeightsMap.get(readerHostSpec3.getHost())); - } - - @Test - public void testUpdateProperties_Weighted() throws SQLException { - assertEquals( - readerHostSpec1.getHost(), - roundRobinHostSelector.getHost(defaultHostsList, HostRole.READER).getHost()); - - assertEquals( - roundRobinHostSelector.getHostCacheEntry(readerHostSpec1), - roundRobinHostSelector.getHostCacheEntry(readerHostSpec2)); + readerHostSpec2.getHost(), + roundRobinHostSelector.getHost(hostsList23, HostRole.READER, defaultProps).getHost()); assertEquals( - roundRobinHostSelector.getHostCacheEntry(readerHostSpec1), - roundRobinHostSelector.getHostCacheEntry(readerHostSpec3)); - - // getHost must be called before updateCachePropertiesForHost - roundRobinHostSelector.updateCachePropertiesForHost(readerHostSpec1, weightedProps); - - RoundRobinHostSelector.RoundRobinClusterInfo clusterInfo = - roundRobinHostSelector.getHostCacheEntry(readerHostSpec1); - assertEquals(clusterInfo.clusterWeightsMap.get(readerHostSpec1.getHost()), 3); - assertEquals(clusterInfo.clusterWeightsMap.get(readerHostSpec2.getHost()), 2); - assertEquals(clusterInfo.clusterWeightsMap.get(readerHostSpec3.getHost()), 1); + readerHostSpec4.getHost(), + roundRobinHostSelector.getHost(hostsList14, HostRole.READER, defaultProps).getHost()); } } diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/ConcurrencyTests.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/ConcurrencyTests.java index 39ae58103..ba6514e82 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/ConcurrencyTests.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/ConcurrencyTests.java @@ -303,7 +303,7 @@ public boolean acceptsStrategy(HostRole role, String strategy) { } @Override - public HostSpec getHostSpecByStrategy(HostRole role, String strategy) { + public HostSpec getHostSpecByStrategy(HostRole role, String strategy, Properties props) { return null; } diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPluginTest.java index 40aa20c38..6d0ff4861 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPluginTest.java @@ -124,7 +124,7 @@ void mockDefaultBehavior() throws SQLException { when(this.mockPluginService.getCurrentConnection()).thenReturn(mockWriterConn); when(this.mockPluginService.getCurrentHostSpec()).thenReturn(writerHostSpec); when(this.mockPluginService.getHosts()).thenReturn(defaultHosts); - when(this.mockPluginService.getHostSpecByStrategy(eq(HostRole.READER), eq("random"))) + when(this.mockPluginService.getHostSpecByStrategy(eq(HostRole.READER), eq("random"), eq(defaultProps))) .thenReturn(readerHostSpec1); when(this.mockPluginService.connect(eq(writerHostSpec), any(Properties.class))) .thenReturn(mockWriterConn);