rabbit_jobs 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,6 +3,7 @@
3
3
  .bundle
4
4
  .config
5
5
  .yardoc
6
+ .DS_Store
6
7
  Gemfile.lock
7
8
  InstalledFiles
8
9
  _yardoc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format documentation
data/Gemfile CHANGED
@@ -1,4 +1,13 @@
1
- source 'https://rubygems.org'
1
+ source :rubygems
2
2
 
3
- # Specify your gem's dependencies in rabbit_jobs.gemspec
4
3
  gemspec
4
+
5
+ gem 'rabbit_jobs', :path => './'
6
+
7
+ group :development do
8
+ gem 'rspec', '~> 2.8'
9
+ gem 'rr'
10
+ gem 'autotest'
11
+ # gem 'fs-event'
12
+ gem 'simplecov', require: false
13
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'bundler/setup'
3
+ require 'rabbit_jobs'
4
+ require 'json'
5
+
6
+ RabbitJobs.configure do |c|
7
+ c.host "127.0.0.1"
8
+
9
+ c.exchange 'test_exchange', durable: true, auto_delete: false
10
+
11
+ c.queue 'rabbit_jobs_test1', durable: true, auto_delete: false, ack: true, arguments: {'x-ha-policy' => 'all'}
12
+ c.queue 'rabbit_jobs_test2', durable: true, auto_delete: false, ack: true, arguments: {'x-ha-policy' => 'all'}
13
+ c.queue 'rabbit_jobs_test3', durable: true, auto_delete: false, ack: true, arguments: {'x-ha-policy' => 'all'}
14
+ end
15
+
16
+ puts JSON.pretty_generate(RabbitJobs.config.to_hash)
17
+
18
+ puts JSON.pretty_generate(RabbitJobs.config.queues)
19
+
20
+ # 10.times {
21
+ RabbitJobs.enqueue_to('rabbit_jobs_test1', Integer, 'to_s')
22
+ # }
@@ -0,0 +1,45 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module RabbitJobs
4
+ module AmqpHelpers
5
+
6
+ # Calls given block with initialized amqp
7
+
8
+ def amqp_with_exchange(&block)
9
+ raise ArgumentError unless block
10
+
11
+ AMQP.start(host: RabbitJobs.config.host) do |connection|
12
+ channel = AMQP::Channel.new(connection)
13
+
14
+ channel.on_error do |ch, channel_close|
15
+ puts "Channel-level error: #{channel_close.reply_text}, shutting down..."
16
+ connection.close { EM.stop }
17
+ end
18
+
19
+ exchange = channel.direct(RabbitJobs.config[:exchange], RabbitJobs.config[:exchange_params])
20
+
21
+ # go work
22
+ block.call(connection, exchange)
23
+ end
24
+ end
25
+
26
+ def amqp_with_queue(routing_key, &block)
27
+
28
+ raise ArgumentError unless routing_key && block
29
+
30
+ amqp_with_exchange do |connection, exchange|
31
+ queue = exchange.channel.queue(RabbitJobs.config.queue_name(routing_key), RabbitJobs.config[:queues][routing_key])
32
+ queue.bind(exchange, :routing_key => routing_key)
33
+
34
+ # go work
35
+ block.call(connection, queue)
36
+ end
37
+ end
38
+
39
+ def make_queue(exchange, routing_key)
40
+ queue = exchange.channel.queue(RabbitJobs.config.queue_name(routing_key), RabbitJobs.config[:queues][routing_key])
41
+ queue.bind(exchange, :routing_key => routing_key)
42
+ queue
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,122 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'yaml'
3
+
4
+ module RabbitJobs
5
+
6
+ extend self
7
+
8
+ def configure(&block)
9
+ @@configuration ||= Configuration.new
10
+ block.call(@@configuration)
11
+ end
12
+
13
+ def config
14
+ @@configuration ||= load_config
15
+ end
16
+
17
+ def load_config
18
+ self.configure do |c|
19
+ c.host 'localhost'
20
+ c.exchange 'rabbit_jobs', auto_delete: false, durable: true
21
+ c.queue 'default', auto_delete: false, ack: true, durable: true
22
+ end
23
+ @@configuration
24
+ end
25
+
26
+ class Configuration
27
+ include Helpers
28
+
29
+ DEFAULT_QUEUE_PARAMS = {
30
+ auto_delete: false,
31
+ durable: true,
32
+ ack: true
33
+ }
34
+
35
+ DEFAULT_EXCHANGE_PARAMS = {
36
+ auto_delete: false,
37
+ durable: true
38
+ }
39
+
40
+ DEFAULT_MESSAGE_PARAMS = {
41
+ persistent: true,
42
+ nowait: false,
43
+ immediate: false
44
+ }
45
+
46
+ def to_hash
47
+ @data.dup
48
+ end
49
+
50
+ def initialize
51
+ @data = {
52
+ host: 'localhost',
53
+ exchange: 'rabbit_jobs',
54
+ exchange_params: DEFAULT_EXCHANGE_PARAMS,
55
+ queues: {}
56
+ }
57
+ end
58
+
59
+ def [](name)
60
+ @data[name]
61
+ end
62
+
63
+ def host(value = nil)
64
+ if value
65
+ raise ArgumentError unless value.is_a?(String) && value != ""
66
+ @data[:host] = value.to_s
67
+ else
68
+ @data[:host]
69
+ end
70
+ end
71
+
72
+ def exchange(value = nil, params = {})
73
+ if value
74
+ raise ArgumentError unless value.is_a?(String) && value != ""
75
+ @data[:exchange] = value
76
+ @data[:exchange_params] = DEFAULT_EXCHANGE_PARAMS.merge(params)
77
+ else
78
+ @data[:exchange]
79
+ end
80
+ end
81
+
82
+ def queue(name, params = {})
83
+ raise ArgumentError.new("name is #{name.inspect}") unless name && name.is_a?(String) && name != ""
84
+ raise ArgumentError.new("params is #{params.inspect}") unless params && params.is_a?(Hash)
85
+
86
+ if @data[:queues][name]
87
+ @data[:queues][name].merge!(params)
88
+ else
89
+ @data[:queues][name] = DEFAULT_QUEUE_PARAMS.merge(params)
90
+ end
91
+ end
92
+
93
+ def routing_keys
94
+ @data[:queues].keys
95
+ end
96
+
97
+ def queue_name(routing_key)
98
+ [@data[:exchange], routing_key].join('#')
99
+ end
100
+
101
+ def load_file(filename)
102
+ load_yaml(File.read(filename))
103
+ end
104
+
105
+ def load_yaml(text)
106
+ convert_yaml_config(YAML.load(text))
107
+ end
108
+
109
+ def convert_yaml_config(yaml)
110
+ if yaml['rabbit_jobs']
111
+ convert_yaml_config(yaml['rabbit_jobs'])
112
+ else
113
+ @data = {host: nil, exchange: nil, queues: {}}
114
+ host yaml['host']
115
+ exchange yaml['exchange'], symbolize_keys!(yaml['exchange_params'])
116
+ yaml['queues'].each do |name, params|
117
+ queue name, symbolize_keys!(params) || {}
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,53 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module RabbitJobs
4
+ module Helpers
5
+ def symbolize_keys!(hash)
6
+ hash.inject({}) do |options, (key, value)|
7
+ options[(key.to_sym rescue key) || key] = value
8
+ options
9
+ end
10
+ end
11
+
12
+
13
+ # Tries to find a constant with the name specified in the argument string:
14
+ #
15
+ # constantize("Module") # => Module
16
+ # constantize("Test::Unit") # => Test::Unit
17
+ #
18
+ # The name is assumed to be the one of a top-level constant, no matter
19
+ # whether it starts with "::" or not. No lexical context is taken into
20
+ # account:
21
+ #
22
+ # C = 'outside'
23
+ # module M
24
+ # C = 'inside'
25
+ # C # => 'inside'
26
+ # constantize("C") # => 'outside', same as ::C
27
+ # end
28
+ #
29
+ # NameError is raised when the constant is unknown.
30
+ def constantize(camel_cased_word)
31
+ camel_cased_word = camel_cased_word.to_s
32
+
33
+ if camel_cased_word.include?('-')
34
+ camel_cased_word = classify(camel_cased_word)
35
+ end
36
+
37
+ names = camel_cased_word.split('::')
38
+ names.shift if names.empty? || names.first.empty?
39
+
40
+ constant = Object
41
+ names.each do |name|
42
+ args = Module.method(:const_get).arity != 1 ? [false] : []
43
+
44
+ if constant.const_defined?(name, *args)
45
+ constant = constant.const_get(name)
46
+ else
47
+ constant = constant.const_missing(name)
48
+ end
49
+ end
50
+ constant
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,43 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'json'
3
+
4
+ module RabbitJobs
5
+ class Job
6
+ include RabbitJobs::Helpers
7
+ include Logger
8
+
9
+ attr_accessor :params, :klass, :child
10
+
11
+ def initialize(payload)
12
+ begin
13
+ self.params = JSON.parse(payload)
14
+ klass_name = params.delete_at(0)
15
+ self.klass = constantize(klass_name)
16
+ rescue
17
+ log "JOB INIT ERROR at #{Time.now.to_s}:"
18
+ log $!.inspect
19
+ log $!.backtrace
20
+ log "message: #{payload.inspect}"
21
+ # Mailer.send(klass_name, params, $!)
22
+ end
23
+ end
24
+
25
+ def perform
26
+ if @child = fork
27
+ srand # Reseeding
28
+ log! "Forked #{@child} at #{Time.now} to process #{klass}.perform(#{ params.map(&:inspect).join(', ') })"
29
+ Process.wait(@child)
30
+ yield if block_given?
31
+ else
32
+ begin
33
+ # log 'before perform'
34
+ klass.perform(*params)
35
+ # log 'after perform'
36
+ rescue
37
+ puts $!.inspect
38
+ end
39
+ exit!
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,18 @@
1
+ module RabbitJobs
2
+ module Logger
3
+ extend self
4
+
5
+ def log(string)
6
+ puts string
7
+ end
8
+
9
+ def log!(string)
10
+ @@verbose ||= false
11
+ log(string) if RabbitJobs::Logger.verbose
12
+ end
13
+
14
+ class << self
15
+ attr_accessor :verbose
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,58 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'json'
4
+ require 'amqp'
5
+ require 'eventmachine'
6
+
7
+ module RabbitJobs
8
+ module Publisher
9
+ extend self
10
+ extend AmqpHelpers
11
+
12
+ def enqueue(klass, *params)
13
+ key = RabbitJobs.config.routing_keys.first
14
+ enqueue_to(key, klass, *params)
15
+ end
16
+
17
+ def enqueue_to(routing_key, klass, *params)
18
+ raise ArgumentError unless klass && routing_key
19
+
20
+ payload = ([klass.to_s] + params).to_json
21
+
22
+ amqp_with_exchange do |connection, exchange|
23
+
24
+ queue = make_queue(exchange, routing_key)
25
+
26
+ exchange.publish(payload, Configuration::DEFAULT_MESSAGE_PARAMS.merge({routing_key: routing_key})) {
27
+ connection.close { EM.stop }
28
+ }
29
+ end
30
+ end
31
+
32
+ # def spam
33
+ # payload = ([klass.to_s] + params).to_json
34
+
35
+ # amqp_with_exchange do |connection, exchange|
36
+ # 10000.times { |i| RabbitJobs.enqueue(RabbitJobs::TestJob, i) }
37
+ # exchange.publish(payload, RabbitJobs.config.publish_params.merge({routing_key: routing_key})) {
38
+ # connection.close { EM.stop }
39
+ # }
40
+ # end
41
+ # end
42
+
43
+ def purge_queue(routing_key)
44
+ raise ArgumentError unless routing_key
45
+
46
+ amqp_with_queue(routing_key) do |connection, queue|
47
+ queue.status do |number_of_messages, number_of_consumers|
48
+ queue.purge {
49
+ connection.close {
50
+ EM.stop
51
+ return number_of_messages
52
+ }
53
+ }
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,57 @@
1
+ # require 'resque/tasks'
2
+ # will give you the resque tasks
3
+
4
+ namespace :rj do
5
+ task :setup
6
+
7
+ desc "Start a Rabbit Jobs worker"
8
+ task :work => [ :preload, :setup ] do
9
+ require 'rabbit_jobs'
10
+
11
+ queues = (ENV['QUEUES'] || ENV['QUEUE']).to_s.split(',')
12
+
13
+ begin
14
+ worker = RabbitJobs::Worker.new(*queues)
15
+ RabbitJobs::Logger.verbose = true if ENV['VERBOSE']
16
+ # worker.very_verbose = ENV['VVERBOSE']
17
+ end
18
+
19
+ if ENV['BACKGROUND']
20
+ Process.daemon(true)
21
+ end
22
+
23
+ if ENV['PIDFILE']
24
+ File.open(ENV['PIDFILE'], 'w') { |f| f << worker.pid }
25
+ end
26
+
27
+ # worker.log "Starting worker #{worker.pid}"
28
+ # worker.verbose = true
29
+ worker.work 1
30
+ # worker.work(ENV['INTERVAL'] || 5) # interval, will block
31
+ end
32
+
33
+ desc "Start multiple Resque workers. Should only be used in dev mode."
34
+ task :workers do
35
+ threads = []
36
+
37
+ ENV['COUNT'].to_i.times do
38
+ threads << Thread.new do
39
+ system "rake resque:work"
40
+ end
41
+ end
42
+
43
+ threads.each { |thread| thread.join }
44
+ end
45
+
46
+ # Preload app files if this is Rails
47
+ task :preload => :setup do
48
+ if defined?(Rails) && Rails.respond_to?(:application)
49
+ # Rails 3
50
+ Rails.application.eager_load!
51
+ elsif defined?(Rails::Initializer)
52
+ # Rails 2.3
53
+ $rails_rake_task = false
54
+ Rails::Initializer.run :load_application_classes
55
+ end
56
+ end
57
+ end
@@ -1,3 +1,3 @@
1
1
  module RabbitJobs
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,104 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module RabbitJobs
4
+ class Worker
5
+ include AmqpHelpers
6
+ include Logger
7
+
8
+ # Workers should be initialized with an array of string queue
9
+ # names. The order is important: a Worker will check the first
10
+ # queue given for a job. If none is found, it will check the
11
+ # second queue name given. If a job is found, it will be
12
+ # processed. Upon completion, the Worker will again check the
13
+ # first queue given, and so forth. In this way the queue list
14
+ # passed to a Worker on startup defines the priorities of queues.
15
+ #
16
+ # If passed a single "*", this Worker will operate on all queues
17
+ # in alphabetical order. Queues can be dynamically added or
18
+ # removed without needing to restart workers using this method.
19
+ def initialize(*queues)
20
+ @queues = queues.map { |queue| queue.to_s.strip }.flatten.uniq
21
+ if @queues == ['*'] || @queues.empty?
22
+ @queues = RabbitJobs.config.routing_keys
23
+ end
24
+ end
25
+
26
+ def queues
27
+ @queues || ['default']
28
+ end
29
+
30
+ # Subscribes to channel and working on jobs
31
+ def work(time = 10)
32
+ startup
33
+
34
+ processed_count = 0
35
+ amqp_with_exchange do |connection, exchange|
36
+ exchange.channel.prefetch(1)
37
+
38
+ check_shutdown = Proc.new {
39
+ if @shutdown
40
+ log "Processed jobs: #{processed_count}"
41
+ log "Stopping worker..."
42
+ connection.close { EM.stop { exit! } }
43
+ end
44
+ }
45
+
46
+ queues.each do |routing_key|
47
+ queue = make_queue(exchange, routing_key)
48
+
49
+ log "Worker ##{Process.pid} <= #{exchange.name}##{routing_key}"
50
+
51
+ queue.subscribe(ack: true) do |metadata, payload|
52
+ @job = Job.new(payload)
53
+ @job.perform
54
+ metadata.ack
55
+ processed_count += 1
56
+ check_shutdown.call
57
+ end
58
+ end
59
+
60
+ EM.add_timer(time) do
61
+ self.shutdown
62
+ end
63
+
64
+ EM.add_periodic_timer(1) do
65
+ check_shutdown.call
66
+ end
67
+ end
68
+ end
69
+
70
+ def shutdown
71
+ @shutdown = true
72
+ end
73
+
74
+ def startup
75
+ # prune_dead_workers
76
+
77
+ # Fix buffering so we can `rake rj:work > resque.log` and
78
+ # get output from the child in there.
79
+ $stdout.sync = true
80
+
81
+ @shutdown = false
82
+
83
+ Signal.trap('TERM') { shutdown }
84
+ Signal.trap('INT') { shutdown! }
85
+ end
86
+
87
+ def shutdown!
88
+ shutdown
89
+ kill_child
90
+ end
91
+
92
+ def kill_child
93
+ if @job && @job.child
94
+ # log! "Killing child at #{@child}"
95
+ if Kernel.system("ps -o pid,state -p #{@job.child}")
96
+ Process.kill("KILL", @job.child) rescue nil
97
+ else
98
+ # log! "Child #{@child} not found, restarting."
99
+ # shutdown
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
data/lib/rabbit_jobs.rb CHANGED
@@ -1,5 +1,36 @@
1
- require "rabbit_jobs/version"
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'rabbit_jobs/version'
4
+
5
+ require 'rabbit_jobs/helpers'
6
+ require 'rabbit_jobs/amqp_helpers'
7
+ require 'rabbit_jobs/configuration'
8
+ require 'rabbit_jobs/logger'
9
+
10
+ require 'rabbit_jobs/job'
11
+ require 'rabbit_jobs/publisher'
12
+ require 'rabbit_jobs/worker'
2
13
 
3
14
  module RabbitJobs
4
- # Your code goes here...
5
- end
15
+ extend self
16
+
17
+ def enqueue(klass, *params)
18
+ RabbitJobs::Publisher.enqueue(klass, *params)
19
+ end
20
+
21
+ def enqueue_to(routing_key, klass, *params)
22
+ RabbitJobs::Publisher.enqueue_to(routing_key, klass, *params)
23
+ end
24
+
25
+ class TestJob < RabbitJobs::Job
26
+ def self.perform(*params)
27
+ # puts "processing in job: " + params.inspect
28
+ # sleep 0.1
29
+
30
+ # if rand(3) == 0
31
+ # puts "ERROR TEXT"
32
+ # raise "ERROR TEXT"
33
+ # end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
3
+ require 'rabbit_jobs/tasks'
data/rabbit_jobs.gemspec CHANGED
@@ -1,5 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/rabbit_jobs/version', __FILE__)
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'rabbit_jobs/version'
3
4
 
4
5
  Gem::Specification.new do |gem|
5
6
  gem.authors = ["Pavel Lazureykis"]
@@ -7,6 +8,7 @@ Gem::Specification.new do |gem|
7
8
  gem.description = %q{Background jobs on RabbitMQ}
8
9
  gem.summary = %q{Background jobs on RabbitMQ}
