From f4fbf45895bacd74a7333bf5dc56ba3651df8e2b Mon Sep 17 00:00:00 2001 From: Florian Krupicka Date: Tue, 24 Aug 2021 16:52:12 +0200 Subject: [PATCH] Use asynchronous ActiveJob for message delivery Calling out to a 3rd party web service like Slack or Mattermost blocks the request for the current Redmine user. Depending on network latency, this can result in very slow response on any action that is notified via `redmine_messenger`. Instead the backend call should make use of Rails builtin asynchronous background job queuing (the same as used for Redmine mails), returning to the user earlier. We don't specify the actual queue backend for this job, so any Redmine installation can select an appropiate queue backend by themselves or simply use the default builtin backends. --- app/models/messenger.rb | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/app/models/messenger.rb b/app/models/messenger.rb index 83b8c6a..38404ee 100644 --- a/app/models/messenger.rb +++ b/app/models/messenger.rb @@ -47,21 +47,8 @@ class Messenger end channels.each do |channel| - uri = URI url params[:channel] = channel - http_options = { use_ssl: uri.scheme == 'https' } - http_options[:verify_mode] = OpenSSL::SSL::VERIFY_NONE unless RedmineMessenger.setting? :messenger_verify_ssl - begin - req = Net::HTTP::Post.new uri - req.set_form_data payload: params.to_json - Net::HTTP.start uri.hostname, uri.port, http_options do |http| - response = http.request req - Rails.logger.warn response.inspect unless [Net::HTTPSuccess, Net::HTTPRedirection, Net::HTTPOK].include? response - end - rescue StandardError => e - Rails.logger.warn "cannot connect to #{url}" - Rails.logger.warn e - end + DeliverMessageJob.perform_later url, params end end @@ -304,4 +291,26 @@ class Messenger [] end end + + class DeliverMessageJob < ActiveJob::Base + queue_as :default + + def perform(url, params) + uri = URI url + params[:channel] = channel + http_options = { use_ssl: uri.scheme == 'https' } + http_options[:verify_mode] = OpenSSL::SSL::VERIFY_NONE unless RedmineMessenger.setting? :messenger_verify_ssl + begin + req = Net::HTTP::Post.new uri + req.set_form_data payload: params.to_json + Net::HTTP.start uri.hostname, uri.port, http_options do |http| + response = http.request req + Rails.logger.warn response.inspect unless [Net::HTTPSuccess, Net::HTTPRedirection, Net::HTTPOK].include? response + end + rescue StandardError => e + Rails.logger.warn "cannot connect to #{url}" + Rails.logger.warn e + end + end + end end