Skip to content

Commit cb61477

Browse files
Kasper JungeRalphify
authored andcommitted
refactor: extract _call_safely helper for best-effort observer callbacks
The same guarded-callback pattern (`if cb is not None: try: cb(...); except Exception: pass`, with identical "best-effort; draining must not stop" comment) was duplicated three times across `_read_agent_stream` and `_pump_stream`. Consolidate into a single `_call_safely` helper defined next to the callback type aliases. Behavior unchanged — the helper preserves the None guard, suppresses all exceptions, and only fires the callback once with the provided arguments. Co-authored-by: Ralphify <noreply@ralphify.co>
1 parent eb2f4b9 commit cb61477

1 file changed

Lines changed: 19 additions & 18 deletions

File tree

src/ralphify/_agent.py

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,22 @@
4848
OutputLineCallback = Callable[[str, OutputStream], None]
4949
"""Receives raw output lines with their stream name ("stdout"/"stderr")."""
5050

51+
52+
def _call_safely(callback: Callable[..., Any] | None, *args: Any) -> None:
53+
"""Invoke an observer *callback* with *args*, swallowing any exception.
54+
55+
Used for best-effort observer callbacks during output draining: a
56+
raising callback must never stop the drain loop or leave the reader
57+
thread hung.
58+
"""
59+
if callback is None:
60+
return
61+
try:
62+
callback(*args)
63+
except Exception:
64+
pass
65+
66+
5167
# Typed constants for the OutputStream literal so the type checker enforces
5268
# that only "stdout" / "stderr" ever reach ``on_output_line``.
5369
_STDOUT: OutputStream = "stdout"
@@ -360,12 +376,7 @@ def _read_agent_stream(
360376
)
361377

362378
stdout_lines.append(line)
363-
if on_output_line is not None:
364-
try:
365-
on_output_line(line.rstrip("\r\n"), _STDOUT)
366-
except Exception:
367-
# Callback is best-effort; draining must not stop.
368-
pass
379+
_call_safely(on_output_line, line.rstrip("\r\n"), _STDOUT)
369380

370381
stripped = line.strip()
371382
if stripped:
@@ -378,12 +389,7 @@ def _read_agent_stream(
378389
parsed.get(_RESULT_FIELD), str
379390
):
380391
result_text = parsed[_RESULT_FIELD]
381-
if on_activity is not None:
382-
try:
383-
on_activity(parsed)
384-
except Exception:
385-
# Callback is best-effort; draining must not stop.
386-
pass
392+
_call_safely(on_activity, parsed)
387393

388394
# Also check deadline after processing — if the reader thread
389395
# already queued many lines, this prevents unbounded processing
@@ -502,12 +508,7 @@ def _pump_stream(
502508
for line in iter(stream.readline, ""):
503509
if buffer is not None:
504510
buffer.append(line)
505-
if on_output_line is not None:
506-
try:
507-
on_output_line(line.rstrip("\r\n"), stream_name)
508-
except Exception:
509-
# Callback is best-effort; draining must not stop.
510-
pass
511+
_call_safely(on_output_line, line.rstrip("\r\n"), stream_name)
511512
except (ValueError, OSError):
512513
# Pipe closed concurrently — exit cleanly so join() returns.
513514
pass

0 commit comments

Comments
 (0)