File size: 1,248 Bytes
28a08e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
"""
utils.py — Backend utilities condivise (P9).

gather_safe(*coros): wrapper asyncio.gather con return_exceptions=True
che filtra eccezioni, le loga, e restituisce solo i risultati validi.
"""
from __future__ import annotations

import asyncio
import logging
from collections.abc import Awaitable
from typing import TypeVar

_logger = logging.getLogger("backend.utils")

T = TypeVar("T")


async def gather_safe(*coros: Awaitable[T], tag: str = "") -> list[T]:
    """
    Esegui le coroutine in parallelo con return_exceptions=True.

    - Le eccezioni vengono loggate come warning (non propagate).
    - Restituisce solo i risultati validi (non-eccezione).
    - tag: stringa opzionale per identificare il callsite nei log.

    Uso:
        results = await gather_safe(coro1(), coro2(), coro3(), tag="web_search")
    """
    raw = await asyncio.gather(*coros, return_exceptions=True)
    results: list[T] = []
    for i, item in enumerate(raw):
        if isinstance(item, BaseException):
            _logger.warning(
                "gather_safe[%s] coro[%d] raised %s: %s",
                tag or "?", i, type(item).__name__, item,
            )
        else:
            results.append(item)  # type: ignore[arg-type]
    return results