Получение нескольких уведомлений об одном и том же ответе

Впервые я заметил дублирующее уведомление на один и тот же ответ, когда в отредактированном сообщении не было добавлено ни ссылки, ни цитаты, ни упоминания, после редактирования по адресу Topics from some categories do not appear on /latest - #36 by JammyDodger. Этот случай немного отличается от описанных ниже шагов воспроизведения, но, думаю, корневая проблема та же.

Второе сообщение, где это произошло, находится по адресу Messages section for sidebar - #13 by nathank. Ситуация была похожа: редактирование не добавляло ничего, что могло бы вызвать уведомление — цитаты уже присутствовали ранее — но тем не менее я получил уведомление повторно.

Вот шаги воспроизведения, которые сработали [1]:

Вам понадобятся три пользователя: OP, notifiedUser и spammer.

  1. OP создаёт тему.
  2. notifiedUser отвечает.
  3. OP отвечает на сообщение notifiedUser.
    notifiedUser получает уведомление об ответе (ожидаемое поведение)
  4. spammer отвечает на сообщение notifiedUser. В ответе есть ссылка на другое сообщение от notifiedUser и цитата из сообщения, на которое вы отвечаете. (опционально: можно также добавить @упоминание notifiedUser)
    notifiedUser получает уведомление об ответе (ожидаемое поведение)
    [Если вы добавили @упоминание, уведомление связано с этим упоминанием (ожидаемое поведение)]
  5. notifiedUser читает новые ответы, чтобы пометить уведомления как прочитанные, и переходит в другое место, чтобы не пропустить следующее уведомление.
  6. spammer редактирует свой ответ и исправляет опечатку (или добавляет «edit1»).
    notifiedUser получает уведомление о цитировании (неожиданно: они уже были уведомлены об этом ответе ранее, и цитата там уже была; нет необходимости сообщать им об этом снова)
  7. spammer снова редактирует ответ, чтобы исправить ещё одну опечатку (или добавляет «edit2»).
    notifiedUser получает уведомление о ссылке (неожиданно: они уже были уведомлены об этом ответе ранее, и ссылка там уже была; нет необходимости сообщать им об этом снова)

Видео демонстрирует только финальные шаги 5–7. Spammer находится слева, notifiedUser — справа.


  1. по крайней мере, в большинстве случаев; иногда даже добавление @упоминания в редактировании не вызывает нового уведомления ↩︎

3 лайка

В post_alerter.rb

Измените строки 589–599 с:
 # linked, quoted, mentioned, chat_quoted могут быть отключены, если у вас уже есть уведомление о ответе
 if [
      Notification.types[:quoted],
      Notification.types[:linked],
      Notification.types[:mentioned],
      Notification.types[:chat_quoted],
    ].include?(type)
   if existing_notifications.find { |n| n.notification_type == Notification.types[:replied] }
     return
   end
 end

 На:
 # linked, quoted, mentioned, chat_quoted могут быть отключены, если у вас уже есть любое уведомление об этом
 # сообщении
 if [
      Notification.types[:quoted],
      Notification.types[:linked],
      Notification.types[:mentioned],
      Notification.types[:chat_quoted],
    ].include?(type)
   return if existing_notifications.any?
 end

Это сработает, но я немного беспокоюсь, так как здесь могут проскочить и другие уведомления (например, уведомления от плагинов, которые мы, возможно, хотим отключить).

@lindsey, здесь возникает вопрос по продукту: когда следует отключать уведомление?

Полагаю, что небольшая правка — это шаг вперёд?

Не уверен. Разве это не уведомление о ответе в моём видео? И всё же после этого появляется ещё одно уведомление о цитате и ссылке. Поэтому расширение этого механизма для других типов уведомлений, возможно, не поможет в данном случае. Но, возможно, это покроет другие крайние случаи.

Интересно, не является ли проблемой в моём примере воспроизведения уведомление «2 ответа». Не нарушает ли оно проверку существующих уведомлений от этого ответа, когда ответ редактируется?

В целом, я ожидал бы, что редактирование не вызовет нового уведомления, если все триггеры уже присутствовали в посте, когда я его прочитал ранее. Исправление опечатки, не связанной с упоминанием, ссылкой или цитатой, не должно приводить к новому уведомлению.

Думаю, в случае замены триггера лучше было бы изменить (или заменить) существующее непрочитанное уведомление, чем получать второе. Удаление @упоминания в посте пользователя, чтобы избежать шума, не должно приводить к появлению второго уведомления о цитате. Я ожидал бы, что уведомление о @упоминании исчезнет.

Думаю, единственный случай, когда я хотел бы получить новое уведомление, — это если редактирование добавляет более важный тип уведомления. Например, когда кто-то ссылается на мой пост, а позже вносит правку, которая меня @упоминает, имеет смысл сообщить мне об этом, поскольку они, похоже, говорят уже не о том, что я написал, а обращаются напрямую ко мне. Поскольку редактирование больше не поднимает тему, @упоминания могут быть полезным способом уведомить пользователей о правках.

Я думаю, что Moin описывает идеал с точки зрения пользователя, но, по-моему, нам будет сложно реализовать эту часть:

Возможно, мы могли бы управлять этим для внутриприложенческих уведомлений, но мы не можем отозвать push-уведомления или уведомления по электронной почте. (В целом я не хочу добавлять лишней сложности в систему уведомлений, поэтому, хотя некоторым может подойти разное поведение для внутриприложенческих уведомлений и для email/push, я предпочту отказаться от этой идеи.)

