resque_stuck_queue 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YWNkZWJjMzVlMTZlNmI4ZDNiZjk5MTk2ZjFiOTVhZTIxYjA4ZDY1Ng==
4
+ Y2RiMWFkM2ZmMGJmOWI1YzcwYzg5MWUyNjU3MTEzNWQwYmZiOWQ1YQ==
5
5
  data.tar.gz: !binary |-
6
- NDlmNDlmZGI3OThiMDk2NjJiZGZhZDlmY2YxNzZhOGY0ZmU1YzMxNQ==
6
+ NjQ2ODNlOTNmMDMzZWU1MDU2NWE1NTc4YmQ1NzAwOGFlYzNlOTU5Nw==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- ODgyNjJhMjNiYjNhNWRjNjBhYzhiNGUxODNmZDhiNWJiNDViODQ1ZTBlNTdk
10
- MzU2ZjU3M2MyMWY0OGE5ZWIzYTBlMGI4OTEzZGFkY2RlNjkyNWU2MmI0NjYy
11
- NDQ3M2IyY2E3YTAwYzUyODExZDNkY2E2ZmI3ZDVjYzAwYWVlN2Q=
9
+ Mzc4ZTI4NjM2ZjlhY2ExNDM3NDhmMjU1NTA0ODE2Y2I3MzkwYzMxNDE3NTNk
10
+ YThjNjQ2ZDhkZjY5Nzk2YzAwMWZhZjgxOWNjMThiYzFhNGJlZWVjZjMzY2Rj
11
+ ZTZjZThlOGQyMzMwMzFlZmE1NTFmNDE4NzY4NmQ3ZTU1MDAwNDI=
12
12
  data.tar.gz: !binary |-
13
- NzM4ZjQyMDQzOTI2MDQyNTExMzQyNzEwNTAxM2M0NmRiYzM2YWJmMmQyYmFk
14
- MTMxZWM1YmY3Nzc2ODM0N2M3MTM3NjI2ZmYxNDFjNDc5ZmUyNmVmZmIxMGQ5
15
- MjkyNWNhOWZkNTNmNWVmM2ExNjg5ZGNkOGRmOTk0ZGU5NGQwYjA=
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?
@@ -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 { $stderr.puts("Shit gone bad with them queues.") }
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
- @config = config.dup #unfreeze
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
@@ -1,5 +1,5 @@
1
1
  module Resque
2
2
  module StuckQueue
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
@@ -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.2
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: