Round-1 review on PR #891: - Guard processor_task's broad except handler against an unbound doc_task (mirrors multi_user_processor_task): initialise doc_task=None before the loop and branch the error log. Fixes a latent NameError if receive() raises a non-TimeoutError/EndOfStream before the first document binds. Regression test added. - Drop the unnecessary `from __future__ import annotations` in vector/_errors.py and express format_exception_group's non-group fast path as an explicit isinstance check. - Add a copy_resource Destination-header encoding test (analogue to MOVE); strengthen the ExceptionGroup test to assert the full leaf repr survives. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
35 lines
1.4 KiB
Python
35 lines
1.4 KiB
Python
"""Error-formatting helpers for the vector-sync pipeline.
|
|
|
|
Vector-sync work runs inside anyio task groups, so a failure in a child task
|
|
surfaces as a ``BaseExceptionGroup`` whose default ``str()`` is the useless
|
|
``"unhandled errors in a TaskGroup (N sub-exception)"`` -- it hides the real
|
|
``ConnectError`` / ``APIConnectionError`` that operators need to triage embed
|
|
drops (card 309). ``format_exception_group`` flattens the group to the leaf
|
|
exceptions so log lines name the actual cause; pair it with ``exc_info=True`` to
|
|
keep the full traceback.
|
|
"""
|
|
|
|
|
|
def format_exception_group(exc: BaseException) -> str:
|
|
"""Return a concise, leaf-naming string for ``exc``.
|
|
|
|
For a (possibly nested) ``BaseExceptionGroup`` this joins the ``repr`` of
|
|
each leaf exception; for an ordinary exception it returns its ``repr``. The
|
|
result is meant for the human-readable portion of a log message, not for
|
|
parsing.
|
|
"""
|
|
if not isinstance(exc, BaseExceptionGroup):
|
|
return repr(exc)
|
|
leaves = _flatten(exc)
|
|
return f"{len(leaves)} sub-exception(s): " + "; ".join(repr(e) for e in leaves)
|
|
|
|
|
|
def _flatten(exc: BaseException) -> list[BaseException]:
|
|
"""Depth-first list of the leaf exceptions within ``exc``."""
|
|
if isinstance(exc, BaseExceptionGroup):
|
|
leaves: list[BaseException] = []
|
|
for sub in exc.exceptions:
|
|
leaves.extend(_flatten(sub))
|
|
return leaves
|
|
return [exc]
|