Merge pull request 'Raise minimum PostgreSQL version to 12' (#786) from Oneric/akkoma:psql-min-ver into develop
Reviewed-on: #786
This commit is contained in:
commit
d1c4b97613
7 changed files with 26 additions and 108 deletions
21
CHANGELOG.md
21
CHANGELOG.md
|
@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
|
## UNRELEASED
|
||||||
|
|
||||||
|
## BREAKING
|
||||||
|
- Minimum PostgreSQL version is raised to 12
|
||||||
|
|
||||||
|
## Added
|
||||||
|
- Implement [FEP-67ff](https://codeberg.org/fediverse/fep/src/branch/main/fep/67ff/fep-67ff.md) (federation documentation)
|
||||||
|
- Meilisearch: it is now possible to use separate keys for search and admin actions
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- Meilisearch: order of results returned from our REST API now actually matches how Meilisearch ranks results
|
||||||
|
|
||||||
## 2024.04.1 (Security)
|
## 2024.04.1 (Security)
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
@ -11,15 +23,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Issue allowing use of non-media objects as attachments and crashing timeline rendering
|
- Issue allowing use of non-media objects as attachments and crashing timeline rendering
|
||||||
- Issue allowing webfinger spoofing in certain situations
|
- Issue allowing webfinger spoofing in certain situations
|
||||||
|
|
||||||
## Added
|
|
||||||
- Implement [FEP-67ff](https://codeberg.org/fediverse/fep/src/branch/main/fep/67ff/fep-67ff.md) (federation documentation)
|
|
||||||
|
|
||||||
## Added
|
|
||||||
- Meilisearch: it is now possible to use separate keys for search and admin actions
|
|
||||||
|
|
||||||
## Fixed
|
|
||||||
- Meilisearch: order of results returned from our REST API now actually matches how Meilisearch ranks results
|
|
||||||
|
|
||||||
## 2024.04
|
## 2024.04
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
|
@ -813,8 +813,10 @@
|
||||||
config :pleroma, configurable_from_database: false
|
config :pleroma, configurable_from_database: false
|
||||||
|
|
||||||
config :pleroma, Pleroma.Repo,
|
config :pleroma, Pleroma.Repo,
|
||||||
parameters: [gin_fuzzy_search_limit: "500"],
|
parameters: [
|
||||||
prepare: :unnamed
|
gin_fuzzy_search_limit: "500",
|
||||||
|
plan_cache_mode: "force_custom_plan"
|
||||||
|
]
|
||||||
|
|
||||||
config :pleroma, :majic_pool, size: 2
|
config :pleroma, :majic_pool, size: 2
|
||||||
|
|
||||||
|
|
|
@ -11,21 +11,3 @@ It is also recommended to not use "Network Storage" option.
|
||||||
If your server runs other services, you may want to take that into account. E.g. if you have 4G ram, but 1G of it is already used for other services, it may be better to tell PGTune you only have 3G.
|
If your server runs other services, you may want to take that into account. E.g. if you have 4G ram, but 1G of it is already used for other services, it may be better to tell PGTune you only have 3G.
|
||||||
|
|
||||||
In the end, PGTune only provides recomended settings, you can always try to finetune further.
|
In the end, PGTune only provides recomended settings, you can always try to finetune further.
|
||||||
|
|
||||||
## Disable generic query plans
|
|
||||||
|
|
||||||
When PostgreSQL receives a query, it decides on a strategy for searching the requested data, this is called a query plan. The query planner has two modes: generic and custom. Generic makes a plan for all queries of the same shape, ignoring the parameters, which is then cached and reused. Custom, on the contrary, generates a unique query plan based on query parameters.
|
|
||||||
|
|
||||||
By default PostgreSQL has an algorithm to decide which mode is more efficient for particular query, however this algorithm has been observed to be wrong on some of the queries Akkoma sends, leading to serious performance loss. Therefore, it is recommended to disable generic mode.
|
|
||||||
|
|
||||||
|
|
||||||
Akkoma already avoids generic query plans by default, however the method it uses is not the most efficient because it needs to be compatible with all supported PostgreSQL versions. For PostgreSQL 12 and higher additional performance can be gained by adding the following to Akkoma configuration:
|
|
||||||
```elixir
|
|
||||||
config :pleroma, Pleroma.Repo,
|
|
||||||
prepare: :named,
|
|
||||||
parameters: [
|
|
||||||
plan_cache_mode: "force_custom_plan"
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
A more detailed explaination of the issue can be found at <https://blog.soykaf.com/post/postgresql-elixir-troubles/>.
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
## Required dependencies
|
## Required dependencies
|
||||||
|
|
||||||
* PostgreSQL 9.6+
|
* PostgreSQL 12+
|
||||||
* Elixir 1.14+ (currently tested up to 1.16)
|
* Elixir 1.14+ (currently tested up to 1.16)
|
||||||
* Erlang OTP 25+ (currently tested up to OTP26)
|
* Erlang OTP 25+ (currently tested up to OTP26)
|
||||||
* git
|
* git
|
||||||
|
|
|
@ -95,34 +95,17 @@ def start(_type, _args) do
|
||||||
|
|
||||||
opts = [strategy: :one_for_one, name: Pleroma.Supervisor, max_restarts: max_restarts]
|
opts = [strategy: :one_for_one, name: Pleroma.Supervisor, max_restarts: max_restarts]
|
||||||
|
|
||||||
with {:ok, data} <- Supervisor.start_link(children, opts) do
|
case Supervisor.start_link(children, opts) do
|
||||||
set_postgres_server_version()
|
{:ok, data} ->
|
||||||
{:ok, data}
|
{:ok, data}
|
||||||
else
|
|
||||||
e ->
|
e ->
|
||||||
Logger.error("Failed to start!")
|
Logger.critical("Failed to start!")
|
||||||
Logger.error("#{inspect(e)}")
|
Logger.critical("#{inspect(e)}")
|
||||||
e
|
e
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp set_postgres_server_version do
|
|
||||||
version =
|
|
||||||
with %{rows: [[version]]} <- Ecto.Adapters.SQL.query!(Pleroma.Repo, "show server_version"),
|
|
||||||
{num, _} <- Float.parse(version) do
|
|
||||||
num
|
|
||||||
else
|
|
||||||
e ->
|
|
||||||
Logger.warning(
|
|
||||||
"Could not get the postgres version: #{inspect(e)}.\nSetting the default value of 9.6"
|
|
||||||
)
|
|
||||||
|
|
||||||
9.6
|
|
||||||
end
|
|
||||||
|
|
||||||
:persistent_term.put({Pleroma.Repo, :postgres_version}, version)
|
|
||||||
end
|
|
||||||
|
|
||||||
def load_custom_modules do
|
def load_custom_modules do
|
||||||
dir = Config.get([:modules, :runtime_dir])
|
dir = Config.get([:modules, :runtime_dir])
|
||||||
|
|
||||||
|
|
|
@ -21,19 +21,12 @@ def search(user, search_query, options \\ []) do
|
||||||
offset = Keyword.get(options, :offset, 0)
|
offset = Keyword.get(options, :offset, 0)
|
||||||
author = Keyword.get(options, :author)
|
author = Keyword.get(options, :author)
|
||||||
|
|
||||||
search_function =
|
|
||||||
if :persistent_term.get({Pleroma.Repo, :postgres_version}) >= 11 do
|
|
||||||
:websearch
|
|
||||||
else
|
|
||||||
:plain
|
|
||||||
end
|
|
||||||
|
|
||||||
try do
|
try do
|
||||||
Activity
|
Activity
|
||||||
|> Activity.with_preloaded_object()
|
|> Activity.with_preloaded_object()
|
||||||
|> Activity.restrict_deactivated_users()
|
|> Activity.restrict_deactivated_users()
|
||||||
|> restrict_public()
|
|> restrict_public()
|
||||||
|> query_with(index_type, search_query, search_function)
|
|> query_with(index_type, search_query)
|
||||||
|> maybe_restrict_local(user)
|
|> maybe_restrict_local(user)
|
||||||
|> maybe_restrict_author(author)
|
|> maybe_restrict_author(author)
|
||||||
|> maybe_restrict_blocked(user)
|
|> maybe_restrict_blocked(user)
|
||||||
|
@ -72,25 +65,7 @@ def restrict_public(q) do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp query_with(q, :gin, search_query, :plain) do
|
defp query_with(q, :gin, search_query) do
|
||||||
%{rows: [[tsc]]} =
|
|
||||||
Ecto.Adapters.SQL.query!(
|
|
||||||
Pleroma.Repo,
|
|
||||||
"select current_setting('default_text_search_config')::regconfig::oid;"
|
|
||||||
)
|
|
||||||
|
|
||||||
from([a, o] in q,
|
|
||||||
where:
|
|
||||||
fragment(
|
|
||||||
"to_tsvector(?::oid::regconfig, ?->>'content') @@ plainto_tsquery(?)",
|
|
||||||
^tsc,
|
|
||||||
o.data,
|
|
||||||
^search_query
|
|
||||||
)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp query_with(q, :gin, search_query, :websearch) do
|
|
||||||
%{rows: [[tsc]]} =
|
%{rows: [[tsc]]} =
|
||||||
Ecto.Adapters.SQL.query!(
|
Ecto.Adapters.SQL.query!(
|
||||||
Pleroma.Repo,
|
Pleroma.Repo,
|
||||||
|
@ -108,19 +83,7 @@ defp query_with(q, :gin, search_query, :websearch) do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp query_with(q, :rum, search_query, :plain) do
|
defp query_with(q, :rum, search_query) do
|
||||||
from([a, o] in q,
|
|
||||||
where:
|
|
||||||
fragment(
|
|
||||||
"? @@ plainto_tsquery(?)",
|
|
||||||
o.fts_content,
|
|
||||||
^search_query
|
|
||||||
),
|
|
||||||
order_by: [fragment("? <=> now()::date", o.inserted_at)]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp query_with(q, :rum, search_query, :websearch) do
|
|
||||||
from([a, o] in q,
|
from([a, o] in q,
|
||||||
where:
|
where:
|
||||||
fragment(
|
fragment(
|
||||||
|
|
|
@ -18,21 +18,6 @@ test "it finds something" do
|
||||||
assert result.id == post.id
|
assert result.id == post.id
|
||||||
end
|
end
|
||||||
|
|
||||||
test "using plainto_tsquery on postgres < 11" do
|
|
||||||
old_version = :persistent_term.get({Pleroma.Repo, :postgres_version})
|
|
||||||
:persistent_term.put({Pleroma.Repo, :postgres_version}, 10.0)
|
|
||||||
on_exit(fn -> :persistent_term.put({Pleroma.Repo, :postgres_version}, old_version) end)
|
|
||||||
|
|
||||||
user = insert(:user)
|
|
||||||
{:ok, post} = CommonAPI.post(user, %{status: "it's wednesday my dudes"})
|
|
||||||
{:ok, _post2} = CommonAPI.post(user, %{status: "it's wednesday my bros"})
|
|
||||||
|
|
||||||
# plainto doesn't understand complex queries
|
|
||||||
assert [result] = DatabaseSearch.search(nil, "wednesday -dudes")
|
|
||||||
|
|
||||||
assert result.id == post.id
|
|
||||||
end
|
|
||||||
|
|
||||||
test "using websearch_to_tsquery" do
|
test "using websearch_to_tsquery" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
{:ok, _post} = CommonAPI.post(user, %{status: "it's wednesday my dudes"})
|
{:ok, _post} = CommonAPI.post(user, %{status: "it's wednesday my dudes"})
|
||||||
|
|
Loading…
Reference in a new issue