defmodule GitGud.Federation.RetentionTest do
use GitGud.DataCase, async: false
alias GitGud.Federation
alias GitGud.Federation.Activity
alias GitGud.Federation.Actor
alias GitGud.Federation.InboxDelivery
alias GitGud.Federation.OutboundDelivery
alias GitGud.Federation.Workers.Retention
alias GitGud.Repo
import GitGud.AccountsFixtures
@moduletag :git_required
setup do
if System.find_executable("git") == nil do
{:skip, "git not on PATH"}
else
user = user_fixture()
{:ok, actor} = Federation.ensure_local_actor(user)
{:ok, actor: actor}
end
end
test "no-op when no retention configured", %{actor: actor} do
insert_delivery(actor, ago_days(120))
insert_delivery(actor, ago_days(5))
assert :ok = Retention.run_now()
assert Repo.aggregate(InboxDelivery, :count) == 2
end
test "prunes inbox deliveries older than the configured window", %{actor: actor} do
insert_delivery(actor, ago_days(120))
insert_delivery(actor, ago_days(89))
fresh = insert_delivery(actor, ago_days(5))
Application.put_env(:git_gud, Retention, inbox_deliveries_days: 90)
on_exit(fn ->
Application.put_env(:git_gud, Retention, inbox_deliveries_days: nil)
end)
assert :ok = Retention.run_now()
remaining = Repo.all(InboxDelivery) |> Enum.map(& &1.id)
assert fresh.id in remaining
assert Enum.all?(remaining, fn id ->
%{inserted_at: t} = Repo.get!(InboxDelivery, id)
DateTime.diff(DateTime.utc_now(), t) <= 90 * 86_400
end)
assert length(remaining) == 2
end
test "never prunes locally-generated activities", %{actor: actor} do
local = insert_activity(actor, is_local: true, age: ago_days(500))
remote = insert_activity(actor, is_local: false, age: ago_days(500))
Application.put_env(:git_gud, Retention, remote_activities_days: 30)
on_exit(fn ->
Application.put_env(:git_gud, Retention, remote_activities_days: nil)
end)
assert :ok = Retention.run_now()
assert Repo.get(Activity, local.id)
refute Repo.get(Activity, remote.id)
end
test "prunes outbound deliveries", %{actor: actor} do
activity = insert_activity(actor, is_local: true, age: ago_days(60))
%OutboundDelivery{}
|> OutboundDelivery.changeset(%{
activity_id: activity.id,
target_inbox_url: "https://x.example/inbox",
status: "failure"
})
|> Repo.insert!()
|> backdate(ago_days(60))
Application.put_env(:git_gud, Retention, outbound_deliveries_days: 30)
on_exit(fn ->
Application.put_env(:git_gud, Retention, outbound_deliveries_days: nil)
end)
assert :ok = Retention.run_now()
assert Repo.aggregate(OutboundDelivery, :count) == 0
end
defp insert_delivery(actor, age) do
delivery =
%InboxDelivery{}
|> InboxDelivery.changeset(%{
target_actor_id: actor.id,
source_actor_url: "https://x.example/users/a",
source_host: "x.example",
raw_body: "{}",
status: "accepted"
})
|> Repo.insert!()
backdate(delivery, age)
end
defp insert_activity(%Actor{} = actor, opts) do
is_local = Keyword.fetch!(opts, :is_local)
age = Keyword.fetch!(opts, :age)
activity =
%Activity{}
|> Activity.changeset(%{
activity_url:
"https://x.example/activities/" <>
Integer.to_string(System.unique_integer([:positive])),
type: "Note",
actor_id: actor.id,
raw: %{},
is_local: is_local
})
|> Repo.insert!()
backdate(activity, age)
end
defp backdate(record, %DateTime{} = ts) do
{1, _} =
Repo.update_all(
from(r in record.__struct__, where: r.id == ^record.id),
set: [inserted_at: ts]
)
%{record | inserted_at: ts}
end
defp ago_days(n) do
DateTime.utc_now()
|> DateTime.add(-n * 86_400, :second)
|> DateTime.truncate(:second)
end
end
3.9 KiB · text
5af55d9