mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-09-07 04:26:45 +00:00
🐛 Fix: 修复结构化并发子依赖取消缓存问题 (#3084)
This commit is contained in:
@ -21,7 +21,12 @@ from nonebot.log import logger
|
||||
from nonebot.typing import _DependentCallable
|
||||
from nonebot.exception import SkippedException
|
||||
from nonebot.compat import FieldInfo, ModelField, PydanticUndefined
|
||||
from nonebot.utils import run_sync, is_coroutine_callable, flatten_exception_group
|
||||
from nonebot.utils import (
|
||||
run_sync,
|
||||
run_coro_with_shield,
|
||||
is_coroutine_callable,
|
||||
flatten_exception_group,
|
||||
)
|
||||
|
||||
from .utils import check_field_type, get_typed_signature
|
||||
|
||||
@ -207,7 +212,10 @@ class Dependent(Generic[R]):
|
||||
|
||||
async with anyio.create_task_group() as tg:
|
||||
for field in self.params:
|
||||
tg.start_soon(_solve_field, field, params)
|
||||
# shield the task to prevent cancellation
|
||||
# when one of the tasks raises an exception
|
||||
# this will improve the dependency cache reusability
|
||||
tg.start_soon(run_coro_with_shield, _solve_field(field, params))
|
||||
|
||||
return result
|
||||
|
||||
|
@ -115,6 +115,9 @@ class DependencyCache:
|
||||
self._exception: Optional[BaseException] = None
|
||||
self._waiter = anyio.Event()
|
||||
|
||||
def done(self) -> bool:
|
||||
return self._state == CacheState.FINISHED
|
||||
|
||||
def result(self) -> Any:
|
||||
"""获取子依赖结果"""
|
||||
|
||||
@ -304,11 +307,18 @@ class DependParam(Param):
|
||||
dependency_cache[call] = cache = DependencyCache()
|
||||
try:
|
||||
result = await target
|
||||
cache.set_result(result)
|
||||
return result
|
||||
except BaseException as e:
|
||||
except Exception as e:
|
||||
cache.set_exception(e)
|
||||
raise
|
||||
except BaseException as e:
|
||||
cache.set_exception(e)
|
||||
# remove cache when base exception occurs
|
||||
# e.g. CancelledError
|
||||
dependency_cache.pop(call, None)
|
||||
raise
|
||||
else:
|
||||
cache.set_result(result)
|
||||
return result
|
||||
|
||||
@override
|
||||
async def _check(self, **kwargs: Any) -> None:
|
||||
|
Reference in New Issue
Block a user