Repository navigation
fix(discord): prevent duplicate user message processing on auto-thread and reconnects (#51057) - #51153
fix(discord): prevent duplicate user message processing on auto-thread and reconnects (#51057)#51153JoaoMarcos44 wants to merge 3 commits into
Conversation
Duplicate of #51129 — both fix the same #51057 regression where Discord |
tonydwb
left a comment
There was a problem hiding this comment.
Adds cross-adapter message deduplication to prevent duplicate processing when Discord RESUME replays events after reconnects. Also adds content-based dedup with 5-second TTL to catch same user message delivered in multiple Discord contexts (channel vs thread). Good fix for issue #51057. Well-scoped to 2 files.
Reviewed by Hermes Agent
…_init__
Tests using object.__new__(GatewayRunner) skip __init__ and therefore never
set _platform_dedup. The committed dedup check used self._platform_dedup.get()
directly, raising AttributeError in every test that dispatched a message with a
message_id (all e2e tests and many gateway unit tests).
- Made the access defensive via getattr() in _handle_message so any stub runner
that lacks the attribute auto-initialises it on first use.
- Added _platform_dedup = {} to conftest.make_runner to document the expected
attribute alongside the other runner fields.
- Added test_handle_message_defensive_platform_dedup to verify the fallback.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…dapter dedup false-positives The gateway-level _platform_dedup (added for Discord reconnect protection) correctly blocks messages whose message_id was already seen on the same platform. Tests that call _handle_message multiple times with the same hardcoded message_id="m1" were silently getting the second call dropped (returning None), causing assertion failures: test_slash_access_dispatch.py::test_non_admin_with_empty_user_commands_gets_floor_only test_telegram_topic_mode.py::test_topic_root_command_explicitly_migrates_and_enables_topic_mode In production every Discord/Telegram message has a unique snowflake/id. The test event factories should reflect this — each factory call now generates a fresh UUID-based id, matching real-world uniqueness and ensuring the dedup never fires on logically distinct test messages. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Thanks for tackling #51057 as well — closing this in favor of #51129, which fixed the same bug and was submitted first. Both PRs correctly identified the auto-thread starter-message root cause. We went with #51129's approach because it's deterministic: it pre-seeds The content-based dedup here ( Merged fix: #51552 (#51552). Appreciate the thorough write-up and tests! |
What does this PR do?
This PR prevents duplicate processing and double agent runs when a single user message is received in Discord. It addresses two distinct root causes:
auto_threadis enabled, the bot creates a thread for that message. This triggers a secondMESSAGE_CREATEevent for the "thread starter message" withmessage.id == thread.idandtype=0(default). Since the two dispatches represent different contexts (parent channel vs. thread channel), they carry different message (snowflake) IDs. This bypasses the standardmessage.iddeduplication and the message type filter, resulting in two parallel agent runs.DiscordAdapterinstance is initialized, its localself._dedupcache starts empty, failing to block duplicate messages replayed during theRESUMEflow.To resolve these, we implement:
u:{author_id}:{content}) arriving in different contexts.GatewayRunnerwhich persists across adapter re-connections and instances.Related Issue
Fixes #51057
Type of Change
Changes Made
plugins/platforms/discord/adapter.py: Added content-based deduplication usingself._content_dedup = MessageDeduplicator(max_size=500, ttl_seconds=5). Dropped duplicate deliveries (author+content) within 5 seconds.gateway/run.py: Added cross-adapter deduplication usingself._platform_dedupon theGatewayRunnerclass to prevent duplicate processing of the same message ID across adapter restarts.tests/gateway/test_discord_cross_adapter_dedup.py: Added comprehensive unit tests for cross-adapter and content deduplication behavior.How to Test
Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AScreenshots / Logs
Logs of successful test run: