resque-insist 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in resque-insist.gemspec
4
+ gemspec
@@ -0,0 +1,42 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ resque-insist (0.1.0)
5
+ resque (~> 1.10.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.1.2)
11
+ json (1.4.6)
12
+ rack (1.2.1)
13
+ redis (2.1.1)
14
+ redis-namespace (0.8.0)
15
+ redis (< 3.0.0)
16
+ resque (1.10.0)
17
+ json (~> 1.4.6)
18
+ redis-namespace (~> 0.8.0)
19
+ sinatra (>= 0.9.2)
20
+ vegas (~> 0.1.2)
21
+ rspec (2.2.0)
22
+ rspec-core (~> 2.2)
23
+ rspec-expectations (~> 2.2)
24
+ rspec-mocks (~> 2.2)
25
+ rspec-core (2.2.1)
26
+ rspec-expectations (2.2.0)
27
+ diff-lcs (~> 1.1.2)
28
+ rspec-mocks (2.2.0)
29
+ sinatra (1.1.0)
30
+ rack (~> 1.1)
31
+ tilt (~> 1.1)
32
+ tilt (1.1)
33
+ vegas (0.1.8)
34
+ rack (>= 1.0.0)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ resque (~> 1.10.0)
41
+ resque-insist!
42
+ rspec (~> 2.2.0)
@@ -0,0 +1,48 @@
1
+ # Resque::Plugins::Insist
2
+ ## Give your Resque jobs a second chance
3
+
4
+ <http://github.com/jrom/resque-insist> by Jordi Romero
5
+
6
+ If you want to give your jobs a second chance (or more)
7
+ extend them with this plugin and let the job fail
8
+ some times before considering it failed.
9
+
10
+ By default a job will be run 3 times before marking it
11
+ as failed, but you can configure that with @insist = N
12
+ in your job.
13
+
14
+ ## Usage
15
+
16
+ require 'resque/plugins/insist'
17
+ class HardJob
18
+ extend Resque::Plugins::Insist
19
+ @queue = :hard_job
20
+ @insist = 5
21
+ def self.perform(something)
22
+ do_work
23
+ end
24
+ end
25
+
26
+ When your job fails for the first time, it will be queued
27
+ again, but will be locked for 8 seconds before the worker
28
+ performs it again. If it fails again, the wait time will be
29
+ 16 seconds, then 32, 64, ... until your job reaches the
30
+ maximum number of attempts or just succeeds (not raising an
31
+ exception).
32
+
33
+ ## Contributing
34
+
35
+ If you want to improve resque-insist
36
+
37
+ 1. Fork the repo
38
+ 2. Create a topic branch `git checkout -b my_feature`
39
+ 3. Push it! `git push origin my_feature`
40
+ 4. Open a pull request
41
+
42
+ Make sure you add specs for your changes and document them.
43
+ Any contribution will be appreciated, both fixing some typo or
44
+ adding the coolest feature ever.
45
+
46
+ ## Issues
47
+
48
+ <http://github.com/jrom/resque-insist/issues>
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,77 @@
1
+ module Resque # :nodoc:
2
+ module Plugins # :nodoc:
3
+ # If you want to give your jobs a second chance (or more)
4
+ # extend them with this plugin and let the job fail
5
+ # some times before considering it failed.
6
+ #
7
+ # By default a job will be run 3 times before marking it
8
+ # as failed, but you can configure that with @insist = N
9
+ # in your job.
10
+ #
11
+ # Example:
12
+ #
13
+ # require 'resque/plugins/insist'
14
+ # class HardJob
15
+ # extend Resque::Plugins::Insist
16
+ # @queue = :hard_job
17
+ # @insist = 5
18
+ # def self.perform(something)
19
+ # do_work
20
+ # end
21
+ # end
22
+ #
23
+ # When your job fails for the first time, it will be queued
24
+ # again, but will be locked for 8 seconds before the worker
25
+ # performs it again. If it fails again, the wait time will be
26
+ # 16 seconds, then 32, 64, ... until your job reaches the
27
+ # maximum number of attempts or just succeeds (not raising an
28
+ # exception).
29
+ module Insist
30
+ include Resque::Helpers
31
+ # Intercept the execution of a job to add the extra security
32
+ # layer.
33
+ def around_perform_insist(*args)
34
+ if redis.get "plugin:insist:wait:#{insist_key(args)}"
35
+ Resque.enqueue constantize(self.to_s), *args
36
+ else
37
+ begin
38
+ yield
39
+ redis.del "plugin:insist:attempts:#{insist_key(args)}"
40
+ rescue => e
41
+ attempts = redis.incr "plugin:insist:attempts:#{insist_key(args)}"
42
+ if attempts.to_i >= insist_times
43
+ redis.del "plugin:insist:wait:#{insist_key(args)}"
44
+ redis.del "plugin:insist:attempts:#{insist_key(args)}"
45
+ raise e
46
+ else
47
+ redis.set "plugin:insist:wait:#{insist_key(args)}", 1
48
+ redis.expire "plugin:insist:wait:#{insist_key(args)}", wait_time(attempts)
49
+ Resque.enqueue constantize(self.to_s), *args
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ # Number of times a job will be executed before considering
56
+ # it failed. By default it's 3. To specify it, set the ivar
57
+ # @insist to an integer. Any value under 1 will make the job
58
+ # perform just once as if the plugin was never there.
59
+ def insist_times
60
+ @insist || 3
61
+ end
62
+
63
+ # Calculates the amount of seconds a job is locked between
64
+ # the last failure and the next attempt.
65
+ def wait_time(attempts)
66
+ 2 ** (attempts.to_i + 2)
67
+ end
68
+
69
+ private
70
+ # Calculates a key to identify the job according to
71
+ # its arguments.
72
+ def insist_key(*args)
73
+ self.to_s + ':' + Digest::SHA1.hexdigest(args.join(','))
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,21 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "resque-insist"
5
+ s.version = "0.1.0"
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["Jordi Romero"]
8
+ s.email = ["jordi@jrom.net"]
9
+ s.homepage = "http://github.com/jrom/resque-insist"
10
+ s.summary = %q{Give your Resque jobs a second chance}
11
+ s.description = %q{If you want to give your jobs a second change (or more) extend them with this plugin and let the job fail some times before considering it failed.}
12
+
13
+ s.files = `git ls-files`.split("\n") - %w(.gitignore .rspec) - ['autotest/discover.rb']
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = ["lib"]
17
+
18
+ s.add_dependency "resque", "~> 1.10.0"
19
+ s.add_development_dependency "rspec", "~> 2.2.0"
20
+
21
+ end
@@ -0,0 +1,30 @@
1
+ daemonize yes
2
+ pidfile ./spec/redis.pid
3
+ port 6378
4
+
5
+ timeout 300
6
+ loglevel debug
7
+ logfile stdout
8
+ databases 16
9
+
10
+ save 900 1
11
+ save 300 10
12
+ save 60 10000
13
+ rdbcompression yes
14
+
15
+ dbfilename dump.rdb
16
+ dir ./spec/
17
+
18
+ appendonly no
19
+ appendfsync everysec
20
+
21
+ vm-enabled no
22
+ vm-swap-file /tmp/redis.swap
23
+ vm-max-memory 0
24
+ vm-page-size 32
25
+ vm-pages 134217728
26
+ vm-max-threads 4
27
+ glueoutputbuf yes
28
+ hash-max-zipmap-entries 64
29
+ hash-max-zipmap-value 512
30
+ activerehashing yes
@@ -0,0 +1,79 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ class Job
4
+ extend Resque::Plugins::Insist
5
+ @queue = :job
6
+ @insist = 2
7
+ def self.perform(success)
8
+ raise 'Not gonna work' unless success
9
+ end
10
+ end
11
+
12
+ describe Resque::Plugins::Insist do
13
+ describe "compliance of Resque Plugins guidelines" do
14
+ it "should be valid" do
15
+ lambda{ Resque::Plugin.lint(Resque::Plugins::Insist) }.should_not raise_error
16
+ end
17
+ end
18
+
19
+ describe "config" do
20
+ it "should take the insist_times value from the @insist ivar" do
21
+ Job.insist_times.should == 2
22
+ end
23
+
24
+ it "shoult default insist_times to 3" do
25
+ class JobWithoutCustomInsist
26
+ extend Resque::Plugins::Insist
27
+ @queue = :job
28
+ def self.perform; end
29
+ end
30
+ JobWithoutCustomInsist.insist_times.should == 3
31
+ end
32
+ end
33
+
34
+ describe "a succeeding Job" do
35
+ it "should be executed on the first attempt and not be enqueued again" do
36
+ Resque.enqueue Job, true
37
+ pending.should == 1
38
+ processed.should == 0
39
+ failed.should == 0
40
+ work_jobs
41
+ pending.should == 0
42
+ processed.should == 1
43
+ failed.should == 0
44
+ end
45
+ end
46
+
47
+ describe "a failing Job" do
48
+ it "should should quietly die and be enqueued back the first time it's executed" do
49
+ Resque.enqueue Job, false # enqueue a failing job
50
+ work_job # try to work it for the first time
51
+ pending.should == 1
52
+ failed.should == 0
53
+ time_before = Time.now
54
+ work_jobs # try to work it for the second and last time
55
+ elapsed_time = Time.now - time_before
56
+ elapsed_time.should > 7 # We wait aprox 8 seconds
57
+ elapsed_time.should < 9
58
+ pending.should == 0
59
+ failed.should == 1 # the job is marked as failed after 2 attempts
60
+ Resque::Failure.all['error'].should == 'Not gonna work' # we get the original error
61
+ end
62
+ end
63
+
64
+ # Defines pending, failed, processed, queues, environment, workers and servers
65
+ Resque.info.keys.each do |key|
66
+ define_method(key) { Resque.info[key] }
67
+ end
68
+
69
+ # Starts a worker to work off queue
70
+ def work_jobs(queue = :job)
71
+ Resque::Worker.new(queue).work(0)
72
+ end
73
+
74
+ # Performs the first job available from queue
75
+ def work_job(queue = :job)
76
+ worker = Resque::Worker.new(queue)
77
+ worker.perform(worker.reserve)
78
+ end
79
+ end
@@ -0,0 +1,25 @@
1
+ Bundler.require(:default, :development)
2
+ require 'lib/resque/plugins/insist'
3
+
4
+ RSpec.configure do |config|
5
+ config.before(:all) do
6
+ if !system('which redis-server')
7
+ puts "\ncan't find `redis-server` in your path"
8
+ abort
9
+ end
10
+ `redis-server #{File.dirname(File.expand_path(__FILE__))}/redis-test.conf` # run Redis with local config
11
+ puts "Starting test redis server: redis-server #{File.dirname(File.expand_path(__FILE__))}/redis-test.conf"
12
+ Resque.redis = 'localhost:6378' # port specified in redis-test.conf
13
+ end
14
+
15
+ config.before(:each) do
16
+ Resque.redis.flushall # Drop all keys between examples
17
+ end
18
+
19
+ config.after(:all) do
20
+ pid = `ps -e -o pid,command | grep [r]edis-test`.split(" ")[0]
21
+ puts "\nKilling test redis server PID #{pid}..."
22
+ `rm -f #{File.dirname(File.expand_path(__FILE__))}/dump.rdb` # file specified in redis-test.conf
23
+ Process.kill("KILL", pid.to_i)
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resque-insist
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Jordi Romero
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-19 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: resque
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 63
30
+ segments:
31
+ - 1
32
+ - 10
33
+ - 0
34
+ version: 1.10.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rspec
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 7
46
+ segments:
47
+ - 2
48
+ - 2
49
+ - 0
50
+ version: 2.2.0
51
+ type: :development
52
+ version_requirements: *id002
53
+ description: If you want to give your jobs a second change (or more) extend them with this plugin and let the job fail some times before considering it failed.
54
+ email:
55
+ - jordi@jrom.net
56
+ executables: []
57
+
58
+ extensions: []
59
+
60
+ extra_rdoc_files: []
61
+
62
+ files:
63
+ - Gemfile
64
+ - Gemfile.lock
65
+ - README.md
66
+ - Rakefile
67
+ - lib/resque/plugins/insist.rb
68
+ - resque-insist.gemspec
69
+ - spec/redis-test.conf
70
+ - spec/resque_insist_spec.rb
71
+ - spec/spec_helper.rb
72
+ has_rdoc: true
73
+ homepage: http://github.com/jrom/resque-insist
74
+ licenses: []
75
+
76
+ post_install_message:
77
+ rdoc_options: []
78
+
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ hash: 3
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ requirements: []
100
+
101
+ rubyforge_project:
102
+ rubygems_version: 1.3.7
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Give your Resque jobs a second chance
106
+ test_files:
107
+ - spec/redis-test.conf
108
+ - spec/resque_insist_spec.rb
109
+ - spec/spec_helper.rb