Skip to content

fix(dingtalk): serialize inbound messages per chat session - #17366

Open
spike2204 wants to merge 1 commit into
NousResearch:mainfrom
spike2204:fix/dingtalk-inbound-queue
Open

fix(dingtalk): serialize inbound messages per chat session#17366
spike2204 wants to merge 1 commit into
NousResearch:mainfrom
spike2204:fix/dingtalk-inbound-queue

Conversation

@spike2204

Copy link
Copy Markdown

Summary

When a user sends multiple messages rapidly (or sends text + file in quick succession), the adapter processes them concurrently, causing race conditions in AI Card lifecycle management — cards from message N clobber cards from message N+1.

Changes

  • Add _enqueue_inbound() — per-chat asyncio.Queue with configurable max depth (default 32)
  • Add _sweep_session_queues() — periodic cleanup of idle session queues (>30min)
  • Route all _on_message() calls through the per-chat queue so messages within the same conversation are processed sequentially while different conversations remain concurrent

Related

Part of the DingTalk adapter enhancement series — see #12769 for the umbrella PR.

…ate agent turns

When the agent is busy processing a message, a second inbound message
for the same chat spawns a parallel turn, producing duplicate or
interleaved replies.

- Add _enqueue_inbound() / _sweep_session_queues() — promise-chain
  queue per chat that serializes message processing
- Send a random busy-ACK phrase for queued messages so the user knows
  their message was received
- Queue entries auto-expire after 5 minutes (matches openclaw-connector
  core/message-handler.ts:92)
- Sweeper task runs every 60s to clean stale queue entries
- Proper cleanup on disconnect (cancel pending tasks) to #
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/dingtalk DingTalk adapter labels Apr 29, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for isolating the same-chat concurrency concern. The issue remains relevant on current main, but this implementation needs rework after the adapter migration.

Problems

  • plugins/platforms/dingtalk/adapter.py:640 stores the latest inbound message per chat, while :863 reads that mutable value for AI Card routing. A second callback can overwrite it while the first turn is still running.
  • The proposed chain would await _on_message(), but gateway/platforms/base.py:4779 starts _process_message_background() and returns. It therefore does not wait for the agent turn that performs card sends, so it cannot protect the mutable context above.
  • The PR targets the removed gateway/platforms/dingtalk.py; current code lives in plugins/platforms/dingtalk/adapter.py after 5600105.

Suggested changes

  • Rework the fix in the plugin adapter around turn-scoped card context or the BasePlatformAdapter session lifecycle, and add a two-message same-chat regression test that holds the first turn active.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform area/sessions Session lifecycle, resume, persistence, history labels Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sessions Session lifecycle, resume, persistence, history comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists platform/dingtalk DingTalk adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants