Изменения не сохраняются в таблице user_actions

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

Это ожидаемое поведение или есть какое-то другое условие, которое я упускаю?

Сложно дать пошаговую инструкцию для воспроизведения этой проблемы, но вот как я её обнаружил:

  1. Найдите пост с уведомлением о редактировании:
  2. Выполните запрос к таблице user_actions для заданного acting_user_id (редактора), заданного user_id (редактируемого пользователя) и заданного topic_id. В моём случае:
select * from user_actions ua 
where ua.acting_user_id = 229 
and ua.user_id = 259 
and ua.target_topic_id = 1907;

Вот что я получил:

  • Тип действия 2 означает, что редактируемый пользователь получил лайк от редактора.
  • Тип действия 6 означает, что редактор ответил редактируемому пользователю.
  id   | action_type | user_id | target_topic_id | target_post_id | target_user_id | acting_user_id |         created_at         |         updated_at
-------+-------------+---------+-----------------+----------------+----------------+----------------+----------------------------+----------------------------
 78476 |           2 |     259 |            1907 |          17893 |                |            229 | 2020-03-20 03:39:12.255619 | 2020-03-20 03:39:12.395574
 78478 |           6 |     259 |            1907 |          17900 |                |            229 | 2020-03-20 03:44:04.847102 | 2020-03-20 03:44:04.847102

Я могу подтвердить оба этих действия в интерфейсе, но также ожидал бы найти action_type 11, указывающий на РЕДАКТИРОВАНИЕ.

Помимо видимости редактирования в интерфейсе, я также могу подтвердить его существование в таблице post_revisions, выполнив запрос по target_post_id:

select id, user_id, post_id, number, created_at, updated_at from post_revisions pr where post_id = 17893;

  id  | user_id | post_id | number |         created_at         |         updated_at         |
------+---------+---------+--------+----------------------------+----------------------------+--------
 8927 |     229 |   17893 |      2 | 2020-03-20 03:40:06.644576 | 2020-03-20 03:43:32.769535 |

Так почему же это действие не отображается в user_actions?

Редактирования не предназначены для хранения там; они сохраняются в post_revisions.

Верно, не редактирование. Я имею в виду событие user_action EDIT:

Дело в том, что оно срабатывает в 90% случаев. Я не понимаю, почему в остальных 10% оно не работает.

Я только что осознал, что либо я до конца не понимаю случаи, когда создаётся уведомление об редактировании, либо это гораздо более распространённая проблема, чем я думал.

Основные предположения

Если пользователь А редактирует то, что написал пользователь Б, происходит следующее:

  • В таблицу post_revisions добавляется новая строка.
  • В таблицу user_actions добавляется новая строка с action_type = 11.
  • Перейдя по адресу /u/userB/notifications/edits, пользователь Б сможет увидеть, что новое редактирование выполнил пользователь А (это зависит от user_actions).
  • Нажав на значок карандаша в своём посте, пользователь Б сможет увидеть само редактирование, выполненное пользователем А (это зависит от post_revisions).

Тест

Если вышеуказанные предположения верны, этот запрос должен показать все строки в таблице post_revisions для постов, созданных пользователем Б (в данном случае id 259), которые были отредактированы любым пользователем (кроме него самого или системного пользователя), вместе с соответствующими строками в user_actions для action_type = 11.

with my_user_posts as (
  select
    p.id,
    p.user_id
  from
    posts p
  where
    p.user_id = 259 -- выберите id пользователя
)
select
  up.user_id as my_user_id,
  ua.user_id as target_user_id,
  pr.post_id,
  ua.target_post_id,
  pr.user_id as editor_user_id,
  ua.acting_user_id,
  ua.action_type,
  pr.created_at as edit_created_at,
  ua.created_at as action_created_at
from
  post_revisions pr
  inner join my_user_posts up on up.id = pr.post_id
  and up.user_id != pr.user_id -- исключим само редактирование
  and pr.user_id != -1 -- исключим системные редактирования
  left join user_actions ua on ua.target_post_id = pr.post_id
  and ua.action_type = 11 -- только действия EDIT
order by
  pr.post_id,
  pr.created_at;

Ожидаемый результат

Каждая строка должна содержать как данные post_revisions, так и данные user_actions.

Фактический результат

Некоторые строки post_revisions не имеют соответствующих данных в user_actions. Следовательно, пользователь может увидеть ревизии, нажав на карандаш в каждом посте, но не получил уведомлений о нескольких редактированиях.

Что я пробовал

  • Добавление дополнительного редактирования к старому посту, у которого нет данных user_action. Результат: данные user_action также не появились.
  • Создание фейкового пользователя, копирование содержимого поста до редактирования, у которого нет данных user_action, создание с ним нового поста и применение того же редактирования, которое было выполнено другим пользователем. Результат: данные user_action появились корректно.
  • Повторение вышеуказанных процедур, когда пользователь активен или офлайн. Результат: изменений нет.
  • Повторение вышеуказанных процедур с изменением периода прощения при редактировании. Результат: изменений нет.

Выводы

  • Проблема, по-видимому, не является:

    • специфичной для пользователя. Она возникает практически у каждого пользователя.
    • специфичной для подключения. Тот факт, что пользователь активен или офлайн, не влияет на результат.
    • специфичной по времени. Изменение периода прощения при редактировании не оказало эффекта.
  • Проблема, по-видимому, является:

    • специфичной для действия. Я не видел никаких проблем с уведомлением о других действиях (LIKE, WAS_LIKED, RESPONSE, REPLY, MENTION или QUOTE). Единственная проблема касается действий EDIT.

    • специфичной для поста. Она возникает не у каждого поста, а только у некоторых (кажется, случайно).

  • Возможно, что при создании определённых постов что-то происходит, что препятствует сохранению user_actions для EDIT, но я не представляю, что это может быть.

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

