package com.sequenceiq.cloudbreak.core.flow2.chain;
import static com.sequenceiq.cloudbreak.core.flow2.Flow2Handler.FLOW_CHAIN_ID;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.sequenceiq.cloudbreak.cloud.event.Selectable;
import com.sequenceiq.cloudbreak.service.flowlog.FlowLogService;
import reactor.bus.Event;
import reactor.bus.EventBus;
@Component
public class FlowChains {
private static final Logger LOGGER = LoggerFactory.getLogger(FlowChains.class);
@Inject
private EventBus eventBus;
@Inject
private FlowLogService flowLogService;
private Map<String, Queue<Selectable>> flowChainMap = new ConcurrentHashMap<>();
private Map<String, String> flowChainParentMap = new ConcurrentHashMap<>();
public void putFlowChain(String flowChainId, String parentFlowChainId, Queue<Selectable> flowChain) {
flowChainMap.put(flowChainId, flowChain);
if (parentFlowChainId != null) {
flowChainParentMap.put(flowChainId, parentFlowChainId);
}
}
public void removeFlowChain(String flowChainId) {
if (flowChainId != null) {
flowChainMap.remove(flowChainId);
}
}
public void removeFullFlowChain(String flowChainId) {
removeFlowChain(flowChainId);
String parentFlowChainId;
while ((parentFlowChainId = flowChainParentMap.remove(flowChainId)) != null) {
removeFlowChain(parentFlowChainId);
flowChainId = parentFlowChainId;
}
}
public void triggerNextFlow(String flowChainId) {
Queue<Selectable> queue = flowChainMap.get(flowChainId);
if (queue != null) {
Selectable selectable = queue.poll();
if (selectable != null) {
sendEvent(flowChainId, selectable);
} else {
removeFlowChain(flowChainId);
triggerParentFlowChain(flowChainId);
}
flowLogService.saveChain(flowChainId, flowChainParentMap.get(flowChainId), queue);
}
}
protected void sendEvent(String flowChainId, Selectable selectable) {
LOGGER.info("Triggering event: {}", selectable);
Map<String, Object> headers = new HashMap<>();
headers.put(FLOW_CHAIN_ID, flowChainId);
eventBus.notify(selectable.selector(), new Event<>(new Event.Headers(headers), selectable));
}
private void triggerParentFlowChain(String flowChainId) {
String parentFlowChainId = flowChainId != null ? flowChainParentMap.remove(flowChainId) : null;
if (parentFlowChainId != null) {
triggerNextFlow(parentFlowChainId);
}
}
}