Skip to content

Commit cf03b93

Browse files
committed
reraise errors in prc
1 parent 16b00d7 commit cf03b93

File tree

2 files changed

+34
-12
lines changed

2 files changed

+34
-12
lines changed

packages/service-library/src/servicelib/rabbitmq/_rpc_router.py

+33-10
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,62 @@
66
from typing import Any, TypeVar
77

88
from models_library.rabbitmq_basic_types import RPCMethodName
9-
from pydantic import SecretStr
109

1110
from ..logging_utils import log_context
1211
from ._errors import RPCServerError
1312

1413
DecoratedCallable = TypeVar("DecoratedCallable", bound=Callable[..., Any])
1514

15+
# NOTE: this is equivalent to http access logs
1616
_logger = logging.getLogger("rpc.access")
1717

18-
_RPC_CUSTOM_ENCODER: dict[Any, Callable[[Any], Any]] = {
19-
SecretStr: SecretStr.get_secret_value
20-
}
18+
19+
def _create_func_msg(func, args: list[Any], kwargs: dict[str, Any]) -> str:
20+
msg = f"{func.__name__}("
21+
22+
if args_msg := ", ".join(map(str, args)):
23+
msg += args_msg
24+
25+
if kwargs_msg := ", ".join({f"{name}={value}" for name, value in kwargs.items()}):
26+
if args:
27+
msg += ", "
28+
msg += kwargs_msg
29+
30+
return f"{msg})"
2131

2232

2333
@dataclass
2434
class RPCRouter:
2535
routes: dict[RPCMethodName, Callable] = field(default_factory=dict)
2636

27-
def expose(self) -> Callable[[DecoratedCallable], DecoratedCallable]:
28-
def decorator(func: DecoratedCallable) -> DecoratedCallable:
37+
def expose(
38+
self,
39+
*,
40+
reraise_if_error_type: tuple[type[Exception], ...] | None = None,
41+
) -> Callable[[DecoratedCallable], DecoratedCallable]:
42+
def _decorator(func: DecoratedCallable) -> DecoratedCallable:
2943
@functools.wraps(func)
30-
async def wrapper(*args, **kwargs):
44+
async def _wrapper(*args, **kwargs):
45+
3146
with log_context(
47+
# NOTE: this is intentionally analogous to the http access log traces.
48+
# To change log-level use getLogger("rpc.access").set_level(...)
3249
_logger,
3350
logging.INFO,
34-
msg=f"calling {func.__name__} with {args}, {kwargs}",
51+
msg=f"RPC call {_create_func_msg(func, args, kwargs)}",
52+
log_duration=True,
3553
):
3654
try:
3755
return await func(*args, **kwargs)
56+
3857
except asyncio.CancelledError:
3958
_logger.debug("call was cancelled")
4059
raise
60+
4161
except Exception as exc: # pylint: disable=broad-except
62+
if reraise_if_error_type and type(exc) in reraise_if_error_type:
63+
raise
64+
4265
_logger.exception("Unhandled exception:")
4366
# NOTE: we do not return internal exceptions over RPC
4467
raise RPCServerError(
@@ -47,7 +70,7 @@ async def wrapper(*args, **kwargs):
4770
msg=f"{exc}",
4871
) from None
4972

50-
self.routes[RPCMethodName(func.__name__)] = wrapper
73+
self.routes[RPCMethodName(func.__name__)] = _wrapper
5174
return func
5275

53-
return decorator
76+
return _decorator

services/payments/tests/unit/test_services_auto_recharge_listener.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
# pylint: disable=unused-argument
55
# pylint: disable=unused-variable
66

7-
from collections.abc import Callable
7+
from collections.abc import Awaitable, Callable, Iterator
88
from datetime import datetime, timedelta, timezone
99
from decimal import Decimal
10-
from typing import Awaitable, Iterator
1110
from unittest import mock
1211

1312
import pytest

0 commit comments

Comments
 (0)