Skip to content

fix(gateway): clean up Discord typing tasks on teardown (resubmit of #23083) - #47222

Open
nazirulhafiy wants to merge 1 commit into
NousResearch:mainfrom
nazirulhafiy:fix/discord-typing-cleanup-v2
Open

fix(gateway): clean up Discord typing tasks on teardown (resubmit of #23083)#47222
nazirulhafiy wants to merge 1 commit into
NousResearch:mainfrom
nazirulhafiy:fix/discord-typing-cleanup-v2

Conversation

@nazirulhafiy

@nazirulhafiy nazirulhafiy commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Fix Discord typing cleanup metadata propagation.

What changed:

  • Forward thread_id metadata through the processing stop path in gateway/platforms/base.py.
  • Keep Discord typing task keys consistent in plugins/platforms/discord/adapter.py.
  • Added regression coverage for thread-scoped typing stop metadata.

Verification:

  • python -m pytest tests/gateway/test_discord_typing_indicator.py tests/gateway/test_keep_typing_timeout.py tests/gateway/test_run_progress_topics.py::test_thread_metadata_is_forwarded_to_processing_stop_typing -q
  • 10 passed

Notes:

  • Temporary typing diagnostics were used to confirm the bug and then removed.
  • The gateway was restarted and the live typing loop now stops cleanly.

@alt-glitch alt-glitch added type/bug Something isn't working comp/plugins Plugin system and bundled plugins platform/discord Discord bot adapter P3 Low — cosmetic, nice to have labels Jun 16, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for preserving the Discord teardown fix from #23083. Current main still keeps Discord typing loops outside the base background-task registry (plugins/platforms/discord/adapter.py:858, :1377-1414, :1442-1483), so that portion is worth salvaging.

Problems

  • The new generic stop_typing(..., metadata=...) calls are incompatible with current overrides that only accept chat_id, including Signal (gateway/platforms/signal.py:1543), Matrix (plugins/platforms/matrix/adapter.py:1709), and Photon (plugins/platforms/photon/adapter.py:1197). Base cleanup suppresses those exceptions (gateway/platforms/base.py:3880-3884, :3908-3913), so this would silently skip cleanup on those platforms.
  • The Discord thread-key premise is stale on current main: Discord builds thread sources with chat_id=str(effective_channel.id) (plugins/platforms/discord/adapter.py:6302-6331), and the current typing implementation keys and stops using that same ID (:3837, :3875-3883).
  • tools/environments/base.py is unrelated to the stated Discord teardown scope.

Suggested changes

  • Salvage the Discord _typing_tasks teardown drain, then either preserve existing override signatures or widen and test every in-tree override before passing metadata generically.
  • Drop the redundant thread-key propagation and split the terminal change for separate review.

This is an automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-broad Sweeper blast radius: broad — a core path most sessions hit labels Jul 14, 2026
The persistent per-channel typing loops spawned by send_typing() are not
tracked by BasePlatformAdapter's message-processing task registry, so on
gateway restart, exception path, or signal handler, they were never
cancelled. The typing endpoint's own 10-second timeout eventually cleared
the indicator on Discord's side, but Hermes would hang in a "typing..."
state for at least that long after every shutdown, with no way to abort
early.

This drains the entire _typing_tasks dict from two teardown points:

1. disconnect() — explicit operator-initiated close. Awaits
   _cancel_typing_tasks before tearing down voice clients and the
   discord.py client, so no in-flight loop survives the close.
2. cancel_background_tasks() — the base adapter's shutdown hook called
   from gateway/run.py on global shutdown. Drains Discord-specific
   tasks first, then defers to super() so the base cleanup still runs.

_cancel_typing_tasks() snapshots the dict, clears it immediately, cancels
each not-done task, and waits up to 2.0s for them to acknowledge the
cancel via asyncio.gather(..., return_exceptions=True). Anything still
alive at 2s logs a warning rather than blocking shutdown indefinitely —
the typing indicator on Discord's side will clear on its own after ~10s
even if the bot process is gone.

Resubmission of NousResearch#23083 (auto-closed 2026-05-27 due to personal files in
the diff). The original 1-file +39-line patch is preserved verbatim in
spirit; only the file path changed because commit cc8e5ec (2026-05-12,
pre-closure) migrated the Discord adapter from gateway/platforms/discord.py
to plugins/platforms/discord/adapter.py as a bundled plugin with full
Teams parity. The bug surface and fix logic are identical to the
original.

Repro path (from the original PR's context): on a healthy gateway, run
/ask in 2+ Discord DMs back-to-back. Force-kill the gateway process
(kill -9) or send SIGTERM. The "Hermes is typing..." indicator in any
chat that had not yet hit its stop_typing() call will linger for ~10s
after the bot process is gone. With this patch, _cancel_typing_tasks
runs from disconnect() and from the shutdown handler before the process
exits, so Discord sees the typing loop end promptly.
@nazirulhafiy
nazirulhafiy force-pushed the fix/discord-typing-cleanup-v2 branch from 7fd538a to 60835c5 Compare July 15, 2026 07:15
@nazirulhafiy

Copy link
Copy Markdown
Contributor Author

Thanks for preserving the Discord teardown fix from #23083. Current main still keeps Discord typing loops outside the base background-task registry (plugins/platforms/discord/adapter.py:858, :1377-1414, :1442-1483), so that portion is worth salvaging.

Problems

  • The new generic stop_typing(..., metadata=...) calls are incompatible with current overrides that only accept chat_id, including Signal (gateway/platforms/signal.py:1543), Matrix (plugins/platforms/matrix/adapter.py:1709), and Photon (plugins/platforms/photon/adapter.py:1197). Base cleanup suppresses those exceptions (gateway/platforms/base.py:3880-3884, :3908-3913), so this would silently skip cleanup on those platforms.
  • The Discord thread-key premise is stale on current main: Discord builds thread sources with chat_id=str(effective_channel.id) (plugins/platforms/discord/adapter.py:6302-6331), and the current typing implementation keys and stops using that same ID (:3837, :3875-3883).
  • tools/environments/base.py is unrelated to the stated Discord teardown scope.

Suggested changes

  • Salvage the Discord _typing_tasks teardown drain, then either preserve existing override signatures or widen and test every in-tree override before passing metadata generically.
  • Drop the redundant thread-key propagation and split the terminal change for separate review.

This is an automated hermes-sweeper review.

Thanks — agreed. I’ve split this down to the Discord teardown fix only:

kept _typing_tasks cleanup on disconnect() and cancel_background_tasks()
removed the generic stop_typing(..., metadata=...) propagation
removed the unrelated tools/environments/base.py change

I also added regression tests for Discord typing-task drain on shutdown/disconnect and verified the existing pending text-batch cleanup still passes.

Pushed as 60835c5 on fix/discord-typing-cleanup-v2.

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

This was generated by AI during triage.

Summary

Three PRs address Discord teardown or adjacent channel-gating failures: #8008 introduced channel-name matching and pending-send flushing, #55525 merged that work with slash-command coverage and a bounded flush deadline, while #47222 separately drains unregistered Discord typing tasks during teardown.

Related pull requests

  • #8008 [closed] related — (+221/-13) — superseded by #55525: It added ID/name/#name matching across message gates and flushed pending text-batch tasks on shutdown; #55525 cherry-picked both fixes with attribution and completed the missing slash-command and timeout-budget handling.
  • #47222 related — (+104/-12) — merge: The current diff narrowly cancels and awaits Discord-owned _typing_tasks from both background-task cleanup and disconnect, with regression coverage, addressing the teardown leak not covered by #55525. This follows the keep_open review on #47222 by salvaging only the Discord typing-task drain; the reviewed stale cross-platform metadata propagation and unrelated environment change are absent from this diff.
  • #55525 [merged] related — (+310/-16) — merged reference implementation: It incorporates #8008's two fixes and extends them to slash-command authorization while keeping the pending-send flush deadline below the adapter teardown budget.

Duplicates

#8008 and #55525 implement substantially the same channel-name matching and pending-send shutdown fix; #55525 is the completed, merged superseding implementation. #47222 is not a duplicate because it handles the separate Discord typing-task registry.

Suggested consolidation

Merge #47222 as the focused remaining Discord typing-task teardown fix; its current diff addresses the contributor's keep_open salvage request without the blocked generic metadata API changes. Keep merged #55525 as the canonical implementation for #8008's work, and leave #8008 closed as superseded by #55525.

Cross-PR triage: Reviewed 3 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 44 kB of PR diffs, 6 kB of issue/PR text, 4 kB of discussion (3 comments), 1 verify verdict. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have platform/discord Discord bot adapter sweeper:blast-broad Sweeper blast radius: broad — a core path most sessions hit sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants