You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit ed757db
Browse filesBrowse the repository at this point in the historyBrowse files
fix(engagement): wait for threads reply containers and handle failed sends (#202)
* fix(engagement): wait for Threads reply containers and handle failed sends
A Threads reply read its container status once, right after creating it,
so any IN_PROGRESS response failed the reply. It now polls the same
container for up to 12 seconds, with timeouts that fit the Octane limit.
The audit of that failure found the same problems elsewhere:
- Raw cURL text reached users through reply, DM, and publish errors. It now
goes to the log and attempt rows, and users see a plain message.
- useHttp sends a 422 only to onError and resolves empty, so callers treated
it as success. Drafts were lost, and a failed mention save blanked the page.
- submit-bar could never show its 422 errors. Publish and queue conflicts now
return 409, and the composer stops when the save before a publish fails.
- Failed requests in Messages, post actions, and the share dialog left
unhandled rejections and no feedback.
- Toasts covered the Reply button, so the toaster moved to top-center.
- Test files under pages/ were built into the production bundle.
Fixes#201
* chore(deps): bump phpunit, pest, and symfony/mime for security advisories
Fixes the composer-audit failure from CVE-2026-119193 (phpunit) and
CVE-2026-45070 (symfony/mime). Pest moves too, because v5.3.3 conflicts with
phpunit above 13.4.3.
* refactor(engagement): send Threads replies from a background job
The bounded poll held an Octane worker while Threads processed the container,
and the 12 second limit was shorter than Meta's guidance.
Threads replies now go through SendReply. The job makes one status check per
run and schedules a follow-up when the container is still processing, so the
wait holds no worker at all. This matters because the default is a single
queue worker, and a sleeping job would delay scheduled posts. The container id
travels in the job, so a retry cannot create a second container.
The inbox polls while a reply is sending. When the job fails, it shows the
stored reason and restores the draft. A queued reply is marked replied only
after the job sends it.
* fix(engagement): keep rate-limited replies queued instead of failing them
SendReply shares a 10-per-minute limit per platform. A rate-limit release
still counts as an attempt, so with tries = 3 a reply that waited for its turn
failed after three releases. Threads text replies now use this job, so a busy
minute would fail them.
The job now retries for 10 minutes and still stops after 3 real exceptions.
* fix(engagement): replace failed reply attempts and say when polling stops
A failed queued reply stayed in the thread, so each retry added another
"Failed to send" bubble. A new reply now deletes our failed attempts at the
same reply, which never reached the platform, and the inbox drops their
bubbles.
The inbox stopped polling a sending reply after 5 minutes without a word. It
now tells the user the reply is still sending.
* fix(engagement): address Copilot review on queued replies
- A save error after the platform accepted the reply no longer retries the
job, which would post it twice. The job fails at once and tells the user
the reply may have posted.
- A failed draft is restored only into its own conversation. A stale poll
could put it into the box of the conversation now open.
- Restored drafts keep their attachments, through a restore handle on the
reply box.
- The failed bubble shows the stored reason, so it is visible after a reload.
- The Threads status check has short timeouts, so a hung request hands the
queue worker back.
* chore(deps): bump symfony 8.1 components for security advisories
Fixes the composer-audit failure from new advisories in symfony/filesystem,
http-foundation, http-kernel, routing, serializer, and yaml (8.1.9 to 8.1.11).
* refactor(frontend): handle failed requests with results, not empty catches
`useHttp` calls a request's failure callback and then still rejects, and it
resolves with nothing on a 422. Callers had silenced that rejection with
empty `catch` blocks and `.catch(() => {})` all over the inbox, composer, and
post pages.
`settle()` in `lib/http/errors.ts` now waits for a request and returns
`{ ok, value }`. The failure callbacks tell the user what went wrong, and each
caller branches on the result:
- Send functions return whether they sent, so the reply and message boxes
keep the draft without a try/catch.
- Like, delete, archive, mark-read, share, retry, reschedule, and mention
save/delete restore or skip their state change when the request failed.
- Thread loading goes through one `loadThread()` that returns null when the
thread cannot be loaded, and ignores answers that arrive after the
selection moved on.
* fix(mentions): explain which characters a mention name may use
An invalid name showed Laravel's default "The name field format is invalid.",
which does not say what to change. Found in an end-to-end run of the composer.
0 commit comments