philomena/lib/philomena_web/user_ip_updater.ex

65 lines
1.4 KiB
Elixir
Raw Permalink Normal View History

2020-05-08 04:03:10 +02:00
defmodule PhilomenaWeb.UserIpUpdater do
2019-12-18 20:32:21 +01:00
alias Philomena.UserIps.UserIp
alias Philomena.Repo
import Ecto.Query
def child_spec([]) do
%{
2020-05-08 04:03:10 +02:00
id: PhilomenaWeb.UserIpUpdater,
start: {PhilomenaWeb.UserIpUpdater, :start_link, [[]]}
2019-12-18 20:32:21 +01:00
}
end
def start_link([]) do
{:ok, spawn_link(&init/0)}
end
def cast(user_id, ip_address, updated_at) do
pid = Process.whereis(:ip_updater)
if pid, do: send(pid, {user_id, ip_address, updated_at})
end
defp init do
Process.register(self(), :ip_updater)
run()
end
defp run do
user_ips = Enum.map(receive_all(), &into_insert_all/1)
2020-01-11 05:20:19 +01:00
update_query =
update(UserIp, inc: [uses: 1], set: [updated_at: fragment("EXCLUDED.updated_at")])
2019-12-18 20:32:21 +01:00
Repo.insert_all(UserIp, user_ips, on_conflict: update_query, conflict_target: [:user_id, :ip])
:timer.sleep(:timer.seconds(60))
run()
end
defp receive_all(user_ips \\ %{}) do
receive do
{user_id, ip_address, updated_at} ->
user_ips
|> Map.put({user_id, ip_address}, updated_at)
|> receive_all()
after
0 ->
user_ips
end
end
defp into_insert_all({{user_id, ip_address}, updated_at}) do
%{
user_id: user_id,
ip: cast_ip(ip_address),
uses: 1,
created_at: updated_at,
updated_at: updated_at
}
end
# There exists no EctoNetwork.INET.cast!/1
defp cast_ip(ip), do: elem(EctoNetwork.INET.cast(ip), 1)
end