From e241ac1e12d14f119b30069c32137729206a85b0 Mon Sep 17 00:00:00 2001 From: Dmitriy Ivliev <3938172+moofkit@users.noreply.github.com> Date: Tue, 16 Jan 2024 21:07:07 +0200 Subject: [PATCH] adds more specs and enrich dsl --- lib/sidekiq/rescue/dsl.rb | 46 ++++++++++++----- spec/sidekiq/rescue/dsl_spec.rb | 88 +++++++++++++++++++++++++++++++++ spec/spec_helper.rb | 8 ++- spec/support/errors.rb | 6 +++ spec/support/jobs.rb | 67 +++++++++++++++++++++++++ 5 files changed, 201 insertions(+), 14 deletions(-) create mode 100644 spec/sidekiq/rescue/dsl_spec.rb create mode 100644 spec/support/errors.rb create mode 100644 spec/support/jobs.rb diff --git a/lib/sidekiq/rescue/dsl.rb b/lib/sidekiq/rescue/dsl.rb index 10b0358..07041f3 100644 --- a/lib/sidekiq/rescue/dsl.rb +++ b/lib/sidekiq/rescue/dsl.rb @@ -19,26 +19,46 @@ module ClassMethods # @param limit [Integer] The maximum number of retries. # @return [void] # @raise [ArgumentError] if error is not a StandardError + # @raise [ArgumentError] if error is not an array of StandardError + # @raise [ArgumentError] if delay is not an Integer or Float + # @raise [ArgumentError] if limit is not an Integer # @example # sidekiq_rescue NetworkError, delay: 60, limit: 10 - def sidekiq_rescue(error, **options) + def sidekiq_rescue(error, delay: nil, limit: nil) + validate_error_argument(error) + validate_delay_argument(delay) + validate_limit_argument(limit) + + self.sidekiq_rescue_options = { + error: error, + delay: delay || Sidekiq::Rescue::DEFAULT_DELAY, + limit: limit || Sidekiq::Rescue::DEFAULT_LIMIT + } + end + + private + + def validate_error_argument(error) error_arg_valid = if error.is_a?(Array) - error.all? { _1 < StandardError } + error.all? { |e| e < StandardError } else error < StandardError end - unless error_arg_valid - raise ArgumentError, - "error must be an ancestor of StandardError or an array of ancestors of StandardError" - end - raise ArgumentError, "delay must be integer" if options[:delay] && !options[:delay].is_a?(Integer) - raise ArgumentError, "limit must be integer" if options[:limit] && !options[:limit].is_a?(Integer) + return if error_arg_valid - self.sidekiq_rescue_options = { - error: error, - delay: Sidekiq::Rescue::DEFAULT_DELAY, - limit: Sidekiq::Rescue::DEFAULT_LIMIT - }.merge(options) + raise ArgumentError, + "error must be an ancestor of StandardError or an array of ancestors of StandardError" + end + + def validate_delay_argument(delay) + return unless delay && !delay.is_a?(Integer) && !delay.is_a?(Float) + + raise ArgumentError, + "delay must be integer or float" + end + + def validate_limit_argument(limit) + raise ArgumentError, "limit must be integer" if limit && !limit.is_a?(Integer) end end end diff --git a/spec/sidekiq/rescue/dsl_spec.rb b/spec/sidekiq/rescue/dsl_spec.rb new file mode 100644 index 0000000..a34772b --- /dev/null +++ b/spec/sidekiq/rescue/dsl_spec.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +RSpec.describe Sidekiq::Rescue::DSL do + let(:job_class) do + Class.new do + include Sidekiq::Job + include Sidekiq::Rescue::DSL + end + end + + def define_dsl(&block) + job_class.instance_eval(&block) + end + + describe "#sidekiq_rescue" do + it "sets error and default options" do + define_dsl { sidekiq_rescue TestError } + + expect(job_class.sidekiq_rescue_options).to eq(error: TestError, delay: 60, limit: 10) + end + + it "sets the error classes" do + define_dsl { sidekiq_rescue [TestError, ParentError, ChildError] } + + expect(job_class.sidekiq_rescue_options[:error]).to eq([TestError, ParentError, ChildError]) + end + + it "sets the delay" do + define_dsl { sidekiq_rescue TestError, delay: 10 } + + expect(job_class.sidekiq_rescue_options[:delay]).to eq(10) + end + + it "sets the limit" do + define_dsl { sidekiq_rescue TestError, limit: 5 } + + expect(job_class.sidekiq_rescue_options[:limit]).to eq(5) + end + + it "raises ArgumentError if there are no arguments" do + expect do + define_dsl do + sidekiq_rescue + end + end.to raise_error(ArgumentError, "wrong number of arguments (given 0, expected 1)") + end + + it "raises ArgumentError if there are unknown options" do + expect do + define_dsl do + sidekiq_rescue TestError, unknown: "option" + end + end.to raise_error(ArgumentError, "unknown keyword: :unknown") + end + + it "raises ArgumentError if error is not a StandardError child" do + exception_class = Class.new(Exception) # rubocop:disable Lint/InheritException + + expect { define_dsl { sidekiq_rescue exception_class } }.to raise_error( + ArgumentError, + "error must be an ancestor of StandardError or an array of ancestors of StandardError" + ) + end + + it "raises ArgumentError if error is not an array of StandardError children" do + klass = Class.new + + expect { define_dsl { sidekiq_rescue [TestError, klass] } }.to raise_error( + ArgumentError, + "error must be an ancestor of StandardError or an array of ancestors of StandardError" + ) + end + + it "raises ArgumentError if delay is not an integer or float" do + expect { define_dsl { sidekiq_rescue TestError, delay: "60" } }.to raise_error( + ArgumentError, + "delay must be integer or float" + ) + end + + it "raises ArgumentError if limit is not an integer" do + expect { define_dsl { sidekiq_rescue TestError, limit: "10" } }.to raise_error( + ArgumentError, + "limit must be integer" + ) + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3a3c4b3..75be57e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -14,5 +14,11 @@ c.syntax = :expect end - Sidekiq.default_configuration.logger = nil unless ENV["LOG"] + if ENV["LOG"].nil? + if defined?(Sidekiq::MAJOR) && Sidekiq::MAJOR >= 7 + Sidekiq.default_configuration.logger = nil + else + Sidekiq.logger = nil + end + end end diff --git a/spec/support/errors.rb b/spec/support/errors.rb new file mode 100644 index 0000000..544e375 --- /dev/null +++ b/spec/support/errors.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +TestError = Class.new(StandardError) +ParentError = Class.new(TestError) +ChildError = Class.new(ParentError) +UnexpectedError = Class.new(StandardError) diff --git a/spec/support/jobs.rb b/spec/support/jobs.rb new file mode 100644 index 0000000..462883a --- /dev/null +++ b/spec/support/jobs.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +class WithTestErrorJob + include Sidekiq::Job + include Sidekiq::Rescue::DSL + + sidekiq_rescue TestError + + def perform(*) + raise TestError + end +end + +class WithTestErrorWithoutResqueJob + include Sidekiq::Job + include Sidekiq::Rescue::DSL + + sidekiq_rescue TestError + + def perform(*) + raise TestError + end +end + +class WithParentErrorJob + include Sidekiq::Job + include Sidekiq::Rescue::DSL + + sidekiq_rescue ParentError + + def perform(*) + raise ParentError + end +end + +class WithChildErrorJob + include Sidekiq::Job + include Sidekiq::Rescue::DSL + + sidekiq_rescue ChildError + + def perform(*) + raise ChildError + end +end + +class WithAllErrorJob + include Sidekiq::Job + include Sidekiq::Rescue::DSL + + sidekiq_rescue [TestError, ParentError, ChildError] + + def perform(*) + raise [TestError, ParentError, ChildError].sample + end +end + +class WithUnexpectedErrorJob + include Sidekiq::Job + include Sidekiq::Rescue::DSL + + sidekiq_rescue TestError + + def perform(*) + raise UnexpectedError + end +end