From 5c06fe490279e3c901aa9e19ebe2bdba4903395f Mon Sep 17 00:00:00 2001
From: Claire <claire.github-309c@sitedethib.com>
Date: Mon, 2 Dec 2024 10:24:34 +0100
Subject: [PATCH] Fix processing incoming post edits with mentions to
 unresolvable accounts (#33129)

---
 .../activitypub/process_status_update_service.rb     | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb
index 1c7584b76..2ddecb634 100644
--- a/app/services/activitypub/process_status_update_service.rb
+++ b/app/services/activitypub/process_status_update_service.rb
@@ -192,6 +192,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
   def update_mentions!
     previous_mentions = @status.active_mentions.includes(:account).to_a
     current_mentions  = []
+    unresolved_mentions = []
 
     @raw_mentions.each do |href|
       next if href.blank?
@@ -205,6 +206,12 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
       mention ||= account.mentions.new(status: @status)
 
       current_mentions << mention
+    rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS
+      # Since previous mentions are about already-known accounts,
+      # they don't try to resolve again and won't fall into this case.
+      # In other words, this failure case is only for new mentions and won't
+      # affect `removed_mentions` so they can safely be retried asynchronously
+      unresolved_mentions << href
     end
 
     current_mentions.each do |mention|
@@ -217,6 +224,11 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
     removed_mentions = previous_mentions - current_mentions
 
     Mention.where(id: removed_mentions.map(&:id)).update_all(silent: true) unless removed_mentions.empty?
+
+    # Queue unresolved mentions for later
+    unresolved_mentions.uniq.each do |uri|
+      MentionResolveWorker.perform_in(rand(30...600).seconds, @status.id, uri, { 'request_id' => @request_id })
+    end
   end
 
   def update_emojis!