Class: ModernTimes::Manager
- Inherits:
-
Object
- Object
- ModernTimes::Manager
- Defined in:
- lib/modern_times/manager.rb
Instance Attribute Summary collapse
-
#allowed_workers ⇒ Object
Returns the value of attribute allowed_workers.
-
#dummy_host ⇒ Object
Returns the value of attribute dummy_host.
-
#supervisors ⇒ Object
readonly
Returns the value of attribute supervisors.
Class Method Summary collapse
-
.parse_worker_file(file, dummy_host, &block) ⇒ Object
Parse the worker file sending the yield block the class, count and options for each worker.
Instance Method Summary collapse
- #add(worker_klass, num_workers, worker_options = {}) ⇒ Object
- #find_supervisor(name) ⇒ Object
-
#initialize(config = {}) ⇒ Manager
constructor
Constructs a manager.
- #join ⇒ Object
- #persist_file=(file) ⇒ Object
- #save_persist_state ⇒ Object
-
#start ⇒ Object
TODO: Get rid of this or prevent worker thread creation until it’s been called?.
- #stop ⇒ Object
- #stop_on_signal ⇒ Object
- #worker_file=(file) ⇒ Object
Constructor Details
#initialize(config = {}) ⇒ Manager
Constructs a manager. Accepts a hash of config values
allowed_workers - array of allowed worker classes. For a rails project, this will be set to the
classes located in the app/workers directory which are a kind_of? ModernTimes::Base::Worker
dummy_host - name to use for host as defined by the worker_file. For a rails project, this will be the value of Rails.env
such that a set of workers can be defined for development without having to specify the hostname. For production, a set of
workers could be defined under production or specific workers for each host name
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/modern_times/manager.rb', line 16 def initialize(config={}) @stopped = false @config = config @domain = config[:domain] || ModernTimes::DEFAULT_DOMAIN # Unless specifically unconfigured (i.e., Rails.env == test), then enable jmx if config[:jmx] != false @jmx_server = JMX::MBeanServer.new bean = ManagerMBean.new(@domain, self) @jmx_server.register_mbean(bean, ModernTimes.manager_mbean_object_name(@domain)) end @supervisors = [] @dummy_host = config[:dummy_host] self.persist_file = config[:persist_file] self.worker_file = config[:worker_file] @allowed_workers = config[:allowed_workers] stop_on_signal if config[:stop_on_signal] end |
Instance Attribute Details
#allowed_workers ⇒ Object
Returns the value of attribute allowed_workers.
7 8 9 |
# File 'lib/modern_times/manager.rb', line 7 def allowed_workers @allowed_workers end |
#dummy_host ⇒ Object
Returns the value of attribute dummy_host.
7 8 9 |
# File 'lib/modern_times/manager.rb', line 7 def dummy_host @dummy_host end |
#supervisors ⇒ Object (readonly)
Returns the value of attribute supervisors.
8 9 10 |
# File 'lib/modern_times/manager.rb', line 8 def supervisors @supervisors end |
Class Method Details
.parse_worker_file(file, dummy_host, &block) ⇒ Object
Parse the worker file sending the yield block the class, count and options for each worker. This is a big kludge to let dummy publishing share this parsing code for Railsable in order to setup dummy workers. Think about a refactor where the manager knows about dummy publishing mode? Get the previous version to unkludge.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/modern_times/manager.rb', line 150 def self.parse_worker_file(file, dummy_host, &block) if File.exist?(file) hash = YAML.load(ERB.new(File.read(file)).result(binding)) config = dummy_host && hash[dummy_host] unless config host = Socket.gethostname.sub(/\..*/, '') config = hash[host] end return unless config config.each do |worker_name, worker_hash| klass_name = worker_hash[:class] || worker_hash[:klass] || "#{worker_name}Worker" # Backwards compat, remove :klass in next release klass = Object.const_get(klass_name.to_s) count = worker_hash[:count] = worker_hash[:options] || {} [:name] = worker_name yield(klass, count, ) end end end |
Instance Method Details
#add(worker_klass, num_workers, worker_options = {}) ⇒ Object
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 |
# File 'lib/modern_times/manager.rb', line 34 def add(worker_klass, num_workers, ={}) ModernTimes.logger.info "Starting #{worker_klass} with #{num_workers} workers with options #{.inspect}" unless worker_klass.kind_of?(Class) begin worker_klass = Object.const_get(worker_klass.to_s) rescue raise "Invalid class: #{worker_klass}" end end if @allowed_workers && !@allowed_workers.include?(worker_klass) raise "Error: #{worker_klass.name} is not an allowed worker" end supervisor = worker_klass.create_supervisor(self, ) raise "A supervisor with name #{supervisor.name} already exists" if find_supervisor(supervisor.name) @supervisors << supervisor supervisor.worker_count = num_workers if @jmx_server mbean = supervisor.create_mbean(@domain) @jmx_server.register_mbean(mbean, "#{@domain}:worker=#{supervisor.name},type=Worker") end ModernTimes.logger.info "Started #{worker_klass.name} named #{supervisor.name} with #{num_workers} workers" rescue Exception => e ModernTimes.logger.error "Exception trying to add #{worker_klass}: #{e.}\n\t#{e.backtrace.join("\n\t")}" raise rescue java.lang.Exception => e ModernTimes.logger.error "Java exception trying to add #{worker_klass.name}: #{e.}\n\t#{e.backtrace.join("\n\t")}" raise end |
#find_supervisor(name) ⇒ Object
123 124 125 126 127 128 |
# File 'lib/modern_times/manager.rb', line 123 def find_supervisor(name) @supervisors.each do |supervisor| return supervisor if supervisor.name == name end return nil end |
#join ⇒ Object
75 76 77 78 79 80 |
# File 'lib/modern_times/manager.rb', line 75 def join while !@stopped sleep 1 end @supervisors.each { |supervisor| supervisor.join } end |
#persist_file=(file) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/modern_times/manager.rb', line 91 def persist_file=(file) return if @persist_file == file @persist_file = nil return unless file if File.exist?(file) hash = YAML.load_file(file) hash.each do |worker_name, worker_hash| klass = worker_hash[:class] || worker_hash[:klass] # Backwards compat, remove klass in next release count = worker_hash[:count] = worker_hash[:options] [:name] = worker_name add(klass, count, ) end end @persist_file = file end |
#save_persist_state ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/modern_times/manager.rb', line 108 def save_persist_state return unless @persist_file hash = {} @supervisors.each do |supervisor| hash[supervisor.name] = { :class => supervisor.worker_klass.name, :count => supervisor.worker_count, :options => supervisor. } end File.open(@persist_file, 'w') do |out| YAML.dump(hash, out ) end end |
#start ⇒ Object
TODO: Get rid of this or prevent worker thread creation until it’s been called?
64 65 66 67 |
# File 'lib/modern_times/manager.rb', line 64 def start return if @started @started = true end |
#stop ⇒ Object
69 70 71 72 73 |
# File 'lib/modern_times/manager.rb', line 69 def stop return if @stopped @stopped = true @supervisors.each { |supervisor| supervisor.stop } end |
#stop_on_signal ⇒ Object
82 83 84 85 86 87 88 89 |
# File 'lib/modern_times/manager.rb', line 82 def stop_on_signal ['HUP', 'INT', 'TERM'].each do |signal_name| Signal.trap(signal_name) do ModernTimes.logger.info "Caught #{signal_name}" stop end end end |
#worker_file=(file) ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/modern_times/manager.rb', line 130 def worker_file=(file) return unless file @worker_file = file # Don't save new states if the user never dynamically updates the workers # Then they can solely define the workers via this file and updates to the counts won't be ignored. save_persist_file = @persist_file @persist_file = nil unless File.exist?(@persist_file) begin self.class.parse_worker_file(file, @dummy_host) do |klass, count, | # Don't add if persist_file already created this supervisor add(klass, count, ) unless find_supervisor([:name]) end ensure @persist_file = save_persist_file end end |