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

com.genexus.cache.redis.RedisClient Maven / Gradle / Ivy

package com.genexus.cache.redis;

import java.io.Closeable;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import org.apache.commons.lang.StringUtils;

import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.genexus.Application;
import com.genexus.ICacheService2;
import com.genexus.diagnostics.core.ILogger;
import com.genexus.diagnostics.core.LogManager;
import com.genexus.util.GXService;
import com.genexus.util.GXServices;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Pipeline;


public class RedisClient implements ICacheService2, Closeable {
	public static final ILogger logger = LogManager.getLogger(RedisClient.class);
	private String keyPattern = "%s_%s_%s"; //Namespace_KEY
	private static int REDIS_DEFAULT_PORT = 6379;
	private JedisPool pool;
	private ObjectMapper objMapper;

	public RedisClient() throws URISyntaxException {
		initCache();
	}

	public RedisClient(String hostOrRedisURL, String password, String cacheKeyPattern) throws URISyntaxException {
		initCache(hostOrRedisURL, password, cacheKeyPattern);
	}

	public JedisPool getConnection() {
		return pool;
	}

	private void initCache() throws URISyntaxException {
		GXService providerService = Application.getGXServices().get(GXServices.CACHE_SERVICE);
		String addresses = providerService.getProperties().get("CACHE_PROVIDER_ADDRESS");
		String cacheKeyPattern = providerService.getProperties().get("CACHE_PROVIDER_KEYPATTERN");
		String password = providerService.getProperties().get("CACHE_PROVIDER_PASSWORD");
		initCache(addresses, password, cacheKeyPattern);
	}

