/*
* Seldon -- open source prediction engine
* =======================================
* Copyright 2011-2015 Seldon Technologies Ltd and Rummble Ltd (http://www.seldon.io/)
*
**********************************************************************************************
*
* 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.seldon.api.caching.redis;
import io.seldon.api.APIException;
import io.seldon.api.caching.ActionHistory;
import io.seldon.api.caching.ActionLogEntry;
import io.seldon.db.redis.RedisPoolManager;
import io.seldon.general.Action;
import io.seldon.memcache.MemCacheKeys;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@Component
public class RedisActionHistory implements ActionHistory {
private static Logger logger = Logger.getLogger(RedisActionHistory.class.getName());
final private RedisPoolManager poolManager;
private ObjectMapper mapper = new ObjectMapper();
@Autowired
public RedisActionHistory(RedisPoolManager poolManager)
{
this.poolManager = poolManager;
}
@Override
public List<Long> getRecentActions(String clientName, long userId,int numActions) {
List<Long> res = new ArrayList<Long>();
JedisPool pool = poolManager.get(clientName);
if (pool != null)
{
Jedis jedis = null;
try
{
jedis = pool.getResource();
String key = MemCacheKeys.getActionHistory(clientName, userId);
Set<String> itemSet = jedis.zrange(key, 0, -1);
for (String item : itemSet)
{
item = item.replaceAll("\"", "");
res.add(0,Long.parseLong(item));// reverse order so last ones are earliest in time
}
if (res.size() > numActions)
res = res.subList(0, numActions);
}
finally
{
if (jedis != null) {
jedis.close();
}
}
}
else
{
logger.error("No redis pool found for "+clientName);
}
if (logger.isDebugEnabled())
logger.debug("For user "+userId+" found "+res.size()+" actions:"+res.toString());
return res;
}
@Override
public List<Action> getRecentFullActions(String clientName, long userId,int numActions) {
List<Action> actions = new ArrayList<Action>();
JedisPool pool = poolManager.get(clientName);
if (pool != null)
{
Jedis jedis = null;
try
{
jedis = pool.getResource();
String key = MemCacheKeys.getActionFullHistory(clientName, userId);
Set<String> actionSet = jedis.zrange(key, 0, -1);
for (String val : actionSet)
{
ActionLogEntry ale = mapper.readValue(val, ActionLogEntry.class);
actions.add(0,ale.toAction());
}
if (actions.size() > numActions)
actions = actions.subList(0, numActions);
}
catch (IOException e) {
logger.error("Failed to convert values to actions ",e);
}
finally
{
if (jedis != null) {
jedis.close();
}
}
}
else
{
logger.error("No redis pool found for "+clientName);
}
if (logger.isDebugEnabled())
logger.debug("For user "+userId+" found "+actions.size()+" full actions");
return actions;
}
@Override
public void addFullAction(String clientName, Action a) throws APIException {
JedisPool pool = poolManager.get(clientName);
if (pool != null)
{
Jedis jedis = null;
try
{
ActionLogEntry al = new ActionLogEntry(clientName,a);
String val = mapper.writeValueAsString(al);
String key = MemCacheKeys.getActionFullHistory(clientName, a.getUserId());
jedis = pool.getResource();
jedis.zadd(key, a.getDate().getTime()/1000, val);
//zremrangebyscore needed
}
catch (JsonProcessingException e)
{
logger.error("Failed to convert action to json ",e);
}
finally
{
if (jedis != null)
{
jedis.close();
}
}
}
else
{
logger.error("No redis pool found for "+clientName);
}
}
@Override
public void addAction(String clientName, long userId, long itemId)
throws APIException {
JedisPool pool = poolManager.get(clientName);
if (pool != null)
{
Jedis jedis = null;
try
{
long now = System.currentTimeMillis()/1000;
String key = MemCacheKeys.getActionHistory(clientName, userId);
jedis = pool.getResource();
jedis.zadd(key, now, ""+itemId);
//zremrangebyscore needed
}
finally
{
if (jedis != null)
{
jedis.close();
}
}
}
else
{
logger.error("No redis pool found for "+clientName);
}
}
}