Skip to content

fix: keep the newer SessionWaiter registration when an older one finishes - #10011

Open
L4XB wants to merge 1 commit into
AstrBotDevs:masterfrom
L4XB:fix/session-waiter-keep-newer-registration
Open

L4XB wants to merge 1 commit into
AstrBotDevs:masterfrom
L4XB:fix/session-waiter-keep-newer-registration

Conversation

@L4XB

@L4XB L4XB commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Motivation / 动机

Fixes #9996. register_wait() can replace the USER_SESSIONS entry of a session_id with a newer SessionWaiter, but the older waiter's _cleanup() always ran USER_SESSIONS.pop(self.session_id, None). So when waiter A finished, timed out or was cancelled after waiter B had registered for the same session, B's entry was removed while B's future was still pending: trigger() could not find B any more and B could only time out. This happens whenever the same user starts an interactive flow twice.

Modifications / 改动点

  • SessionWaiter._cleanup() only removes the registry entry if it still points at the waiter being cleaned up (USER_SESSIONS.get(self.session_id) is self). Removing the filter and stopping the controller are unchanged.
  • New tests/test_session_waiter.py: registering A then B for the same session, stopping A keeps B registered and reachable (trigger() runs B's handler with B's controller), and B still cleans up after itself; plus the plain single-waiter cleanup case. The first test fails on master and passes with the fix.

Verification / 验证

uv run pytest tests/test_session_waiter.py   (2 passed)
ruff check / ruff format --check on the changed files

Checklist / 检查清单

  • 我已经确认了我的更改不会引入新的错误 / I have confirmed my changes do not introduce new errors
  • 我已经添加了必要的测试 / I have added the necessary tests
  • 我已经更新了相关文档 (if needed) / I have updated the relevant documentation (if needed)

Summary by Sourcery

Prevent stale session waiters from removing newer registrations and leaving interactive flows unreachable.

Bug Fixes:

  • Preserve a newer session waiter registration when an older waiter finishes, times out, or is cancelled for the same session.
  • Ensure single-waiter registrations are still removed during cleanup.

Tests:

  • Add coverage for replacement waiter cleanup, triggering the newer waiter, and normal single-waiter cleanup.

…shes

register_wait() lets a newer waiter replace the registry entry of the
same session_id, but the older waiter's _cleanup() popped the entry
unconditionally. When the older waiter finished, timed out or was
cancelled, the newer waiter disappeared from USER_SESSIONS while its
future kept waiting, so trigger() could no longer reach it and it could
only time out.

Only remove the registry entry if it still points at the waiter being
cleaned up.

Fixes AstrBotDevs#9996

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@kilisamemarisaaa kilisamemarisaaa 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.

Reviewed the latest head and the registry race fix is correct.
egister_wait() can replace USER_SESSIONS[session_id], while the older waiter's cleanup previously removed the newer entry unconditionally; the identity guard now preserves the active waiter and still cleans up the single-waiter case. The added tests exercise replacement cleanup, trigger reachability/handler controller identity, and normal cleanup, with fixture isolation for USER_SESSIONS and FILTERS. I found no remaining correctness blockers.

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.

[Bug] 同一 session 注册新等待器后,旧 SessionWaiter 结束会删除新等待器

2 participants