fix(repositories): stop calling a lost answer a failed publication - #16
Conversation
A publish-now request that ends without an answer said "Failed to connect to Content Maestro API", which reads as "nothing was published" - and the posts had gone out. Backgrounding the PWA is enough to cause it: the browser suspends the page and tears the connection down mid-request. An unanswered request now reports an unknown outcome, and the dialog goes on to establish the real one from the two records that outlive the request - the run Content Maestro logged and the posted flag in Content Alchemist - so the per-integration results are shown even though the answer carrying them was lost. An answered refusal keeps saying what Content Maestro said, and is not reconciled. An absent run is deliberately not reported as "nothing was published": runs are logged when they finish, so an unfinished one looks exactly the same, and that guess is what causes a double post.
Deploying content-sentinel with
|
| Latest commit: |
c58e016
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://a4bf06f0.content-sentinel.pages.dev |
| Branch Preview URL: | https://fix-publish-now-unknown-outc.content-sentinel.pages.dev |
Three problems found in review of the reconciliation: Any recorded run for the repository was accepted as ours, but Cron History marks manual runs and a scheduled one for the same repository is a different publication - which happens whenever an earlier run published it and failed to mark it posted, so it never left the queue. Only manual runs are matched now; a scheduled one still surfaces through the posted flag. A run that sent nothing was described with the queue note, so a repository some other run had published read as "the run published nothing, so finish the rest with Publish again" - contradictory, and an invitation to publish it twice. That case now says another run published it, and reports the repository as published. getRepositoryByUrl trusted the body of any 200, but Content Alchemist answers some errors that way, which turned a readable failure into "this repository does not exist".
|
Review findings addressed in c58e016. 1. The remaining same-window overlap is a manual Publish-again for the same url, which is a deliberate action by the same person rather than a background race. 2. Contradictory verdict when a matched run sent nothing but 3. Tests: 50 pass (3 new - a scheduled run being ignored, and the two sent-nothing verdicts). |
|
🎉 This PR is included in version 1.51.1 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Problem
A publish-now request that ends without an answer was reported as
Failed to connect to Content Maestro API, which reads as "nothing was published". In production the posts had in fact gone out: backgrounding the PWA mid-publish is enough to trigger it, because the browser suspends the page and tears the connection down while the request is still open.fetchthen rejects with aTypeError, andapiErrorMessageasserts a connectivity failure it cannot actually know about.What changes
An unanswered request now reports an unknown outcome.
classifyPublishFailureseparates "Content Maestro refused this" (an HTTP answer, shown verbatim as before) from "we never heard back" (timeout, abort, dropped connection), and the second says the publication may still be running instead of claiming it failed.The dialog then establishes what actually happened.
reconcilePublishreads the two records that outlive the request - the run Content Maestro logged incron-historyand the repository'spostedflag in Content Alchemist - and reports the real outcome, including the per-integration rows recovered from the run. Each source is read independently, so one of them being unreachable still leaves the other worth reporting; an unreadable run list is reported as unknown rather than as an absent run.An absent run is deliberately not reported as "nothing was published": runs are logged when they finish, so an unfinished publication looks exactly like one that never happened, and that guess is what causes a double post.
New code
src/utils/publish-reconcile.ts-classifyPublishFailure,reconcilePublish(pure, 19 unit tests).src/api.ts-getRepositoryByUrl, a url-filtered lookup that skips the request queue and the display-language filter, and refuses an answer for another repository (an older Content Alchemist ignores the filter and returns the head of the queue).publish-repository-dialog.tsx- areconcilingphase, the verdict banner, and rows built from the recovered run.Verification
Unit: 47 tests pass (19 new).
tscclean apart from the two errors already onmaininsrc/hooks/useRepositories.ts.npm run buildpasses. Local eslint is broken onmain(unrelated rule-loading error), so it could not be run.End to end against a local stack (content-alchemist + content-maestro + two connector stubs) with a proxy that forwards the publish request upstream and closes the client connection without answering - the exact production scenario:
The browser also replayed the cut POST on its own during the test, and Content Maestro refused the replay with 409 (
another publication is already running) - the duplicate-post guard from #15 holding up under the real failure mode.