Example #1
0
    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)
Example #2
0
    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())
Example #3
0
    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())
Example #4
0
 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)
Example #5
0
    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)
Example #6
0
    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)
Example #7
0
    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)
Example #8
0
    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)
Example #9
0
    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)
Example #10
0
    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)
Example #11
0
    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)
Example #12
0
 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)
Example #13
0
    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)