Add support for PGroonga
This commit is contained in:
parent
f03c0bc63f
commit
557fce16e5
13 changed files with 176 additions and 25 deletions
|
@ -71,8 +71,14 @@
|
||||||
config :pleroma, :http_security, report_uri: "https://endpoint.com"
|
config :pleroma, :http_security, report_uri: "https://endpoint.com"
|
||||||
|
|
||||||
rum_enabled = System.get_env("RUM_ENABLED") == "true"
|
rum_enabled = System.get_env("RUM_ENABLED") == "true"
|
||||||
config :pleroma, :database, rum_enabled: rum_enabled
|
pgroonga_enabled = System.get_env("PGROONGA_ENABLED") == "true"
|
||||||
|
|
||||||
|
config :pleroma, :database,
|
||||||
|
rum_enabled: rum_enabled,
|
||||||
|
pgroonga_enabled: pgroonga_enabled
|
||||||
|
|
||||||
IO.puts("RUM enabled: #{rum_enabled}")
|
IO.puts("RUM enabled: #{rum_enabled}")
|
||||||
|
IO.puts("PGroonga enabled: #{pgroonga_enabled}")
|
||||||
|
|
||||||
config :pleroma, Pleroma.ReverseProxy.Client, Pleroma.ReverseProxy.ClientMock
|
config :pleroma, Pleroma.ReverseProxy.Client, Pleroma.ReverseProxy.ClientMock
|
||||||
|
|
||||||
|
|
|
@ -689,7 +689,9 @@
|
||||||
issue_new_refresh_token: true,
|
issue_new_refresh_token: true,
|
||||||
clean_expired_tokens: false
|
clean_expired_tokens: false
|
||||||
|
|
||||||
config :pleroma, :database, rum_enabled: false
|
config :pleroma, :database,
|
||||||
|
rum_enabled: false,
|
||||||
|
pgroonga_enabled: false
|
||||||
|
|
||||||
config :pleroma, :features, improved_hashtag_timeline: :auto
|
config :pleroma, :features, improved_hashtag_timeline: :auto
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,10 @@
|
||||||
# Configure web push notifications
|
# Configure web push notifications
|
||||||
config :web_push_encryption, :vapid_details, subject: "mailto:#{System.get_env("NOTIFY_EMAIL")}"
|
config :web_push_encryption, :vapid_details, subject: "mailto:#{System.get_env("NOTIFY_EMAIL")}"
|
||||||
|
|
||||||
config :pleroma, :database, rum_enabled: false
|
config :pleroma, :database,
|
||||||
|
rum_enabled: false,
|
||||||
|
pgroonga_enabled: false
|
||||||
|
|
||||||
config :pleroma, :instance, static_dir: "/var/lib/akkoma/static"
|
config :pleroma, :instance, static_dir: "/var/lib/akkoma/static"
|
||||||
config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/akkoma/uploads"
|
config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/akkoma/uploads"
|
||||||
|
|
||||||
|
|
|
@ -98,8 +98,14 @@
|
||||||
config :pleroma, :http, send_user_agent: false
|
config :pleroma, :http, send_user_agent: false
|
||||||
|
|
||||||
rum_enabled = System.get_env("RUM_ENABLED") == "true"
|
rum_enabled = System.get_env("RUM_ENABLED") == "true"
|
||||||
config :pleroma, :database, rum_enabled: rum_enabled
|
pgroonga_enabled = System.get_env("PGROONGA_ENABLED") == "true"
|
||||||
|
|
||||||
|
config :pleroma, :database,
|
||||||
|
rum_enabled: rum_enabled,
|
||||||
|
pgroonga_enabled: pgroonga_enabled
|
||||||
|
|
||||||
IO.puts("RUM enabled: #{rum_enabled}")
|
IO.puts("RUM enabled: #{rum_enabled}")
|
||||||
|
IO.puts("PGroonga enabled: #{pgroonga_enabled}")
|
||||||
|
|
||||||
config :joken, default_signer: "yU8uHKq+yyAkZ11Hx//jcdacWc8yQ1bxAAGrplzB0Zwwjkp35v0RK9SO8WTPr6QZ"
|
config :joken, default_signer: "yU8uHKq+yyAkZ11Hx//jcdacWc8yQ1bxAAGrplzB0Zwwjkp35v0RK9SO8WTPr6QZ"
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ version: "3.7"
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
image: postgres:14-alpine
|
image: postgres:14-alpine
|
||||||
|
# image: groonga/pgroonga:3.1.1-alpine-14 # Use this one if you want to use PGroonga
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: akkoma
|
POSTGRES_DB: akkoma
|
||||||
|
|
|
@ -54,6 +54,7 @@ The configuration of Akkoma (and Pleroma) has traditionally been managed with a
|
||||||
* config :pleroma, Pleroma.Repo
|
* config :pleroma, Pleroma.Repo
|
||||||
* config :pleroma, configurable\_from\_database
|
* config :pleroma, configurable\_from\_database
|
||||||
* config :pleroma, :database, rum_enabled
|
* config :pleroma, :database, rum_enabled
|
||||||
|
* config :pleroma, :database, pgroonga_enabled
|
||||||
* config :pleroma, :connections_pool
|
* config :pleroma, :connections_pool
|
||||||
|
|
||||||
Here is an example of a server config stripped down after migration:
|
Here is an example of a server config stripped down after migration:
|
||||||
|
|
|
@ -326,37 +326,50 @@ def run(["set_text_search_config", tsconfig]) do
|
||||||
"ALTER DATABASE #{db} SET default_text_search_config = '#{tsconfig}';"
|
"ALTER DATABASE #{db} SET default_text_search_config = '#{tsconfig}';"
|
||||||
)
|
)
|
||||||
|
|
||||||
# non-exist config will not raise excpetion but only give >0 messages
|
# non-exist config will not raise exception but only give >0 messages
|
||||||
if length(msg) > 0 do
|
if length(msg) > 0 do
|
||||||
shell_info("Error: #{inspect(msg, pretty: true)}")
|
shell_info("Error: #{inspect(msg, pretty: true)}")
|
||||||
else
|
else
|
||||||
rum_enabled = Pleroma.Config.get([:database, :rum_enabled])
|
rum_enabled = Pleroma.Config.get([:database, :rum_enabled])
|
||||||
shell_info("Recreate index, RUM: #{rum_enabled}")
|
pgroonga_enabled = Pleroma.Config.get([:database, :pgroonga_enabled])
|
||||||
|
shell_info("Recreate index, RUM: #{rum_enabled}, PGroonga: #{pgroonga_enabled}")
|
||||||
|
|
||||||
# Note SQL below needs to be kept up-to-date with latest GIN or RUM index definition in future
|
# Note SQL below needs to be kept up-to-date with latest GIN or RUM index definition in future
|
||||||
if rum_enabled do
|
cond do
|
||||||
Ecto.Adapters.SQL.query!(
|
rum_enabled ->
|
||||||
Pleroma.Repo,
|
Ecto.Adapters.SQL.query!(
|
||||||
"CREATE OR REPLACE FUNCTION objects_fts_update() RETURNS trigger AS $$ BEGIN
|
Pleroma.Repo,
|
||||||
|
"CREATE OR REPLACE FUNCTION objects_fts_update() RETURNS trigger AS $$ BEGIN
|
||||||
new.fts_content := to_tsvector(new.data->>'content');
|
new.fts_content := to_tsvector(new.data->>'content');
|
||||||
RETURN new;
|
RETURN new;
|
||||||
END
|
END
|
||||||
$$ LANGUAGE plpgsql",
|
$$ LANGUAGE plpgsql",
|
||||||
[],
|
[],
|
||||||
timeout: :infinity
|
timeout: :infinity
|
||||||
)
|
)
|
||||||
|
|
||||||
shell_info("Refresh RUM index")
|
shell_info("Refresh RUM index")
|
||||||
Ecto.Adapters.SQL.query!(Pleroma.Repo, "UPDATE objects SET updated_at = NOW();")
|
Ecto.Adapters.SQL.query!(Pleroma.Repo, "UPDATE objects SET updated_at = NOW();")
|
||||||
else
|
|
||||||
Ecto.Adapters.SQL.query!(Pleroma.Repo, "DROP INDEX IF EXISTS objects_fts;")
|
|
||||||
|
|
||||||
Ecto.Adapters.SQL.query!(
|
pgroonga_enabled ->
|
||||||
Pleroma.Repo,
|
Ecto.Adapters.SQL.query!(Pleroma.Repo, "DROP INDEX IF EXISTS object_content_pgroonga;")
|
||||||
"CREATE INDEX CONCURRENTLY objects_fts ON objects USING gin(to_tsvector('#{tsconfig}', data->>'content')); ",
|
|
||||||
[],
|
Ecto.Adapters.SQL.query!(
|
||||||
timeout: :infinity
|
Pleroma.Repo,
|
||||||
)
|
"CREATE INDEX object_content_pgroonga ON objects USING pgroonga ((data->'content')) WITH (tokenizer='TokenMecab');",
|
||||||
|
[],
|
||||||
|
timeout: :infinity
|
||||||
|
)
|
||||||
|
|
||||||
|
true ->
|
||||||
|
Ecto.Adapters.SQL.query!(Pleroma.Repo, "DROP INDEX IF EXISTS objects_fts;")
|
||||||
|
|
||||||
|
Ecto.Adapters.SQL.query!(
|
||||||
|
Pleroma.Repo,
|
||||||
|
"CREATE INDEX CONCURRENTLY objects_fts ON objects USING gin(to_tsvector('#{tsconfig}', data->>'content'));",
|
||||||
|
[],
|
||||||
|
timeout: :infinity
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
shell_info('Done.')
|
shell_info('Done.')
|
||||||
|
|
|
@ -28,6 +28,7 @@ def run(["gen" | rest]) do
|
||||||
dbuser: :string,
|
dbuser: :string,
|
||||||
dbpass: :string,
|
dbpass: :string,
|
||||||
rum: :string,
|
rum: :string,
|
||||||
|
pgroonga: :string,
|
||||||
indexable: :string,
|
indexable: :string,
|
||||||
db_configurable: :string,
|
db_configurable: :string,
|
||||||
uploads_dir: :string,
|
uploads_dir: :string,
|
||||||
|
@ -127,6 +128,18 @@ def run(["gen" | rest]) do
|
||||||
"n"
|
"n"
|
||||||
) === "y"
|
) === "y"
|
||||||
|
|
||||||
|
pgroonga_enabled =
|
||||||
|
if rum_enabled do
|
||||||
|
false
|
||||||
|
else
|
||||||
|
get_option(
|
||||||
|
options,
|
||||||
|
:pgroonga,
|
||||||
|
"Would you like to use PGroonga to index and search?",
|
||||||
|
"n"
|
||||||
|
) === "y"
|
||||||
|
end
|
||||||
|
|
||||||
listen_port =
|
listen_port =
|
||||||
get_option(
|
get_option(
|
||||||
options,
|
options,
|
||||||
|
@ -225,6 +238,7 @@ def run(["gen" | rest]) do
|
||||||
static_dir: static_dir,
|
static_dir: static_dir,
|
||||||
uploads_dir: uploads_dir,
|
uploads_dir: uploads_dir,
|
||||||
rum_enabled: rum_enabled,
|
rum_enabled: rum_enabled,
|
||||||
|
pgroonga_enabled: pgroonga_enabled,
|
||||||
listen_ip: listen_ip,
|
listen_ip: listen_ip,
|
||||||
listen_port: listen_port,
|
listen_port: listen_port,
|
||||||
upload_filters:
|
upload_filters:
|
||||||
|
|
|
@ -24,6 +24,7 @@ def verify! do
|
||||||
|> check_migrations_applied!()
|
|> check_migrations_applied!()
|
||||||
|> check_welcome_message_config!()
|
|> check_welcome_message_config!()
|
||||||
|> check_rum!()
|
|> check_rum!()
|
||||||
|
|> check_pgroonga!()
|
||||||
|> check_repo_pool_size!()
|
|> check_repo_pool_size!()
|
||||||
|> handle_result()
|
|> handle_result()
|
||||||
end
|
end
|
||||||
|
@ -162,6 +163,55 @@ defp do_check_rum!(setting, migrate) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Checks for settings of PGroonga.
|
||||||
|
#
|
||||||
|
defp check_pgroonga!(:ok) do
|
||||||
|
{_, res, _} =
|
||||||
|
Ecto.Migrator.with_repo(Pleroma.Repo, fn repo ->
|
||||||
|
# TODO: check migrate
|
||||||
|
migrate =
|
||||||
|
from(o in "pg_indexes",
|
||||||
|
where: o.indexname == "object_content_pgroonga"
|
||||||
|
)
|
||||||
|
|> repo.exists?()
|
||||||
|
|
||||||
|
setting = Pleroma.Config.get([:database, :pgroonga_enabled], false)
|
||||||
|
|
||||||
|
do_check_pgroonga!(setting, migrate)
|
||||||
|
end)
|
||||||
|
|
||||||
|
res
|
||||||
|
end
|
||||||
|
|
||||||
|
defp check_pgroonga!(result), do: result
|
||||||
|
|
||||||
|
defp do_check_pgroonga!(setting, migrate) do
|
||||||
|
case {setting, migrate} do
|
||||||
|
{true, false} ->
|
||||||
|
Logger.error(
|
||||||
|
"PGroonga is enabled, but no migrations have been applied for it.\n" <>
|
||||||
|
"If you want to start Akkoma without using PGroonga, set `config :pleroma, :database, pgroonga_enabled: false`.\n" <>
|
||||||
|
"Otherwise apply the following migrations:\n" <>
|
||||||
|
"`mix ecto.migrate --migrations-path priv/repo/optional_migrations/pgroonga/`"
|
||||||
|
)
|
||||||
|
|
||||||
|
{:error, "Unapplied PGroonga Migrations detected"}
|
||||||
|
|
||||||
|
{false, true} ->
|
||||||
|
Logger.error(
|
||||||
|
"Detected applied migrations to use PGroonga to search, but it is not enabled in the settings.\n" <>
|
||||||
|
"If you want to use PGroonga, set `config :pleroma, :database, pgroonga_enabled: true`.\n" <>
|
||||||
|
"Otherwise apply the following migrations:\n" <>
|
||||||
|
"`mix ecto.rollback --migrations-path priv/repo/optional_migrations/pgroonga/`"
|
||||||
|
)
|
||||||
|
|
||||||
|
{:error, "PGroonga Migrations detected"}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp check_system_commands!(:ok) do
|
defp check_system_commands!(:ok) do
|
||||||
filter_commands_statuses = [
|
filter_commands_statuses = [
|
||||||
check_filter(Pleroma.Upload.Filter.Exiftool, "exiftool"),
|
check_filter(Pleroma.Upload.Filter.Exiftool, "exiftool"),
|
||||||
|
|
|
@ -16,7 +16,13 @@ defmodule Pleroma.Search.DatabaseSearch do
|
||||||
@behaviour Pleroma.Search.SearchBackend
|
@behaviour Pleroma.Search.SearchBackend
|
||||||
|
|
||||||
def search(user, search_query, options \\ []) do
|
def search(user, search_query, options \\ []) do
|
||||||
index_type = if Pleroma.Config.get([:database, :rum_enabled]), do: :rum, else: :gin
|
index_type =
|
||||||
|
cond do
|
||||||
|
Pleroma.Config.get([:database, :rum_enabled]) -> :rum
|
||||||
|
Pleroma.Config.get([:database, :pgroonga_enabled]) -> :pgroonga
|
||||||
|
true -> :gin
|
||||||
|
end
|
||||||
|
|
||||||
limit = Enum.min([Keyword.get(options, :limit), 40])
|
limit = Enum.min([Keyword.get(options, :limit), 40])
|
||||||
offset = Keyword.get(options, :offset, 0)
|
offset = Keyword.get(options, :offset, 0)
|
||||||
author = Keyword.get(options, :author)
|
author = Keyword.get(options, :author)
|
||||||
|
@ -132,6 +138,18 @@ defp query_with(q, :rum, search_query, :websearch) do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp query_with(q, :pgroonga, search_query, _) do
|
||||||
|
# PGroonga only supports PostgreSQL version 11 or newer
|
||||||
|
from([a, o] in q,
|
||||||
|
where:
|
||||||
|
fragment(
|
||||||
|
"?->'content' &@~ ?",
|
||||||
|
o.data,
|
||||||
|
^search_query
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
def maybe_restrict_local(q, user) do
|
def maybe_restrict_local(q, user) do
|
||||||
limit = Pleroma.Config.get([:instance, :limit_to_local_content], :unauthenticated)
|
limit = Pleroma.Config.get([:instance, :limit_to_local_content], :unauthenticated)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.CreatePgroongaIndex do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
execute("CREATE EXTENSION IF NOT EXISTS pgroonga")
|
||||||
|
|
||||||
|
drop_if_exists(
|
||||||
|
index(:objects, ["(to_tsvector('english', data->>'content'))"],
|
||||||
|
using: :gin,
|
||||||
|
name: :objects_fts
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
execute(
|
||||||
|
"CREATE INDEX object_content_pgroonga ON objects USING pgroonga ((data->'content')) WITH (tokenizer='TokenMecab')"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
execute("DROP INDEX IF EXISTS object_content_pgroonga")
|
||||||
|
|
||||||
|
create_if_not_exists(
|
||||||
|
index(:objects, ["(to_tsvector('english', data->>'content'))"],
|
||||||
|
using: :gin,
|
||||||
|
name: :objects_fts
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
|
@ -41,7 +41,10 @@ config :web_push_encryption, :vapid_details,
|
||||||
public_key: "<%= web_push_public_key %>",
|
public_key: "<%= web_push_public_key %>",
|
||||||
private_key: "<%= web_push_private_key %>"
|
private_key: "<%= web_push_private_key %>"
|
||||||
|
|
||||||
config :pleroma, :database, rum_enabled: <%= rum_enabled %>
|
config :pleroma, :database,
|
||||||
|
rum_enabled: <%= rum_enabled %>,
|
||||||
|
pgroonga_enabled: <%= pgroonga_enabled %>
|
||||||
|
|
||||||
config :pleroma, :instance, static_dir: "<%= static_dir %>"
|
config :pleroma, :instance, static_dir: "<%= static_dir %>"
|
||||||
config :pleroma, Pleroma.Uploaders.Local, uploads: "<%= uploads_dir %>"
|
config :pleroma, Pleroma.Uploaders.Local, uploads: "<%= uploads_dir %>"
|
||||||
|
|
||||||
|
|
|
@ -10,3 +10,8 @@ CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
else
|
else
|
||||||
""
|
""
|
||||||
end %>
|
end %>
|
||||||
|
<%= if pgroonga_enabled do
|
||||||
|
"CREATE EXTENSION IF NOT EXISTS pgroonga;"
|
||||||
|
else
|
||||||
|
""
|
||||||
|
end %>
|
||||||
|
|
Loading…
Reference in a new issue