-
Notifications
You must be signed in to change notification settings - Fork 523
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
AO3-5054 Update kudos when kudos-giver changes username #4264
AO3-5054 Update kudos when kudos-giver changes username #4264
Conversation
Tried a different approach involving touch_all on kudos.commentable, since I was having trouble testing fragment expiration in kudos sweeper. The other approach is basically:
I tried out both ways and the feature test I added passes either way, I just wasn't sure how to write spec tests for the latter. Also maybe the second approach loads more into memory and/or performs more calls since it can't do the update with just one call to the database? But then again I don't know what knock-on effects touching all these works would have either. I'm not sure how to verify what's better here. The main problem is that |
I moved cache expiration into a model callback (#4293) so we don't need to trigger the sweeper separately anymore.
Yeah, I think your "Changing username updates kudos fragment" test should cover it.
We've had tests for cache invalidation like: otwarchive/spec/models/pseud_spec.rb Lines 52 to 64 in a7c6b4e
That's really unfortunate. The downside of using |
app/models/user.rb
Outdated
@@ -146,15 +146,16 @@ class User < ApplicationRecord | |||
|
|||
def expire_caches | |||
return unless saved_change_to_login? | |||
Work.kudosed_by_user(self).touch_all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this can take a long time, I believe this should be moved to an asynchronous task sorry.
Looking at https://apidock.com/rails/ActiveRecord/Relation/touch_all it looks like touch_all changes the record in the database, I don't believe we want to do that we just want to delete the fragments. There are a silly number of Kudo and reseting the username of someone who had kudosed lots of work could create issues. ( If we did have to change the works then it would have to be in a transaction in batches of say 1000 ).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does asynchronous task just mean "a thing that executes asynchronously," or does it have a specific technical meaning in this situation? I was trying to write up a response and then realized that I wasn't sure.
I agree that touch_all
seems like not quite the right solution, but I'm struggling to figure out how to trigger mass fragment deletion. The key point is that we need to run ActionController::Base.new.expire_fragment("#{commentable.cache_key}/kudos-v3")
for each work the user has kudosed, right? So is the idea that we somehow trigger an asynchronous task that iterates through a user's kudos (with commentable id) in batches of 1000? Would that be something like a new sweeper that observes users and reacts when they change usernames, or something else?
I notice that app/sweepers/kudos_sweeper.rb
was removed in #4293 and its functionality moved to app/models/kudo.rb
; that'll be some fun merging for me, but after looking the change over I don't think it fundamentally alters the core problem/high-level solution here.
Anyway, thanks for the feedback, and sorry it took me a bit to get back to you about it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The key thing here is that to expire the cache, which looks like this:
ActionController::Base.new.expire_fragment("#{kudo.commentable.cache_key}/kudos-v3")
we need to expire the fragment for every work a user has kudo'ed (Work.kudosed_by_user(self)
), either by directly expiring it, or by causing the work's cache_key to change (which touch would do).
I tried looking through the code base to try to find where it would make sense to put an asynchronous task to expire the fragments, and I'm not sure--is it more like indexing, which seems to add things to a queue and then batch that every so often? Or would it be more like one of the rake tasks that performs periodic cleanup? I'm not clear on how to make this work and could use an example.
Change summary:
Notes/Questions:
|
Based on some discussion on slack, I've switched back to I updated the cache key version from 3 to 4, since I figured we want to expire the current state of the cache in order to reset existing cases where a user might have changed their username since leaving kudos, but if we don't need that I don't think it adds anything. |
We discussed this in chat. @irrationalpie7 suggested the approaches to cache expiration:
Instead of clearing the kudo cache on some database change, let's set Like #4034, you should also set |
(not quite ready for review yet, I'm still trying to get docker back working on my machine so I can actually run the tests) |
I used #4524 as an example for some of the tests to write, not sure why they're failing at the moment but I'll continue to investigate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
There are 2-3 minor style changes that would be nice to have if you have the time. But I don't think that they are mandatory to merge this.
features/users/user_delete.feature
Outdated
@@ -117,3 +117,14 @@ Scenario: Delete a user who has coauthored a work | |||
And a user account should not exist for "testuser" | |||
When I go to orphan_account's series page | |||
Then I should see "Epic" | |||
|
|||
Scenario: Deleting user updates kudos fragment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scenario: Deleting user updates kudos fragment | |
Scenario: Deleting user updates kudos fragment cache |
would be a bit clearer for what is getting tested. Same for the other test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these tests are misleading, tbh. The cache fragment isn't actually getting expired by the user deletion or rename; it just gets expired periodically.
We'd rather the tests go in kudos.feature and be rephrased to something like "Kudos cache expires periodically to ensure deleted users are removed and renamed users are updated." Both the rename and the deletion can go in the same scenario.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved the test as @sarken suggested!
Pull Request Checklist
as the first thing in your pull request title (e.g.
AO3-1234 Fix thing
)until they are reviewed and merged before creating new pull requests.
Issue
https://otwarchive.atlassian.net/browse/AO3-5054
Purpose
When a user updates their username, updates the user's username in the kudos listing of every work they've kudosed.
Notes
Testing Instructions
2 cucumber tests added.
Jira "steps to reproduce" should be sufficient for any manual testing.
Credit
irrationalpie they/them