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

com.netflix.dyno.jedis.JedisConnectionFactory Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright 2011 Netflix
 *
 * 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.dyno.jedis;

import com.netflix.dyno.connectionpool.AsyncOperation;
import com.netflix.dyno.connectionpool.Connection;
import com.netflix.dyno.connectionpool.ConnectionContext;
import com.netflix.dyno.connectionpool.ConnectionFactory;
import com.netflix.dyno.connectionpool.Host;
import com.netflix.dyno.connectionpool.HostConnectionPool;
import com.netflix.dyno.connectionpool.ListenableFuture;
import com.netflix.dyno.connectionpool.Operation;
import com.netflix.dyno.connectionpool.OperationMonitor;
import com.netflix.dyno.connectionpool.OperationResult;
import com.netflix.dyno.connectionpool.exception.DynoConnectException;
import com.netflix.dyno.connectionpool.exception.DynoException;
import com.netflix.dyno.connectionpool.exception.FatalConnectionException;
import com.netflix.dyno.connectionpool.impl.ConnectionContextImpl;
import com.netflix.dyno.connectionpool.impl.OperationResultImpl;
import org.apache.commons.lang.NotImplementedException;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.util.Sharded;

import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocketFactory;
import java.util.concurrent.TimeUnit;

public class JedisConnectionFactory implements ConnectionFactory {

    private static final org.slf4j.Logger Logger = LoggerFactory.getLogger(JedisConnectionFactory.class);

    private final OperationMonitor opMonitor;
    private final SSLSocketFactory sslSocketFactory;

    public JedisConnectionFactory(OperationMonitor monitor, SSLSocketFactory sslSocketFactory) {
        this.opMonitor = monitor;
        this.sslSocketFactory = sslSocketFactory;
    }

    @Override
    public Connection createConnection(HostConnectionPool pool)
            throws DynoConnectException {
        return new JedisConnection(pool);
    }

    @Override
    public Connection createConnectionWithDataStore(HostConnectionPool pool)
            throws DynoConnectException {
        return new JedisConnection(pool, true);
    }

    @Override
    public Connection createConnectionWithConsistencyLevel(HostConnectionPool pool, String consistency) {
        JedisConnection connection = new JedisConnection(pool);
        connection.setConsistencyLevel(consistency);
        return connection;
    }

    // TODO: raghu compose redisconnection with jedisconnection in it
    public class JedisConnection implements Connection {

        private final HostConnectionPool hostPool;
        private final Jedis jedisClient;
        private final ConnectionContextImpl context = new ConnectionContextImpl();
        private String consistencyLevel;

        private DynoConnectException lastDynoException;

        public JedisConnection(HostConnectionPool hostPool) {
            this(hostPool, false);
        }

        public JedisConnection(HostConnectionPool hostPool, boolean connectDataStore) {
            this.hostPool = hostPool;
            Host host = hostPool.getHost();

            int port = connectDataStore ? host.getDatastorePort() : host.getPort();

            if (sslSocketFactory == null) {
                JedisShardInfo shardInfo = new JedisShardInfo(host.getHostAddress(), port,
                        hostPool.getConnectionTimeout(), hostPool.getSocketTimeout(), Sharded.DEFAULT_WEIGHT);
                shardInfo.setPassword(host.getPassword());

                jedisClient = new Jedis(shardInfo);
            } else {
                JedisShardInfo shardInfo = new JedisShardInfo(host.getHostAddress(), port,
                        hostPool.getConnectionTimeout(), hostPool.getSocketTimeout(), Sharded.DEFAULT_WEIGHT,
                        true, sslSocketFactory, new SSLParameters(), null);
                shardInfo.setPassword(host.getPassword());

                jedisClient = new Jedis(shardInfo);
            }
        }

        public void setConsistencyLevel(String consistency) {
            this.consistencyLevel = consistency;
        }

        public boolean isConsistencyLevelProvided() {
            return this.consistencyLevel != null;
        }

        @Override
        public  OperationResult execute(Operation op) throws DynoException {

            long startTime = System.nanoTime() / 1000;
            String opName = op.getName();

            OperationResultImpl opResult = null;

            try {
                R result = op.execute(jedisClient, context);
                if (context.hasMetadata("compression") || context.hasMetadata("decompression")) {
                    opMonitor.recordSuccess(opName, true);
                } else {
                    opMonitor.recordSuccess(opName);
                }
                opResult = new OperationResultImpl(opName, result, opMonitor);
                opResult.addMetadata("connectionId", String.valueOf(this.hashCode()));
                return opResult;

            } catch (JedisConnectionException ex) {
                Logger.warn("Caught JedisConnectionException: " + ex.getMessage());
                opMonitor.recordFailure(opName, ex.getMessage());
                lastDynoException = (DynoConnectException) new FatalConnectionException(ex).setAttempt(1).setHost(this.getHost());
                throw lastDynoException;

            } catch (RuntimeException ex) {
                Logger.warn("Caught RuntimeException: " + ex.getMessage());
                opMonitor.recordFailure(opName, ex.getMessage());
                lastDynoException = (DynoConnectException) new FatalConnectionException(ex).setAttempt(1).setHost(this.getHost());
                throw lastDynoException;

            } finally {
                long duration = System.nanoTime() / 1000 - startTime;
                if (opResult != null) {
                    opResult.setLatency(duration, TimeUnit.MICROSECONDS);
                }
            }
        }

        @Override
        public  ListenableFuture> executeAsync(AsyncOperation op) throws DynoException {
            throw new NotImplementedException();
        }

        @Override
        public void close() {
            jedisClient.quit();
            jedisClient.disconnect();
        }

        @Override
        public Host getHost() {
            return hostPool.getHost();
        }

        @Override
        public void open() throws DynoException {
            jedisClient.connect();
            if (isConsistencyLevelProvided()) {
                jedisClient.getClient().sendCommand(DynoConfigCommand.CONN_CONSISTENCY, this.consistencyLevel);
                jedisClient.getClient().getStatusCodeReply();
            }
        }

        @Override
        public DynoConnectException getLastException() {
            return lastDynoException;
        }

        @Override
        public HostConnectionPool getParentConnectionPool() {
            return hostPool;
        }

        @Override
        public void execPing() {
            final String result;

            try {
                result = jedisClient.ping();
            } catch (JedisConnectionException e) {
                throw new DynoConnectException("Unsuccessful ping", e);
            }

            if (result == null || result.isEmpty()) {
                throw new DynoConnectException("Unsuccessful ping, got empty result");
            }
        }

        @Override
        public ConnectionContext getContext() {
            return context;
        }

        public Jedis getClient() {
            return jedisClient;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy