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().
|
call to stop() will be issued prior to shutdown().
|
||||||
|
|
||||||
**States:**
|
**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`
|
**Started** - The Component has been started by the :class:`ComponentRegistry`
|
||||||
and will have it's update timer started.
|
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.
|
**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
|
**Paused** - The Component has had it's update timer stopped, but will
|
||||||
still be considered in a Started state.
|
still be considered in a Started state.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, interval=1, depend=None):
|
def __init__(self, name, interval=1, depend=None):
|
||||||
self._component_name = name
|
self._component_name = name
|
||||||
|
@ -86,6 +92,8 @@ class Component(object):
|
||||||
self._component_depend = depend
|
self._component_depend = depend
|
||||||
self._component_state = "Stopped"
|
self._component_state = "Stopped"
|
||||||
self._component_timer = None
|
self._component_timer = None
|
||||||
|
self._component_starting_deferred = None
|
||||||
|
self._component_stopping_deferred = None
|
||||||
_ComponentRegistry.register(self)
|
_ComponentRegistry.register(self)
|
||||||
|
|
||||||
def _component_start_timer(self):
|
def _component_start_timer(self):
|
||||||
|
@ -96,15 +104,20 @@ class Component(object):
|
||||||
def _component_start(self):
|
def _component_start(self):
|
||||||
def on_start(result):
|
def on_start(result):
|
||||||
self._component_state = "Started"
|
self._component_state = "Started"
|
||||||
|
self._component_starting_deferred = None
|
||||||
self._component_start_timer()
|
self._component_start_timer()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if self._component_state == "Stopped":
|
if self._component_state == "Stopped":
|
||||||
if hasattr(self, "start"):
|
if hasattr(self, "start"):
|
||||||
|
self._component_state = "Starting"
|
||||||
d = maybeDeferred(self.start)
|
d = maybeDeferred(self.start)
|
||||||
d.addCallback(on_start)
|
d.addCallback(on_start)
|
||||||
|
self._component_starting_deferred = d
|
||||||
else:
|
else:
|
||||||
d = maybeDeferred(on_start, None)
|
d = maybeDeferred(on_start, None)
|
||||||
|
elif self._component_state == "Starting":
|
||||||
|
return self._component_starting_deferred
|
||||||
elif self._component_state == "Started":
|
elif self._component_state == "Started":
|
||||||
d = succeed(True)
|
d = succeed(True)
|
||||||
else:
|
else:
|
||||||
|
@ -119,13 +132,18 @@ class Component(object):
|
||||||
self._component_timer.stop()
|
self._component_timer.stop()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if self._component_state != "Stopped":
|
if self._component_state != "Stopped" and self._component_state != "Stopping":
|
||||||
if hasattr(self, "stop"):
|
if hasattr(self, "stop"):
|
||||||
|
self._component_state = "Stopping"
|
||||||
d = maybeDeferred(self.stop)
|
d = maybeDeferred(self.stop)
|
||||||
d.addCallback(on_stop)
|
d.addCallback(on_stop)
|
||||||
|
self._component_stopping_deferred = d
|
||||||
else:
|
else:
|
||||||
d = maybeDeferred(on_stop, None)
|
d = maybeDeferred(on_stop, None)
|
||||||
|
|
||||||
|
if self._component_state == "Stopping":
|
||||||
|
return self._component_stopping_deferred
|
||||||
|
|
||||||
return succeed(None)
|
return succeed(None)
|
||||||
|
|
||||||
def _component_pause(self):
|
def _component_pause(self):
|
||||||
|
|
|
@ -6,10 +6,14 @@ class testcomponent(component.Component):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
component.Component.__init__(self, name)
|
component.Component.__init__(self, name)
|
||||||
self.start_count = 0
|
self.start_count = 0
|
||||||
|
self.stop_count = 0
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.start_count += 1
|
self.start_count += 1
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.stop_count += 1
|
||||||
|
|
||||||
class testcomponent_delaystart(testcomponent):
|
class testcomponent_delaystart(testcomponent):
|
||||||
def start(self):
|
def start(self):
|
||||||
def do_sleep():
|
def do_sleep():
|
||||||
|
@ -25,18 +29,26 @@ class testcomponent_update(component.Component):
|
||||||
component.Component.__init__(self, name)
|
component.Component.__init__(self, name)
|
||||||
self.counter = 0
|
self.counter = 0
|
||||||
self.start_count = 0
|
self.start_count = 0
|
||||||
|
self.stop_count = 0
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
self.counter += 1
|
self.counter += 1
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.stop_count += 1
|
||||||
|
|
||||||
class testcomponent_shutdown(component.Component):
|
class testcomponent_shutdown(component.Component):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
component.Component.__init__(self, name)
|
component.Component.__init__(self, name)
|
||||||
self.shutdowned = False
|
self.shutdowned = False
|
||||||
|
self.stop_count = 0
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
self.shutdowned = True
|
self.shutdowned = True
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.stop_count += 1
|
||||||
|
|
||||||
class ComponentTestClass(unittest.TestCase):
|
class ComponentTestClass(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
component._ComponentRegistry.components = {}
|
component._ComponentRegistry.components = {}
|
||||||
|
@ -106,6 +118,7 @@ class ComponentTestClass(unittest.TestCase):
|
||||||
def on_stop(result, c):
|
def on_stop(result, c):
|
||||||
self.assertEquals(c._component_state, "Stopped")
|
self.assertEquals(c._component_state, "Stopped")
|
||||||
self.assertFalse(c._component_timer.running)
|
self.assertFalse(c._component_timer.running)
|
||||||
|
self.assertEquals(c.stop_count, 1)
|
||||||
|
|
||||||
def on_start(result, c):
|
def on_start(result, c):
|
||||||
self.assertEquals(c._component_state, "Started")
|
self.assertEquals(c._component_state, "Started")
|
||||||
|
@ -120,6 +133,7 @@ class ComponentTestClass(unittest.TestCase):
|
||||||
def on_stop(*args):
|
def on_stop(*args):
|
||||||
for c in args[1:]:
|
for c in args[1:]:
|
||||||
self.assertEquals(c._component_state, "Stopped")
|
self.assertEquals(c._component_state, "Stopped")
|
||||||
|
self.assertEquals(c.stop_count, 1)
|
||||||
|
|
||||||
def on_start(*args):
|
def on_start(*args):
|
||||||
for c in args[1:]:
|
for c in args[1:]:
|
||||||
|
@ -169,6 +183,7 @@ class ComponentTestClass(unittest.TestCase):
|
||||||
def on_shutdown(result, c1):
|
def on_shutdown(result, c1):
|
||||||
self.assertTrue(c1.shutdowned)
|
self.assertTrue(c1.shutdowned)
|
||||||
self.assertEquals(c1._component_state, "Stopped")
|
self.assertEquals(c1._component_state, "Stopped")
|
||||||
|
self.assertEquals(c1.stop_count, 1)
|
||||||
|
|
||||||
def on_start(result, c1):
|
def on_start(result, c1):
|
||||||
d = component.shutdown()
|
d = component.shutdown()
|
||||||
|
|
Loading…
Reference in New Issue