diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2018-10-11 00:50:18 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-11 00:50:18 +0200 |
commit | 790d3bc6370f1baf0d00ccf89e81387204c65194 (patch) | |
tree | 7dc95810d0e641afd7a6cc7fdab7273760457cb0 | |
parent | ac7df62a0441b95ec04fd9111a9394795dd53ff2 (diff) |
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.
-rw-r--r-- | app/lib/activitypub/activity/create.rb | 85 |
1 files changed, 52 insertions, 33 deletions
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 978289788..b889461cb 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 = {} - ApplicationRecord.transaction do - @status = Status.create!(status_params) + process_status_params + process_tags - process_tags(@status) + ApplicationRecord.transaction do + @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), - } - end - - def process_tags(status) + @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 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? |