From ce087ef889460122d195e39252f1d05216c5e1aa Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 11 Oct 2018 00:50:18 +0200 Subject: [PATCH] Move network calls out of transaction in ActivityPub handler (#8951) Mention and emoji code may perform network calls, but does not need to do that inside the database transaction. This may improve availability of database connections when using pgBouncer in transaction mode. --- app/lib/activitypub/activity/create.rb | 81 ++++++++++++++++---------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 9782897884..b889461cb0 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -22,12 +22,16 @@ class ActivityPub::Activity::Create < ActivityPub::Activity private def process_status - status_params = process_status_params + @tags = [] + @mentions = [] + @params = {} + + process_status_params + process_tags ApplicationRecord.transaction do - @status = Status.create!(status_params) - - process_tags(@status) + @status = Status.create!(@params) + attach_tags(@status) end resolve_thread(@status) @@ -42,62 +46,77 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def process_status_params - { - uri: @object['id'], - url: object_url || @object['id'], - account: @account, - text: text_from_content || '', - language: detected_language, - spoiler_text: text_from_summary || '', - created_at: @object['published'], - override_timestamps: @options[:override_timestamps], - reply: @object['inReplyTo'].present?, - sensitive: @object['sensitive'] || false, - visibility: visibility_from_audience, - thread: replied_to_status, - conversation: conversation_from_uri(@object['conversation']), - media_attachment_ids: process_attachments.take(4).map(&:id), - } + @params = begin + { + uri: @object['id'], + url: object_url || @object['id'], + account: @account, + text: text_from_content || '', + language: detected_language, + spoiler_text: text_from_summary || '', + created_at: @object['published'], + override_timestamps: @options[:override_timestamps], + reply: @object['inReplyTo'].present?, + sensitive: @object['sensitive'] || false, + visibility: visibility_from_audience, + thread: replied_to_status, + conversation: conversation_from_uri(@object['conversation']), + media_attachment_ids: process_attachments.take(4).map(&:id), + } + end end - def process_tags(status) + def attach_tags(status) + @tags.each do |tag| + status.tags << tag + TrendingTags.record_use!(hashtag, status.account, status.created_at) if status.public_visibility? + end + + @mentions.each do |mention| + mention.status = status + mention.save + end + end + + def process_tags return if @object['tag'].nil? as_array(@object['tag']).each do |tag| if equals_or_includes?(tag['type'], 'Hashtag') - process_hashtag tag, status + process_hashtag tag elsif equals_or_includes?(tag['type'], 'Mention') - process_mention tag, status + process_mention tag elsif equals_or_includes?(tag['type'], 'Emoji') - process_emoji tag, status + process_emoji tag end end end - def process_hashtag(tag, status) + def process_hashtag(tag) return if tag['name'].blank? hashtag = tag['name'].gsub(/\A#/, '').mb_chars.downcase hashtag = Tag.where(name: hashtag).first_or_create(name: hashtag) - return if status.tags.include?(hashtag) + return if @tags.include?(hashtag) - status.tags << hashtag - TrendingTags.record_use!(hashtag, status.account, status.created_at) if status.public_visibility? + @tags << hashtag rescue ActiveRecord::RecordInvalid nil end - def process_mention(tag, status) + def process_mention(tag) return if tag['href'].blank? account = account_from_uri(tag['href']) account = ::FetchRemoteAccountService.new.call(tag['href'], id: false) if account.nil? + return if account.nil? - account.mentions.create(status: status) + + @mentions << Mention.new(account: account) end - def process_emoji(tag, _status) + def process_emoji(tag) return if skip_download? return if tag['name'].blank? || tag['icon'].blank? || tag['icon']['url'].blank?