package de.anycook.newrecipe; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import de.anycook.db.drafts.RecipeDraftsStore; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.ws.rs.container.AsyncResponse; import javax.ws.rs.core.Response; import java.sql.SQLException; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; /** * @author Jan Graßegger<jan@anycook.de> */ public enum DraftNumberProvider { INSTANCE; private final Logger logger; private final Cache<Integer, BlockingQueue<AsyncResponse>> suspended; private DraftNumberProvider(){ logger = LogManager.getLogger(getClass()); suspended = CacheBuilder.newBuilder() .maximumSize(10000) .expireAfterWrite(5, TimeUnit.MINUTES) .build(); } public void wakeUpSuspended(int userId) throws SQLException { logger.debug("waking up suspended"); BlockingQueue<AsyncResponse> queue = suspended.getIfPresent(userId); if(queue == null) return; int newNumber = 0; try(RecipeDraftsStore draftsStore = RecipeDraftsStore.getRecipeDraftStore()) { newNumber = draftsStore.countDrafts(userId); } catch (Exception e) { logger.error("failed to retrieve new draft number", e); } while(!queue.isEmpty()){ logger.debug("reading response"); try { AsyncResponse response = queue.take(); if(response.isSuspended()) response.resume(String.valueOf(newNumber)); } catch (InterruptedException e) { logger.warn(e, e); } } suspended.put(userId, queue); } public void suspend(int userId, AsyncResponse response){ response.setTimeoutHandler(asyncResponse -> { logger.info("reached timeout"); asyncResponse.resume(Response.ok().build()); }); response.setTimeout(5, TimeUnit.MINUTES); logger.debug("supending "+userId); try { BlockingQueue<AsyncResponse> queue = suspended.get(userId, () -> new ArrayBlockingQueue<>(1000)); queue.add(response); suspended.put(userId, queue); } catch (ExecutionException e) { logger.error(e, e); } } }