def _hook_launch(self, kwargs, d): """Snoop launch commands to keep track of the current task.""" self.task = kwargs['task'] self.launcher = kwargs.pop('launcher') self.logRelay = LogRelay(self.launcher.bus.sendToTarget, self.task) # Fail tasks that exited cleanly but didn't report success. def cb_checkResult(result): if not self.task.status.final: raise InternalWorkerError("Task failed to send a finalized " "status before terminating.") return result d.addCallback(cb_checkResult) # Turn process termination events into relevant exceptions. def eb_filterErrors(reason): if reason.check(ierror.ProcessTerminated, ierror.ProcessDone): log.error("Worker exited prematurely with status %s", reason.value.status) raise InternalWorkerError("The worker executing the task " "has exited abnormally.") return reason d.addErrback(eb_filterErrors) # Report errors back to the dispatcher. Using a function here because # self.task will get replaced. def eb_failTask(reason): self.launcher.failTask(reason, self.task) d.addErrback(eb_failTask) # Clear saved task and launcher fields after the task is done. def bb_clearTask(result): self.logRelay.close() self.task = self.launcher = self.logRelay = None d.addBoth(bb_clearTask) d.addErrback(logger.logFailure)
class WorkerParent(WorkerProtocol): """Communicate messages from the launcher to the executor.""" def __init__(self): self.ctr = 0 self.pending = {} self.task = None self.launcher = None self.logRelay = None def callRemote(self, command, **kwargs): ctr = self.ctr self.ctr += 1 d = self.pending[ctr] = defer.Deferred() if command == 'launch': self._hook_launch(kwargs, d) self.sendCommand(ctr, command, **kwargs) return d def connectionLost(self, reason): """Child process went away, fail all pending calls.""" for d in self.pending.values(): d.errback(reason) def cmd_ack(self, ctr, **result): if not result: result = None d = self.pending.pop(ctr) d.callback(result) def _hook_launch(self, kwargs, d): """Snoop launch commands to keep track of the current task.""" self.task = kwargs['task'] self.launcher = kwargs.pop('launcher') self.logRelay = LogRelay(self.launcher.bus.sendToTarget, self.task) # Fail tasks that exited cleanly but didn't report success. def cb_checkResult(result): if not self.task.status.final: raise InternalWorkerError("Task failed to send a finalized " "status before terminating.") return result d.addCallback(cb_checkResult) # Turn process termination events into relevant exceptions. def eb_filterErrors(reason): if reason.check(ierror.ProcessTerminated, ierror.ProcessDone): log.error("Worker exited prematurely with status %s", reason.value.status) raise InternalWorkerError("The worker executing the task " "has exited abnormally.") return reason d.addErrback(eb_filterErrors) # Report errors back to the dispatcher. Using a function here because # self.task will get replaced. def eb_failTask(reason): self.launcher.failTask(reason, self.task) d.addErrback(eb_failTask) # Clear saved task and launcher fields after the task is done. def bb_clearTask(result): self.logRelay.close() self.task = self.launcher = self.logRelay = None d.addBoth(bb_clearTask) d.addErrback(logger.logFailure) def cmd_status_update(self, ctr, task): """Propagate status updates back to the dispatcher.""" if task.task_uuid != self.task.task_uuid: log.warning("Dropping worker status report for wrong task.") return self.task = task self.launcher.forwardTaskStatus(task) def cmd_push_logs(self, ctr, records): if not self.task: return self.launcher.forwardTaskLogs(self.task, records)