8
8
Callable ,
9
9
List ,
10
10
Optional ,
11
- Set ,
12
11
cast ,
13
12
)
14
13
from weakref import WeakSet
15
14
16
- from eth .tools .logging import TraceLogger
17
-
18
15
from cancel_token import CancelToken , OperationCancelled
16
+ from eth_utils import (
17
+ ValidationError ,
18
+ )
19
+
20
+ from eth .tools .logging import TraceLogger
19
21
20
22
from p2p .cancellable import CancellableMixin
21
23
from p2p .utils import get_asyncio_executor
@@ -32,8 +34,8 @@ def __init__(self) -> None:
32
34
33
35
class BaseService (ABC , CancellableMixin ):
34
36
logger : TraceLogger = None
35
- _child_services : Set ['BaseService' ]
36
37
# Use a WeakSet so that we don't have to bother updating it when tasks finish.
38
+ _child_services : 'WeakSet[BaseService]'
37
39
_tasks : 'WeakSet[asyncio.Future[Any]]'
38
40
_finished_callbacks : List [Callable [['BaseService' ], None ]]
39
41
# Number of seconds cancel() will wait for run() to finish.
@@ -49,7 +51,7 @@ def __init__(self,
49
51
loop : asyncio .AbstractEventLoop = None ) -> None :
50
52
self .events = ServiceEvents ()
51
53
self ._run_lock = asyncio .Lock ()
52
- self ._child_services = set ()
54
+ self ._child_services = WeakSet ()
53
55
self ._tasks = WeakSet ()
54
56
self ._finished_callbacks = []
55
57
@@ -88,9 +90,9 @@ async def run(
88
90
finished_callback (if one was passed).
89
91
"""
90
92
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" )
92
94
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" )
94
96
95
97
if finished_callback :
96
98
self ._finished_callbacks .append (finished_callback )
@@ -144,6 +146,15 @@ def run_child_service(self, child_service: 'BaseService') -> None:
144
146
"""
145
147
Run a child service and keep a reference to it to be considered during the cleanup.
146
148
"""
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
+
147
158
self ._child_services .add (child_service )
148
159
self .run_task (child_service .run ())
149
160
@@ -153,6 +164,15 @@ def run_daemon(self, service: 'BaseService') -> None:
153
164
154
165
If the service finishes while we're still running, we'll terminate as well.
155
166
"""
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
+
156
176
self ._child_services .add (service )
157
177
158
178
async def _run_daemon_wrapper () -> None :
@@ -193,7 +213,7 @@ async def cancel(self) -> None:
193
213
self .logger .warning ("Tried to cancel %s, but it was already cancelled" , self )
194
214
return
195
215
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" )
197
217
198
218
self .logger .debug ("Cancelling %s" , self )
199
219
self .events .cancelled .set ()
0 commit comments