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-команда должна быстро подтверждать запрос и независимо завершать тяжелую операцию. Я могу доработать обработчики, очередь, защиту от дублей и наблюдаемость бота.