-
Notifications
You must be signed in to change notification settings - Fork 1
✨ feat: Add duplicate LLM request prevention #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Implement request tracking to prevent duplicate LLM API calls when users click translation/inspiration buttons multiple times. Uses tuple-based tracking with (user_id, problem_id, request_type) to ensure proper request isolation. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Add asyncio.Lock for thread-safe request tracking - Replace remove() with discard() to prevent KeyError - Extract duplicate logic into reusable helper methods - Add comprehensive unit tests for concurrency scenarios 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive documentation for the new test_interaction_handler.py file, including detailed descriptions of all 8 test cases and instructions for running the tests. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Replace direct discard() calls with _cleanup_request() method to prevent race conditions. All modifications to ongoing_llm_requests set now go through lock-protected methods. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a mechanism to track and prevent duplicate LLM requests in the Discord bot and adds comprehensive tests and documentation for this feature.
- Add
ongoing_llm_requestsset with anasyncio.Lockto serialize check-and-add in handlers - Augment translation and inspiration branches with duplicate-request checks and proper cleanup in
finallyblocks - New async tests (
test_interaction_handler.py) and updatedtests/README.mdfor running interaction handler tests
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| tests/test_interaction_handler.py | New async test suite covering duplicate prevention, cleanup, and concurrency |
| tests/README.md | Document new tests and commands for running interaction handler tests |
| cogs/interaction_handler_cog.py | Implement duplicate-request lock, prevention logic, and cleanup |
Comments suppressed due to low confidence (2)
tests/README.md:104
- [nitpick] The command
uv run pytestseems incorrect; consider updating it to a standardpytest tests/test_interaction_handler.py -vinvocation for clarity.
uv run pytest tests/test_interaction_handler.py -v
cogs/interaction_handler_cog.py:152
- Consider adding a unit test that verifies
_cleanup_requestis called when serving cached translations, ensuring that the request is removed from tracking after a cached response.
await self._cleanup_request(request_key)
| await interaction.followup.send(translation, ephemeral=True) | ||
| # Remove from ongoing requests when returning cached result | ||
| await self._cleanup_request(request_key) | ||
| return |
Copilot
AI
Jul 7, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This inline cleanup call is redundant since the final finally block performs cleanup as well; consider removing branch-specific cleanup to simplify the flow.
| await interaction.followup.send(translation, ephemeral=True) | |
| # Remove from ongoing requests when returning cached result | |
| await self._cleanup_request(request_key) | |
| return | |
| await interaction.followup.send(translation, ephemeral=True) | |
| return |
| # tests/test_interaction_handler.py | ||
| import pytest | ||
| import asyncio | ||
| from unittest.mock import MagicMock, AsyncMock, patch |
Copilot
AI
Jul 7, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The patch import is not used in this file; consider removing it to clean up unused imports.
| from unittest.mock import MagicMock, AsyncMock, patch | |
| from unittest.mock import MagicMock, AsyncMock |
| import discord | ||
| from discord.ext import commands | ||
| import time | ||
| import asyncio | ||
| from leetcode import html_to_text # 確保這個 import 存在 | ||
| # from utils.logger import get_logger # 使用 bot.logger |
Copilot
AI
Jul 7, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Imports could be reorganized to follow PEP8 ordering (e.g., place import asyncio before import time) for consistency.
| import discord | |
| from discord.ext import commands | |
| import time | |
| import asyncio | |
| from leetcode import html_to_text # 確保這個 import 存在 | |
| # from utils.logger import get_logger # 使用 bot.logger | |
| import asyncio | |
| import time | |
| import discord | |
| from discord.ext import commands | |
| from leetcode import html_to_text # 確保這個 import 存在 | |
| # from utils.logger import get_logger # 使用 bot.logger |
The finally block in Python always executes even after return statements, so explicit cleanup calls before returns are redundant. Keep only the cleanup in finally blocks to avoid duplicate lock acquisitions. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Summary
Test plan
🤖 Generated with Claude Code