// Path: src/main/java/com/github/phantomthief/failover/util/SharedCheckExecutorHolder.java
// public class SharedCheckExecutorHolder {
// 
//     private static final int THREAD_COUNT = 10;
// 
//     public static ScheduledExecutorService getInstance() {
//         return LazyHolder.INSTANCE;
//     }
// 
//     private static class LazyHolder {
// 
//         private static final ScheduledExecutorService INSTANCE = new ScheduledThreadPoolExecutor(
//                 THREAD_COUNT,
//                 new ThreadFactory() {
//                     private AtomicLong count = new AtomicLong();
//                     private static final String NAME_PATTERN = "scheduled-failover-recovery-check-%d";
//                     @Override
//                     public Thread newThread(Runnable r) {
//                         String name = format(NAME_PATTERN, count.getAndIncrement());
//                         Thread thread = new Thread(r, name);
//                         thread.setDaemon(true);
//                         thread.setPriority(MIN_PRIORITY);
//                         if (Thread.getDefaultUncaughtExceptionHandler() == null) {
//                             thread.setUncaughtExceptionHandler((t, e) -> {
//                                 e.printStackTrace();
//                             });
//                         }
//                         return thread;
//                     }
//                 }) {
// 
//             public void shutdown() {
//                 throw new UnsupportedOperationException();
//             }
// 
//             public List<Runnable> shutdownNow() {
//                 throw new UnsupportedOperationException();
//             }
//         };
//     }
// }


import static java.util.Objects.requireNonNull;
import java.time.Duration;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.github.phantomthief.failover.util.SharedCheckExecutorHolder;

        public int getPriority() {
            return priority;
        }

        public double getMaxWeight() {
            return maxWeight;
        }

        public double getMinWeight() {
            return minWeight;
        }

        public double getInitWeight() {
            return initWeight;
        }
    }


    static class PriorityFailoverConfig<T> implements Cloneable {
        private Map<T, ResConfig> resources = new HashMap<>();
        private String name;

        private double priorityFactor = 1.4;
        private WeightFunction<T> weightFunction = new RatioWeightFunction<>();
        @Nullable
        private WeightListener<T> weightListener;
        private boolean concurrencyControl = false;
        private boolean manualConcurrencyControl = false;
        private Duration checkDuration = Duration.ofSeconds(1);
// Path: src/main/java/com/github/phantomthief/failover/util/SharedCheckExecutorHolder.java
// public class SharedCheckExecutorHolder {
// 
//     private static final int THREAD_COUNT = 10;
// 
//     public static ScheduledExecutorService getInstance() {
//         return LazyHolder.INSTANCE;
//     }
// 
//     private static class LazyHolder {
// 
//         private static final ScheduledExecutorService INSTANCE = new ScheduledThreadPoolExecutor(
//                 THREAD_COUNT,
//                 new ThreadFactory() {
//                     private AtomicLong count = new AtomicLong();
//                     private static final String NAME_PATTERN = "scheduled-failover-recovery-check-%d";
//                     @Override
//                     public Thread newThread(Runnable r) {
//                         String name = format(NAME_PATTERN, count.getAndIncrement());
//                         Thread thread = new Thread(r, name);
//                         thread.setDaemon(true);
//                         thread.setPriority(MIN_PRIORITY);
//                         if (Thread.getDefaultUncaughtExceptionHandler() == null) {
//                             thread.setUncaughtExceptionHandler((t, e) -> {
//                                 e.printStackTrace();
//                             });
//                         }
//                         return thread;
//                     }
//                 }) {
// 
//             public void shutdown() {
//                 throw new UnsupportedOperationException();
//             }
// 
//             public List<Runnable> shutdownNow() {
//                 throw new UnsupportedOperationException();
//             }
//         };
//     }
// }


// Path: src/main/java/com/github/phantomthief/failover/impl/PriorityFailoverBuilder.java
import static java.util.Objects.requireNonNull;
import java.time.Duration;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.github.phantomthief.failover.util.SharedCheckExecutorHolder;


        public int getPriority() {
            return priority;
        }

        public double getMaxWeight() {
            return maxWeight;
        }

        public double getMinWeight() {
            return minWeight;
        }

        public double getInitWeight() {
            return initWeight;
        }
    }


    static class PriorityFailoverConfig<T> implements Cloneable {
        private Map<T, ResConfig> resources = new HashMap<>();
        private String name;

        private double priorityFactor = 1.4;
        private WeightFunction<T> weightFunction = new RatioWeightFunction<>();
        @Nullable
        private WeightListener<T> weightListener;
        private boolean concurrencyControl = false;
        private boolean manualConcurrencyControl = false;
        private Duration checkDuration = Duration.ofSeconds(1);
        private ScheduledExecutorService checkExecutor = SharedCheckExecutorHolder.getInstance();