package fi.otavanopisto.muikku.plugins.schooldatapyramus.rest.cache; import java.io.IOException; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.PostConstruct; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Observes; import javax.inject.Inject; import org.apache.commons.lang3.StringUtils; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import fi.otavanopisto.muikku.plugins.schooldatapyramus.webhook.WebhookNotificationEvent; @ApplicationScoped public class EntityCacheEvictor { @Inject private Logger logger; @Inject private CacheConfigs cacheConfigs; @PostConstruct public void init() { caches = Collections.synchronizedSet(new HashSet<AbstractEntityCache>()); } public void addCache(AbstractEntityCache cache) { try { caches.add(cache); } catch (Exception e) { logger.log(Level.SEVERE, "Failed to add cache to entity cache evictor", e); } } public void removeCache(AbstractEntityCache cache) { try { caches.remove(cache); } catch (Exception e) { logger.log(Level.SEVERE, "Failed to remove cache from entity cache evictor", e); } } public void evictPath(String path) { try { for (AbstractEntityCache cache : caches) { cache.remove(path); } } catch (Exception e) { logger.log(Level.SEVERE, String.format("Failed to evict path %s", path)); } } public void flushAll() { try { for (AbstractEntityCache cache : caches) { cache.clear(); } } catch (Exception e) { logger.log(Level.SEVERE, String.format("Failed to flush all caches")); } } public void onWebhookNotificationEvent(@Observes WebhookNotificationEvent event) { try { List<String> evictTypePaths = cacheConfigs.getEvictTypePaths(event.getType()); Map<String, String> data = null; try { data = new ObjectMapper().readValue(event.getData(), new TypeReference<Map<String, String>>() { }); } catch (IOException e) { logger.log(Level.SEVERE, "Could not parse webhook notification data", e); return; } for (AbstractEntityCache cache : caches) { try { Pattern pattern = Pattern.compile("\\{[a-zA-Z]*\\}"); for (String evictTypePath : evictTypePaths) { String path = evictTypePath; Matcher matcher = pattern.matcher(path); while (matcher.find()) { String variable = StringUtils.substring(matcher.group(0), 1, -1); String value = data.get(variable); if (value != null) { path = matcher.replaceFirst(value); } else { logger.log(Level.SEVERE, String.format("Failed to parse path %s", evictTypePath)); break; } matcher = pattern.matcher(path); } cache.remove(path); } } catch (Exception e) { logger.log(Level.SEVERE, "Failed to evict caches", e); return; } } } catch (Exception e) { logger.log(Level.SEVERE, "Cache evict crashed", e); } } private Set<AbstractEntityCache> caches; }