diff --git a/app/models/observer/ticket/article/communicate_facebook.rb b/app/models/observer/ticket/article/communicate_facebook.rb index ea6387284..73ad34211 100644 --- a/app/models/observer/ticket/article/communicate_facebook.rb +++ b/app/models/observer/ticket/article/communicate_facebook.rb @@ -19,36 +19,7 @@ class Observer::Ticket::Article::CommunicateFacebook < ActiveRecord::Observer type = Ticket::Article::Type.lookup(id: record.type_id) return if type['name'] !~ /\Afacebook/ - 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 "Channel.find(#{channel.id}) isn't a twitter channel!" if channel.options[:adapter] !~ /\Afacebook/i - - # check source object id - ticket = record.ticket - if !ticket.preferences['channel_fb_object_id'] - raise "fb object id is missing in ticket.preferences['channel_fb_object_id'] for Ticket.find(#{ticket.id})" - end - - # fill in_reply_to - if !record.in_reply_to || record.in_reply_to.empty? - record.in_reply_to = ticket.articles.first.message_id - end - - facebook = Channel::Driver::Facebook.new - post = facebook.send( - channel.options, - ticket.preferences[:channel_fb_object_id], - { - type: type['name'], - to: record.to, - body: record.body, - in_reply_to: record.in_reply_to, - } - ) - record.from = post['from']['name'] - record.message_id = post['id'] - record.save + Delayed::Job.enqueue(Observer::Ticket::Article::CommunicateFacebook::BackgroundJob.new(record.id)) end + end diff --git a/app/models/observer/ticket/article/communicate_facebook/background_job.rb b/app/models/observer/ticket/article/communicate_facebook/background_job.rb new file mode 100644 index 000000000..702208419 --- /dev/null +++ b/app/models/observer/ticket/article/communicate_facebook/background_job.rb @@ -0,0 +1,99 @@ +class Observer::Ticket::Article::CommunicateFacebook::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, "Channel.find(#{channel.id}) isn't a twitter channel!") if channel.options[:adapter] !~ /\Afacebook/i + + # check source object id + if !ticket.preferences['channel_fb_object_id'] + log_error(article, "fb object id is missing in ticket.preferences['channel_fb_object_id'] for Ticket.find(#{ticket.id})") + end + + # fill in_reply_to + if !article.in_reply_to || article.in_reply_to.empty? + article.in_reply_to = ticket.articles.first.message_id + end + + begin + facebook = Channel::Driver::Facebook.new + post = facebook.send( + channel.options, + ticket.preferences[:channel_fb_object_id], + { + 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 !post + log_error(article, 'Unable to send message to facebook') + return + end + + # fill article with post info + article.from = post['from']['name'] + article.message_id = post['id'] + + # set delivery status + article.preferences['delivery_status_message'] = nil + article.preferences['delivery_status'] = 'success' + article.preferences['delivery_status_date'] = Time.zone.now + + 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/facebook_test.rb b/test/integration/facebook_test.rb index ba61aa570..91807e713 100644 --- a/test/integration/facebook_test.rb +++ b/test/integration/facebook_test.rb @@ -36,6 +36,11 @@ class FacebookTest < ActiveSupport::TestCase customer_id = ENV['FACEBOOK_CUSTOMER'].split(':')[1] customer_access_token = ENV['FACEBOOK_CUSTOMER'].split(':')[2] + #app_id = '16148802753996712' + #app_secret = '4ff83ae48ae7a375ca25576956cd51dc12' + #oauth = Koala::Facebook::OAuth.new(app_id, app_secret) + #customer_access_token = oauth.exchange_access_token(customer_access_token) + provider_options = { adapter: 'facebook', auth: { @@ -184,6 +189,10 @@ class FacebookTest < 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(outbound_article.from, 'Hansi Merkurs Hutfabrik', 'ticket article outbound count') assert_equal(outbound_article.ticket.articles.count, 2, 'ticket article outbound count') @@ -209,6 +218,10 @@ class FacebookTest < 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(outbound_article.from, 'Hansi Merkurs Hutfabrik', 'ticket article outbound count') assert_equal(outbound_article.ticket.articles.count, 4, 'ticket article outbound count')