added verify RUM settings before start app
authorMaksim Pechnikov <parallel588@gmail.com>
Mon, 22 Jun 2020 14:27:49 +0000 (17:27 +0300)
committerMaksim Pechnikov <parallel588@gmail.com>
Mon, 22 Jun 2020 14:27:49 +0000 (17:27 +0300)
lib/pleroma/application.ex
lib/pleroma/application_requirements.ex [new file with mode: 0644]
lib/pleroma/repo.ex
priv/repo/optional_migrations/rum_indexing/20190510135645_add_fts_index_to_objects_two.exs
test/application_requirements_test.exs [new file with mode: 0644]
test/repo_test.exs

index 9d3d92b3835200249e073aaae57d6fd038d65e40..c30e5aadf94abfbf64624b08f52642bef897f8f1 100644 (file)
@@ -39,7 +39,7 @@ defmodule Pleroma.Application do
     Pleroma.HTML.compile_scrubbers()
     Config.DeprecationWarnings.warn()
     Pleroma.Plugs.HTTPSecurityPlug.warn_if_disabled()
-    Pleroma.Repo.check_migrations_applied!()
+    Pleroma.ApplicationRequirements.verify!()
     setup_instrumenters()
     load_custom_modules()
 
diff --git a/lib/pleroma/application_requirements.ex b/lib/pleroma/application_requirements.ex
new file mode 100644 (file)
index 0000000..3bba70b
--- /dev/null
@@ -0,0 +1,103 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.ApplicationRequirements do
+  @moduledoc """
+  The module represents the collection of validations to runs before start server.
+  """
+
+  defmodule VerifyError, do: defexception([:message])
+
+  import Ecto.Query
+
+  require Logger
+
+  @spec verify!() :: :ok | VerifyError.t()
+  def verify! do
+    :ok
+    |> check_migrations_applied!()
+    |> check_rum!()
+    |> handle_result()
+  end
+
+  defp handle_result(:ok), do: :ok
+  defp handle_result({:error, message}), do: raise(VerifyError, message: message)
+
+  defp check_migrations_applied!(:ok) do
+    unless Pleroma.Config.get(
+             [:i_am_aware_this_may_cause_data_loss, :disable_migration_check],
+             false
+           ) do
+      {_, res, _} =
+        Ecto.Migrator.with_repo(Pleroma.Repo, fn repo ->
+          down_migrations =
+            Ecto.Migrator.migrations(repo)
+            |> Enum.reject(fn
+              {:up, _, _} -> true
+              {:down, _, _} -> false
+            end)
+
+          if length(down_migrations) > 0 do
+            down_migrations_text =
+              Enum.map(down_migrations, fn {:down, id, name} -> "- #{name} (#{id})\n" end)
+
+            Logger.error(
+              "The following migrations were not applied:\n#{down_migrations_text}If you want to start Pleroma anyway, set\nconfig :pleroma, :i_am_aware_this_may_cause_data_loss, disable_migration_check: true"
+            )
+
+            {:error, "Unapplied Migrations detected"}
+          else
+            :ok
+          end
+        end)
+
+      res
+    else
+      :ok
+    end
+  end
+
+  defp check_migrations_applied!(result), do: result
+
+  defp check_rum!(:ok) do
+    {_, res, _} =
+      Ecto.Migrator.with_repo(Pleroma.Repo, fn repo ->
+        migrate =
+          from(o in "columns",
+            where: o.table_name == "objects",
+            where: o.column_name == "fts_content"
+          )
+          |> repo.exists?(prefix: "information_schema")
+
+        setting = Pleroma.Config.get([:database, :rum_enabled], false)
+
+        do_check_rum!(setting, migrate)
+      end)
+
+    res
+  end
+
+  defp check_rum!(result), do: result
+
+  defp do_check_rum!(setting, migrate) do
+    case {setting, migrate} do
+      {true, false} ->
+        Logger.error(
+          "Use `RUM` index is enabled, but were not applied migrations for it.\nIf you want to start Pleroma anyway, set\nconfig :pleroma, :database, rum_enabled: false\nOtherwise apply the following migrations:\n`mix ecto.migrate --migrations-path priv/repo/optional_migrations/rum_indexing/`"
+        )
+
+        {:error, "Unapplied RUM Migrations detected"}
+
+      {false, true} ->
+        Logger.error(
+          "Detected applied migrations to use `RUM` index, but `RUM` isn't enable in settings.\nIf you want to use `RUM`, set\nconfig :pleroma, :database, rum_enabled: true\nOtherwise roll `RUM` migrations back.\n`mix ecto.rollback --migrations-path priv/repo/optional_migrations/rum_indexing/`"
+        )
+
+        {:error, "RUM Migrations detected"}
+
+      _ ->
+        :ok
+    end
+  end
+end
index 6d85d70bc66c9ac6de1d0266c4937572402c2e95..f317e4d582e6cea6fee974190e30015797cffb8a 100644 (file)
@@ -11,9 +11,7 @@ defmodule Pleroma.Repo do
   import Ecto.Query
   require Logger
 
