Page MenuHomePhorge

No OneTemporary

Size
14 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index 27ed91554..b1ad67ee8 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -1,171 +1,171 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Application do
use Application
alias Pleroma.Config
require Logger
@name Mix.Project.config()[:name]
@version Mix.Project.config()[:version]
@repository Mix.Project.config()[:source_url]
@env Mix.env()
@type env() :: :test | :benchmark | :dev | :prod
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.base_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)
# Disable warnings_as_errors at runtime, it breaks Phoenix live reload
# due to protocol consolidation warnings
Code.compiler_options(warnings_as_errors: false)
Pleroma.Telemetry.Logger.attach()
Config.Holder.save_default()
Pleroma.HTML.compile_scrubbers()
Pleroma.Config.Oban.warn()
Config.DeprecationWarnings.warn()
Pleroma.Plugs.HTTPSecurityPlug.warn_if_disabled()
Pleroma.Application.Requirements.verify!()
setup_instrumenters()
load_custom_modules()
check_system_commands()
Pleroma.Docs.JSON.compile()
if Application.get_env(:tesla, :adapter) == Tesla.Adapter.Gun do
if version = Pleroma.OTPVersion.version() do
[major, minor] =
version
|> String.split(".")
|> Enum.map(&String.to_integer/1)
|> Enum.take(2)
if (major == 22 and minor < 2) or major < 22 do
raise "
!!!OTP VERSION WARNING!!!
You are using gun adapter with OTP version #{version}, which doesn't support correct handling of unordered certificates chains. Please update your Erlang/OTP to at least 22.2.
"
end
else
raise "
!!!OTP VERSION WARNING!!!
To support correct handling of unordered certificates chains - OTP version must be > 22.2.
"
end
end
# Define workers and child supervisors to be supervised
children = [
Pleroma.Repo,
Pleroma.Application.DynamicSupervisor,
- {Registry, keys: :duplicate, name: Pleroma.Application.DynamicSupervisor.registry()}
+ Pleroma.Application.Agent
]
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
# for other strategies and supported options
Supervisor.start_link(children, strategy: :one_for_one, name: Pleroma.Supervisor)
end
def start_phase(:update_env, :normal, _args) do
# Load and update the environment from the config settings in the database
Pleroma.Config.Environment.load_and_update()
end
def start_phase(:static_children, :normal, _args) do
# Start static children,
# which don't require any configuration or can be configured in runtime
Pleroma.Application.Static.start_children(@env)
end
def start_phase(:dynamic_children, :normal, _args) do
# Start dynamic children,
# which require restart after some config changes
Pleroma.Application.DynamicSupervisor.start_children(@env)
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 @env != :test do
Enum.each(modules, fn mod ->
Logger.info("Custom module loaded: #{inspect(mod)}")
end)
end
:ok
end
end
end
defp setup_instrumenters do
require Prometheus.Registry
if Application.get_env(:prometheus, Pleroma.Repo.Instrumenter) do
:ok =
:telemetry.attach(
"prometheus-ecto",
[:pleroma, :repo, :query],
&Pleroma.Repo.Instrumenter.handle_event/4,
%{}
)
Pleroma.Repo.Instrumenter.setup()
end
Pleroma.Web.Endpoint.MetricsExporter.setup()
Pleroma.Web.Endpoint.PipelineInstrumenter.setup()
Pleroma.Web.Endpoint.Instrumenter.setup()
end
defp check_system_commands do
filters = Config.get([Pleroma.Upload, :filters])
check_filter = fn filter, command_required ->
with true <- filter in filters,
false <- Pleroma.Utils.command_available?(command_required) do
Logger.error(
"#{filter} is specified in list of Pleroma.Upload filters, but the #{command_required} command is not found"
)
end
end
check_filter.(Pleroma.Upload.Filters.Exiftool, "exiftool")
check_filter.(Pleroma.Upload.Filters.Mogrify, "mogrify")
check_filter.(Pleroma.Upload.Filters.Mogrifun, "mogrify")
end
end
diff --git a/lib/pleroma/application/agent.ex b/lib/pleroma/application/agent.ex
new file mode 100644
index 000000000..cf37ef952
--- /dev/null
+++ b/lib/pleroma/application/agent.ex
@@ -0,0 +1,45 @@
+# # Pleroma: A lightweight social networking server
+# # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# # SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Application.Agent do
+ use Agent
+
+ def start_link(_) do
+ Agent.start_link(fn -> %{reboot_paths: [], pids: %{}} end, name: __MODULE__)
+ end
+
+ @spec pid(any()) :: pid()
+ def pid(key) do
+ Agent.get(__MODULE__, fn state -> state[:pids][key] end)
+ end
+
+ @spec put_pid(any(), pid()) :: :ok
+ def put_pid(key, pid) do
+ Agent.update(__MODULE__, fn state -> put_in(state, [:pids, key], pid) end)
+ end
+
+ @spec delete_pid(any()) :: :ok
+ def delete_pid(key) do
+ Agent.update(__MODULE__, fn state -> put_in(state[:pids], Map.delete(state[:pids], key)) end)
+ end
+
+ @spec put_paths([any()]) :: :ok
+ def put_paths(paths) do
+ Agent.update(__MODULE__, fn state ->
+ put_in(state[:reboot_paths], Enum.uniq(state[:reboot_paths] ++ paths))
+ end)
+ end
+
+ @spec get_and_reset_paths() :: [any()]
+ def get_and_reset_paths do
+ Agent.get_and_update(__MODULE__, fn state ->
+ {state[:reboot_paths], put_in(state[:reboot_paths], [])}
+ end)
+ end
+
+ @spec paths() :: [any()]
+ def paths do
+ Agent.get(__MODULE__, fn state -> state[:reboot_paths] end)
+ end
+end
diff --git a/lib/pleroma/application/dynamic_supervisor.ex b/lib/pleroma/application/dynamic_supervisor.ex
index d1c683a5b..54af19e63 100644
--- a/lib/pleroma/application/dynamic_supervisor.ex
+++ b/lib/pleroma/application/dynamic_supervisor.ex
@@ -1,222 +1,191 @@
# # Pleroma: A lightweight social networking server
# # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Application.DynamicSupervisor do
use DynamicSupervisor
require Logger
- @registry Pleroma.Application.DynamicSupervisor.Registry
-
@type child() ::
Supervisor.child_spec()
| {module(), term()}
| module()
def start_link(_), do: DynamicSupervisor.start_link(__MODULE__, :no_arg, name: __MODULE__)
@impl true
def init(_), do: DynamicSupervisor.init(strategy: :one_for_one)
- @spec registry() :: module()
- def registry, do: @registry
-
@spec start_child(child()) :: DynamicSupervisor.on_start_child()
def start_child(child), do: DynamicSupervisor.start_child(__MODULE__, child)
@spec start_children(Pleroma.Application.env()) :: :ok
def start_children(env) do
- start_agent()
-
[
Pleroma.Plugs.RateLimiter.Supervisor,
Oban,
Pleroma.Web.Endpoint,
Pleroma.Gopher.Server,
Pleroma.Web.ChatChannel.ChatChannelState,
Pleroma.Web.FedSockets.Supervisor
]
|> add_http_children(env)
|> add_streamer(env)
|> Enum.each(&start_dynamic_child/1)
end
- defp start_agent do
- {:ok, pid} = DynamicSupervisor.start_child(__MODULE__, {Agent, fn -> [] end})
-
- Registry.register(@registry, "agent", pid)
- end
-
- defp find_in_registry(key) do
- [{_, pid}] = Registry.lookup(@registry, key)
- pid
- end
-
defp add_http_children(children, :test) do
[Pleroma.Application.HackneySupervisor, Pleroma.Application.GunSupervisor | children]
end
defp add_http_children(children, _) do
adapter = Application.get_env(:tesla, :adapter)
child =
if adapter == Tesla.Adapter.Gun do
Pleroma.Application.GunSupervisor
else
Pleroma.Application.HackneySupervisor
end
[child | children]
end
defp add_streamer(children, env) when env in [:test, :benchmark], do: children
defp add_streamer(children, _), do: [Pleroma.Web.StreamerRegistry | children]
defp start_dynamic_child(child) do
with {:ok, pid} <- dynamic_child(child),
mappings <- find_mappings(child) do
Enum.each(mappings, fn {key, _} ->
- Registry.register(@registry, key, pid)
+ Pleroma.Application.Agent.put_pid(key, pid)
end)
else
:ignore ->
# consider this behavior is normal
- Logger.warn("#{inspect(child)} is ignored.")
+ Logger.info("#{inspect(child)} is ignored.")
error ->
Logger.warn(inspect(error))
end
end
defp dynamic_child(child) do
with {:error, _} = error <- DynamicSupervisor.start_child(__MODULE__, spec(child)) do
error
end
end
defp spec(Oban), do: {Oban, Pleroma.Config.get(Oban)}
defp spec(Pleroma.Web.StreamerRegistry) do
{Registry,
[
name: Pleroma.Web.Streamer.registry(),
keys: :duplicate,
partitions: System.schedulers_online()
]}
end
defp spec(child), do: child
defp config_path_mappings do
adapter_module =
if Application.get_env(:tesla, :adapter) == Tesla.Adapter.Gun do
Pleroma.Application.GunSupervisor
else
Pleroma.Application.HackneySupervisor
end
[
{{:pleroma, :chat}, Pleroma.Web.ChatChannel.ChatChannelState},
{{:pleroma, Oban}, Oban},
{{:pleroma, :rate_limit}, Pleroma.Plugs.RateLimiter.Supervisor},
{{:pleroma, :streamer}, Pleroma.Web.Streamer.registry()},
{{:pleroma, :pools}, Pleroma.Application.GunSupervisor},
{{:pleroma, :connections_pool}, Pleroma.Application.GunSupervisor},
{{:pleroma, :hackney_pools}, Pleroma.Application.HackneySupervisor},
{{:pleroma, Pleroma.Captcha, [:seconds_valid]}, Pleroma.Web.Endpoint},
{{:pleroma, Pleroma.Upload, [:proxy_remote]}, adapter_module},
{{:pleroma, :instance, [:upload_limit]}, Pleroma.Web.Endpoint},
{{:pleroma, :gopher, [:enabled]}, Pleroma.Gopher.Server},
{{:pleroma, :fed_sockets, [:enabled]}, Pleroma.Web.Endpoint}
]
end
@spec save_need_reboot_paths([Pleroma.ConfigDB.t()]) :: :ok
def save_need_reboot_paths([]), do: :ok
def save_need_reboot_paths(configs) do
configs
|> Enum.map(&find_path(&1.group, &1.key, &1.value))
|> Enum.filter(& &1)
|> save_paths()
end
defp find_path(group, key, value) do
with {path, _} <-
Enum.find(config_path_mappings(), fn
{{g, k}, _} ->
g == group and k == key
{{g, k, subkeys}, _} ->
Keyword.keyword?(value) and g == group and k == key and
Enum.any?(Keyword.keys(value), &(&1 in subkeys))
end) do
path
end
end
defp save_paths([]), do: :ok
- defp save_paths(paths) do
- "agent"
- |> find_in_registry()
- |> Agent.update(&Enum.uniq(&1 ++ paths))
- end
+ defp save_paths(paths), do: Pleroma.Application.Agent.put_paths(paths)
@spec need_reboot?() :: boolean()
- def need_reboot? do
- paths =
- "agent"
- |> find_in_registry()
- |> Agent.get(& &1)
-
- paths != []
- end
+ def need_reboot?, do: Pleroma.Application.Agent.paths() != []
@spec restart_children() :: :ok
def restart_children do
- "agent"
- |> find_in_registry()
- |> Agent.get_and_update(&{&1, []})
+ Pleroma.Application.Agent.get_and_reset_paths()
|> Enum.each(&restart_child/1)
end
defp restart_child(path) do
- pid = find_in_registry(path)
+ pid = Pleroma.Application.Agent.pid(path)
# main module can have multiple keys
# first we search for main module
with {_, module} <- find_mapping(path),
:ok <- terminate(pid),
# then we search for mappings, which depends on this main module
mappings <- find_mappings(module) do
Enum.each(mappings, fn {key, _} ->
- Registry.unregister(@registry, key)
+ Pleroma.Application.Agent.delete_pid(key)
end)
start_dynamic_child(module)
else
error ->
Logger.warn(inspect(error))
end
end
defp find_mapping(path) do
with nil <- Enum.find(config_path_mappings(), fn {key, _} -> key == path end) do
{:error, :mapping_not_found}
end
end
defp find_mappings(module) do
with [] <- Enum.filter(config_path_mappings(), fn {_, m} -> m == module end) do
{:error, :empty_mappings}
end
end
defp terminate(pid) do
with {:error, :not_found} = error <- DynamicSupervisor.terminate_child(__MODULE__, pid) do
error
end
end
end

File Metadata

Mime Type
text/x-diff
Expires
Fri, Oct 9, 5:54 AM (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1784469
Default Alt Text
(14 KB)

Event Timeline