def __init__(self, target=None, listeners=None, name=None, service=None, cleanup_method=None, **kwargs): """ Constructs an ION process. You don't create one of these directly, the IonProcessThreadManager run by a container does this for you via the ProcManager interface. Call the container's spawn_process method and this method will run. @param target A callable to run in the PyonThread. If None (typical), will use the target method defined in this class. @param listeners A list of listening endpoints attached to this thread. @param name The name of this ION process. @param service An instance of the BaseService derived class which contains the business logic for an ION process. @param cleanup_method An optional callable to run when the process is stopping. Runs after all other notify_stop calls have run. Should take one param, this instance. """ self._startup_listeners = listeners or [] self.listeners = [] self.name = name self.service = service self._cleanup_method = cleanup_method self.thread_manager = ThreadManager(failure_notify_callback=self._child_failed) # bubbles up to main thread manager self._ctrl_queue = Queue() self._ready_control = Event() PyonThread.__init__(self, target=target, **kwargs)
def _notify_stop(self): """ Called when the process is about to be shut down. Instructs all listeners to close, puts a StopIteration into the synchronized queue, and waits for the listeners to close and for the control queue to exit. """ for listener in self.listeners: try: listener.close() except Exception as ex: tb = traceback.format_exc() log.warn("Could not close listener, attempting to ignore: %s\nTraceback:\n%s", ex, tb) self._ctrl_queue.put(StopIteration) # wait_children will join them and then get() them, which may raise an exception if any of them # died with an exception. self.thread_manager.wait_children(30) PyonThread._notify_stop(self) # run the cleanup method if we have one if self._cleanup_method is not None: try: self._cleanup_method(self) except Exception as ex: log.warn("Cleanup method error, attempting to ignore: %s\nTraceback: %s", ex, traceback.format_exc())
def _notify_stop(self): """ Called when the process is about to be shut down. Instructs all listeners to close, puts a StopIteration into the synchronized queue, and waits for the listeners to close and for the control queue to exit. """ for listener in self.listeners: try: listener.close() except Exception as ex: tb = traceback.format_exc() log.warn( "Could not close listener, attempting to ignore: %s\nTraceback:\n%s", ex, tb) self._ctrl_queue.put(StopIteration) # wait_children will join them and then get() them, which may raise an exception if any of them # died with an exception. self.thread_manager.wait_children(30) PyonThread._notify_stop(self) # run the cleanup method if we have one if self._cleanup_method is not None: try: self._cleanup_method(self) except Exception as ex: log.warn( "Cleanup method error, attempting to ignore: %s\nTraceback: %s", ex, traceback.format_exc())
def test_proc(self): self.counter = 0 proc = PyonThread(self.increment, 2) proc.start() self.assertEqual(self.counter, 0) time.sleep(0.2) proc.join() self.assertGreaterEqual(self.counter, 2)
def __init__(self, target=None, listeners=None, name=None, service=None, **kwargs): self._startup_listeners = listeners or [] self.listeners = [] self.name = name self.service = service self.thread_manager = ThreadManager(failure_notify_callback=self._child_failed) # bubbles up to main thread manager self._ctrl_queue = Queue() PyonThread.__init__(self, target=target, **kwargs)
def __init__(self, target=None, listeners=None, name=None, service=None, cleanup_method=None, heartbeat_secs=10, **kwargs): """ Constructs an ION process. You don't create one of these directly, the IonProcessThreadManager run by a container does this for you via the ProcManager interface. Call the container's spawn_process method and this method will run. @param target A callable to run in the PyonThread. If None (typical), will use the target method defined in this class. @param listeners A list of listening endpoints attached to this thread. @param name The name of this ION process. @param service An instance of the BaseService derived class which contains the business logic for an ION process. @param cleanup_method An optional callable to run when the process is stopping. Runs after all other notify_stop calls have run. Should take one param, this instance. @param heartbeat_secs Number of seconds to wait in between heartbeats. """ self._startup_listeners = listeners or [] self.listeners = [] self._listener_map = {} self.name = name self.service = service self._cleanup_method = cleanup_method self.thread_manager = ThreadManager( failure_notify_callback=self._child_failed ) # bubbles up to main thread manager self._dead_children = [] # save any dead children for forensics self._ctrl_thread = None self._ctrl_queue = Queue() self._ready_control = Event() self._errors = [] self._ctrl_current = None # set to the AR generated by _routing_call when in the context of a call # processing vs idle time (ms) self._start_time = None self._proc_time = 0 # for heartbeats, used to detect stuck processes self._heartbeat_secs = heartbeat_secs # amount of time to wait between heartbeats self._heartbeat_stack = None # stacktrace of last heartbeat self._heartbeat_time = None # timestamp of heart beat last matching the current op self._heartbeat_op = None # last operation (by AR) self._heartbeat_count = 0 # number of times this operation has been seen consecutively PyonThread.__init__(self, target=target, **kwargs)
def __init__(self, target=None, listeners=None, name=None, service=None, cleanup_method=None, heartbeat_secs=10, **kwargs): """ Constructs the control part of an ION process. Used by the container's IonProcessThreadManager, as part of spawn_process. @param target A callable to run in the PyonThread. If None (typical), will use the target method defined in this class. @param listeners A list of listening endpoints attached to this thread. @param name The name of this ION process. @param service An instance of the BaseService derived class which contains the business logic for the ION process. @param cleanup_method An optional callable to run when the process is stopping. Runs after all other notify_stop calls have run. Should take one param, this instance. @param heartbeat_secs Number of seconds to wait in between heartbeats. """ self._startup_listeners = listeners or [] self.listeners = [] self._listener_map = {} self.name = name self.service = service self._cleanup_method = cleanup_method self.thread_manager = ThreadManager(failure_notify_callback=self._child_failed) # bubbles up to main thread manager self._dead_children = [] # save any dead children for forensics self._ctrl_thread = None self._ctrl_queue = Queue() self._ready_control = Event() self._errors = [] self._ctrl_current = None # set to the AR generated by _routing_call when in the context of a call # processing vs idle time (ms) self._start_time = None self._proc_time = 0 # busy time since start self._proc_time_prior = 0 # busy time at the beginning of the prior interval self._proc_time_prior2 = 0 # busy time at the beginning of 2 interval's ago self._proc_interval_num = 0 # interval num of last record # for heartbeats, used to detect stuck processes self._heartbeat_secs = heartbeat_secs # amount of time to wait between heartbeats self._heartbeat_stack = None # stacktrace of last heartbeat self._heartbeat_time = None # timestamp of heart beat last matching the current op self._heartbeat_op = None # last operation (by AR) self._heartbeat_count = 0 # number of times this operation has been seen consecutively self._log_call_exception = CFG.get_safe("container.process.log_exceptions", False) self._log_call_dbstats = CFG.get_safe("container.process.log_dbstats", False) self._warn_call_dbstmt_threshold = CFG.get_safe("container.process.warn_dbstmt_threshold", 0) PyonThread.__init__(self, target=target, **kwargs)
def _notify_stop(self): """ Called when the process is about to be shut down. Instructs all listeners to close, puts a StopIteration into the synchronized queue, and waits for the listeners to close and for the control queue to exit. """ map(lambda x: x.close(), self.listeners) self._ctrl_queue.put(StopIteration) # wait_children will join them and then get() them, which may raise an exception if any of them # died with an exception. self.thread_manager.wait_children(30) PyonThread._notify_stop(self)
def __init__( self, target=None, listeners=None, name=None, service=None, cleanup_method=None, heartbeat_secs=10, **kwargs ): """ Constructs an ION process. You don't create one of these directly, the IonProcessThreadManager run by a container does this for you via the ProcManager interface. Call the container's spawn_process method and this method will run. @param target A callable to run in the PyonThread. If None (typical), will use the target method defined in this class. @param listeners A list of listening endpoints attached to this thread. @param name The name of this ION process. @param service An instance of the BaseService derived class which contains the business logic for an ION process. @param cleanup_method An optional callable to run when the process is stopping. Runs after all other notify_stop calls have run. Should take one param, this instance. @param heartbeat_secs Number of seconds to wait in between heartbeats. """ self._startup_listeners = listeners or [] self.listeners = [] self._listener_map = {} self.name = name self.service = service self._cleanup_method = cleanup_method self.thread_manager = ThreadManager( failure_notify_callback=self._child_failed ) # bubbles up to main thread manager self._dead_children = [] # save any dead children for forensics self._ctrl_thread = None self._ctrl_queue = Queue() self._ready_control = Event() self._errors = [] self._ctrl_current = None # set to the AR generated by _routing_call when in the context of a call # processing vs idle time (ms) self._start_time = None self._proc_time = 0 # for heartbeats, used to detect stuck processes self._heartbeat_secs = heartbeat_secs # amount of time to wait between heartbeats self._heartbeat_stack = None # stacktrace of last heartbeat self._heartbeat_time = None # timestamp of heart beat last matching the current op self._heartbeat_op = None # last operation (by AR) self._heartbeat_count = 0 # number of times this operation has been seen consecutively PyonThread.__init__(self, target=target, **kwargs)
def __init__(self, target=None, listeners=None, name=None, service=None, **kwargs): self._startup_listeners = listeners or [] self.listeners = [] self.name = name self.service = service self.thread_manager = ThreadManager( failure_notify_callback=self._child_failed ) # bubbles up to main thread manager self._ctrl_queue = Queue() PyonThread.__init__(self, target=target, **kwargs)
def __init__(self, target=None, listeners=None, name=None, service=None, cleanup_method=None, heartbeat_secs=10, **kwargs): """ Constructs the control part of an ION process. Used by the container's IonProcessThreadManager, as part of spawn_process. @param target A callable to run in the PyonThread. If None (typical), will use the target method defined in this class. @param listeners A list of listening endpoints attached to this thread. @param name The name of this ION process. @param service An instance of the BaseService derived class which contains the business logic for the ION process. @param cleanup_method An optional callable to run when the process is stopping. Runs after all other notify_stop calls have run. Should take one param, this instance. @param heartbeat_secs Number of seconds to wait in between heartbeats. """ self._startup_listeners = listeners or [] self.listeners = [] self._listener_map = {} self.name = name self.service = service self._cleanup_method = cleanup_method self.thread_manager = ThreadManager( failure_notify_callback=self._child_failed ) # bubbles up to main thread manager self._dead_children = [] # save any dead children for forensics self._ctrl_thread = None self._ctrl_queue = Queue() self._ready_control = Event() self._errors = [] self._ctrl_current = None # set to the AR generated by _routing_call when in the context of a call # processing vs idle time (ms) self._start_time = None self._proc_time = 0 # busy time since start self._proc_time_prior = 0 # busy time at the beginning of the prior interval self._proc_time_prior2 = 0 # busy time at the beginning of 2 interval's ago self._proc_interval_num = 0 # interval num of last record # for heartbeats, used to detect stuck processes self._heartbeat_secs = heartbeat_secs # amount of time to wait between heartbeats self._heartbeat_stack = None # stacktrace of last heartbeat self._heartbeat_time = None # timestamp of heart beat last matching the current op self._heartbeat_op = None # last operation (by AR) self._heartbeat_count = 0 # number of times this operation has been seen consecutively self._log_call_exception = CFG.get_safe( "container.process.log_exceptions", False) self._log_call_dbstats = CFG.get_safe("container.process.log_dbstats", False) self._warn_call_dbstmt_threshold = CFG.get_safe( "container.process.warn_dbstmt_threshold", 0) PyonThread.__init__(self, target=target, **kwargs)