Keep Mastodon auto-refresh under the rate limit so posts don't fail with 429 - #24
Merged
Merged
Conversation
Auto-refresh polls every open timeline each interval. With many timelines open (57 here, ~110 requests/minute) that exhausts Mastodon's ~300 calls per 5 minutes per account within minutes, and posts then fail with 429 and only an error earcon. Route every MastodonAccount HTTP call through one send() helper that reads X-RateLimit-Remaining/Reset from our own instance; when fewer than 100 calls remain (or on a 429), background refresh is skipped for that account until the server's reset time. Also log failed non-GET requests with their status and error body, and include the WinHTTP error code on transport failures, so a failed action leaves something in the log. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Thread and user timelines whose newest post is over a day old rarely change, but with dozens open, refreshing each every auto-refresh tick is what spends the rate limit. Refresh those only every 15th tick; the timeline being viewed always refreshes, and manual refresh is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
|
I'll merge this, but mate, I very strongly suggest you use lists. having 60 user timelines open is going to put strain on your Mastodon server regardless. That's just, wow. |
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.
Keeps Mastodon auto-refresh within the server's rate limit so posting stops failing with 429. There are two changes: auto-refresh backs off when the limit is nearly spent, and idle threads and user timelines are polled every 15 minutes instead of every minute.
Problem
On Mastodon, posting fails with the error earcon and nothing in the log. After adding logging, the server response turned out to be:
Auto-refresh (default every 60s) refreshes every open timeline. With 57 timelines restored (mostly user and thread timelines, about 2 requests each), that's roughly 110 requests a minute. Mastodon allows about 300 per 5 minutes per account, so the budget is gone within about 3 minutes of each window, and anything the user does after that gets a 429 until the window resets. Posting works right after launch and then starts failing.
Fix
MastodonAccountroutes every HTTP call through a singlesend()helper that readsX-RateLimit-Remaining/X-RateLimit-Resetfrom the user's own instance. Remote-instance timelines are ignored.background_refresh_allowed()returns false until the server's reset time. If there's no reset header, it waits 5 minutes.CoreSession::refresh_all_accounts()(the auto-refresh tick) skips accounts that are throttled. Manual refresh, streaming and user actions are unaffected. Bluesky keeps the default oftrue.GetLastError()code. Without this, the 429 couldn't be seen.Testing
build.bat test: 822 checks, 0 failures. The newtest_mastodon_rate_limit_pauses_refreshcovers plenty of budget, nearly spent, reset time already passed, and a bare 429.🤖 Generated with Claude Code