schedule activity expiration in Oban
This commit is contained in:
parent
0254696e30
commit
9bf1065a06
23 changed files with 229 additions and 386 deletions
|
|
@ -1,55 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.ActivityExpirationTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.ActivityExpiration
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do: clear_config([ActivityExpiration, :enabled])
|
||||
|
||||
test "finds activities due to be deleted only" do
|
||||
activity = insert(:note_activity)
|
||||
|
||||
expiration_due =
|
||||
insert(:expiration_in_the_past, %{activity_id: activity.id}) |> Repo.preload(:activity)
|
||||
|
||||
activity2 = insert(:note_activity)
|
||||
insert(:expiration_in_the_future, %{activity_id: activity2.id})
|
||||
|
||||
expirations = ActivityExpiration.due_expirations()
|
||||
|
||||
assert length(expirations) == 1
|
||||
assert hd(expirations) == expiration_due
|
||||
end
|
||||
|
||||
test "denies expirations that don't live long enough" do
|
||||
activity = insert(:note_activity)
|
||||
now = NaiveDateTime.utc_now()
|
||||
assert {:error, _} = ActivityExpiration.create(activity, now)
|
||||
end
|
||||
|
||||
test "deletes an expiration activity" do
|
||||
Pleroma.Config.put([ActivityExpiration, :enabled], true)
|
||||
activity = insert(:note_activity)
|
||||
|
||||
naive_datetime =
|
||||
NaiveDateTime.add(
|
||||
NaiveDateTime.utc_now(),
|
||||
-:timer.minutes(2),
|
||||
:millisecond
|
||||
)
|
||||
|
||||
expiration =
|
||||
insert(
|
||||
:expiration_in_the_past,
|
||||
%{activity_id: activity.id, scheduled_at: naive_datetime}
|
||||
)
|
||||
|
||||
Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(%Oban.Job{})
|
||||
|
||||
refute Pleroma.Repo.get(Pleroma.Activity, activity.id)
|
||||
refute Pleroma.Repo.get(Pleroma.ActivityExpiration, expiration.id)
|
||||
end
|
||||
end
|
||||
|
|
@ -185,15 +185,6 @@ defmodule Pleroma.ActivityTest do
|
|||
end
|
||||
end
|
||||
|
||||
test "add an activity with an expiration" do
|
||||
activity = insert(:note_activity)
|
||||
insert(:expiration_in_the_future, %{activity_id: activity.id})
|
||||
|
||||
Pleroma.ActivityExpiration
|
||||
|> where([a], a.activity_id == ^activity.id)
|
||||
|> Repo.one!()
|
||||
end
|
||||
|
||||
test "all_by_ids_with_object/1" do
|
||||
%{id: id1} = insert(:note_activity)
|
||||
%{id: id2} = insert(:note_activity)
|
||||
|
|
|
|||
|
|
@ -200,25 +200,6 @@ defmodule Pleroma.Factory do
|
|||
|> Map.merge(attrs)
|
||||
end
|
||||
|
||||
defp expiration_offset_by_minutes(attrs, minutes) do
|
||||
scheduled_at =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.add(:timer.minutes(minutes), :millisecond)
|
||||
|> NaiveDateTime.truncate(:second)
|
||||
|
||||
%Pleroma.ActivityExpiration{}
|
||||
|> Map.merge(attrs)
|
||||
|> Map.put(:scheduled_at, scheduled_at)
|
||||
end
|
||||
|
||||
def expiration_in_the_past_factory(attrs \\ %{}) do
|
||||
expiration_offset_by_minutes(attrs, -60)
|
||||
end
|
||||
|
||||
def expiration_in_the_future_factory(attrs \\ %{}) do
|
||||
expiration_offset_by_minutes(attrs, 61)
|
||||
end
|
||||
|
||||
def article_activity_factory do
|
||||
article = insert(:article)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,15 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mix.Tasks.Pleroma.DatabaseTest do
|
||||
use Pleroma.DataCase
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
use Pleroma.DataCase
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup_all do
|
||||
|
|
@ -130,40 +131,45 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do
|
|||
|
||||
describe "ensure_expiration" do
|
||||
test "it adds to expiration old statuses" do
|
||||
%{id: activity_id1} = insert(:note_activity)
|
||||
activity1 = insert(:note_activity)
|
||||
|
||||
%{id: activity_id2} =
|
||||
insert(:note_activity, %{inserted_at: NaiveDateTime.from_iso8601!("2015-01-23 23:50:07")})
|
||||
{:ok, inserted_at, 0} = DateTime.from_iso8601("2015-01-23T23:50:07Z")
|
||||
activity2 = insert(:note_activity, %{inserted_at: inserted_at})
|
||||
|
||||
%{id: activity_id3} = activity3 = insert(:note_activity)
|
||||
%{id: activity_id3} = insert(:note_activity)
|
||||
|
||||
expires_at =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.add(60 * 61, :second)
|
||||
|> NaiveDateTime.truncate(:second)
|
||||
expires_at = DateTime.add(DateTime.utc_now(), 60 * 61)
|
||||
|
||||
Pleroma.ActivityExpiration.create(activity3, expires_at)
|
||||
Pleroma.Workers.PurgeExpiredActivity.enqueue(%{
|
||||
activity_id: activity_id3,
|
||||
expires_at: expires_at
|
||||
})
|
||||
|
||||
Mix.Tasks.Pleroma.Database.run(["ensure_expiration"])
|
||||
|
||||
expirations =
|
||||
Pleroma.ActivityExpiration
|
||||
|> order_by(:activity_id)
|
||||
|> Repo.all()
|
||||
assert_enqueued(
|
||||
worker: Pleroma.Workers.PurgeExpiredActivity,
|
||||
args: %{activity_id: activity1.id},
|
||||
scheduled_at:
|
||||
activity1.inserted_at
|
||||
|> DateTime.from_naive!("Etc/UTC")
|
||||
|> Timex.shift(days: 365)
|
||||
)
|
||||
|
||||
assert [
|
||||
%Pleroma.ActivityExpiration{
|
||||
activity_id: ^activity_id1
|
||||
},
|
||||
%Pleroma.ActivityExpiration{
|
||||
activity_id: ^activity_id2,
|
||||
scheduled_at: ~N[2016-01-23 23:50:07]
|
||||
},
|
||||
%Pleroma.ActivityExpiration{
|
||||
activity_id: ^activity_id3,
|
||||
scheduled_at: ^expires_at
|
||||
}
|
||||
] = expirations
|
||||
assert_enqueued(
|
||||
worker: Pleroma.Workers.PurgeExpiredActivity,
|
||||
args: %{activity_id: activity2.id},
|
||||
scheduled_at:
|
||||
activity2.inserted_at
|
||||
|> DateTime.from_naive!("Etc/UTC")
|
||||
|> Timex.shift(days: 365)
|
||||
)
|
||||
|
||||
assert_enqueued(
|
||||
worker: Pleroma.Workers.PurgeExpiredActivity,
|
||||
args: %{activity_id: activity_id3},
|
||||
scheduled_at: expires_at
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2069,18 +2069,25 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
end
|
||||
|
||||
describe "global activity expiration" do
|
||||
setup do: clear_config([:mrf, :policies])
|
||||
|
||||
test "creates an activity expiration for local Create activities" do
|
||||
Pleroma.Config.put(
|
||||
[:mrf, :policies],
|
||||
Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy
|
||||
clear_config([:mrf, :policies], Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy)
|
||||
|
||||
{:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
|
||||
{:ok, follow} = ActivityBuilder.insert(%{"type" => "Follow", "context" => "3hu"})
|
||||
|
||||
assert_enqueued(
|
||||
worker: Pleroma.Workers.PurgeExpiredActivity,
|
||||
args: %{activity_id: activity.id},
|
||||
scheduled_at:
|
||||
activity.inserted_at
|
||||
|> DateTime.from_naive!("Etc/UTC")
|
||||
|> Timex.shift(days: 365)
|
||||
)
|
||||
|
||||
{:ok, %{id: id_create}} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
|
||||
{:ok, _follow} = ActivityBuilder.insert(%{"type" => "Follow", "context" => "3hu"})
|
||||
|
||||
assert [%{activity_id: ^id_create}] = Pleroma.ActivityExpiration |> Repo.all()
|
||||
refute_enqueued(
|
||||
worker: Pleroma.Workers.PurgeExpiredActivity,
|
||||
args: %{activity_id: follow.id}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
|
|||
"object" => %{"type" => "Note"}
|
||||
})
|
||||
|
||||
assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364
|
||||
assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364
|
||||
end
|
||||
|
||||
test "keeps existing `expires_at` if it less than the config setting" do
|
||||
expires_at = NaiveDateTime.utc_now() |> Timex.shift(days: 1)
|
||||
expires_at = DateTime.utc_now() |> Timex.shift(days: 1)
|
||||
|
||||
assert {:ok, %{"type" => "Create", "expires_at" => ^expires_at}} =
|
||||
ActivityExpirationPolicy.filter(%{
|
||||
|
|
@ -35,7 +35,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
|
|||
end
|
||||
|
||||
test "overwrites existing `expires_at` if it greater than the config setting" do
|
||||
too_distant_future = NaiveDateTime.utc_now() |> Timex.shift(years: 2)
|
||||
too_distant_future = DateTime.utc_now() |> Timex.shift(years: 2)
|
||||
|
||||
assert {:ok, %{"type" => "Create", "expires_at" => expires_at}} =
|
||||
ActivityExpirationPolicy.filter(%{
|
||||
|
|
@ -46,7 +46,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicyTest do
|
|||
"object" => %{"type" => "Note"}
|
||||
})
|
||||
|
||||
assert Timex.diff(expires_at, NaiveDateTime.utc_now(), :days) == 364
|
||||
assert Timex.diff(expires_at, DateTime.utc_now(), :days) == 364
|
||||
end
|
||||
|
||||
test "ignores remote activities" do
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
defmodule Pleroma.Web.CommonAPITest do
|
||||
use Pleroma.DataCase
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Chat
|
||||
alias Pleroma.Conversation.Participation
|
||||
|
|
@ -598,15 +600,15 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
test "it can handle activities that expire" do
|
||||
user = insert(:user)
|
||||
|
||||
expires_at =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.truncate(:second)
|
||||
|> NaiveDateTime.add(1_000_000, :second)
|
||||
expires_at = DateTime.add(DateTime.utc_now(), 1_000_000)
|
||||
|
||||
assert {:ok, activity} = CommonAPI.post(user, %{status: "chai", expires_in: 1_000_000})
|
||||
|
||||
assert expiration = Pleroma.ActivityExpiration.get_by_activity_id(activity.id)
|
||||
assert expiration.scheduled_at == expires_at
|
||||
assert_enqueued(
|
||||
worker: Pleroma.Workers.PurgeExpiredActivity,
|
||||
args: %{activity_id: activity.id},
|
||||
scheduled_at: expires_at
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.ActivityExpiration
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Object
|
||||
|
|
@ -29,8 +29,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
setup do: oauth_access(["write:statuses"])
|
||||
|
||||
test "posting a status does not increment reblog_count when relaying", %{conn: conn} do
|
||||
Pleroma.Config.put([:instance, :federating], true)
|
||||
Pleroma.Config.get([:instance, :allow_relay], true)
|
||||
Config.put([:instance, :federating], true)
|
||||
Config.get([:instance, :allow_relay], true)
|
||||
|
||||
response =
|
||||
conn
|
||||
|
|
@ -103,7 +103,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
|
||||
# An activity that will expire:
|
||||
# 2 hours
|
||||
expires_in = 120 * 60
|
||||
expires_in = 2 * 60 * 60
|
||||
|
||||
expires_at = DateTime.add(DateTime.utc_now(), expires_in)
|
||||
|
||||
conn_four =
|
||||
conn
|
||||
|
|
@ -116,19 +118,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
assert fourth_response =
|
||||
%{"id" => fourth_id} = json_response_and_validate_schema(conn_four, 200)
|
||||
|
||||
assert activity = Activity.get_by_id(fourth_id)
|
||||
assert expiration = ActivityExpiration.get_by_activity_id(fourth_id)
|
||||
assert Activity.get_by_id(fourth_id)
|
||||
|
||||
estimated_expires_at =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.add(expires_in)
|
||||
|> NaiveDateTime.truncate(:second)
|
||||
|
||||
# This assert will fail if the test takes longer than a minute. I sure hope it never does:
|
||||
assert abs(NaiveDateTime.diff(expiration.scheduled_at, estimated_expires_at, :second)) < 60
|
||||
|
||||
assert fourth_response["pleroma"]["expires_at"] ==
|
||||
NaiveDateTime.to_iso8601(expiration.scheduled_at)
|
||||
assert_enqueued(
|
||||
worker: Pleroma.Workers.PurgeExpiredActivity,
|
||||
args: %{activity_id: fourth_id},
|
||||
scheduled_at: expires_at
|
||||
)
|
||||
end
|
||||
|
||||
test "it fails to create a status if `expires_in` is less or equal than an hour", %{
|
||||
|
|
@ -160,8 +156,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
end
|
||||
|
||||
test "Get MRF reason when posting a status is rejected by one", %{conn: conn} do
|
||||
Pleroma.Config.put([:mrf_keyword, :reject], ["GNO"])
|
||||
Pleroma.Config.put([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy])
|
||||
Config.put([:mrf_keyword, :reject], ["GNO"])
|
||||
Config.put([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy])
|
||||
|
||||
assert %{"error" => "[KeywordPolicy] Matches with rejected keyword"} =
|
||||
conn
|
||||
|
|
@ -1681,19 +1677,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
|||
|
||||
test "expires_at is nil for another user" do
|
||||
%{conn: conn, user: user} = oauth_access(["read:statuses"])
|
||||
expires_at = DateTime.add(DateTime.utc_now(), 1_000_000)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "foobar", expires_in: 1_000_000})
|
||||
|
||||
expires_at =
|
||||
activity.id
|
||||
|> ActivityExpiration.get_by_activity_id()
|
||||
|> Map.get(:scheduled_at)
|
||||
|> NaiveDateTime.to_iso8601()
|
||||
|
||||
assert %{"pleroma" => %{"expires_at" => ^expires_at}} =
|
||||
assert %{"pleroma" => %{"expires_at" => a_expires_at}} =
|
||||
conn
|
||||
|> get("/api/v1/statuses/#{activity.id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
{:ok, a_expires_at, 0} = DateTime.from_iso8601(a_expires_at)
|
||||
assert DateTime.diff(expires_at, a_expires_at) == 0
|
||||
|
||||
%{conn: conn} = oauth_access(["read:statuses"])
|
||||
|
||||
assert %{"pleroma" => %{"expires_at" => nil}} =
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Workers.Cron.PurgeExpiredActivitiesWorkerTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.ActivityExpiration
|
||||
alias Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker
|
||||
|
||||
import Pleroma.Factory
|
||||
import ExUnit.CaptureLog
|
||||
|
||||
setup do
|
||||
clear_config([ActivityExpiration, :enabled])
|
||||
end
|
||||
|
||||
test "deletes an expiration activity" do
|
||||
Pleroma.Config.put([ActivityExpiration, :enabled], true)
|
||||
activity = insert(:note_activity)
|
||||
|
||||
naive_datetime =
|
||||
NaiveDateTime.add(
|
||||
NaiveDateTime.utc_now(),
|
||||
-:timer.minutes(2),
|
||||
:millisecond
|
||||
)
|
||||
|
||||
expiration =
|
||||
insert(
|
||||
:expiration_in_the_past,
|
||||
%{activity_id: activity.id, scheduled_at: naive_datetime}
|
||||
)
|
||||
|
||||
Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(%Oban.Job{})
|
||||
|
||||
refute Pleroma.Repo.get(Pleroma.Activity, activity.id)
|
||||
refute Pleroma.Repo.get(Pleroma.ActivityExpiration, expiration.id)
|
||||
end
|
||||
|
||||
test "works with ActivityExpirationPolicy" do
|
||||
Pleroma.Config.put([ActivityExpiration, :enabled], true)
|
||||
|
||||
clear_config([:mrf, :policies], Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy)
|
||||
|
||||
user = insert(:user)
|
||||
|
||||
days = Pleroma.Config.get([:mrf_activity_expiration, :days], 365)
|
||||
|
||||
{:ok, %{id: id} = activity} = Pleroma.Web.CommonAPI.post(user, %{status: "cofe"})
|
||||
|
||||
past_date =
|
||||
NaiveDateTime.utc_now() |> Timex.shift(days: -days) |> NaiveDateTime.truncate(:second)
|
||||
|
||||
activity
|
||||
|> Repo.preload(:expiration)
|
||||
|> Map.get(:expiration)
|
||||
|> Ecto.Changeset.change(%{scheduled_at: past_date})
|
||||
|> Repo.update!()
|
||||
|
||||
Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(%Oban.Job{})
|
||||
|
||||
assert [%{data: %{"type" => "Delete", "deleted_activity_id" => ^id}}] =
|
||||
Pleroma.Repo.all(Pleroma.Activity)
|
||||
end
|
||||
|
||||
describe "delete_activity/1" do
|
||||
test "adds log message if activity isn't find" do
|
||||
assert capture_log([level: :error], fn ->
|
||||
PurgeExpiredActivitiesWorker.delete_activity(%ActivityExpiration{
|
||||
activity_id: "test-activity"
|
||||
})
|
||||
end) =~ "Couldn't delete expired activity: not found activity"
|
||||
end
|
||||
|
||||
test "adds log message if actor isn't find" do
|
||||
assert capture_log([level: :error], fn ->
|
||||
PurgeExpiredActivitiesWorker.delete_activity(%ActivityExpiration{
|
||||
activity_id: "test-activity"
|
||||
})
|
||||
end) =~ "Couldn't delete expired activity: not found activity"
|
||||
end
|
||||
end
|
||||
end
|
||||
47
test/workers/purge_expired_activity_test.exs
Normal file
47
test/workers/purge_expired_activity_test.exs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Workers.PurgeExpiredActivityTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
use Oban.Testing, repo: Pleroma.Repo
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Workers.PurgeExpiredActivity
|
||||
|
||||
test "denies expirations that don't live long enough" do
|
||||
activity = insert(:note_activity)
|
||||
|
||||
assert {:error, :expiration_too_close} =
|
||||
PurgeExpiredActivity.enqueue(%{
|
||||
activity_id: activity.id,
|
||||
expires_at: DateTime.utc_now()
|
||||
})
|
||||
|
||||
refute_enqueued(
|
||||
worker: Pleroma.Workers.PurgeExpiredActivity,
|
||||
args: %{activity_id: activity.id}
|
||||
)
|
||||
end
|
||||
|
||||
test "enqueue job" do
|
||||
activity = insert(:note_activity)
|
||||
|
||||
assert {:ok, _} =
|
||||
PurgeExpiredActivity.enqueue(%{
|
||||
activity_id: activity.id,
|
||||
expires_at: DateTime.add(DateTime.utc_now(), 3601)
|
||||
})
|
||||
|
||||
assert_enqueued(
|
||||
worker: Pleroma.Workers.PurgeExpiredActivity,
|
||||
args: %{activity_id: activity.id}
|
||||
)
|
||||
|
||||
assert {:ok, _} =
|
||||
perform_job(Pleroma.Workers.PurgeExpiredActivity, %{activity_id: activity.id})
|
||||
|
||||
assert %Oban.Job{} = Pleroma.Workers.PurgeExpiredActivity.get_expiration(activity.id)
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue