@ -10,6 +10,30 @@ defmodule Pleroma.Config.TransferTask do
require Logger
@type env ( ) :: :test | :benchmark | :dev | :prod
@reboot_time_keys [
{ :pleroma , :hackney_pools } ,
{ :pleroma , :chat } ,
{ :pleroma , Oban } ,
{ :pleroma , :rate_limit } ,
{ :pleroma , :markup } ,
{ :plerome , :streamer }
]
@reboot_time_subkeys [
{ :pleroma , Pleroma.Captcha , [ :seconds_valid ] } ,
{ :pleroma , Pleroma.Upload , [ :proxy_remote ] } ,
{ :pleroma , :instance , [ :upload_limit ] } ,
{ :pleroma , :email_notifications , [ :digest ] } ,
{ :pleroma , :oauth2 , [ :clean_expired_tokens ] } ,
{ :pleroma , Pleroma.ActivityExpiration , [ :enabled ] } ,
{ :pleroma , Pleroma.ScheduledActivity , [ :enabled ] } ,
{ :pleroma , :gopher , [ :enabled ] }
]
@reject [ nil , :prometheus ]
def start_link ( _ ) do
load_and_update_env ( )
if Pleroma.Config . get ( :env ) == :test , do : Ecto.Adapters.SQL.Sandbox . checkin ( Repo )
@ -17,21 +41,34 @@ defmodule Pleroma.Config.TransferTask do
end
@spec load_and_update_env ( [ ConfigDB . t ( ) ] ) :: :ok | false
def load_and_update_env ( deleted \\ [ ] ) do
def load_and_update_env ( deleted \\ [ ] , restart_pleroma? \\ true ) do
with true <- Pleroma.Config . get ( :configurable_from_database ) ,
true <- Ecto.Adapters.SQL . table_exists? ( Repo , " config " ) ,
started_applications <- Application . started_applications ( ) do
# We need to restart applications for loaded settings take effect
in_db = Repo . all ( ConfigDB )
with_deleted = in_db ++ deleted
with_deleted
|> Enum . map ( & merge_and_update ( &1 ) )
|> Enum . uniq ( )
# TODO: some problem with prometheus after restart!
|> Enum . reject ( & ( &1 in [ :pleroma , nil , :prometheus ] ) )
|> Enum . each ( & restart ( started_applications , &1 ) )
reject_for_restart = if restart_pleroma? , do : @reject , else : [ :pleroma | @reject ]
applications =
with_deleted
|> Enum . map ( & merge_and_update ( &1 ) )
|> Enum . uniq ( )
# TODO: some problem with prometheus after restart!
|> Enum . reject ( & ( &1 in reject_for_restart ) )
# to be ensured that pleroma will be restarted last
applications =
if :pleroma in applications do
List . delete ( applications , :pleroma ) ++ [ :pleroma ]
else
applications
end
Enum . each ( applications , & restart ( started_applications , &1 , Pleroma.Config . get ( :env ) ) )
:ok
end
@ -43,12 +80,25 @@ defmodule Pleroma.Config.TransferTask do
group = ConfigDB . from_string ( setting . group )
default = Pleroma.Config.Holder . config ( group , key )
merged_value = merge_value ( setting , default , group , key )
value = ConfigDB . from_binary ( setting . value )
merged_value =
if Ecto . get_meta ( setting , :state ) == :deleted do
default
else
if can_be_merged? ( default , value ) do
ConfigDB . merge_group ( group , key , default , value )
else
value
end
end
:ok = update_env ( group , key , merged_value )
if group != :logger do
group
if group != :pleroma or pleroma_need_restart? ( group , key , value ) do
group
end
else
# change logger configuration in runtime, without restart
if Keyword . keyword? ( merged_value ) and
@ -76,22 +126,31 @@ defmodule Pleroma.Config.TransferTask do
end
end
defp merge_value ( %{ __meta__ : %{ state : :deleted } } , default , _group , _key ) , do : default
@spec pleroma_need_restart? ( atom ( ) , atom ( ) , any ( ) ) :: boolean ( )
def pleroma_need_restart? ( group , key , value ) do
group_and_key_need_reboot? ( group , key ) or group_and_subkey_need_reboot? ( group , key , value )
end
defp merge_value ( setting , default , group , key ) do
value = ConfigDB . from_binary ( setting . value )
defp group_and_key_need_reboot? ( group , key ) do
Enum . any? ( @reboot_time_keys , fn { g , k } -> g == group and k == key end )
end
if can_be_merged? ( default , value ) do
ConfigDB . merge_group ( group , key , default , value )
else
value
end
defp group_and_subkey_need_reboot? ( group , key , value ) do
Keyword . keyword? ( value ) and
Enum . any? ( @reboot_time_subkeys , fn { g , k , subkeys } ->
g == group and k == key and
Enum . any? ( Keyword . keys ( value ) , & ( &1 in subkeys ) )
end )
end
defp update_env ( group , key , nil ) , do : Application . delete_env ( group , key )
defp update_env ( group , key , value ) , do : Application . put_env ( group , key , value )
defp restart ( started_applications , app ) do
defp restart ( _ , :pleroma , :test ) , do : Logger . warn ( " pleroma restarted " )
defp restart ( _ , :pleroma , _ ) , do : send ( Restarter.Pleroma , :after_boot )
defp restart ( started_applications , app , _ ) do
with { ^ app , _ , _ } <- List . keyfind ( started_applications , app , 0 ) ,
:ok <- Application . stop ( app ) do
:ok = Application . start ( app )