Class: Kamisama

Inherits:
Object
  • Object
show all
Defined in:
lib/kamisama.rb,
lib/kamisama/task.rb,
lib/kamisama/version.rb,
lib/kamisama/process_ctrl.rb

Defined Under Namespace

Classes: ProcessCtrl, RespawnLimiter, Task

Constant Summary collapse

VERSION =
"0.1.0"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options, &block) ⇒ Kamisama

Returns a new instance of Kamisama.



11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/kamisama.rb', line 11

def initialize(options, &block)
  @block            = block
  @instances        = options.fetch(:instances)
  @respawn_limit    = options.fetch(:respawn_limit, 3)
  @respawn_interval = options.fetch(:respawn_interval, 60)
  @monitor_sleep    = 2

  @term_signal_received = false

  @respawn_limiter = Kamisama::RespawnLimiter.new(@respawn_limit, @respawn_interval)

  @tasks = []
end

Class Method Details

.run(options = {}, &block) ⇒ Object



7
8
9
# File 'lib/kamisama.rb', line 7

def self.run(options = {}, &block)
  new(options, &block).run
end

Instance Method Details

#add_workerObject



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/kamisama.rb', line 53

def add_worker
  puts "[Kamisama Master] #{Process.pid} Spawning new instance."

  @worker_index ||= 0
  @worker_index += 1

  task = Kamisama::Task.new(@worker_index, @block)
  task.start

  @tasks << task
end

#handle_signalsObject



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/kamisama.rb', line 36

def handle_signals
  trap("TTIN") do
    @instances += 1
  end

  trap("TTOU") do
    # make sure that we always have at least one running worker
    if @instances > 1
      @instances -= 1
    end
  end

  trap("TERM") do
    @term_signal_received = true
  end
end

#monitorObject



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/kamisama.rb', line 72

def monitor
  loop do
    break if @term_signal_received

    add_worker  while @tasks.count < @instances
    term_worker while @tasks.count > @instances

    dead_tasks = @tasks.reject(&:alive?)

    dead_tasks.each do |task|
      @respawn_limiter.record!
      task.restart!
    end

    sleep(@monitor_sleep)
  end

  puts "[Kamisama Master] #{Process.pid} Terminating all instances"
  @tasks.each(&:terminate!)
  exit
end

#runObject



25
26
27
28
29
30
31
32
33
34
# File 'lib/kamisama.rb', line 25

def run
  puts "[Kamisama Master] Process id: #{Process.pid}"
  puts "[Kamisama Master] Starting #{@instances} workers. \n"

  @instances.times { add_worker }

  handle_signals

  monitor
end

#term_workerObject



65
66
67
68
69
70
# File 'lib/kamisama.rb', line 65

def term_worker
  puts "[Kamisama Master] #{Process.pid} Terminating an instance."

  task = @tasks.shift
  task.terminate!
end