Skip to content

Commit 4cc72a4

Browse files
committed
test decorator
1 parent 9d8c132 commit 4cc72a4

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

packages/service-library/src/servicelib/background_task.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,9 @@
44
import functools
55
import logging
66
from collections.abc import AsyncIterator, Awaitable, Callable
7-
from typing import Final, ParamSpec, TypeVar
8-
9-
from tenacity import (
10-
TryAgain,
11-
before_sleep_log,
12-
retry,
13-
retry_always,
14-
retry_if_exception_type,
15-
)
7+
from typing import Any, Coroutine, Final, ParamSpec, TypeVar
8+
9+
from tenacity import TryAgain, before_sleep_log, retry, retry_if_exception_type
1610
from tenacity.asyncio import AsyncRetrying
1711
from tenacity.wait import wait_fixed
1812

@@ -46,8 +40,12 @@ def periodic(
4640
interval: datetime.timedelta,
4741
raise_on_error: bool = False,
4842
early_wake_up_event: asyncio.Event | None = None,
49-
) -> Callable[[Callable[P, Awaitable[None]]], Callable[P, Awaitable[None]]]:
50-
def _decorator(func: Callable[P, Awaitable[None]]) -> Callable[P, Awaitable[None]]:
43+
) -> Callable[
44+
[Callable[P, Coroutine[Any, Any, None]]], Callable[P, Coroutine[Any, Any, None]]
45+
]:
46+
def _decorator(
47+
func: Callable[P, Coroutine[Any, Any, None]],
48+
) -> Callable[P, Coroutine[Any, Any, None]]:
5149
nap = (
5250
asyncio.sleep
5351
if early_wake_up_event is None
@@ -99,7 +97,9 @@ async def _periodic_scheduled_task(
9997
sleep=nap,
10098
wait=wait_fixed(interval.total_seconds()),
10199
reraise=True,
102-
retry=retry_if_exception_type(TryAgain) if raise_on_error else retry_always,
100+
retry=retry_if_exception_type(TryAgain)
101+
if raise_on_error
102+
else retry_if_exception_type(),
103103
):
104104
with attempt:
105105
with (

packages/service-library/tests/test_background_task.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@
99
from collections.abc import AsyncIterator, Awaitable, Callable
1010
from typing import Final
1111
from unittest import mock
12+
from unittest.mock import AsyncMock
1213

1314
import pytest
1415
from faker import Faker
1516
from pytest_mock.plugin import MockerFixture
16-
from servicelib.background_task import (
17+
from servicelib.background_task import ( # Assuming the module is imported correctly
18+
periodic,
1719
periodic_task,
1820
start_periodic_task,
1921
stop_periodic_task,
@@ -177,3 +179,24 @@ async def test_periodic_task_context_manager(
177179
assert asyncio_task.cancelled() is False
178180
assert asyncio_task.done() is False
179181
assert asyncio_task.cancelled() is True
182+
183+
184+
async def test_periodic_decorator():
185+
# This mock function will allow us to test if the function is called periodically
186+
mock_func = AsyncMock()
187+
188+
@periodic(interval=datetime.timedelta(seconds=0.1))
189+
async def _func() -> None:
190+
await mock_func()
191+
192+
task = asyncio.create_task(_func())
193+
194+
# Give some time for the periodic calls to happen
195+
await asyncio.sleep(0.5)
196+
197+
# Once enough time has passed, cancel the task
198+
task.cancel()
199+
with pytest.raises(asyncio.CancelledError):
200+
await task
201+
202+
assert mock_func.call_count > 1

0 commit comments

Comments
 (0)