// Path: breakerbox-turbine/src/main/java/com/yammer/breakerbox/turbine/client/TurbineTenacityClient.java
// public interface TurbineTenacityClient {
//     Optional<Collection<String>> getTenacityPropertyKeys(Instance instance);
// 
//     Optional<TenacityConfiguration> getTenacityConfiguration(Instance instance, TenacityPropertyKey key);
// 
//     Optional<Collection<CircuitBreaker>> getCircuitBreakers(Instance instance);
// 
//     Optional<CircuitBreaker> getCircuitBreaker(Instance instance, TenacityPropertyKey key);
// 
//     Optional<CircuitBreaker> modifyCircuitBreaker(Instance instance,
//                                                   TenacityPropertyKey key,
//                                                   CircuitBreaker.State state);
// 
//     static URI toUri(Instance instance) {
//         final String rawHostname = instance.getHostname().trim();
//         if (rawHostname.startsWith("http")) {
//             return URI.create(rawHostname);
//         } else {
//             return URI.create("http://" + rawHostname);
//         }
//     }
// }


import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.netflix.turbine.discovery.Instance;
import com.yammer.breakerbox.turbine.client.TurbineTenacityClient;
import com.yammer.tenacity.core.TenacityCommand;
import com.yammer.tenacity.core.config.TenacityConfiguration;
import com.yammer.tenacity.core.properties.TenacityPropertyKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkNotNull;
            if (obj == null || getClass() != obj.getClass()) {
                return false;
            }
            final Key other = (Key) obj;
            return Objects.equals(this.instance, other.instance)
                    && Objects.equals(this.tenacityPropertyKey, other.tenacityPropertyKey);
        }
    }

    private final TurbineTenacityClient client;
    private final Key key;
    private static final Cache<Key, TenacityConfiguration> cache = CacheBuilder
            .newBuilder()
            .expireAfterWrite(10, TimeUnit.SECONDS) //Small TTL to collapse simultaneous requests
            .build();
    private static final Logger LOGGER = LoggerFactory.getLogger(TenacityConfigurationFetcher.class);

    public TenacityConfigurationFetcher(TurbineTenacityClient client,
                                        Instance instance,
                                        TenacityPropertyKey key) {
        super(BreakerboxDependencyKey.BRKRBX_SERVICES_CONFIGURATION);
        this.client = checkNotNull(client);
        this.key = new Key(checkNotNull(instance), checkNotNull(key));
    }

    @Override
    protected Optional<TenacityConfiguration> run() throws Exception {
        try {
            return Optional.of(cache.get(key, () ->
                client.getTenacityConfiguration(key.instance, key.tenacityPropertyKey).orElse(null)));
// Path: breakerbox-turbine/src/main/java/com/yammer/breakerbox/turbine/client/TurbineTenacityClient.java
// public interface TurbineTenacityClient {
//     Optional<Collection<String>> getTenacityPropertyKeys(Instance instance);
// 
//     Optional<TenacityConfiguration> getTenacityConfiguration(Instance instance, TenacityPropertyKey key);
// 
//     Optional<Collection<CircuitBreaker>> getCircuitBreakers(Instance instance);
// 
//     Optional<CircuitBreaker> getCircuitBreaker(Instance instance, TenacityPropertyKey key);
// 
//     Optional<CircuitBreaker> modifyCircuitBreaker(Instance instance,
//                                                   TenacityPropertyKey key,
//                                                   CircuitBreaker.State state);
// 
//     static URI toUri(Instance instance) {
//         final String rawHostname = instance.getHostname().trim();
//         if (rawHostname.startsWith("http")) {
//             return URI.create(rawHostname);
//         } else {
//             return URI.create("http://" + rawHostname);
//         }
//     }
// }


// Path: breakerbox-service/src/main/java/com/yammer/breakerbox/service/tenacity/TenacityConfigurationFetcher.java
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.netflix.turbine.discovery.Instance;
import com.yammer.breakerbox.turbine.client.TurbineTenacityClient;
import com.yammer.tenacity.core.TenacityCommand;
import com.yammer.tenacity.core.config.TenacityConfiguration;
import com.yammer.tenacity.core.properties.TenacityPropertyKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkNotNull;

            if (obj == null || getClass() != obj.getClass()) {
                return false;
            }
            final Key other = (Key) obj;
            return Objects.equals(this.instance, other.instance)
                    && Objects.equals(this.tenacityPropertyKey, other.tenacityPropertyKey);
        }
    }

    private final TurbineTenacityClient client;
    private final Key key;
    private static final Cache<Key, TenacityConfiguration> cache = CacheBuilder
            .newBuilder()
            .expireAfterWrite(10, TimeUnit.SECONDS) //Small TTL to collapse simultaneous requests
            .build();
    private static final Logger LOGGER = LoggerFactory.getLogger(TenacityConfigurationFetcher.class);

    public TenacityConfigurationFetcher(TurbineTenacityClient client,
                                        Instance instance,
                                        TenacityPropertyKey key) {
        super(BreakerboxDependencyKey.BRKRBX_SERVICES_CONFIGURATION);
        this.client = checkNotNull(client);
        this.key = new Key(checkNotNull(instance), checkNotNull(key));
    }

    @Override
    protected Optional<TenacityConfiguration> run() throws Exception {
        try {
            return Optional.of(cache.get(key, () ->
                client.getTenacityConfiguration(key.instance, key.tenacityPropertyKey).orElse(null)));
        } catch (CacheLoader.InvalidCacheLoadException err) {