Skip to content

修正:投票投影片端斷線後重送目前這頁的開題/離開狀態 - #6

Merged
keanu77 merged 2 commits into
mainfrom
fix/poll-resend-on-reconnect
Oct 19, 2026
Merged

keanu77 merged 2 commits into
mainfrom
fix/poll-resend-on-reconnect

Conversation

@keanu77

@keanu77 keanu77 commented Oct 19, 2026

Copy link
Copy Markdown
Owner

補上 #5 留下的缺口:斷線超過 5 秒時,開題/離開的 /api/control 會逾時,之後沒有任何重送,所以網路恢復後,後端(和觀眾手機)可能還停在舊的題目,或根本沒開題。

修改內容(只動 screen/live-poll.js,docs/index.html 重新 build)

  • 退避重送目前這頁:開題/離開失敗(navFail)後,依 1、2、4、8 秒退避重送,上限 15 秒、最多 8 次(約 75 秒),不會密集重試。重送時讀的是當下這一頁的狀態:投票頁就重跑 enterPoll(先查結果,已揭曉的題就送 revealed),非投票頁就送 {poll:null}。
  • 網路恢復立即重送:online 事件或螢幕端 WebSocket 重新連上時,如果有待重送的狀態就馬上送出,不必等退避;8 次用完之後,網路恢復也會再送一次。
  • 只送最新狀態:每次重送都綁定 navSeq,講者換頁後舊的重送就作廢,由新的那頁自己送。
  • 揭曉(A)與清空(Shift+R)不重送:維持原本的行為。
  • 順便修一個漏洞:用 navDone 記錄後端最後確認的換頁序號。原本斷線時連過兩張非投票頁,第一張的「離開」排隊時被當成過期略過,第二張又因為 current 已經是 null 而不送,後端就一直停在上一題。現在只要上一頁的狀態還沒確認,非投票頁也會送出「離開」。
  • ?offline/QA(webdriver)模式不排重送,畫面訊息和原本一樣。
  • CHANGELOG 的 Unreleased 補一行。

驗證(本機)

  • CI 的 Syntax checks 整段在 Node 20.19.2 下跑過:全部 node --check、demo 模擬模式/不含 key 檢查、polls.json、py_compile、bash -n、ruff check 都通過
  • worker node --test test/stats.test.js:3 項通過
  • demo npm run qa(離線模式 QA):12 頁通過,沒有溢出、沒有 JS 錯誤,QR 全部相符
  • Playwright 修正前後對照(修正前=main)。/api/control 在斷線期間不回應(客戶端 5 秒逾時),表格列出後端實際收到的請求:
情境 main 這個 PR
A:斷線 0–8 秒,連換多頁,最後停在 size 只有逾時的 warmup open、size open,最後後端 active=null,沒有開題 11.1 秒重送 size open 成功,後端 active="size";過期的 warmup/null 沒有補送
B:斷線 0–8 秒,從 warmup 離開,最後停在非投票頁 {poll:null} 逾時後就沒有下文 11.1 秒重送 {poll:null} 成功
C:warmup 已開;斷線 0.5–8.5 秒時連過兩張非投票頁 後端一直停在 active="warmup" 12.0 秒送出 {poll:null} 成功,後端 active=null
D:warmup 已開;斷線時按 A 揭曉逾時,不重送 一樣不重送(揭曉不在重送範圍內)
E:瀏覽器離線 0.5–9.5 秒後恢復(online 事件) 不會送出「離開」 9.5 秒恢復時立即送出 {poll:null}

請審閱,不要自動合併。

控制請求逾時後以退避(上限 15 秒、最多 8 次)重送目前這頁的狀態,
online 事件或 WebSocket 重連時立即重送;換頁即作廢舊重送,揭曉/清空不重送。
另以 navDone 追蹤後端已確認的換頁,修正斷線時連過兩張非投票頁、後端停在上一題。
重新 build docs/index.html。
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-19T12:39:49.295325Z c383a20 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c383a20455

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +115 to +116
clearTimeout(navTimer); navWait = seq; navBad = true;
if (navTry < 8) navTimer = setTimeout(() => navResend(seq), Math.min(15000, 1000 * 2 ** navTry++));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reset the retry budget when the slide changes

When an outage consumes retries on one slide and the presenter then navigates, navTry retains the previous slide's count because it is reset only after success or an online/WebSocket-open event. If it has already reached 8, the new slide's first failed request sets navWait but schedules no retry here; when the browser remains online and the existing WebSocket stays open (for example, a transient HTTP/control-path failure), recovery emits neither event, so the backend can remain on the old poll indefinitely. Reset the counter when starting a new navigation sequence.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已在 615fa50 修正:onShow 每次換頁都會把 navTry 歸零,所以每一頁各有 8 次重送額度。已用 Playwright 驗證:WebSocket 一直開著、瀏覽器也在線,只有 /api/control 回 500。先在 warmup 用完 8 次重送,再換到非投票頁。修正前,{poll:null} 失敗 1 次之後就不再送,後端停在舊題;修正後會持續退避重送,控制路徑恢復後就送成功,後端 active=null。

上一頁斷線用完 8 次後換頁,新頁失敗不會再排重送;在網路與 WebSocket 都正常、
只有控制路徑失敗時,後端可能一直停在舊題。改在 onShow 重設 navTry。
@keanu77
keanu77 merged commit 68b0028 into main Oct 19, 2026
2 checks passed
@keanu77
keanu77 deleted the fix/poll-resend-on-reconnect branch October 19, 2026 13:57
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.

1 participant