Skip to content

Harden session lifecycle, timers, and canonical room routing - #10

Merged
Andyccr merged 1 commit into
mainfrom
cursor/arch-upgrade-7527
Sep 17, 2026
Merged

Andyccr merged 1 commit into
mainfrom
cursor/arch-upgrade-7527

Conversation

@Andyccr

@Andyccr Andyccr commented Sep 17, 2026

Copy link
Copy Markdown
Owner

Full architecture audit after #9. This PR hardens the remaining lifecycle, timer, and navigation gaps without changing the v1 wire or leaving the static Pages constraint.

What was wrong

  • Failed joins left a live transport; retry stacked connections.
  • Outbound ack timers kept running while the tab was hidden (false 未送达 on mobile).
  • Presence prune treated ICE-connected quiet peers as gone.
  • Room names were raw in lobby/hash/recent and normalized only on parse — tab highlight and share URLs drifted.
  • go() raced hashchange and could double-open; empty room names were joinable; App catch clobbered relay diagnostics.

What changed

  • Session teardown + epoch — join always leaves the previous transport; in-flight send/ping/payload ignore stale generations.
  • Visibility-aware Outbound — deadlines pause while hidden, then settle remaining time on resume.
  • Presence prune — skip ids still in transport.peerIds().
  • Payload routerapplyIncoming dispatches hello/typing/ack/chat.
  • Canonical RoomSpec — one name at lobby, jump, hash, recent, and RoomManager. Empty names rejected.
  • Single hash pipelinego() only writes the hash; hashchange routes.
  • Debounced log cache — snapshot ~2s after new lines, not only on leave.
  • Jump dialog shows 口令 copy, respects canJoin(), nick commits before send.

Still static GitHub Pages, public WebTorrent/Nostr, no TURN, no libp2p, no PWA, no protocol v2.

Test plan

  • npm test (62 tests)
  • npm run build:pages
  • Join 茶 室 from lobby → URL and tab use 茶-室
  • Empty room name does not join
  • Two windows: send, 送达; background a tab during pending ack and confirm it does not immediately fail
Open in Web Open in Cursor 

Failed joins now tear down the transport instead of leaking a zombie connection. Outbound ack timers pause while the tab is hidden, presence prune skips peers still in the ICE set, and inbound payloads dispatch through the router. Room names are canonical at the navigation boundary, empty rooms are rejected, the hash router is a single pipeline, and the log cache snapshots on a debounce. Still v1 wire, static Pages, no TURN.

Co-authored-by: Andy <mail@andychen.net>
@Andyccr
Andyccr marked this pull request as ready for review September 17, 2026 21:07
@Andyccr
Andyccr merged commit 3e7fa0b into main Sep 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants