update stats counters when specific actions are taken

This commit is contained in:
byte[] 2019-12-05 14:23:26 -05:00
parent 0822fe7618
commit a3187ae150
12 changed files with 67 additions and 89 deletions

View file

@ -6,8 +6,9 @@ defmodule Philomena.ImageFaves do
import Ecto.Query, warn: false import Ecto.Query, warn: false
alias Ecto.Multi alias Ecto.Multi
alias Philomena.Images.Image
alias Philomena.ImageFaves.ImageFave alias Philomena.ImageFaves.ImageFave
alias Philomena.UserStatistics
alias Philomena.Images.Image
@doc """ @doc """
Creates a image_hide. Creates a image_hide.
@ -25,6 +26,9 @@ defmodule Philomena.ImageFaves do
Multi.new Multi.new
|> Multi.insert(:fave, fave) |> Multi.insert(:fave, fave)
|> Multi.update_all(:inc_faves_count, image_query, inc: [faves_count: 1]) |> Multi.update_all(:inc_faves_count, image_query, inc: [faves_count: 1])
|> Multi.run(:inc_fave_stat, fn _repo, _changes ->
UserStatistics.inc_stat(user, :images_favourited, 1)
end)
end end
@doc """ @doc """
@ -48,6 +52,8 @@ defmodule Philomena.ImageFaves do
image_query image_query
|> repo.update_all(inc: [faves_count: -faves]) |> repo.update_all(inc: [faves_count: -faves])
UserStatistics.inc_stat(user, :images_favourited, -faves)
{:ok, count} {:ok, count}
end) end)
end end

View file

@ -6,8 +6,9 @@ defmodule Philomena.ImageVotes do
import Ecto.Query, warn: false import Ecto.Query, warn: false
alias Ecto.Multi alias Ecto.Multi
alias Philomena.Images.Image
alias Philomena.ImageVotes.ImageVote alias Philomena.ImageVotes.ImageVote
alias Philomena.UserStatistics
alias Philomena.Images.Image
@doc """ @doc """
Creates a image_vote. Creates a image_vote.
@ -28,6 +29,9 @@ defmodule Philomena.ImageVotes do
Multi.new Multi.new
|> Multi.insert(:vote, vote) |> Multi.insert(:vote, vote)
|> Multi.update_all(:inc_vote_count, image_query, inc: [upvotes_count: upvotes, downvotes_count: downvotes, score: upvotes - downvotes]) |> Multi.update_all(:inc_vote_count, image_query, inc: [upvotes_count: upvotes, downvotes_count: downvotes, score: upvotes - downvotes])
|> Multi.run(:inc_vote_stat, fn _repo, _changes ->
UserStatistics.inc_stat(user, :votes_cast, 1)
end)
end end
@doc """ @doc """
@ -59,6 +63,8 @@ defmodule Philomena.ImageVotes do
image_query image_query
|> repo.update_all(inc: [upvotes_count: -upvotes, downvotes_count: -downvotes, score: downvotes - upvotes]) |> repo.update_all(inc: [upvotes_count: -upvotes, downvotes_count: -downvotes, score: downvotes - upvotes])
UserStatistics.inc_stat(user, :votes_cast, -(upvotes + downvotes))
{:ok, count} {:ok, count}
end) end)
end end

View file

