package io.lumify.core.model.notification; import io.lumify.core.model.lock.LockRepository; import io.lumify.core.model.user.UserRepository; import io.lumify.core.model.workQueue.WorkQueueRepository; import io.lumify.core.user.User; import io.lumify.core.util.LumifyLogger; import io.lumify.core.util.LumifyLoggerFactory; import org.apache.commons.lang.time.DateUtils; import org.json.JSONObject; import java.util.Date; import java.util.List; public abstract class SystemNotificationRepository extends NotificationRepository { private static final LumifyLogger LOGGER = LumifyLoggerFactory.getLogger(SystemNotificationRepository.class); private static final String LOCK_NAME = SystemNotificationRepository.class.getName(); private boolean shutdown; public abstract List<SystemNotification> getActiveNotifications(User user); public abstract List<SystemNotification> getFutureNotifications(Date maxDate, User user); public abstract SystemNotification createNotification(SystemNotificationSeverity severity, String title, String message, String actionEvent, JSONObject actionPayload, Date startDate, Date endDate); public SystemNotification createNotification( SystemNotificationSeverity severity, String title, String message, Date startDate, Date endDate ) { return createNotification(severity, title, message, null, null, startDate, endDate); } public SystemNotification createNotification( SystemNotificationSeverity severity, String title, String message, String externalUrl, Date startDate, Date endDate ) { String actionEvent = null; JSONObject actionPayload = null; if (externalUrl != null) { actionEvent = Notification.ACTION_EVENT_EXTERNAL_URL; actionPayload = new JSONObject(); actionPayload.put("url", externalUrl); } return createNotification(severity, title, message, actionEvent, actionPayload, startDate, endDate); } public abstract SystemNotification getNotification(String rowKey, User user); public abstract SystemNotification updateNotification(SystemNotification notification); public abstract void endNotification(SystemNotification notification); public static JSONObject toJSONObject(SystemNotification notification) { JSONObject json = new JSONObject(); json.put("id", notification.getId()); json.put("type", "system"); json.put("severity", notification.getSeverity().toString()); json.put("title", notification.getTitle()); json.put("message", notification.getMessage()); if (notification.getActionEvent() != null) { JSONObject action = new JSONObject(); action.put("event", notification.getActionEvent()); action.putOpt("data", notification.getActionPayload()); json.put("action", action); } json.put("startDate", notification.getStartDate().getTime()); json.put("endDate", notification.getEndDate() == null ? null : notification.getEndDate().getTime()); json.put("hash", hash(json.toString())); return json; } public static boolean isActive(SystemNotification notification) { Date now = new Date(); Date endDate = notification.getEndDate(); return notification.getStartDate().before(now) && (endDate == null || endDate.after(now)); } // TODO: use LeaderSelector, http://curator.apache.org/curator-recipes/leader-election.html protected void startBackgroundThread(final LockRepository lockRepository, final UserRepository userRepository, final WorkQueueRepository workQueueRepository) { Runnable acquireLock = new Runnable() { @Override public void run() { Runnable useLock = new Runnable() { @Override public void run() { LOGGER.debug("using successfully acquired lock"); runPeriodically(userRepository, workQueueRepository); } }; LOGGER.debug("acquiring lock..."); lockRepository.lock(LOCK_NAME, useLock); } }; LOGGER.debug("starting background thread"); Thread thread = new Thread(acquireLock); thread.setName(this.getClass().getSimpleName() + "-background-thread"); thread.setDaemon(true); thread.start(); } private void runPeriodically(UserRepository userRepository, WorkQueueRepository workQueueRepository) { while (!shutdown) { LOGGER.debug("running periodically"); Date now = new Date(); Date nowPlusOneMinute = DateUtils.addMinutes(now, 1); List<SystemNotification> notifications = getFutureNotifications(nowPlusOneMinute, userRepository.getSystemUser()); for (SystemNotification notification : notifications) { workQueueRepository.pushSystemNotification(notification); } try { long remainingMilliseconds = nowPlusOneMinute.getTime() - System.currentTimeMillis(); if (remainingMilliseconds > 0) { Thread.sleep(remainingMilliseconds); } } catch (InterruptedException e) { // do nothing } } } public void shutdown() { shutdown = true; } }