package com.breakersoft.plow.dispatcher; import java.util.UUID; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.stereotype.Component; import com.breakersoft.plow.Node; import com.breakersoft.plow.Task; import com.breakersoft.plow.dispatcher.domain.DispatchNode; import com.breakersoft.plow.dispatcher.domain.DispatchProc; import com.breakersoft.plow.dispatcher.pipeline.PipelineCommandService; import com.breakersoft.plow.dispatcher.pipeline.PipelineController; import com.breakersoft.plow.dispatcher.pipeline.StopTaskCommand; import com.breakersoft.plow.monitor.PlowStats; import com.breakersoft.plow.rnd.thrift.Ping; import com.breakersoft.plow.rnd.thrift.RunTaskResult; import com.breakersoft.plow.service.JobService; import com.breakersoft.plow.service.NodeService; import com.breakersoft.plow.util.PlowUtils; /** * Manages the the running procs on a node. * * @author chambers * */ @Component public class RndEventHandler { private static final Logger logger = org.slf4j.LoggerFactory.getLogger(RndEventHandler.class); @Autowired StatsService statsService; @Autowired NodeService nodeService; @Autowired NodeDispatcher nodeDispatcher; @Autowired DispatchService dispatchService; @Autowired JobService jobService; @Autowired PipelineCommandService pipelineCommandService; @Autowired PipelineController pipelineController; /** * This is a oneway method, the RNDaemon is not listening for a response. * * @param ping */ public void handleNodePing(Ping ping) { logger.trace("{} node reporting in.", ping.getHostname()); DispatchNode node; try { node = dispatchService.getDispatchNode(ping.hostname); nodeService.updateNode(node, ping); } catch (EmptyResultDataAccessException e) { Node newNode = nodeService.createNode(ping); node = dispatchService.getDispatchNode(newNode.getName()); } PlowStats.rndPingCount.incrementAndGet(); if (PlowUtils.isValid(ping.tasks)) { statsService.updateProcRuntimeStats(ping.tasks); statsService.updateTaskRuntimeStats(ping.tasks); statsService.updateLayerRuntimeStats(ping.tasks); statsService.recalculateLayerMinimumMemory(ping.tasks); statsService.updateJobRuntimeStats(ping.tasks); } if (node.isDispatchable()) { nodeDispatcher.asyncDispatch(node); } } public void handleRunTaskResult(RunTaskResult result) { Task task = null; DispatchProc proc = null; try { task = jobService.getTask(UUID.fromString(result.taskId)); } catch (EmptyResultDataAccessException e) { logger.error("The task {} no longer exists, on job: {}. Ignoring RunTaskResult.", result.taskId, result.jobId); } try { proc = dispatchService.getDispatchProc(result.procId); } catch (EmptyResultDataAccessException e) { logger.error("The proc {} no longer exists, was running task {}. Ignoring RunTaskResult.", result.procId, result.taskId); } // TODO: might be possible to recover task rather than just returning. // in one of two ways. If the task is waiting then we accept a good // RunTaskResult and mark it succeeded. If its running, we can kill // the existing process and mark as succeeded. if (proc == null || task == null) { return; } PlowStats.rndTaskComplete.incrementAndGet(); // May throw back to RND if the job's pipeline is full. // Will internally spawn a dispatch proc command. pipelineController.execute( new StopTaskCommand(result, task, proc, pipelineCommandService)); } }