package gov.nysenate.openleg.service.notification.dispatch; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Range; import gov.nysenate.openleg.dao.base.LimitOffset; import gov.nysenate.openleg.dao.notification.NotificationSearchDao; import gov.nysenate.openleg.dao.notification.NotificationSubscriptionDao; import gov.nysenate.openleg.model.notification.*; import gov.nysenate.openleg.model.search.SearchException; import gov.nysenate.openleg.model.search.SearchResults; import gov.nysenate.openleg.service.notification.data.NotificationDigestService; import gov.nysenate.openleg.util.DateUtils; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * A service that gets pending notification digest subscriptions, constructs the subscribed digests, * and dispatches them to a notification digest sender */ @Service public class NotificationDigestDispatcher { private static final Logger logger = LoggerFactory.getLogger(NotificationDigestDispatcher.class); @Autowired private NotificationSubscriptionDao subDao; @Autowired private NotificationDigestService digestService; @Autowired private List<NotificationDigestSender> senderList; /** A map of target types (email, slack etc.) to services that will send formatted digests to these types */ private ImmutableMap<NotificationTarget, NotificationDigestSender> senderMap; @PostConstruct public void init() { Map<NotificationTarget, NotificationDigestSender> senderMapInit = new HashMap<>(); senderList.forEach(sender -> sender.getTargets().forEach(target -> senderMapInit.put(target, sender))); senderMap = ImmutableMap.copyOf(senderMapInit); } @Scheduled(cron = "0 */1 * * * *") public void processPendingDigests() { Set<NotificationDigestSubscription> pendingDigests = subDao.getPendingDigests(); if (pendingDigests.isEmpty()) { return; } logger.info("processing {} pending notification digests..", pendingDigests.size()); pendingDigests.stream() .peek(this::sendDigest) .forEach(this::postProcess); logger.info("notification digests sent"); } public void sendDigest(NotificationDigestSubscription subscription) { NotificationDigest digest = null; try { digest = digestService.getDigest(subscription); if (subscription.isSendEmptyDigest() || !digest.isEmpty()) { logger.info("sending {} to {}:{}", NotificationDigestFormatter.getSummary(digest), digest.getTarget(), digest.getAddress()); senderMap.get(subscription.getTarget()).sendDigest(digest); } } catch (SearchException e) { logger.error("Could not retrieve notifications for digest subscription: \n" + subscription, e); } } /** --- Internal Methods --- */ /** Sets the next digest time for a processed subscription */ private void postProcess(NotificationDigestSubscription subscription) { subDao.updateNextDigest(subscription.getId(), subscription.getNewNextDigest()); } }