run_rabbit_run 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ log
19
+ .rvmrc
20
+ *.swp
21
+ dump.rdb
22
+ *.pid
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in run_rabbit_run.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Arturs Kreipans
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # RunRabbitRun
2
+
3
+ git@github.com:fragallia/run_rabbit_run.git
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'run_rabbit_run'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install run_rabbit_run
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ module RunRabbitRun
2
+ module Callbacks
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def define_callback *names
9
+ names.each do | name |
10
+ define_method name do | &block |
11
+ @callbacks ||= {}
12
+ @callbacks[name.to_sym] ||= []
13
+ @callbacks[name.to_sym] << block
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def call_callback name, *params
20
+ @callbacks[name.to_sym].each { | c | c.call *params } if @callbacks
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,36 @@
1
+ module RunRabbitRun
2
+ module Config
3
+ class Worker
4
+ attr_accessor :options
5
+
6
+ def initialize(path, options = {})
7
+ @options = {
8
+ path: File.expand_path(path),
9
+ log_to_master: true,
10
+ processes: 1,
11
+ }.merge(options)
12
+
13
+ @options[:processes] = 1 unless @options[:processes].to_i > 0
14
+
15
+ raise "File not exists: #{@options[:path]}" unless File.exists?(@options[:path])
16
+ end
17
+
18
+ def options
19
+ @options ||= {}
20
+ end
21
+
22
+ def name value
23
+ options[:name] = value
24
+ end
25
+
26
+ def processes value
27
+ options[:processes] = value > 0 ? value : 1
28
+ end
29
+
30
+ def log_to_master value
31
+ options[:log_to_master] = !!value
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,54 @@
1
+ require 'run_rabbit_run/config/worker'
2
+
3
+ module RunRabbitRun
4
+ module Config
5
+ extend self
6
+
7
+ attr_accessor :options
8
+
9
+ def load(application_path)
10
+ @options = {
11
+ application_path: application_path,
12
+ pid: "#{application_path}/tmp/pids/run_rabbit_run.pid",
13
+ environment: (ENV['RAKE_ENV'] || ENV['RAILS_ENV'] || 'development'),
14
+ log: "log/run_rabbit_run.log",
15
+ }
16
+
17
+ load_from_file "#{application_path}/config/rrr.rb"
18
+ load_from_file "#{application_path}/config/rrr/#{@options[:environment]}.rb"
19
+
20
+ options
21
+ end
22
+
23
+ def options
24
+ @options ||= {}
25
+ end
26
+
27
+ def log value
28
+ options[:log] = File.expand_path(value)
29
+ end
30
+
31
+ def pid value
32
+ options[:pid] = File.expand_path(value)
33
+ end
34
+
35
+ def worker name, path, options = {}, &block
36
+ worker = RunRabbitRun::Config::Worker.new(path, options)
37
+ worker.instance_exec &block if block_given?
38
+
39
+ self.options[:workers] ||= {}
40
+ self.options[:workers][name] = worker.options
41
+ end
42
+
43
+ def run *workers
44
+ options[:run] = workers
45
+ end
46
+
47
+ private
48
+
49
+ def load_from_file(path)
50
+ instance_eval File.read(path), path
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,98 @@
1
+ require 'run_rabbit_run/workers'
2
+ require 'run_rabbit_run/rabbitmq'
3
+ require 'run_rabbit_run/rabbitmq/system_messages'
4
+ require 'run_rabbit_run/pid'
5
+ require 'run_rabbit_run/processes/master'
6
+
7
+ module RunRabbitRun
8
+ module Master
9
+ extend self
10
+
11
+ def master_process
12
+ @master_process ||= begin
13
+ master = RunRabbitRun::Processes::Master.new
14
+ master.pid = Pid.pid
15
+
16
+ master
17
+ end
18
+ end
19
+
20
+ def start
21
+ master_process.start do
22
+ workers = RunRabbitRun::Workers.new
23
+ workers.start
24
+
25
+ add_periodic_timer 2 do
26
+ begin
27
+ workers.check unless exiting?
28
+ rescue => e
29
+ RunRabbitRun.logger.error e.message
30
+ end
31
+ end
32
+
33
+ before_exit do
34
+ workers.stop
35
+ end
36
+
37
+ before_reload do
38
+ workers.reload
39
+ end
40
+
41
+ on_system_message_received do | from, message, data |
42
+ begin
43
+ RunRabbitRun.logger.info "[master] got message [#{message}] from [#{from}] with data [#{data.inspect}]"
44
+
45
+ case message.to_sym
46
+ when :add_worker
47
+ workers.add(data['worker'])
48
+ when :remove_worker
49
+ workers.remove(data['worker'])
50
+ when :process_started
51
+ workers.worker(from.to_s).pid = data["pid"].to_i
52
+ end
53
+ rescue => e
54
+ RunRabbitRun.logger.error e.message
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ Pid.save(master_process.pid)
61
+ end
62
+
63
+ def add_worker name
64
+ EventMachine.run do
65
+ rabbitmq = RunRabbitRun::Rabbitmq::Base.new
66
+
67
+ system_messages = RunRabbitRun::Rabbitmq::SystemMessages.new(rabbitmq)
68
+ system_messages.publish(:system, :master, :add_worker, { worker: name })
69
+
70
+ EventMachine.add_timer(2) do
71
+ rabbitmq.stop
72
+ end
73
+ end
74
+ end
75
+
76
+ def remove_worker name
77
+ EventMachine.run do
78
+ rabbitmq = RunRabbitRun::Rabbitmq::Base.new
79
+
80
+ system_messages = RunRabbitRun::Rabbitmq::SystemMessages.new(rabbitmq)
81
+ system_messages.publish(:system, :master, :remove_worker, { worker: name })
82
+
83
+ EventMachine.add_timer(2) do
84
+ rabbitmq.stop
85
+ end
86
+ end
87
+ end
88
+
89
+ def stop
90
+ RunRabbitRun::Processes::Signals.stop_signal(:master, master_process.pid)
91
+ Pid.remove
92
+ end
93
+
94
+ def reload
95
+ RunRabbitRun::Processes::Signals.reload_signal(:master, master_process.pid)
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,32 @@
1
+ module RunRabbitRun
2
+ module Pid
3
+ extend self
4
+
5
+ def remove
6
+ File.delete(path) if File.exists?(path)
7
+ end
8
+
9
+ def pid
10
+ File.open(path, 'r') { |file| file.read }.to_i if File.exists?(path)
11
+ end
12
+
13
+ def save(pid)
14
+ create_directory_if_not_exists(File.dirname(path))
15
+
16
+ File.open(path, "w") {|file| file.puts(pid) }
17
+ end
18
+
19
+ private
20
+
21
+ def path
22
+ raise "[ERROR] please specify the pid file path" unless RunRabbitRun.config[:pid]
23
+
24
+ RunRabbitRun.config[:pid]
25
+ end
26
+
27
+ def create_directory_if_not_exists(dir)
28
+ FileUtils.mkdir_p(dir) unless File.exists?(dir)
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,82 @@
1
+ require 'run_rabbit_run/callbacks'
2
+ require 'run_rabbit_run/processes/signals'
3
+
4
+ module RunRabbitRun
5
+ module Processes
6
+ class Base
7
+ include RunRabbitRun::Callbacks
8
+
9
+ define_callback :before_exit
10
+ define_callback :before_reload
11
+
12
+ attr_accessor :pid, :name
13
+
14
+ def initialize name
15
+ @name = name
16
+ end
17
+
18
+ def start &block
19
+ if RunRabbitRun::Processes::Signals.running? @pid
20
+ raise "The process [#{@name}] is already running"
21
+ end
22
+
23
+ RunRabbitRun.logger.info "[#{@name}] process starting"
24
+
25
+ @pid = fork do
26
+ $0 = "[ruby] [RunRabbitRun] #{@name}"
27
+
28
+ signals = []
29
+
30
+ Signal.trap(RunRabbitRun::SIGNAL_EXIT) { signals << RunRabbitRun::SIGNAL_EXIT }
31
+ Signal.trap(RunRabbitRun::SIGNAL_RELOAD) { signals << RunRabbitRun::SIGNAL_RELOAD }
32
+
33
+ EventMachine.run do
34
+
35
+ instance_exec &block
36
+
37
+ EventMachine::add_periodic_timer( 0.5 ) do
38
+ if signals.include?( RunRabbitRun::SIGNAL_RELOAD )
39
+ signals.delete( RunRabbitRun::SIGNAL_RELOAD )
40
+
41
+ call_callback :before_reload
42
+ end
43
+ if signals.include?( RunRabbitRun::SIGNAL_EXIT )
44
+ @exiting = true
45
+
46
+ call_callback :before_exit
47
+ EventMachine::add_timer( 10 ) do
48
+ EventMachine.stop { exit }
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ RunRabbitRun.logger.info "[#{@name}] process finished"
55
+ end
56
+
57
+ Process.detach(@pid)
58
+
59
+ end
60
+
61
+ def exiting?
62
+ @exiting ||= false
63
+ end
64
+
65
+ def guid
66
+ "#{@name}-#{@pid}"
67
+ end
68
+
69
+ def add_timer seconds, &block
70
+ EventMachine::add_timer( seconds ) do
71
+ block.call
72
+ end
73
+ end
74
+
75
+ def add_periodic_timer seconds, &block
76
+ EventMachine::add_periodic_timer( seconds ) do
77
+ block.call
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,32 @@
1
+ require 'run_rabbit_run/processes/base'
2
+
3
+ module RunRabbitRun
4
+
5
+ module Processes
6
+ class Master < Base
7
+
8
+ define_callback :on_system_message_received
9
+
10
+ def initialize name = :master
11
+ super name
12
+ end
13
+
14
+ def start &block
15
+ super do
16
+ instance_exec &block
17
+
18
+ rabbitmq = RunRabbitRun::Rabbitmq::Base.new
19
+ system_messages = RunRabbitRun::Rabbitmq::SystemMessages.new(rabbitmq)
20
+
21
+ system_messages.subscribe "master.#" do | headers, payload |
22
+ call_callback :on_system_message_received, payload["from"].to_sym, payload["message"].to_sym, payload["data"]
23
+ end
24
+
25
+ before_exit do
26
+ rabbitmq.stop
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,56 @@
1
+ module RunRabbitRun
2
+ module Processes
3
+ module Signals
4
+ extend self
5
+
6
+ def running? pid
7
+ return false unless pid
8
+
9
+ begin
10
+ Process.getpgid(pid.to_i )
11
+
12
+ return true
13
+ rescue Errno::ESRCH
14
+ rescue Exception => e
15
+ RunRabbitRun.logger.error "#{e}, #{e.backtrace.join("\n")}"
16
+ end
17
+
18
+ return false
19
+ end
20
+
21
+ def kill_signal name, pid
22
+ send_signal name, pid, RunRabbitRun::SIGNAL_KILL
23
+ end
24
+
25
+ def stop_signal name, pid
26
+ send_signal name, pid, RunRabbitRun::SIGNAL_EXIT
27
+ end
28
+
29
+ def reload_signal name, pid
30
+ send_signal name, pid, RunRabbitRun::SIGNAL_RELOAD
31
+ end
32
+
33
+ private
34
+
35
+ def send_signal name, pid, signal
36
+ if running? pid
37
+ RunRabbitRun.logger.info "[#{name}] send #{signal_name(signal)} signal to process"
38
+ Process.kill(signal, pid)
39
+ else
40
+ RunRabbitRun.logger.debug "[#{name}] is not running"
41
+ end
42
+ end
43
+
44
+ def signal_name code
45
+ case code
46
+ when 'QUIT'
47
+ 'exit'
48
+ when 'USR1'
49
+ 'reload'
50
+ when 'KILL'
51
+ 'kill'
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,39 @@
1
+ require 'run_rabbit_run/processes/base'
2
+
3
+ module RunRabbitRun
4
+ module Processes
5
+ class Worker < Base
6
+
7
+ def initialize name, options
8
+ @options = options
9
+
10
+ super name
11
+ end
12
+
13
+ def start &block
14
+ super do
15
+ instance_exec &block if block_given?
16
+
17
+ rabbitmq = RunRabbitRun::Rabbitmq::Base.new
18
+ system_messages = RunRabbitRun::Rabbitmq::SystemMessages.new(rabbitmq)
19
+
20
+ system_messages.publish(@name, :master, :process_started, { pid: Process.pid } )
21
+
22
+ rabbitmq.on_message_received do | queue |
23
+ system_messages.publish(@name, :master, :message_received, { queue: queue.name } ) if @options[:log_to_master]
24
+ end
25
+ rabbitmq.on_message_processed do | queue |
26
+ system_messages.publish(@name, :master, :message_processed, { queue: queue.name } ) if @options[:log_to_master]
27
+ end
28
+
29
+ rabbitmq.instance_eval File.read(@options[:path]), @options[:path]
30
+
31
+ before_exit do
32
+ system_messages.publish(@name, :master, :process_quit)
33
+ rabbitmq.stop
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,37 @@
1
+ module RunRabbitRun
2
+ module Rabbitmq
3
+ class SystemMessages
4
+ def initialize(rabbitmq)
5
+ @rabbitmq = rabbitmq
6
+ end
7
+
8
+ def subscribe routing_key, &block
9
+ system_queue.bind(system_exchange, routing_key: "profile.#{RunRabbitRun.config[:environment]}.#{routing_key}")
10
+ system_queue.subscribe do | headers, payload |
11
+ block.call(headers, JSON.parse(payload))
12
+ end
13
+ end
14
+
15
+ def publish from, target, message, data = {}
16
+ system_exchange.publish(
17
+ JSON.generate({
18
+ from: from,
19
+ message: message,
20
+ data: { time: Time.now.to_f }.merge(data)
21
+ }),
22
+ routing_key: "profile.#{RunRabbitRun.config[:environment]}.#{target}")
23
+ end
24
+
25
+ private
26
+
27
+ def system_queue
28
+ @system_queue ||= @rabbitmq.channel.queue("profile.#{RunRabbitRun.config[:environment]}", auto_delete: false)
29
+ end
30
+
31
+ def system_exchange
32
+ @system_exchange ||= @rabbitmq.channel.topic("runrabbitrun.system", durable: true)
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,50 @@
1
+ require 'run_rabbit_run/callbacks'
2
+
3
+ module RunRabbitRun
4
+ module Rabbitmq
5
+ class Base
6
+ include RunRabbitRun::Callbacks
7
+
8
+ define_callback :on_message_received
9
+ define_callback :on_message_processed
10
+
11
+ def subscribe(queue, options = {}, &block)
12
+ opts = options.dup
13
+ time_logging = opts.delete(:time_logging) || false
14
+
15
+ queue.subscribe do | header, payload |
16
+ RunRabbitRun.logger.info "[#{queue.name}] [#{Time.now.to_f}] started" if time_logging
17
+ call_callback :on_message_received, queue
18
+
19
+ instance_exec(header, JSON.parse(payload), &block)
20
+
21
+ call_callback :on_message_processed, queue
22
+ RunRabbitRun.logger.info "[#{queue.name}] [#{Time.now.to_f}] finished" if time_logging
23
+ end
24
+ end
25
+
26
+ def publish(queue, data)
27
+ exchange.publish JSON.generate(data), :routing_key => queue.name
28
+ end
29
+
30
+ def connection
31
+ @connection ||= AMQP.connect(host: '127.0.0.1', username: "guest", password: "guest")
32
+ end
33
+
34
+ def channel
35
+ @channel ||= AMQP::Channel.new(connection, AMQP::Channel.next_channel_id, auto_recovery: true)
36
+ end
37
+
38
+ def exchange
39
+ @exchange ||= channel.direct('')
40
+ end
41
+
42
+ def stop
43
+ connection.close {
44
+ EventMachine.stop { exit }
45
+ }
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,47 @@
1
+ require "run_rabbit_run"
2
+
3
+ namespace :rrr do
4
+ desc 'Starts profile workers'
5
+ task start: [ :config ] do
6
+ RunRabbitRun::Master.start
7
+ end
8
+
9
+ desc 'Stops profile workers'
10
+ task stop: [ :config ] do
11
+ RunRabbitRun::Master.stop
12
+ end
13
+
14
+ desc 'Reloads config, stops old workers and runs new with new config'
15
+ task reload: [ :config ] do
16
+ RunRabbitRun::Master.reload
17
+ end
18
+
19
+ namespace :worker do
20
+ desc 'Adds one process for given worker'
21
+ task :add, [ :worker_name ] => [ :config ] do | t, args |
22
+ raise 'Please specify worker name' unless args[:worker_name]
23
+ RunRabbitRun::Master.add_worker(args[:worker_name])
24
+ end
25
+
26
+ desc 'Stops one process for given worker'
27
+ task :remove, [ :worker_name ] => [ :config ] do | t, args |
28
+ raise 'Please specify worker name' unless args[:worker_name]
29
+ RunRabbitRun::Master.remove_worker(args[:worker_name])
30
+ end
31
+
32
+ task :new, [ :worker_name, :worker_guid ] => [ :config ] do | t, args |
33
+ raise 'Please specify worker name' unless args[:worker_name]
34
+ raise 'Please specify worker guid' unless args[:worker_guid]
35
+
36
+ require 'run_rabbit_run/processes/worker'
37
+
38
+ options = RunRabbitRun.config[:workers][args[:worker_name].to_sym]
39
+
40
+ RunRabbitRun::Processes::Worker.new(args[:worker_guid], options).start
41
+ end
42
+ end
43
+
44
+ task :config do
45
+ RunRabbitRun.load_config(Rake.original_dir)
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module RunRabbitRun
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,33 @@
1
+ require 'run_rabbit_run/processes/signals'
2
+
3
+ module RunRabbitRun
4
+ class Worker
5
+ attr_accessor :name, :guid, :pid, :status
6
+ def initialize(name, guid)
7
+ @name, @guid, @pid = name, guid, nil
8
+
9
+ @status = :unknown
10
+ end
11
+
12
+ def run
13
+ #TODO get path for bundle
14
+ success = system("RAKE_ENV=#{RunRabbitRun.config[:environment]} bundle exec rake rrr:worker:new[#{@name},#{@guid}]")
15
+ end
16
+
17
+ def kill
18
+ RunRabbitRun::Processes::Signals.kill_signal(@guid, @pid)
19
+ end
20
+
21
+ def stop
22
+ RunRabbitRun::Processes::Signals.stop_signal(@guid, @pid)
23
+ end
24
+
25
+ def reload
26
+ RunRabbitRun::Processes::Signals.reload_signal(@guid, @pid)
27
+ end
28
+
29
+ def running?
30
+ RunRabbitRun::Processes::Signals.running? @pid
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,112 @@
1
+ module RunRabbitRun
2
+ require 'run_rabbit_run/worker'
3
+
4
+ class Workers
5
+ def initialize
6
+ @workers = {}
7
+ end
8
+
9
+ def worker(guid)
10
+ @workers.each do | name, workers |
11
+ workers.each do | current_guid, worker |
12
+ return worker if current_guid == guid
13
+ end
14
+ end
15
+
16
+ nil
17
+ end
18
+
19
+ def check
20
+ @workers.each do | name, workers |
21
+ workers.each do | guid, worker |
22
+ worker.run unless worker.running?
23
+ end
24
+ diff = RunRabbitRun.config[:workers][name][:processes] - workers.size
25
+ diff.times{ run_new_worker name } if diff > 0
26
+ end
27
+ end
28
+
29
+ def add name
30
+ run_new_worker name
31
+ end
32
+
33
+ def remove name
34
+ guid = @workers[name.to_sym].keys.sort.first
35
+ worker = @workers[name.to_sym][guid]
36
+
37
+ worker.stop
38
+
39
+ sleep 1
40
+
41
+ if worker.running?
42
+ sleep 4
43
+ worker.kill if worker.running?
44
+ end
45
+
46
+ @workers[name.to_sym].delete(guid)
47
+ end
48
+
49
+ def start
50
+ RunRabbitRun.config[:run].each do | name |
51
+ RunRabbitRun.config[:workers][name][:processes].times do | n |
52
+ run_new_worker name
53
+ end
54
+ end
55
+ end
56
+
57
+ def stop
58
+ # try to stop gracefully
59
+ @workers.each { | name, workers | workers.each { | guid, worker | worker.stop } }
60
+
61
+ sleep 1
62
+
63
+ @workers.each do | name, workers |
64
+ workers.each do | guid, worker |
65
+ if worker.running?
66
+ sleep 4
67
+ self.kill # kill workers which are still running
68
+ return
69
+ end
70
+ end
71
+ end
72
+
73
+ @workers = {}
74
+ end
75
+
76
+ def kill
77
+ @workers.each { | name, workers | workers.each { | guid, worker | worker.kill if worker.running? } }
78
+
79
+ @workers = {}
80
+ end
81
+
82
+ def reload
83
+ # reload the config file
84
+ RunRabbitRun.load_config( RunRabbitRun.config[:application_path] )
85
+
86
+ self.stop
87
+ self.start
88
+ end
89
+
90
+ private
91
+
92
+ def run_new_worker name
93
+ name = name.to_sym
94
+ guid = generate_guid(name)
95
+ worker = RunRabbitRun::Worker.new(name, guid)
96
+
97
+ @workers[name] ||= {}
98
+ @workers[name][guid] = worker
99
+
100
+ worker.run
101
+ end
102
+
103
+ def generate_guid name
104
+ last_guid = @workers[name].keys.sort.last if @workers[name]
105
+
106
+ index = (last_guid ? last_guid.split('-').last.to_i : 0) + 1
107
+
108
+ "#{name}-#{index}"
109
+ end
110
+
111
+ end
112
+ end
@@ -0,0 +1,44 @@
1
+ require "run_rabbit_run/version"
2
+
3
+ require 'amqp'
4
+ require 'bson'
5
+ require 'json'
6
+ require 'logger'
7
+
8
+ module RunRabbitRun
9
+ require 'run_rabbit_run/master'
10
+ require 'run_rabbit_run/config'
11
+
12
+ extend self
13
+
14
+ SIGNAL_EXIT = 'QUIT'
15
+ SIGNAL_RELOAD = 'USR1'
16
+ SIGNAL_KILL = 'KILL'
17
+
18
+ def load_config application_path
19
+ @@config = RunRabbitRun::Config.load(application_path)
20
+ end
21
+
22
+ def config
23
+ @@config
24
+ end
25
+
26
+ def logger
27
+ @@logger ||= begin
28
+ path = self.config[:log]
29
+
30
+ FileUtils.mkdir_p(File.dirname(path)) unless File.exists?(File.dirname(path))
31
+
32
+ logger = Logger.new(path, 10, 1024000)
33
+
34
+ if self.config[:environment] == 'development'
35
+ logger.level = Logger::DEBUG
36
+ else
37
+ logger.level = Logger::INFO
38
+ end
39
+
40
+ logger
41
+ end
42
+ end
43
+ end
44
+
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ # include gem version
5
+ require 'run_rabbit_run/version'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.authors = ["Arturs Kreipans"]
9
+ gem.email = ["arturs.kreipans@gmail.com"]
10
+ gem.description = %q{RunRabbitRun gem lets to run and manage multiple ruby processes for RabbitMQ}
11
+ gem.summary = %q{RunRabbitRun gem lets to run and manage multiple ruby processes for RabbitMQ}
12
+ gem.homepage = ""
13
+
14
+ gem.files = `git ls-files`.split($\)
15
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.name = "run_rabbit_run"
18
+ gem.require_paths = ["lib"]
19
+ gem.version = RunRabbitRun::VERSION
20
+
21
+ gem.add_dependency "rake"
22
+ gem.add_dependency "bson_ext"
23
+ gem.add_dependency "amqp"
24
+
25
+ gem.add_development_dependency 'pry'
26
+ gem.add_development_dependency 'pry-remote'
27
+ end
@@ -0,0 +1,3 @@
1
+ gem 'run_rabbit_run', path: '../../'
2
+ gem 'pry'
3
+ gem 'pry-remote'
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env rake
2
+ require 'rake'
3
+ require "run_rabbit_run/tasks"
4
+
@@ -0,0 +1 @@
1
+ run :worker1, :worker2
@@ -0,0 +1,15 @@
1
+ require 'run_rabbit_run'
2
+
3
+ #TODO working_directory '/path/to/working/directory'
4
+
5
+ log "log/run_rabbit_run.log"
6
+ pid "tmp/pids/run_rabbit_run.pid"
7
+
8
+ worker :worker1, 'workers/worker_name_1.rb', processes: 1
9
+
10
+ worker :worker2, 'workers/worker_name_2.rb' do
11
+ name 'Worker name 2'
12
+ log_to_master true
13
+
14
+ processes 1
15
+ end
@@ -0,0 +1,13 @@
1
+ output = channel.queue('output', auto_delete: false)
2
+ input = channel.queue('input', auto_delete: false)
3
+
4
+ publish(output, {some: 'data'})
5
+
6
+ subscribe(output, time_logging: true) do | header, data |
7
+ RunRabbitRun.logger.info data.inspect
8
+ publish(input, {received: 'data'})
9
+ end
10
+
11
+ subscribe(input) do | header, data |
12
+ RunRabbitRun.logger.info data.inspect
13
+ end
@@ -0,0 +1,13 @@
1
+ output = channel.queue('output2', auto_delete: false)
2
+ input = channel.queue('input2', auto_delete: false)
3
+
4
+ publish(output, {some: 'data'})
5
+
6
+ subscribe(output) do | header, data |
7
+ RunRabbitRun.logger.info data.inspect
8
+ publish(input, {received: 'data'})
9
+ end
10
+
11
+ subscribe(input) do | header, data |
12
+ RunRabbitRun.logger.info data.inspect
13
+ end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: run_rabbit_run
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Arturs Kreipans
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: bson_ext
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: amqp
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: pry
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: pry-remote
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: RunRabbitRun gem lets to run and manage multiple ruby processes for RabbitMQ
95
+ email:
96
+ - arturs.kreipans@gmail.com
97
+ executables: []
98
+ extensions: []
99
+ extra_rdoc_files: []
100
+ files:
101
+ - .gitignore
102
+ - Gemfile
103
+ - LICENSE
104
+ - README.md
105
+ - Rakefile
106
+ - lib/run_rabbit_run.rb
107
+ - lib/run_rabbit_run/callbacks.rb
108
+ - lib/run_rabbit_run/config.rb
109
+ - lib/run_rabbit_run/config/worker.rb
110
+ - lib/run_rabbit_run/master.rb
111
+ - lib/run_rabbit_run/pid.rb
112
+ - lib/run_rabbit_run/processes/base.rb
113
+ - lib/run_rabbit_run/processes/master.rb
114
+ - lib/run_rabbit_run/processes/signals.rb
115
+ - lib/run_rabbit_run/processes/worker.rb
116
+ - lib/run_rabbit_run/rabbitmq.rb
117
+ - lib/run_rabbit_run/rabbitmq/system_messages.rb
118
+ - lib/run_rabbit_run/tasks.rb
119
+ - lib/run_rabbit_run/version.rb
120
+ - lib/run_rabbit_run/worker.rb
121
+ - lib/run_rabbit_run/workers.rb
122
+ - run_rabbit_run.gemspec
123
+ - spec/dummy/Gemfile
124
+ - spec/dummy/Rakefile
125
+ - spec/dummy/config/rrr.rb
126
+ - spec/dummy/config/rrr/development.rb
127
+ - spec/dummy/workers/worker_name_1.rb
128
+ - spec/dummy/workers/worker_name_2.rb
129
+ homepage: ''
130
+ licenses: []
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ! '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ none: false
143
+ requirements:
144
+ - - ! '>='
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubyforge_project:
149
+ rubygems_version: 1.8.24
150
+ signing_key:
151
+ specification_version: 3
152
+ summary: RunRabbitRun gem lets to run and manage multiple ruby processes for RabbitMQ
153
+ test_files:
154
+ - spec/dummy/Gemfile
155
+ - spec/dummy/Rakefile
156
+ - spec/dummy/config/rrr.rb
157
+ - spec/dummy/config/rrr/development.rb
158
+ - spec/dummy/workers/worker_name_1.rb
159
+ - spec/dummy/workers/worker_name_2.rb