Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85803482
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
17 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
rPUBE pleroma-upstream
Attached
Detach File
Event Timeline
Log In to Comment