/* * This is a common dao with basic CRUD operations and is not limited to any * persistent layer implementation * * Copyright (C) 2010 Imran M Yousuf (imyousuf@smartitengineering.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package com.smartitengineering.common.dao.search.impl; import com.google.inject.Inject; import com.google.inject.name.Named; import com.smartitengineering.common.dao.search.CommonFreeTextPersistentDao; import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author imyousuf */ public class CommonAsyncFreeTextPersistentDaoImpl<T> implements CommonFreeTextPersistentDao<T> { protected final Logger logger = LoggerFactory.getLogger(getClass()); private final Queue<Task<T[]>> saveQueue; private final long saveScheduleInterval; private final ScheduledExecutorService scheduledExecutorService; @Inject @Named("primaryFreeTextPersistentDao") private CommonFreeTextPersistentDao<T> primaryDao; @Inject public CommonAsyncFreeTextPersistentDaoImpl(@Named("saveInterval") long saveInterval, @Named("intervalTimeUnit") TimeUnit timeUnit) { saveQueue = new ConcurrentLinkedQueue<Task<T[]>>(); scheduledExecutorService = Executors.newScheduledThreadPool(1); this.saveScheduleInterval = saveInterval; initScheduledThreads(timeUnit); } private void initScheduledThreads(TimeUnit timeUnit) { scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { List<Task<T[]>> nextTasks = new ArrayList<Task<T[]>>(); Task<T[]> nextTask; do { nextTask = saveQueue.poll(); if (nextTask != null && nextTask.getEntity() != null) { nextTasks.add(nextTask); } } while (nextTask != null); for (Task<T[]> task : nextTasks) { T[] next = task.getEntity(); try { switch (task.getTaskType()) { case CREATE: primaryDao.save(next); break; case UPDATE: primaryDao.update(next); break; case DELETE: primaryDao.delete(next); break; } } catch (Exception ex) { logger.warn("Persisting to search persistent dao did not succeed! Adding back to queue", ex); saveQueue.add(task); } } } }, saveScheduleInterval, saveScheduleInterval, timeUnit); } @Override public void save(T... data) { addToTaskQueue(TaskType.CREATE, data); } @Override public void update(T... data) { addToTaskQueue(TaskType.UPDATE, data); } @Override public void delete(T... data) { addToTaskQueue(TaskType.DELETE, data); } private void addToTaskQueue(TaskType type, T... entities) { saveQueue.add(new Task<T[]>(type, entities)); } private static enum TaskType { CREATE, UPDATE, DELETE; } private static class Task<P> { private TaskType taskType; private P entity; public Task(TaskType taskType, P entity) { this.taskType = taskType; this.entity = entity; } public P getEntity() { return entity; } public TaskType getTaskType() { return taskType; } } }