2018-12-23 20:04:54 +00:00
# Pleroma: A lightweight social networking server
2021-01-13 06:49:20 +00:00
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
2018-12-23 20:04:54 +00:00
# SPDX-License-Identifier: AGPL-3.0-only
2017-03-17 16:09:58 +00:00
defmodule Pleroma.Application do
use Application
2020-02-11 07:12:57 +00:00
import Cachex.Spec
alias Pleroma.Config
2019-12-09 12:11:54 +00:00
require Logger
2017-03-17 16:09:58 +00:00
2019-02-01 17:11:23 +00:00
@name Mix.Project . config ( ) [ :name ]
2018-11-20 16:55:03 +00:00
@version Mix.Project . config ( ) [ :version ]
2019-02-01 17:11:23 +00:00
@repository Mix.Project . config ( ) [ :source_url ]
2021-02-04 16:11:48 +00:00
@mix_env Mix . env ( )
2019-08-14 15:55:17 +00:00
2018-11-20 16:55:03 +00:00
def name , do : @name
def version , do : @version
2019-03-05 03:18:43 +00:00
def named_version , do : @name <> " " <> @version
2019-02-01 06:55:10 +00:00
def repository , do : @repository
2018-11-20 16:55:03 +00:00
2019-03-05 03:18:43 +00:00
def user_agent do
2020-09-02 12:45:47 +00:00
if Process . whereis ( Pleroma.Web.Endpoint ) do
case Config . get ( [ :http , :user_agent ] , :default ) do
:default ->
2021-05-31 20:09:11 +00:00
info = " #{ Pleroma.Web.Endpoint . url ( ) } < #{ Config . get ( [ :instance , :email ] , " " ) } > "
2020-09-02 12:45:47 +00:00
named_version ( ) <> " ; " <> info
custom ->
custom
end
else
# fallback, if endpoint is not started yet
" Pleroma Data Loader "
2019-11-25 09:53:11 +00:00
end
2018-11-23 16:40:45 +00:00
end
2017-03-17 16:09:58 +00:00
# See http://elixir-lang.org/docs/stable/elixir/Application.html
# for more information on OTP Applications
def start ( _type , _args ) do
2020-07-14 08:41:30 +00:00
# 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 )
2020-09-01 06:08:54 +00:00
# Disable warnings_as_errors at runtime, it breaks Phoenix live reload
# due to protocol consolidation warnings
Code . compiler_options ( warnings_as_errors : false )
2020-07-15 12:26:25 +00:00
Pleroma.Telemetry.Logger . attach ( )
2020-07-09 15:53:51 +00:00
Config.Holder . save_default ( )
2019-12-08 16:42:40 +00:00
Pleroma.HTML . compile_scrubbers ( )
2020-09-06 09:13:26 +00:00
Pleroma.Config.Oban . warn ( )
2020-02-11 07:12:57 +00:00
Config.DeprecationWarnings . warn ( )
2020-06-24 07:39:17 +00:00
Pleroma.Web.Plugs.HTTPSecurityPlug . warn_if_disabled ( )
2020-06-22 14:27:49 +00:00
Pleroma.ApplicationRequirements . verify! ( )
2019-01-30 15:32:30 +00:00
setup_instrumenters ( )
2019-12-05 13:18:25 +00:00
load_custom_modules ( )
2020-07-12 15:23:33 +00:00
Pleroma.Docs.JSON . compile ( )
2020-09-10 07:54:57 +00:00
limiters_setup ( )
2019-01-28 11:09:41 +00:00
2020-03-12 15:28:54 +00:00
adapter = Application . get_env ( :tesla , :adapter )
2021-12-15 20:42:37 +00:00
if match? ( { Tesla.Adapter.Finch , _ } , adapter ) do
Logger . info ( " Starting Finch " )
2021-12-15 18:53:09 +00:00
Finch . start_link ( name : MyFinch )
end
2020-03-12 15:28:54 +00:00
if adapter == Tesla.Adapter.Gun do
2020-03-04 06:23:42 +00:00
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 ! ! !
2020-05-12 14:30:39 +00:00
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.
2020-03-04 06:23:42 +00:00
"
end
else
raise "
! ! ! OTP VERSION WARNING ! ! !
To support correct handling of unordered certificates chains - OTP version must be > 22.2 .
"
end
2020-03-03 10:24:19 +00:00
end
2017-03-17 16:09:58 +00:00
# Define workers and child supervisors to be supervised
2018-03-30 13:01:53 +00:00
children =
[
2019-08-14 15:55:17 +00:00
Pleroma.Repo ,
2020-02-11 07:12:57 +00:00
Config.TransferTask ,
2019-08-14 15:55:17 +00:00
Pleroma.Emoji ,
2020-06-24 05:38:42 +00:00
Pleroma.Web.Plugs.RateLimiter.Supervisor
2018-03-30 13:01:53 +00:00
] ++
2019-08-14 15:55:17 +00:00
cachex_children ( ) ++
2021-02-04 16:11:48 +00:00
http_children ( adapter , @mix_env ) ++
2019-01-30 11:38:38 +00:00
[
2019-08-14 15:55:17 +00:00
Pleroma.Stats ,
2019-09-26 11:49:57 +00:00
Pleroma.JobQueueMonitor ,
2020-06-16 13:11:45 +00:00
{ Majic.Pool , [ name : Pleroma.MajicPool , pool_size : Config . get ( [ :majic_pool , :size ] , 2 ) ] } ,
2021-02-22 20:09:41 +00:00
{ Oban , Config . get ( Oban ) } ,
Pleroma.Web.Endpoint
2019-01-30 11:38:38 +00:00
] ++
2021-02-04 16:11:48 +00:00
task_children ( @mix_env ) ++
dont_run_in_test ( @mix_env ) ++
2022-06-27 16:31:16 +00:00
shout_child ( shout_enabled? ( ) )
2017-03-17 16:09:58 +00:00
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
# for other strategies and supported options
opts = [ strategy : :one_for_one , name : Pleroma.Supervisor ]
2020-11-20 15:26:22 +00:00
result = Supervisor . start_link ( children , opts )
set_postgres_server_version ( )
result
end
2020-11-20 15:38:05 +00:00
defp set_postgres_server_version do
2020-11-20 15:26:22 +00:00
version =
with %{ rows : [ [ version ] ] } <- Ecto.Adapters.SQL . query! ( Pleroma.Repo , " show server_version " ) ,
{ num , _ } <- Float . parse ( version ) do
num
else
e ->
Logger . warn (
" Could not get the postgres version: #{ inspect ( e ) } . \n Setting the default value of 9.6 "
)
9.6
end
2020-11-23 14:29:55 +00:00
:persistent_term . put ( { Pleroma.Repo , :postgres_version } , version )
2017-03-17 16:09:58 +00:00
end
2018-02-01 17:23:26 +00:00
2019-12-05 13:29:17 +00:00
def load_custom_modules do
2020-02-11 07:12:57 +00:00
dir = Config . get ( [ :modules , :runtime_dir ] )
2019-12-05 13:18:25 +00:00
if dir && File . exists? ( dir ) do
dir
2019-12-09 11:23:07 +00:00
|> Pleroma.Utils . compile_dir ( )
2019-12-05 13:18:25 +00:00
|> case do
{ :error , _errors , _warnings } ->
raise " Invalid custom modules "
{ :ok , modules , _warnings } ->
2021-02-04 16:11:48 +00:00
if @mix_env != :test do
2019-12-06 10:05:09 +00:00
Enum . each ( modules , fn mod ->
2019-12-09 12:11:54 +00:00
Logger . info ( " Custom module loaded: #{ inspect ( mod ) } " )
2019-12-06 10:05:09 +00:00
end )
end
2019-12-05 13:18:25 +00:00
:ok
end
end
end
2019-04-04 17:36:57 +00:00
defp setup_instrumenters do
2019-03-25 08:29:04 +00:00
require Prometheus.Registry
2019-05-20 23:30:18 +00:00
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
2019-03-25 08:29:04 +00:00
Pleroma.Web.Endpoint.MetricsExporter . setup ( )
Pleroma.Web.Endpoint.PipelineInstrumenter . setup ( )
2020-10-22 10:54:15 +00:00
# Note: disabled until prometheus-phx is integrated into prometheus-phoenix:
# Pleroma.Web.Endpoint.Instrumenter.setup()
PrometheusPhx . setup ( )
2019-03-25 08:29:04 +00:00
end
2019-08-14 15:55:17 +00:00
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 ) ,
2019-09-09 18:53:08 +00:00
build_cachex ( " idempotency " , expiration : idempotency_expiration ( ) , limit : 2500 ) ,
2019-08-12 10:13:01 +00:00
build_cachex ( " web_resp " , limit : 2500 ) ,
2019-10-01 20:00:27 +00:00
build_cachex ( " emoji_packs " , expiration : emoji_packs_expiration ( ) , limit : 10 ) ,
2020-06-14 18:02:57 +00:00
build_cachex ( " failed_proxy_url " , limit : 2500 ) ,
2020-10-31 02:50:48 +00:00
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
)
2019-08-14 15:55:17 +00:00
]
end
2018-11-19 19:58:12 +00:00
2019-08-12 10:13:01 +00:00
defp emoji_packs_expiration ,
do : expiration ( default : :timer . seconds ( 5 * 60 ) , interval : :timer . seconds ( 60 ) )
2019-08-14 15:55:17 +00:00
defp idempotency_expiration ,
2019-08-14 18:01:11 +00:00
do : expiration ( default : :timer . seconds ( 6 * 60 * 60 ) , interval : :timer . seconds ( 60 ) )
2019-08-14 15:55:17 +00:00
2020-10-31 02:50:48 +00:00
defp chat_message_id_idempotency_key_expiration ,
do : expiration ( default : :timer . minutes ( 2 ) , interval : :timer . seconds ( 60 ) )
2019-08-14 15:55:17 +00:00
defp seconds_valid_interval ,
2020-02-11 07:12:57 +00:00
do : :timer . seconds ( Config . get! ( [ Pleroma.Captcha , :seconds_valid ] ) )
2019-08-14 15:55:17 +00:00
2020-07-03 16:18:08 +00:00
@spec build_cachex ( String . t ( ) , keyword ( ) ) :: map ( )
def build_cachex ( type , opts ) ,
2019-08-14 18:01:11 +00:00
do : %{
id : String . to_atom ( " cachex_ " <> type ) ,
start : { Cachex , :start_link , [ String . to_atom ( type <> " _cache " ) , opts ] } ,
type : :worker
}
2019-08-14 15:55:17 +00:00
2020-08-03 23:41:49 +00:00
defp shout_enabled? , do : Config . get ( [ :shout , :enabled ] )
2019-08-14 15:55:17 +00:00
2020-09-18 11:58:22 +00:00
defp dont_run_in_test ( env ) when env in [ :test , :benchmark ] , do : [ ]
2019-08-14 15:55:17 +00:00
2020-09-18 11:58:22 +00:00
defp dont_run_in_test ( _ ) do
2020-05-07 09:13:32 +00:00
[
{ Registry ,
[
name : Pleroma.Web.Streamer . registry ( ) ,
keys : :duplicate ,
partitions : System . schedulers_online ( )
2020-11-17 14:28:30 +00:00
] }
2021-03-12 09:18:11 +00:00
] ++ background_migrators ( )
end
defp background_migrators do
[
Pleroma.Migrators.HashtagsTableMigrator
2020-05-07 09:13:32 +00:00
]
2018-02-01 17:23:26 +00:00
end
2019-01-30 11:38:38 +00:00
2020-08-03 23:41:49 +00:00
defp shout_child ( true ) do
2020-10-07 18:28:39 +00:00
[
2020-08-03 23:34:58 +00:00
Pleroma.Web.ShoutChannel.ShoutChannelState ,
2020-10-07 18:28:39 +00:00
{ Phoenix.PubSub , [ name : Pleroma.PubSub , adapter : Phoenix.PubSub.PG2 ] }
]
2019-08-14 15:55:17 +00:00
end
2020-08-03 23:41:49 +00:00
defp shout_child ( _ ) , do : [ ]
2019-08-14 15:55:17 +00:00
2019-09-17 14:44:52 +00:00
defp task_children ( :test ) do
[
%{
id : :web_push_init ,
start : { Task , :start_link , [ & Pleroma.Web.Push . init / 0 ] } ,
restart : :temporary
}
]
end
defp task_children ( _ ) do
[
%{
id : :web_push_init ,
start : { Task , :start_link , [ & Pleroma.Web.Push . init / 0 ] } ,
restart : :temporary
} ,
%{
id : :internal_fetch_init ,
start : { Task , :start_link , [ & Pleroma.Web.ActivityPub.InternalFetchActor . init / 0 ] } ,
restart : :temporary
}
]
end
2020-02-11 07:12:57 +00:00
# start hackney and gun pools in tests
2020-03-12 15:28:54 +00:00
defp http_children ( _ , :test ) do
2020-05-05 22:51:10 +00:00
http_children ( Tesla.Adapter.Hackney , nil ) ++ http_children ( Tesla.Adapter.Gun , nil )
2020-02-11 07:12:57 +00:00
end
2020-03-12 15:28:54 +00:00
defp http_children ( Tesla.Adapter.Hackney , _ ) do
2020-02-11 07:12:57 +00:00
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
2020-05-05 22:51:10 +00:00
defp http_children ( Tesla.Adapter.Gun , _ ) do
2020-05-17 19:16:02 +00:00
Pleroma.Gun.ConnectionPool . children ( ) ++
[ { Task , & Pleroma.HTTP.AdapterHelper.Gun . limiter_setup / 0 } ]
2020-05-05 22:51:10 +00:00
end
2020-03-03 09:19:29 +00:00
2020-03-12 15:28:54 +00:00
defp http_children ( _ , _ ) , do : [ ]
2020-09-10 07:54:57 +00:00
2020-11-20 08:37:01 +00:00
@spec limiters_setup ( ) :: :ok
2020-09-10 07:54:57 +00:00
def limiters_setup do
2021-01-09 15:52:40 +00:00
config = Config . get ( ConcurrentLimiter , [ ] )
2021-01-21 06:50:18 +00:00
[ Pleroma.Web.RichMedia.Helpers , Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy ]
2021-01-09 15:52:40 +00:00
|> 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 )
2020-09-10 07:54:57 +00:00
end
2017-03-17 16:09:58 +00:00
end