Edits not being stored in user_actions table

I thought that every time a user edits someone else’s post, this action would be recorded in the user_actions table, but I’ve just realized this only happens sporadically (only for some users some of the time).

Is this the intended behavior or is there another condition I’m not considering?

It’s hard to give a step-by-step to reproduce this issue, but this is how I detected it:

  1. Find a post with an edit notification:
    image
  2. Query user_actions for the given acting_user_id (the editor), the given user_id (the edited) and the given topic_id. In my case:
select * from user_actions ua 
where ua.acting_user_id = 229 
and ua.user_id = 259 
and ua.target_topic_id = 1907;

This is what I get:

  • Action type 2 means that the edited user received a LIKE from the editor.
  • Action type 6 means that the editor responded to the edited user.
  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

I can confirm both of these actions in the UI, but I would also expect to find an action_type 11 indicating the EDIT.

Besides seeing the edit in the UI, I can also confirm its existence in the post_revisions table querying using the 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 |

So, why doesn’t this action show up in user_actions?

1 Like

Edits are not meant to be stored there, they are stored in post_revisions.

2 Likes

Right, not the edit. I mean the user_action EDIT event:

https://github.com/discourse/discourse/blob/master/app/models/user_action.rb#L19

The thing is that it’s triggered 90% of the time. I don’t understand why it doesn’t work the other 10%

1 Like

I just realized that either I don’t fully understand the cases where an edit notification is created or this is a much more widespread problem than I thought.

Main assumptions

If User A edits what User B wrote, several things happen:

  • A new row gets added to the post_revisions table.
  • A new row gets added to the user_actions table with action_type = 11.
  • By going to /u/userB/notifications/edits, User B will be able to see that a new edit was made by User A (this depends on user_actions).
  • By clicking on the pencil icon in his post, User B will be able to see the actual edit that User A performed (this depends on post_revisions).

Test

If the above assumptions are correct, this query should show all the rows in the post_revisions table for posts created by User B (in this case, id 259) that were edited by any user (other than himself, or the system user), along with the corresponding rows in user_actions for action_type = 11.

