Skip to content

Instantly share code, notes, and snippets.

@marianposaceanu
Created August 29, 2011 13:54
Show Gist options
  • Save marianposaceanu/1178437 to your computer and use it in GitHub Desktop.
Save marianposaceanu/1178437 to your computer and use it in GitHub Desktop.
heartbeat
# we're using the TmpIO class
# -*- encoding: binary -*-
# :stopdoc:
require 'tmpdir'
# some versions of Ruby had a broken Tempfile which didn't work
# well with unlinked files. This one is much shorter, easier
# to understand, and slightly faster.
class TmpIO < File
# creates and returns a new File object. The File is unlinked
# immediately, switched to binary mode, and userspace output
# buffering is disabled
def self.new
fp = begin
super("#{Dir::tmpdir}/#{rand}", RDWR|CREAT|EXCL, 0600)
rescue Errno::EEXIST
retry
end
unlink(fp.path)
fp.binmode
fp.sync = true
fp
end
# for easier env["rack.input"] compatibility with Rack <= 1.1
def size
stat.size
end unless File.method_defined?(:size)
end
# end
#
# EXAMPLE
#
# usage : worker = Worker.new(worker_nr, Unicorn::TmpIO.new)
# p TmpIO.new
# p TmpIO.new
#
# Worker class
#
class Worker < Struct.new(:nr, :tmp, :switched)
# worker objects may be compared to just plain Integers
def ==(other_nr) # :nodoc:
nr == other_nr
end
end
#
# EXAMPLE
#
# we create some workers
w1 = Worker.new 1, TmpIO.new
w2 = Worker.new 2, TmpIO.new
# The chmod will use either ‘1’ or ‘0’ each time this gets executed.
# (Assign ‘0’ to the local variable ‘m’, compare it to ‘0’. If it matches (m == 0), m = 1, otherwise m = 0.
# A one line toggle.)
# this one should be stale
p w1.tmp.chmod(m = 0 == m ? 1 : 0)
sleep 5
# this one should be ok
p w2.tmp.chmod(m = 0 == m ? 1 : 0)
WORKERS = []
WORKERS << w1
WORKERS << w2
# Here’s what the master does to check the worker’s status
# Even though the file is unlinked it still has metadata associated with it.
# Using the file’s #ctime we can check when the file was last mode changed,
# and thus when the worker was last alive.
timeout = 3
WORKERS.each do |worker|
stat = worker.tmp.stat
unless (diff = (Time.now - stat.ctime)) <= timeout
p "Worker #{worker.nr} has gone stale and needs to be respawned"
else
p "Worker #{worker.nr} is not stale"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment