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

io.inversion.redis.RedisAction Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2015-2019 Rocket Partners, LLC
 * https://github.com/inversion-api
 *
 * 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 io.inversion.redis;

import io.inversion.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.TreeMap;

/**
 * The service builds a key from the request url and parameters.  If the key does not exist within Redis,
 * the request is passed along to the GetHandler.  The JSON response from the GetHandler will be inserted
 * into Redis with an expiration if the JSON is not null or empty.
 * 

* The initial Redis check can be bypassed by including the skipCache (verify value below) request parameter. *

* The current implementation of Jedis.set() does not allow clobbering a key/value and expiration but will in * a future build. Because of that, Jedis.setex() is used. Since the SET command options can replace SETNX, * SETEX, PSETEX, it is possible that in future versions of Redis these three commands will be deprecated * and finally removed. *

* Jedis.set() parameter explanation... * nxxx NX|XX, NX -- Only set the key if it does not already exist. XX -- Only set the key if it already exist. * expx EX|PX, expire time units: EX = seconds; PX = milliseconds *

* A future version of jedis alter's .set() to allow for a SetParams object to be used to set 'ex' * without requiring the setting of 'nx' */ public class RedisAction extends Action { protected final Logger log = LoggerFactory.getLogger(getClass()); @Override public void run(Request req, Response res) throws ApiException { // //caching only makes sense for GET requests // if (!"GET".equalsIgnoreCase(req.getMethod())) // return; // // //only cache top level request, on internal recursive requests // if (req.getChain().getParent() != null) // return; // // RedisDb db = (RedisDb) req.getCollection().getDb(); // // String nocacheParam = req.getChain().getConfig("redisNocacheParam", db.getNocacheParam()); // // // remove this param before creating the key, so this param is not included in the key // boolean skipCache = (req.removeParam(nocacheParam) != null); // // if (skipCache) // return; // // Jedis jedis = null; // // try // { // if (!skipCache) // { // // the key is derived from the URL // String key = getCacheKey(req.getChain()); // // // request should include a json object // JSNode resJson = null; // // String value = null; // try // { // jedis = db.getRedisClient(); // value = jedis.get(key); // } // catch (Exception ex) // { // log.warn("Failed to retrieve from Redis the key: " + key, ex); // } // // if (value != null) // { // log.debug("CACHE HIT : " + key); // // resJson = JSNode.parseJsonNode(value); // res.withJson(resJson); // res.withStatus(Status.SC_200_OK); // req.getChain().cancel(); // } // else // { // log.debug("CACHE MISS: " + key); // // req.getChain().go(); // // // TODO should the naming convention include the TTL in the name? // // // see class header for explanation on setex() // // jedis.set(key, chain.getResponse().getJson().toString(), setParams().ex(ttl)); // // JSNode json = res.getJson(); // // if (res.getStatusCode() == 200 && json != null && json.getProperties().size() > 0) // { // // will NOT store empty JSON responses // try // { // int ttl = req.getChain().getConfig("redisTtl", db.getTtl()); // jedis.setex(key, ttl, json.toString()); // } // catch (Exception ex) // { // log.warn("Failed to save Redis key: " + key, ex); // } // } // } // } // } // finally // { // if (jedis != null) // { // try // { // jedis.close(); // } // catch (Exception ex) // { // log.warn("Error closing redis connection", ex); // } // } // } } /** * @param chain chain of the current request * @return an alphabetically concatenated string of each param beginning with '?' and joined by '&' */ String getCacheKey(Chain chain) { TreeMap sortedKeyMap = new TreeMap<>(chain.getRequest().getUrl().getParams()); StringBuilder sortedParams = new StringBuilder(); boolean isFirstParam = true; for (Map.Entry entry : sortedKeyMap.entrySet()) { if (isFirstParam) { sortedParams.append("?"); isFirstParam = false; } else sortedParams.append("&"); sortedParams.append(entry.getKey()); if (!entry.getValue().isEmpty()) { sortedParams.append("=").append(entry.getValue()); } } String key = chain.getRequest().getApiUrl(); key = key.substring(key.indexOf("://") + 3); key += chain.getRequest().getPath(); key += sortedParams; return key; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy