/* * 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.items; import io.seldon.api.resource.ConsumerBean; import io.seldon.api.resource.service.PersistenceProvider; import io.seldon.db.jdo.JDOFactory; import io.seldon.general.ItemPeer; import io.seldon.memcache.DogpileHandler; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.*; @Component public class RecentItemsWithTagsManager { private static Logger logger = Logger.getLogger(RecentItemsWithTagsManager.class.getName()); public static final int CACHE_TIME_SECS = 1800; private final PersistenceProvider persister; private final DogpileHandler dogpileHandler; private final ConcurrentMap<String, ItemTags> clientStores = new ConcurrentHashMap<>(); private final ConcurrentMap<String, Boolean> loading = new ConcurrentHashMap<>(); private BlockingQueue<Runnable> queue = new LinkedBlockingDeque<>(); private ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 3, 10, TimeUnit.MINUTES, queue) { protected void afterExecute(java.lang.Runnable runnable, java.lang.Throwable throwable) { JDOFactory.get().cleanupPM(); } }; @Autowired public RecentItemsWithTagsManager(PersistenceProvider persister,DogpileHandler dogpileHandler) { this.persister = persister; this.dogpileHandler = dogpileHandler; } private void getRecentItems(final String client,final Set<Long> ids,final int attrId,final String table) { executor.execute(new Runnable() { @Override public void run() { final String key = getKey(client,attrId,table); try { ItemPeer iPeer = persister.getItemPersister(client); ConsumerBean c = new ConsumerBean(); c.setShort_name(client); logger.info("Loading recent item tags for "+key); long t1 = System.currentTimeMillis(); Map<Long,List<String>> res = iPeer.getRecentItemTags(ids,attrId,table); long t2 = System.currentTimeMillis(); logger.info("Loaded recent item tags of size "+res.size()+" for "+key+" in "+(t2-t1)+" msec"); clientStores.put(key, new ItemTags(res,ids)); } catch(Exception ex) { logger.error("Failed to load recent items with key "+key,ex); } finally { loading.remove(key); dogpileHandler.updated(key, CACHE_TIME_SECS); } } }); } private String getKey(String client,int attrId,String table) { return client + ":" +attrId+":"+table; } public Map<Long,List<String>> retrieveRecentItems(String client, Set<Long> ids,int attrId,String table) { final String key = getKey(client, attrId,table); ItemTags items = clientStores.get(key); if(items!=null && !ids.equals(items.ids)){ logger.info("Tag ids mismatch so setting items to null for "+client+" attrId:"+attrId+" table "+table); items = null; } if (items == null) { if ((loading.putIfAbsent(key, true) == null)) { getRecentItems(client, ids, attrId, table); } return new HashMap<>(); } else { if (dogpileHandler.updateIsRequired(key, items, CACHE_TIME_SECS)) { getRecentItems(client, ids, attrId, table); } return items.itemTags; } } public ItemPeer getRecentItemPeer(String client){ return null; } private static class ItemTags { Map<Long,List<String>> itemTags; Set<Long> ids; public ItemTags(Map<Long, List<String>> itemTags,Set<Long> ids) { super(); this.itemTags = itemTags; this.ids = ids; } } }