forked from AkkomaGang/akkoma
116 lines
3.1 KiB
Elixir
116 lines
3.1 KiB
Elixir
# Pleroma: A lightweight social networking server
|
|
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
defmodule Pleroma.Migrators.Support.BaseMigratorState do
|
|
@moduledoc """
|
|
Base background migrator state functionality.
|
|
"""
|
|
|
|
@callback data_migration() :: Pleroma.DataMigration.t()
|
|
|
|
defmacro __using__(_opts) do
|
|
quote do
|
|
use Agent
|
|
|
|
alias Pleroma.DataMigration
|
|
|
|
@behaviour Pleroma.Migrators.Support.BaseMigratorState
|
|
@reg_name {:global, __MODULE__}
|
|
|
|
def start_link(_) do
|
|
Agent.start_link(fn -> load_state_from_db() end, name: @reg_name)
|
|
end
|
|
|
|
def data_migration, do: raise("data_migration/0 is not implemented")
|
|
defoverridable data_migration: 0
|
|
|
|
defp load_state_from_db do
|
|
data_migration = data_migration()
|
|
|
|
data =
|
|
if data_migration do
|
|
Map.new(data_migration.data, fn {k, v} -> {String.to_atom(k), v} end)
|
|
else
|
|
%{}
|
|
end
|
|
|
|
%{
|
|
data_migration_id: data_migration && data_migration.id,
|
|
data: data
|
|
}
|
|
end
|
|
|
|
def persist_to_db do
|
|
%{data_migration_id: data_migration_id, data: data} = state()
|
|
|
|
if data_migration_id do
|
|
DataMigration.update_one_by_id(data_migration_id, data: data)
|
|
else
|
|
{:error, :nil_data_migration_id}
|
|
end
|
|
end
|
|
|
|
def reset do
|
|
%{data_migration_id: data_migration_id} = state()
|
|
|
|
with false <- is_nil(data_migration_id),
|
|
:ok <-
|
|
DataMigration.update_one_by_id(data_migration_id,
|
|
state: :pending,
|
|
data: %{}
|
|
) do
|
|
reinit()
|
|
else
|
|
true -> {:error, :nil_data_migration_id}
|
|
e -> e
|
|
end
|
|
end
|
|
|
|
def reinit do
|
|
Agent.update(@reg_name, fn _state -> load_state_from_db() end)
|
|
end
|
|
|
|
def state do
|
|
Agent.get(@reg_name, & &1)
|
|
end
|
|
|
|
def get_data_key(key, default \\ nil) do
|
|
get_in(state(), [:data, key]) || default
|
|
end
|
|
|
|
def put_data_key(key, value) do
|
|
_ = persist_non_data_change(key, value)
|
|
|
|
Agent.update(@reg_name, fn state ->
|
|
put_in(state, [:data, key], value)
|
|
end)
|
|
end
|
|
|
|
def increment_data_key(key, increment \\ 1) do
|
|
Agent.update(@reg_name, fn state ->
|
|
initial_value = get_in(state, [:data, key]) || 0
|
|
updated_value = initial_value + increment
|
|
put_in(state, [:data, key], updated_value)
|
|
end)
|
|
end
|
|
|
|
defp persist_non_data_change(:state, value) do
|
|
with true <- get_data_key(:state) != value,
|
|
true <- value in Pleroma.DataMigration.State.__valid_values__(),
|
|
%{data_migration_id: data_migration_id} when not is_nil(data_migration_id) <- state() do
|
|
DataMigration.update_one_by_id(data_migration_id, state: value)
|
|
else
|
|
false -> :ok
|
|
_ -> {:error, :nil_data_migration_id}
|
|
end
|
|
end
|
|
|
|
defp persist_non_data_change(_, _) do
|
|
nil
|
|
end
|
|
|
|
def data_migration_id, do: Map.get(state(), :data_migration_id)
|
|
end
|
|
end
|
|
end
|