Skip to content

Commit

Permalink
Merge pull request #420 from elandau/bugfix/overrides
Browse files Browse the repository at this point in the history
config: Simplify how overrides are applied
  • Loading branch information
elandau committed May 20, 2019
2 parents 532285a + c6e492d commit 5356690
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
*/
package com.netflix.client.config;

import com.netflix.config.ConfigurationManager;

import java.util.concurrent.TimeUnit;

Expand Down Expand Up @@ -302,7 +301,6 @@ public DefaultClientConfigImpl(String nameSpace) {
}

public void loadDefaultValues() {
super.loadDefaultValues();
set(CommonClientConfigKey.MaxHttpConnectionsPerHost, getDefaultMaxHttpConnectionsPerHost());
set(CommonClientConfigKey.MaxTotalHttpConnections, getDefaultMaxTotalHttpConnections());
set(CommonClientConfigKey.EnableConnectionPool, getDefaultEnableConnectionPool());
Expand All @@ -319,18 +317,8 @@ public void loadDefaultValues() {
set(CommonClientConfigKey.ConnIdleEvictTimeMilliSeconds, getDefaultConnectionidleTimeInMsecs());
set(CommonClientConfigKey.ConnectionCleanerRepeatInterval, getDefaultConnectionIdleTimertaskRepeatInMsecs());
set(CommonClientConfigKey.EnableGZIPContentEncodingFilter, getDefaultEnableGzipContentEncodingFilter());
String proxyHost = ConfigurationManager.getConfigInstance().getString(getDefaultPropName(CommonClientConfigKey.ProxyHost.key()));
if (proxyHost != null && proxyHost.length() > 0) {
set(CommonClientConfigKey.ProxyHost, proxyHost);
}
Integer proxyPort = ConfigurationManager
.getConfigInstance()
.getInteger(
getDefaultPropName(CommonClientConfigKey.ProxyPort),
(Integer.MIN_VALUE + 1)); // + 1 just to avoid potential clash with user setting
if (proxyPort != (Integer.MIN_VALUE + 1)) {
set(CommonClientConfigKey.ProxyPort, proxyPort);
}
set(CommonClientConfigKey.ProxyHost, null);
set(CommonClientConfigKey.ProxyPort, null);
set(CommonClientConfigKey.Port, getDefaultPort());
set(CommonClientConfigKey.EnablePrimeConnections, getDefaultEnablePrimeConnections());
set(CommonClientConfigKey.MaxRetriesPerServerPrimeConnection, getDefaultMaxRetriesPerServerPrimeConnection());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;

Expand Down Expand Up @@ -285,4 +286,16 @@ public String toString() {
@Override
public T defaultValue() { return defaultValue; }

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CommonClientConfigKey<?> that = (CommonClientConfigKey<?>) o;
return Objects.equals(configKey, that.configKey);
}

@Override
public int hashCode() {
return Objects.hash(configKey);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,6 @@ public interface IClientConfig {

Map<String, Object> getProperties();

/**
* Iterate all properties and report the default value only to the consumer
* @param consumer
*/
default void forEachDefault(BiConsumer<IClientConfigKey<?>, Object> consumer) {
throw new UnsupportedOperationException();
}

/**
* Iterate all properties and report the final value. Can be null if a default value is not specified.
* @param consumer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public abstract class ReloadableClientConfig implements IClientConfig {
private static final String DEFAULT_NAMESPACE = "ribbon";

// Map of raw property names (without namespace or client) to values set via code
private final Map<String, Object> internalProperties = new HashMap<>();
private final Map<IClientConfigKey, Object> internalProperties = new HashMap<>();

// Map of all seen dynamic properties. This map will hold on properties requested with the exception of
// those returned from getGlobalProperty().
Expand All @@ -57,19 +57,15 @@ public abstract class ReloadableClientConfig implements IClientConfig {

private String namespace = DEFAULT_NAMESPACE;

private boolean isDynamic;

private boolean isLoaded = false;

protected ReloadableClientConfig(PropertyResolver resolver) {
this.clientName = DEFAULT_CLIENT_NAME;
this.isDynamic = false;
this.resolver = resolver;
}

protected ReloadableClientConfig(PropertyResolver resolver, String clientName) {
this.clientName = clientName;
this.isDynamic = true;
this.resolver = resolver;
}

Expand Down Expand Up @@ -112,29 +108,24 @@ public final void setNameSpace(String nameSpace) {
public void loadProperties(String clientName) {
Preconditions.checkState(isLoaded == false, "Config '{}' can only be loaded once", clientName);
if (!isLoaded) {
loadDefaultValues();
this.isLoaded = true;
resolver.onChange(this::reload);
}

this.isDynamic = true;
this.clientName = clientName;
loadDefaultValues();
}

@Override
public void loadDefaultValues() {
this.isDynamic = true;
reload();
}

@Override
public final Map<String, Object> getProperties() {
return Collections.unmodifiableMap(internalProperties);
}

@Override
public void forEachDefault(BiConsumer<IClientConfigKey<?>, Object> consumer) {
dynamicProperties.forEach((key, value) -> consumer.accept(key, internalProperties.get(key.key())));
final Map<String, Object> result = new HashMap<>(dynamicProperties.size());
dynamicProperties.forEach((key, value) -> {
Object v = value.get().orElse(null);
if (v != null) {
result.put(key.key(), String.valueOf(v));
}
});
return result;
}

@Override
Expand All @@ -150,9 +141,7 @@ private <T> ReloadableProperty<T> createProperty(final Supplier<Optional<T>> val

{
refresh();
if (isDynamic) {
changeActions.add(this::refresh);
}
changeActions.add(this::refresh);
}

@Override
Expand Down Expand Up @@ -192,11 +181,7 @@ public String toString() {

@Override
public final <T> T get(IClientConfigKey<T> key) {
if (isLoaded) {
return getOrCreateProperty(key).get().orElse(null);
} else {
return getIfSet(key).orElse(null);
}
return getOrCreateProperty(key).get().orElse(null);
}

private final <T> ReloadableProperty<T> getOrCreateProperty(IClientConfigKey<T> key) {
Expand Down Expand Up @@ -251,6 +236,12 @@ private <T> Optional<T> resolveFinalProperty(IClientConfigKey<T> key) {
return getIfSet(key);
}

/**
* Resolve a p
* @param key
* @param <T>
* @return
*/
private <T> Optional<T> resolverScopedProperty(IClientConfigKey<T> key) {
Optional<T> value = resolver.get(clientName + "." + getNameSpace() + "." + key.key(), key.type());
if (value.isPresent()) {
Expand All @@ -262,7 +253,7 @@ private <T> Optional<T> resolverScopedProperty(IClientConfigKey<T> key) {

@Override
public <T> Optional<T> getIfSet(IClientConfigKey<T> key) {
return Optional.ofNullable(internalProperties.get(key.key()))
return Optional.ofNullable(internalProperties.get(key))
.map(value -> {
final Class<T> type = key.type();
// Unfortunately there's some legacy code setting string values for typed keys. Here are do our best to parse
Expand Down Expand Up @@ -359,7 +350,7 @@ public final <T> IClientConfig set(IClientConfigKey<T> key, T value) {
if (value == null) {
internalProperties.remove(key.key());
} else {
internalProperties.put(key.key(), value);
internalProperties.put(key, value);
}

if (isLoaded) {
Expand Down Expand Up @@ -418,8 +409,16 @@ public IClientConfig applyOverride(IClientConfig override) {
return this;
}

this.internalProperties.putAll(override.getProperties());
reload();
// When overriding we only really care of picking up properties that were explicitly set in code. This is a
// bit of an optimization to avoid excessive memory allocation as requests are made and overrides are applied
if (override instanceof ReloadableClientConfig) {
((ReloadableClientConfig)override).internalProperties.forEach((key, value) -> {
if (value != null) {
setProperty(key, value);
}
});
}

return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import org.junit.Test;
import org.junit.rules.TestName;
import org.junit.runners.MethodSorters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Properties;

Expand All @@ -41,6 +43,8 @@
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ClientConfigTest {
private static final Logger LOG = LoggerFactory.getLogger(ClientConfigTest.class);

@Rule
public TestName testName = new TestName();

Expand Down Expand Up @@ -186,7 +190,7 @@ public void testValueOf() {
ConfigurationManager.getConfigInstance().setProperty("testValueOf.ribbon.CustomValueOf", "value");

DefaultClientConfigImpl clientConfig = new DefaultClientConfigImpl();
clientConfig.setClientName("testValueOf");
clientConfig.loadProperties("testValueOf");

Property<CustomValueOf> prop = clientConfig.getDynamicProperty(CUSTOM_KEY);
Assert.assertEquals("value", prop.getOrDefault().getValue());
Expand All @@ -198,7 +202,7 @@ public void testScopedProperty() {
ConfigurationManager.getConfigInstance().setProperty("testScopedProperty.ribbon.foo.ScopePropertyTimeout", "1000");

DefaultClientConfigImpl clientConfig = new DefaultClientConfigImpl();
clientConfig.setClientName("testScopedProperty");
clientConfig.loadProperties("testScopedProperty");

Property<Integer> prop = clientConfig.getScopedProperty(new CommonClientConfigKey<Integer>("foo.ScopePropertyTimeout", 0) {});
Assert.assertEquals(1000, prop.get().get().intValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public void testSorting() {
@Test
public void testFiltering() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.setClientName("SubsetFilerTest");
config.loadProperties("SubsetFilerTest");

ServerListSubsetFilter<Server> filter = new ServerListSubsetFilter<Server>(config);
LoadBalancerStats stats = new LoadBalancerStats("default");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public void testChooseZone() throws Exception {
ConfigurationManager.getConfigInstance().setProperty("niws.loadbalancer.serverStats.activeRequestsCount.effectiveWindowSeconds", 10);

DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.setClientName("testChooseZone");
config.loadProperties("testChooseZone");
ZoneAwareLoadBalancer<Server> balancer = new ZoneAwareLoadBalancer<Server>();
balancer.init();
IRule globalRule = new RoundRobinRule();
Expand Down

0 comments on commit 5356690

Please sign in to comment.