Add activity expirations table
authorMike Verdone <spiral@arcseconds.net>
Mon, 22 Jul 2019 12:16:20 +0000 (14:16 +0200)
committerMike Verdone <spiral@arcseconds.net>
Wed, 24 Jul 2019 11:14:52 +0000 (13:14 +0200)
Add a table to store activity expirations. An activity can have zero or
one expirations. The expiration has a scheduled_at field which stores
the time at which the activity should expire and be deleted.

lib/pleroma/activity.ex
lib/pleroma/activity_expiration.ex [new file with mode: 0644]
priv/repo/migrations/20190716100804_add_expirations_table.exs [new file with mode: 0644]
test/activity_expiration_test.exs [new file with mode: 0644]
test/activity_test.exs
test/support/factory.ex

index 46552c7be67a25465dbdaab02a1f46013ce3b166..be485056018bb12c1e28d1a891736a216f53a027 100644 (file)
@@ -6,6 +6,7 @@ defmodule Pleroma.Activity do
   use Ecto.Schema
 
   alias Pleroma.Activity
+  alias Pleroma.ActivityExpiration
   alias Pleroma.Bookmark
   alias Pleroma.Notification
   alias Pleroma.Object
@@ -59,6 +60,8 @@ defmodule Pleroma.Activity do
     # typical case.
     has_one(:object, Object, on_delete: :nothing, foreign_key: :id)
 
+    has_one(:expiration, ActivityExpiration, on_delete: :delete_all)
+
     timestamps()
   end
 
diff --git a/lib/pleroma/activity_expiration.ex b/lib/pleroma/activity_expiration.ex
new file mode 100644 (file)
index 0000000..d3d95f9
--- /dev/null
@@ -0,0 +1,31 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.ActivityExpiration do
+  use Ecto.Schema
+
+  alias Pleroma.Activity
+  alias Pleroma.ActivityExpiration
+  alias Pleroma.FlakeId
+  alias Pleroma.Repo
+
+  import Ecto.Query
+
+  @type t :: %__MODULE__{}
+
+  schema "activity_expirations" do
+    belongs_to(:activity, Activity, type: FlakeId)
+    field(:scheduled_at, :naive_datetime)
+  end
+
+  def due_expirations(offset \\ 0) do
+    naive_datetime =
+      NaiveDateTime.utc_now()
+      |> NaiveDateTime.add(offset, :millisecond)
+
+    ActivityExpiration
+    |> where([exp], exp.scheduled_at < ^naive_datetime)
+    |> Repo.all()
+  end
+end
diff --git a/priv/repo/migrations/20190716100804_add_expirations_table.exs b/priv/repo/migrations/20190716100804_add_expirations_table.exs
new file mode 100644 (file)
index 0000000..fbde8f9
--- /dev/null
@@ -0,0 +1,10 @@
+defmodule Pleroma.Repo.Migrations.AddExpirationsTable do
+  use Ecto.Migration
+
+  def change do
+    create_if_not_exists table(:activity_expirations) do
+      add(:activity_id, references(:activities, type: :uuid, on_delete: :delete_all))
+      add(:scheduled_at, :naive_datetime, null: false)
+    end
+  end
+end
diff --git a/test/activity_expiration_test.exs b/test/activity_expiration_test.exs
new file mode 100644 (file)
index 0000000..20566a1
--- /dev/null
@@ -0,0 +1,21 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2019 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
+
+  test "finds activities due to be deleted only" do
+    activity = insert(:note_activity)
+    expiration_due = insert(:expiration_in_the_past, %{activity_id: activity.id})
+    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
+end
index b27f6fd369ac82f20f07ee6f84445eafdf12cf1d..785c4b3cf2bff8897fe655f960a7b900ac8f8b45 100644 (file)
@@ -164,4 +164,13 @@ defmodule Pleroma.ActivityTest do
       Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
     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
 end
index c751546ce46bbf4edc6aedd14b824b29f4f3286c..7b52b13283fde34f4f5818663c6b2653b1372c14 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Factory do
@@ -142,6 +142,23 @@ defmodule Pleroma.Factory do
     |> Map.merge(attrs)
   end
 
+  defp expiration_offset_by_minutes(attrs, minutes) do
+    %Pleroma.ActivityExpiration{}
+    |> Map.merge(attrs)
+    |> Map.put(
+      :scheduled_at,
+      NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(minutes), :millisecond)
+    )
+  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, 60)
+  end
+
   def article_activity_factory do
     article = insert(:article)