clients.md: Add Kyclos
[akkoma] / lib / pleroma / config / transfer_task.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Config.TransferTask do
6 use Task
7
8 alias Pleroma.ConfigDB
9 alias Pleroma.Repo
10
11 require Logger
12
13 def start_link(_) do
14 load_and_update_env()
15 if Pleroma.Config.get(:env) == :test, do: Ecto.Adapters.SQL.Sandbox.checkin(Repo)
16 :ignore
17 end
18
19 @spec load_and_update_env([ConfigDB.t()]) :: :ok | false
20 def load_and_update_env(deleted \\ []) do
21 with true <- Pleroma.Config.get(:configurable_from_database),
22 true <- Ecto.Adapters.SQL.table_exists?(Repo, "config"),
23 started_applications <- Application.started_applications() do
24 # We need to restart applications for loaded settings take effect
25 in_db = Repo.all(ConfigDB)
26
27 with_deleted = in_db ++ deleted
28
29 with_deleted
30 |> Enum.map(&merge_and_update(&1))
31 |> Enum.uniq()
32 # TODO: some problem with prometheus after restart!
33 |> Enum.reject(&(&1 in [:pleroma, nil, :prometheus]))
34 |> Enum.each(&restart(started_applications, &1))
35
36 :ok
37 end
38 end
39
40 defp merge_and_update(setting) do
41 try do
42 key = ConfigDB.from_string(setting.key)
43 group = ConfigDB.from_string(setting.group)
44
45 default = Pleroma.Config.Holder.config(group, key)
46 merged_value = merge_value(setting, default, group, key)
47
48 :ok = update_env(group, key, merged_value)
49
50 if group != :logger do
51 group
52 else
53 # change logger configuration in runtime, without restart
54 if Keyword.keyword?(merged_value) and
55 key not in [:compile_time_application, :backends, :compile_time_purge_matching] do
56 Logger.configure_backend(key, merged_value)
57 else
58 Logger.configure([{key, merged_value}])
59 end
60
61 nil
62 end
63 rescue
64 error ->
65 error_msg =
66 "updating env causes error, group: " <>
67 inspect(setting.group) <>
68 " key: " <>
69 inspect(setting.key) <>
70 " value: " <>
71 inspect(ConfigDB.from_binary(setting.value)) <> " error: " <> inspect(error)
72
73 Logger.warn(error_msg)
74
75 nil
76 end
77 end
78
79 defp merge_value(%{__meta__: %{state: :deleted}}, default, _group, _key), do: default
80
81 defp merge_value(setting, default, group, key) do
82 value = ConfigDB.from_binary(setting.value)
83
84 if can_be_merged?(default, value) do
85 ConfigDB.merge_group(group, key, default, value)
86 else
87 value
88 end
89 end
90
91 defp update_env(group, key, nil), do: Application.delete_env(group, key)
92 defp update_env(group, key, value), do: Application.put_env(group, key, value)
93
94 defp restart(started_applications, app) do
95 with {^app, _, _} <- List.keyfind(started_applications, app, 0),
96 :ok <- Application.stop(app) do
97 :ok = Application.start(app)
98 else
99 nil ->
100 Logger.warn("#{app} is not started.")
101
102 error ->
103 error
104 |> inspect()
105 |> Logger.warn()
106 end
107 end
108
109 defp can_be_merged?(val1, val2) when is_list(val1) and is_list(val2) do
110 Keyword.keyword?(val1) and Keyword.keyword?(val2)
111 end
112
113 defp can_be_merged?(_val1, _val2), do: false
114 end