Class: Raemon::Runner

Inherits:
Master
  • Object
show all
Defined in:
lib/raemon/runner.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.queuesObject



7
# File 'lib/raemon/runner.rb', line 7

def self.queues; @queues end

.queues=(queues) ⇒ Object



3
4
5
# File 'lib/raemon/runner.rb', line 3

def self.queues=(queues)
  @queues ||= queues.to_s.split(',')
end

Instance Method Details

#maintain_worker_countObject



9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/raemon/runner.rb', line 9

def maintain_worker_count
  # check if any jobs are available
  logger.info "** Checking if any jobs are available on #{self.class.queues.inspect}"
  worker = Resque::Runner.new(self.class.queues)
  if worker.empty?
    logger.info "** No Jobs available, sleeping for #{Choice.choices[:interval]}"
    sleep Choice.choices[:interval]
  else
    logger.info "** Job found, starting worker"
    super
  end
end

#master_loop!Object

monitors children and receives signals forever (or until a termination signal is sent). This handles signals one-at-a-time time and we’ll happily drop signals in case somebody is signalling us too often.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/raemon/runner.rb', line 26

def master_loop!
  # this pipe is used to wake us up from select(2) in #join when signals
  # are trapped.  See trap_deferred
  init_self_pipe!
  @respawn = true

  QUEUE_SIGS.each { |sig| trap_deferred(sig) }
  trap(:CHLD) { |sig_nr| awaken_master }
  
  process_name 'master'
  logger.info "master process ready"
  
  # Spawn workers for the first time
  maintain_worker_count
  
  begin
    loop do
      monitor_memory_usage
      reap_all_workers

      case SIG_QUEUE.shift
      when nil
        murder_lazy_workers
        maintain_worker_count if @respawn
        master_sleep
      when :QUIT # graceful shutdown
        break
      when :TERM, :INT # immediate shutdown
        stop(false)
        break
      when :USR1
        kill_each_worker(:USR1)
      when :USR2
        kill_each_worker(:USR2)
      when :WINCH
        if Process.ppid == 1 || Process.getpgrp != $$
          @respawn = false
          logger.info "gracefully stopping all workers"
          kill_each_worker(:QUIT)
        else
          logger.info "SIGWINCH ignored because we're not daemonized"
        end
      when :TTIN
        @num_workers += 1
      when :TTOU
        @num_workers -= 1 if @num_workers > 0
      when :HUP
        # TODO: should restart the workers, but a :QUIT could stall
        # respawn = true
        # kill_each_worker(:QUIT)
      end
    end
  rescue Errno::EINTR
    retry
  rescue => ex
    logger.error "Unhandled master loop exception #{ex.inspect}."
    logger.error ex.backtrace.join("\n")
    retry
  end
  
  # Gracefully shutdown all workers on our way out
  stop
  logger.info "master complete"
  
  # Close resources
  unlink_pid_safe(pid_file) if pid_file
  logger.close
end