@@ -89,7 +89,7 @@ async def run(
8989 """
9090 if self .is_running :
9191 raise RuntimeError ("Cannot start the service while it's already running" )
92- elif self .cancel_token . triggered :
92+ elif self .is_cancelled :
9393 raise RuntimeError ("Cannot restart a service that has already been cancelled" )
9494
9595 if finished_callback :
@@ -135,6 +135,7 @@ async def _run_task_wrapper() -> None:
135135 pass
136136 except Exception as e :
137137 self .logger .warning ("Task %s finished unexpectedly: %s" , awaitable , e )
138+ self .logger .warning ("Task failure traceback" , exc_info = True )
138139 else :
139140 self .logger .debug ("Task %s finished with no errors" , awaitable )
140141 self ._tasks .add (asyncio .ensure_future (_run_task_wrapper ()))
@@ -158,7 +159,7 @@ async def _run_daemon_wrapper() -> None:
158159 try :
159160 await service .run ()
160161 finally :
161- if not self .cancel_token . triggered :
162+ if not self .is_cancelled :
162163 self .logger .debug (
163164 "%s finished while we're still running, terminating as well" , service )
164165 self .cancel_token .trigger ()
@@ -188,7 +189,7 @@ async def cleanup(self) -> None:
188189
189190 async def cancel (self ) -> None :
190191 """Trigger the CancelToken and wait for the cleaned_up event to be set."""
191- if self .cancel_token . triggered :
192+ if self .is_cancelled :
192193 self .logger .warning ("Tried to cancel %s, but it was already cancelled" , self )
193194 return
194195 elif not self .is_running :
@@ -215,6 +216,14 @@ def _forcibly_cancel_all_tasks(self) -> None:
215216 for task in self ._tasks :
216217 task .cancel ()
217218
219+ @property
220+ def is_cancelled (self ) -> bool :
221+ return self .cancel_token .triggered
222+
223+ @property
224+ def is_operational (self ) -> bool :
225+ return self .events .started .is_set () and not self .cancel_token .triggered
226+
218227 @property
219228 def is_running (self ) -> bool :
220229 return self ._run_lock .locked ()
0 commit comments