package com.baasbox.service.events;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
import com.baasbox.util.EmptyConcurrentMap;
import com.fasterxml.jackson.databind.JsonNode;
/**
* Stub service for sse connections
* Created by Andrea Tortorella on 12/09/14.
*/
public class EventsService {
private static final ConcurrentMap<EventSource,EventSource> DEFAULT = new EmptyConcurrentMap<>();
public static enum StatType{
SCRIPT,
ALL,
SYSTEM_LOGGER
}
private final static ConcurrentMap<StatType,ConcurrentMap<EventSource,EventSource>> STATS_CHANNELS =
new ConcurrentHashMap<>();
public static final AtomicInteger howManyScriptLoggerListener = new AtomicInteger(0);
public static void addListener(StatType channel,EventSource src){
STATS_CHANNELS.compute(channel,(c,listeners)->{
if (listeners == null){
listeners = new ConcurrentHashMap<EventSource, EventSource>();
}
listeners.put(src,src);
if (channel==StatType.SCRIPT) howManyScriptLoggerListener.getAndIncrement();
return listeners;
});
}
public static void removeScriptLogListener(EventSource src){
removeListener(StatType.SCRIPT,src);
}
public static void addScriptLogListener(EventSource src){
addListener(StatType.SCRIPT,src);
}
public static void removeSystemLogListener(EventSource src){
removeListener(StatType.SYSTEM_LOGGER,src);
}
public static void addSystemLogListener(EventSource src){
addListener(StatType.SYSTEM_LOGGER,src);
}
/**
*
* @param channel
* @param src
* @return true if no more listeners are present for this channel type
*/
public static boolean removeListener(StatType channel,EventSource src){
ConcurrentMap<EventSource, EventSource> remaining = STATS_CHANNELS.computeIfPresent(channel,(ch,listeners)->{
EventSource removed = listeners.remove(src);
if(removed!=null){
removed.close();
}
if (listeners.isEmpty()){
return null;
}
return listeners;
});
return remaining==null||remaining.isEmpty();
}
public static int publish(StatType type,String message) throws IllegalArgumentException{
if (type ==StatType.ALL){
throw new IllegalArgumentException("Cannot publish on all channel");
}
LongAdder a= new LongAdder();
String messageToSend=message;
STATS_CHANNELS.getOrDefault(type,DEFAULT).forEach((_e,e)->{
e.sendData(messageToSend);
a.increment();
});
return a.intValue();
}
public static int publish(StatType type,JsonNode message) throws IllegalArgumentException{
return publish(type,message.toString());
}
}