From 49d3611273b1f8b4190863ee525fe4f958afd251 Mon Sep 17 00:00:00 2001 From: Dominik Sander Date: Tue, 23 Aug 2016 17:52:34 +0200 Subject: [PATCH] Allow TwitterUserAgent to retry failed actions Add new `emit_error_events` option which is set to `false` for all new `TwitterActionAgent`s. This will ensure the Agent is retried when the action failed by raising an exception. For all existing `TwitterUserAgent`s the option is set to `true` to keep the previous behavior. --- app/models/agents/twitter_action_agent.rb | 11 +++- ...t_error_event_for_twitter_action_agents.rb | 15 +++++ .../agents/twitter_action_agent_spec.rb | 55 +++++++++++++++---- 3 files changed, 68 insertions(+), 13 deletions(-) create mode 100644 db/migrate/20160823151303_set_emit_error_event_for_twitter_action_agents.rb diff --git a/app/models/agents/twitter_action_agent.rb b/app/models/agents/twitter_action_agent.rb index c56ff95f..5d360bbe 100644 --- a/app/models/agents/twitter_action_agent.rb +++ b/app/models/agents/twitter_action_agent.rb @@ -16,6 +16,7 @@ module Agents Set `expected_receive_period_in_days` to the maximum amount of time that you'd expect to pass between Events being received by this Agent. Set `retweet` to either true or false. Set `favorite` to either true or false. + Set `emit_error_events` to true to emit an Event when the action failed, otherwise the action will be retried. MD def validate_options @@ -25,6 +26,9 @@ module Agents unless retweet? || favorite? errors.add(:base, "at least one action must be true") end + if emit_error_events?.nil? + errors.add(:base, "emit_error_events must be set to 'true' or 'false'") + end end def working? @@ -36,6 +40,7 @@ module Agents 'expected_receive_period_in_days' => '2', 'favorite' => 'false', 'retweet' => 'true', + 'emit_error_events' => 'false' } end @@ -47,6 +52,10 @@ module Agents boolify(options['favorite']) end + def emit_error_events? + boolify(options['emit_error_events']) + end + def receive(incoming_events) tweets = tweets_from_events(incoming_events) @@ -54,6 +63,7 @@ module Agents twitter.favorite(tweets) if favorite? twitter.retweet(tweets) if retweet? rescue Twitter::Error => e + raise e unless emit_error_events? create_event :payload => { 'success' => false, 'error' => e.message, @@ -71,4 +81,3 @@ module Agents end end end - diff --git a/db/migrate/20160823151303_set_emit_error_event_for_twitter_action_agents.rb b/db/migrate/20160823151303_set_emit_error_event_for_twitter_action_agents.rb new file mode 100644 index 00000000..b38d97b0 --- /dev/null +++ b/db/migrate/20160823151303_set_emit_error_event_for_twitter_action_agents.rb @@ -0,0 +1,15 @@ +class SetEmitErrorEventForTwitterActionAgents < ActiveRecord::Migration + def up + Agents::TwitterActionAgent.find_each do |agent| + agent.options['emit_error_events'] = 'true' + agent.save!(validate: false) + end + end + + def down + Agents::TwitterActionAgent.find_each do |agent| + agent.options.delete('emit_error_events') + agent.save!(validate: false) + end + end +end diff --git a/spec/models/agents/twitter_action_agent_spec.rb b/spec/models/agents/twitter_action_agent_spec.rb index fd29ef15..46605eb8 100644 --- a/spec/models/agents/twitter_action_agent_spec.rb +++ b/spec/models/agents/twitter_action_agent_spec.rb @@ -24,11 +24,11 @@ describe Agents::TwitterActionAgent do context 'when set up to retweet' do before do - @agent = build_agent({ - 'expected_receive_period_in_days' => '2', + @agent = build_agent( 'favorite' => 'false', 'retweet' => 'true', - }) + 'emit_error_events' => 'true' + ) @agent.save! end @@ -68,9 +68,9 @@ describe Agents::TwitterActionAgent do context 'when set up to favorite' do before do @agent = build_agent( - 'expected_receive_period_in_days' => '2', 'favorite' => 'true', 'retweet' => 'false', + 'emit_error_events' => 'true' ) @agent.save! end @@ -107,13 +107,48 @@ describe Agents::TwitterActionAgent do end end end + + context 'with emit_error_events set to false' do + it 'does re-raises the exception on failure' do + agent = build_agent + + stub(agent.twitter).retweet(anything) { + raise Twitter::Error.new('uh oh') + } + + expect { agent.receive([@event1]) }.to raise_error(StandardError, /uh oh/) + + end + end end describe "#validate_options" do + it 'the default options are valid' do + agent = build_agent(described_class.new.default_options) + + expect(agent).to be_valid + end + + context 'emit_error_events' do + it 'can be set to true' do + agent = build_agent(described_class.new.default_options.merge('emit_error_events' => 'true')) + expect(agent).to be_valid + end + + it 'must be a boolean' do + agent = build_agent(described_class.new.default_options.merge('emit_error_events' => 'notbolean')) + expect(agent).not_to be_valid + end + end + + it 'expected_receive_period_in_days must be set' do + agent = build_agent(described_class.new.default_options.merge('expected_receive_period_in_days' => '')) + expect(agent).not_to be_valid + end + context 'when set up to neither favorite or retweet' do it 'is invalid' do agent = build_agent( - 'expected_receive_period_in_days' => '2', 'favorite' => 'false', 'retweet' => 'false', ) @@ -129,11 +164,7 @@ describe Agents::TwitterActionAgent do end it 'checks if events have been received within the expected time period' do - agent = build_agent( - 'expected_receive_period_in_days' => '2', - 'favorite' => 'false', - 'retweet' => 'true', - ) + agent = build_agent agent.save! expect(agent).not_to be_working # No events received @@ -147,10 +178,10 @@ describe Agents::TwitterActionAgent do end end - def build_agent(options) + def build_agent(options = {}) described_class.new do |agent| agent.name = 'twitter stuff' - agent.options = options + agent.options = agent.default_options.merge(options) agent.service = services(:generic) agent.user = users(:bob) end