5f27e26bb4
The repository push email can be very expensive to generate, especially with syntax-highlighted diffs. Instead of generating the email for each recipient, generate one email object and reset the Message-Id and To headers for each recipient. (Cloning would also be expensive in the case of large emails, although probably not as bad as generating from scratch.)
83 lines
2.3 KiB
Ruby
83 lines
2.3 KiB
Ruby
class EmailsOnPushWorker
|
|
include Sidekiq::Worker
|
|
|
|
attr_reader :email, :skip_premailer
|
|
|
|
def perform(project_id, recipients, push_data, options = {})
|
|
options.symbolize_keys!
|
|
options.reverse_merge!(
|
|
send_from_committer_email: false,
|
|
disable_diffs: false
|
|
)
|
|
send_from_committer_email = options[:send_from_committer_email]
|
|
disable_diffs = options[:disable_diffs]
|
|
|
|
project = Project.find(project_id)
|
|
before_sha = push_data["before"]
|
|
after_sha = push_data["after"]
|
|
ref = push_data["ref"]
|
|
author_id = push_data["user_id"]
|
|
|
|
action =
|
|
if Gitlab::Git.blank_ref?(before_sha)
|
|
:create
|
|
elsif Gitlab::Git.blank_ref?(after_sha)
|
|
:delete
|
|
else
|
|
:push
|
|
end
|
|
|
|
compare = nil
|
|
reverse_compare = false
|
|
if action == :push
|
|
compare = Gitlab::Git::Compare.new(project.repository.raw_repository, before_sha, after_sha)
|
|
|
|
return false if compare.same
|
|
|
|
if compare.commits.empty?
|
|
compare = Gitlab::Git::Compare.new(project.repository.raw_repository, after_sha, before_sha)
|
|
|
|
reverse_compare = true
|
|
|
|
return false if compare.commits.empty?
|
|
end
|
|
end
|
|
|
|
recipients.split.each do |recipient|
|
|
begin
|
|
send_email(
|
|
recipient,
|
|
project_id,
|
|
author_id: author_id,
|
|
ref: ref,
|
|
action: action,
|
|
compare: compare,
|
|
reverse_compare: reverse_compare,
|
|
send_from_committer_email: send_from_committer_email,
|
|
disable_diffs: disable_diffs
|
|
)
|
|
|
|
# These are input errors and won't be corrected even if Sidekiq retries
|
|
rescue Net::SMTPFatalError, Net::SMTPSyntaxError => e
|
|
logger.info("Failed to send e-mail for project '#{project.name_with_namespace}' to #{recipient}: #{e}")
|
|
end
|
|
end
|
|
ensure
|
|
@email = nil
|
|
compare = nil
|
|
GC.start
|
|
end
|
|
|
|
private
|
|
|
|
def send_email(recipient, project_id, options)
|
|
# Generating the body of this email can be expensive, so only do it once
|
|
@skip_premailer ||= email.present?
|
|
@email ||= Notify.repository_push_email(project_id, options)
|
|
|
|
email.to = recipient
|
|
email.add_message_id
|
|
email.header[:skip_premailer] = true if skip_premailer
|
|
email.deliver_now
|
|
end
|
|
end
|