Skip to content

Commit e351230

Browse files
committed
fix(ui): add kv.ready poll timeout and partVersion debounce to prevent Linux TUI freeze
1 parent 6a229f1 commit e351230

1 file changed

Lines changed: 17 additions & 7 deletions

File tree

src/index.tsx

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -633,8 +633,14 @@ function TokenCachePanel(props: {
633633
if (props.api.kv.ready) {
634634
doRestore()
635635
} else {
636+
// Poll kv.ready with a 1-second timeout to avoid infinite busy-wait
637+
// on platforms where kv initialisation may be delayed (Linux single-thread
638+
// mode, session switch storms, etc.).
639+
const MAX_POLL = 100
640+
let tries = 0
636641
const pollRestore = () => {
637642
if (!props.api.kv.ready) {
643+
if (++tries > MAX_POLL) { doRestore(); return }
638644
setTimeout(pollRestore, 10)
639645
return
640646
}
@@ -643,13 +649,17 @@ function TokenCachePanel(props: {
643649
pollRestore()
644650
}
645651

646-
const unsubPart = props.api.event.on("message.part.updated", () => {
647-
setPartVersion((v) => v + 1)
648-
})
649-
const unsubMsg = props.api.event.on("message.updated", () => {
650-
setPartVersion((v) => v + 1)
651-
})
652-
onCleanup(() => { unsubPart(); unsubMsg() })
652+
// Debounce partVersion updates so that event bursts during session
653+
// switching / streaming don't cause data() to re-compute on every
654+
// single event (up to hundreds per second on Linux single-thread).
655+
let partTimer: ReturnType<typeof setTimeout> | undefined
656+
const bumpPartVersion = () => {
657+
clearTimeout(partTimer)
658+
partTimer = setTimeout(() => setPartVersion((v) => v + 1), 100)
659+
}
660+
const unsubPart = props.api.event.on("message.part.updated", bumpPartVersion)
661+
const unsubMsg = props.api.event.on("message.updated", bumpPartVersion)
662+
onCleanup(() => { clearTimeout(partTimer); unsubPart(); unsubMsg() })
653663
})
654664

655665
// ── colours ──

0 commit comments

Comments
 (0)