ruby - How to test retries and failures in resque-retry and Rails 4? -
i trying write spec tests retry functionality of resque-retry , can not seem tests hit binding.pry's correctly. there way test functionality using rspec 3 can verify functioning intended?
this request spec , trying simulate live request via fixtures, no matter try can't seem job retry.
gem 'resque', require: 'resque/server' gem 'resque-web', require: 'resque_web' gem 'resque-scheduler' gem 'resque-retry' gem 'resque-lock-timeout'
i using resque_rspec, , trying testing strategy.
partial spec
it 'retries it' stub_request(:any, /.*api.bigcartel.*/).to_return(body: '{}', status: 200) @order_shipped_json['order']['originator_id'] = @provider_order post "/hook/shops/#{@shop.id}", @order_shipped_json.to_json, format: :json resquespec.perform_all(queue_name) ??? end
queue job
class queuehook extend resque::plugins::locktimeout extend resque::plugins::retry extend queuelock extend queuelogger @queue = appsettings.queues[:hook_queue_name].to_sym @lock_timeout = 600 @retry_exceptions = [queueerror::lockfailed] @retry_limit = 600 @retry_delay = 1 class << self def perform(web_hook_payload_id, _whiplash_customer_id) activerecord::base.clear_active_connections! @web_hook_payload = webhookpayload.find(web_hook_payload_id) klass_constructor @hook.process_event end def identifier(_web_hook_payload_id, whiplash_customer_id) "lock:integration_hook:#{whiplash_customer_id}" end def after_perform_delete_webhook(_web_hook_payload_id, _whiplash_customer_id) @web_hook_payload.destroy end private ... end end
queue job modules
module queuelogger def before_perform_log_job(*args) rails.logger.info "[resque][#{self}] running #{args.inspect}..." end def on_failure_log_job(*args) message = "[resque][#{self}] failed #{args.inspect}..." run_counters rails.logger.info message_builder(message) end private def run_counters @num_attempts += retry_attempt @all_attempts += retry_limit end def message_builder(message) return message unless @num_attempts return message += " retrying (attempt ##{@num_attempts + 1})" if @num_attempts < @all_attempts message += ' giving up.' message end end module queuelock def loner_enqueue_failed(*args) rails.logger.info "[resque][#{self}] enqueued: #{args.inspect}..." end def lock_failed(*) raise queueerror::lockfailed end end
so specific failure want test retries comes hook implemented.
def lock_failed(*) raise queueerror::lockfailed end
we need trigger this. here gets used in plugin. since you're using lock timeout looks want stub .acquire_lock_algorithm!
. dangerous since method part of plugin's internal api. keep in mind when upgrade plugin.
it 'retries it' stub_request(:any, /.*api.bigcartel.*/).to_return(body: '{}', status: 200) allow(queuehook).to receive(:acquire_lock_algorithm!).and_return(false, true) @order_shipped_json['order']['originator_id'] = @provider_order post "/hook/shops/#{@shop.id}", @order_shipped_json.to_json, format: :json resquespec.perform_all(queue_name) end
this spec should failing failure/error: raise queueerror::lockfailed
. since that's expected can set expectation.
it 'retries it' stub_request(:any, /.*api.bigcartel.*/).to_return(body: '{}', status: 200) allow(queuehook).to receive(:acquire_lock_algorithm!).and_return(false, true) @order_shipped_json['order']['originator_id'] = @provider_order post "/hook/shops/#{@shop.id}", @order_shipped_json.to_json, format: :json expect { resquespec.perform_all(queue_name) }.to raise_error(queueerror::lockfailed) end
the spec should passing unless have set resquespec.inline = true
. if have set false spec. easier follow.
if resque-retry working job's failure should have resulted in job being re-enqueued resquespec. can add expectation that. expect(resquespec.queues[queue_name]).to be_present
. not can run jobs again. mocked second return value of acquire_lock_algorithm!
true job should succeed time.
since want test counters lets add readers them
module queuelogger attr_reader :all_attempts, :num_attempts end
and finish spec...
it 'retries it' stub_request(:any, /.*api.bigcartel.*/).to_return(body: '{}', status: 200) allow(queuehook).to receive(:acquire_lock_algorithm!).and_return(false, true) @order_shipped_json['order']['originator_id'] = @provider_order post "/hook/shops/#{@shop.id}", @order_shipped_json.to_json, format: :json # failing expect { resquespec.perform_all(queue_name) }.to raise_error(queueerror::lockfailed) expect(resquespec.queues[queue_name]).to be_present # retrying resquespec.perform_all(queue_name) expect(queuehook.num_attempts).to eq(2) ... # whatever else want test. end
if want test logging stub them , set expectations regarding called with. should it, have simplified version running on own machine. if not might have details of test , resque configs.
Comments
Post a Comment