Skip to content

Commit 466805c

Browse files
Set Actor restart delay fixed to 2 seconds
Signed-off-by: Christian Parpart <[email protected]>
1 parent 365fb0d commit 466805c

File tree

2 files changed

+14
-9
lines changed

2 files changed

+14
-9
lines changed

src/frequenz/sdk/actor/_actor.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import abc
77
import asyncio
88
import logging
9+
from datetime import timedelta
910

1011
from ._background_service import BackgroundService
1112

@@ -27,6 +28,9 @@ class Actor(BackgroundService, abc.ABC):
2728
comprehensive guide on how to use and implement actors properly.
2829
"""
2930

31+
RESTART_DELAY: timedelta = timedelta(seconds=2)
32+
"""The delay to wait between restarts of this actor."""
33+
3034
_restart_limit: int | None = None
3135
"""The number of times actors can be restarted when they are stopped by unhandled exceptions.
3236
@@ -64,7 +68,7 @@ async def _delay_if_restart(self, iteration: int) -> None:
6468
# the longer the actor has been running.
6569
# Not just for the restart-delay but actually for the n_restarts counter as well.
6670
if iteration > 0:
67-
delay: int = 1 << iteration # delay for 1, 2, 4, 8, ... seconds
71+
delay = Actor.RESTART_DELAY.total_seconds()
6872
_logger.info("Actor %s: Waiting %s seconds...", self, delay)
6973
await asyncio.sleep(delay)
7074

tests/actor/test_actor.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"""Simple test for the BaseActor."""
55

66
import asyncio
7+
from datetime import timedelta
78

89
import pytest
910
from frequenz.channels import Broadcast, Receiver, Sender
@@ -194,7 +195,7 @@ async def test_basic_actor(caplog: pytest.LogCaptureFixture) -> None:
194195
]
195196

196197

197-
def expected_wait_time(iterations: int) -> int:
198+
def expected_wait_time(iterations: int) -> timedelta:
198199
"""Calculate the expected wait time for a given iteration.
199200
200201
Args:
@@ -203,12 +204,10 @@ def expected_wait_time(iterations: int) -> int:
203204
Returns:
204205
The expected wait time in seconds.
205206
"""
206-
if iterations == 0:
207-
return 0
208-
return expected_wait_time(iterations - 1) + 1 << iterations
207+
return timedelta(seconds=iterations * Actor.RESTART_DELAY.total_seconds())
209208

210209

211-
@pytest.mark.parametrize("restart_limit", [0, 1, 2, 3])
210+
@pytest.mark.parametrize("restart_limit", [0, 1, 2, 10])
212211
async def test_restart_on_unhandled_exception(
213212
restart_limit: int, caplog: pytest.LogCaptureFixture
214213
) -> None:
@@ -225,8 +224,9 @@ async def test_restart_on_unhandled_exception(
225224

226225
channel: Broadcast[int] = Broadcast("channel")
227226

228-
async with asyncio.timeout(1 + expected_wait_time(restart_limit)):
229-
print(f"Expecting a wait time of {expected_wait_time(restart_limit)} seconds")
227+
# NB: We're adding 1.0s to the timeout to account for the time it takes to
228+
# run, crash, and restart the actor.
229+
async with asyncio.timeout(expected_wait_time(restart_limit).total_seconds() + 1.0):
230230
with actor_restart_limit(restart_limit):
231231
actor = RaiseExceptionActor(
232232
channel.new_receiver(),
@@ -244,6 +244,7 @@ async def test_restart_on_unhandled_exception(
244244
(*RUN_INFO, "Actor RaiseExceptionActor[test]: Starting..."),
245245
(*ACTOR_INFO, "Actor RaiseExceptionActor[test]: Started."),
246246
]
247+
restart_delay = Actor.RESTART_DELAY.total_seconds()
247248
for i in range(restart_limit):
248249
expected_log.extend(
249250
[
@@ -257,7 +258,7 @@ async def test_restart_on_unhandled_exception(
257258
),
258259
(
259260
*ACTOR_INFO,
260-
f"Actor RaiseExceptionActor[test]: Waiting {1 << (1 + i)} seconds...",
261+
f"Actor RaiseExceptionActor[test]: Waiting {restart_delay} seconds...",
261262
),
262263
]
263264
)

0 commit comments

Comments
 (0)