package gov.nysenate.openleg.service.notification.subscription;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import gov.nysenate.openleg.dao.notification.NotificationSubscriptionDao;
import gov.nysenate.openleg.model.cache.CacheEvictEvent;
import gov.nysenate.openleg.model.cache.CacheEvictIdEvent;
import gov.nysenate.openleg.model.cache.CacheWarmEvent;
import gov.nysenate.openleg.model.cache.ContentCache;
import gov.nysenate.openleg.model.notification.NotificationDigestSubscription;
import gov.nysenate.openleg.model.notification.NotificationSubscription;
import gov.nysenate.openleg.model.notification.NotificationType;
import gov.nysenate.openleg.service.base.data.CachingService;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Service
public class CachedNotificationSubscriptionDataService implements NotificationSubscriptionDataService, CachingService
{
@Autowired private CacheManager cacheManager;
@Autowired private EventBus eventBus;
@Autowired
private NotificationSubscriptionDao subscriptionDao;
private Cache subCache;
private static final String subCacheKey = "sUbCaChE";
@PostConstruct
private void init() {
setupCaches();
eventBus.register(this);
}
@PreDestroy
private void cleanUp() {
evictCaches();
cacheManager.removeCache(ContentCache.NOTIFICATION_SUBSCRIPTION.name());
}
/** --- NotificationSubscriptionDataService Implementation --- */
/**
* {@inheritDoc}
*/
@Override
public Set<NotificationSubscription> getSubscriptions(String userName) {
return getSubscriptions().stream()
.filter(subscription -> StringUtils.equals(userName, subscription.getUserName()))
.collect(Collectors.toSet());
}
/**
* {@inheritDoc}
*/
@Override
public Set<NotificationSubscription> getSubscriptions(NotificationType type) {
return getSubscriptions().stream()
.filter(subscription -> subscription.getType().covers(type))
.collect(Collectors.toSet());
}
/**
* {@inheritDoc}
*/
@Override
public void insertSubscription(NotificationSubscription subscription) {
try {
subscriptionDao.insertSubscription(subscription);
evictCaches();
} catch (DuplicateKeyException ignored){}
}
/**
* {@inheritDoc}
*/
@Override
public void removeSubscription(NotificationSubscription subscription) {
subscriptionDao.removeSubscription(subscription);
evictCaches();
}
/** {@inheritDoc} */
@Override
public Set<NotificationDigestSubscription> getPendingDigests() {
return subscriptionDao.getPendingDigests();
}
/** {@inheritDoc} */
@Override
public Set<NotificationDigestSubscription> getDigestSubsForUser(String username) {
return subscriptionDao.getDigestSubsForUser(username);
}
/** {@inheritDoc} */
@Override
public void insertDigestSubscription(NotificationDigestSubscription subscription) {
subscriptionDao.insertDigestSubscription(subscription);
}
/** {@inheritDoc} */
@Override
public void updateNextDigest(int digestSubscriptionId, LocalDateTime nextDigest) {
subscriptionDao.updateNextDigest(digestSubscriptionId, nextDigest);
}
/** {@inheritDoc} */
@Override
public void removeDigestSubscription(int digestSubscriptionId) {
subscriptionDao.removeDigestSubscription(digestSubscriptionId);
}
/** --- CachingService Implementations --- */
/**
* {@inheritDoc}
*/
@Override
public void setupCaches() {
subCache = new Cache(new CacheConfiguration().name(ContentCache.NOTIFICATION_SUBSCRIPTION.name())
.eternal(true)
.sizeOfPolicy(defaultSizeOfPolicy()));
cacheManager.addCache(subCache);
}
/**
* {@inheritDoc}
*/
@Override
public List<Ehcache> getCaches() {
return Arrays.asList(subCache);
}
/**
* {@inheritDoc}
*/
@Subscribe
@Override
public void handleCacheEvictEvent(CacheEvictEvent evictEvent) {
if (evictEvent.affects(ContentCache.NOTIFICATION_SUBSCRIPTION)) {
evictCaches();
}
}
/** {@inheritDoc} */
@Subscribe
@Override
public void handleCacheEvictIdEvent(CacheEvictIdEvent evictIdEvent) {
if (evictIdEvent.affects(ContentCache.NOTIFICATION_SUBSCRIPTION)) {
evictCaches();
}
}
/** {@inheritDoc} */
@Override
public void evictContent(Object o) {
evictCaches();
}
/**
* {@inheritDoc}
*/
@Override
public void warmCaches() {
getSubscriptions();
}
/**
* {@inheritDoc}
*/
@Subscribe
@Override
public void handleCacheWarmEvent(CacheWarmEvent warmEvent) {
if (warmEvent.affects(ContentCache.NOTIFICATION_SUBSCRIPTION)) {
warmCaches();
}
}
/** --- Internal Methods --- */
private Set<NotificationSubscription> getSubscriptions() {
Element element = subCache.get(subCacheKey);
if (element != null) {
return (Set<NotificationSubscription>) element.getObjectValue();
}
Set<NotificationSubscription> subscriptions = subscriptionDao.getSubscriptions();
subCache.put(new Element(subCacheKey, subscriptions));
return subscriptions;
}
}