Skip to content

Instantly share code, notes, and snippets.

@baya
Created November 6, 2012 05:26
Show Gist options
  • Save baya/4022774 to your computer and use it in GitHub Desktop.
Save baya/4022774 to your computer and use it in GitHub Desktop.
确保程序能够独断运行
class Dogmatism
def initialize(process_name)
@process_name = process_name
@uuid = SecureRandom.uuid
end
def protect
begin
if File.exists? pidfile_path
puts "因为已经有#{pidfile_path}存在,将立即退出进程:#{@process_name}@#{@uuid}\n"
# do nothing
else
create_pidfile
yield
end
ensure
clear_pidfile
end
end
def pidfile_path
File.expand_path File.join(File.dirname(__FILE__), '..', 'tmp', "#{@process_name}.pid")
end
def create_pidfile
File.open(pidfile_path, 'w+') {|f| f.write @uuid }
end
def clear_pidfile
if File.exists? pidfile_path
pid = File.open(pidfile_path, 'r') {|f| f.read }
File.delete(pidfile_path) if pid == @uuid or pid.blank?
end
end
end
def Dogmatism(process_name)
Dogmatism.new(process_name).protect do
yield
end
end
@baya
Copy link
Author

baya commented Nov 6, 2012

require 'test_helper'

class DogmatismTest < ActiveSupport::TestCase

def setup
@process_name = 'lotfarm_autobatch_bets'
@pidfile_path = File.join(Rails.root, "tmp", "#{@process_name}.pid")
File.delete(@pidfile_path) if File.exists? @pidfile_path
@Dog = Dogmatism.new(@process_name)
end

test '#pidfile_path' do
assert_equal @pidfile_path, @dog.pidfile_path
end

test '#create_pidfile' do
@dog.create_pidfile
assert File.exists?(@pidfile_path)
end

test '#clear_pidfile' do
assert_nothing_raised do
@dog.clear_pidfile
end

`touch #@pidfile_path`
@dog.clear_pidfile
assert !File.exists?(@pidfile_path)

end

test '#protect' do
# 程序正常结束,清理pid文件
Dogmatism(@process_name) do
assert File.exists?(@pidfile_path)
1 + 1
end
assert !File.exists?(@pidfile_path)

# 程序异常结束,清理pid文件
assert_raise RuntimeError do
  Dogmatism(@process_name) do
    1 + 1
    raise
  end
end

assert !File.exists?(@pidfile_path)

# 多个进程并发运行
$a = 0
$b = 0
$c = 0
$d = 0
$e = 0
t_a = Thread.new { Dogmatism(@process_name) { loop{$a += 1}}}
sleep(0.1)
t_b = Thread.new { Dogmatism(@process_name) { $b += 1}}
t_c = Thread.new { Dogmatism(@process_name) { $c += 1}}
t_d = Thread.new { Dogmatism(@process_name) { $d += 1}}
t_e = Thread.new { Dogmatism(@process_name) { $e += 1}}
loop do
  if [t_b, t_c, t_d].all?{|t| !t.alive?}
    Thread.kill t_a
    break
  end  
end  

assert_not_equal $a, 0
assert_equal $b, 0
assert_equal $c, 0
assert_equal $d, 0
assert_equal $e, 0

end

end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment