# Pleroma: A lightweight social networking server # Copyright © 2017-2022 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Workers.PublisherWorker do alias Pleroma.Activity alias Pleroma.Config alias Pleroma.Instances alias Pleroma.Web.Federator use Oban.Worker, queue: :federator_outgoing, max_attempts: 13 @publish_one_param_keys %{ "activity_id" => :activity_id, "cc" => :cc, "inbox" => :inbox, "unreachable_since" => :unreachable_since } @impl true def perform(%Job{args: %{"op" => "publish", "activity_id" => activity_id}}) do activity = Activity.get_by_id(activity_id) federator().perform(:publish, activity) end def perform(%Job{args: %{"op" => "publish_one", "params" => params}} = job) do params = Enum.reduce(params, %{}, fn {key, value}, acc -> case @publish_one_param_keys do %{^key => atom_key} -> Map.put(acc, atom_key, value) _ -> acc end end) # Cancel / skip the job if this server believed to be unreachable now if not Instances.reachable?(params.inbox) do {:cancel, :unreachable} else case federator().perform(:publish_one, params) do {:ok, _} -> :ok {:error, _} = error -> # Only mark as unreachable on final failure if job.attempt == job.max_attempts do Instances.set_unreachable(params.inbox) end error error -> # Unexpected error, may have been client side error end end end @impl true def timeout(_job), do: :timer.seconds(10) defp federator, do: Config.get([:pipeline, :federator], Federator) @base_backoff 15 @pow 5 @impl true def backoff(%Job{attempt: attempt}) when is_integer(attempt) do backoff = :math.pow(attempt, @pow) + @base_backoff + :rand.uniform(2 * @base_backoff) * attempt trunc(backoff) end end