package com.neverwinterdp.scribengin.dataflow.service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.neverwinterdp.registry.Node;
import com.neverwinterdp.registry.Registry;
import com.neverwinterdp.registry.RegistryException;
import com.neverwinterdp.registry.event.NodeEventListener;
import com.neverwinterdp.registry.event.NodeChildrenListener;
import com.neverwinterdp.registry.event.NodeEvent;
import com.neverwinterdp.scribengin.dataflow.DataflowRegistry;
import com.neverwinterdp.scribengin.dataflow.DataflowTaskDescriptor;
import com.neverwinterdp.scribengin.event.ScribenginEvent;
public class AssignedDataflowTaskListener extends NodeChildrenListener<ScribenginEvent> {
private Map<String, DataflowTaskHeartbeatListener> assignedTaskListeners = new HashMap<>();
private DataflowRegistry dataflowRegistry ;
public AssignedDataflowTaskListener(DataflowRegistry dataflowRegistry) throws RegistryException {
super(dataflowRegistry.getRegistry(), true);
this.dataflowRegistry = dataflowRegistry;
watchChildren(dataflowRegistry.getTasksAssignedPath());
}
@Override
public ScribenginEvent toAppEvent(Registry registry, NodeEvent nodeEvent) throws Exception {
ScribenginEvent appEvent = new ScribenginEvent("assigned-tasks", nodeEvent);
return appEvent;
}
@Override
public void onEvent(ScribenginEvent event) throws Exception {
NodeEvent nodeEvent = event.getNodeEvent();
if(nodeEvent.getType() == NodeEvent.Type.CHILDREN_CHANGED) {
onChildrenChange(event) ;
} else if(nodeEvent.getType() == NodeEvent.Type.DELETE) {
} else {
System.err.println("unhandle assigned dataflow task event: " + nodeEvent.getPath() + " - " + nodeEvent.getType());
}
}
synchronized public void onChildrenChange(ScribenginEvent event) {
try {
Registry registry = getRegistry();
List<String> assignedTaskNames = registry.getChildren(dataflowRegistry.getTasksAssignedPath());
for(String taskName : assignedTaskNames) {
if(assignedTaskListeners.containsKey(taskName)) continue;
addHeartbeatListener(taskName);
}
} catch (RegistryException e) {
e.printStackTrace();
}
}
synchronized void addHeartbeatListener(String taskName) throws RegistryException {
DataflowTaskHeartbeatListener heartbeatListener = new DataflowTaskHeartbeatListener(dataflowRegistry, taskName);
assignedTaskListeners.put(taskName, heartbeatListener);
}
synchronized void removeHeartbeatListener(String heartbeatPath) throws RegistryException {
Node heartbeatNode = new Node(getRegistry(), heartbeatPath);
Node assignedTaskNode = heartbeatNode.getParentNode();
assignedTaskListeners.remove(assignedTaskNode.getName());
DataflowTaskDescriptor descriptor = dataflowRegistry.getTaskDescriptor(assignedTaskNode.getName());
DataflowTaskDescriptor.Status status = descriptor.getStatus();
if(status != DataflowTaskDescriptor.Status.SUSPENDED && status != DataflowTaskDescriptor.Status.TERMINATED) {
dataflowRegistry.dataflowTaskSuspend(descriptor);
System.err.println(" detect unfinished task: " + assignedTaskNode.getName() + ", status = " + status);
}
}
public class DataflowTaskHeartbeatListener extends NodeEventListener<ScribenginEvent> {
public DataflowTaskHeartbeatListener(DataflowRegistry dataflowRegistry, String taskName) throws RegistryException {
super(dataflowRegistry.getRegistry(), true);
String heartbeatPath = dataflowRegistry.getTasksAssignedPath() + "/" + taskName + "/heartbeat";
watchExists(heartbeatPath);
}
@Override
public ScribenginEvent toAppEvent(Registry registry, NodeEvent nodeEvent) throws Exception {
ScribenginEvent appEvent = new ScribenginEvent("assigned-task-heartbeat", nodeEvent);
return appEvent;
}
@Override
public void onEvent(ScribenginEvent event) throws Exception {
NodeEvent nodeEvent = event.getNodeEvent();
if(nodeEvent.getType() == NodeEvent.Type.DELETE) {
removeHeartbeatListener(nodeEvent.getPath());
setComplete();
}
}
}
}