diff --git a/arq/utils.py b/arq/utils.py index 2cbde056..d1b92817 100644 --- a/arq/utils.py +++ b/arq/utils.py @@ -4,7 +4,7 @@ from datetime import datetime, timedelta, timezone from functools import lru_cache from time import time -from typing import TYPE_CHECKING, Any, AsyncGenerator, Dict, Optional, Sequence, overload +from typing import TYPE_CHECKING, Any, AsyncGenerator, Callable, Dict, Optional, Sequence, overload from .constants import timezone_env_vars @@ -19,6 +19,14 @@ from .typing import SecondsTimedelta +class LazyStr: + def __init__(self, fn: Callable[[], str]) -> None: + self.fn = fn + + def __str__(self) -> str: + return self.fn() + + def as_int(f: float) -> int: return int(round(f)) diff --git a/arq/worker.py b/arq/worker.py index 4c33b677..61d5cedc 100644 --- a/arq/worker.py +++ b/arq/worker.py @@ -29,6 +29,7 @@ retry_key_prefix, ) from .utils import ( + LazyStr, args_to_string, import_string, ms_to_datetime, @@ -580,7 +581,7 @@ async def job_failed(exc: BaseException) -> None: start_ms = timestamp_ms() success = False try: - s = args_to_string(args, kwargs) + s = LazyStr(partial(args_to_string, args, kwargs)) extra = f' try={job_try}' if job_try > 1 else '' if (start_ms - score) > 1200: extra += f' delayed={(start_ms - score) / 1000:0.2f}s' @@ -596,7 +597,7 @@ async def job_failed(exc: BaseException) -> None: exc_extra = exc_extra() raise else: - result_str = '' if result is None or not self.log_results else truncate(repr(result)) + result_str = LazyStr(lambda: '' if result is None or not self.log_results else truncate(repr(result))) finally: del self.job_tasks[job_id] diff --git a/tests/test_utils.py b/tests/test_utils.py index 9de66f88..a19eae4a 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -256,3 +256,17 @@ def test_settings_from_socket_dsn(): 'retry': None, 'max_connections': None, } + + +def test_lazy_str(): + called = False + + def get_str() -> str: + nonlocal called + called = True + return 'get_str' + + lazy_str = arq.utils.LazyStr(get_str) + assert not called + assert str(lazy_str) == 'get_str' + assert called