def process_death(pids, run_number): """ Execute death on the current transform. This is invoked in a sub-process via a call from the Celery master process. If death has already been invoked then this is a no-op. @aram pids List of process IDs whose process_birth method has been invoked. If this process is in the list then this method just returns (PID, None). @return status of (PID, None) if all went well or (PID, {"error":ERROR, "message":MESSAGE}) if an exception arose. PID is the sub-process ID. This lets the master process know that the sub-process has executed this operation. """ run_footer = "" status = None logger = logging.getLogger(__name__) # Check if processed already. if (not os.getpid() in pids): # Only call if the transform is not already dead. if (not MausTransform.is_dead): try: if logger.isEnabledFor(logging.INFO): logger.info("Deathing transform "+str(run_number)) MausTransform.death() run_footer = maus_cpp.run_action_manager.end_of_run(run_number) except Exception as exc: # pylint:disable = W0703 status = {} status["error"] = str(exc.__class__) status["message"] = str(exc) if logger.isEnabledFor(logging.DEBUG): logger.debug("Status: %s " % status) return (os.getpid(), status, run_footer)
def process_death(pids, run_number): """ Execute death on the current transform. This is invoked in a sub-process via a call from the Celery master process. If death has already been invoked then this is a no-op. @aram pids List of process IDs whose process_birth method has been invoked. If this process is in the list then this method just returns (PID, None). @return status of (PID, None) if all went well or (PID, {"error":ERROR, "message":MESSAGE}) if an exception arose. PID is the sub-process ID. This lets the master process know that the sub-process has executed this operation. """ run_footer = "" status = None logger = logging.getLogger(__name__) # Check if processed already. if (not os.getpid() in pids): # Only call if the transform is not already dead. if (not MausTransform.is_dead): try: if logger.isEnabledFor(logging.INFO): logger.info("Deathing transform " + str(run_number)) MausTransform.death() run_footer = maus_cpp.run_action_manager.end_of_run(run_number) except Exception as exc: # pylint:disable = W0703 status = {} status["error"] = str(exc.__class__) status["message"] = str(exc) if logger.isEnabledFor(logging.DEBUG): logger.debug("Status: %s " % status) return (os.getpid(), status, run_footer)
def test_birth(self): """ Invoke birth @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("{}") self.assertTrue(not MausTransform.is_dead, \ "Expected is_dead to be False")
def test_birth(self): """ Invoke birth @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("{}") self.assertTrue(not MausTransform.is_dead, \ "Expected is_dead to be False")
def test_birth_exception(self): """ Invoke birth when a ValueError is thrown by birth. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") with self.assertRaisesRegexp(WorkerBirthFailedException, ".*Birth exception.*"): MausTransform.birth("""{"birth_result":%s}""" % \ MapPyTestMap.EXCEPTION)
def test_birth_fails(self): """ Invoke birth when WorkerBirthFailedException is thrown. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") with self.assertRaisesRegexp(WorkerBirthFailedException, ".*MapPyTestMap returned False.*"): MausTransform.birth("""{"birth_result":%s}""" % \ MapPyTestMap.FAIL)
def test_birth_fails(self): """ Invoke birth when WorkerBirthFailedException is thrown. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") with self.assertRaisesRegexp(WorkerBirthFailedException, ".*MapPyTestMap returned False.*"): MausTransform.birth("""{"birth_result":%s}""" % \ MapPyTestMap.FAIL)
def test_birth_exception(self): """ Invoke birth when a ValueError is thrown by birth. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") with self.assertRaisesRegexp(WorkerBirthFailedException, ".*Birth exception.*"): MausTransform.birth("""{"birth_result":%s}""" % \ MapPyTestMap.EXCEPTION)
def test_process(self): """ Invoke process. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("{}") spill = MausTransform.process("{}") spill_doc = json.loads(spill) self.assertTrue(spill_doc.has_key("processed"), "Expected spill to have been processed")
def test_initialize(self): """ Invoke initialize. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") self.assertEquals(MapPyTestMap, \ MausTransform.transform.__class__, "Unexpected transform") self.assertTrue(MausTransform.is_dead, "Expected is_dead to be True") self.assertTrue(ROOT.gROOT.IsBatch(), "Expected ROOT.IsBatch() to be True") # pylint:disable=E1101, C0301
def test_execute_transform(self): """ Invoke execute_transform. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("{}") spill = execute_transform("{}") spill_doc = json.loads(spill) self.assertTrue(spill_doc.has_key("processed"), "Expected spill to have been processed")
def test_initialize(self): """ Invoke initialize. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") self.assertEquals(MapPyTestMap, \ MausTransform.transform.__class__, "Unexpected transform") self.assertTrue(MausTransform.is_dead, "Expected is_dead to be True") self.assertTrue(ROOT.gROOT.IsBatch(), "Expected ROOT.IsBatch() to be True") # pylint:disable=E1101, C0301
def test_initialize_bad_transform(self): """ Invoke initialize with an unknown transform. @param self Object reference. """ with self.assertRaisesRegexp( ValueError, ".*No such transform: UnknownTransform.*"): MausTransform.initialize("UnknownTransform") self.assertEquals(None, MausTransform.transform, \ "Unexpected transform") self.assertTrue(MausTransform.is_dead, \ "Expected is_dead to be True")
def test_initialize_bad_transform(self): """ Invoke initialize with an unknown transform. @param self Object reference. """ with self.assertRaisesRegexp(ValueError, ".*No such transform: UnknownTransform.*"): MausTransform.initialize("UnknownTransform") self.assertEquals(None, MausTransform.transform, \ "Unexpected transform") self.assertTrue(MausTransform.is_dead, \ "Expected is_dead to be True")
def test_execute_transform_fails(self): """ Invoke execute_transform when a ValueError is thrown by the transform's process method. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("""{"process_result":%s}""" % \ MapPyTestMap.EXCEPTION) with self.assertRaisesRegexp( WorkerProcessException, ".*MapPyTestMap process threw an exception.*"): execute_transform("{}")
def execute_transform(spill, client_id = "Unknown"): """ MAUS Celery transform task used by sub-processes to execute jobs from clients. Proxies of this task are invoked by clients.This applies the current transform to the spill and returns the new spill. @param spill JSON document string holding spill. @param client_id ID of client who submitted job. @return JSON document string holding new spill. @throws Exception if there is a problem when process is called. """ logger = Task.get_logger() if logger.isEnabledFor(logging.INFO): logger.info("Task invoked by %s" % client_id) try: spill_json = json.loads(spill) if "maus_event_type" in spill_json.keys() and \ spill_json["maus_event_type"] != "Spill": return spill else: return maus_cpp.converter.string_repr(MausTransform.process(spill)) except Exception as exc: # pylint:disable = W0703 # Filter exceptions so no unPicklable exception causes # problems. status = {} status["error"] = str(exc.__class__) status["message"] = str(exc) raise WorkerProcessException(MausConfiguration.transform, status)
def process_birth(pids, config_id, transform, configuration, run_number): """ Create and birth a new transform. This is invoked in a sub-process via a call from the Celery master process. Any existing transform is death-ed first. @param pids List of process IDs whose process_birth method has been invoked. If this process is in the list then this method just returns (PID, None). @param config_id Configuration ID from client. @param transform Either a single name can be given - representing a single transform - or a list of transforms - representing a MapPyGroup. Sub-lists are treated as nested MapPyGroups. If None then the current transform is deathed and rebirthed. @param configuration Valid JSON configuration document. @return status of (PID, None) if all went well or (PID, {"error":ERROR, "message":MESSAGE}) if an exception arose. PID is the sub-process ID. This lets the master process know that the sub-process has executed this operation. """ run_header = "" status = None logger = logging.getLogger(__name__) # Check if processed already. if (not os.getpid() in pids): try: if not maus_cpp.globals.has_instance(): maus_cpp.globals.birth(configuration) if logger.isEnabledFor(logging.INFO): logger.info("Start of run action") run_header = maus_cpp.run_action_manager.start_of_run(run_number) if logger.isEnabledFor(logging.INFO): logger.info("Birthing transform %s" % transform) MausTransform.initialize(transform) MausTransform.birth(configuration) # Update sub-process configuration. MausConfiguration.configuration = configuration MausConfiguration.transform = transform MausConfiguration.config_id = config_id if logger.isEnabledFor(logging.INFO): logger.info("Finished birthing transforms %s" % transform) except Exception as exc: # pylint:disable = W0703 status = {} status["error"] = str(exc.__class__) status["message"] = str(exc) if logger.isEnabledFor(logging.DEBUG): logger.debug("Status: %s " % status) return (os.getpid(), status, run_header)
def process_birth(pids, config_id, transform, configuration, run_number): """ Create and birth a new transform. This is invoked in a sub-process via a call from the Celery master process. Any existing transform is death-ed first. @param pids List of process IDs whose process_birth method has been invoked. If this process is in the list then this method just returns (PID, None). @param config_id Configuration ID from client. @param transform Either a single name can be given - representing a single transform - or a list of transforms - representing a MapPyGroup. Sub-lists are treated as nested MapPyGroups. If None then the current transform is deathed and rebirthed. @param configuration Valid JSON configuration document. @return status of (PID, None) if all went well or (PID, {"error":ERROR, "message":MESSAGE}) if an exception arose. PID is the sub-process ID. This lets the master process know that the sub-process has executed this operation. """ run_header = "" status = None logger = logging.getLogger(__name__) # Check if processed already. if (not os.getpid() in pids): try: if not maus_cpp.globals.has_instance(): maus_cpp.globals.birth(configuration) if logger.isEnabledFor(logging.INFO): logger.info("Start of run action") run_header = maus_cpp.run_action_manager.start_of_run(run_number) if logger.isEnabledFor(logging.INFO): logger.info("Birthing transform %s" % transform) MausTransform.initialize(transform) MausTransform.birth(configuration) # Update sub-process configuration. MausConfiguration.configuration = configuration MausConfiguration.transform = transform MausConfiguration.config_id = config_id if logger.isEnabledFor(logging.INFO): logger.info("Finished birthing transforms %s" % transform) except Exception as exc: # pylint:disable = W0703 status = {} status["error"] = str(exc.__class__) status["message"] = str(exc) if logger.isEnabledFor(logging.DEBUG): logger.debug("Status: %s " % status) return (os.getpid(), status, run_header)
def test_process_after_death(self): """ Invoke death when WorkerDeathFailedException is thrown. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("{}") MausTransform.death() with self.assertRaisesRegexp(WorkerDeadException, ".*MapPyTestMap process called after death.*"): MausTransform.process("{}")
def worker_process_init_callback(**kwargs): # pylint:disable = W0613 """ Callback from worker_process_init which is called when a Celery sub-process starts. It is used to create and births a transform in MausTransform, using MausConfiguration. Since sub-processes will receive a copy of MausConfiguration from the Celery master process, the sub-process will always inherit the latest version of MausConfiguration from the master process. @param kwargs Arguments - unused. """ logger = logging.getLogger(__name__) if logger.isEnabledFor(logging.INFO): logger.info("Setting MAUS ErrorHandler to raise exceptions") ErrorHandler.DefaultHandler().on_error = 'raise' if not maus_cpp.globals.has_instance() and \ MausConfiguration.configuration != '{}': maus_cpp.globals.birth(MausConfiguration.configuration) MausTransform.initialize(MausConfiguration.transform) MausTransform.birth(MausConfiguration.configuration)
def test_process_after_death(self): """ Invoke death when WorkerDeathFailedException is thrown. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("{}") MausTransform.death() with self.assertRaisesRegexp( WorkerDeadException, ".*MapPyTestMap process called after death.*"): MausTransform.process("{}")
def worker_process_init_callback(**kwargs): # pylint:disable = W0613 """ Callback from worker_process_init which is called when a Celery sub-process starts. It is used to create and births a transform in MausTransform, using MausConfiguration. Since sub-processes will receive a copy of MausConfiguration from the Celery master process, the sub-process will always inherit the latest version of MausConfiguration from the master process. @param kwargs Arguments - unused. """ logger = logging.getLogger(__name__) if logger.isEnabledFor(logging.INFO): logger.info("Setting MAUS ErrorHandler to raise exceptions") ErrorHandler.DefaultHandler().on_error = 'raise' if not maus_cpp.globals.has_instance() and \ MausConfiguration.configuration != '{}': maus_cpp.globals.birth(MausConfiguration.configuration) MausTransform.initialize(MausConfiguration.transform) MausTransform.birth(MausConfiguration.configuration)
def test_initialize_fails_birth(self): """ Test initialize when current transform death returns False. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("""{"death_result":%s}""" % \ MapPyTestMap.FAIL) with self.assertRaisesRegexp(WorkerDeathFailedException, ".*MapPyTestMap returned False.*"): MausTransform.initialize("MapPyTestMap") # Except success on second attempt. MausTransform.initialize("MapPyTestMap")
def test_initialize_fails_birth(self): """ Test initialize when current transform death returns False. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("""{"death_result":%s}""" % \ MapPyTestMap.FAIL) with self.assertRaisesRegexp(WorkerDeathFailedException, ".*MapPyTestMap returned False.*"): MausTransform.initialize("MapPyTestMap") # Except success on second attempt. MausTransform.initialize("MapPyTestMap")
def test_process_exception(self): """ Invoke process when a ValueError is thrown by process. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("""{"process_result":%s}""" % \ MapPyTestMap.EXCEPTION) with self.assertRaisesRegexp(ValueError, ".*Process exception.*"): MausTransform.process("{}")
def test_death(self): """ Invoke death. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("{}") MausTransform.death() self.assertTrue(MausTransform.is_dead, \ "Expected is_dead to be True")
def test_death(self): """ Invoke death. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("{}") MausTransform.death() self.assertTrue(MausTransform.is_dead, \ "Expected is_dead to be True")
def test_process_exception(self): """ Invoke process when a ValueError is thrown by process. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("""{"process_result":%s}""" % \ MapPyTestMap.EXCEPTION) with self.assertRaisesRegexp(ValueError, ".*Process exception.*"): MausTransform.process("{}")
def test_death_exception(self): """ Invoke death when a ValueError is thrown by death. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("""{"death_result":%s}""" % \ MapPyTestMap.EXCEPTION) with self.assertRaisesRegexp(WorkerDeathFailedException, ".*Death exception.*"): MausTransform.death() self.assertTrue(MausTransform.is_dead, "Expected is_dead to be True")
def test_death_exception(self): """ Invoke death when a ValueError is thrown by death. @param self Object reference. """ MausTransform.initialize("MapPyTestMap") MausTransform.birth("""{"death_result":%s}""" % \ MapPyTestMap.EXCEPTION) with self.assertRaisesRegexp(WorkerDeathFailedException, ".*Death exception.*"): MausTransform.death() self.assertTrue(MausTransform.is_dead, "Expected is_dead to be True")