"""pull_file — вытащить файл с ВМ-буфера исходящим GET с ретраями.""" import logging import time from .config import PULL_RETRIES, PULL_RETRY_DELAY log = logging.getLogger("upload.upload_refs.pull") def pull_file(client, url: str, retries: int = PULL_RETRIES, delay: float = PULL_RETRY_DELAY, sid: str = None, name: str = None) -> bytes: """GET url с ретраями; читает по частям (stream). Args: client: httpx.Client url: URL файла на ВМ-буфере. retries: число попыток. delay: пауза между попытками (сек). sid/name: для логирования (опционально). Returns: Содержимое файла (bytes). Raises: Последнюю ошибку попытки, если все ретраи не удались. """ last_err = None for attempt in range(retries): try: with client.stream("GET", url) as resp: resp.raise_for_status() return b"".join(resp.iter_bytes()) except Exception as e: last_err = e log.warning("pull: attempt %d/%d failed sid=%s file=%r: %r", attempt + 1, retries, sid, name, e) time.sleep(delay) raise last_err if last_err else RuntimeError("pull failed")