Page MenuHomePhorge

No OneTemporary

Size
17 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index 8e1c5de0d..4b6c2704d 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -1,292 +1,293 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Application do
use Application
import Cachex.Spec
alias Pleroma.Config
require Logger
@name Mix.Project.config()[:name]
@version Mix.Project.config()[:version]
@repository Mix.Project.config()[:source_url]
def name, do: @name
def version, do: @version
def named_version, do: @name <> " " <> @version
def repository, do: @repository
def user_agent do
if Process.whereis(Pleroma.Web.Endpoint) do
case Config.get([:http, :user_agent], :default) do
:default ->
info = "#{Pleroma.Web.Endpoint.url()} <#{Config.get([:instance, :email], "")}>"
named_version() <> "; " <> info
custom ->
custom
end
else
# fallback, if endpoint is not started yet
"Pleroma Data Loader"
end
end
# See http://elixir-lang.org/docs/stable/elixir/Application.html
# for more information on OTP Applications
def start(_type, _args) do
# Scrubbers are compiled at runtime and therefore will cause a conflict
# every time the application is restarted, so we disable module
# conflicts at runtime
Code.compiler_options(ignore_module_conflict: true)
Pleroma.Telemetry.Logger.attach()
Config.Holder.save_default()
Pleroma.HTML.compile_scrubbers()
Pleroma.Config.Oban.warn()
Config.DeprecationWarnings.warn()
if Config.get([Pleroma.Web.Plugs.HTTPSecurityPlug, :enable], true) do
Pleroma.Web.Plugs.HTTPSecurityPlug.warn_if_disabled()
end
if Config.get(:env) != :test do
Pleroma.ApplicationRequirements.verify!()
end
load_custom_modules()
Pleroma.Docs.JSON.compile()
limiters_setup()
adapter = Application.get_env(:tesla, :adapter)
if match?({Tesla.Adapter.Finch, _}, adapter) do
Logger.info("Starting Finch")
Finch.start_link(name: MyFinch)
end
# Disable warnings_as_errors at runtime, it breaks Phoenix live reload
# due to protocol consolidation warnings
# :warnings_as_errors is deprecated via Code.compiler_options/2 since 1.18
if Version.compare(System.version(), "1.18.0") == :lt do
Code.compiler_options(warnings_as_errors: false)
end
# Define workers and child supervisors to be supervised
children =
[
Pleroma.PromEx,
Pleroma.LDAP,
Pleroma.Repo,
Config.TransferTask,
Pleroma.Emoji,
Pleroma.Web.Plugs.RateLimiter.Supervisor,
{Task.Supervisor, name: Pleroma.TaskSupervisor}
] ++
cachex_children() ++
http_children(adapter) ++
[
Pleroma.Stats,
Pleroma.JobQueueMonitor,
{Majic.Pool, [name: Pleroma.MajicPool, pool_size: Config.get([:majic_pool, :size], 2)]},
{Oban, Config.get(Oban)},
Pleroma.Web.Endpoint
] ++
task_children() ++
streamer_registry() ++
background_migrators() ++
shout_child(shout_enabled?()) ++
[Pleroma.Gopher.Server] ++
[Pleroma.Search.Healthcheck]
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
# for other strategies and supported options
# If we have a lot of caches, default max_restarts can cause test
# resets to fail.
# Go for the default 3 unless we're in test
max_restarts = Application.get_env(:pleroma, __MODULE__)[:max_restarts]
opts = [strategy: :one_for_one, name: Pleroma.Supervisor, max_restarts: max_restarts]
Supervisor.start_link(children, opts)
end
def load_custom_modules do
dir = Config.get([:modules, :runtime_dir])
if dir && File.exists?(dir) do
dir
|> Pleroma.Utils.compile_dir()
|> case do
{:error, _errors, _warnings} ->
raise "Invalid custom modules"
{:ok, modules, _warnings} ->
if Application.get_env(:pleroma, __MODULE__)[:load_custom_modules] do
Enum.each(modules, fn mod ->
Logger.info("Custom module loaded: #{inspect(mod)}")
end)
end
:ok
end
end
end
defp cachex_children do
[
build_cachex("used_captcha", ttl_interval: seconds_valid_interval()),
build_cachex("user", default_ttl: 25_000, ttl_interval: 1000, limit: 2500),
build_cachex("object", default_ttl: 25_000, ttl_interval: 1000, limit: 2500),
build_cachex("rich_media", default_ttl: :timer.minutes(120), limit: 5000),
build_cachex("scrubber", limit: 2500),
build_cachex("scrubber_management", limit: 2500),
build_cachex("idempotency", expiration: idempotency_expiration(), limit: 2500),
build_cachex("web_resp", limit: 2500),
build_cachex("emoji_packs", expiration: emoji_packs_expiration(), limit: 10),
build_cachex("failed_proxy_url", limit: 2500),
build_cachex("failed_media_helper_url", default_ttl: :timer.minutes(15), limit: 2_500),
build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000),
build_cachex("chat_message_id_idempotency_key",
expiration: chat_message_id_idempotency_key_expiration(),
limit: 500_000
),
build_cachex("rel_me", limit: 2500),
build_cachex("host_meta", default_ttl: :timer.minutes(120), limit: 5_000),
build_cachex("translations", default_ttl: :timer.hours(24), limit: 5_000)
]
end
defp emoji_packs_expiration,
do: expiration(default: :timer.seconds(5 * 60), interval: :timer.seconds(60))
defp idempotency_expiration,
do: expiration(default: :timer.seconds(6 * 60 * 60), interval: :timer.seconds(60))
defp chat_message_id_idempotency_key_expiration,
do: expiration(default: :timer.minutes(2), interval: :timer.seconds(60))
defp seconds_valid_interval,
do: :timer.seconds(Config.get!([Pleroma.Captcha, :seconds_valid]))
@spec build_cachex(String.t(), keyword()) :: map()
def build_cachex(type, opts),
do: %{
id: String.to_atom("cachex_" <> type),
start: {Cachex, :start_link, [String.to_atom(type <> "_cache"), opts]},
type: :worker
}
defp shout_enabled?, do: Config.get([:shout, :enabled])
defp streamer_registry do
if Application.get_env(:pleroma, __MODULE__)[:streamer_registry] do
[
{Registry,
[
name: Pleroma.Web.Streamer.registry(),
keys: :duplicate,
partitions: System.schedulers_online()
]}
]
else
[]
end
end
defp background_migrators do
if Application.get_env(:pleroma, __MODULE__)[:background_migrators] do
[
Pleroma.Migrators.HashtagsTableMigrator,
- Pleroma.Migrators.ContextObjectsDeletionMigrator
+ Pleroma.Migrators.ContextObjectsDeletionMigrator,
+ Pleroma.Migrators.RelayActorTypeMigrator
]
else
[]
end
end
defp shout_child(true) do
[
Pleroma.Web.ShoutChannel.ShoutChannelState,
{Phoenix.PubSub, [name: Pleroma.PubSub, adapter: Phoenix.PubSub.PG2]}
]
end
defp shout_child(_), do: []
defp task_children do
children = [
%{
id: :web_push_init,
start: {Task, :start_link, [&Pleroma.Web.Push.init/0]},
restart: :temporary
}
]
if Application.get_env(:pleroma, __MODULE__)[:internal_fetch] do
children ++
[
%{
id: :internal_fetch_init,
start: {Task, :start_link, [&Pleroma.Web.ActivityPub.InternalFetchActor.init/0]},
restart: :temporary
}
]
else
children
end
end
# start hackney and gun pools in tests
defp http_children(adapter) do
if Application.get_env(:pleroma, __MODULE__)[:test_http_pools] do
http_children_hackney() ++ http_children_gun()
else
cond do
match?(Tesla.Adapter.Hackney, adapter) -> http_children_hackney()
match?(Tesla.Adapter.Gun, adapter) -> http_children_gun()
true -> []
end
end
end
defp http_children_hackney do
pools = [:federation, :media]
pools =
if Config.get([Pleroma.Upload, :proxy_remote]) do
[:upload | pools]
else
pools
end
for pool <- pools do
options = Config.get([:hackney_pools, pool])
:hackney_pool.child_spec(pool, options)
end
end
defp http_children_gun do
Pleroma.Gun.ConnectionPool.children() ++
[{Task, &Pleroma.HTTP.AdapterHelper.Gun.limiter_setup/0}]
end
@spec limiters_setup() :: :ok
def limiters_setup do
config = Config.get(ConcurrentLimiter, [])
[
Pleroma.Search
]
|> Enum.each(fn module ->
mod_config = Keyword.get(config, module, [])
max_running = Keyword.get(mod_config, :max_running, 5)
max_waiting = Keyword.get(mod_config, :max_waiting, 5)
ConcurrentLimiter.new(module, max_running, max_waiting)
end)
end
end
diff --git a/lib/pleroma/data_migration.ex b/lib/pleroma/data_migration.ex
index be4bf6489..d2bb244a2 100644
--- a/lib/pleroma/data_migration.ex
+++ b/lib/pleroma/data_migration.ex
@@ -1,48 +1,49 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.DataMigration do
use Ecto.Schema
alias Pleroma.DataMigration
alias Pleroma.DataMigration.State
alias Pleroma.Repo
import Ecto.Changeset
import Ecto.Query
@type t :: %__MODULE__{}
schema "data_migrations" do
field(:name, :string)
field(:state, State, default: :pending)
field(:feature_lock, :boolean, default: false)
field(:params, :map, default: %{})
field(:data, :map, default: %{})
timestamps()
end
def changeset(data_migration, params \\ %{}) do
data_migration
|> cast(params, [:name, :state, :feature_lock, :params, :data])
|> validate_required([:name])
|> unique_constraint(:name)
end
def update_one_by_id(id, params \\ %{}) do
with {1, _} <-
from(dm in DataMigration, where: dm.id == ^id)
|> Repo.update_all(set: params) do
:ok
end
end
def get_by_name(name) do
Repo.get_by(DataMigration, name: name)
end
def populate_hashtags_table, do: get_by_name("populate_hashtags_table")
def delete_context_objects, do: get_by_name("delete_context_objects")
+ def update_relay_actor_type, do: get_by_name("update_relay_actor_type")
end
diff --git a/lib/pleroma/migrators/relay_actor_type_migrator.ex b/lib/pleroma/migrators/relay_actor_type_migrator.ex
new file mode 100644
index 000000000..a74c3a826
--- /dev/null
+++ b/lib/pleroma/migrators/relay_actor_type_migrator.ex
@@ -0,0 +1,144 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Migrators.RelayActorTypeMigrator do
+ defmodule State do
+ use Pleroma.Migrators.Support.BaseMigratorState
+
+ @impl Pleroma.Migrators.Support.BaseMigratorState
+ defdelegate data_migration(), to: Pleroma.DataMigration, as: :update_relay_actor_type
+ end
+
+ import Ecto.Changeset
+
+ use Pleroma.Migrators.Support.BaseMigrator
+
+ alias Pleroma.Migrators.Support.BaseMigrator
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Builder
+ alias Pleroma.Web.ActivityPub.Pipeline
+
+ @doc "This migration updates relay actor type to 'Application'."
+
+ @impl BaseMigrator
+ def feature_config_path, do: [:features, :update_relay_actor_type]
+
+ @impl BaseMigrator
+ def fault_rate_allowance, do: 0
+
+ @impl BaseMigrator
+ def perform do
+ # data_migration_id = data_migration_id()
+ max_processed_id = get_stat(:max_processed_id, 0)
+
+ Logger.info("Migrating local relay actor types (from uid: #{max_processed_id})...")
+
+ query()
+ |> Repo.chunk_stream(1, :batches, timeout: :infinity)
+ |> Stream.each(fn users ->
+ user_ids = Enum.map(users, fn user -> user.id end)
+
+ results = Enum.map(users, &update_relay_actor_type(&1))
+
+ # failed_ids =
+ # results
+ # |> Enum.filter(&(elem(&1, 0) == :error))
+ # |> Enum.map(&elem(&1, 1))
+
+ chunk_affected_count =
+ results
+ # |> Enum.filter(&(elem(&1, 0) == :ok))
+ |> length()
+
+ # for failed_id <- failed_ids do
+ # _ =
+ # Repo.query(
+ # "INSERT INTO data_migration_failed_ids(data_migration_id, record_id) " <>
+ # "VALUES ($1, $2) ON CONFLICT DO NOTHING;",
+ # [data_migration_id, failed_id]
+ # )
+ # end
+
+ # _ =
+ # Repo.query(
+ # "DELETE FROM data_migration_failed_ids " <>
+ # "WHERE data_migration_id = $1 AND record_id = ANY($2)",
+ # [data_migration_id, user_ids -- failed_ids]
+ # )
+
+ max_user_id = Enum.at(user_ids, -1)
+
+ put_stat(:max_processed_id, max_user_id)
+ increment_stat(:iteration_processed_count, length(user_ids))
+ increment_stat(:processed_count, length(user_ids))
+ increment_stat(:failed_count, 0)
+ increment_stat(:affected_count, chunk_affected_count)
+ put_stat(:records_per_second, records_per_second())
+ persist_state()
+ end)
+ |> Stream.run()
+ end
+
+ @impl BaseMigrator
+ def query do
+ ap_id = Pleroma.Web.ActivityPub.Relay.ap_id()
+
+ from(
+ u in User,
+ where: u.local == true and u.ap_id == ^ap_id and u.actor_type == "Person"
+ )
+ end
+
+ @spec update_relay_actor_type(User.t()) :: {:ok | :error, integer()}
+ defp update_relay_actor_type(user) do
+ with changeset <- cast(user, %{actor_type: "Application"}, [:actor_type]),
+ {:ok, unpersisted_user} <- Ecto.Changeset.apply_action(changeset, :update),
+ updated_object <-
+ Pleroma.Web.ActivityPub.UserView.render("user.json", user: unpersisted_user)
+ |> Map.delete("@context"),
+ {:ok, update_data, []} <- Builder.update(user, updated_object),
+ {:ok, _update, _} <-
+ Pipeline.common_pipeline(update_data,
+ local: true,
+ user_update_changeset: changeset
+ ) do
+ {:ok, user.id}
+ else
+ _ -> {:error, user.id}
+ end
+ end
+
+ @impl BaseMigrator
+ def retry_failed do
+ data_migration_id = data_migration_id()
+
+ failed_objects_query()
+ |> Repo.chunk_stream(100, :one)
+ |> Stream.each(fn user ->
+ with {res, _} when res != :error <- update_relay_actor_type(user) do
+ _ =
+ Repo.query(
+ "DELETE FROM data_migration_failed_ids " <>
+ "WHERE data_migration_id = $1 AND record_id = $2",
+ [data_migration_id, user.id]
+ )
+ end
+ end)
+ |> Stream.run()
+
+ put_stat(:failed_count, failures_count())
+ persist_state()
+
+ force_continue()
+ end
+
+ defp failed_objects_query do
+ from(u in User)
+ |> join(:inner, [u], dmf in fragment("SELECT * FROM data_migration_failed_ids"),
+ on: dmf.record_id == u.id
+ )
+ |> where([_u, dmf], dmf.data_migration_id == ^data_migration_id())
+ |> order_by([u], asc: u.id)
+ end
+end
diff --git a/priv/repo/migrations/20230811140000_change_relay_actor_type.exs b/priv/repo/migrations/20230811140000_change_relay_actor_type.exs
deleted file mode 100644
index ddc87d680..000000000
--- a/priv/repo/migrations/20230811140000_change_relay_actor_type.exs
+++ /dev/null
@@ -1,20 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Repo.Migrations.ChangeRelayActorType do
- use Ecto.Migration
-
- alias Pleroma.Repo
- alias Pleroma.User
-
- def change do
- relay = Repo.get_by(User, nickname: "relay")
-
- if relay != nil and User.invisible?(relay) do
- relay
- |> Ecto.Changeset.change(actor_type: "Application")
- |> Repo.update()
- end
- end
-end
diff --git a/priv/repo/migrations/20240403000000_data_migration_update_relay_actor_type.exs b/priv/repo/migrations/20240403000000_data_migration_update_relay_actor_type.exs
new file mode 100644
index 000000000..716ecc9b6
--- /dev/null
+++ b/priv/repo/migrations/20240403000000_data_migration_update_relay_actor_type.exs
@@ -0,0 +1,20 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Repo.Migrations.DataMigrationUpdateRelayActorType do
+ use Ecto.Migration
+
+ def up do
+ dt = NaiveDateTime.utc_now()
+
+ execute(
+ "INSERT INTO data_migrations(name, inserted_at, updated_at) " <>
+ "VALUES ('update_relay_actor_type', '#{dt}', '#{dt}') ON CONFLICT DO NOTHING;"
+ )
+ end
+
+ def down do
+ execute("DELETE FROM data_migrations WHERE name = 'update_relay_actor_type';")
+ end
+end

File Metadata

Mime Type
text/x-diff
Expires
Fri, Oct 9, 8:05 AM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1784542
Default Alt Text
(17 KB)

Event Timeline