/* * Copyright (c) 2010 Lockheed Martin Corporation * * 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 org.eurekastreams.server.action.execution.stream; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.eurekastreams.commons.actions.TaskHandlerExecutionStrategy; import org.eurekastreams.commons.actions.context.ActionContext; import org.eurekastreams.commons.actions.context.TaskHandlerActionContext; import org.eurekastreams.commons.logging.LogFactory; import org.eurekastreams.commons.server.UserActionRequest; import org.eurekastreams.server.action.request.DeleteFromSearchIndexRequest; import org.eurekastreams.server.action.request.stream.DeleteIdsFromListsRequest; import org.eurekastreams.server.domain.stream.Activity; import org.eurekastreams.server.persistence.mappers.cache.CacheKeys; import org.eurekastreams.server.persistence.mappers.db.DeleteActivities; import org.eurekastreams.server.persistence.mappers.db.GetListsContainingActivities; import org.eurekastreams.server.persistence.mappers.requests.BulkActivityDeleteResponse; /** * This execution strategy is responsible for deleting a batch of activities based on a list of activity ids supplied. * * This execution strategy will handle deleting the activities directly from the db and cache and then offload cached * list updates to an async job. * */ public class DeleteActivitiesByIdsExecution implements TaskHandlerExecutionStrategy<ActionContext> { /** * Local instance of logger. */ private final Log log = LogFactory.make(); /** * Mapper to get a list of cache keys that contain references to expired activities. */ private GetListsContainingActivities listsMapper; /** * Mapper to remove expired activities from the database. */ private DeleteActivities deleteMapper; /** * Constructor. * * @param inListsMapper * the lists containing activity references mapper. * @param inDeleteMapper * the delete mapper. */ public DeleteActivitiesByIdsExecution(final GetListsContainingActivities inListsMapper, final DeleteActivities inDeleteMapper) { listsMapper = inListsMapper; deleteMapper = inDeleteMapper; } /** * Delete the activities from the database and submit an async task to remove the activities from the respective * cache locations. {@inheritDoc}. */ @SuppressWarnings("unchecked") @Override public Serializable execute(final TaskHandlerActionContext<ActionContext> inActionContext) { List<Long> activityIds = (List<Long>) inActionContext.getActionContext().getParams(); if (log.isTraceEnabled()) { log.trace("Calling DeleteMapper to delete " + activityIds.size() + " activities"); } List<String> keys = listsMapper.execute(activityIds); // Deletes the activities and their comments from the database BulkActivityDeleteResponse response = deleteMapper.execute(activityIds); // Put an action on the queue to delete the activities from the appropriate lists if (log.isInfoEnabled()) { log.info("Queuing UserActionRequest for removing expired activities from index (num of ids): " + response.getActivityIds().size()); } // Put an action on the queue to delete the activities from search index inActionContext.getUserActionRequests().add( new UserActionRequest("deleteFromSearchIndexAction", null, new DeleteFromSearchIndexRequest( Activity.class, response.getActivityIds()))); if (log.isInfoEnabled()) { log.info("Queuing UserActionRequest for removing expired activity ids from lists cache keys: " + keys); } inActionContext.getUserActionRequests().add( new UserActionRequest("deleteIdsFromLists", null, new DeleteIdsFromListsRequest(keys, response .getActivityIds()))); if (log.isInfoEnabled()) { log.info("Queuing UserActionRequests for removing expired activity ids from cache: " + response.getActivityIds().size()); } // remove ALL activities from cache (low priority should we even do this?) generateIndividualDeleteKeyFromCacheTasks(new HashSet<String>(createKeys(CacheKeys.ACTIVITY_BY_ID, response .getActivityIds())), inActionContext); // Clean up security records. generateIndividualDeleteKeyFromCacheTasks(new HashSet<String>(createKeys(CacheKeys.ACTIVITY_SECURITY_BY_ID, response.getActivityIds())), inActionContext); if (log.isInfoEnabled()) { log.info("Queuing UserActionRequests for removing expired activitys' comment ids from cache: " + response.getCommentIds()); } // remove ALL comments from cache (low priority should we even do this?) generateIndividualDeleteKeyFromCacheTasks(new HashSet<String>(createKeys(CacheKeys.COMMENT_BY_ID, response .getCommentIds())), inActionContext); return null; } /** * Queues UserActionRequest for deleteKeysFromCache action, one for each key. * * @param keys * keys to delete from cache. * @param inActionContext * {@link TaskHandlerActionContext}. */ private void generateIndividualDeleteKeyFromCacheTasks(final Set<String> keys, final TaskHandlerActionContext<ActionContext> inActionContext) { Iterator<String> it = keys.iterator(); while (it.hasNext()) { inActionContext.getUserActionRequests() .add( new UserActionRequest("deleteCacheKeysAction", null, new HashSet<String>(Arrays.asList(it .next())))); } } /** * Generate cacheKeys. * * @param keyRoot * Root of key. * @param inIds * Id for key * @return List of generated keys. */ private List<String> createKeys(final String keyRoot, final List<Long> inIds) { List<String> keys = new ArrayList<String>(); for (Long id : inIds) { keys.add(keyRoot + id); } return keys; } }