Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove special case notifying author of threads #1037

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from

Conversation

MoshiKoi
Copy link
Member

Instead of special casing creating a notification, we just have them follow normally automatically. Resolves #1025

Instead of special casing creating a notification,
we just have them follow normally automatically.
@cellio cellio requested a review from a team April 21, 2023 13:09
@MoshiKoi
Copy link
Member Author

By the way (I forgot to mention), this does mean that everyone will no longer be following new threads on their posts since this change isn't retroactive. They'd have to actually click the follow new threads button on their posts. Someone could presumably make a one-off migration script somewhere to fix this, I'm not confident enough to do so myself.

@cellio
Copy link
Member

cellio commented Apr 23, 2023

By the way (I forgot to mention), this does mean that everyone will no longer be following new threads on their posts since this change isn't retroactive. They'd have to actually click the follow new threads button on their posts. Someone could presumably make a one-off migration script somewhere to fix this, I'm not confident enough to do so myself.

Oh, that would be bad; we don't want to quietly cancel notifications on older posts. I don't know how to write the migration script either, but the other way to do it would be to keep the extra check until we do -- so do make the change where we implement notifications as auto-follows on new posts, but in the code that decides whether to notify, keep the check for "is my post" along with "is followed" until we can fix existing follows.

@trichoplax
Copy link
Contributor

trichoplax commented Apr 24, 2023

Problems discovered during testing

I also don't know how to write the database script, but happy to work together on learning how once we know what we're aiming for. Before that, I've found some odd behaviour.

I've tested on this new branch and also on develop for comparison. The problems seem to stem from existing problems that predate this new branch. I don't understand the findings, but I'm sharing them here as they suggest there is more happening than expected from reading the changed code.

I checked the contents of the thread_followers database table at each step. I've noted what changed but I haven't established which part of the codebase causes these changes.

Summary of the problems

  • On develop:
    • Pressing "unfollow new" on your own post does not prevent notifications for new threads.
    • Pressing "follow new" on your own post causes a duplicate row in the database. As a result you have to press "unfollow" twice on a thread before it takes effect.
  • On this new branch:
    • Pressing "unfollow new" on your own post does not prevent notifications for new threads (it only prevents a notification for the initial comment of a new thread - notifications are still received for subsequent comments in that thread).
    • Pressing "follow new" on your own post causes a duplicate row in the database. As a result you have to press "unfollow" twice on a thread before it takes effect (Same problem as on develop except now it applies to a new post immediately as the post now defaults to the post author following new threads).

Tests on develop

(Differences from the new branch in bold.)

Test 1

  • UserA posts a new question.
  • No new rows in thread_followers.
  • UserB posts a new thread.
  • 2 new rows appear in thread_followers, 1 for each of UserA and UserB, each with null post_id and non-null comment_thread_id.
  • UserA receives a notification.

Test 2

  • UserA presses "follow new" on the question (which they posted in the previous test).
  • 1 new row is added to thread_followers for UserA, with null comment_thread_id and non-null post_id.
  • UserB posts a new thread.
  • 1 new row appears in thread_followers for UserB, as before, but 2 new rows appear for UserA.
  • UserA still only receives 1 notification (no unexpected behaviour from the user perspective).

Test 3

  • UserA presses "unfollow new" on the question.
  • The previously added row in thread_followers for UserA with non-null post_id is hard deleted.
  • UserB posts a new thread.
  • 2 new rows appear in thread_followers, 1 for each of UserA and UserB, as in test 1.
  • UserA receives a notification, as in test 1.

Test 4

  • UserA opens the thread from test 2 for which UserA has 2 identical rows in the thread_followers table.
  • UserA presses "unfollow" for this thread.
  • Instead of changing to "follow", it remains "unfollow".
  • In the thread_followers table, the first (smallest id) of the 2 rows is hard deleted.
  • UserA presses "unfollow" again.
  • This time it changes to "follow" as expected.
  • In the thread_followers table, the second of the 2 rows is hard deleted, so the table no longer contains any rows to cause notifications for UserA for this thread.

The same tests on this new branch

(Differences from develop in bold.)

Test 1

  • UserA posts a new question.
  • 1 new row is added to thread_followers for UserA, with null comment_thread_id and non-null post_id.
  • UserB posts a new thread.
  • 1 new row appears in thread_followers for UserB, but 2 new rows appear for UserA, each with null post_id and non-null comment_thread_id.
  • UserA receives a notification.

Test 3

(Order switched with test 2 to align with the tests on develop, since on this branch new questions start out with the post author already following new threads.)

  • UserA presses "unfollow new" on the question (which they posted in the previous test).
  • The previously added row in thread_followers for UserA with non-null post_id is hard deleted.
  • UserB posts a new thread.
  • 2 new rows appear in thread_followers, 1 for each of UserA and UserB.
  • UserA does not receive a notification.
  • UserA does show as being a follower (the thread page shows "unfollow").
  • When UserB posts a further message in the same thread, UserA receives a notification.

Test 2

(Order switched with test 3 to align with the tests on develop, since on this branch new questions start out with the post author following new threads.)

  • UserA presses "follow new" on the question.
  • 1 new row is added to thread_followers for UserA, with null comment_thread_id and non-null post_id.
  • UserB posts a new thread.
  • 1 new row appears in thread_followers for UserB, as before, but 2 new rows appear for UserA.
  • UserA still only receives 1 notification (no unexpected behaviour from the user perspective).

