perf(server): return 204 from post_message (LC-228) #292
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/lc-228-post-message-no-content"
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
The composer form posts with
hx-swap="none"(templates/room/composer.html:11), so any body returned byPOST /room/{id}/messagesis discarded by htmx. The handler was rendering a ~5 KBComposerFragmenttemplate + serializing it on every send for nothing. This PR returns204 No Contentinstead, skipping the render + serialization. The slash-dispatch branch still returns its own fragment (commands like/merender through the route), and the link-filter Block branch also flips to 204 since its old behaviour was the same wasted-render pattern.The user-visible effects (textarea clear, send-button enable) are driven by
event.detail.successfulonhx-on::after-request, which fires for any 2xx response including 204. The rendered message itself is fanned out to every connected client byfinalize_message_sendvia the WS hub - nothing on the wire to the sender is needed.Test plan
just checkclean (clippy + fmt for both standalone and saas)just testpasses (50 integration binaries)just test-saaspasses (modulo the known-flakyroutes_uploadsunder concurrent-binary load - documented in CLAUDE.md)StatusCode::OKafter a POST to/room/{id}/messagesupdated to assertStatusCode::NO_CONTENT. PATCH /messages/{id} (edit) is unchanged.The composer form posts with `hx-swap="none"` (composer.html:11), so any body returned by `POST /room/{id}/messages` is discarded by htmx. The handler was rendering a ~5 KB `ComposerFragment` template and serializing it on every send for nothing. Switch the success return (and the link-filter Block branch) to `StatusCode::NO_CONTENT` and drop the unused `ComposerFragment` import. The slash-dispatch arm continues to return its own fragment via `into_response()` so commands like `/me` still render through the route. The user-visible effects (textarea clear, send-button enable) are driven by `event.detail.successful` on `hx-on::after-request`, which fires for any 2xx including 204; the rendered message itself is fanned out via the WS hub by `finalize_message_send`. Test contract: this is a category-4 (test-contract drift) change per CLAUDE.md. Updated every integration test that POSTs to `/room/{id}/messages` and asserts `StatusCode::OK` to assert `StatusCode::NO_CONTENT` instead. `PATCH /messages/{id}` (edit) is unchanged and still returns 200 with the rendered fragment.The slash-command dispatch in `routes/slash.rs` had the same waste pattern as the LC-228 fix in `post_message`: `/me`, `/shrug`, `/poll`, `/remind`, and custom commands all rendered a ~5 KB `ComposerFragment` after posting their message, even though the composer form posts with `hx-swap="none"` so htmx discards the body. Flipping these to 204 saves the render on every slash send. Signature: `try_dispatch` now returns `Result<Option<Response>, AppError>` instead of `Result<Option<Html>, AppError>` so it can mix the 204 path with the `/help` render path (which legitimately returns HTML for the ephemeral OOB result panel). The room.rs caller is simplified to return `resp` directly (no `.into_response()` wrap needed on a Response). Tests: routes_slash.rs `/me` and `/remind` now assert NO_CONTENT; `/help` stays OK (legit render). routes_polls.rs `slash_command_posts_poll` flipped to NO_CONTENT (POST /room/{id}/messages -> slash dispatch -> /poll).