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

com.github.lontime.extredisson.configuration.OptionResolver Maven / Gradle / Ivy

The newest version!
package com.github.lontime.extredisson.configuration;

import java.net.URI;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import com.github.lontime.base.commonj.utils.CollectionHelper;
import com.github.lontime.base.commonj.utils.NetHelper;
import com.github.lontime.base.commonj.utils.StringHelper;
import com.github.lontime.base.commonj.utils.SupplierHelper;
import com.github.lontime.base.serial.model.Header;
import com.github.lontime.extconfig.ConfigHelper;
import com.github.lontime.extconfig.WrapperConfig;
import com.github.lontime.extredisson.common.ClientKind;
import com.github.lontime.extredisson.common.CodecKind;
import com.github.lontime.extredisson.common.InternalRPCUtils;
import com.github.lontime.extredisson.common.ListenerKind;
import com.github.lontime.extredisson.common.LoadBalancerPolicy;
import com.github.lontime.extredisson.common.RedisKeys;
import com.github.lontime.extredisson.common.WatchKind;
import com.github.lontime.shaded.com.google.common.base.Splitter;
import com.github.lontime.shaded.io.helidon.config.Config;
import com.github.lontime.shaded.org.redisson.api.StreamMessageId;
import com.github.lontime.shaded.org.redisson.config.ReadMode;
import com.github.lontime.shaded.org.redisson.config.SslProvider;
import com.github.lontime.shaded.org.redisson.config.SubscriptionMode;
import com.github.lontime.shaded.org.redisson.config.TransportMode;
import com.github.lontime.shaded.org.redisson.connection.balancer.LoadBalancer;
import com.github.lontime.shaded.org.redisson.connection.balancer.RandomLoadBalancer;
import com.github.lontime.shaded.org.redisson.connection.balancer.RoundRobinLoadBalancer;
import com.github.lontime.shaded.org.redisson.connection.balancer.WeightedRoundRobinBalancer;

import static com.github.lontime.extredisson.common.Constants.CONSUMER_DEFAULT_GROUP;
import static com.github.lontime.extredisson.common.Constants.SERVICE_REPLYS;

/**
 * Redisson Option Resolver.
 *
 * @author lontime
 * @since 1.0
 */
public class OptionResolver {

    private static final String NAME = "redisson";

    //------------------singleton------------------
    /**
     * supplier.
     */
    private static Supplier supplier = SupplierHelper.memoize(OptionResolver::new);

    public static OptionResolver getInstance() {
        return supplier.get();
    }
    //------------------singleton------------------

    private final Options redissonOptions;

    public OptionResolver() {
        this.redissonOptions = ConfigHelper.resolve(NAME).as(new Mapper()).orElse(new Options());
    }

    public RedisKeys getProjectName() {
        return redissonOptions.getProjectName();
    }

    public String ip() {
        return redissonOptions.getIp();
    }

    public Duration getWaitPollTimeout() {
        return redissonOptions.getWaitPollTimeout();
    }

    public List getConnections() {
        final List connections = redissonOptions.getConnections();
        return CollectionHelper.isEmpty(connections) ? Collections.emptyList() : connections;
    }

    public ProducerOption getProducer(String name) {
        if (StringHelper.isNotEmpty(name)) {
            final List producers = redissonOptions.getProducers();
            for (ProducerOption producer : producers) {
                if (producer.getName().equals(name)) {
                    return producer;
                }
            }
        }
        return ProducerOption.topic(name);
    }

    public NodeOption getNodeOption() {
        return redissonOptions.getNode();
    }

    public ConnectionOption getConnection(String name) {
        final List connections = getConnections();
        if (StringHelper.isEmpty(name) || CollectionHelper.isEmpty(connections)) {
            return null;
        }
        return connections.stream().filter(s -> name.equals(s.getName())).findFirst().orElse(null);
    }

    public List getConsumers() {
        final List consumers = redissonOptions.getConsumers();
        final List services = redissonOptions.getServices();
        final List all = new ArrayList<>();
        if (CollectionHelper.isNotEmpty(consumers)) {
            all.addAll(consumers);
        }
        if (CollectionHelper.isNotEmpty(services)) {
            all.addAll(services);
        }
        return all;
    }

    public List getStreamNames() {
        return getConsumers().stream().map(ConsumerOption::getTopic).collect(Collectors.toList());
    }

    public RegistryOption registry() {
        return Optional.ofNullable(redissonOptions.getRegistry()).orElse(new RegistryOption());
    }

    public WatchOption getWatchOption() {
        return redissonOptions.getWatch();
    }

    static class Mapper implements Function {

        @Override
        public Options apply(Config config) {
            final Options options = new Options();
            final WrapperConfig wrapperConfig = new WrapperConfig(config);
            options.setIp(wrapperConfig.getAsString("ip").orElseGet(NetHelper::getLocalHost));
            wrapperConfig.getAsString("project").map(RedisKeys::create).ifPresent(options::setProjectName);
            options.setNode(config.get("node").as(new NodeMapper()).orElseGet(NodeOption::create));
            config.get("connections").asList(new ConnectionMapper()).ifPresent(options::setConnections);
            config.get("producers").asList(new ProducerMapper()).ifPresent(options::setProducers);
            config.get("consumers").asList(new ConsumerMapper()).ifPresent(options::setConsumers);
            config.get("services").asList(new ServiceMapper()).ifPresent(options::setServices);
            config.get("watch").as(new WatchMapper()).ifPresent(options::setWatch);
            config.get("registry").as(new RegistryMapper()).ifPresent(options::setRegistry);
            wrapperConfig.getAsDuration("waitPollTimeout").ifPresent(options::setWaitPollTimeout);
            return options;
        }
    }

    static class NodeMapper implements Function {

        @Override
        public NodeOption apply(Config config) {
            final WrapperConfig wrapperConfig = new WrapperConfig(config);
            final NodeOption option = wrapperConfig.getAsString("id")
                    .map(NodeOption::create).orElseGet(NodeOption::create);
            wrapperConfig.getAsDuration("period").ifPresent(option::setPeriod);
            wrapperConfig.getAsDuration("ttl").ifPresent(option::setTtl);
            wrapperConfig.getAsString("namespace").ifPresent(option::setNamespace);
            return option;
        }
    }

    static class ProducerMapper implements Function {

        @Override
        public ProducerOption apply(Config config) {
            final String name = config.get("name").asString().orElse(config.name());
            final ProducerOption option = new ProducerOption();
            option.setName(name);
            option.setTopic(config.get("topic").asString().orElse(name));
            config.get("timeout").asString().map(Duration::parse).ifPresent(option::setTimeout);
            config.get("headers").detach().asMap().map(this::headers).ifPresent(option::setHeaders);
            config.get("tags").asString()
                    .map(s -> Splitter.on(",").trimResults().omitEmptyStrings().splitToList(s))
                    .ifPresent(option::setTags);
            config.get("ref").asBoolean().ifPresent(option::setRef);
            config.get("enableReply").asBoolean().ifPresent(option::setEnableReply);
            config.get("maxRecheck").asInt().ifPresent(option::setMaxRecheck);
            config.get("page").asInt().ifPresent(option::setPage);
            return option;
        }

