perf(discord): build reply references from ids instead of fetch_message - #76357
perf(discord): build reply references from ids instead of fetch_message#76357spfcraze wants to merge 1 commit into
Conversation
Every reply paid one extra Discord API round trip: the text send path, the voice send path, and the edit path each called fetch_message() just to obtain a reference or an editable handle. Discord resolves message_reference payloads from ids alone, and PartialMessage.edit() works without a fetch — so build MessageReference directly (with fail_if_not_exists=False, preserving the deleted-target behavior the existing send-side 10008 retry already covered) and use channel.get_partial_message() for edits. Overflow continuations keep threading via an ids-built reference fallback for PartialMessage. Measured by call count (deterministic): reply sends and edits now make ZERO fetch_message calls where they made 1 per reply and 1 per edit (including every streaming edit tick). Tests: pin that first-mode replies construct the reference without any fetch, deleted-target retry test updated to assert fetch await_count==0 (retry now happens purely send-side), overflow/edit mocks retargeted from fetch_message to get_partial_message (any fetch regression breaks all five). Note: 4 discord-suite failures are pre-existing ordering flakes — identical with the change stashed on clean main.
|
Thanks for the focused Discord performance improvement. Current main still performs the three redundant fetches at Automated hermes-sweeper review. |
|
Thanks @spfcraze — verified end-to-end (byte-identical wire payloads against discord.py 2.7.1 source, all 7 send/edit paths audited, mutation-checked) and salvaged into #76875 with your authorship preserved via cherry-pick, plus a small refactor follow-up (shared reference-builder helper + a comment correction). Closing in favor of the salvage. |
…lMessage comment Review follow-ups on the #76357 salvage: - _message_reference_from_ids + _reply_reference_for_send collapse the 3x duplicated MessageReference construction (naming mirrors telegram's _reply_to_message_id_for_send). - The overflow elif's comment claimed PartialMessage has no to_reference; discord.py 2.7.1's PartialMessage does (message.py L1901) — the branch is belt-and-suspenders for duck-typed priors, now labeled as such.
…lMessage comment Review follow-ups on the NousResearch#76357 salvage: - _message_reference_from_ids + _reply_reference_for_send collapse the 3x duplicated MessageReference construction (naming mirrors telegram's _reply_to_message_id_for_send). - The overflow elif's comment claimed PartialMessage has no to_reference; discord.py 2.7.1's PartialMessage does (message.py L1901) — the branch is belt-and-suspenders for duck-typed priors, now labeled as such.
What does this PR do?
Every Discord reply paid one extra API round trip: the text send path, the voice send path, and the edit path each called fetch_message() just to obtain a reference or an editable handle. Discord resolves message_reference payloads from ids alone and PartialMessage.edit() needs no fetch, so build MessageReference directly (fail_if_not_exists=False preserves the deleted-target behavior the send-side 10008 retry already covered) and use channel.get_partial_message() for edits. Overflow continuations keep threading via an ids-built reference fallback for PartialMessage.
Related Issue
No GitHub issue — discovered via code review and reproduced live (see below). Happy to file one first if preferred.
Changes Made
fix/discord-reply-fetch— 4 file(s) changed vs base:plugins/platforms/discord/adapter.pytests/gateway/test_discord_edit_message_overflow.pytests/gateway/test_discord_reply_mode.pytests/gateway/test_discord_send.pyplugins/platforms/discord/adapter.py: 3 sites (text reply, voice reply, edit path) + an ids-built reference fallback in _edit_overflow_split so PartialMessage continuations stay threaded. Tests: new first-mode no-fetch pin in test_discord_reply_mode.py; deleted-target retry test now pins fetch await_count==0 (retry happens purely send-side); overflow/edit mocks retargeted from fetch_message to get_partial_message so any fetch regression breaks all five; reply_mode harness cleaned of the dead fetch setup and its stale comments. Note: 4 discord-suite failures are pre-existing ordering flakes, identical with the change stashed on clean main. Adjacent: #75945 and #75633 touch the line after the edit-path fetch — trivial rebase either way, no semantic overlap.
How to Test
Measured by call count (deterministic — API RTTs vary): reply sends and edits made 1 fetch_message call each (plus 1 per streaming edit tick); after the change they make zero. At a typical 30-150 ms Discord RTT that is one avoided blocking round trip per reply and per edit tick.
Validation completed (recorded by prp):
tests/gateway/test_discord_reply_mode.py.tests/gateway/: branch 4512 passed / 6 failed vs baseline 4509 passed / 6 failed — zero branch-only failures.Logs
Sabotage verification output: