From 081034a15ad01c80b80b37fc9908abff89761dfc Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sat, 25 Jun 2016 22:30:22 +0200 Subject: [PATCH] Moved to background job for sending twitter messages. --- .../ticket/article/communicate_twitter.rb | 43 +------ .../communicate_twitter/background_job.rb | 109 ++++++++++++++++++ test/integration/twitter_test.rb | 16 +++ 3 files changed, 126 insertions(+), 42 deletions(-) create mode 100644 app/models/observer/ticket/article/communicate_twitter/background_job.rb diff --git a/app/models/observer/ticket/article/communicate_twitter.rb b/app/models/observer/ticket/article/communicate_twitter.rb index b878a12b4..c68ce42e9 100644 --- a/app/models/observer/ticket/article/communicate_twitter.rb +++ b/app/models/observer/ticket/article/communicate_twitter.rb @@ -17,48 +17,7 @@ class Observer::Ticket::Article::CommunicateTwitter < ActiveRecord::Observer type = Ticket::Article::Type.lookup(id: record.type_id) return if type['name'] !~ /\Atwitter/i - ticket = Ticket.lookup(id: record.ticket_id) - raise "Can't find ticket.preferences for Ticket.find(#{record.ticket_id})" if !ticket.preferences - raise "Can't find ticket.preferences['channel_id'] for Ticket.find(#{record.ticket_id})" if !ticket.preferences['channel_id'] - channel = Channel.lookup(id: ticket.preferences['channel_id']) - raise "No such channel id #{ticket.preferences['channel_id']}" if !channel - raise "Channel.find(#{channel.id}) isn't a twitter channel!" if channel.options[:adapter] !~ /\Atwitter/i - tweet = channel.deliver( - type: type['name'], - to: record.to, - body: record.body, - in_reply_to: record.in_reply_to - ) - - # fill article with tweet info - - # direct message - if tweet.class == Twitter::DirectMessage - record.from = "@#{tweet.sender.screen_name}" - record.to = "@#{tweet.recipient.screen_name}" - - # regular tweet - elsif tweet.class == Twitter::Tweet - record.from = "@#{tweet.user.screen_name}" - if tweet.user_mentions - to = '' - twitter_mention_ids = [] - tweet.user_mentions.each {|user| - if to != '' - to += ' ' - end - to += "@#{user.screen_name}" - twitter_mention_ids.push user.id - } - record.to = to - record.preferences[:twitter_mention_ids] = twitter_mention_ids - end - else - raise "Unknown tweet type '#{tweet.class}'" - end - - record.message_id = tweet.id - record.save + Delayed::Job.enqueue(Observer::Ticket::Article::CommunicateTwitter::BackgroundJob.new(record.id)) end end diff --git a/app/models/observer/ticket/article/communicate_twitter/background_job.rb b/app/models/observer/ticket/article/communicate_twitter/background_job.rb new file mode 100644 index 000000000..d8b664b92 --- /dev/null +++ b/app/models/observer/ticket/article/communicate_twitter/background_job.rb @@ -0,0 +1,109 @@ +class Observer::Ticket::Article::CommunicateTwitter::BackgroundJob + def initialize(id) + @article_id = id + end + + def perform + article = Ticket::Article.find(@article_id) + + # set retry count + if !article.preferences['delivery_retry'] + article.preferences['delivery_retry'] = 0 + end + article.preferences['delivery_retry'] += 1 + + ticket = Ticket.lookup(id: article.ticket_id) + log_error(article, "Can't find ticket.preferences for Ticket.find(#{article.ticket_id})") if !ticket.preferences + log_error(article, "Can't find ticket.preferences['channel_id'] for Ticket.find(#{article.ticket_id})") if !ticket.preferences['channel_id'] + channel = Channel.lookup(id: ticket.preferences['channel_id']) + log_error(article, "No such channel id #{ticket.preferences['channel_id']}") if !channel + log_error(article, "Channel.find(#{channel.id}) isn't a twitter channel!") if channel.options[:adapter] !~ /\Atwitter/i + + begin + tweet = channel.deliver( + type: article.type.name, + to: article.to, + body: article.body, + in_reply_to: article.in_reply_to + ) + rescue => e + log_error(article, e.message) + return + end + if !tweet + log_error(article, 'Unable to send message to twitter') + return + end + + # fill article with tweet info + + # direct message + if tweet.class == Twitter::DirectMessage + article.from = "@#{tweet.sender.screen_name}" + article.to = "@#{tweet.recipient.screen_name}" + + # regular tweet + elsif tweet.class == Twitter::Tweet + article.from = "@#{tweet.user.screen_name}" + if tweet.user_mentions + to = '' + twitter_mention_ids = [] + tweet.user_mentions.each {|user| + if to != '' + to += ' ' + end + to += "@#{user.screen_name}" + twitter_mention_ids.push user.id + } + article.to = to + article.preferences[:twitter_mention_ids] = twitter_mention_ids + end + else + raise "Unknown tweet type '#{tweet.class}'" + end + + # set delivery status + article.preferences['delivery_status_message'] = nil + article.preferences['delivery_status'] = 'success' + article.preferences['delivery_status_date'] = Time.zone.now + + article.message_id = tweet.id.to_s + article.save + + end + + def log_error(local_record, message) + local_record.preferences['delivery_status'] = 'fail' + local_record.preferences['delivery_status_message'] = message + local_record.preferences['delivery_status_date'] = Time.zone.now + local_record.save + Rails.logger.error message + + if local_record.preferences['delivery_retry'] > 3 + Ticket::Article.create( + ticket_id: local_record.ticket_id, + content_type: 'text/plain', + body: "Unable to send tweet: #{message}", + internal: true, + sender: Ticket::Article::Sender.find_by(name: 'System'), + type: Ticket::Article::Type.find_by(name: 'note'), + updated_by_id: 1, + created_by_id: 1, + ) + return + end + + raise message + end + + def max_attempts + 4 + end + + def reschedule_at(current_time, attempts) + if Rails.env.production? + return current_time + attempts * 120.seconds + end + current_time + 5.seconds + end +end diff --git a/test/integration/twitter_test.rb b/test/integration/twitter_test.rb index feb2f362c..f8206bba5 100644 --- a/test/integration/twitter_test.rb +++ b/test/integration/twitter_test.rb @@ -125,6 +125,10 @@ class TwitterTest < ActiveSupport::TestCase updated_by_id: 1, created_by_id: 1, ) + + Scheduler.worker(true) + + article = Ticket::Article.find(article.id) assert(article, "outbound article created, text: #{text}") assert_equal(system_login, article.from, 'ticket article from') assert_equal('', article.to, 'ticket article to') @@ -223,6 +227,10 @@ class TwitterTest < ActiveSupport::TestCase updated_by_id: 1, created_by_id: 1, ) + + Scheduler.worker(true) + + article = Ticket::Article.find(article.id) assert(article, "outbound article created, text: #{reply_text}") assert_equal(system_login, article.from, 'ticket article from') assert_equal(customer_login, article.to, 'ticket article to') @@ -306,6 +314,10 @@ class TwitterTest < ActiveSupport::TestCase updated_by_id: 1, created_by_id: 1, ) + + Scheduler.worker(true) + + outbound_article = Ticket::Article.find(outbound_article.id) assert(outbound_article, 'outbound article created') assert_equal(2, outbound_article.ticket.articles.count, 'ticket article outbound count') assert_equal(system_login, outbound_article.from, 'ticket article from') @@ -445,6 +457,10 @@ class TwitterTest < ActiveSupport::TestCase updated_by_id: 1, created_by_id: 1, ) + + Scheduler.worker(true) + + article = Ticket::Article.find(article.id) assert(article, "outbound article created, text: #{reply_text}") assert_equal(system_login, article.from, 'ticket article from') assert_equal('', article.to, 'ticket article to')