Add 2 new states to Component: Starting and Stopping
Fix issue where a Component could have it's start and stop methods called more than once while waiting for their deferreds to fire
This commit is contained in:
parent
46a6576c68
commit
7be5b4c8bc
|
@ -68,17 +68,23 @@ class Component(object):
|
|||
call to stop() will be issued prior to shutdown().
|
||||
|
||||
**States:**
|
||||
|
||||
A Component can be in one of these 3 states.
|
||||
|
||||
|
||||
A Component can be in one of these 5 states.
|
||||
|
||||
**Started** - The Component has been started by the :class:`ComponentRegistry`
|
||||
and will have it's update timer started.
|
||||
|
||||
|
||||
**Starting** - The Component has had it's start method called, but it hasn't
|
||||
fully started yet.
|
||||
|
||||
**Stopped** - The Component has either been stopped or has yet to be started.
|
||||
|
||||
|
||||
**Stopping** - The Component has had it's stop method called, but it hasn't
|
||||
fully stopped yet.
|
||||
|
||||
**Paused** - The Component has had it's update timer stopped, but will
|
||||
still be considered in a Started state.
|
||||
|
||||
|
||||
"""
|
||||
def __init__(self, name, interval=1, depend=None):
|
||||
self._component_name = name
|
||||
|
@ -86,6 +92,8 @@ class Component(object):
|
|||
self._component_depend = depend
|
||||
self._component_state = "Stopped"
|
||||
self._component_timer = None
|
||||
self._component_starting_deferred = None
|
||||
self._component_stopping_deferred = None
|
||||
_ComponentRegistry.register(self)
|
||||
|
||||
def _component_start_timer(self):
|
||||
|
@ -96,15 +104,20 @@ class Component(object):
|
|||
def _component_start(self):
|
||||
def on_start(result):
|
||||
self._component_state = "Started"
|
||||
self._component_starting_deferred = None
|
||||
self._component_start_timer()
|
||||
return True
|
||||
|
||||
if self._component_state == "Stopped":
|
||||
if hasattr(self, "start"):
|
||||
self._component_state = "Starting"
|
||||
d = maybeDeferred(self.start)
|
||||
d.addCallback(on_start)
|
||||
self._component_starting_deferred = d
|
||||
else:
|
||||
d = maybeDeferred(on_start, None)
|
||||
elif self._component_state == "Starting":
|
||||
return self._component_starting_deferred
|
||||
elif self._component_state == "Started":
|
||||
d = succeed(True)
|
||||
else:
|
||||
|
@ -119,13 +132,18 @@ class Component(object):
|
|||
self._component_timer.stop()
|
||||
return True
|
||||
|
||||
if self._component_state != "Stopped":
|
||||
if self._component_state != "Stopped" and self._component_state != "Stopping":
|
||||
if hasattr(self, "stop"):
|
||||
self._component_state = "Stopping"
|
||||
d = maybeDeferred(self.stop)
|
||||
d.addCallback(on_stop)
|
||||
self._component_stopping_deferred = d
|
||||
else:
|
||||
d = maybeDeferred(on_stop, None)
|
||||
|
||||
if self._component_state == "Stopping":
|
||||
return self._component_stopping_deferred
|
||||
|
||||
return succeed(None)
|
||||
|
||||
def _component_pause(self):
|
||||
|
|
|
@ -6,10 +6,14 @@ class testcomponent(component.Component):
|
|||
def __init__(self, name):
|
||||
component.Component.__init__(self, name)
|
||||
self.start_count = 0
|
||||
self.stop_count = 0
|
||||
|
||||
def start(self):
|
||||
self.start_count += 1
|
||||
|
||||
def stop(self):
|
||||
self.stop_count += 1
|
||||
|
||||
class testcomponent_delaystart(testcomponent):
|
||||
def start(self):
|
||||
def do_sleep():
|
||||
|
@ -25,18 +29,26 @@ class testcomponent_update(component.Component):
|
|||
component.Component.__init__(self, name)
|
||||
self.counter = 0
|
||||
self.start_count = 0
|
||||
self.stop_count = 0
|
||||
|
||||
def update(self):
|
||||
self.counter += 1
|
||||
|
||||
def stop(self):
|
||||
self.stop_count += 1
|
||||
|
||||
class testcomponent_shutdown(component.Component):
|
||||
def __init__(self, name):
|
||||
component.Component.__init__(self, name)
|
||||
self.shutdowned = False
|
||||
self.stop_count = 0
|
||||
|
||||
def shutdown(self):
|
||||
self.shutdowned = True
|
||||
|
||||
def stop(self):
|
||||
self.stop_count += 1
|
||||
|
||||
class ComponentTestClass(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
component._ComponentRegistry.components = {}
|
||||
|
@ -106,6 +118,7 @@ class ComponentTestClass(unittest.TestCase):
|
|||
def on_stop(result, c):
|
||||
self.assertEquals(c._component_state, "Stopped")
|
||||
self.assertFalse(c._component_timer.running)
|
||||
self.assertEquals(c.stop_count, 1)
|
||||
|
||||
def on_start(result, c):
|
||||
self.assertEquals(c._component_state, "Started")
|
||||
|
@ -120,6 +133,7 @@ class ComponentTestClass(unittest.TestCase):
|
|||
def on_stop(*args):
|
||||
for c in args[1:]:
|
||||
self.assertEquals(c._component_state, "Stopped")
|
||||
self.assertEquals(c.stop_count, 1)
|
||||
|
||||
def on_start(*args):
|
||||
for c in args[1:]:
|
||||
|
@ -169,6 +183,7 @@ class ComponentTestClass(unittest.TestCase):
|
|||
def on_shutdown(result, c1):
|
||||
self.assertTrue(c1.shutdowned)
|
||||
self.assertEquals(c1._component_state, "Stopped")
|
||||
self.assertEquals(c1.stop_count, 1)
|
||||
|
||||
def on_start(result, c1):
|
||||
d = component.shutdown()
|
||||
|
|
Loading…
Reference in New Issue