-  defmodule Instrumenter do
-    use Prometheus.EctoInstrumenter
-  end
+  defmodule Instrumenter, do: use(Prometheus.EctoInstrumenter)
 
   @doc """
   Dynamically loads the repository url from the
@@ -51,35 +49,6 @@ defmodule Pleroma.Repo do
     end
   end
 
-  def check_migrations_applied!() do
-    unless Pleroma.Config.get(
-             [:i_am_aware_this_may_cause_data_loss, :disable_migration_check],
-             false
-           ) do
-      Ecto.Migrator.with_repo(__MODULE__, fn repo ->
-        down_migrations =
-          Ecto.Migrator.migrations(repo)
-          |> Enum.reject(fn
-            {:up, _, _} -> true
-            {:down, _, _} -> false
-          end)
-
-        if length(down_migrations) > 0 do
-          down_migrations_text =
-            Enum.map(down_migrations, fn {:down, id, name} -> "- #{name} (#{id})\n" end)
-
-          Logger.error(
-            "The following migrations were not applied:\n#{down_migrations_text}If you want to start Pleroma anyway, set\nconfig :pleroma, :i_am_aware_this_may_cause_data_loss, disable_migration_check: true"
-          )
-
-          raise Pleroma.Repo.UnappliedMigrationsError
-        end
-      end)
-    else
-      :ok
-    end
-  end
-
   def chunk_stream(query, chunk_size) do
     # We don't actually need start and end funcitons of resource streaming,
     # but it seems to be the only way to not fetch records one-by-one and
@@ -107,7 +76,3 @@ defmodule Pleroma.Repo do
     )
   end
 end
-
-defmodule Pleroma.Repo.UnappliedMigrationsError do
-  defexception message: "Unapplied Migrations detected"
-end
index 79bde163d286f575a92753856f7ae845f042514c..757afa129fb3ec7e5a83bd4fbc28cb786183abd5 100644 (file)
@@ -2,29 +2,24 @@ defmodule Pleroma.Repo.Migrations.AddFtsIndexToObjectsTwo do
   use Ecto.Migration
 
   def up do
-    if Pleroma.Config.get([:database, :rum_enabled]) do
-      execute("create extension if not exists rum")
-      drop_if_exists index(:objects, ["(to_tsvector('english', data->>'content'))"], using: :gin, name: :objects_fts)
-      alter table(:objects) do
-        add(:fts_content, :tsvector)
-      end
+    execute("create extension if not exists rum")
+    drop_if_exists index(:objects, ["(to_tsvector('english', data->>'content'))"], using: :gin, name: :objects_fts)
+    alter table(:objects) do
+      add(:fts_content, :tsvector)
+    end
 
-      execute("CREATE FUNCTION objects_fts_update() RETURNS trigger AS $$
-      begin
-      new.fts_content := to_tsvector('english', new.data->>'content');
-      return new;
-      end
-      $$ LANGUAGE plpgsql")
-      execute("create index if not exists objects_fts on objects using RUM (fts_content rum_tsvector_addon_ops, inserted_at) with (attach = 'inserted_at', to = 'fts_content');")
+    execute("CREATE FUNCTION objects_fts_update() RETURNS trigger AS $$
+    begin
+    new.fts_content := to_tsvector('english', new.data->>'content');
+    return new;
+    end
+    $$ LANGUAGE plpgsql")
+    execute("create index if not exists objects_fts on objects using RUM (fts_content rum_tsvector_addon_ops, inserted_at) with (attach = 'inserted_at', to = 'fts_content');")
 
-      execute("CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE ON objects
-      FOR EACH ROW EXECUTE PROCEDURE objects_fts_update()")
+    execute("CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE ON objects
+    FOR EACH ROW EXECUTE PROCEDURE objects_fts_update()")
 
-      execute("UPDATE objects SET updated_at = NOW()")
-    else
-        raise Ecto.MigrationError,
-          message: "Migration is not allowed. You can change this behavior by setting `database/rum_enabled` to true."
-    end
+    execute("UPDATE objects SET updated_at = NOW()")
   end
 
   def down do
diff --git a/test/application_requirements_test.exs b/test/application_requirements_test.exs
new file mode 100644 (file)
index 0000000..0981fcd
--- /dev/null
@@ -0,0 +1,67 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.RepoTest do
+  use Pleroma.DataCase
+  import ExUnit.CaptureLog
+  import Mock
+
+  describe "check_rum!" do
+    setup_with_mocks([
+      {Ecto.Migrator, [],
+       [
+         with_repo: fn repo, fun -> passthrough([repo, fun]) end,
+         migrations: fn Pleroma.Repo -> [] end
+       ]}
+    ]) do
+      :ok
+    end
+
+    setup do: clear_config([:database, :rum_enabled])
+
+    test "raises if rum is enabled and  detects unapplied rum migrations" do
+      Pleroma.Config.put([:database, :rum_enabled], true)
+
+      assert_raise Pleroma.ApplicationRequirements.VerifyError,
+                   "Unapplied RUM Migrations detected",
+                   fn ->
+                     capture_log(&Pleroma.ApplicationRequirements.verify!/0)
+                   end
+    end
+  end
+
+  describe "check_migrations_applied!" do
+    setup_with_mocks([
+      {Ecto.Migrator, [],
+       [
+         with_repo: fn repo, fun -> passthrough([repo, fun]) end,
+         migrations: fn Pleroma.Repo ->
+           [
+             {:up, 20_191_128_153_944, "fix_missing_following_count"},
+             {:up, 20_191_203_043_610, "create_report_notes"},
+             {:down, 20_191_220_174_645, "add_scopes_to_pleroma_feo_auth_records"}
+           ]
+         end
+       ]}
+    ]) do
+      :ok
+    end
+
+    setup do: clear_config([:i_am_aware_this_may_cause_data_loss, :disable_migration_check])
+
+    test "raises if it detects unapplied migrations" do
+      assert_raise Pleroma.ApplicationRequirements.VerifyError,
+                   "Unapplied Migrations detected",
+                   fn ->
+                     capture_log(&Pleroma.ApplicationRequirements.verify!/0)
+                   end
+    end
+
+    test "doesn't do anything if disabled" do
+      Pleroma.Config.put([:i_am_aware_this_may_cause_data_loss, :disable_migration_check], true)
+
+      assert :ok == Pleroma.ApplicationRequirements.verify!()
+    end
+  end
+end
index daffc65427487492b2d5d4113f0889ece8648d9c..92e827c950fb68401b38d2327f8fdc00d963fe85 100644 (file)
@@ -4,9 +4,7 @@
 
 defmodule Pleroma.RepoTest do
   use Pleroma.DataCase
-  import ExUnit.CaptureLog
   import Pleroma.Factory
-  import Mock
 
   alias Pleroma.User
 
@@ -49,36 +47,4 @@ defmodule Pleroma.RepoTest do
       assert Repo.get_assoc(token, :user) == {:error, :not_found}
     end
   end
-
-  describe "check_migrations_applied!" do
-    setup_with_mocks([
-      {Ecto.Migrator, [],
-       [
-         with_repo: fn repo, fun -> passthrough([repo, fun]) end,
-         migrations: fn Pleroma.Repo ->
-           [
-             {:up, 20_191_128_153_944, "fix_missing_following_count"},
-             {:up, 20_191_203_043_610, "create_report_notes"},
-             {:down, 20_191_220_174_645, "add_scopes_to_pleroma_feo_auth_records"}
-           ]
-         end
-       ]}
-    ]) do
-      :ok
-    end
-
-    setup do: clear_config([:i_am_aware_this_may_cause_data_loss, :disable_migration_check])
-
-    test "raises if it detects unapplied migrations" do
-      assert_raise Pleroma.Repo.UnappliedMigrationsError, fn ->
-        capture_log(&Repo.check_migrations_applied!/0)
-      end
-    end
-
-    test "doesn't do anything if disabled" do
-      Pleroma.Config.put([:i_am_aware_this_may_cause_data_loss, :disable_migration_check], true)
-
-      assert :ok == Repo.check_migrations_applied!()
-    end
-  end
 end