Однако я согласен с этим:

  • Если пост должен уведомить пользователя (например, автор поста цитирует Пользователя А), уведомите соответствующего пользователя (например, Пользователь А получит уведомление о том, что его процитировали).
  • Если редактирование этого поста не меняет того, кого нужно уведомить или почему (например, автор поста исправляет опечатку), никого не уведомляйте.
  • Если редактирование этого поста меняет того, кого нужно уведомить (например, автор поста упоминает Пользователя Б), или почему (например, автор поста упоминает Пользователя А), уведомите затронутых пользователей (например, Пользователь Б получит уведомление об упоминании, Пользователь А тоже получит уведомление об упоминании).

@moin, так ли это?

1 лайк

Да, я закрою здесь свой PR и назову это новой функцией.

В частности, здесь есть пробел:

  • @Moin хотел бы… обновлять старые уведомления
  • @lindsey хотел бы… создавать новые уведомления для новой информации, отредактированной в посте

Полное согласование здесь требует довольно сложного отслеживания… Я оцениваю масштаб изменений, но, честно говоря, пока лучше ничего не делать, так как изменение в итоге окажется очень хрупким.

Определение того, какие упоминания новые, а какие старые, потребует либо парсера (на этом этапе мы не парсим), либо хрупких регулярных выражений.

Переношу это в задачу по новой функции для @Moin и пока закрываю свой PR.

Прежде всего, я не хочу получать ещё одно уведомление, если в сообщении ничего не изменилось и нет повода для уведомления. Исправление опечатки не должно приводить к уведомлению, если я уже был уведомлён, даже если два уведомления по одной теме были свернуты. И я не замечал этого годами, пока это не произошло в декабре.

Я попросил ChatGPT составить краткое изложение того, что он сообщил мне об этой проблеме, когда я пытался найти шаги воспроизведения на основе кода

Краткое содержание: почему обычно предотвращаются дублирующиеся уведомления и почему это не работает в данном случае ИИ

Основная проблема

Предотвращение дублирования полагается на поиск уведомления о ответе, которое всё ещё относится к отредактированному сообщению, но уведомления о ответе сворачиваются, уничтожаются или перепривязываются к другому сообщению.
В результате подавление при редактировании не может надёжно определить, что пользователь уже был уведомлён об ответе.


Дублирующие уведомления предотвращаются в PostAlerter следующим образом:

  1. Отслеживание пользователей, уже уведомлённых при создании сообщения
notified = []
  1. Подавление повторных срабатываний, если существует уведомление о ответе
if [:quoted, :linked, :mentioned, :chat_quoted].include?(type)
  return if existing_notifications.find { |n|
    n.notification_type == Notification.types[:replied]
  }
end

Это должно предотвратить двукратное уведомление пользователя об одном и том же сообщении.

  1. Сворачивание уведомлений о ответе
    Уведомления о ответе (:replied) сворачиваются по теме:
destroy_notifications(user, COLLAPSED_NOTIFICATION_TYPES, topic)

Сохранённое уведомление перепривязывается к:

post = first_unread_post(user, topic)

поэтому уведомление больше не представляет сообщение, которое изначально его вызвало. В результате логика подавления, полагающаяся на совпадение post_number, не может надёжно обнаружить предыдущие уведомления для отредактированных сообщений.


Почему это не работает в случае воспроизведения

В случае воспроизведения:

  • Пользователь получает уведомление об ответе изначально
  • При наличии нескольких ответов уведомления о ответе сворачиваются
  • Свёрнутое уведомление:
    • может больше не существовать для отредактированного сообщения, или
    • существовать с другим post_number
  • При редактировании:
    • логика ответа не выполняется (new_record == false)
    • проверка подавления ищет только уведомление :replied, привязанное к сообщению
    • ничего не найдено → подавление не срабатывает
  • Обнаружение цитат/ссылок выполняется снова и создаёт новые уведомления

С точки зрения пользователя:

«Меня уже уведомляли об этом ответе».

С точки зрения кода:

«Для этого сообщения существующего уведомления нет».

Оба утверждения верны.

Когда я создаю тему, упоминающую моего тестового пользователя в публичной категории, и через несколько минут перемещаю её в приватную категорию, уведомление также удаляется из интерфейса — несмотря на то, что пользователь получил письмо об упоминании @.
Таким образом, уже существуют уведомления внутри приложения, которые удаляются, даже если было отправлено письмо по электронной почте.

Это всё ещё ощущается как ошибка: когда mcwumbly добавляет тег к своей теме, я получаю новое уведомление о том, что мой пост был упомянут. Ссылка уже присутствовала в момент публикации темы, и я уже был уведомлён о цитировании. Ничего не изменилось, кроме тега. Так почему же ожидается, что редактирование вызовет повторное уведомление?

Помимо шагов, описанных в первом сообщении, это также происходит при следующих действиях:

  1. notifiedUser создаёт тему
  2. spammer отвечает, ссылаясь на эту тему. В сообщении по умолчанию есть ссылка, поэтому достаточно добавить @упоминание и цитату.
    → notifiedUser получает уведомление об @упоминании (ожидаемо) и читает тему
  3. spammer добавляет тег к теме
    → notifiedUser получает уведомление о том, что его процитировали в сообщении (неожиданно: уведомление уже было получено, и ничего не изменилось)
  4. spammer редактирует заголовок темы
    → notifiedUser получает уведомление о том, что на него сослались в сообщении (неожиданно: уведомление уже было получено ранее, и само сообщение не изменилось)

2 лайка