All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.hystrix.strategy.properties.HystrixPropertiesChainedProperty Maven / Gradle / Ivy

There is a newer version: 1.5.18
Show newest version
/**
 * Copyright 2016 Netflix, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.netflix.hystrix.strategy.properties;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.netflix.hystrix.strategy.HystrixPlugins;

/**
 * Chained property allowing a chain of defaults properties which is uses the properties plugin.
 * 

* Instead of just a single dynamic property with a default this allows a sequence of properties that fallback to the farthest down the chain with a value. * * TODO This should be replaced by a version in the Archaius library once available. * * @ExcludeFromJavadoc */ public abstract class HystrixPropertiesChainedProperty { private static final Logger logger = LoggerFactory.getLogger(HystrixPropertiesChainedProperty.class); /** * @ExcludeFromJavadoc */ private static abstract class ChainLink { private final AtomicReference> pReference; private final ChainLink next; private final List callbacks; /** * @return String */ public abstract String getName(); /** * @return T */ protected abstract T getValue(); /** * @return Boolean */ public abstract boolean isValueAcceptable(); /** * No arg constructor - used for end node */ public ChainLink() { next = null; pReference = new AtomicReference>(this); callbacks = new ArrayList(); } /** * @param nextProperty next property in the chain */ public ChainLink(ChainLink nextProperty) { next = nextProperty; pReference = new AtomicReference>(next); callbacks = new ArrayList(); } protected void checkAndFlip() { // in case this is the end node if (next == null) { pReference.set(this); return; } if (this.isValueAcceptable()) { logger.debug("Flipping property: {} to use its current value: {}", getName(), getValue()); pReference.set(this); } else { logger.debug("Flipping property: {} to use NEXT property: {}", getName(), next); pReference.set(next); } for (Runnable r : callbacks) { r.run(); } } /** * @return T */ public T get() { if (pReference.get() == this) { return this.getValue(); } else { return pReference.get().get(); } } /** * @param r callback to execut */ public void addCallback(Runnable r) { callbacks.add(r); } /** * @return String */ public String toString() { return getName() + " = " + get(); } } public static abstract class ChainBuilder { private ChainBuilder() { super(); } private List> properties = new ArrayList>(); public ChainBuilder add(HystrixDynamicProperty property) { properties.add(property); return this; } public ChainBuilder add(String name, T defaultValue) { properties.add(getDynamicProperty(name, defaultValue, getType())); return this; } public HystrixDynamicProperty build() { if (properties.size() < 1) throw new IllegalArgumentException(); if (properties.size() == 1) return properties.get(0); List> reversed = new ArrayList>(properties); Collections.reverse(reversed); ChainProperty current = null; for (HystrixDynamicProperty p : reversed) { if (current == null) { current = new ChainProperty(p); } else { current = new ChainProperty(p, current); } } return new ChainHystrixProperty(current); } protected abstract Class getType(); } private static ChainBuilder forType(final Class type) { return new ChainBuilder() { @Override protected Class getType() { return type; } }; } public static ChainBuilder forString() { return forType(String.class); } public static ChainBuilder forInteger() { return forType(Integer.class); } public static ChainBuilder forBoolean() { return forType(Boolean.class); } public static ChainBuilder forLong() { return forType(Long.class); } private static class ChainHystrixProperty implements HystrixDynamicProperty { private final ChainProperty property; public ChainHystrixProperty(ChainProperty property) { super(); this.property = property; } @Override public String getName() { return property.getName(); } @Override public T get() { return property.get(); } @Override public void addCallback(Runnable callback) { property.addCallback(callback); } } private static class ChainProperty extends ChainLink { private final HystrixDynamicProperty sProp; public ChainProperty(HystrixDynamicProperty sProperty) { super(); sProp = sProperty; } public ChainProperty(HystrixDynamicProperty sProperty, ChainProperty next) { super(next); // setup next pointer sProp = sProperty; sProp.addCallback(new Runnable() { @Override public void run() { logger.debug("Property changed: '{} = {}'", getName(), getValue()); checkAndFlip(); } }); checkAndFlip(); } @Override public boolean isValueAcceptable() { return (sProp.get() != null); } @Override protected T getValue() { return sProp.get(); } @Override public String getName() { return sProp.getName(); } } private static HystrixDynamicProperty getDynamicProperty(String propName, T defaultValue, Class type) { HystrixDynamicProperties properties = HystrixPlugins.getInstance().getDynamicProperties(); HystrixDynamicProperty p = HystrixDynamicProperties.Util.getProperty(properties, propName, defaultValue, type); return p; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy