Add mix task to add expiration to all local statuses
authorEgor Kislitsyn <egor@kislitsyn.com>
Sat, 8 Aug 2020 12:29:40 +0000 (16:29 +0400)
committerEgor Kislitsyn <egor@kislitsyn.com>
Sat, 8 Aug 2020 12:29:40 +0000 (16:29 +0400)
docs/administration/CLI_tasks/database.md
lib/mix/tasks/pleroma/database.ex
lib/pleroma/activity_expiration.ex
test/tasks/database_test.exs

index 647f6f27467aa87689a518b54cb7467daf02b52d..64dd66c0cc0391ce1f144ed3e07a5e6be4a65958 100644 (file)
@@ -97,4 +97,14 @@ but should only be run if necessary. **It is safe to cancel this.**
 
 ```sh tab="From Source"
 mix pleroma.database vacuum full
-```
\ No newline at end of file
+```
+
+## Add expiration to all local statuses
+
+```sh tab="OTP"
+./bin/pleroma_ctl database ensure_expiration
+```
+
+```sh tab="From Source"
+mix pleroma.database ensure_expiration
+```
index 82e2abdcbd9a2056441430000caf6a8d695a1841..d57e59b113da8e40787e0d5088ee83b91f72a17c 100644 (file)
@@ -10,6 +10,7 @@ defmodule Mix.Tasks.Pleroma.Database do
   alias Pleroma.User
   require Logger
   require Pleroma.Constants
+  import Ecto.Query
   import Mix.Pleroma
   use Mix.Task
 
@@ -53,8 +54,6 @@ defmodule Mix.Tasks.Pleroma.Database do
   end
 
   def run(["prune_objects" | args]) do
-    import Ecto.Query
-
     {options, [], []} =
       OptionParser.parse(
         args,
@@ -94,8 +93,6 @@ defmodule Mix.Tasks.Pleroma.Database do
   end
 
   def run(["fix_likes_collections"]) do
-    import Ecto.Query
-
     start_pleroma()
 
     from(object in Object,
@@ -130,4 +127,23 @@ defmodule Mix.Tasks.Pleroma.Database do
 
     Maintenance.vacuum(args)
   end
+
+  def run(["ensure_expiration"]) do
+    start_pleroma()
+    days = Pleroma.Config.get([:mrf_activity_expiration, :days], 365)
+
+    Pleroma.Activity
+    |> join(:left, [a], u in assoc(a, :expiration))
+    |> where(local: true)
+    |> where([a, u], is_nil(u))
+    |> Pleroma.RepoStreamer.chunk_stream(100)
+    |> Stream.each(fn activities ->
+      Enum.each(activities, fn activity ->
+        expires_at = Timex.shift(activity.inserted_at, days: days)
+
+        Pleroma.ActivityExpiration.create(activity, expires_at, false)
+      end)
+    end)
+    |> Stream.run()
+  end
 end
index db9c88d84b4a5039e22620d3333b6247e8a3662f..7cc9668b373cc252cf0f42d812cc459e4c321324 100644 (file)
@@ -20,11 +20,11 @@ defmodule Pleroma.ActivityExpiration do
     field(:scheduled_at, :naive_datetime)
   end
 
-  def changeset(%ActivityExpiration{} = expiration, attrs) do
+  def changeset(%ActivityExpiration{} = expiration, attrs, validate_scheduled_at) do
     expiration
     |> cast(attrs, [:scheduled_at])
     |> validate_required([:scheduled_at])
-    |> validate_scheduled_at()
+    |> validate_scheduled_at(validate_scheduled_at)
   end
 
   def get_by_activity_id(activity_id) do
@@ -33,9 +33,9 @@ defmodule Pleroma.ActivityExpiration do
     |> Repo.one()
   end
 
-  def create(%Activity{} = activity, scheduled_at) do
+  def create(%Activity{} = activity, scheduled_at, validate_scheduled_at \\ true) do
     %ActivityExpiration{activity_id: activity.id}
-    |> changeset(%{scheduled_at: scheduled_at})
+    |> changeset(%{scheduled_at: scheduled_at}, validate_scheduled_at)
     |> Repo.insert()
   end
 
@@ -49,7 +49,9 @@ defmodule Pleroma.ActivityExpiration do
     |> Repo.all()
   end
 
-  def validate_scheduled_at(changeset) do
+  def validate_scheduled_at(changeset, false), do: changeset
+
+  def validate_scheduled_at(changeset, true) do
     validate_change(changeset, :scheduled_at, fn _, scheduled_at ->
       if not expires_late_enough?(scheduled_at) do
         [scheduled_at: "an ephemeral activity must live for at least one hour"]
index 883828d7731cb132268edf2d0128f471a6762f8f..3a28aa1330c86bd2276c6b6f241231da7a22d94e 100644 (file)
@@ -127,4 +127,43 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do
       assert Enum.empty?(Object.get_by_id(object2.id).data["likes"])
     end
   end
+
+  describe "ensure_expiration" do
+    test "it adds to expiration old statuses" do
+      %{id: activity_id1} = insert(:note_activity)
+
+      %{id: activity_id2} =
+        insert(:note_activity, %{inserted_at: NaiveDateTime.from_iso8601!("2015-01-23 23:50:07")})
+
+      %{id: activity_id3} = activity3 = insert(:note_activity)
+
+      expires_at =
+        NaiveDateTime.utc_now()
+        |> NaiveDateTime.add(60 * 61, :second)
+        |> NaiveDateTime.truncate(:second)
+
+      Pleroma.ActivityExpiration.create(activity3, expires_at)
+
+      Mix.Tasks.Pleroma.Database.run(["ensure_expiration"])
+
+      expirations =
+        Pleroma.ActivityExpiration
+        |> order_by(:activity_id)
+        |> Repo.all()
+
+      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
+    end
+  end
 end