        public List
headers(Map map) { final List
headers = new ArrayList<>(map.size()); for (Map.Entry entry : map.entrySet()) { headers.add(Header.from(entry.getKey(), entry.getValue())); } return headers; } } static class RegistryMapper implements Function { @Override public RegistryOption apply(Config config) { final RegistryOption options = new RegistryOption(); config.get("name").asString().ifPresent(options::setName); config.get("keepAlive").asString().map(Duration::parse).ifPresent(options::setKeepAlive); return options; } } static class WatchMapper implements Function { @Override public WatchOption apply(Config config) { final WatchOption option = new WatchOption(); config.get("enabled").asBoolean().ifPresent(option::setEnabled); config.get("interval").asString().map(Duration::parse).ifPresent(option::setInterval); config.get("warmup").asString().map(Duration::parse).ifPresent(option::setWarmup); config.get("enableStream").asBoolean().ifPresent(option::setEnableStream); config.get("specs").asList(this::spec).ifPresent(option::setSpecs); config.get("enableServiceReply").asBoolean().ifPresent(option::setEnableServiceReply); config.get("serviceReply").as(this::spec).map(s -> { s.setName(SERVICE_REPLYS); s.setKind(WatchKind.REPLY); return s; }).ifPresent(option::setServiceReply); return option; } private WatchOption.Spec spec(Config config) { WatchOption.Spec specOption = new WatchOption.Spec(); specOption.setName(config.get("name").asString().orElse(config.name())); config.get("kind").asString().map(ConfigHelper::formatEnumName).map(WatchKind::valueOf) .ifPresent(specOption::setKind); config.get("maxLen").asInt().ifPresent(specOption::setMaxLen); config.get("maxLenRate").asDouble().ifPresent(specOption::setMaxLenRate); config.get("timeToLive").asString().map(Duration::parse).ifPresent(specOption::setTimeToLive); config.get("lockWaitTime").asString().map(Duration::parse).ifPresent(specOption::setLockWaitTime); config.get("lockLeaseTime").asString().map(Duration::parse).ifPresent(specOption::setLockLeaseTime); config.get("batchSize").asInt().ifPresent(specOption::setBatchSize); return specOption; } } static class ServiceMapper implements Function { @Override public ConsumerOption apply(Config config) { final CommonConsumerMapper mapper = new CommonConsumerMapper(); final ConsumerOption option = mapper.apply(config); config.get("service").asString().ifPresent(option::setTopic); option.setKind(ListenerKind.SERVICE); option.setMessageId(StreamMessageId.NEWEST); option.setGroupNoAck(Boolean.TRUE); return option; } } static class ConsumerMapper implements Function { @Override public ConsumerOption apply(Config config) { final CommonConsumerMapper mapper = new CommonConsumerMapper(); final ConsumerOption option = mapper.apply(config); option.setKind(ListenerKind.STREAM); return option; } } static class CommonConsumerMapper implements Function { @Override public ConsumerOption apply(Config config) { final WrapperConfig wrapperConfig = new WrapperConfig(config); final String name = config.name(); final ConsumerOption option = new ConsumerOption(); config.get("tag").asString().ifPresent(option::setTag); option.setName(config.get("name").asString().orElse(name)); option.setGroupName(config.get("groupName").asString().orElse(CONSUMER_DEFAULT_GROUP)); wrapperConfig.getAsEnum("kind", ListenerKind::valueOf).ifPresent(option::setKind); // config.get("kind").asString().map(String::toUpperCase).map(ListenerKind::valueOf).ifPresent(option::setKind); config.get("ref").asBoolean().ifPresent(option::setRef); option.setTopic(config.get("topic").asString().orElse(name)); config.get("next").asString().ifPresent(option::setNext); config.get("messageId").asString().map(this::streamMessageId).ifPresent(option::setMessageId); config.get("batchSize").asInt().ifPresent(option::setBatchSize); config.get("initLatestSize").asInt().ifPresent(option::setInitLatestSize); wrapperConfig.getAsDuration("timeout").ifPresent(option::setTimeout); option.setListener(config.get("listener").asString().orElse(name)); wrapperConfig.getAsDuration("interval").ifPresent(option::setInterval); wrapperConfig.getAsDuration("warmup").ifPresent(option::setWarmup); // config.get("groupName").asString().ifPresent(option::setGroupName); config.get("groupNoAck").asBoolean().ifPresent(option::setGroupNoAck); config.get("lazyListener").asBoolean().ifPresent(option::setLazyListener); wrapperConfig.getAsBoolean("enableClean").ifPresent(option::setEnableClean); wrapperConfig.getAsDuration("heartbeatInterval").ifPresent(option::setHeartbeatInterval); wrapperConfig.getAsDuration("localCleanInterval").ifPresent(option::setLocalCleanInterval); wrapperConfig.getAsDuration("cleanInterval").ifPresent(option::setCleanInterval); config.get("broadcast").asBoolean().ifPresent(option::setBroadcast); config.get("disableGroup").asBoolean().ifPresent(option::setDisableGroup); config.get("maxLen").asInt().ifPresent(option::setMaxLen); config.get("maxLenRate").asDouble().ifPresent(option::setMaxLenRate); return option; } private StreamMessageId streamMessageId(String m) { final char c = m.charAt(0); switch (c) { case '>': return StreamMessageId.NEVER_DELIVERED; case '$': return StreamMessageId.NEWEST; case '0': return StreamMessageId.ALL; default: return InternalRPCUtils.parseMessageId(m); } } } static class ConnectionMapper implements Function { @Override public ConnectionOption apply(Config config) { final ConnectionOption options = new ConnectionOption(); options.setName(config.name()); config.get("kind").asString() .map(String::toUpperCase) .map(s -> ClientKind.valueOf(s)) .ifPresent(options::setKind); config.get("database").asInt().ifPresent(options::setDatabase); config.get("username").asString().ifPresent(options::setUsername); config.get("password").asString().ifPresent(options::setPassword); config.get("clientName").asString().ifPresent(options::setClientName); config.get("codec").asString().map(String::toUpperCase) .map(s -> CodecKind.valueOf(s)).ifPresent(options::setCodec); config.get("threads").asInt().ifPresent(options::setThreads); config.get("nettyThreads").asInt().ifPresent(options::setNettyThreads); config.get("executor").asString().ifPresent(options::setExecutor); config.get("transportMode").asString().map(String::toUpperCase) .map(s -> TransportMode.valueOf(s)).ifPresent(options::setTransportMode); config.get("lockWatchdogTimeout").asInt().ifPresent(options::setLockWatchdogTimeout); config.get("keepPubSubOrder").asBoolean().ifPresent(options::setKeepPubSubOrder); config.get("performanceMode").asString().ifPresent(options::setPerformanceMode); config.get("sslEnableEndpointIdentification").asBoolean().ifPresent(options::setSslEnableEndpointIdentification); config.get("sslProvider").asString().map(String::toUpperCase).map(s -> SslProvider.valueOf(s)) .ifPresent(options::setSslProvider); config.get("sslTruststore").asList(String.class).ifPresent(options::setSslProtocols); config.get("sslTruststore").asString().map(s -> { try { return URI.create(s).toURL(); } catch (Exception e) { return null; } }).ifPresent(options::setSslTruststore); config.get("sslTruststorePassword").asString().ifPresent(options::setSslTruststorePassword); config.get("sslKeystore").asString().map(s -> { try { return URI.create(s).toURL(); } catch (Exception e) { return null; } }).ifPresent(options::setSslKeystore); config.get("sslKeystorePassword").asString().ifPresent(options::setSslKeystorePassword); config.get("dnsMonitoringInterval").asInt().ifPresent(options::setDnsMonitoringInterval); config.get("pingConnectionInterval").asInt().ifPresent(options::setPingConnectionInterval); config.get("keepAlive").asBoolean().ifPresent(options::setKeepAlive); config.get("tcpNoDelay").asBoolean().ifPresent(options::setTcpNoDelay); config.get("idleConnectionTimeout").asInt().ifPresent(options::setIdleConnectionTimeout); config.get("connectTimeout").asInt().ifPresent(options::setConnectTimeout); config.get("timeout").asInt().ifPresent(options::setTimeout); config.get("retryAttempts").asInt().ifPresent(options::setRetryAttempts); config.get("retryInterval").asInt().ifPresent(options::setRetryInterval); config.get("subscriptionsPerConnection").asInt().ifPresent(options::setSubscriptionsPerConnection); config.get("subscriptionConnectionMinimumIdleSize").asInt().ifPresent(options::setSubscriptionConnectionMinimumIdleSize); config.get("subscriptionConnectionPoolSize").asInt().ifPresent(options::setSubscriptionConnectionPoolSize); config.get("readMode").asString().map(String::toUpperCase).map(s -> ReadMode.valueOf(s)).ifPresent(options::setReadMode); config.get("subscriptionMode").asString().map(String::toUpperCase).map(s -> SubscriptionMode.valueOf(s)).ifPresent(options::setSubscriptionMode); config.get("loadBalancer").asString() .map(String::toUpperCase) .map(s -> LoadBalancerPolicy.valueOf(s)) .map(s -> this.balancer(s, config.get("weights"))) .ifPresent(options::setLoadBalancer); config.get("failedSlaveReconnectionInterval").asInt().ifPresent(options::setFailedSlaveReconnectionInterval); config.get("failedSlaveCheckInterval").asInt().ifPresent(options::setFailedSlaveCheckInterval); config.get("slaveConnectionMinimumIdleSize").asInt().ifPresent(options::setSlaveConnectionMinimumIdleSize); config.get("slaveConnectionPoolSize").asInt().ifPresent(options::setSlaveConnectionPoolSize); config.get("masterConnectionMinimumIdleSize").asInt().ifPresent(options::setMasterConnectionMinimumIdleSize); config.get("masterConnectionPoolSize").asInt().ifPresent(options::setMasterConnectionPoolSize); //cluster config.get("cluster").asNode().map(this::cluster).ifPresent(options::setCluster); //sentinel config.get("sentinel").asNode().map(this::sentinel).ifPresent(options::setSentinel); //MasterSlave config.get("masterSlave").asNode().map(this::masterSlave).ifPresent(options::setMasterSlave); //single // config.get("single").asNode().map(this::single).ifPresent(options::setSingle); config.get("address").asString().ifPresent(options::setAddress); config.get("connectionMinimumIdleSize").asInt().ifPresent(options::setConnectionMinimumIdleSize); config.get("connectionPoolSize").asInt().ifPresent(options::setConnectionPoolSize); return options; } private ConnectionOption.MasterSlave masterSlave(Config config) { final ConnectionOption.MasterSlave masterSlave = new ConnectionOption.MasterSlave(); config.get("slaveAddress").asList(String.class).map(s -> new HashSet<>(s)).ifPresent(masterSlave::setSlaveAddress); config.get("masterAddress").asString().ifPresent(masterSlave::setMasterAddress); return masterSlave; } private ConnectionOption.Sentinel sentinel(Config config) { final ConnectionOption.Sentinel sentinel = new ConnectionOption.Sentinel(); config.get("sentinelAddress").asList(String.class).ifPresent(sentinel::setSentinelAddress); config.get("masterName").asString().ifPresent(sentinel::setMasterName); config.get("sentinelPassword").asString().ifPresent(sentinel::setSentinelPassword); config.get("scanInterval").asInt().ifPresent(sentinel::setScanInterval); config.get("checkSentinelsList").asBoolean().ifPresent(sentinel::setCheckSentinelsList); config.get("checkSlaveStatusWithSyncing").asBoolean().ifPresent(sentinel::setCheckSlaveStatusWithSyncing); config.get("sentinelsDiscovery").asBoolean().ifPresent(sentinel::setSentinelsDiscovery); return sentinel; } private ConnectionOption.Cluster cluster(Config config) { final ConnectionOption.Cluster cluster = new ConnectionOption.Cluster(); config.get("nodeAddresses").asList(String.class).ifPresent(cluster::setNodeAddresses); config.get("scanInterval").asInt().ifPresent(cluster::setScanInterval); config.get("slots").asInt().ifPresent(cluster::setSlots); config.get("checkSlotsCoverage").asBoolean().ifPresent(cluster::setCheckSlotsCoverage); return cluster; } private LoadBalancer balancer(LoadBalancerPolicy policy, Config weightConfig) { if (policy == LoadBalancerPolicy.ROUND_ROBIN) { return new RoundRobinLoadBalancer(); } if (policy == LoadBalancerPolicy.RANDOM) { return new RandomLoadBalancer(); } if (policy == LoadBalancerPolicy.WEIGHTED_ROUND_ROBIN) { final Map hostMap = weightConfig.get("uris").detach().asMap().orElse(null); if (CollectionHelper.isEmpty(hostMap)) { return null; } final Integer defaultWeight = weightConfig.get("defaultWeight").asInt().orElse(100 / hostMap.size()); final Map weights = new HashMap<>(); for (Map.Entry entry : hostMap.entrySet()) { weights.put(Config.Key.unescapeName(entry.getKey()), Integer.valueOf(entry.getValue())); } return new WeightedRoundRobinBalancer(weights, defaultWeight); } return null; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy