resque_worker_heartbeat 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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MjM5MGNjODExZjhhNzJjOTAxNjU0ZTJmZjE0MGM3NmViYmNkM2I4Ng==
5
+ data.tar.gz: !binary |-
6
+ ZTk3NDY4ZjgyNjcwOGM3YzZjZmJhM2YxYjc1ZWE2OWVlODg4OTNmZQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MDk5NDdhMjkyMzljZGY1ZjI5MWYxZWQ3NmI5YzYxM2ZjMWUxNjlmOWEyOTAz
10
+ ZTQ1MmQyNTE0NWEwMDUzYzEwZDVhN2Q3OTJlZmZjYjliMDE2YTA1YzdiOGI2
11
+ NDM3ZGJiMDcwOTE0Nzg1NDk4ODI2MDZhNzM2N2U3NTkzZTBmZWY=
12
+ data.tar.gz: !binary |-
13
+ MmQ1OGY1ZTQzZTJmNTE0MDllNGJkN2I3ZjA3YTY1YzdjNDU4NDAzYzg0NjA0
14
+ MzVmOWNlY2JjYjBjODI5ODI1ZmRjYTZmOWE1NGQ0NmQyODAzNjk0ZjhkMGRj
15
+ NGM0ODYyNjNkMDI4YTBlMTY0ODhmZjdiODNhMDlkYjdkYmE0NWM=
@@ -0,0 +1,127 @@
1
+ require 'resque'
2
+
3
+ module Resque
4
+ class Worker
5
+ alias_method(:startup_without_heartbeat, :startup)
6
+ def startup_with_heartbeat
7
+ startup_without_heartbeat
8
+ heart.run
9
+ end
10
+ alias_method(:startup, :startup_with_heartbeat)
11
+
12
+ alias_method(:unregister_worker_without_heartbeat, :unregister_worker)
13
+ def unregister_worker_with_heartbeat(*args)
14
+ heart.stop
15
+ unregister_worker_without_heartbeat(*args)
16
+ end
17
+ alias_method(:unregister_worker, :unregister_worker_with_heartbeat)
18
+
19
+ def heart
20
+ @heart ||= Heart.new(self)
21
+ end
22
+
23
+ def remote_hostname
24
+ id.split(':').first
25
+ end
26
+
27
+ def dead?
28
+ return heart.dead?
29
+ end
30
+
31
+ def prune_if_dead
32
+ return nil unless dead?
33
+
34
+ Resque.logger.info "Pruning worker '#{remote_hostname}' from resque"
35
+ unregister_worker
36
+ end
37
+
38
+ class Heart
39
+ attr_reader :worker
40
+
41
+ def self.heartbeat_interval_seconds
42
+ ENV['HEARTBEAT_INTERVAL_SECONDS'] || 2
43
+ end
44
+
45
+ def self.heartbeats_before_dead
46
+ ENV['HEARTBEATS_BEFORE_DEAD'] || 25
47
+ end
48
+
49
+
50
+ def initialize(worker)
51
+ @worker = worker
52
+ end
53
+
54
+ def run
55
+ @thrd ||= Thread.new do
56
+ loop do
57
+ begin
58
+ beat! && sleep(2)
59
+ rescue Exception => e
60
+ Resque.logger.error "Error while doing heartbeat: #{e} : #{e.backtrace}"
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ def stop
67
+ Thread.kill(@thrd)
68
+ redis.del key
69
+ rescue
70
+ nil
71
+ end
72
+
73
+ def redis
74
+ Resque.redis
75
+ end
76
+
77
+ # you can send a redis wildcard to filter the workers you're looking for
78
+ def Heart.heartbeat_key(worker_name)
79
+ "worker:#{worker_name}:heartbeat"
80
+ end
81
+
82
+ def key
83
+ Heart.heartbeat_key worker.remote_hostname
84
+ end
85
+
86
+ def beat!
87
+ redis.sadd(:workers, worker)
88
+ redis.setex(key, Heart.heartbeat_interval_seconds * Heart.heartbeats_before_dead, '')
89
+ rescue Exception => e
90
+ Resque.logger.fatal "Unable to set the heartbeat for worker '#{worker.remote_hostname}': #{e} : #{e.backtrace}"
91
+ end
92
+
93
+ def dead?
94
+ !redis.exists(key)
95
+ end
96
+
97
+ def ttl
98
+ Resque.redis.ttl key
99
+ end
100
+ end
101
+ end
102
+
103
+ # NOTE: this assumes all of your workers are putting out heartbeats
104
+ def self.prune_dead_workers!
105
+ begin
106
+ beats = Resque.redis.keys(Worker::Heart.heartbeat_key('*'))
107
+ Worker.all.each do |worker|
108
+ worker.prune_if_dead
109
+
110
+ # remove the worker from consideration
111
+ beats.delete worker.heart.key
112
+ end
113
+
114
+ # at this point, beats only contains stuff from workers we don't even know about. Ditch 'em.
115
+ beats.each do |key|
116
+ Resque.logger.info "Removing #{key} from heartbeats because the worker isn't talking to Resque."
117
+ Resque.redis.del key
118
+ end
119
+ rescue Exception => e
120
+ p e
121
+ end
122
+ end
123
+
124
+ def self.dead_workers
125
+ Worker.all.select{|w| w.dead?}
126
+ end
127
+ end
@@ -0,0 +1,3 @@
1
+ module ResqueWorkerHeartbeat
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1 @@
1
+ require 'resque/heartbeat'
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resque_worker_heartbeat
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sven Fuchs
8
+ - Jon Phillips
9
+ - Andy Sykes
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-01-17 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: resque
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.25.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ version: 1.25.0
29
+ - !ruby/object:Gem::Dependency
30
+ name: rspec
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: rake
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ description: Gives Resque workers a heartbeat to allow dead worker detection
58
+ email: developers@forward3d.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - lib/resque/heartbeat.rb
64
+ - lib/resque_worker_heartbeat.rb
65
+ - lib/resque_worker_heartbeat/version.rb
66
+ homepage: https://github.com/forward3d/resque_worker_heartbeat
67
+ licenses:
68
+ - MIT
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 2.1.11
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: Gives Resque workers a heartbeat to allow dead worker detection
90
+ test_files: []