@ -7,53 +7,7 @@ defmodule Philomena.UserStatistics do
alias Philomena.Repo alias Philomena.Repo
alias Philomena.UserStatistics.UserStatistic alias Philomena.UserStatistics.UserStatistic
alias Philomena.Users.User
@doc """
Returns the list of user_statistics.
## Examples
iex> list_user_statistics()
[%UserStatistic{}, ...]
"""
def list_user_statistics do
Repo.all(UserStatistic)
end
@doc """
Gets a single user_statistic.
Raises `Ecto.NoResultsError` if the User statistic does not exist.
## Examples
iex> get_user_statistic!(123)
%UserStatistic{}
iex> get_user_statistic!(456)
** (Ecto.NoResultsError)
"""
def get_user_statistic!(id), do: Repo.get!(UserStatistic, id)
@doc """
Creates a user_statistic.
## Examples
iex> create_user_statistic(%{field: value})
{:ok, %UserStatistic{}}
iex> create_user_statistic(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_user_statistic(attrs \\ %{}) do
%UserStatistic{}
|> UserStatistic.changeset(attrs)
|> Repo.insert()
end
@doc """ @doc """
Updates a user_statistic. Updates a user_statistic.
@ -67,38 +21,29 @@ defmodule Philomena.UserStatistics do
{:error, %Ecto.Changeset{}} {:error, %Ecto.Changeset{}}
""" """
def update_user_statistic(%UserStatistic{} = user_statistic, attrs) do def inc_stat(user, action, amount \\ 1)
user_statistic
|> UserStatistic.changeset(attrs)
|> Repo.update()
end
@doc """ def inc_stat(nil, _action, _amount), do: {:ok, nil}
Deletes a UserStatistic. def inc_stat(%{id: user_id}, action, amount)
when action in [:uploads, :images_favourited, :comments_posted, :votes_cast, :metadata_updates, :forum_posts]
do
now =
DateTime.utc_now()
|> DateTime.to_unix(:second)
|> div(86400)
## Examples user = User |> where(id: ^user_id)
action_count = :"#{action}_count"
iex> delete_user_statistic(user_statistic) run = fn ->
{:ok, %UserStatistic{}} Repo.update_all(user, inc: [{action_count, amount}])
Repo.insert(
Map.put(%UserStatistic{day: now, user_id: user_id}, action, amount),
on_conflict: [inc: [{action, amount}]],
conflict_target: [:day, :user_id]
)
end
iex> delete_user_statistic(user_statistic) Repo.transaction(run)
{:error, %Ecto.Changeset{}}
"""
def delete_user_statistic(%UserStatistic{} = user_statistic) do
Repo.delete(user_statistic)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking user_statistic changes.
## Examples
iex> change_user_statistic(user_statistic)
%Ecto.Changeset{source: %UserStatistic{}}
"""
def change_user_statistic(%UserStatistic{} = user_statistic) do
UserStatistic.changeset(user_statistic, %{})
end end
end end

View file

@ -4,6 +4,7 @@ defmodule Philomena.UserStatistics.UserStatistic do
alias Philomena.Users.User alias Philomena.Users.User
# fixme: rekey this on (user_id, day)
schema "user_statistics" do schema "user_statistics" do
belongs_to :user, User belongs_to :user, User
field :day, :integer, default: 0 field :day, :integer, default: 0
@ -18,7 +19,9 @@ defmodule Philomena.UserStatistics.UserStatistic do
@doc false @doc false
def changeset(user_statistic, attrs) do def changeset(user_statistic, attrs) do
user_statistic user_statistic
|> cast(attrs, []) |> cast(attrs, [
|> validate_required([]) :uploads, :votes_cast, :comments_posted, :metadata_updates,
:images_favourited, :forum_posts
])
end end
end end

View file

@ -2,6 +2,7 @@ defmodule PhilomenaWeb.Image.CommentController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.{Images.Image, Comments.Comment, Textile.Renderer} alias Philomena.{Images.Image, Comments.Comment, Textile.Renderer}
alias Philomena.UserStatistics
alias Philomena.Comments alias Philomena.Comments
alias Philomena.Images alias Philomena.Images
alias Philomena.Repo alias Philomena.Repo
@ -69,6 +70,7 @@ defmodule PhilomenaWeb.Image.CommentController do
Comments.notify_comment(comment) Comments.notify_comment(comment)
Comments.reindex_comment(comment) Comments.reindex_comment(comment)
Images.reindex_image(conn.assigns.image) Images.reindex_image(conn.assigns.image)
UserStatistics.inc_stat(conn.assigns.current_user, :comments_posted)
conn conn
|> put_flash(:info, "Comment created successfully.") |> put_flash(:info, "Comment created successfully.")

View file

@ -20,7 +20,7 @@ defmodule PhilomenaWeb.Image.FaveController do
) )
|> Multi.append(ImageVotes.delete_vote_transaction(image, user)) |> Multi.append(ImageVotes.delete_vote_transaction(image, user))
|> Multi.append(ImageVotes.create_vote_transaction(image, user, true)) |> Multi.append(ImageVotes.create_vote_transaction(image, user, true))
|> Repo.transaction() |> Repo.isolated_transaction(:serializable)
|> case do |> case do
{:ok, _result} -> {:ok, _result} ->
image = image =
@ -42,7 +42,7 @@ defmodule PhilomenaWeb.Image.FaveController do
image = conn.assigns.image image = conn.assigns.image
ImageFaves.delete_fave_transaction(image, user) ImageFaves.delete_fave_transaction(image, user)
|> Repo.transaction() |> Repo.isolated_transaction(:serializable)
|> case do |> case do
{:ok, _result} -> {:ok, _result} ->
image = image =

View file

@ -1,8 +1,9 @@
defmodule PhilomenaWeb.Image.SourceController do defmodule PhilomenaWeb.Image.SourceController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Images alias Philomena.UserStatistics
alias Philomena.Images.Image alias Philomena.Images.Image
alias Philomena.Images
plug PhilomenaWeb.FilterBannedUsersPlug plug PhilomenaWeb.FilterBannedUsersPlug
plug PhilomenaWeb.CaptchaPlug plug PhilomenaWeb.CaptchaPlug
@ -19,6 +20,8 @@ defmodule PhilomenaWeb.Image.SourceController do
changeset = changeset =
Images.change_image(image) Images.change_image(image)
UserStatistics.inc_stat(conn.assigns.current_user, :metadata_updates)
conn conn
|> put_view(PhilomenaWeb.ImageView) |> put_view(PhilomenaWeb.ImageView)
|> render("_source.html", layout: false, image: image, changeset: changeset) |> render("_source.html", layout: false, image: image, changeset: changeset)

View file

@ -1,8 +1,9 @@
defmodule PhilomenaWeb.Image.TagController do defmodule PhilomenaWeb.Image.TagController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Images alias Philomena.UserStatistics
alias Philomena.Images.Image alias Philomena.Images.Image
alias Philomena.Images
alias Philomena.Tags alias Philomena.Tags
alias Philomena.Repo alias Philomena.Repo
@ -20,6 +21,7 @@ defmodule PhilomenaWeb.Image.TagController do
{:ok, %{image: {image, added_tags, removed_tags}}} -> {:ok, %{image: {image, added_tags, removed_tags}}} ->
Images.reindex_image(image) Images.reindex_image(image)
Tags.reindex_tags(added_tags ++ removed_tags) Tags.reindex_tags(added_tags ++ removed_tags)
UserStatistics.inc_stat(conn.assigns.current_user, :metadata_updates)
image = image =
image image

View file

@ -18,7 +18,7 @@ defmodule PhilomenaWeb.Image.VoteController do
ImageVotes.delete_vote_transaction(image, user), ImageVotes.delete_vote_transaction(image, user),
ImageVotes.create_vote_transaction(image, user, params["up"] == true) ImageVotes.create_vote_transaction(image, user, params["up"] == true)
) )
|> Repo.transaction() |> Repo.isolated_transaction(:serializable)
|> case do |> case do
{:ok, _result} -> {:ok, _result} ->
image = image =
@ -40,7 +40,7 @@ defmodule PhilomenaWeb.Image.VoteController do
image = conn.assigns.image image = conn.assigns.image
ImageVotes.delete_vote_transaction(image, user) ImageVotes.delete_vote_transaction(image, user)
|> Repo.transaction() |> Repo.isolated_transaction(:serializable)
|> case do |> case do
{:ok, _result} -> {:ok, _result} ->
image = image =

