mirror of
https://github.com/tiqi-group/pydase.git
synced 2025-04-21 00:40:01 +02:00
task: adds exit_on_failure option
This commit is contained in:
parent
8a8ac9d297
commit
1b35dba64f
@ -36,6 +36,7 @@ class PerInstanceTaskDescriptor(Generic[R]):
|
|||||||
start_limit_interval_sec: float | None = None,
|
start_limit_interval_sec: float | None = None,
|
||||||
start_limit_burst: int = 3,
|
start_limit_burst: int = 3,
|
||||||
timeout_start_sec: float = 0.0,
|
timeout_start_sec: float = 0.0,
|
||||||
|
exit_on_failure: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.__func = func
|
self.__func = func
|
||||||
self.__autostart = autostart
|
self.__autostart = autostart
|
||||||
@ -45,6 +46,7 @@ class PerInstanceTaskDescriptor(Generic[R]):
|
|||||||
self.__start_limit_interval_sec = start_limit_interval_sec
|
self.__start_limit_interval_sec = start_limit_interval_sec
|
||||||
self.__start_limit_burst = start_limit_burst
|
self.__start_limit_burst = start_limit_burst
|
||||||
self.__timeout_start_sec = timeout_start_sec
|
self.__timeout_start_sec = timeout_start_sec
|
||||||
|
self.__exit_on_failure = exit_on_failure
|
||||||
|
|
||||||
def __set_name__(self, owner: type[DataService], name: str) -> None:
|
def __set_name__(self, owner: type[DataService], name: str) -> None:
|
||||||
"""Stores the name of the task within the owning class. This method is called
|
"""Stores the name of the task within the owning class. This method is called
|
||||||
@ -85,6 +87,7 @@ class PerInstanceTaskDescriptor(Generic[R]):
|
|||||||
start_limit_interval_sec=self.__start_limit_interval_sec,
|
start_limit_interval_sec=self.__start_limit_interval_sec,
|
||||||
start_limit_burst=self.__start_limit_burst,
|
start_limit_burst=self.__start_limit_burst,
|
||||||
timeout_start_sec=self.__timeout_start_sec,
|
timeout_start_sec=self.__timeout_start_sec,
|
||||||
|
exit_on_failure=self.__exit_on_failure,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -99,6 +102,7 @@ def task( # noqa: PLR0913
|
|||||||
start_limit_interval_sec: float | None = None,
|
start_limit_interval_sec: float | None = None,
|
||||||
start_limit_burst: int = 3,
|
start_limit_burst: int = 3,
|
||||||
timeout_start_sec: float = 0.0,
|
timeout_start_sec: float = 0.0,
|
||||||
|
exit_on_failure: bool = False,
|
||||||
) -> Callable[
|
) -> Callable[
|
||||||
[
|
[
|
||||||
Callable[[Any], Coroutine[None, None, R]]
|
Callable[[Any], Coroutine[None, None, R]]
|
||||||
@ -143,6 +147,9 @@ def task( # noqa: PLR0913
|
|||||||
not permitted to start any more. Defaults to 3.
|
not permitted to start any more. Defaults to 3.
|
||||||
timeout_start_sec:
|
timeout_start_sec:
|
||||||
Configures the time to wait for start-up. Defaults to 0.0.
|
Configures the time to wait for start-up. Defaults to 0.0.
|
||||||
|
exit_on_failure:
|
||||||
|
If True, exit the service if the task fails and restart_on_failure is False
|
||||||
|
or burst limits are exceeded.
|
||||||
Returns:
|
Returns:
|
||||||
A decorator that wraps an asynchronous function in a
|
A decorator that wraps an asynchronous function in a
|
||||||
[`PerInstanceTaskDescriptor`][pydase.task.decorator.PerInstanceTaskDescriptor]
|
[`PerInstanceTaskDescriptor`][pydase.task.decorator.PerInstanceTaskDescriptor]
|
||||||
@ -188,6 +195,7 @@ def task( # noqa: PLR0913
|
|||||||
start_limit_interval_sec=start_limit_interval_sec,
|
start_limit_interval_sec=start_limit_interval_sec,
|
||||||
start_limit_burst=start_limit_burst,
|
start_limit_burst=start_limit_burst,
|
||||||
timeout_start_sec=timeout_start_sec,
|
timeout_start_sec=timeout_start_sec,
|
||||||
|
exit_on_failure=exit_on_failure,
|
||||||
)
|
)
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
import signal
|
||||||
from collections.abc import Callable, Coroutine
|
from collections.abc import Callable, Coroutine
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from time import time
|
from time import time
|
||||||
@ -55,6 +57,9 @@ class Task(pydase.data_service.data_service.DataService, Generic[R]):
|
|||||||
not permitted to start any more. Defaults to 3.
|
not permitted to start any more. Defaults to 3.
|
||||||
timeout_start_sec:
|
timeout_start_sec:
|
||||||
Configures the time to wait for start-up. Defaults to 0.0.
|
Configures the time to wait for start-up. Defaults to 0.0.
|
||||||
|
exit_on_failure:
|
||||||
|
If True, exit the service if the task fails and restart_on_failure is False
|
||||||
|
or burst limits are exceeded.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```python
|
```python
|
||||||
@ -93,6 +98,7 @@ class Task(pydase.data_service.data_service.DataService, Generic[R]):
|
|||||||
start_limit_interval_sec: float | None = None,
|
start_limit_interval_sec: float | None = None,
|
||||||
start_limit_burst: int = 3,
|
start_limit_burst: int = 3,
|
||||||
timeout_start_sec: float = 0.0,
|
timeout_start_sec: float = 0.0,
|
||||||
|
exit_on_failure: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._autostart = autostart
|
self._autostart = autostart
|
||||||
@ -101,6 +107,7 @@ class Task(pydase.data_service.data_service.DataService, Generic[R]):
|
|||||||
self._start_limit_interval_sec = start_limit_interval_sec
|
self._start_limit_interval_sec = start_limit_interval_sec
|
||||||
self._start_limit_burst = start_limit_burst
|
self._start_limit_burst = start_limit_burst
|
||||||
self._timeout_start_sec = timeout_start_sec
|
self._timeout_start_sec = timeout_start_sec
|
||||||
|
self._exit_on_failure = exit_on_failure
|
||||||
self._func_name = func.__name__
|
self._func_name = func.__name__
|
||||||
self._func = func
|
self._func = func
|
||||||
self._task: asyncio.Task[R | None] | None = None
|
self._task: asyncio.Task[R | None] | None = None
|
||||||
@ -139,18 +146,19 @@ class Task(pydase.data_service.data_service.DataService, Generic[R]):
|
|||||||
self._task = None
|
self._task = None
|
||||||
self._status = TaskStatus.NOT_RUNNING
|
self._status = TaskStatus.NOT_RUNNING
|
||||||
|
|
||||||
|
exception = None
|
||||||
try:
|
try:
|
||||||
task.exception()
|
exception = task.exception()
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
pass
|
return
|
||||||
except Exception as e:
|
|
||||||
logger.exception(
|
if exception is not None:
|
||||||
"Task '%s' encountered an exception: %s: %s",
|
logger.error(
|
||||||
|
"Task '%s' encountered an exception: %r",
|
||||||
self._func_name,
|
self._func_name,
|
||||||
type(e).__name__,
|
exception,
|
||||||
e,
|
|
||||||
)
|
)
|
||||||
raise e
|
os.kill(os.getpid(), signal.SIGTERM)
|
||||||
else:
|
else:
|
||||||
self._result = task.result()
|
self._result = task.result()
|
||||||
|
|
||||||
@ -186,6 +194,8 @@ class Task(pydase.data_service.data_service.DataService, Generic[R]):
|
|||||||
datetime.fromtimestamp(start_time),
|
datetime.fromtimestamp(start_time),
|
||||||
)
|
)
|
||||||
if not self._restart_on_failure:
|
if not self._restart_on_failure:
|
||||||
|
if self._exit_on_failure:
|
||||||
|
raise e
|
||||||
break
|
break
|
||||||
if self._start_limit_interval_sec is not None:
|
if self._start_limit_interval_sec is not None:
|
||||||
if (time() - start_time) > self._start_limit_interval_sec:
|
if (time() - start_time) > self._start_limit_interval_sec:
|
||||||
@ -197,6 +207,8 @@ class Task(pydase.data_service.data_service.DataService, Generic[R]):
|
|||||||
"Task %r exceeded restart burst limit. Stopping.",
|
"Task %r exceeded restart burst limit. Stopping.",
|
||||||
self._func.__name__,
|
self._func.__name__,
|
||||||
)
|
)
|
||||||
|
if self._exit_on_failure:
|
||||||
|
raise e
|
||||||
break
|
break
|
||||||
await asyncio.sleep(self._restart_sec)
|
await asyncio.sleep(self._restart_sec)
|
||||||
return None
|
return None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user