CaptainFact / captain-fact

📚 Documentation, wiki and community discussions
https://captainfact.io
67 stars 7 forks source link

Reputation log: better record inversed votes #213

Open Betree opened 3 years ago

Betree commented 3 years ago

Currently, voting down after voting up (or the opposite) just removes the old vote and replaces it with the new one, recording only one UserAction for the new vote. To make sure we register things properly with the reputation, we should record a revert_vote action before recording the new one.

Betree commented 3 years ago

Only the first part of the issue was solved in https://github.com/CaptainFact/captain-fact-api/pull/367, we still need a migration to fix the reputation for past entries.

```elixir defmodule :"Elixir.DB.Repo.Migrations.Add-missing-revert-vote-actions" do use Ecto.Migration def up do Ecto.Adapters.SQL.query!(DB.Repo, """ WITH vote_actions AS ( SELECT user_id, entity, entity_id FROM users_actions WHERE entity IN (4,5) -- comments + sourced comments AND "type" IN (9,10,12,13) -- Votes up/down AND their revert actions AND entity_id IS NOT NULL -- TODO: See what TO DO WITH deleted comments GROUP BY user_id, entity, entity_id HAVING COUNT(*) > 1 ) SELECT ua.* FROM users_actions ua INNER JOIN vote_actions va ON va.user_id = ua.user_id AND va.entity = ua.entity AND va.entity_id = ua.entity_id ORDER BY user_id ASC, entity ASC, entity_id ASC, inserted_at ASC, id ASC """) |> Map.get(:rows) |> Enum.group_by(fn action -> "#{action.user_id}-#{action.entity}-#{action.entity_id}" end) |> Enum.each(fn {_key, actions} -> analyze_actions(actions) end) # TODO: Need to test with real data (local dev doesn't have occurences) raise "abort" end def down do # No rollack end defp analyze_actions([action | next_actions], prev_action = nil) do check_action(action, prev_action) analyze_actions(next_actions, action) end defp analyze_actions([], _prev_action = nil) do nil end # Triggered when a vote up is found right after a vote down defp check_action(action, prev_action) when not is_nil(prev_action) and prev_action.type == 10 and action.type == 9 do action.user_id |> CF.Actions.ActionCreator.action_revert_vote(action.video_id, :revert_vote_down, comment) |> Ecto.Changeset.change(inserted_at: DateTime.add(prev_action.inserted_at, 1, :microsecond)) |> DB.Repo.insert() end defp check_action(_action, _prev_action) do nil end end ```