feat(api): publish a repository immediately - #3
Merged
Merged
Conversation
A post lost after publication - a bad record deleted from the queue once it was already sent - cannot be recovered by promoting anything: the item is gone from the queue. Promoting only moves a repository to the head of it, so there was no way to get a replacement post out without waiting for the cron. POST /api/message/publish publishes one repository right now, to every integration whose api_configs row is enabled. The enabled set is resolved server-side: a dashboard's cached configuration must not decide what is sent. RetryMessagePost and the new PublishNow now share publishManually, which differs between them in only three places - which connectors to use, when a still-unposted item may leave the queue, and the cron-history prefix. Retry keeps its all-or-nothing marking; publishing on demand follows the cron and marks the item posted as soon as any integration accepts it, recording the run as manual so the connectors that failed are finished off with the retry endpoint. Two guards make a duplicate post impossible: the item is refused when it has already left the queue (a stale dashboard row, or a cron run seconds earlier), and publishing takes the mutex with TryLock rather than queueing behind a cron run that can hold it for minutes. The message cron now takes that same mutex, which it never did - a manual run marking its item posted mid-cron would have left the cron marking an item it never sent. PublishResult gained posted/posted_error, so "published but still in the queue" is visible instead of only logged.
Review found the pre-flight lookup mapping every failure to 500, so a typo'd url or a row deleted since the dashboard rendered it - a routine client mistake - was reported the same way as content-alchemist being down. That contradicts the handler's own promise that its error statuses say why nothing was attempted, and it pollutes 5xx alerting. The repository package now exports ErrRepositoryNotFound and wraps both ways a lookup can come up empty: content-alchemist answering 404, and an empty item list. Publishing maps it to 404 and leaves 500 for a content-alchemist that could not be reached at all. The pre-flight lookup is deliberately kept even though the connector loop fetches the item again a moment later: it is what turns an unpublishable request into one clear error instead of a set of per-connector failures plus a cron-history row for a run that could never have worked. Said so in a comment, since the duplicate fetch reads like an oversight otherwise. Also documents what the retry endpoint's blocking lock now means: it waits for a cron run or a publish-now rather than refusing, the wait is unbounded, and there is no request timeout.
Driving the endpoint against a local stack surfaced the wording: publishing a repository with no url answered "invalid retry request: url is required", and the dashboard shows Content Maestro's plain-text errors verbatim. The sentinel keeps its identifier - it is what both manual endpoints reject with - but its message no longer names one of them.
Member
Author
|
🎉 This PR is included in version 3.9.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
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.
Why
A post lost after publication — a bad record deleted from the queue once it had already been sent — cannot be recovered by promoting anything: the item is gone from the queue. Promoting only moves a repository to the head of the queue, so there was no way to get a replacement post out without waiting for the
messagecron.What
New
POST /api/message/publish—{"url": "..."}— publishes one repository now, to every integration whoseapi_configsrow isenabled. There is deliberately noapisparameter: the enabled set is resolved server-side, because a dashboard's cached configuration must not decide what actually goes out.RetryMessagePostand the newPublishNownow sharepublishManually, which differs between them in only three places — which connectors to use, when a still-unposted item may leave the queue, and the cron-history prefix:409409A partial run is recorded in cron history as manual, so the connectors that failed are finished off with the existing "Publish again" button.
Duplicate-post guards
TryLock: publishing refuses rather than queueing behind a cron run that can hold the lock for minutes.Also
PublishResultgainedposted/posted_error, so "published but still in the queue" is visible instead of only logged — theboolfromUpdateRepositoryPostedused to be discarded into_.Duration warning
The request is synchronous and can take minutes: image generation retries for ~63 s, the Threads connector alone is configured with a 90 s timeout, and every integration adds its own repository lookup. Any reverse proxy in front of content-maestro needs a matching read timeout, or the browser gets a
504while the publication keeps running. Documented inapi_docs.md.Tests
go test -race ./...— all green. 8 new tests ininternal/schedule/message-publish_test.go(enabled-only fan-out and its stable order, mark-posted on partial success, nothing sent, missing url, no enabled integration, already-posted refusal, concurrent-run refusal) plus a newinternal/server/api_test.gocovering the error→status mapping (405/400/409/200). The four existing retry tests pass untouched, which is also what proves the cron policy did not leak into retry.Paired with think-root/content-sentinel#15 (the dialog that drives this endpoint).