resque_stuck_queue_revised 0.5.1
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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +19 -0
- data/LICENSE.txt +22 -0
- data/README.md +199 -0
- data/Rakefile +26 -0
- data/THOUGHTS +9 -0
- data/lib/resque/stuck_queue.rb +1 -0
- data/lib/resque_stuck_queue.rb +320 -0
- data/lib/resque_stuck_queue/config.rb +81 -0
- data/lib/resque_stuck_queue/heartbeat_job.rb +19 -0
- data/lib/resque_stuck_queue/version.rb +5 -0
- data/resque_stuck_queue.gemspec +27 -0
- data/test/resque/set_redis_key.rb +9 -0
- data/test/test_collision.rb +47 -0
- data/test/test_config.rb +67 -0
- data/test/test_helper.rb +57 -0
- data/test/test_integration.rb +172 -0
- data/test/test_lagtime.rb +34 -0
- data/test/test_named_queues.rb +96 -0
- data/test/test_resque_stuck_queue.rb +58 -0
- data/test/test_set_custom_refresh_job.rb +41 -0
- data/test/test_ver_2.rb +45 -0
- metadata +132 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'minitest'
|
2
|
+
require "minitest/autorun"
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
$:.unshift(".")
|
6
|
+
require 'resque_stuck_queue'
|
7
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "resque", "set_redis_key")
|
8
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
9
|
+
|
10
|
+
class TestLagTime < Minitest::Test
|
11
|
+
|
12
|
+
include TestHelper
|
13
|
+
|
14
|
+
def setup
|
15
|
+
Resque::StuckQueue.config[:redis] = Redis.new
|
16
|
+
Resque::StuckQueue.redis.flushall
|
17
|
+
Resque::StuckQueue.config[:abort_on_exception] = true
|
18
|
+
Resque::StuckQueue.config[:watcher_interval] = 1
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_triggers_handler_with_lagtime
|
22
|
+
Resque::StuckQueue.config[:trigger_timeout] = 2 # won't allow waiting too much and will complain (eg trigger) sooner than later
|
23
|
+
Resque::StuckQueue.config[:heartbeat_interval] = 1
|
24
|
+
@lagtime = 0
|
25
|
+
Resque::StuckQueue.config[:triggered_handler] = proc { |queue_name, lagtime| @lagtime = lagtime }
|
26
|
+
start_and_stop_loops_after(5)
|
27
|
+
|
28
|
+
# check handler did get called
|
29
|
+
assert @lagtime > 0, "lagtime shoudl be set"
|
30
|
+
assert @lagtime < 5, "lagtime shoudl be set"
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
2
|
+
|
3
|
+
class TestNamedQueues < Minitest::Test
|
4
|
+
|
5
|
+
include TestHelper
|
6
|
+
|
7
|
+
def setup
|
8
|
+
Resque::StuckQueue.config[:trigger_timeout] = 1
|
9
|
+
Resque::StuckQueue.config[:heartbeat_interval] = 1
|
10
|
+
Resque::StuckQueue.config[:abort_on_exception] = true
|
11
|
+
Resque::StuckQueue.config[:redis] = Redis.new
|
12
|
+
Resque::StuckQueue.config[:watcher_interval] = 1
|
13
|
+
Resque::StuckQueue.redis.flushall
|
14
|
+
end
|
15
|
+
|
16
|
+
def teardown
|
17
|
+
hax_kill_resque
|
18
|
+
Resque::StuckQueue.force_stop!
|
19
|
+
Process.waitpid(@resque_pid) if @resque_pid
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_no_custom_queues_defaults_to_app
|
23
|
+
puts "#{__method__}"
|
24
|
+
Resque::StuckQueue.config[:queues] = nil
|
25
|
+
start_and_stop_loops_after(2)
|
26
|
+
assert Resque::StuckQueue.heartbeat_keys.include?("app:resque-stuck-queue"), 'has global keys'
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_has_custom_queues
|
30
|
+
puts "#{__method__}"
|
31
|
+
Resque::StuckQueue.config[:queues] = [:foo,:bar]
|
32
|
+
assert Resque::StuckQueue.heartbeat_keys.include?("foo:resque-stuck-queue"), 'has global keys'
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_resque_enqueues_a_job_with_resqueue_running_but_on_that_queue_does_trigger
|
36
|
+
puts "#{__method__}"
|
37
|
+
Resque::StuckQueue.config[:trigger_timeout] = 2 # won't allow waiting too much and will complain (eg trigger) sooner than later
|
38
|
+
Resque::StuckQueue.config[:heartbeat_interval] = 1
|
39
|
+
Resque::StuckQueue.config[:queues] = [:custom_queue_name]
|
40
|
+
@triggered = false
|
41
|
+
Resque::StuckQueue.config[:triggered_handler] = proc { |queue_name| @triggered = queue_name }
|
42
|
+
Resque::StuckQueue.start_in_background
|
43
|
+
|
44
|
+
# job gets enqueued successfully
|
45
|
+
@resque_pid = run_resque("no-such-jobs-for-this-queue")
|
46
|
+
sleep 2 # allow timeout to trigger
|
47
|
+
|
48
|
+
# check handler did get called
|
49
|
+
assert_equal @triggered, :custom_queue_name
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_resque_enqueues_a_job_correct_queue_does_not_trigger
|
53
|
+
puts "#{__method__}"
|
54
|
+
Resque::StuckQueue.config[:trigger_timeout] = 2 # won't allow waiting too much and will complain (eg trigger) sooner than later
|
55
|
+
Resque::StuckQueue.config[:heartbeat_interval] = 1
|
56
|
+
Resque::StuckQueue.config[:queues] = [:custom_queue_name, :diff_one]
|
57
|
+
assert Resque::StuckQueue.heartbeat_keys.include?("custom_queue_name:resque-stuck-queue"), 'has global keys'
|
58
|
+
@triggered = false
|
59
|
+
Resque::StuckQueue.config[:triggered_handler] = proc { @triggered = true }
|
60
|
+
@resque_pid = run_resque("custom_queue_name")
|
61
|
+
Resque::StuckQueue.start_in_background
|
62
|
+
sleep 2 # allow timeout to trigger
|
63
|
+
|
64
|
+
# check handler did not get called
|
65
|
+
assert_equal @triggered, false
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_triggers_once_and_then_recovers
|
69
|
+
# FIXME test refactoring wrong place for this test.
|
70
|
+
puts "#{__method__}"
|
71
|
+
|
72
|
+
Resque::StuckQueue.config[:trigger_timeout] = 2
|
73
|
+
Resque::StuckQueue.config[:heartbeat_interval] = 1
|
74
|
+
Resque::StuckQueue.config[:queues] = [:app]
|
75
|
+
|
76
|
+
@triggered = 0
|
77
|
+
@recovered = 0
|
78
|
+
Resque::StuckQueue.config[:triggered_handler] = proc { @triggered += 1 }
|
79
|
+
Resque::StuckQueue.config[:recovered_handler] = proc { @recovered += 1 }
|
80
|
+
|
81
|
+
Thread.new {
|
82
|
+
# mock a job going through after we trigger :recovered so we'll w/o doing a run_resque
|
83
|
+
Thread.current.abort_on_exception = true
|
84
|
+
sleep 3
|
85
|
+
Resque::StuckQueue.redis.set(Resque::StuckQueue.heartbeat_key_for(:app), Time.now.to_i)
|
86
|
+
}
|
87
|
+
start_and_stop_loops_after(4)
|
88
|
+
|
89
|
+
# check handler did get called ONCE
|
90
|
+
assert_equal @recovered, 1
|
91
|
+
assert_equal @triggered, 1
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
2
|
+
|
3
|
+
class TestResqueStuckQueue < Minitest::Test
|
4
|
+
|
5
|
+
include TestHelper
|
6
|
+
|
7
|
+
def teardown
|
8
|
+
puts "#{__method__}"
|
9
|
+
Resque::StuckQueue.unstub(:read_from_redis)
|
10
|
+
end
|
11
|
+
|
12
|
+
def setup
|
13
|
+
puts "#{__method__}"
|
14
|
+
# clean previous test runs
|
15
|
+
Resque::StuckQueue.config[:redis] = Redis.new
|
16
|
+
Resque::StuckQueue.config[:watcher_interval] = 1
|
17
|
+
Resque::StuckQueue.redis.flushall
|
18
|
+
Resque::StuckQueue.config[:heartbeat_interval] = 1 # seconds
|
19
|
+
Resque::StuckQueue.config[:abort_on_exception] = true
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_configure_heartbeat_key
|
23
|
+
puts "#{__method__}"
|
24
|
+
assert_nil Resque::StuckQueue.redis.get("it-is-configurable"), "global key should not be set"
|
25
|
+
Resque::StuckQueue.config[:heartbeat_key] = "it-is-configurable"
|
26
|
+
start_and_stop_loops_after(3)
|
27
|
+
refute_nil Resque::StuckQueue.redis.get("app:it-is-configurable"), "global key should be set"
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_it_does_not_trigger_handler_if_under_max_time
|
31
|
+
puts "#{__method__}"
|
32
|
+
Resque::StuckQueue.config[:trigger_timeout] = 5
|
33
|
+
Resque::StuckQueue.stubs(:read_from_redis).returns(Time.now.to_i)
|
34
|
+
|
35
|
+
@triggered = false
|
36
|
+
Resque::StuckQueue.config[:triggered_handler] = proc { @triggered = true }
|
37
|
+
start_and_stop_loops_after(3)
|
38
|
+
assert_equal false, @triggered # "handler should not be called"
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_stops_if_handler_raises
|
42
|
+
puts "#{__method__}"
|
43
|
+
Resque::StuckQueue.config[:trigger_timeout] = 1 # wait a short time, will trigger
|
44
|
+
Resque::StuckQueue.config[:abort_on_exception] = true # bubble up the raise
|
45
|
+
last_time_too_old = Time.now.to_i - Resque::StuckQueue::TRIGGER_TIMEOUT
|
46
|
+
Resque::StuckQueue.config[:triggered_handler] = proc { raise "handler had bad sad!" }
|
47
|
+
begin
|
48
|
+
start_and_stop_loops_after(4)
|
49
|
+
sleep 4
|
50
|
+
assert false, "should raise"
|
51
|
+
rescue => e
|
52
|
+
puts e.inspect
|
53
|
+
assert true, "should raise handler bad sad #{e.inspect}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
2
|
+
|
3
|
+
class TestYourOwnRefreshJob < Minitest::Test
|
4
|
+
|
5
|
+
include TestHelper
|
6
|
+
|
7
|
+
def setup
|
8
|
+
Resque::StuckQueue.reset!
|
9
|
+
Resque::StuckQueue.config[:trigger_timeout] = 1
|
10
|
+
Resque::StuckQueue.config[:heartbeat_interval] = 1
|
11
|
+
Resque::StuckQueue.config[:watcher_interval] = 1
|
12
|
+
Resque::StuckQueue.config[:abort_on_exception] = true
|
13
|
+
Resque::StuckQueue.config[:heartbeat_job] = nil
|
14
|
+
Resque::StuckQueue.config[:redis] = Redis.new
|
15
|
+
Resque::StuckQueue.redis.flushall
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_will_trigger_with_unrefreshing_custom_heartbeat_job
|
19
|
+
# it will trigger because the key will be unrefreshed, hence 'old' and will always trigger.
|
20
|
+
puts "#{__method__}"
|
21
|
+
Resque::StuckQueue.config[:heartbeat_job] = proc { nil } # does not refresh global key
|
22
|
+
@triggered = false
|
23
|
+
Resque::StuckQueue.config[:triggered_handler] = proc { @triggered = true }
|
24
|
+
start_and_stop_loops_after(3)
|
25
|
+
assert @triggered, "will trigger because global key will be old"
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_will_fail_with_bad_custom_heartbeat_job
|
29
|
+
puts "#{__method__}"
|
30
|
+
begin
|
31
|
+
Resque::StuckQueue.config[:heartbeat_job] = proc { raise 'bad proc doc' } # does not refresh global key
|
32
|
+
@triggered = false
|
33
|
+
Resque::StuckQueue.config[:triggered_handler] = proc { @triggered = true }
|
34
|
+
start_and_stop_loops_after(3)
|
35
|
+
assert false, "should not succeed with bad refresh_job"
|
36
|
+
rescue
|
37
|
+
assert true, "will fail with bad refresh_job"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/test/test_ver_2.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# run with
|
2
|
+
# $ RESQUE_2=1 bi; RESQUE_2=1 be ruby -I. -Ilib/ test/test_resque_2.rb
|
3
|
+
if !ENV['RESQUE_2'].nil?
|
4
|
+
|
5
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
6
|
+
|
7
|
+
class TestResque2 < Minitest::Test
|
8
|
+
|
9
|
+
include TestHelper
|
10
|
+
|
11
|
+
def setup
|
12
|
+
assert (Resque::VERSION.match /^2\./), "must run in 2.0"
|
13
|
+
Resque.redis = Redis.new
|
14
|
+
Resque::StuckQueue.config[:redis] = Redis.new
|
15
|
+
Redis.new.flushall
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_works_with_2_point_oh_do_not_trigger_because_key_is_updated
|
19
|
+
|
20
|
+
Resque::StuckQueue.config[:redis] = Redis.new
|
21
|
+
|
22
|
+
Resque::StuckQueue.config[:watcher_interval] = 1
|
23
|
+
Resque::StuckQueue.config[:heartbeat_interval] = 1
|
24
|
+
Resque::StuckQueue.config[:abort_on_exception] = true
|
25
|
+
Resque::StuckQueue.config[:trigger_timeout] = 5
|
26
|
+
Resque::StuckQueue.config[:logger] = Logger.new($stdout)
|
27
|
+
Resque::StuckQueue.config[:triggered_handler] = proc { Redis.new.incr("test-incr-key") }
|
28
|
+
Resque::StuckQueue.config[:redis] = Redis.new
|
29
|
+
Resque::StuckQueue.config[:queues] = [:app]
|
30
|
+
|
31
|
+
#binding.pry
|
32
|
+
Resque::StuckQueue.start_in_background
|
33
|
+
|
34
|
+
@r2_pid = fork { Resque::StuckQueue.config[:redis] = Redis.new ; Resque::Worker.new("*", :graceful_term => true).work ; Process.waitall }
|
35
|
+
sleep 10
|
36
|
+
|
37
|
+
# triggers once
|
38
|
+
assert_equal Redis.new.get("test-incr-key").to_i, 1
|
39
|
+
hax_kill_resque
|
40
|
+
Resque::StuckQueue.force_stop!
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: resque_stuck_queue_revised
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dave Kerr
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: redis-mutex
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: redis-namespace
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: where the wild things are. err, when resque gets stuck
|
70
|
+
email:
|
71
|
+
- davek09@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- Gemfile
|
78
|
+
- LICENSE.txt
|
79
|
+
- README.md
|
80
|
+
- Rakefile
|
81
|
+
- THOUGHTS
|
82
|
+
- lib/resque/stuck_queue.rb
|
83
|
+
- lib/resque_stuck_queue.rb
|
84
|
+
- lib/resque_stuck_queue/config.rb
|
85
|
+
- lib/resque_stuck_queue/heartbeat_job.rb
|
86
|
+
- lib/resque_stuck_queue/version.rb
|
87
|
+
- resque_stuck_queue.gemspec
|
88
|
+
- test/resque/set_redis_key.rb
|
89
|
+
- test/test_collision.rb
|
90
|
+
- test/test_config.rb
|
91
|
+
- test/test_helper.rb
|
92
|
+
- test/test_integration.rb
|
93
|
+
- test/test_lagtime.rb
|
94
|
+
- test/test_named_queues.rb
|
95
|
+
- test/test_resque_stuck_queue.rb
|
96
|
+
- test/test_set_custom_refresh_job.rb
|
97
|
+
- test/test_ver_2.rb
|
98
|
+
homepage: ''
|
99
|
+
licenses:
|
100
|
+
- MIT
|
101
|
+
metadata: {}
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options: []
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - '>='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
requirements: []
|
117
|
+
rubyforge_project:
|
118
|
+
rubygems_version: 2.2.2
|
119
|
+
signing_key:
|
120
|
+
specification_version: 4
|
121
|
+
summary: fire a handler when your queues are wonky
|
122
|
+
test_files:
|
123
|
+
- test/resque/set_redis_key.rb
|
124
|
+
- test/test_collision.rb
|
125
|
+
- test/test_config.rb
|
126
|
+
- test/test_helper.rb
|
127
|
+
- test/test_integration.rb
|
128
|
+
- test/test_lagtime.rb
|
129
|
+
- test/test_named_queues.rb
|
130
|
+
- test/test_resque_stuck_queue.rb
|
131
|
+
- test/test_set_custom_refresh_job.rb
|
132
|
+
- test/test_ver_2.rb
|