Activities rejected by MRF being retried by oban worker due to match errors in transmogrifier
Incoming federated activites when being processed by transmogrifier are having a chance to be rejected by one of local MRFs.
Transmogrifier calls to common_pipeline (e.g. https://git.pleroma.social/pleroma/pleroma/-/blob/develop/lib/pleroma/web/activity_pub/transmogrifier.ex#L495-516 ) however do not account for possibility of rejection, resulting in error being returned from oban job invocation and causing it to be retried at later time until retry limit is exceeded.
Possible solution may be to explicitly handle :reject
s in transmogrifier calls to common_pipeline
, or pass it up the call chain, ultimately handling reject as an :ok
result, to avoid further job retries.
Incorrect assumptions, has nothing to do with actual problem, see #2912 (comment 92995)
Generally, when `:reject` is returned from MRF, it is interpreted by remote instance as an error, and activity re-delivery attempts are being made, receiving `:reject` again and repeating the cycle until remote instance exhausts delivery retry count for this activity.This may put some excessive and most importantly pointless strain on the network as a whole, clogging outgoing queues and requiring receiving instance to react to the same activity again and again. Probably best solution would be to equate :reject
with a distinct error and make sure every project would handle it accordingly, but it may be difficult or even unrealistic to get every project on board. At the same time, it is possible to return fake OK status, while executing no side-effects locally. This may have it's own issues, hence why I'd like to discuss this and consider possible pros and cons first.
As far as implementation goes, simply adding a new symbol handling to the do_common_pipeline
, e.g.
def do_common_pipeline(message, meta) do
with {_, {:ok, message, meta}} <- {:validate, object_validator().validate(message, meta)},
{_, {:ok, message, meta}} <- {:mrf, mrf().pipeline_filter(message, meta)},
{_, {:ok, message, meta}} <- {:persist, activity_pub().persist(message, meta)},
{_, {:ok, message, meta}} <- {:side_effects, side_effects().handle(message, meta)},
{_, {:ok, _}} <- {:federation, maybe_federate(message, meta)} do
{:ok, message, meta}
else
{:mrf, {:reject, message, _}} -> {:reject, message}
+ {:mrf, {:ignore, message, meta}} -> {:ok, message, meta}
e -> {:error, e}
end
end
with this :ignore
returned from MRF instead of :reject
seem to be sufficient to the requirement of ending the activity processing on both ends.
There is a tangentially related issue #2765 for the case when local instance is the initiator of a fetch action and this action being retried even after got rejected by local MRF policy.
This issue is more specific to the case when initiator is the remote instance, not necessarily pleroma, trying to re-deliver an activity previously rejected by a local MRF policy, with local record of rejected activities doing nothing to prevent unnecessary network interaction.