Следующие шаги

  • Если вы знаете причину, по которой уведомления о редактировании могут не срабатывать каждый раз при редактировании, пожалуйста, сообщите об этом.
  • Если у вас есть собственный экземпляр Discourse, могли бы вы выполнить вышеуказанный SQL-запрос на некоторых id пользователей, чтобы проверить, видите ли вы также отсутствующие данные user_actions, и сообщить результаты?

Я просто хочу на 100% убедиться, что вы чётко понимаете, как работают периоды для редактирования, которые продолжают действовать даже в случае, если пост редактирует другой пользователь.

(Да, если пользователь A редактирует пост пользователя B, всегда создаётся принудительная ревизия редактирования. Однако это не означает, что если пользователь A отредактирует пост пользователя B 6 раз за 60 секунд, будет создано 6 ревизий и 6 уведомлений. Как видно на скриншоте выше, будет создана только одна ревизия и одно уведомление.)

Отстоят ли каждое из этих редактирований друг от друга более чем на 5 минут?

Спасибо за комментарий, Джефф. Я могу подтвердить, что да, эти правки сделаны с интервалом более 5 минут. Но даже если бы это было не так, если создается хотя бы одна запись post_revision, разве всегда не должно быть сопровождающего действия пользователя EDIT?

Кстати, я также попробовал установить период прощения для редактирования в 0, и при этом для каждого изменения создаются две идентичные записи post_revision. Не знаю, является ли это задумкой разработчиков или это несвязанный баг.

Просто хотел убедиться в этом, хорошо, что подтвердили.

Мог бы кто-нибудь выполнить вышеуказанный запрос на своём сайте Discourse, чтобы проверить, есть ли у них post_revisions без соответствующих user_actions типа 11?

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

Спасибо, Сэм. Я ожидал именно этого, но на моём сайте (по крайней мере) ситуация иная. Как видно из результатов моего запроса, в некоторых случаях пользователь A редактирует пост пользователя B (что добавляет строку в post_revisions), но соответствующей строки в user_actions (с action_type 11) нет. Вот этого я не понимаю.

Есть ли у вас воспроизведение проблемы, или это разовый случай?

Это происходит постоянно и периодически с тех пор, как я создал свой сайт. Как я уже упоминал выше, мне не удаётся выявить закономерность.

Если есть возможность предоставить дамп данных или вам нужна какая-либо другая информация, я с радостью помогу.

Чтобы я был уверен, что правильно понял: вы сообщаете о следующей ошибке:

При определённых условиях пользователь A редактирует пост пользователя B, но пользователь B не получает уведомление?

Точно. Уведомление не отображается здесь и в блоке пользователя (поскольку оба зависят от user_actions):

Однако оно отображается в правом верхнем углу поста (поскольку это зависит от post_revisions):

Я написал запрос для проверки этого. Если вы запустите его на своём сайте (с другими ID пользователей), вы тоже увидите пропуски.

Это экземпляр, размещённый нами, или самоподдерживаемый экземпляр?

Наше уведомление срабатывает здесь:

Условие довольно строгое:

Уведомление создаётся здесь:

Что может нарушить этот процесс:

  1. Очередь Sidekiq перегружена задачами или приостановлена.

  2. Крайне редкое условие прерывания задачи на полпути при отправке уведомления.

Я могу привести конкретный пример на хостинге, управляемом вами.

Этот пост (id 1067), созданный пользователем 3 2019-08-03 19:22 UTC, был отредактирован мной (пользователь 2) через несколько минут после создания.

Однако не было создано записи user_action типа 11 (в отличие от двух других правок, которые этот пользователь получил в тот же день для постов 1001 и 1003)

Вы можете увидеть это более наглядно, выполнив следующий запрос:

with my_user_posts as (
  select
    p.id,
    p.user_id
  from
    posts p
  where
    p.user_id = 3 -- выберите id пользователя
)
select
  up.user_id as my_user_id,
  ua.user_id as target_user_id,
  pr.post_id,
  ua.target_post_id,
  pr.user_id as editor_user_id,
  ua.acting_user_id,
  ua.action_type,
  pr.created_at as edit_created_at,
  ua.created_at as action_created_at
from
  post_revisions pr
  inner join my_user_posts up on up.id = pr.post_id
  and up.user_id != pr.user_id -- исключая самоправки
  and pr.user_id != -1 -- исключая системные правки
  left join user_actions ua on ua.target_post_id = pr.post_id
  and ua.action_type = 11 -- только действия EDIT  
WHERE
  pr.created_at between '2019-08-03' and '2019-08-04'
order by
  pr.post_id,
  pr.created_at

Я провёл некоторые расчёты, и в зависимости от даты от 7% до 25% правок постов (post_revisions), не являющихся самоправками, не имеют соответствующей записи user_action.

Возможно, у нас всё-таки есть ошибка здесь, @Nacho_Caballero. Оставайтесь на связи. Спасибо за настойчивость в этом вопросе.

У нас была эта ошибка:

А затем я улучшил реализацию с помощью этой функции:

Существовал пограничный случай: когда пользователь ставил лайк посту другого пользователя, а затем редактировал его, уведомление об изменении не отправлялось.

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

Отлично. Это имеет большой смысл. Большое спасибо за исправление!