with my_user_posts as (
  select
    p.id,
    p.user_id
  from
    posts p
  where
    p.user_id = 259 -- choose a user 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 -- no self edits
  and pr.user_id != -1 -- no system edits
  left join user_actions ua on ua.target_post_id = pr.post_id
  and ua.action_type = 11 -- only EDIT actions
order by
  pr.post_id,
  pr.created_at;

Expected output

Every row has both post_revisions data along with user_actions data.

Actual output

Some of the post_revisions rows doesn’t have matching user_actions data. Therefore, the user can see the revisions by clicking on the pencil in each post, but wasn’t notified about receiving several edits.

Things I’ve tried

  • Adding an additional edit to an old post without user_action data. Result: the user_action data also did not appear.
  • Creating a fake user, copying the pre-edit content of a post without user_action data, creating a post with it and applying the same edit that was done with a different user. Result: the user_action data appeared correctly.
  • Repeating the above procedures when the user is active or offline. Result: no change.
  • Repeating the above procedures changing the editing grace period. Result: no change.

Conclusions

  • The issue doesn’t appear to be:

    • user-specific. It happens to practically every user.
    • connection-specific. The fact that the user is active or offline doesn’t change the output.
    • time-specific. Changing the editing grace period had no effect.
  • The issue appears to be

    • action-specific. I have not seen any issues notifying any of the other actions (LIKE, WAS_LIKED, RESPONSE, REPLY, MENTION or QUOTE). The only problem is with EDIT actions.

    • post-specific. It doesn’t happen to every post, only specific ones (seemingly at random)

  • One possibility is that something is happening during the creation of specific posts to prevent EDIT user_actions from being saved, but I have no idea what this could be.

  • It’s also possible that this is happening by design and that there are specific conditions under which users are not notified of edits, but I haven’t seen this documented anywhere.

Next steps

  • If you know a reason why edit notifications might not get triggered every time there is an edit, please let me know.
  • If you have your own Discourse instance, could you run the above SQL query on some of your user ids to see if you also see missing user_actions data and report back?
1 Like

I just want to be 100% sure you’re clear about edit grace periods, which would still apply even if there is a different user editing the post.

(Yes, if user A edits user B’s post, there is always a forced edit revision, but that doesn’t mean that if user A edits user B’s post 6 times in 60 seconds, there are 6 revisions and 6 notifications created. There will be only one revision and one notification, as you can see in the above screenshot.)

Are each of these edits more than 5 minutes apart?

2 Likes

Thanks for the comment, Jeff. I can confirm that yes, these edits are more than 5 minutes apart. But even if they weren’t, as long as a single post_revision gets created, shouldn’t there ALWAYS be an accompanying EDIT user_action?

As a side note, I also tried changing the editing grace period to 0 and when I do that, 2 identical post_revisions are created for every change. I don’t know if this is by design or if it’s an unrelated bug.

Just making sure about that, good to confirm.

1 Like

Could someone run the above query on their Discourse site to see if they also get post_revisions without corresponding user_actions of type 11?

Digging through our code I think you only get user_action type 11 if you edit someone elses post or trigger a notification regarding the edit in some other way.

3 Likes

Thanks, Sam. That’s what I was expecting, but it’s not what I’ve found (on my site, at least). As you can see from the results of my query, in some cases, user A edits a post by user B (which adds a row in post_revisions), but there is no corresponding row in user_actions (with action_type 11). That is what I don’t understand.

Do you have a repro of the issue, is it a once off?

1 Like

It’s been happening continually and sporadically since I started my site. I haven’t been able to see the pattern as I mentioned above.

If there is a way I can provide you with a data dump or you need any other information, I’m happy to help.

Just so I am clear the actual bug you are reporting here is:

Under some conditions User A edits a post of User B and User B is not notified?

1 Like

Exactly. The notification does not show up here or in the user box (since both depend on user_actions):

However, it does show up in the top right corner of the post (since that depends on post_revisions):

image

I wrote a query to test this. If you run it on your site (with different user ids), you should also see gaps.

1 Like

Is this an instance hosted by us or a self hosted instance?

Our notification fires here:

https://github.com/discourse/discourse/blob/776caa24c9454b67fd0d2c3737263c126eb3b557/app/services/post_action_notifier.rb#L117-L127

The condition is quite strong:

https://github.com/discourse/discourse/blob/776caa24c9454b67fd0d2c3737263c126eb3b557/app/services/post_action_notifier.rb#L104-L106

Notification is created here:

https://github.com/discourse/discourse/blob/776caa24c9454b67fd0d2c3737263c126eb3b557/app/jobs/regular/notify_post_revision.rb#L11-L24

The thing that could break this is

  1. Sidekiq being backed up with jobs or paused

  2. Super rare condition of terminating the job half way through notifying

2 Likes

I can give you a specific example in an instance hosted by you.

This post (id 1067) created by user 3 on 2019-08-03 19:22 UTC received an edit by me (user 2) a few minutes after it was created.

However, no user_action of type 11 was created (unlike the other 2 edits that that user received that day on posts 1001 and 1003)

You can see it more clearly if you run this query:

with my_user_posts as (
  select
    p.id,
    p.user_id
  from
    posts p
  where
    p.user_id = 3 -- choose a user 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 -- no self edits
  and pr.user_id != -1 -- no system edits
  left join user_actions ua on ua.target_post_id = pr.post_id
  and ua.action_type = 11 -- only EDIT actions  
WHERE
  pr.created_at between '2019-08-03' and '2019-08-04'
order by
  pr.post_id,
  pr.created_at

I ran some numbers and, depending on the date, between 7% and 25% of non-self post_revisions don’t have a matching user_action.

We might have a bug here @Nacho_Caballero after all… stand by. Thanks for persisting on this.

3 Likes

We had this bug:

https://github.com/discourse/discourse/commit/3d0ccf864243fdfecc07ad3764df499a7b7a55f8

And I improved the implementation with this feature:

https://github.com/discourse/discourse/commit/3877ef2cfa17155a4c6063d6d3625c9bd4d5b5df

We had an edge case where when a user liked a post by another user and then followed up by editing it we would not notify on the edit.

Additionally I added a safety guard that ensures we notify unconditionally once a day even if it is a repeat editor. (we suppress repeat edit notifications from the same editor for 1 day). This is not configurable at the moment.

6 Likes

Excellent. That makes a lot of sense. Thanks a lot for the fix!

1 Like