Daily publish cap #90
Labels
No labels
bug
devops
duplicate
enhancement
good first issue
layout
next major release
next minor release
question
research
testing
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lvl0/fedi-feed-router#90
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Cap how many articles may be published per day, so a feed that suddenly returns a large batch cannot flood a community.
Why this matters concretely
Belga's feed fetches
count=50per poll.PublishNextArticleJobruns every five minutes and publishes one article per run, so the current ceiling is roughly 288 posts/day with no way to lower it beyond stretching the global interval — which also slows normal operation.Setting
daily_publish_cap00= unlimitedDefaulting to unlimited matters: an existing install must publish exactly as it does today until someone opts in.
Design
PublishNextArticleJobbefore article selection — the cap is article-independent, so there's no reason to run the candidate query when it has been reached.article_publicationscreated today, compared against the cap.publishing_timezonesetting introduced in #129; once that ships, this should switch to counting from local midnight. Noted deliberately rather than pre-built.Tasks
daily_publish_capsetting +SettingaccessorsPublishNextArticleJobSettingsControllerTests that matter
0= unlimited (regression guard: today's behaviour exactly)Constraints
PublishNextArticleJobisShouldBeUniquewithuniqueFor = 300on a five-minute schedule. Confirm an early return releases the unique lock rather than suppressing the following tick, before adding a new early-return path.Do not weaken #123 (
Cache::lockduplicate guard) or #119 (scopeDueForPublishingis the single source of truth for publish eligibility — do not re-express that threshold in a new query).Superseded scope
This ticket originally read "Publishing schedule control" and bundled four features. It was split because they are independent in design, review, and risk, and because three of them change the publishing path hardened by #123 and #119.
Split out to v2.0.0:
Original description:
Publishing schedule controlto Daily publish capImplemented in
cb63a05onrelease/v1.4.0.Delivered
daily_publish_capsetting, default0= unlimitedPublishNextArticleJob::dailyCapReached(), checked before the interval check and before the candidate querySettingsController(index + update, validatedinteger|min:0)Semantics worth knowing
The cap counts
ArticlePublicationrows, not distinct articles. An article cross-posted to three channels consumes three units.This is deliberate. The cap exists to stop a community being flooded; counting distinct articles would let each of three channels receive the full cap. The Settings copy states this explicitly rather than saying "articles", which would have been misleading.
Counting runs from
now()->startOfDay()— the UTC day, sinceconfig/app.phpis'timezone' => 'UTC'. Once #129 landspublishing_timezone, this should switch to local midnight. Noted in.claude/PLATFORM.mdso it isn't rediscovered as a bug.Open question from the ticket — resolved
It does.
CallQueuedHandler::ensureUniqueJobLockIsReleased()runs afterhandle()returns regardless of how it returned, so a cap-gated skip cannot suppress the next five-minute tick. The schedule entry also carries its ownwithoutOverlapping()as a second layer.Not done
The Settings row has not been exercised in a browser — it is test-green only.
Verification
960 tests / 2524 assertions passing (948 before), Pint clean (303 files), PHPStan clean. Verified by mutation that the cap test fails when the gate is removed.
Quiet hours and per-channel pacing were split out of this ticket to #129 and #130 (v2.0.0).