88 Callable ,
99 List ,
1010 Optional ,
11- Set ,
1211 cast ,
1312)
1413from weakref import WeakSet
1514
16- from eth .tools .logging import TraceLogger
17-
1815from cancel_token import CancelToken , OperationCancelled
16+ from eth_utils import (
17+ ValidationError ,
18+ )
19+
20+ from eth .tools .logging import TraceLogger
1921
2022from p2p .cancellable import CancellableMixin
2123from p2p .utils import get_asyncio_executor
@@ -32,8 +34,8 @@ def __init__(self) -> None:
3234
3335class BaseService (ABC , CancellableMixin ):
3436 logger : TraceLogger = None
35- _child_services : Set ['BaseService' ]
3637 # Use a WeakSet so that we don't have to bother updating it when tasks finish.
38+ _child_services : 'WeakSet[BaseService]'
3739 _tasks : 'WeakSet[asyncio.Future[Any]]'
3840 _finished_callbacks : List [Callable [['BaseService' ], None ]]
3941 # Number of seconds cancel() will wait for run() to finish.
@@ -49,7 +51,7 @@ def __init__(self,
4951 loop : asyncio .AbstractEventLoop = None ) -> None :
5052 self .events = ServiceEvents ()
5153 self ._run_lock = asyncio .Lock ()
52- self ._child_services = set ()
54+ self ._child_services = WeakSet ()
5355 self ._tasks = WeakSet ()
5456 self ._finished_callbacks = []
5557
@@ -88,9 +90,9 @@ async def run(
8890 finished_callback (if one was passed).
8991 """
9092 if self .is_running :
91- raise RuntimeError ("Cannot start the service while it's already running" )
93+ raise ValidationError ("Cannot start the service while it's already running" )
9294 elif self .is_cancelled :
93- raise RuntimeError ("Cannot restart a service that has already been cancelled" )
95+ raise ValidationError ("Cannot restart a service that has already been cancelled" )
9496
9597 if finished_callback :
9698 self ._finished_callbacks .append (finished_callback )
@@ -144,6 +146,15 @@ def run_child_service(self, child_service: 'BaseService') -> None:
144146 """
145147 Run a child service and keep a reference to it to be considered during the cleanup.
146148 """
149+ if child_service .is_running :
150+ raise ValidationError (
151+ f"Can't start service { child_service !r} , child of { self !r} : it's already running"
152+ )
153+ elif child_service .is_cancelled :
154+ raise ValidationError (
155+ f"Can't restart { child_service !r} , child of { self !r} : it's already completed"
156+ )
157+
147158 self ._child_services .add (child_service )
148159 self .run_task (child_service .run ())
149160
@@ -153,6 +164,15 @@ def run_daemon(self, service: 'BaseService') -> None:
153164
154165 If the service finishes while we're still running, we'll terminate as well.
155166 """
167+ if service .is_running :
168+ raise ValidationError (
169+ f"Can't start daemon { service !r} , child of { self !r} : it's already running"
170+ )
171+ elif service .is_cancelled :
172+ raise ValidationError (
173+ f"Can't restart daemon { service !r} , child of { self !r} : it's already completed"
174+ )
175+
156176 self ._child_services .add (service )
157177
158178 async def _run_daemon_wrapper () -> None :
@@ -193,7 +213,7 @@ async def cancel(self) -> None:
193213 self .logger .warning ("Tried to cancel %s, but it was already cancelled" , self )
194214 return
195215 elif not self .is_running :
196- raise RuntimeError ("Cannot cancel a service that has not been started" )
216+ raise ValidationError ("Cannot cancel a service that has not been started" )
197217
198218 self .logger .debug ("Cancelling %s" , self )
199219 self .events .cancelled .set ()
0 commit comments