resque_worker_heartbeat 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []