2018-12-23 21:04:54 +01:00
# Pleroma: A lightweight social networking server
2020-03-02 06:08:45 +01:00
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
2018-12-23 21:04:54 +01:00
# SPDX-License-Identifier: AGPL-3.0-only
2017-03-17 17:09:58 +01:00
defmodule Pleroma.Repo do
2019-03-20 14:04:59 +01:00
use Ecto.Repo ,
otp_app : :pleroma ,
adapter : Ecto.Adapters.Postgres ,
migration_timestamps : [ type : :naive_datetime_usec ]
2017-03-17 17:09:58 +01:00
2020-06-16 22:45:59 +02:00
import Ecto.Query
2020-01-16 17:01:31 +01:00
require Logger
2019-01-30 16:32:30 +01:00
defmodule Instrumenter do
use Prometheus.EctoInstrumenter
end
2017-03-17 17:09:58 +01:00
@doc """
Dynamically loads the repository url from the
DATABASE_URL environment variable .
"""
def init ( _ , opts ) do
{ :ok , Keyword . put ( opts , :url , System . get_env ( " DATABASE_URL " ) ) }
end
2019-05-06 19:51:03 +02:00
@doc " find resource based on prepared query "
@spec find_resource ( Ecto.Query . t ( ) ) :: { :ok , struct ( ) } | { :error , :not_found }
def find_resource ( % Ecto.Query { } = query ) do
case __MODULE__ . one ( query ) do
nil -> { :error , :not_found }
resource -> { :ok , resource }
end
end
def find_resource ( _query ) , do : { :error , :not_found }
@doc """
Gets association from cache or loads if need
## Examples
iex > Repo . get_assoc ( token , :user )
% User { }
"""
@spec get_assoc ( struct ( ) , atom ( ) ) :: { :ok , struct ( ) } | { :error , :not_found }
def get_assoc ( resource , association ) do
case __MODULE__ . preload ( resource , association ) do
%{ ^ association = > assoc } when not is_nil ( assoc ) -> { :ok , assoc }
_ -> { :error , :not_found }
end
end
2020-01-16 17:01:31 +01:00
def check_migrations_applied! ( ) do
unless Pleroma.Config . get (
[ :i_am_aware_this_may_cause_data_loss , :disable_migration_check ] ,
false
) do
Ecto.Migrator . with_repo ( __MODULE__ , fn repo ->
down_migrations =
Ecto.Migrator . migrations ( repo )
|> Enum . reject ( fn
{ :up , _ , _ } -> true
{ :down , _ , _ } -> false
end )
if length ( down_migrations ) > 0 do
down_migrations_text =
Enum . map ( down_migrations , fn { :down , id , name } -> " - #{ name } ( #{ id } ) \n " end )
Logger . error (
" The following migrations were not applied: \n #{ down_migrations_text } If you want to start Pleroma anyway, set \n config :pleroma, :i_am_aware_this_may_cause_data_loss, disable_migration_check: true "
)
raise Pleroma.Repo.UnappliedMigrationsError
end
end )
else
:ok
end
end
2020-06-16 22:45:59 +02:00
def chunk_stream ( query , chunk_size ) do
# We don't actually need start and end funcitons of resource streaming,
# but it seems to be the only way to not fetch records one-by-one and
# have individual records be the elements of the stream, instead of
# lists of records
Stream . resource (
fn -> 0 end ,
fn
last_id ->
query
|> order_by ( asc : :id )
|> where ( [ r ] , r . id > ^ last_id )
|> limit ( ^ chunk_size )
|> all ( )
|> case do
[ ] ->
{ :halt , last_id }
records ->
last_id = List . last ( records ) . id
{ records , last_id }
end
end ,
fn _ -> :ok end
)
end
2020-01-16 17:01:31 +01:00
end
defmodule Pleroma.Repo.UnappliedMigrationsError do
defexception message : " Unapplied Migrations detected "
2017-03-17 17:09:58 +01:00
end