Test 4

  • UserA opens the thread from test 2 for which UserA has 2 identical rows in the thread_followers table.
  • UserA presses "unfollow" for this thread.
  • Instead of changing to "follow", it remains "unfollow".
  • In the thread_followers table, the first (smallest id) of the 2 rows is hard deleted.
  • UserA presses "unfollow" again.
  • This time it changes to "follow" as expected.
  • In the thread_followers table, the second of the 2 rows is hard deleted, so the table no longer contains any rows to cause notifications for UserA for this thread.

Thoughts

Although these problems are mostly pre-existing (not caused by this branch) we should probably ensure we understand them well enough to fix them before we merge a pull request that requires adjusting the database. We need to understand well enough to ensure our database script takes into account the unintended state of some of the historical data.

Should we aim to put the database in a correct state and have the code trust that the database is always as expected in future, or should the code take into account that the database may not always be in the expected state (as a failsafe)? For example:

  • When unfollowing a thread the code could ensure all matching rows are deleted rather than the current approach of assuming there is only one row and just removing the first row found.
  • When following a thread the code could add a row only if none already exist.

This might help protect against any bugs we have not yet discovered, and any historical data problems we haven't yet spotted.

I'm not looking to make a case either way, just wondering which approach people would prefer.

@MoshiKoi
Copy link
Member Author

Sorry it took so long to address those issues! Life (and accidental database corruption) got in the way. The last commit should fix them (apparently there comment following logic is spread out over all three of PostsController, CommentsController and the CommentThread model, which made it hard to track down where the ThreadFollowers were being created

Test 1

  • UserA posts a new question.
  • 1 new row is added to thread_followers for UserA, with null comment_thread_id and non-null post_id.
  • UserB posts a new thread.
  • 1 new row appears in thread_followers for each of UserB and UserA, each with null post_id and non-null comment_thread_id.
  • UserA receives a notification.

Test 3

  • UserA presses "unfollow new" on the question (which they posted in the previous test).
  • The previously added row in thread_followers for UserA with non-null post_id is hard deleted.
  • UserB posts a new thread.
  • 1 new rows appear in thread_followers, UserB.
  • UserA does not receive a notification.
  • UserA does not show as being a follower (the thread page shows "follow").
  • When UserB posts a further message in the same thread, UserA does not receive a notification.

Test 2

  • UserA presses "follow new" on the question.
  • 1 new row is added to thread_followers for UserA, with null comment_thread_id and non-null post_id.
  • UserB posts a new thread.
  • 1 new row appears in thread_followers for each of UserB and UserA.
  • UserA still only receives 1 notification (no unexpected behaviour from the user perspective).

Test 4

  • UserA opens the thread from test 2
  • UserA presses "unfollow" for this thread.
  • It changes to "follow"
  • the table no longer contains any rows to cause notifications for UserA for this thread.

@trichoplax
Copy link
Contributor

Thanks for fixing all the problems!

Please don't apologise for life getting in the way - life comes first. I'm not just saying that because of being distracted myself recently - it's my view in general.

I don't have access to approve pull requests but it's looking good to me. Is the database script you mentioned previously the only thing remaining now? I'm guessing it would need to do the following:

  • Make the author of every post that can have comments a follower of new threads

It looks like there are some one-off scripts in db/scripts and some of them are .rb files and others are .sql files. I have no experience of writing database scripts in Ruby but happy to have a go in SQL if you'd like a hand. I think writing it should be straightforward but I don't know how long it will take to run - maybe someone with access could test it on a backup of the live database to make sure it's going to complete quickly enough.

@cellio
Copy link
Member

cellio commented May 22, 2023

We could set this up on the dev server for testing when the DB-update stuff is ready.

@Taeir
Copy link
Contributor

Taeir commented Nov 12, 2023

@MoshiKoi So users need to follow their own posts now, that would be
rails generate migration FollowOwnPosts
on the command line. This will generate a new file like db/migrate/<timestamp>_follow_own_posts.rb which will be initially mostly empty.

Then modify this file and change the change method as follows:

  def change
    to_insert = Post.where.not(post_type_id: [PolicyDoc.post_type_id, HelpDoc.post_type_id])
                    .where.not(user_id: nil)
                    .pluck(:id, :user_id)
                    .map { |post_id, user_id| { post_id: post_id, user_id: user_id } }
    ThreadFollower.insert_all(to_insert)
  end

This will transform each post into an entry { user_id: <post_author_id>, post_id: <post_id> }, which will be bulk inserted as ThreadFollowers using insert_all. Performance wise, this should be about as good as we can do. It will run the following two queries:

SELECT id, user_id FROM posts WHERE post_type_id IN (?, ?) AND user_id IS NOT NULL;
INSERT INTO thread_followers (post_id, user_id, created_at, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP()), (?, ?, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP()), ...

In rails, it avoids constructing all the post objects, instead constructing only an array of the ids and user ids, which is then transformed into an array of hashes to be able to be passed to insert_all.

@cellio
Copy link
Member

cellio commented Nov 12, 2023

@Taeir will that migration preserve the following for existing posts? (Do I understand that correctly?)

@MoshiKoi , does the new code auto-follow new threads your own posts (at post-creation time)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

On your own posts, show that you're following new threads (don't show "follow new" when you already are)
4 participants