Repository navigation
Harden browser social posting: concurrency cap + Reddit fallback subreddit - #63
Merged
Merged
Conversation
…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>
vu1nz Security Review0 finding(s) in PR #? No security issues found. |
ralyodio
marked this pull request as ready for review
July 4, 2026 02:05
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-postendpoint once per account (fire-and-forget), so they all launched in parallel and exhausted the process thread limit:Fix: a module-singleton
AsyncSemaphore(lib/sp/browserSemaphore.ts, default 2, tunable viaSP_BROWSER_CONCURRENCY) gateslaunchContext. The slot is acquired before launch and released on the browser'sdisconnectedevent — so it caps running browsers (launch → close), and the 7 per-platform functions need no changes (their existingfinally { browser.close() }triggers the release). Launch/setup failures release the slot in acatchso 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 withSP_REDDIT_DEFAULT_SUBS. The choice is resolved and persisted on the row at queue time inpostViaAccount, with a matching fallback inprocessBrowserPostfor any legacy/direct rows.Verification
tsc --noEmitcleantests/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)🤖 Generated with Claude Code