Discord ожидает быстрое подтверждение interaction. Если обработчик сначала обращается к внешнему API, строит отчет или ждет базу, токен может истечь, а пользователь увидит ошибку «приложение не ответило».
Разделите подтверждение команды и тяжелую работу. Сразу отправьте defer, а результат верните editReply или followUp после завершения вычисления.
Что сделать в первую очередь
- Измерьте время от получения interaction до первого ответа.
- Найдите синхронные операции и внешние запросы до reply или defer.
- Проверьте, не отвечает ли один обработчик на interaction дважды.
- Сохраните correlation id для команды и фоновой задачи.
Почему возникает проблема
Симптом обычно появляется не из-за одной настройки. Сначала разделите путь данных на этапы и найдите место, где фактическое поведение расходится с ожидаемым.
- Медленный запрос к API выполняется до deferReply.
- Событие ждет свободного worker в перегруженном процессе.
- Исключение перехватывается, но пользовательский ответ не отправляется.
- Несколько экземпляров бота одновременно обрабатывают одну interaction.
Пошаговая диагностика
- Добавьте метки времени received, acknowledged, started и completed.
- Проверьте p95 и p99 задержки базы и внешних сервисов.
- Найдите блокирующие операции в основном event loop.
- Сопоставьте interaction id с числом попыток обработки.
- Проверьте путь ошибки и наличие editReply после defer.
Как исправить
Исправляйте подтвержденную первопричину и сохраняйте возможность отката. После каждого изменения повторяйте один и тот же контрольный сценарий, чтобы не спутать результат нескольких правок.
- Вызывайте deferReply сразу для потенциально долгих команд.
- Перенесите тяжелую работу в очередь и обновляйте отложенный ответ.
- Ограничьте время внешних запросов и добавьте понятный fallback.
- Защитите interaction id уникальным ключом от параллельной обработки.
- Отправляйте короткое сообщение об ошибке, если задача завершилась неуспешно.
Как проверить результат
- Команда подтверждается быстро даже при медленном внешнем API.
- Один interaction создает ровно один основной ответ.
- Ошибки фоновой задачи обновляют сообщение, а не пропадают в журнале.
Как не допустить повторения
- Мониторьте время до ACK отдельно от полной длительности команды.
- Нагрузочно тестируйте самые тяжелые slash-команды.
- Используйте ограниченную очередь и сообщайте пользователю о перегрузке.
Частые вопросы
Можно ли всегда использовать deferReply?
Да, для долгих команд это нормально, но быстрые команды лучше отвечают сразу и дают более живой интерфейс.
Почему появляется Unknown interaction после defer?
Обычно код пытается повторно вызвать reply, использует старый токен или слишком поздно отправляет follow-up.
Когда стоит обратиться за помощью
Если задержка появляется только под нагрузкой, нужны метрики event loop, очереди и времени внешних зависимостей. Это позволяет исправить архитектуру, а не просто увеличить ресурсы.
Итог
Discord-команда должна быстро подтверждать запрос и независимо завершать тяжелую операцию. Я могу доработать обработчики, очередь, защиту от дублей и наблюдаемость бота.