Skip to content

Add retry button for failed /recent outreach - #62

Merged
ralyodio merged 1 commit into
masterfrom
outreach-retry-button
Jul 4, 2026
Merged

ralyodio merged 1 commit into
masterfrom
outreach-retry-button

Conversation

@ralyodio

@ralyodio ralyodio commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

What

Failed (and timed-out) rows in the Send outreach history on /recent had no way to re-attempt delivery. This adds a Retry button to each such row.

This is the surface behind the delivery log you'd see after a "post to all" run — e.g. Bluesky/Discord/Telegram sent, while X/Threads/Instagram/Facebook/LinkedIn/Mastodon failed with the Chromium launch crash (pthread_create: Resource temporarily unavailable — parallel headless-browser launches exhausting the thread limit), and Reddit failed on a missing subreddit.

How

  • retryRecentOutreach({ messageId }) server action — reads the stored recent_outreach_messages row, verifies org ownership, guards on failed/timed_out, and reconstructs the original request (channel, subject, body, visibility, audit, org) to run back through the existing sendRecentAuditOutreach. That means credit charging, fresh history recording, and failure refunds all behave exactly like a first attempt — the old row is left intact as an audit trail.
  • Social rows only record the platform, not the specific account, so the action resolves the user's active account(s) on that platform to retry against (clear error if none is connected).
  • RetryOutreachButton in outreach-form.tsx — mirrors the existing RetryPostButton pattern (transition + router.refresh()), shown on failed/timed-out history rows.

Bonus: retrying one row at a time naturally avoids the parallel browser-launch storm that makes bulk sends fail on the browser-driven platforms — a practical mitigation until browser concurrency is capped.

Verification

  • tsc --noEmit clean
  • tests/sp/* pass (20/20)
  • Pattern matches the existing, working retryPost → RetryPostButton flow; the delegated sendRecentAuditOutreach credit/record/refund path is unchanged. A live end-to-end run wasn't exercised here (needs seeded auth + org + a failed message + a connected social account).

Not included

The root-cause fix for the bulk failures — capping concurrency of the browser-based posters (a semaphore so only 1–2 headless Chromium launch at once) — is a separate change; happy to follow up if wanted.

🤖 Generated with Claude Code

Failed (and timed-out) rows in the "Send outreach" history on /recent had
no way to re-attempt delivery — which stung most on the Chromium-based
social platforms, where a bulk "post to all" run fails several at once due
to parallel browser-launch resource exhaustion.

Adds a Retry button on each failed/timed-out history row plus a
retryRecentOutreach server action. The action reconstructs the original
request from the stored recent_outreach_messages row (channel, subject,
body, visibility, audit, org) and runs it back through
sendRecentAuditOutreach, so credit charging, history recording, and
failure refunds all behave exactly like a first attempt. Social rows only
record the platform, so it resolves the user's active account(s) on that
platform to retry against. Retrying one row at a time also sidesteps the
parallel-launch crash that bulk sends hit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@ralyodio
ralyodio marked this pull request as ready for review July 4, 2026 02:04
@ralyodio
ralyodio merged commit 8a349c5 into master Jul 4, 2026
8 checks passed
@ralyodio
ralyodio deleted the outreach-retry-button branch July 4, 2026 02:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant