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

ai.grakn.engine.data.RedisWrapper Maven / Gradle / Ivy

There is a newer version: 1.4.3
Show newest version
/*
 * Grakn - A Distributed Semantic Database
 * Copyright (C) 2016-2018 Grakn Labs Limited
 *
 * Grakn is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Grakn is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Grakn. If not, see .
 */
package ai.grakn.engine.data;

import ai.grakn.engine.GraknConfig;
import ai.grakn.exception.GraknBackendException;
import ai.grakn.util.SimpleURI;
import com.google.common.base.Preconditions;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.util.Pool;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static ai.grakn.GraknConfigKey.REDIS_HOST;
import static ai.grakn.GraknConfigKey.REDIS_POOL_SIZE;
import static ai.grakn.GraknConfigKey.REDIS_SENTINEL_HOST;
import static ai.grakn.GraknConfigKey.REDIS_SENTINEL_MASTER;

/**
 * This class just wraps a Jedis  pool so it's transparent whether
 * we use Sentinel or not (and TODO partitioning)
 *
 * @author pluraliseseverythings
 */
public class RedisWrapper {

    private Pool jedisPool;
    private Set uriSet;

    private RedisWrapper(Pool jedisPool, Set uriSet) {
        this.jedisPool = jedisPool;
        this.uriSet = uriSet;
    }

    public static RedisWrapper create(GraknConfig config) {
        List redisUrl = config.getProperty(REDIS_HOST);
        List sentinelUrl = config.getProperty(REDIS_SENTINEL_HOST);
        int poolSize = config.getProperty(REDIS_POOL_SIZE);
        boolean useSentinel = !sentinelUrl.isEmpty();
        Builder builder = builder()
                .setUseSentinel(useSentinel)
                .setPoolSize(poolSize)
                .setURI((useSentinel ? sentinelUrl : redisUrl));
        if (useSentinel) {
            builder.setMasterName(config.getProperty(REDIS_SENTINEL_MASTER));
        }
        return builder.build();
    }

    public Pool getJedisPool() {
        return jedisPool;
    }

    public static Builder builder() {
        return new Builder();
    }

    public void close() {
        jedisPool.close();
    }

    public void testConnection() {
        try {
            getJedisPool().getResource();
        } catch (JedisConnectionException e) {
            throw GraknBackendException.serverStartupException(
                "Redis is not available. Make sure it's running on "
                        + String.join(", ", uriSet)
                        + ". It's possible the destination"
                        + "directory for the rdb and aof files is not writable. Restarting "
                        + "Redis could fix it.", e);
        }
    }

    /**
     * Builder for the wrapper
     */
    public static class Builder {

        static final int DEFAULT_PORT = 6379;
        static final int TIMEOUT = 5000;

        private boolean useSentinel = false;
        private Set uriSet = new HashSet<>();
        private String masterName = null;

        // This is the number of simultaneous connections to Jedis
        private int poolSize = 32;

        public Builder setUseSentinel(boolean useSentinel) {
            this.useSentinel = useSentinel;
            return this;
        }

        public Builder addURI(String uri) {
            this.uriSet.add(uri);
            return this;
        }

        public Builder setURI(Collection uri) {
            this.uriSet = new HashSet<>(uri);
            return this;
        }

        public Builder setMasterName(String masterName) {
            this.masterName = masterName;
            return this;
        }

        public Builder setPoolSize(int poolSize) {
            this.poolSize = poolSize;
            return this;
        }

        public RedisWrapper build() {
            // TODO make connection pool sizes configurable
            Preconditions
                    .checkState(!uriSet.isEmpty(), "Trying to build RedisWrapper without uriSet");
            Preconditions.checkState(!(!useSentinel && uriSet.size() > 1),
                    "More than one URL provided but Sentinel not used");
            Preconditions.checkState(!(useSentinel && masterName == null),
                    "Using Sentinel but master name not provided");
            Pool jedisPool;
            JedisPoolConfig poolConfig = new JedisPoolConfig();
            poolConfig.setTestOnBorrow(true);
            poolConfig.setTestOnReturn(true);
            poolConfig.setMaxTotal(poolSize);
            if (useSentinel) {
                jedisPool = new JedisSentinelPool(masterName, uriSet, poolConfig, TIMEOUT);
            } else {
                String uri = uriSet.iterator().next();
                SimpleURI simpleURI = SimpleURI.withDefaultPort(uri, DEFAULT_PORT);
                jedisPool = new JedisPool(poolConfig, simpleURI.getHost(), simpleURI.getPort(),
                        TIMEOUT);
            }
            return new RedisWrapper(jedisPool, uriSet);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy