From be5d6edeb445a26dc50c226f2c30dd49a344e78f Mon Sep 17 00:00:00 2001 From: Konstantinos Kostis Date: Thu, 1 Aug 2019 20:57:00 +0300 Subject: [PATCH 1/7] Introduce BlacklistExceptionsRegistrar module This commit introduces a new module for accessing a class variable named `blacklist`. This class variable represents exceptions that will not be pushed to the failed queue when a job fails with an exception that is included in the blacklist. Every class that includes this module can access/manipulate its `blacklist` class variable. Also it adds a method called `blacklisted_exception_raised?` which checks if the raised exception belongs to the backend's blacklisted exceptions. --- .../failure/blacklist_exceptions_registrar.rb | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 lib/resque/failure/blacklist_exceptions_registrar.rb diff --git a/lib/resque/failure/blacklist_exceptions_registrar.rb b/lib/resque/failure/blacklist_exceptions_registrar.rb new file mode 100644 index 000000000..81ba255fe --- /dev/null +++ b/lib/resque/failure/blacklist_exceptions_registrar.rb @@ -0,0 +1,50 @@ +module Resque + module Failure + # A module to access blacklisted exceptions + # on a class level + module BlacklistExceptionsRegistrar + def self.included(base) + base.extend ClassMethods + end + + # Class methods for accessing + # blacklisted exceptions + module ClassMethods + # Set a list of blacklisted exceptions + # + # The method sets a list of exceptions which will + # not be pushed to the failed queue when a job fails and it's + # exception is included to the blacklisted ones. + # + # @param [Array] exceptions the list of exceptions to blacklist + # @raise [StandardError] if the exceptions argument is not an array + # @return [void] + def set_blacklisted_exceptions(exceptions) + unless exceptions.is_a?(Array) + raise StandardError.new("The exceptions argument must be an array") + end + + @blacklist = exceptions + end + + # Fetch the blacklisted exceptions of a failure backend class + # + # @return [Array] + def get_blacklisted_exceptions + return @blacklist if defined?(@blacklist) + + [] + end + end + + # Check if the raised exception belongs + # to the backend's blacklisted exceptions. + # + # @return [true, false] true if raised exception is blacklisted, + # false otherwise + def blacklisted_exception_raised? + self.class&.get_blacklisted_exceptions&.include?(@exception.class.to_s) + end + end + end +end From 35ca21294e629ff747de85453ae475c1f674b38c Mon Sep 17 00:00:00 2001 From: Konstantinos Kostis Date: Thu, 1 Aug 2019 21:02:32 +0300 Subject: [PATCH 2/7] Failure::Base: Include the BlacklistExceptionsRegistrar module This commit allows Resque::Failure::Base to include the module BlacklistExceptionsRegistrar and by extension allowing every descendant of base class to manipulate its `blacklist` class variable. --- lib/resque/failure/base.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/resque/failure/base.rb b/lib/resque/failure/base.rb index 832020a39..748520151 100644 --- a/lib/resque/failure/base.rb +++ b/lib/resque/failure/base.rb @@ -1,3 +1,5 @@ +require 'resque/failure/blacklist_exceptions_registrar' + module Resque module Failure # All Failure classes are expected to subclass Base. @@ -5,6 +7,8 @@ module Failure # When a job fails, a new instance of your Failure backend is created # and #save is called. class Base + include BlacklistExceptionsRegistrar + # The exception object raised by the failed job attr_accessor :exception From 1fb9dfc93d96744c2505aa80bbf27b48ad8ed28f Mon Sep 17 00:00:00 2001 From: Konstantinos Kostis Date: Thu, 1 Aug 2019 21:05:18 +0300 Subject: [PATCH 3/7] Failure::Redis: Use blacklisted exceptions on save This commit uses the `blacklisted_exception_raised?`, provided by the BlacklistExceptionsRegistrar module, to determine if the raised exception of the failed job is a blacklisted exception and by extension if the job should be pushed to the failed queue or not. --- lib/resque/failure/redis.rb | 2 + test/resque_failure_redis_test.rb | 80 +++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/lib/resque/failure/redis.rb b/lib/resque/failure/redis.rb index c63122cf9..4c35efd6e 100644 --- a/lib/resque/failure/redis.rb +++ b/lib/resque/failure/redis.rb @@ -16,6 +16,8 @@ def self.data_store end def save + return if blacklisted_exception_raised? + data = { :failed_at => UTF8Util.clean(Time.now.strftime("%Y/%m/%d %H:%M:%S %Z")), :payload => payload, diff --git a/test/resque_failure_redis_test.rb b/test/resque_failure_redis_test.rb index e14754267..3c338bb8a 100644 --- a/test/resque_failure_redis_test.rb +++ b/test/resque_failure_redis_test.rb @@ -99,3 +99,83 @@ end end + +class CustomException < StandardError; end + +describe "blacklisted exceptions" do + + let(:exception) { CustomException.new("Custom error") } + let(:queue) { "test" } + let(:worker) { Resque::Worker.new([queue]) } + let(:payload) { { "class" => Object, "args" => 3 } } + let(:blacklisted_exceptions) { ["CustomException"] } + let(:redis_backend) do + Resque::Failure::Redis.new(exception, worker, queue, payload) + end + + describe "set blacklisted exceptions to empty array" do + before do + Resque::Failure::Redis.clear + Resque::Failure::Redis.set_blacklisted_exceptions([]) + end + + it "returns blacklisted exceptions" do + assert_equal [], redis_backend.class.get_blacklisted_exceptions + end + + it "pushes to failed queue" do + redis_backend.save + + assert_equal 1, Resque::Failure::Redis.count + end + end + + describe "exception during set_blacklisted_exceptions" do + it "raises exception due to wrong argument type" do + assert_raises StandardError do + Resque::Failure::Redis.set_blacklisted_exceptions("CustomException") + end + end + end + + describe "setting and using blacklisted exceptions" do + before do + Resque::Failure::Redis.clear + Resque::Failure::Redis.set_blacklisted_exceptions(blacklisted_exceptions) + end + + it "returns blacklisted exceptions" do + assert_equal blacklisted_exceptions, redis_backend.class.get_blacklisted_exceptions + end + + it "does not push to failed queue" do + redis_backend.save + + assert_equal 0, Resque::Failure::Redis.count + end + end + + describe "blacklisted_exception_raised?" do + describe "when raised exception is blacklisted" do + before do + Resque::Failure::Redis.clear + Resque::Failure::Redis.set_blacklisted_exceptions(blacklisted_exceptions) + end + + it "returns true" do + assert_equal true, redis_backend.blacklisted_exception_raised? + end + end + + describe "when raised exception is not blacklisted" do + before do + Resque::Failure::Redis.clear + Resque::Failure::Redis.set_blacklisted_exceptions(["AnotherException"]) + end + + it "returns false" do + assert_equal false, redis_backend.blacklisted_exception_raised? + end + end + end +end From 3366d76accd8cd04a4c00ad1d2065d72128efd8e Mon Sep 17 00:00:00 2001 From: Konstantinos Kostis Date: Thu, 1 Aug 2019 21:09:42 +0300 Subject: [PATCH 4/7] Failure::RedisMultiQueue: Use blacklisted exceptions on save This commit uses the `blacklisted_exception_raised?`, provided by the BlacklistExceptionsRegistrar module, to determine if the raised exception of the failed job is a blacklisted exception and by extension if the job should be pushed to the failed queue or not. --- lib/resque/failure/redis_multi_queue.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/resque/failure/redis_multi_queue.rb b/lib/resque/failure/redis_multi_queue.rb index 18c88b94d..261bc93c3 100644 --- a/lib/resque/failure/redis_multi_queue.rb +++ b/lib/resque/failure/redis_multi_queue.rb @@ -13,6 +13,8 @@ def self.data_store end def save + return if blacklisted_exception_raised? + data = { :failed_at => Time.now.strftime("%Y/%m/%d %H:%M:%S %Z"), :payload => payload, From ad338270d9f0f1663eea4fb6314ef32d361dfbbf Mon Sep 17 00:00:00 2001 From: Konstantinos Kostis Date: Thu, 1 Aug 2019 21:12:10 +0300 Subject: [PATCH 5/7] Failure::Multiple: Use blacklisted exceptions on save This commit uses the `blacklisted_exception_raised?`, provided by the BlacklistExceptionsRegistrar module, to determine if the save method of a respective backend should be called or not if a failed job with a given exception occurs. --- lib/resque/failure/multiple.rb | 2 +- test/resque_failure_multiple_test.rb | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/resque/failure/multiple.rb b/lib/resque/failure/multiple.rb index 2ad2bf4cc..4fc12bf17 100644 --- a/lib/resque/failure/multiple.rb +++ b/lib/resque/failure/multiple.rb @@ -25,7 +25,7 @@ def save exception = nil @backends.each do |b| begin - b.save + b.save unless b.blacklisted_exception_raised? rescue => e exception = e log("Failed saving to #{b.class.name}, error #{e.to_s}") diff --git a/test/resque_failure_multiple_test.rb b/test/resque_failure_multiple_test.rb index d6190ac48..676ba8ea2 100644 --- a/test/resque_failure_multiple_test.rb +++ b/test/resque_failure_multiple_test.rb @@ -16,6 +16,8 @@ def save end end +class CustomException < StandardError; end + describe "Resque::Failure::Multiple" do it 'requeue_all and does not raise an exception' do @@ -62,3 +64,22 @@ def save end end end + +describe "blacklisted_exceptions" do + it "sets blacklisted_exceptions on the multiple backend" do + blacklisted_exceptions = ["CustomException"] + Resque::Failure::Redis.set_blacklisted_exceptions(blacklisted_exceptions) + Resque::Failure::Multiple.classes = [Resque::Failure::Redis] + + exception = CustomException.new("Custom error") + worker = Resque::Worker.new(:test) + payload = { "class" => Object, "args" => 3 } + + multiple_backend = Resque::Failure::Multiple.new(exception, worker, 'test', payload) + backends = multiple_backend.instance_variable_get(:@backends) + backends.each do |b| + assert_equal blacklisted_exceptions, b.class.get_blacklisted_exceptions + end + end +end + From d3d7b80443dbe806a1ca5bf9db0cd5deed08ec7f Mon Sep 17 00:00:00 2001 From: Konstantinos Kostis Date: Thu, 1 Aug 2019 21:18:06 +0300 Subject: [PATCH 6/7] Travis: Modify ruby versions --- .travis.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 77b03812a..653c0de47 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,6 @@ language: ruby rvm: - - 1.9.3 - - 2.2 - 2.3.0 + - 2.3.3 + - 2.5.5 sudo: false -matrix: - include: - - rvm: 1.8.7 - gemfile: Gemfiles/Gemfile.1.8.7 From 4ff4dadeced65a7aa6b25b4cfafbbdb5689eee9b Mon Sep 17 00:00:00 2001 From: Konstantinos Kostis Date: Thu, 1 Aug 2019 21:19:03 +0300 Subject: [PATCH 7/7] Bump version to 1.27.4.skroutz.2 --- lib/resque/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/resque/version.rb b/lib/resque/version.rb index 65049a901..09743edbc 100644 --- a/lib/resque/version.rb +++ b/lib/resque/version.rb @@ -1,3 +1,3 @@ module Resque - Version = VERSION = '1.27.4.skroutz.1' + Version = VERSION = '1.27.4.skroutz.2' end