9
10
  gem.homepage = ""
11
+ gem.date = Time.now.strftime('%Y-%m-%d')
10
12
 
11
13
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
14
  gem.files = `git ls-files`.split("\n")
@@ -15,7 +17,5 @@ Gem::Specification.new do |gem|
15
17
  gem.require_paths = ["lib"]
16
18
  gem.version = RabbitJobs::VERSION
17
19
 
18
- gem.add_development_dependency "rspec", "~> 2.8"
19
-
20
20
  gem.add_dependency "amqp", "~> 0.9"
21
21
  end
@@ -0,0 +1,17 @@
1
+ rabbit_jobs:
2
+ host: example.com
3
+ exchange: 'my_exchange'
4
+ exchange_params:
5
+ durable: true
6
+ auto_delete: false
7
+ queues:
8
+ durable_queue:
9
+ durable: true
10
+ auto_delete: false
11
+ ack: true
12
+ arguments:
13
+ x-ha-policy: all
14
+ fast_queue:
15
+ durable: false
16
+ auto_delete: true
17
+ ack: false
@@ -0,0 +1,17 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+ require 'json'
4
+
5
+ describe RabbitJobs::Publisher do
6
+ it 'should publish message to queue' do
7
+
8
+ RabbitJobs.configure do |c|
9
+ # c.host "somehost.lan"
10
+ c.exchange 'test', auto_delete: true
11
+ c.queue 'rspec_queue', auto_delete: true
12
+ end
13
+
14
+ RabbitJobs.enqueue(Integer, 'some', 'other', 'params')
15
+ RabbitJobs::Publisher.purge_queue('rspec_queue').should == 1
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'simplecov'
3
+ SimpleCov.start {
4
+ add_filter "spec" # ignore gems
5
+ }
6
+
7
+ require 'rr'
8
+
9
+ require 'rabbit_jobs'
10
+
11
+ RSpec.configure do |config|
12
+ config.mock_with :rr
13
+ # or if that doesn't work due to a version incompatibility
14
+ # config.mock_with RR::Adapters::Rspec
15
+
16
+ config.before(:each) do
17
+ # clear config options
18
+ RabbitJobs.class_variable_set '@@configuration', nil
19
+ end
20
+ end
@@ -0,0 +1,89 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe RabbitJobs::Configuration do
5
+ it 'builds configuration from configure block' do
6
+ RabbitJobs.configure do |c|
7
+ c.host "somehost.lan"
8
+
9
+ c.exchange 'my_exchange', durable: true, auto_delete: false
10
+
11
+ c.queue 'durable_queue', durable: true, auto_delete: false, ack: true, arguments: {'x-ha-policy' => 'all'}
12
+ c.queue 'fast_queue', durable: false, auto_delete: true, ack: false
13
+ end
14
+
15
+ RabbitJobs.config.to_hash.should == {
16
+ host: "somehost.lan",
17
+ exchange: "my_exchange",
18
+ exchange_params: {
19
+ durable: true,
20
+ auto_delete: false
21
+ },
22
+ queues: {
23
+ "durable_queue" => {
24
+ durable: true,
25
+ auto_delete: false,
26
+ ack: true,
27
+ arguments: {"x-ha-policy"=>"all"}
28
+ },
29
+ "fast_queue" => {
30
+ durable: false,
31
+ auto_delete: true,
32
+ ack: false
33
+ },
34
+ }
35
+ }
36
+ end
37
+
38
+ it 'builds configuration from yaml' do
39
+ RabbitJobs.config.load_file(File.expand_path('../../fixtures/config.yml', __FILE__))
40
+
41
+ RabbitJobs.config.to_hash.should == {
42
+ host: "example.com",
43
+ exchange: "my_exchange",
44
+ exchange_params: {
45
+ durable: true,
46
+ auto_delete: false
47
+ },
48
+ queues: {
49
+ "durable_queue" => {
50
+ durable: true,
51
+ auto_delete: false,
52
+ ack: true,
53
+ arguments: {"x-ha-policy"=>"all"}
54
+ },
55
+ "fast_queue" => {
56
+ durable: false,
57
+ auto_delete: true,
58
+ ack: false
59
+ }
60
+ }
61
+ }
62
+ end
63
+
64
+ it 'use default config' do
65
+ RabbitJobs.config.to_hash.should == {
66
+ host: "localhost",
67
+ exchange: "rabbit_jobs",
68
+ exchange_params: {
69
+ auto_delete: false,
70
+ durable: true
71
+ },
72
+ queues: {
73
+ "default" => {
74
+ auto_delete: false,
75
+ ack: true,
76
+ durable: true
77
+ }
78
+ }
79
+ }
80
+ end
81
+
82
+ it 'returns settings on some methods' do
83
+ RabbitJobs.config.host.should == 'localhost'
84
+ RabbitJobs.config[:host].should == 'localhost'
85
+ RabbitJobs.config.routing_keys.should == ['default']
86
+ RabbitJobs.config.exchange.should == 'rabbit_jobs'
87
+ RabbitJobs.config.queue_name('default').should == 'rabbit_jobs#default'
88
+ end
89
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe RabbitJobs::Logger do
5
+ it '#log should write messages to stdout' do
6
+ mock($stdout).puts "hello"
7
+ RabbitJobs::Logger.log("hello")
8
+ end
9
+
10
+ it '#log! should not write messages to stdout in normal mode' do
11
+ RabbitJobs::Logger.verbose = false
12
+
13
+ dont_allow(RabbitJobs::Logger).log("hello")
14
+ RabbitJobs::Logger.log!("hello")
15
+ end
16
+
17
+ it '#log! should write messages to stdout in verbose mode' do
18
+ RabbitJobs::Logger.verbose = true
19
+
20
+ mock(RabbitJobs::Logger).log("hello")
21
+ RabbitJobs::Logger.log!("hello")
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ describe RabbitJobs do
4
+ it 'should pass enqueue methods to publisher' do
5
+ mock(RabbitJobs::Publisher).enqueue(Integer, 1, 2, "string")
6
+ RabbitJobs.enqueue(Integer, 1, 2, "string")
7
+
8
+ mock(RabbitJobs::Publisher).enqueue_to('default_queue', Integer, 1, 2, "string")
9
+ RabbitJobs.enqueue_to('default_queue', Integer, 1, 2, "string")
10
+ end
11
+ end
@@ -0,0 +1,49 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe RabbitJobs::Worker do
5
+ describe 'methods' do
6
+ before :each do
7
+ @worker = RabbitJobs::Worker.new
8
+ end
9
+
10
+ it '#initialize with default options' do
11
+ @worker.queues.should == ['default']
12
+ end
13
+
14
+ it '#startup' do
15
+ @worker.instance_variable_get('@shutdown').should_not == true
16
+
17
+ mock(Signal).trap('TERM')
18
+ mock(Signal).trap('INT')
19
+
20
+ @worker.startup
21
+
22
+ @worker.instance_variable_get('@shutdown').should_not == true
23
+ end
24
+
25
+ it '#shutdown should set @shutdown to true' do
26
+ @worker.instance_variable_get('@shutdown').should_not == true
27
+ @worker.shutdown
28
+ @worker.instance_variable_get('@shutdown').should == true
29
+ end
30
+
31
+ it '#shutdown! should kill child process' do
32
+ mock(@worker.kill_child)
33
+ mock(@worker.shutdown)
34
+
35
+ @worker.shutdown!
36
+ end
37
+
38
+ it '#kill_child' do
39
+ job = RabbitJobs::Job.new(['RabbitJobs'].to_json)
40
+ job.instance_variable_set '@child', 123123
41
+ @worker.instance_variable_set('@job', job)
42
+
43
+ mock(Kernel).system("ps -o pid,state -p #{123123}") { true }
44
+ mock(Process).kill("KILL", 123123)
45
+
46
+ @worker.kill_child
47
+ end
48
+ end
49
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rabbit_jobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-24 00:00:00.000000000 Z
12
+ date: 2012-01-27 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: rspec
16
- requirement: &70100539559980 !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ~>
20
- - !ruby/object:Gem::Version
21
- version: '2.8'
22
- type: :development
23
- prerelease: false
24
- version_requirements: *70100539559980
25
14
  - !ruby/object:Gem::Dependency
26
15
  name: amqp
27
- requirement: &70100539559360 !ruby/object:Gem::Requirement
16
+ requirement: &70147046160300 !ruby/object:Gem::Requirement
28
17
  none: false
29
18
  requirements:
30
19
  - - ~>
@@ -32,7 +21,7 @@ dependencies:
32
21
  version: '0.9'
33
22
  type: :runtime
34
23
  prerelease: false
35
- version_requirements: *70100539559360
24
+ version_requirements: *70147046160300
36
25
  description: Background jobs on RabbitMQ
37
26
  email:
38
27
  - lazureykis@gmail.com
@@ -41,13 +30,31 @@ extensions: []
41
30
  extra_rdoc_files: []
42
31
  files:
43
32
  - .gitignore
33
+ - .rspec
44
34
  - Gemfile
45
35
  - LICENSE
46
36
  - README.md
47
37
  - Rakefile
38
+ - examples/configuration.rb
48
39
  - lib/rabbit_jobs.rb
40
+ - lib/rabbit_jobs/amqp_helpers.rb
41
+ - lib/rabbit_jobs/configuration.rb
42
+ - lib/rabbit_jobs/helpers.rb
43
+ - lib/rabbit_jobs/job.rb
44
+ - lib/rabbit_jobs/logger.rb
45
+ - lib/rabbit_jobs/publisher.rb
46
+ - lib/rabbit_jobs/tasks.rb
49
47
  - lib/rabbit_jobs/version.rb
48
+ - lib/rabbit_jobs/worker.rb
49
+ - lib/tasks/rabbit_jobs.rake
50
50
  - rabbit_jobs.gemspec
51
+ - spec/fixtures/config.yml
52
+ - spec/integration/publisher_spec.rb
53
+ - spec/spec_helper.rb
54
+ - spec/unit/configuration_spec.rb
55
+ - spec/unit/logger_spec.rb
56
+ - spec/unit/rabbit_jobs_spec.rb
57
+ - spec/unit/worker_spec.rb
51
58
  homepage: ''
52
59
  licenses: []
53
60
  post_install_message:
@@ -72,4 +79,11 @@ rubygems_version: 1.8.15
72
79
  signing_key:
73
80
  specification_version: 3
74
81
  summary: Background jobs on RabbitMQ
75
- test_files: []
82
+ test_files:
83
+ - spec/fixtures/config.yml
84
+ - spec/integration/publisher_spec.rb
85
+ - spec/spec_helper.rb
86
+ - spec/unit/configuration_spec.rb
87
+ - spec/unit/logger_spec.rb
88
+ - spec/unit/rabbit_jobs_spec.rb
89
+ - spec/unit/worker_spec.rb