MushroomObserver / mushroom-observer

A website for sharing observations of mushrooms.
https://mushroomobserver.org
MIT License
77 stars 26 forks source link

Clean stale non-contributors #2177

Open JoeCohen opened 3 weeks ago

JoeCohen commented 3 weeks ago

A chron job should delete Users with zero contribution [and no API] who haven't accessed the site in a while (3 months). See https://github.com/MushroomObserver/mushroom-observer/pull/2160#issuecomment-2159463377.

nimmolo commented 3 weeks ago

@JoeCohen - if you want to tackle this, this could be MO's first cron job in Ruby. Solid Queue as of recently now enables setting up recurring jobs on whatever frequency.

You could use Nathan's existing job as an example, and the SQ github docs for making it cron-like.

Or, i have a PR branch open that has rewrites of process_image, transform_image, etc. as jobs -- although those jobs are a little more complicated than this, they basically call a PORO and the job class itself is quite brief.

I imagine this job would be basically like writing a migration: it needs to call a new User class method that finds and deletes these users (maybe with a new AR query scope without_contribution on the model?). The meat of the job could just be a one-liner calling this method.

Note: jobs cannot return values, but they can log their progress via logger.warn etc. My job PR has examples.

mo-nathan commented 3 weeks ago

The one case that occurs to me that might be tricky is a newbie at a mushroom event who creates an account, but cannot get the QR code stuff working and don't pursue it long enough to make any actual contribution. However, a recorder might then use their login as a collector on a field slip. Currently this info is stored as a Textile string and not as a reference that can easily be looked up. Admittedly this is an edge case and I don't know that there are any existing similar cases where it would be desirable to keep non-participatory users. Maybe being listed as a Collector should award a contribution point?

JoeCohen commented 3 weeks ago
  1. Thanks @nimmolo for the suggestion on how to proceed. I will probably tackle this eventually. But not now: I need to prioritize #2150 and avoid interesting, but less urgent, diversions.
  2. In addition to the case pointed out by @mo-nathan, we cannot rely on Contribution. E.g., the user may have created a Project, edited a GlossaryTerm, accessed the site only via the API etc. Would something like the following work?
    • Before starting to code the job, insure that there are no Rails/InverseOf offenses. (Update the rubocop todo list, look there, fix any offenses.)
    • In the chron job:
    • Reflect on the User model to find the relevant associations. relevant associations == all associations except those we actually want to be destroyed, e.g. user_stats, user_group_users (or is it user_groups).
    • Use the result to construct an AR query for Users who have none of those associations and whose last login is long ago.
    • Call delete_all on the query results (should be safe at this point).