From a8a5277365035532228ffc2c1b84ee70f4ea7ffb Mon Sep 17 00:00:00 2001 From: Jaakko Lappalainen Date: Mon, 5 Apr 2021 10:26:31 +0000 Subject: [PATCH 1/5] use new param to specify first wait period --- docs/user-guide/repeated-tasks.md | 1 + fastapi_utils/tasks.py | 8 +++++++- tests/test_tasks.py | 13 +++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/user-guide/repeated-tasks.md b/docs/user-guide/repeated-tasks.md index 3d8bd733..968097af 100644 --- a/docs/user-guide/repeated-tasks.md +++ b/docs/user-guide/repeated-tasks.md @@ -51,6 +51,7 @@ Here is a more detailed description of the various keyword arguments for `repeat * `seconds: float` : The number of seconds to wait between successive calls * `wait_first: bool = False` : If `False` (the default), the wrapped function is called immediately when the decorated function is first called. If `True`, the decorated function will wait one period before making the first call to the wrapped function +* `wait_first_seconds: float = 0` : If `wait_first` is `True`, `wait_first_seconds` specifies the duration of the first wait period for the wrapped function to be called. If left as default, it will use `seconds` as the duration. * `logger: Optional[logging.Logger] = None` : If you pass a logger, any exceptions raised in the repeating execution loop will be logged (with a traceback) to the provided logger. * `raise_exceptions: bool = False` diff --git a/fastapi_utils/tasks.py b/fastapi_utils/tasks.py index 0cbe6dd3..8428aa30 100644 --- a/fastapi_utils/tasks.py +++ b/fastapi_utils/tasks.py @@ -16,6 +16,7 @@ def repeat_every( *, seconds: float, wait_first: bool = False, + wait_first_seconds: float = 0.0, logger: Optional[logging.Logger] = None, raise_exceptions: bool = False, max_repetitions: Optional[int] = None, @@ -32,6 +33,8 @@ def repeat_every( The number of seconds to wait between repeated calls wait_first: bool (default False) If True, the function will wait for a single period before the first call + wait_first_seconds: float (default 0.0) + If > 0 and wait_first = True, specifies a duration in seconds before the first call, other than `seconds`. logger: Optional[logging.Logger] (default None) The logger to use to log any exceptions raised by calls to the decorated function. If not provided, exceptions will not be logged by this function (though they may be handled by the event loop). @@ -57,7 +60,10 @@ async def wrapped() -> None: async def loop() -> None: nonlocal repetitions if wait_first: - await asyncio.sleep(seconds) + if wait_first_seconds: + await asyncio.sleep(wait_first_seconds) + else: + await asyncio.sleep(seconds) while max_repetitions is None or repetitions < max_repetitions: try: if is_coroutine: diff --git a/tests/test_tasks.py b/tests/test_tasks.py index a47f0dc4..75baf802 100644 --- a/tests/test_tasks.py +++ b/tests/test_tasks.py @@ -61,6 +61,19 @@ def repeatedly_print_hello() -> None: assert err == "" +@pytest.mark.asyncio +async def test_repeat_print_wait_first_seconds(capsys: CaptureFixture) -> None: + @repeat_every(seconds=0.07, max_repetitions=3, wait_first=0.1) + def repeatedly_print_hello() -> None: + print("hello") + + await repeatedly_print_hello() + await asyncio.sleep(0.18) + out, err = capsys.readouterr() + assert out == "hello\nhello\n" * 1 + assert err == "" + + @pytest.mark.asyncio async def test_repeat_unlogged_error(caplog: LogCaptureFixture) -> None: @repeat_every(seconds=0.07, max_repetitions=None) From efe385c31a6147ea99fda1d96276bb0254411edd Mon Sep 17 00:00:00 2001 From: Jaakko Lappalainen Date: Mon, 5 Apr 2021 11:32:35 +0100 Subject: [PATCH 2/5] fix test --- tests/test_tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tasks.py b/tests/test_tasks.py index 75baf802..4bb44206 100644 --- a/tests/test_tasks.py +++ b/tests/test_tasks.py @@ -63,7 +63,7 @@ def repeatedly_print_hello() -> None: @pytest.mark.asyncio async def test_repeat_print_wait_first_seconds(capsys: CaptureFixture) -> None: - @repeat_every(seconds=0.07, max_repetitions=3, wait_first=0.1) + @repeat_every(seconds=0.07, max_repetitions=3, wait_first=True, wait_first_seconds=0.1) def repeatedly_print_hello() -> None: print("hello") From 6840b33857f8674b1738cc45891b0a8784caf59c Mon Sep 17 00:00:00 2001 From: Jaakko Lappalainen Date: Mon, 5 Apr 2021 11:34:22 +0100 Subject: [PATCH 3/5] add useful comment in tests --- tests/test_tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tasks.py b/tests/test_tasks.py index 4bb44206..36fe8b5e 100644 --- a/tests/test_tasks.py +++ b/tests/test_tasks.py @@ -68,7 +68,7 @@ def repeatedly_print_hello() -> None: print("hello") await repeatedly_print_hello() - await asyncio.sleep(0.18) + await asyncio.sleep(0.18) # wait for 0.07 + 0.1 secs out, err = capsys.readouterr() assert out == "hello\nhello\n" * 1 assert err == "" From f2b52c75ba27103dbfed2de2c9282bbbdb0e559f Mon Sep 17 00:00:00 2001 From: Jaakko Lappalainen Date: Mon, 5 Apr 2021 11:36:38 +0100 Subject: [PATCH 4/5] improve assertion --- tests/test_tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tasks.py b/tests/test_tasks.py index 36fe8b5e..b6b105b4 100644 --- a/tests/test_tasks.py +++ b/tests/test_tasks.py @@ -70,7 +70,7 @@ def repeatedly_print_hello() -> None: await repeatedly_print_hello() await asyncio.sleep(0.18) # wait for 0.07 + 0.1 secs out, err = capsys.readouterr() - assert out == "hello\nhello\n" * 1 + assert out == "hello\n" * 2, "Printed 'hello' twice" assert err == "" From 33b3afa48dec5b3818d177438ab91a509cfdd89a Mon Sep 17 00:00:00 2001 From: Jaakko Lappalainen Date: Mon, 5 Apr 2021 11:39:05 +0100 Subject: [PATCH 5/5] formatting --- tests/test_tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tasks.py b/tests/test_tasks.py index b6b105b4..0ad2d4f4 100644 --- a/tests/test_tasks.py +++ b/tests/test_tasks.py @@ -68,7 +68,7 @@ def repeatedly_print_hello() -> None: print("hello") await repeatedly_print_hello() - await asyncio.sleep(0.18) # wait for 0.07 + 0.1 secs + await asyncio.sleep(0.18) #  wait for 0.07 + 0.1 secs out, err = capsys.readouterr() assert out == "hello\n" * 2, "Printed 'hello' twice" assert err == ""