View file

@ -5,6 +5,7 @@ defmodule PhilomenaWeb.ImageController do
alias PhilomenaWeb.NotificationCountPlug alias PhilomenaWeb.NotificationCountPlug
alias Philomena.{Images, Images.Image, Comments.Comment, Galleries.Gallery, Galleries.Interaction, Textile.Renderer} alias Philomena.{Images, Images.Image, Comments.Comment, Galleries.Gallery, Galleries.Interaction, Textile.Renderer}
alias Philomena.Servers.ImageProcessor alias Philomena.Servers.ImageProcessor
alias Philomena.UserStatistics
alias Philomena.Interactions alias Philomena.Interactions
alias Philomena.Comments alias Philomena.Comments
alias Philomena.Tags alias Philomena.Tags
@ -104,6 +105,7 @@ defmodule PhilomenaWeb.ImageController do
ImageProcessor.cast(image.id) ImageProcessor.cast(image.id)
Images.reindex_image(image) Images.reindex_image(image)
Tags.reindex_tags(image.added_tags) Tags.reindex_tags(image.added_tags)
UserStatistics.inc_stat(conn.assigns.current_user, :uploads)
conn conn
|> put_flash(:info, "Image created successfully.") |> put_flash(:info, "Image created successfully.")

View file

@ -2,6 +2,7 @@ defmodule PhilomenaWeb.Topic.PostController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.{Forums.Forum, Topics.Topic, Posts} alias Philomena.{Forums.Forum, Topics.Topic, Posts}
alias Philomena.UserStatistics
alias Philomena.Repo alias Philomena.Repo
plug PhilomenaWeb.FilterBannedUsersPlug plug PhilomenaWeb.FilterBannedUsersPlug
@ -19,6 +20,7 @@ defmodule PhilomenaWeb.Topic.PostController do
{:ok, %{post: post}} -> {:ok, %{post: post}} ->
Posts.notify_post(post) Posts.notify_post(post)
Posts.reindex_post(post) Posts.reindex_post(post)
UserStatistics.inc_stat(conn.assigns.current_user, :forum_posts)
conn conn
|> put_flash(:info, "Post created successfully.") |> put_flash(:info, "Post created successfully.")

View file

@ -2,8 +2,8 @@
-- PostgreSQL database dump -- PostgreSQL database dump
-- --
-- Dumped from database version 11.5 (Debian 11.5-1.pgdg100+1) -- Dumped from database version 12.1 (Debian 12.1-1.pgdg100+1)
-- Dumped by pg_dump version 11.5 (Debian 11.5-1.pgdg100+1) -- Dumped by pg_dump version 12.1 (Debian 12.1-1.pgdg90+1)
SET statement_timeout = 0; SET statement_timeout = 0;
SET lock_timeout = 0; SET lock_timeout = 0;
@ -18,7 +18,7 @@ SET row_security = off;
SET default_tablespace = ''; SET default_tablespace = '';
SET default_with_oids = false; SET default_table_access_method = heap;
-- --
-- Name: adverts; Type: TABLE; Schema: public; Owner: - -- Name: adverts; Type: TABLE; Schema: public; Owner: -
@ -3743,6 +3743,13 @@ CREATE INDEX index_user_name_changes_on_user_id ON public.user_name_changes USIN
CREATE INDEX index_user_statistics_on_user_id ON public.user_statistics USING btree (user_id); CREATE INDEX index_user_statistics_on_user_id ON public.user_statistics USING btree (user_id);
--
-- Name: index_user_statistics_on_user_id_and_day; Type: INDEX; Schema: public; Owner: -
--
CREATE UNIQUE INDEX index_user_statistics_on_user_id_and_day ON public.user_statistics USING btree (user_id, day);
-- --
-- Name: index_user_whitelists_on_user_id; Type: INDEX; Schema: public; Owner: - -- Name: index_user_whitelists_on_user_id; Type: INDEX; Schema: public; Owner: -
-- --