zmq_jobs 0.0.1.alpha

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ log/*.log
6
+ tmp/*
7
+ tmp/**/*
8
+ nbproject/*
9
+ nbproject/**/*
10
+ .idea/*
11
+ .idea/**/*
12
+ .DS_Store
13
+ *.tmproj
14
+ .rvmrc
15
+ Icon*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --drb
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in zmq_jobs.gemspec
4
+ gemspec
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+ require 'rdoc/task'
4
+ require 'rspec/core/rake_task'
5
+
6
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
7
+
8
+ RSpec::Core::RakeTask.new(:spec) do |spec|
9
+ spec.pattern = "spec/**/*_spec.rb"
10
+ end
11
+
12
+ task :default => ["spec"]
data/bin/broker ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
4
+ require 'zmq_jobs'
5
+
6
+ ZmqJobs::BrokerCommand.new(ARGV).start
data/bin/worker ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
4
+ require 'zmq_jobs'
5
+
6
+ ZmqJobs::WorkerCommand.new(ARGV).start
@@ -0,0 +1,14 @@
1
+ workers_dir: ./examples/workers
2
+ workers:
3
+ test_worker:
4
+ iothreads: 1
5
+ hosts: ['127.0.0.1']
6
+ ports: [2203]
7
+ broker:
8
+ iothreads: 1
9
+ frontend:
10
+ hosts: ['127.0.0.1']
11
+ ports: [<%= (2200..2202).to_a.join(', ') %>]
12
+ backend:
13
+ host: '127.0.0.1'
14
+ port: 2203
@@ -0,0 +1,18 @@
1
+ workers_dir: ./workers
2
+ workers:
3
+ default:
4
+ iothreads: 1
5
+ hosts: ['127.0.0.1']
6
+ ports: [2203]
7
+ test_worker:
8
+ iothreads: 1
9
+ hosts: ['127.0.0.1']
10
+ ports: [2203]
11
+ broker:
12
+ iothreads: 1
13
+ frontend:
14
+ hosts: ['127.0.0.1']
15
+ ports: [<%= (2200..2202).to_a.join(', ') %>]
16
+ backend:
17
+ host: '127.0.0.1'
18
+ port: 2203
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
+ require 'zmq_jobs'
3
+ message = lambda{|num|"Message ##{num}"}
4
+ index = 0
5
+
6
+ Signal.trap('INT') do
7
+ publisher.stop
8
+ end
9
+
10
+ publisher = ZmqJobs::Socket::Pub.new(
11
+ 'host' => '127.0.0.1',
12
+ 'port' => 2200
13
+ )
14
+ publisher.run do |socket|
15
+ msg = message.call(index)
16
+ socket.send_string(msg)
17
+ puts "Send message: #{msg}"
18
+ index += 1
19
+ sleep 2
20
+ end.terminate
@@ -0,0 +1,11 @@
1
+ require 'zmq_jobs'
2
+ class Default < ZmqJobs::Worker::Base
3
+ def execute message
4
+ logger.info 'Start execute job'
5
+ logger.info message
6
+ sleep 4
7
+ logger.info 'Finished execute job'
8
+ end
9
+ end
10
+
11
+ Default.cmd(ARGV) if $0 == __FILE__
@@ -0,0 +1,11 @@
1
+ require 'zmq_jobs'
2
+ class TestWorker < ZmqJobs::Worker::Base
3
+ def execute message
4
+ logger.info 'Start execute job'
5
+ logger.info message
6
+ sleep 4
7
+ logger.info 'Finished execute job'
8
+ end
9
+ end
10
+
11
+ TestWorker.cmd(ARGV) if $0 == __FILE__
data/lib/command.rb ADDED
@@ -0,0 +1,172 @@
1
+ require 'optparse'
2
+ require 'daemons'
3
+ require 'yaml'
4
+ require 'erb'
5
+
6
+ module ZmqJobs
7
+ class Command
8
+ attr_reader :daemonize, :monitor, :config_file, :execute_dir, :options
9
+ DEVICES = {'broker' => Broker, 'balancer' => Balancer}
10
+
11
+ def self.define_properties options
12
+ options.each do |property, value|
13
+ define_method(property.to_sym) do |*args|
14
+ value
15
+ end
16
+ end
17
+ end
18
+
19
+ def initialize(args)
20
+ raise 'You can not create instance of abstract class' if self.class == Command
21
+ @daemonize = false
22
+ @monitor = false
23
+ @execute_dir = Dir.pwd
24
+ @pid_dir = './tmp'
25
+ @config_file = './config/zmq_jobs.yml'
26
+ @options = read_config_file
27
+
28
+ if args.empty?
29
+ puts opts_parser
30
+ exit 1
31
+ else
32
+ @args = opts_parser.parse!(args)
33
+ end
34
+ end
35
+
36
+ def start
37
+ start_daemon(type, daemon_config(type))
38
+ end
39
+
40
+ protected
41
+ def opts_parser
42
+ opts_parser_builder
43
+ end
44
+
45
+ def opts_parser_builder
46
+ OptionParser.new do |opts|
47
+ opts.banner = opts_banner
48
+ opts.separator ''
49
+ opts.on('-h', '--help', 'Show this message') do
50
+ puts opts
51
+ exit 1
52
+ end
53
+ opts.on('-m', '--monitor', 'Start monitor process.') do
54
+ @monitor = true
55
+ end
56
+ opts.on('-d', '--daemonize', "Daemonize the #{type} process") do
57
+ @daemonize = true
58
+ end
59
+ opts.on('-c CONFIG', '--config CONFIG', "Use config file, default: #{config_file}") do |config|
60
+ @config_file = config
61
+ end
62
+ yield opts if block_given?
63
+ end
64
+ end
65
+
66
+ def opts_banner
67
+ "Usage: #{type} <start|stop|restart> [options]"
68
+ end
69
+
70
+ def start_daemon daemon_name, config
71
+ return false unless config
72
+ Daemons.run_proc(
73
+ daemon_name,
74
+ {
75
+ :multiple => false,
76
+ :dir_mode => :normal,
77
+ :monitor => monitor,
78
+ :ARGV => @args,
79
+ :ontop => !daemonize
80
+ }
81
+ ) do
82
+ daemon_class(daemon_name).new(config).start
83
+ end
84
+ true
85
+ end
86
+
87
+ def read_config_file
88
+ YAML.load(ERB.new(File.new(File.expand_path(config_file, execute_dir)).read).result)
89
+ end
90
+
91
+ def daemon_config name
92
+ options[name] || (
93
+ ::ZmqJobs.logger.info("#{type.capitalize} '#{name}' not found in config file") and
94
+ return false
95
+ )
96
+ end
97
+ end
98
+
99
+ class BrokerCommand < Command
100
+ define_properties :type => 'broker', :daemon_class => Broker
101
+ end
102
+
103
+ class BalancerCommand < Command
104
+ define_properties :type => 'balancer', :daemon_class => Balancer
105
+ end
106
+
107
+ class WorkerCommand < Command
108
+ define_properties :type => 'worker'
109
+
110
+ def start
111
+ ::ZmqJobs.logger.info('You do not have any workers to start') if workers_to_start.size < 1
112
+
113
+ raise ArgumentError.new(
114
+ 'You can not start more then one worker without -d option'
115
+ ) if workers_to_start.size > 1 && !daemonize
116
+
117
+ success = workers_to_start.map{|worker|
118
+ preload_worker_class(daemon_classname(worker))
119
+ start_daemon(worker, daemon_config(worker))
120
+ }.inject(&:'&&')
121
+
122
+ ::ZmqJobs.logger.info('One or more workers do not started') unless success
123
+ end
124
+
125
+ protected
126
+ def preload_worker_class classname
127
+ worker_class_dir = File.expand_path(options['workers_dir'], execute_dir)
128
+ Kernel.require(
129
+ "#{worker_class_dir}/#{ActiveSupport::Inflector.underscore(classname)}"
130
+ ) unless Kernel.const_defined?(classname)
131
+ end
132
+
133
+ def opts_parser
134
+ opts_parser_builder do |opts|
135
+ opts.on('-w', '--workers LIST', 'Workers which have to run.') do |workers|
136
+ @workers = workers.split(',')
137
+ end
138
+ end
139
+ end
140
+
141
+ def daemon_config name
142
+ options['workers'][name] || (
143
+ ::ZmqJobs.logger.info("#{type.capitalize} '#{name}' not found in config file") and
144
+ return nil
145
+ )
146
+ end
147
+
148
+ def daemon_class name=nil
149
+ ActiveSupport::Inflector.constantize(daemon_classname(name))
150
+ end
151
+
152
+ def daemon_classname name
153
+ ActiveSupport::Inflector.camelize(name, true)
154
+ end
155
+
156
+ def all_workers
157
+ options['workers'].keys
158
+ end
159
+
160
+ def input_workers
161
+ @workers
162
+ end
163
+
164
+ def workers_to_start
165
+ @workers_to_start ||= if !input_workers || input_workers.empty?
166
+ all_workers
167
+ else
168
+ input_workers.select{|w|all_workers.include?(w)}
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,5 @@
1
+ module ZmqJobs
2
+ class Balancer < Device
3
+
4
+ end
5
+ end
@@ -0,0 +1,20 @@
1
+ module ZmqJobs
2
+ class Broker < Device
3
+ protected
4
+ def start_device
5
+ @device = ZMQ::Device.new(ZMQ::FORWARDER, frontend.socket, backend.socket)
6
+ end
7
+
8
+ def create_frontend
9
+ config = frontend_options
10
+ config['context'] = context
11
+ Socket::Sub.new(config).connect
12
+ end
13
+
14
+ def create_backend
15
+ config = backend_options
16
+ config['context'] = context
17
+ Socket::Pub.new(config).connect
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,65 @@
1
+ module ZmqJobs
2
+ class Device
3
+ class << self
4
+ def start options
5
+ new(options).start
6
+ end
7
+ end
8
+
9
+ attr_reader :options, :device
10
+
11
+ def initialize options
12
+ @options = options.assert_valid_keys('iothreads', 'frontend', 'backend')
13
+ end
14
+
15
+ def context
16
+ @context ||= ZMQ::Context.create(options['iothreads'])
17
+ end
18
+
19
+ def start
20
+ trap('TERM'){stop;Process.exit}
21
+ trap('INT'){stop;Process.exit}
22
+ logger.info "#{self.class} is starting ..."
23
+ start_device
24
+ end
25
+
26
+ def stop
27
+ frontend.disconnect
28
+ backend.disconnect
29
+ #context.terminate
30
+ logger.info 'Exiting...'
31
+ end
32
+
33
+ def frontend
34
+ @frontent ||= create_frontend
35
+ end
36
+
37
+ def backend
38
+ @backend ||= create_backend
39
+ end
40
+
41
+ def create_frontend
42
+ end
43
+
44
+ def create_backend
45
+ end
46
+
47
+ protected
48
+ def start_device
49
+ end
50
+
51
+ def frontend_options
52
+ options['frontend'].
53
+ assert_valid_keys('hosts', 'ports', 'subscribe', 'linger')
54
+ end
55
+
56
+ def backend_options
57
+ options['backend'].
58
+ assert_valid_keys('host', 'port')
59
+ end
60
+
61
+ def logger
62
+ ::ZmqJobs.logger
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,93 @@
1
+ module ZmqJobs
2
+ module Socket
3
+ class Error < RuntimeError;end
4
+ class Base
5
+ attr_reader :socket, :options
6
+
7
+ def initialize options={}
8
+ iothreads = options['iothreads'] ? options['iothreads'].to_i : 1
9
+ @context = options.delete('context') || ZMQ::Context.create(iothreads)
10
+ raise Error.new('Can not create context') unless @context
11
+ @options = default_options.merge(options)
12
+ @socket = @context.socket(ZMQ::PUB)
13
+ @running = false
14
+ end
15
+
16
+ def create_link url
17
+ end
18
+
19
+ def connect
20
+ urls.each{|url|assert(create_link(url))}
21
+ @connected = true
22
+ self
23
+ end
24
+
25
+ def disconnect
26
+ socket.close if connected?
27
+ @connected = false
28
+ self
29
+ end
30
+
31
+ def run
32
+ @running = true
33
+ connect
34
+
35
+ loop do
36
+ yield socket
37
+ break unless running?
38
+ end
39
+
40
+ self
41
+ end
42
+
43
+ def stop
44
+ @running = false
45
+ disconnect
46
+ end
47
+
48
+ def terminate
49
+ @context.terminate if @context && @context.respond_to?(:terminate)
50
+ end
51
+
52
+ def running?
53
+ !!@running
54
+ end
55
+
56
+ def connected?
57
+ !!@connected
58
+ end
59
+
60
+ protected
61
+ def assert(rc)
62
+ raise Error.new(
63
+ "Operation failed, errno [#{ZMQ::Util.errno}] description [#{ZMQ::Util.error_string}]"
64
+ ) unless ZMQ::Util.resultcode_ok?(rc)
65
+ end
66
+
67
+ def urls
68
+ u = []
69
+ hosts.each do |host|
70
+ ports.each do |port|
71
+ u << "tcp://#{host}:#{port}"
72
+ end
73
+ end
74
+ u
75
+ end
76
+
77
+ def hosts
78
+ options['hosts'].is_a?(Array) ? options['hosts'] : [options['hosts']]
79
+ end
80
+
81
+ def ports
82
+ options['ports'].is_a?(Array) ? options['ports'] : [options['ports']]
83
+ end
84
+
85
+ def default_options
86
+ {
87
+ 'hosts' => '*',
88
+ 'ports' => 2200
89
+ }
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,33 @@
1
+ module ZmqJobs
2
+ module Socket
3
+ class Pub < Base
4
+ def initialize options={}
5
+ super(options)
6
+ @socket = @context.socket(ZMQ::PUB)
7
+ end
8
+
9
+ def create_link url
10
+ socket.bind(url).tap do
11
+ sleep 1
12
+ ::ZmqJobs.logger.info "Publisher have started at #{url}"
13
+ end
14
+ end
15
+
16
+ private
17
+ def hosts
18
+ options['host'].is_a?(Array) ? [options['host'].first] : [options['host']]
19
+ end
20
+
21
+ def ports
22
+ options['port'].is_a?(Array) ? [options['port'].first] : [options['port']]
23
+ end
24
+
25
+ def default_options
26
+ {
27
+ 'host' => '*',
28
+ 'port' => 2200
29
+ }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ module ZmqJobs
2
+ module Socket
3
+ class Sub < Base
4
+ def initialize options={}
5
+ super(options)
6
+ @socket = @context.socket(ZMQ::SUB)
7
+ assert(socket.setsockopt(ZMQ::LINGER, self.options['linger'])) if self.options['linger']
8
+ assert(socket.setsockopt(ZMQ::SUBSCRIBE, self.options['subscribe'])) if self.options['subscribe']
9
+ end
10
+
11
+ def create_link url
12
+ socket.connect(url).tap do
13
+ ::ZmqJobs.logger.info "Subscriber have started at #{url}"
14
+ end
15
+ end
16
+
17
+ protected
18
+ def default_options
19
+ {
20
+ 'linger' => 0,
21
+ 'subscribe' => '',
22
+ 'hosts' => ['127.0.0.1'],
23
+ 'ports' => [2200]
24
+ }
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module ZmqJobs
2
+ VERSION = "0.0.1.alpha"
3
+ end
@@ -0,0 +1,59 @@
1
+ module ZmqJobs
2
+ module Worker
3
+ class Base
4
+ attr_reader :options
5
+ class << self
6
+ def cmd args
7
+ count = args[2].to_i || 0
8
+ options = {
9
+ 'hosts' => [args[0]],
10
+ 'ports' => (args[1].to_i..(args[1].to_i + count)).to_a
11
+ }
12
+ options['iothreads'] = args[3] if args[3]
13
+ start(options)
14
+ end
15
+
16
+ def start options
17
+ new(options).start
18
+ end
19
+ end
20
+
21
+ def initialize options={}
22
+ @options = options
23
+ end
24
+
25
+ def start
26
+ trap('TERM'){stop}
27
+ trap('INT'){stop}
28
+ logger.info "#{self.class} is starting ..."
29
+
30
+ subscriber.run do |socket|
31
+ message = ''
32
+ rc = socket.recv_string(message, ZMQ::NOBLOCK)
33
+ if ZMQ::Util.resultcode_ok?(rc)
34
+ #message = BSON.deserialize(bson)
35
+ execute_job message
36
+ end
37
+ end
38
+ end
39
+
40
+ def stop
41
+ logger.info "Exiting..."
42
+ subscriber.stop
43
+ #subscriber.terminate
44
+ end
45
+
46
+ def execute_job message
47
+ execute(message)
48
+ end
49
+
50
+ def subscriber
51
+ @subscriber ||= Socket::Sub.new(options)
52
+ end
53
+
54
+ def logger
55
+ ::ZmqJobs.logger
56
+ end
57
+ end
58
+ end
59
+ end
data/lib/zmq_jobs.rb ADDED
@@ -0,0 +1,52 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup :default, (ENV['RACK_ENV'] || 'development')
4
+ require 'yaml'
5
+ require 'active_support'
6
+ require 'active_support/core_ext/hash/keys'
7
+ require 'ffi-rzmq'
8
+ require 'logger'
9
+
10
+ module ZmqJobs
11
+ extend self
12
+ extend ActiveSupport::Autoload
13
+
14
+ autoload_under 'devices' do
15
+ autoload :Device
16
+ autoload :Balancer
17
+ autoload :Broker
18
+ end
19
+
20
+ module Worker
21
+ extend ActiveSupport::Autoload
22
+
23
+ autoload :Base
24
+ end
25
+
26
+ module Socket
27
+ extend ActiveSupport::Autoload
28
+
29
+ autoload :Base
30
+ autoload :Pub
31
+ autoload :Sub
32
+ end
33
+
34
+ def logger
35
+ @logger = default_logger unless defined?(@logger)
36
+ @logger
37
+ end
38
+
39
+ def logger=(logger)
40
+ case logger
41
+ when Logger then @logger = logger
42
+ when false, nil then @logger = nil
43
+ end
44
+ end
45
+
46
+ protected
47
+ def default_logger
48
+ defined?(Rails) && Rails.respond_to?(:logger) ? Rails.logger : ::Logger.new($stdout)
49
+ end
50
+ end
51
+
52
+ require 'command'
@@ -0,0 +1,45 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe ZmqJobs::BrokerCommand do
4
+ let(:command) do
5
+ ZmqJobs::BrokerCommand.any_instance.stub(:read_config_file => options, :start => true)
6
+ ZmqJobs::BrokerCommand.new(args)
7
+ end
8
+ let(:options){{:key1 => :value1, :key2 => :value2}}
9
+
10
+ context 'without option' do
11
+ let(:args){['start']}
12
+
13
+ specify{command.daemonize.should be_false}
14
+ specify{command.monitor.should be_false}
15
+ specify{command.config_file.should == './config/zmq_jobs.yml'}
16
+ specify{command.execute_dir.should == Dir.pwd}
17
+ specify{command.options.should == options}
18
+ specify{command.type.should == 'broker'}
19
+ specify{command.daemon_class.should == ZmqJobs::Broker}
20
+ end
21
+
22
+ context 'with option -d' do
23
+ let(:args){['start', '-d']}
24
+
25
+ specify{command.daemonize.should be_true}
26
+ specify{command.monitor.should be_false}
27
+ specify{command.config_file.should == './config/zmq_jobs.yml'}
28
+ end
29
+
30
+ context 'with option -m' do
31
+ let(:args){['start', '-m']}
32
+
33
+ specify{command.daemonize.should be_false}
34
+ specify{command.monitor.should be_true}
35
+ specify{command.config_file.should == './config/zmq_jobs.yml'}
36
+ end
37
+
38
+ context 'with option -c' do
39
+ let(:args){['start', '-c', 'bla-bla-bla']}
40
+
41
+ specify{command.daemonize.should be_false}
42
+ specify{command.monitor.should be_false}
43
+ specify{command.config_file.should == 'bla-bla-bla'}
44
+ end
45
+ end
@@ -0,0 +1,7 @@
1
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
+ require "rspec"
3
+ require 'zmq_jobs'
4
+
5
+ RSpec.configure do |config|
6
+ config.mock_with :rspec
7
+ end
data/zmq_jobs.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "zmq_jobs/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "zmq_jobs"
7
+ s.version = ZmqJobs::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Undr"]
10
+ s.email = ["undr@yandex.ru"]
11
+ s.homepage = "http://github.com/undr/zmq_jobs"
12
+ s.summary = %q{ZeroMQ-based queue system for background job}
13
+ s.description = %q{ZeroMQ-based queue system for background job}
14
+
15
+ s.rubyforge_project = "zmq_jobs"
16
+
17
+ s.add_development_dependency "rspec", ">= 2"
18
+ s.add_development_dependency "yard", "~> 0.6.0"
19
+ s.add_development_dependency "ruby-debug19"
20
+
21
+ s.add_dependency "bundler", "~> 1.0.0"
22
+ s.add_dependency "rake"
23
+ s.add_dependency "ffi"
24
+ s.add_dependency "ffi-rzmq"
25
+ s.add_dependency "activesupport"
26
+ s.add_dependency "daemons"
27
+
28
+ s.files = `git ls-files`.split("\n")
29
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
30
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
31
+ s.require_paths = ["lib"]
32
+ end
metadata ADDED
@@ -0,0 +1,181 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zmq_jobs
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: 6
5
+ version: 0.0.1.alpha
6
+ platform: ruby
7
+ authors:
8
+ - Undr
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-11-10 00:00:00 +07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "2"
25
+ type: :development
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: yard
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: 0.6.0
36
+ type: :development
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: ruby-debug19
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: bundler
51
+ prerelease: false
52
+ requirement: &id004 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ~>
56
+ - !ruby/object:Gem::Version
57
+ version: 1.0.0
58
+ type: :runtime
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: rake
62
+ prerelease: false
63
+ requirement: &id005 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ type: :runtime
70
+ version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
72
+ name: ffi
73
+ prerelease: false
74
+ requirement: &id006 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ type: :runtime
81
+ version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
83
+ name: ffi-rzmq
84
+ prerelease: false
85
+ requirement: &id007 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: "0"
91
+ type: :runtime
92
+ version_requirements: *id007
93
+ - !ruby/object:Gem::Dependency
94
+ name: activesupport
95
+ prerelease: false
96
+ requirement: &id008 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: "0"
102
+ type: :runtime
103
+ version_requirements: *id008
104
+ - !ruby/object:Gem::Dependency
105
+ name: daemons
106
+ prerelease: false
107
+ requirement: &id009 !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: "0"
113
+ type: :runtime
114
+ version_requirements: *id009
115
+ description: ZeroMQ-based queue system for background job
116
+ email:
117
+ - undr@yandex.ru
118
+ executables:
119
+ - broker
120
+ - worker
121
+ extensions: []
122
+
123
+ extra_rdoc_files: []
124
+
125
+ files:
126
+ - .gitignore
127
+ - .rspec
128
+ - Gemfile
129
+ - README
130
+ - Rakefile
131
+ - bin/broker
132
+ - bin/worker
133
+ - config/zmq_jobs.yml
134
+ - examples/config/zmq_jobs.yml
135
+ - examples/publisher.rb
136
+ - examples/workers/default.rb
137
+ - examples/workers/test_worker.rb
138
+ - lib/command.rb
139
+ - lib/zmq_jobs.rb
140
+ - lib/zmq_jobs/devices/balancer.rb
141
+ - lib/zmq_jobs/devices/broker.rb
142
+ - lib/zmq_jobs/devices/device.rb
143
+ - lib/zmq_jobs/socket/base.rb
144
+ - lib/zmq_jobs/socket/pub.rb
145
+ - lib/zmq_jobs/socket/sub.rb
146
+ - lib/zmq_jobs/version.rb
147
+ - lib/zmq_jobs/worker/base.rb
148
+ - spec/lib/command_spec.rb
149
+ - spec/spec_helper.rb
150
+ - zmq_jobs.gemspec
151
+ has_rdoc: true
152
+ homepage: http://github.com/undr/zmq_jobs
153
+ licenses: []
154
+
155
+ post_install_message:
156
+ rdoc_options: []
157
+
158
+ require_paths:
159
+ - lib
160
+ required_ruby_version: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: "0"
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ none: false
168
+ requirements:
169
+ - - ">"
170
+ - !ruby/object:Gem::Version
171
+ version: 1.3.1
172
+ requirements: []
173
+
174
+ rubyforge_project: zmq_jobs
175
+ rubygems_version: 1.6.2
176
+ signing_key:
177
+ specification_version: 3
178
+ summary: ZeroMQ-based queue system for background job
179
+ test_files:
180
+ - spec/lib/command_spec.rb
181
+ - spec/spec_helper.rb