	private void initCache(String hostOrRedisURL, String password, String cacheKeyPattern) throws URISyntaxException {
		keyPattern = isNullOrEmpty(cacheKeyPattern) ? keyPattern : cacheKeyPattern;
		String host = "127.0.0.1";
		hostOrRedisURL = isNullOrEmpty(hostOrRedisURL) ? host: hostOrRedisURL;
		int port = REDIS_DEFAULT_PORT;

		boolean isRedisURIScheme = hostOrRedisURL.startsWith("redis://");
		String sRedisURI = isRedisURIScheme ? hostOrRedisURL : "redis://" + hostOrRedisURL;

		try {
			URI redisURI = new URI(sRedisURI);
			host = redisURI.getHost();
			if (redisURI.getPort() > 0) {
				port = redisURI.getPort();
			}
		} catch (URISyntaxException e) {
			logger.error(String.format("Could not parse Redis URL. Check for supported URLs: %s" , sRedisURI), e);
			throw e;
		}

		password = (!isNullOrEmpty(password)) ? password : null;

		pool = new JedisPool(new JedisPoolConfig(), host, port, redis.clients.jedis.Protocol.DEFAULT_TIMEOUT, password);

		objMapper = new ObjectMapper();
		objMapper
			.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
			.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
			.setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE)
			.setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.NONE);
		objMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
		objMapper.enable(SerializationFeature.INDENT_OUTPUT);
	}

	private boolean isNullOrEmpty(String s) {
		return s == null || s.trim().length() == 0;
	}

	private Boolean containsKey(String key) {
		try (Jedis jedis = pool.getResource()) {
			return jedis.exists(key);
		} catch (Exception e) {
			logger.error("Contains failed", e);
		}
		return false;
	}

	private  void set(String key, T value) {
		set(key, value, 0);
	}

	private  void set(String key, T value, int expirationSeconds) {
		try (Jedis jedis = pool.getResource()) {
			String valueJSON = objMapper.writeValueAsString(value);
			if (expirationSeconds > 0)
				jedis.setex(key, expirationSeconds, valueJSON);
			else
				jedis.set(key, valueJSON);
		} catch (Exception e) {
			logger.error("Set with TTL failed", e);
		}
	}

	public  void setAll(String cacheid, String[] keys, T[] values, int expirationSeconds) {
		try (Jedis jedis = pool.getResource()) {
			if (keys != null && values != null && keys.length == values.length) {
				String[] prefixedKeys = getKey(cacheid, keys);
				Pipeline p = jedis.pipelined();
				int idx = 0;
				for (String key : prefixedKeys) {
					String valueJSON = objMapper.writeValueAsString(values[idx]);
					if (expirationSeconds > 0)
						p.setex(key, expirationSeconds, valueJSON);
					else
						p.set(key, valueJSON);
					idx++;
				}
				p.sync();
			}
		} catch (Exception e) {
			logger.error("SetAll with TTL failed", e);
		}
	}

	private  T get(String key, Class type) {
		try (Jedis jedis = pool.getResource()) {
			String json = jedis.get(key);
			if (StringUtils.isNotEmpty(json)) {
				return objMapper.readValue(json, type);
			} else {
				return null;
			}
		} catch (Exception e) {
			logger.error("Get Item failed", e);
		}
		return null;
	}

	public  List getAll(String cacheid, String[] keys, Class type) {
		List result = null;
		try (Jedis jedis = pool.getResource()) {
			String[] prefixedKeys = getKey(cacheid, keys);
			List json = jedis.mget(prefixedKeys);
			result = new ArrayList();
			for (String val : json) {
				if (val != null)
					result.add(objMapper.readValue(val, type));
				else
					result.add(null);
			}
			return result;
		} catch (Exception e) {
			logger.error("Get Item failed", e);
		}
		return null;
	}


	public boolean containtsKey(String cacheid, String key) {
		return containsKey(getKey(cacheid, key));
	}

	public  T get(String cacheid, String key, Class type) {
		return get(getKey(cacheid, key), type);
	}


	public  void set(String cacheid, String key, T value) {
		set(getKey(cacheid, key), value);
	}

	public  void set(String cacheid, String key, T value, int duration) {
		set(getKey(cacheid, key), value, duration);
	}

	public void clear(String cacheid, String key) {
		try (Jedis jedis = pool.getResource()) {
			jedis.del(getKey(cacheid, key));
		} catch (Exception e) {
			logger.error("Remove Item failed", e);
		}
	}

	public void clearCache(String cacheid) {
		try (Jedis jedis = pool.getResource()) {
			jedis.incr(cacheid);
		} catch (Exception e) {
			logger.error("clearCache failed", e);
		}
	}

	public void clearKey(String key) {
		try (Jedis jedis = pool.getResource()) {
			jedis.del(key);
		} catch (Exception e) {
			logger.error("Remove Item failed", e);
		}
	}

	public void clearAllCaches() {
		try (Jedis jedis = pool.getResource()) {
			jedis.flushAll();
		} catch (Exception e) {
			logger.error("Clear All Caches failed", e);
		}
	}

	private String getKey(String cacheid, String key) {
		return String.format(keyPattern, cacheid, getKeyPrefix(cacheid), com.genexus.CommonUtil.getHash(key));
	}

	private String[] getKey(String cacheid, String[] keys) {
		Long prefix = getKeyPrefix(cacheid);
		String[] prefixedKeys = new String[keys.length];
		for (int idx = 0; idx < keys.length; idx++) {
			prefixedKeys[idx] = formatKey(cacheid, keys[idx], prefix);
		}
		return prefixedKeys;
	}

	private String formatKey(String cacheid, String key, Long prefix) {
		return String.format(keyPattern, cacheid, prefix, com.genexus.CommonUtil.getHash(key));
	}

	private Long getKeyPrefix(String cacheid) {
		Long prefix = get(cacheid, Long.class);
		if (prefix == null) {
			prefix = new java.util.Date().getTime();
			set(cacheid, Long.valueOf(prefix));
		}
		return prefix;
	}

	@Override
	public void close() throws IOException {
		if (pool != null)
			pool.destroy();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy