|  | @@ -1,120 +0,0 @@
 | 
	
		
			
				|  |  | -import time
 | 
	
		
			
				|  |  | -import multiprocessing
 | 
	
		
			
				|  |  | -from multiprocessing import TimeoutError
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -JOIN_TIMEOUT = 2
 | 
	
		
			
				|  |  | -CHECK_INTERVAL = 2
 | 
	
		
			
				|  |  | -MAX_RESTART_FREQ = 3
 | 
	
		
			
				|  |  | -MAX_RESTART_FREQ_TIME = 10
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -class MaxRestartsExceededError(Exception):
 | 
	
		
			
				|  |  | -    """Restarts exceeded the maximum restart frequency."""
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -class OFASupervisor(object):
 | 
	
		
			
				|  |  | -    """Process supervisor using the `one_for_all`_ strategy.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    .. _`one_for_all`:
 | 
	
		
			
				|  |  | -        http://erlang.org/doc/design_principles/sup_princ.html#5.3.2
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    However, instead of registering a list of processes, you have one
 | 
	
		
			
				|  |  | -    process which runs a pool. Makes for an easy implementation.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    :param target: see :attr:`target`.
 | 
	
		
			
				|  |  | -    :param args: see :attr:`args`.
 | 
	
		
			
				|  |  | -    :param kwargs: see :attr:`kwargs`.
 | 
	
		
			
				|  |  | -    :param max_restart_freq: see :attr:`max_restart_freq`.
 | 
	
		
			
				|  |  | -    :param max_restart_freq_time: see :attr:`max_restart_freq_time`.
 | 
	
		
			
				|  |  | -    :param check_interval: see :attr:`max_restart_freq_time`.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    .. attribute:: target
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        The target callable to be launched in a new process.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    .. attribute:: args
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        The positional arguments to apply to :attr:`target`.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    .. attribute:: kwargs
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        The keyword arguments to apply to :attr:`target`.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    .. attribute:: max_restart_freq
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        Limit the number of restarts which can occur in a given time interval.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        The max restart frequency is the number of restarts that can occur
 | 
	
		
			
				|  |  | -        within the interval :attr:`max_restart_freq_time`.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        The restart mechanism prevents situations where the process repeatedly
 | 
	
		
			
				|  |  | -        dies for the same reason. If this happens both the process and the
 | 
	
		
			
				|  |  | -        supervisor is terminated.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    .. attribute:: max_restart_freq_time
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        See :attr:`max_restart_freq`.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    .. attribute:: check_interval
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        The time in seconds, between process pings.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    """
 | 
	
		
			
				|  |  | -    Process = multiprocessing.Process
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def __init__(self, target, args=None, kwargs=None,
 | 
	
		
			
				|  |  | -            max_restart_freq=MAX_RESTART_FREQ,
 | 
	
		
			
				|  |  | -            join_timeout=JOIN_TIMEOUT,
 | 
	
		
			
				|  |  | -            max_restart_freq_time=MAX_RESTART_FREQ_TIME,
 | 
	
		
			
				|  |  | -            check_interval=CHECK_INTERVAL):
 | 
	
		
			
				|  |  | -        self.target = target
 | 
	
		
			
				|  |  | -        self.join_timeout = join_timeout
 | 
	
		
			
				|  |  | -        self.args = args or []
 | 
	
		
			
				|  |  | -        self.kwargs = kwargs or {}
 | 
	
		
			
				|  |  | -        self.check_interval = check_interval
 | 
	
		
			
				|  |  | -        self.max_restart_freq = max_restart_freq
 | 
	
		
			
				|  |  | -        self.max_restart_freq_time = max_restart_freq_time
 | 
	
		
			
				|  |  | -        self.restarts_in_frame = 0
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def start(self):
 | 
	
		
			
				|  |  | -        """Launches the :attr:`target` in a seperate process and starts
 | 
	
		
			
				|  |  | -        supervising it."""
 | 
	
		
			
				|  |  | -        target = self.target
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        def _start_supervised_process():
 | 
	
		
			
				|  |  | -            """Start the :attr:`target` in a new process."""
 | 
	
		
			
				|  |  | -            process = self.Process(target=target,
 | 
	
		
			
				|  |  | -                                   args=self.args, kwargs=self.kwargs)
 | 
	
		
			
				|  |  | -            process.start()
 | 
	
		
			
				|  |  | -            return process
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        def _restart(process):
 | 
	
		
			
				|  |  | -            """Terminate the process and restart."""
 | 
	
		
			
				|  |  | -            process.join(timeout=self.join_timeout)
 | 
	
		
			
				|  |  | -            process.terminate()
 | 
	
		
			
				|  |  | -            self.restarts_in_frame += 1
 | 
	
		
			
				|  |  | -            process = _start_supervised_process()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        process = _start_supervised_process()
 | 
	
		
			
				|  |  | -        try:
 | 
	
		
			
				|  |  | -            restart_frame = 0
 | 
	
		
			
				|  |  | -            while True:
 | 
	
		
			
				|  |  | -                if restart_frame > self.max_restart_freq_time:
 | 
	
		
			
				|  |  | -                    if self.restarts_in_frame >= self.max_restart_freq:
 | 
	
		
			
				|  |  | -                        raise MaxRestartsExceededError(
 | 
	
		
			
				|  |  | -                                "Supervised: Max restart frequency reached")
 | 
	
		
			
				|  |  | -                restart_frame = 0
 | 
	
		
			
				|  |  | -                self.restarts_in_frame = 0
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                try:
 | 
	
		
			
				|  |  | -                    proc_is_alive = process.is_alive()
 | 
	
		
			
				|  |  | -                except TimeoutError:
 | 
	
		
			
				|  |  | -                    proc_is_alive = False
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                if not proc_is_alive:
 | 
	
		
			
				|  |  | -                    _restart(process)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                time.sleep(self.check_interval)
 | 
	
		
			
				|  |  | -                restart_frame += self.check_interval
 | 
	
		
			
				|  |  | -        finally:
 | 
	
		
			
				|  |  | -            process.join()
 |