resque_stuck_queue 0.0.2 → 0.0.3
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 +8 -8
- data/README.md +14 -2
- data/THOUGHTS +2 -1
- data/lib/resque_stuck_queue.rb +23 -5
- data/lib/resque_stuck_queue/version.rb +1 -1
- data/test/test_logger.rb +30 -0
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
Y2RiMWFkM2ZmMGJmOWI1YzcwYzg5MWUyNjU3MTEzNWQwYmZiOWQ1YQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NjQ2ODNlOTNmMDMzZWU1MDU2NWE1NTc4YmQ1NzAwOGFlYzNlOTU5Nw==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
Mzc4ZTI4NjM2ZjlhY2ExNDM3NDhmMjU1NTA0ODE2Y2I3MzkwYzMxNDE3NTNk
|
10
|
+
YThjNjQ2ZDhkZjY5Nzk2YzAwMWZhZjgxOWNjMThiYzFhNGJlZWVjZjMzY2Rj
|
11
|
+
ZTZjZThlOGQyMzMwMzFlZmE1NTFmNDE4NzY4NmQ3ZTU1MDAwNDI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YzIzYWMxYWVkZGRiYjdhY2Y3ZDNlYzQ1NzcyYzQ2ZTcxZjM1NTE5NDgyMDU1
|
14
|
+
OTFkMmZjNWM5NjJiZmNkM2MyNDIyMWY5Y2Q4NTk4MDZkMTViMDY2ZDlhNDgz
|
15
|
+
NjQ0NGJiNzEwNDIyN2Y4NTJjZTYwODI0ZTRiYjgwYWM5OGI1MGU=
|
data/README.md
CHANGED
@@ -16,8 +16,6 @@ It will trigger a pre-defined proc (see below) if the last time the hearbeat job
|
|
16
16
|
|
17
17
|
## Usage
|
18
18
|
|
19
|
-
Add this to wherever you're setting up resque (config/initializers or wherever).
|
20
|
-
|
21
19
|
Configure it first:
|
22
20
|
|
23
21
|
<pre>
|
@@ -41,6 +39,10 @@ Resque::StuckQueue.config[:global_key] = "name-the-refresh-key-as-you-please"
|
|
41
39
|
|
42
40
|
# optional, if you want the resque-stuck-queue threads to explicitly raise, default is false
|
43
41
|
Resque::StuckQueue.config[:abort_on_exception] = true
|
42
|
+
|
43
|
+
# optional, pass a logger. Default a ruby logger will be instantiated. Needs to respond to that interface.
|
44
|
+
Resque::StuckQueue.config[:logger] = Logger.new($stdout)
|
45
|
+
|
44
46
|
</pre>
|
45
47
|
|
46
48
|
Then start it:
|
@@ -57,6 +59,16 @@ Resque::StuckQueue.stop # this will block until the threads end
|
|
57
59
|
Resque::StuckQueue.force_stop! # force kill those threads and let's move on
|
58
60
|
</pre>
|
59
61
|
|
62
|
+
## Deployment/Integration
|
63
|
+
|
64
|
+
* Include this in the app in a config initializer of some sort.
|
65
|
+
|
66
|
+
Note though, the resque-stuck threads will live alongside the app server process so you will need to explicitely handle `start` _and_ `stop`. If you're deployed in a forking-server environment and the whatever process has this does not get restarted the threads will keep on going indefinitely.
|
67
|
+
|
68
|
+
* Run this as a daemon somewhere alongside the app/in your setup.
|
69
|
+
|
70
|
+
<!-- TODO example -->
|
71
|
+
|
60
72
|
## Tests
|
61
73
|
|
62
74
|
Run the tests:
|
data/THOUGHTS
CHANGED
@@ -28,4 +28,5 @@ verify @config options, raise if no handler, etc.
|
|
28
28
|
- ensure it only runs from the server box and not the resque box??
|
29
29
|
(the deploy restarts the server but not resque workers)
|
30
30
|
|
31
|
-
|
31
|
+
add a 'resque_stuck_queue/tasks' bit? See tres eg
|
32
|
+
require 'resque/stuck_queue' instead?
|
data/lib/resque_stuck_queue.rb
CHANGED
@@ -7,13 +7,15 @@ Redis::Classy.db = Resque.redis
|
|
7
7
|
# TODO move this require into a configurable?
|
8
8
|
require 'resque'
|
9
9
|
|
10
|
+
require 'logger'
|
11
|
+
|
10
12
|
module Resque
|
11
13
|
module StuckQueue
|
12
14
|
|
13
15
|
GLOBAL_KEY = "resque-stuck-queue"
|
14
16
|
HEARTBEAT = 60 * 60 # check/refresh every hour
|
15
17
|
TRIGGER_TIMEOUT = 5 * 60 * 60 # warn/trigger 5 hours
|
16
|
-
HANDLER = proc { $
|
18
|
+
HANDLER = proc { $stdout.puts("Shit gone bad with them queues.") }
|
17
19
|
|
18
20
|
class << self
|
19
21
|
|
@@ -38,6 +40,10 @@ module Resque
|
|
38
40
|
@config ||= {}
|
39
41
|
end
|
40
42
|
|
43
|
+
def logger
|
44
|
+
@logger ||= (config[:logger] || Logger.new($stdout))
|
45
|
+
end
|
46
|
+
|
41
47
|
def start_in_background
|
42
48
|
Thread.new do
|
43
49
|
self.start
|
@@ -65,34 +71,44 @@ module Resque
|
|
65
71
|
# fo-eva.
|
66
72
|
@threads.map(&:join)
|
67
73
|
|
74
|
+
logger.info("threads stopped")
|
68
75
|
@stopped = true
|
69
76
|
end
|
70
77
|
|
71
|
-
# for tests
|
72
78
|
def stop
|
73
|
-
|
74
|
-
@running = false
|
75
|
-
|
79
|
+
reset!
|
76
80
|
# wait for clean thread shutdown
|
77
81
|
while @stopped == false
|
78
82
|
sleep 1
|
79
83
|
end
|
84
|
+
logger.info("Stopped")
|
80
85
|
end
|
81
86
|
|
82
87
|
def force_stop!
|
83
88
|
@threads.map(&:kill)
|
89
|
+
reset!
|
90
|
+
logger.info("Force stopped")
|
91
|
+
end
|
92
|
+
|
93
|
+
def reset!
|
94
|
+
# clean state so we can stop and start in the same process.
|
95
|
+
@config = config.dup #unfreeze
|
96
|
+
@logger = nil
|
97
|
+
@running = false
|
84
98
|
end
|
85
99
|
|
86
100
|
private
|
87
101
|
|
88
102
|
def enqueue_repeating_refresh_job
|
89
103
|
@threads << Thread.new do
|
104
|
+
logger.info("Starting heartbeat thread")
|
90
105
|
while @running
|
91
106
|
wait_for_it
|
92
107
|
# we want to go through resque jobs, because that's what we're trying to test here:
|
93
108
|
# ensure that jobs get executed and the time is updated!
|
94
109
|
#
|
95
110
|
# TODO REDIS 2.0 compat
|
111
|
+
logger.info("Sending refresh job")
|
96
112
|
Resque.enqueue(RefreshLatestTimestamp, global_key)
|
97
113
|
end
|
98
114
|
end
|
@@ -100,12 +116,14 @@ module Resque
|
|
100
116
|
|
101
117
|
def setup_checker_thread
|
102
118
|
@threads << Thread.new do
|
119
|
+
logger.info("Starting checker thread")
|
103
120
|
while @running
|
104
121
|
wait_for_it
|
105
122
|
mutex = Redis::Mutex.new('resque_stuck_queue_lock', block: 0)
|
106
123
|
if mutex.lock
|
107
124
|
begin
|
108
125
|
if Time.now.to_i - last_time_worked > max_wait_time
|
126
|
+
logger.info("Triggering handler at #{Time.now} (pid: #{Process.pid})")
|
109
127
|
trigger_handler
|
110
128
|
end
|
111
129
|
ensure
|
data/test/test_logger.rb
ADDED
@@ -0,0 +1,30 @@
|
|
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 setup
|
8
|
+
Resque::StuckQueue.config[:trigger_timeout] = 1
|
9
|
+
Resque::StuckQueue.config[:heartbeat] = 1
|
10
|
+
Resque::StuckQueue.config[:abort_on_exception] = true
|
11
|
+
end
|
12
|
+
|
13
|
+
def teardown
|
14
|
+
Resque::StuckQueue.reset!
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_has_logger
|
18
|
+
puts "#{__method__}"
|
19
|
+
begin
|
20
|
+
Resque::StuckQueue.config[:logger] = Logger.new($stdout)
|
21
|
+
start_and_stop_loops_after(2)
|
22
|
+
assert true, "should not have raised"
|
23
|
+
rescue
|
24
|
+
assert false, "should have succeeded with good logger"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque_stuck_queue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shai Rosenfeld
|
@@ -74,6 +74,7 @@ files:
|
|
74
74
|
- test/test_collision.rb
|
75
75
|
- test/test_helper.rb
|
76
76
|
- test/test_integration.rb
|
77
|
+
- test/test_logger.rb
|
77
78
|
- test/test_resque_stuck_queue.rb
|
78
79
|
homepage: https://github.com/shaiguitar/resque_stuck_queue/
|
79
80
|
licenses:
|
@@ -105,5 +106,6 @@ test_files:
|
|
105
106
|
- test/test_collision.rb
|
106
107
|
- test/test_helper.rb
|
107
108
|
- test/test_integration.rb
|
109
|
+
- test/test_logger.rb
|
108
110
|
- test/test_resque_stuck_queue.rb
|
109
111
|
has_rdoc:
|