fix: give outbound media the same retry/backoff as text#3186
fix: give outbound media the same retry/backoff as text#3186praisonai-triage-agent[bot] wants to merge 2 commits into
Conversation
Media uploads via DeliveryRouter.send_media were attempted exactly once β a transient transport blip (HTTP 5xx, rate limit, connection reset) silently dropped the file while the accompanying text was delivered durably. Text gets resilience because adapters wrap send_message in deliver_with_retry (bounded exponential backoff honouring server Retry-After); the raw media upload path reached none of it. Wrap the media upload in the same deliver_with_retry helper, reusing the adapter's already-configured backoff policy when present. Non-retryable outcomes are preserved: an adapter with no upload primitive still returns False without retrying, and a permanent error still surfaces as a failed send. No new params, modules, exports, or schema β the minimal wiring that closes the reliability gap. Co-authored-by: MervinPraison <MervinPraison@users.noreply.github.com>
|
@coderabbitai review |
|
/review |
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more β On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
β Action performedReview finished.
|
|
Important Review skippedBot user detected. To trigger a single review, invoke the βοΈ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
π WalkthroughWalkthrough
ChangesMedia retry delivery
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
π₯ Pre-merge checks | β 4 | β 1β Failed checks (1 warning)
β Passed checks (4 passed)
β¨ Finishing Touchesπ§ͺ Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAI (not a fork), you are able to make modifications to this branch and push directly. SCOPE: Focus ONLY on Python packages (praisonaiagents, praisonai). Do NOT modify praisonai-rust or praisonai-ts. Read ALL comments above from Gemini, Qodo, CodeRabbit, and Copilot carefully before responding. Phase 1: Review per AGENTS.md
Phase 2: FIX Valid Issues Phase 3: Final Verdict |
|
Claude finished @MervinPraison's task ββ View job Final Architecture Review β PR #3186 β
Phase 1 β ReviewVerdict: sound, minimal, correctly scoped. The PR wraps
Phase 2 β Valid issue found & fixedGreptile's finding is correct and I confirmed it. The Discord native branch in except Exception as e:
logger.warning("Discord media upload failed for %s: %s", channel_id, e)
return FalseBecause Fix pushed ( Added Files modified this review
Skipped: the durable-outbox/idempotency/DLQ expansion from the original issue sketch (scope creep, no live consumer, not how text achieves resilience) β consistent with the PR author's own critical-review reasoning. Tests
Phase 3 β Verdictβ
Approve. The change is a genuine, lightweight robustness improvement with parity across all three native transports (Telegram, Slack, Discord) plus the (Note: I can't submit a formal GitHub approval for security reasons β this comment is the review.) |
The Discord native upload branch caught all exceptions and returned False, so a transient blip bypassed deliver_with_retry entirely and the file was silently dropped β the exact gap this PR set out to close, but only Telegram/Slack got it. Let transport errors propagate (matching the other transports) so the retry wrapper backs off and retries; only the missing optional discord dependency is caught locally, and unresolved channels still fall through to the no-primitive False return. Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
Fixes #3184
Summary
Outbound media/file uploads were best-effort:
DeliveryRouter.send_mediacalled the raw upload primitive (send_photo/files_upload_v2/Discord file send) exactly once, so a transient transport blip (HTTP 5xx, rate limit, connection reset) silently dropped the file β while the accompanying text was delivered durably.Critical-review finding
I traced the real delivery path rather than the issue's idealised sketch. Text delivered via
BotOutboundMessenger.send()does not itself ride the SQLiteOutboundQueue/DLQ β that machinery lives on the adapter reply path. What text does get that media lacked isdeliver_with_retry(bounded exponential backoff honouring serverRetry-After): every adapter wraps its rawsend_messagein it viaOutboundResilienceMixin, whiledeliver_media_to_adapterreached none of it.So the confirmed, honest gap is media has no retry/backoff, and the minimal fix is to give it the same retry wrapper text already uses β at the same wrapper layer.
Change
DeliveryRouter.send_medianow wraps the upload indeliver_with_retry, reusing the adapter's already-configured_outbound_backoffpolicy when present (falling back to a sensible default otherwise).Falsewithout retrying; a permanent error still surfaces as a failed send.OutboundQueue.enqueue) as it duplicates surface with no live consumer and isn't how text achieves resilience here.Tests
Added three focused tests in
test_outbound_media.py:False) after the attempt budget;Falsewithout retrying.All delivery/media/messenger/resilience tests pass (132 passed in the changed areas). Remaining failures in the wider bot suite are pre-existing environmental issues (missing
pydantic), unrelated to this change.Generated with Claude Code
Summary by CodeRabbit