Skip to content

Harden browser social posting: concurrency cap + Reddit fallback subreddit - #63

Merged
ralyodio merged 1 commit into
masterfrom
harden-browser-posting
Jul 4, 2026
Merged

ralyodio merged 1 commit into
masterfrom
harden-browser-posting

Conversation

@ralyodio

@ralyodio ralyodio commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Two fixes for the failures seen in a bulk "post to all" outreach run (Bluesky/Discord/Telegram sent; X/Threads/Instagram/Facebook/LinkedIn/Mastodon crashed; Reddit rejected).

1. Cap headless-Chromium concurrency

Every browser-automated post launches its own Chromium. A "post to all" run hits the worker's /sp/browser-post endpoint once per account (fire-and-forget), so they all launched in parallel and exhausted the process thread limit:

pthread_create: Resource temporarily unavailable (11)
FATAL: Failed to start BrowserThread:IO

Fix: a module-singleton AsyncSemaphore (lib/sp/browserSemaphore.ts, default 2, tunable via SP_BROWSER_CONCURRENCY) gates launchContext. The slot is acquired before launch and released on the browser's disconnected event — so it caps running browsers (launch → close), and the 7 per-platform functions need no changes (their existing finally { browser.close() } triggers the release). Launch/setup failures release the slot in a catch so capacity can't leak.

2. Reddit fallback subreddit

Reddit is cookie/browser-based, so outreach/autopost rows reach the worker without a subreddit and failed with "Subreddit is required for Reddit posts."

Fix: resolveSubreddit (lib/sp/redditSubreddit.ts) routes such a post to a related, relatively open ("low moderation") subreddit by keyword over a small curated list (SideProject / juststart / SEO / artificial), overridable with SP_REDDIT_DEFAULT_SUBS. The choice is resolved and persisted on the row at queue time in postViaAccount, with a matching fallback in processBrowserPost for any legacy/direct rows.

Note: the curated "low moderation" list is best-effort — moderation strictness isn't verifiable from here and changes over time — hence the env override. Tune SP_REDDIT_DEFAULT_SUBS to your preferred targets.

Verification

  • tsc --noEmit clean
  • tests/sp/* pass (29/29), including the new AsyncSemaphore tests (peak concurrency == max across 8 tasks; full serialization at max=1; slot released on throw) and subreddit tests (keyword routing, r/ normalization, env override)
  • Not exercised live (no Playwright/worker + connected cookie accounts in this environment); the concurrency slot lifetime and the Reddit routing are covered by unit tests instead.

🤖 Generated with Claude Code

…eddit

Two fixes for the failures seen in bulk "post to all" outreach runs.

1. Cap headless-Chromium concurrency. Every browser-automated post launches
   its own Chromium; firing many at once (the worker's /sp/browser-post
   endpoint hit once per account) launched them all in parallel and blew past
   the process thread limit — every launch died with "pthread_create:
   Resource temporarily unavailable / Failed to start BrowserThread:IO". A
   module-singleton AsyncSemaphore (default 2, SP_BROWSER_CONCURRENCY) now
   gates launchContext; the slot is held for the whole browser lifetime and
   released on the 'disconnected' event, so no changes to the per-platform
   functions are needed.

2. Reddit no longer fails when no subreddit is given. Outreach/autopost rows
   don't carry one, so the post threw "Subreddit is required." resolveSubreddit
   now routes the post to a related, relatively open ("low moderation")
   subreddit by keyword (curated list, overridable via SP_REDDIT_DEFAULT_SUBS),
   persisted on the row at queue time, with a matching fallback in the worker
   for legacy rows.

Tests: AsyncSemaphore concurrency ceiling + release-on-throw; subreddit keyword
routing, r/ normalization, and env override.

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:05
@ralyodio
ralyodio merged commit 6dfb20e into master Jul 4, 2026
8 checks passed
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