mirror of
https://github.com/A-Minos/nonebot-plugin-tetris-stats.git
synced 2026-03-05 05:36:54 +08:00
✨ 完善 retry 装饰器
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
from asyncio import sleep
|
from asyncio import sleep
|
||||||
from collections.abc import Awaitable, Callable
|
from collections.abc import Callable, Coroutine
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from typing import ParamSpec, TypeVar, cast
|
from typing import Any, ParamSpec, TypeVar
|
||||||
|
|
||||||
from nonebot.log import logger
|
from nonebot.log import logger
|
||||||
from nonebot_plugin_alconna.uniseg import SerializeFailed, UniMessage
|
from nonebot_plugin_alconna.uniseg import SerializeFailed, UniMessage
|
||||||
@@ -17,24 +17,28 @@ def retry(
|
|||||||
exception_type: type[BaseException] | tuple[type[BaseException], ...] = Exception,
|
exception_type: type[BaseException] | tuple[type[BaseException], ...] = Exception,
|
||||||
delay: timedelta | None = None,
|
delay: timedelta | None = None,
|
||||||
reply: str | UniMessage | None = None,
|
reply: str | UniMessage | None = None,
|
||||||
) -> Callable[[Callable[P, Awaitable[T]]], Callable[P, Awaitable[T]]]:
|
) -> Callable[[Callable[P, Coroutine[Any, Any, T]]], Callable[P, Coroutine[Any, Any, T]]]:
|
||||||
def decorator(func: Callable[P, Awaitable[T]]) -> Callable[P, Awaitable[T]]:
|
def decorator(func: Callable[P, Coroutine[Any, Any, T]]) -> Callable[P, Coroutine[Any, Any, T]]:
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
||||||
for i in range(1, max_attempts + 1):
|
for i in range(max_attempts + 1):
|
||||||
try:
|
if i > 0:
|
||||||
return await func(*args, **kwargs)
|
|
||||||
except exception_type as e: # noqa: PERF203
|
|
||||||
logger.exception(e)
|
|
||||||
if delay is not None:
|
|
||||||
await sleep(delay.total_seconds())
|
|
||||||
message = f'Retrying: {func.__name__} ({i}/{max_attempts})'
|
message = f'Retrying: {func.__name__} ({i}/{max_attempts})'
|
||||||
logger.debug(message)
|
logger.debug(message)
|
||||||
with suppress(SerializeFailed):
|
with suppress(SerializeFailed):
|
||||||
await UniMessage(reply or message).send()
|
await UniMessage(reply or message).send()
|
||||||
msg = 'Unexpectedly reached the end of the retry loop'
|
if i == max_attempts:
|
||||||
raise RuntimeError(msg)
|
break
|
||||||
|
try:
|
||||||
|
return await func(*args, **kwargs)
|
||||||
|
except exception_type as e:
|
||||||
|
if i == max_attempts:
|
||||||
|
raise
|
||||||
|
logger.exception(e)
|
||||||
|
if delay is not None:
|
||||||
|
await sleep(delay.total_seconds())
|
||||||
|
return await func(*args, **kwargs)
|
||||||
|
|
||||||
return cast(Callable[P, Awaitable[T]], wrapper)
|
return wrapper
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|||||||
Reference in New Issue
Block a user