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.
This commit is contained in:
parent
0167397218
commit
ce087ef889
1 changed files with 50 additions and 31 deletions
|
@ -22,12 +22,16 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
||||||
private
|
private
|
||||||
|
|
||||||
def process_status
|
def process_status
|
||||||
status_params = process_status_params
|
@tags = []
|
||||||
|
@mentions = []
|
||||||
|
@params = {}
|
||||||
|
|
||||||
|
process_status_params
|
||||||
|
process_tags
|
||||||
|
|
||||||
ApplicationRecord.transaction do
|
ApplicationRecord.transaction do
|
||||||
@status = Status.create!(status_params)
|
@status = Status.create!(@params)
|
||||||
|
attach_tags(@status)
|
||||||
process_tags(@status)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
resolve_thread(@status)
|
resolve_thread(@status)
|
||||||
|
@ -42,62 +46,77 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_status_params
|
def process_status_params
|
||||||
{
|
@params = begin
|
||||||
uri: @object['id'],
|
{
|
||||||
url: object_url || @object['id'],
|
uri: @object['id'],
|
||||||
account: @account,
|
url: object_url || @object['id'],
|
||||||
text: text_from_content || '',
|
account: @account,
|
||||||
language: detected_language,
|
text: text_from_content || '',
|
||||||
spoiler_text: text_from_summary || '',
|
language: detected_language,
|
||||||
created_at: @object['published'],
|
spoiler_text: text_from_summary || '',
|
||||||
override_timestamps: @options[:override_timestamps],
|
created_at: @object['published'],
|
||||||
reply: @object['inReplyTo'].present?,
|
override_timestamps: @options[:override_timestamps],
|
||||||
sensitive: @object['sensitive'] || false,
|
reply: @object['inReplyTo'].present?,
|
||||||
visibility: visibility_from_audience,
|
sensitive: @object['sensitive'] || false,
|
||||||
thread: replied_to_status,
|
visibility: visibility_from_audience,
|
||||||
conversation: conversation_from_uri(@object['conversation']),
|
thread: replied_to_status,
|
||||||
media_attachment_ids: process_attachments.take(4).map(&:id),
|
conversation: conversation_from_uri(@object['conversation']),
|
||||||
}
|
media_attachment_ids: process_attachments.take(4).map(&:id),
|
||||||
|
}
|
||||||
|
end
|
||||||
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?
|
return if @object['tag'].nil?
|
||||||
|
|
||||||
as_array(@object['tag']).each do |tag|
|
as_array(@object['tag']).each do |tag|
|
||||||
if equals_or_includes?(tag['type'], 'Hashtag')
|
if equals_or_includes?(tag['type'], 'Hashtag')
|
||||||
process_hashtag tag, status
|
process_hashtag tag
|
||||||
elsif equals_or_includes?(tag['type'], 'Mention')
|
elsif equals_or_includes?(tag['type'], 'Mention')
|
||||||
process_mention tag, status
|
process_mention tag
|
||||||
elsif equals_or_includes?(tag['type'], 'Emoji')
|
elsif equals_or_includes?(tag['type'], 'Emoji')
|
||||||
process_emoji tag, status
|
process_emoji tag
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_hashtag(tag, status)
|
def process_hashtag(tag)
|
||||||
return if tag['name'].blank?
|
return if tag['name'].blank?
|
||||||
|
|
||||||
hashtag = tag['name'].gsub(/\A#/, '').mb_chars.downcase
|
hashtag = tag['name'].gsub(/\A#/, '').mb_chars.downcase
|
||||||
hashtag = Tag.where(name: hashtag).first_or_create(name: hashtag)
|
hashtag = Tag.where(name: hashtag).first_or_create(name: hashtag)
|
||||||
|
|
||||||
return if status.tags.include?(hashtag)
|
return if @tags.include?(hashtag)
|
||||||
|
|
||||||
status.tags << hashtag
|
@tags << hashtag
|
||||||
TrendingTags.record_use!(hashtag, status.account, status.created_at) if status.public_visibility?
|
|
||||||
rescue ActiveRecord::RecordInvalid
|
rescue ActiveRecord::RecordInvalid
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_mention(tag, status)
|
def process_mention(tag)
|
||||||
return if tag['href'].blank?
|
return if tag['href'].blank?
|
||||||
|
|
||||||
account = account_from_uri(tag['href'])
|
account = account_from_uri(tag['href'])
|
||||||
account = ::FetchRemoteAccountService.new.call(tag['href'], id: false) if account.nil?
|
account = ::FetchRemoteAccountService.new.call(tag['href'], id: false) if account.nil?
|
||||||
|
|
||||||
return if account.nil?
|
return if account.nil?
|
||||||
account.mentions.create(status: status)
|
|
||||||
|
@mentions << Mention.new(account: account)
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_emoji(tag, _status)
|
def process_emoji(tag)
|
||||||
return if skip_download?
|
return if skip_download?
|
||||||
return if tag['name'].blank? || tag['icon'].blank? || tag['icon']['url'].blank?
|
return if tag['name'].blank? || tag['icon'].blank? || tag['icon']['url'].blank?
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue