Source-only publication of reviewed commit 64e96a7f423673dc29ad56485be9fc79bce8af1c.
Passed in isolation: focused frontend/backend tests, race checks, TypeScript typecheck, lint, Go compilation, Flowgram build, and deterministic SDK build/tests.
Not accepted as a production release: Next.js export/native assembly remains blocked by environment memory limits; browser interaction and MySQL staging acceptance remain unverified. No production server, database/schema, runtime configuration, deployment, release tag, or workflow execution was performed.
Expected source tree: 0a4a7528e9.
72 lines
3.8 KiB
Markdown
72 lines
3.8 KiB
Markdown
# Support chat realtime recovery
|
|
|
|
This targeted change is based on canonical Gitea main snapshot
|
|
`e57610a27c556e005b9b3b68115477ba1fdd3f1b` (tree
|
|
`9cf938c2498ce6b63faaad7cf8b286c1cfe7a5ef`). That original targeted change did not import
|
|
the separate hardening-review branch. The current integration reconciles it with that branch,
|
|
preserving both realtime recovery and scoped identity/draft safeguards.
|
|
|
|
## Report and source findings
|
|
|
|
The reported scenario is opening a new chat from a previous one: sending works,
|
|
but replies appear only after a page reload. Source inspection does **not** prove
|
|
why the deployed WebSocket fails. The deployed version, reverse proxy, browser
|
|
handshake and network have not been observed or tested for this report.
|
|
|
|
The source does establish these recovery gaps:
|
|
|
|
- A socket in `CONNECTING` has no deadline; subsequent create/select/send paths
|
|
see it and return without starting a replacement.
|
|
- HTTP fallback checks end after 1.5, 3.5 and 7 seconds, so a later reply is not
|
|
retrieved while realtime remains unavailable.
|
|
- Reusing an open socket on create/select bypasses the shared status repair path.
|
|
- Initial history failure prevents bootstrap/retry from starting realtime.
|
|
- A replaced socket's late close can clear the current heartbeat/subscription
|
|
bookkeeping. A late close-conversation response can affect a newer selection.
|
|
|
|
## Changes
|
|
|
|
- Bound connection/authentication attempts to 15 seconds, invalidate abandoned
|
|
attempts, and retry using the existing exponential reconnect policy.
|
|
- Ignore close events from replaced sockets before touching current state.
|
|
- Route new/selected chats through the existing subscription/connection helper.
|
|
- Fetch late replies every 5 seconds only while the chat is open, visible, has
|
|
an active nonclosed conversation, and realtime is not connected. Never label
|
|
HTTP fallback as an online WebSocket.
|
|
- Keep latest-message refresh single-flight with a 15-second abort deadline.
|
|
Cancel previous-view requests and fence their completion before starting a new
|
|
one. Ignore stale identity/view results, stop recovery on connection, hiding,
|
|
close or teardown, and recover on focus, visibility or network return.
|
|
Background recovery failures remain quiet. The optional API AbortSignal is
|
|
backward-compatible with existing history/pagination callers.
|
|
- Connect independently of initial HTTP history success and merge history so it
|
|
cannot remove a reply already delivered by realtime.
|
|
- Restrict a close response to the conversation it actually closed.
|
|
|
|
No backend, SDK bundle, credentials, database, deployment configuration or
|
|
production data is changed.
|
|
|
|
## Validation status
|
|
|
|
Completed static checks only:
|
|
|
|
- `git diff --check`.
|
|
- Isolated strict TypeScript compile of `web/lib/realtime-connection.ts` using an
|
|
already installed TypeScript 6.0.3 compiler.
|
|
- TypeScript syntax/transpile diagnostics for the four changed production files.
|
|
- JavaScript syntax checks for the two focused regression files.
|
|
|
|
Added offline mock regressions for delayed replies beyond seven seconds, moving
|
|
from a previous chat, resubscription, stuck handshakes, late authentication and
|
|
socket close events, hidden/unmounted lifecycle, single-flight fallback,
|
|
identity/view changes, abort deadlines, stalled previous-view fetches, history
|
|
failures and late close responses.
|
|
|
|
The integrated 2026-10-16 baseline has now executed all 226 frontend Node tests,
|
|
including these recovery regressions, and the declared-dependency frontend
|
|
typecheck. Both passed. Focused backend security/setup tests and their race run
|
|
also passed; see [the current validation record](../hardening/VALIDATION.md) for
|
|
exact scope, fixture corrections and remaining build/lint/MySQL/browser gates.
|
|
No production services were started, real support messages sent, or deployment
|
|
performed. These checks are not a claim of production acceptance.
|