From ee808bf5c0e7fd2c8dcafc89eff6795cdb59a711 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Mon, 6 Jun 2011 11:11:05 +0200 Subject: [PATCH] initial commit --- README | 0 Rakefile | 10 +++++ lib/resque/heartbeat.rb | 70 +++++++++++++++++++++++++++++++++ lib/resque_heartbeat.rb | 1 + lib/resque_heartbeat/version.rb | 3 ++ resque-heartbeat.gemspec | 19 +++++++++ 6 files changed, 103 insertions(+) create mode 100644 README create mode 100644 Rakefile create mode 100644 lib/resque/heartbeat.rb create mode 100644 lib/resque_heartbeat.rb create mode 100644 lib/resque_heartbeat/version.rb create mode 100644 resque-heartbeat.gemspec diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..47e7ef4 --- /dev/null +++ b/Rakefile @@ -0,0 +1,10 @@ +require 'rake' +require 'rake/testtask' + +Rake::TestTask.new do |t| + t.libs << 'lib' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end + +task :default => :test diff --git a/lib/resque/heartbeat.rb b/lib/resque/heartbeat.rb new file mode 100644 index 0000000..36cf21e --- /dev/null +++ b/lib/resque/heartbeat.rb @@ -0,0 +1,70 @@ +require 'resque' + +module Resque + def self.prune_dead_workers + begin + Worker.all.each { |worker| worker.prune_if_dead } + rescue Exception => e + p e + end + end + + class Worker + def startup_with_heartbeat + startup_without_heartbeat + heart.run + end + alias startup_without_heartbeat startup + alias startup startup_with_heartbeat + + def heart + @heart ||= Heart.new(self) + end + + def prune_if_dead + unregister_worker if heart.last_beat_before?(5) + end + + class Heart + attr_reader :worker + + def initialize(worker) + @worker = worker + end + + def run + Thread.new { loop { sleep(2) && beat! } } + end + + def redis + @redis && connected? ? @redis : @redis = connect + end + + def connect + # apparently the Redis connection is not thread-safe, so we connect another instance + # see https://github.com/ezmobius/redis-rb/issues#issue/75 + redis = Redis.connect(:url => Travis.config['redis']['url']).tap { |redis| redis.client.connect } + Redis::Namespace.new(:resque, :redis => redis) + end + + def connected? + @redis.client.connected? + end + + def beat! + redis.sadd(:workers, worker) + redis.set("worker:#{worker}:heartbeat", Time.now.to_s) + rescue Exception => e + p e + end + + def last_beat_before?(seconds) + Time.parse(last_beat).utc < (Time.now.utc - seconds) rescue true + end + + def last_beat + Resque.redis.get("worker:#{worker}:heartbeat") || worker.started + end + end + end +end diff --git a/lib/resque_heartbeat.rb b/lib/resque_heartbeat.rb new file mode 100644 index 0000000..fad9009 --- /dev/null +++ b/lib/resque_heartbeat.rb @@ -0,0 +1 @@ +require 'resque/heartbeat' diff --git a/lib/resque_heartbeat/version.rb b/lib/resque_heartbeat/version.rb new file mode 100644 index 0000000..83624ec --- /dev/null +++ b/lib/resque_heartbeat/version.rb @@ -0,0 +1,3 @@ +module ResqueHeartbeat + VERSION = "0.0.1" +end diff --git a/resque-heartbeat.gemspec b/resque-heartbeat.gemspec new file mode 100644 index 0000000..561bde4 --- /dev/null +++ b/resque-heartbeat.gemspec @@ -0,0 +1,19 @@ +# encoding: utf-8 + +$:.unshift File.expand_path('../lib', __FILE__) +require 'resque_heartbeat/version' + +Gem::Specification.new do |s| + s.name = "resque-heartbeat" + s.version = ResqueHeartbeat::VERSION + s.authors = ["Sven Fuchs"] + s.email = "svenfuchs@artweb-design.de" + s.homepage = "http://github.com/svenfuchs/resque-heartbeat" + s.summary = "[summary]" + s.description = "[description]" + + s.files = `git ls-files app lib`.split("\n") + s.platform = Gem::Platform::RUBY + s.require_path = 'lib' + s.rubyforge_project = '[none]' +end