queuel 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/.cane +3 -0
  2. data/.gitignore +1 -1
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile.lock +112 -0
  6. data/Guardfile +22 -0
  7. data/README.md +17 -11
  8. data/Rakefile +7 -0
  9. data/lib/queuel.rb +50 -27
  10. data/lib/queuel/base/engine.rb +35 -0
  11. data/lib/queuel/base/message.rb +32 -0
  12. data/lib/queuel/base/poller.rb +161 -0
  13. data/lib/queuel/base/queue.rb +59 -0
  14. data/lib/queuel/client.rb +15 -3
  15. data/lib/queuel/configurator.rb +65 -0
  16. data/lib/queuel/introspect.rb +11 -0
  17. data/lib/queuel/iron_mq/engine.rb +11 -17
  18. data/lib/queuel/iron_mq/message.rb +5 -26
  19. data/lib/queuel/iron_mq/poller.rb +8 -111
  20. data/lib/queuel/iron_mq/queue.rb +13 -24
  21. data/lib/queuel/null/engine.rb +3 -7
  22. data/lib/queuel/null/message.rb +1 -16
  23. data/lib/queuel/null/poller.rb +2 -114
  24. data/lib/queuel/null/queue.rb +6 -9
  25. data/lib/queuel/version.rb +1 -1
  26. data/queuel.gemspec +10 -0
  27. data/spec/lib/queuel/base/queue_spec.rb +23 -0
  28. data/spec/lib/queuel/client_spec.rb +30 -0
  29. data/spec/lib/queuel/configurator_spec.rb +32 -0
  30. data/spec/lib/queuel/iron_mq/engine_spec.rb +28 -0
  31. data/spec/lib/queuel/iron_mq/message_spec.rb +2 -2
  32. data/spec/lib/queuel/iron_mq/poller_spec.rb +15 -1
  33. data/spec/lib/queuel/iron_mq/queue_spec.rb +2 -2
  34. data/spec/lib/queuel_spec.rb +12 -7
  35. data/spec/spec_helper.rb +4 -0
  36. data/spec/support/engine_shared_example.rb +4 -2
  37. data/spec/support/message_shared_example.rb +2 -11
  38. data/spec/support/poller_shared_example.rb +23 -57
  39. data/spec/support/queue_shared_example.rb +14 -1
  40. metadata +163 -4
@@ -1,12 +1,8 @@
1
1
  module Queuel
2
2
  module Null
3
- class Engine
4
- def initialize(*)
5
- end
6
-
7
- def queue(*)
8
- Queue.new
9
- end
3
+ class Engine < Base::Engine
4
+ def client; end
5
+ def client_klass; end
10
6
  end
11
7
  end
12
8
  end
@@ -1,21 +1,6 @@
1
- require 'forwardable'
2
1
  module Queuel
3
2
  module Null
4
- class Message
5
- def initialize(id, body, queue = nil)
6
- self.id = id
7
- self.body = body
8
- self.queue = queue
9
- end
10
-
11
- attr_reader :id
12
- attr_reader :queue
13
- attr_reader :body
14
-
15
- private
16
- attr_writer :id
17
- attr_writer :queue
18
- attr_writer :body
3
+ class Message < Base::Message
19
4
  end
20
5
  end
21
6
  end
@@ -1,120 +1,8 @@
1
1
  require 'timeout'
2
2
  module Queuel
3
3
  module Null
4
- class Poller
5
- # q is here for similar API, but not needed in THIS
6
- # class
7
- def initialize(q, options, block)
8
- self.options = options || {}
9
- self.block = block
10
- self.tries = 0
11
- self.continue_looping = true
12
- end
13
-
14
- def poll
15
- choose_looper do |msg|
16
- if msg.nil?
17
- tried
18
- quit_looping! if break_if_nil? || maxed_tried?
19
- sleep(sleep_time)
20
- end
21
- !msg.nil?
22
- end
23
- end
24
-
25
- protected
26
- attr_accessor :tries
27
-
28
- private
29
- attr_accessor :queue
30
- attr_accessor :args
31
- attr_accessor :options
32
- attr_accessor :block
33
- attr_accessor :continue_looping
34
-
35
- def choose_looper(&loop_block)
36
- timeout? ? timeout_looper(loop_block) : looper(loop_block)
37
- end
38
-
39
- def timeout_looper(loop_block)
40
- Timeout.timeout(timeout) { looper(loop_block) }
41
- rescue Timeout::Error
42
- false
43
- end
44
-
45
- def looper(loop_block)
46
- while continue_looping? do
47
- loop_block.call(pop_new_message)
48
- end
49
- end
50
-
51
- def continue_looping?
52
- !!continue_looping
53
- end
54
-
55
- def quit_looping!
56
- self.continue_looping = false
57
- end
58
-
59
- def timeout
60
- options[:poll_timeout].to_i
61
- end
62
-
63
- def timeout?
64
- timeout > 0
65
- end
66
-
67
- def pop_new_message
68
- nil
69
- end
70
-
71
- def start_sleep_time
72
- 0.1
73
- end
74
-
75
- def sleep_time
76
- tries < 30 ? (start_sleep_time * tries) : 3
77
- end
78
-
79
- def reset_tries
80
- self.tries = 0
81
- end
82
-
83
- def maxed_tried?
84
- tries >= max_fails if max_fails_given?
85
- end
86
-
87
- def max_fails_given?
88
- max_fails > 0
89
- end
90
-
91
- def max_fails
92
- options[:max_consecutive_fails].to_i
93
- end
94
-
95
- def tried
96
- self.tries += 1
97
- end
98
-
99
- def break_if_nil?
100
- !!options.fetch(:break_if_nil, false)
101
- end
102
-
103
- def option_keys
104
- %w[break_if_nil poll_timeout max_consecutive_fails]
105
- end
106
-
107
- def my_options
108
- options.select { |key,_| option_keys.include? key.to_s }
109
- end
110
-
111
- def built_options
112
- options.merge default_args # intentional direction, force defaults
113
- end
114
-
115
- def default_args
116
- { n: 1 }
117
- end
4
+ class Poller < Base::Poller
5
+ alias built_options options
118
6
  end
119
7
  end
120
8
  end
@@ -1,19 +1,16 @@
1
1
  require 'queuel/null/poller'
2
2
  module Queuel
3
3
  module Null
4
- class Queue
5
- def initialize(*)
4
+ class Queue < Base::Queue
5
+ def peek(options = {})
6
+ []
6
7
  end
7
8
 
8
- # For IronMQ it should just be (message)
9
- def push(*)
9
+ def push(message)
10
10
  end
11
11
 
12
- def pop(*args, &block)
13
- end
14
-
15
- def receive(options = {}, &block)
16
- Poller.new(options, block).poll
12
+ # Nullify
13
+ def pop(options = {}, &block)
17
14
  end
18
15
  end
19
16
  end
@@ -1,3 +1,3 @@
1
1
  module Queuel
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/queuel.gemspec CHANGED
@@ -24,5 +24,15 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "simplecov"
25
25
  spec.add_development_dependency "iron_mq"
26
26
  spec.add_development_dependency "typhoeus"
27
+ spec.add_development_dependency "guard-bundler"
28
+ spec.add_development_dependency "guard-rspec"
29
+ spec.add_development_dependency "guard-cane"
30
+ spec.add_development_dependency "rb-inotify"
31
+ spec.add_development_dependency "rb-fsevent"
32
+ spec.add_development_dependency "rb-fchange"
33
+ spec.add_development_dependency "cane"
27
34
  spec.add_development_dependency "json", "~> 1.7.7"
35
+
36
+ spec.add_dependency "thread"
37
+ spec.add_dependency "mono_logger"
28
38
  end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+ module Queuel
3
+ module Base
4
+ describe Queue do
5
+ let(:client) { double "Client" }
6
+ let(:queue_name) { double "some_queue" }
7
+ subject { described_class.new client, queue_name }
8
+
9
+ its(:thread_count) { should == 1 }
10
+
11
+ it "fails on non-impleneted push" do
12
+ expect { subject.push("") }.to raise_error NotImplementedError
13
+ end
14
+
15
+ describe "polling" do
16
+ it "delegates polling to a new poller" do
17
+ Poller.any_instance.should_receive(:poll).once
18
+ subject.receive { |m| }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -8,6 +8,36 @@ module Queuel
8
8
  it { should respond_to :receive }
9
9
  it { should respond_to :with }
10
10
 
11
+ describe "fails without a queue" do
12
+ it "fails for push" do
13
+ expect { subject.push }.to raise_error NoQueueGivenError
14
+ end
15
+
16
+ it "fails for pop" do
17
+ expect { subject.pop }.to raise_error NoQueueGivenError
18
+ end
19
+
20
+ it "fails for receive" do
21
+ expect { subject.receive }.to raise_error NoQueueGivenError
22
+ end
23
+ end
24
+
25
+ describe "fails without a valid name queue" do
26
+ subject { described_class.new(IronMq::Engine, {}).with " " }
27
+
28
+ it "fails for push" do
29
+ expect { subject.push }.to raise_error NoQueueGivenError
30
+ end
31
+
32
+ it "fails for pop" do
33
+ expect { subject.pop }.to raise_error NoQueueGivenError
34
+ end
35
+
36
+ it "fails for receive" do
37
+ expect { subject.receive }.to raise_error NoQueueGivenError
38
+ end
39
+ end
40
+
11
41
  describe "queue swapping" do
12
42
  before do
13
43
  Queuel.stub default_queue: "default"
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ module Queuel
3
+ describe Configurator do
4
+ describe "configuration" do
5
+ before do
6
+ subject.credentials username: "jon"
7
+ end
8
+
9
+ it "set the logger" do
10
+ subject.logger.should be_a Logger
11
+ subject.log_level.should == MonoLogger::ERROR
12
+ end
13
+
14
+ describe "configured logger" do
15
+ let(:some_other_logger) { double "logger" }
16
+
17
+ it "fails on a logger without the correct methods" do
18
+ expect { subject.logger some_other_logger }.to raise_error Configurator::InvalidConfigurationError,
19
+ "Logger must respond to #{%w[info warn debug level level]}"
20
+ end
21
+ end
22
+
23
+ it "set the credentials" do
24
+ subject.credentials.should == { username: "jon" }
25
+ end
26
+
27
+ it "has a default worker count" do
28
+ subject.receiver_threads.should == 1
29
+ end
30
+ end
31
+ end
32
+ end
@@ -3,6 +3,34 @@ module Queuel
3
3
  module IronMq
4
4
  describe Engine do
5
5
  it_should_behave_like "an engine"
6
+
7
+ describe "loading typhoeus" do
8
+ describe "with typhoeus" do
9
+ before do
10
+ subject.stub :require do
11
+ raise LoadError
12
+ end
13
+ end
14
+
15
+ its(:try_typhoeus) { should == false }
16
+ end
17
+
18
+ describe "without typhoeus" do
19
+ its(:try_typhoeus) { should == true }
20
+ end
21
+ end
22
+
23
+ describe "getting iron client" do
24
+ its(:client_klass) { should == ::IronMQ::Client }
25
+
26
+ describe "undefined" do
27
+ before do
28
+ subject.stub defined?: false
29
+ end
30
+
31
+ its(:client_klass) { should == ::IronMQ::Client }
32
+ end
33
+ end
6
34
  end
7
35
  end
8
36
  end
@@ -5,8 +5,8 @@ module Queuel
5
5
  it_should_behave_like "a message"
6
6
  describe "initialization with Iron Object" do
7
7
  let(:queue_double) { double "Queue" }
8
- let(:message_object) { double "IronMessage", id: 1, msg: "body", queue: queue_double }
9
- subject { described_class.new_from_iron_mq_object(message_object) }
8
+ let(:message_object) { double "IronMessage", id: 1, body: "body", queue: queue_double }
9
+ subject { described_class.new(message_object) }
10
10
 
11
11
  its(:id) { should == 1 }
12
12
  its(:body) { should == "body" }
@@ -2,7 +2,21 @@ require 'spec_helper'
2
2
  module Queuel
3
3
  module IronMq
4
4
  describe Poller do
5
- it_should_behave_like "a poller"
5
+ describe "canned behavior" do
6
+ it_should_behave_like "a poller"
7
+ end
8
+
9
+ describe "specific to Iron MQ" do
10
+ let(:queue) { double "Queue" }
11
+ let(:options) { {} }
12
+ let(:block) { double "Callable" }
13
+ subject { described_class.new queue, block, options }
14
+
15
+ describe "its options" do
16
+ its(:built_options) { should == { n: 1 } }
17
+ its(:default_options) { should == { n: 1 } }
18
+ end
19
+ end
6
20
  end
7
21
  end
8
22
  end
@@ -2,8 +2,8 @@ require 'spec_helper'
2
2
  module Queuel
3
3
  module IronMq
4
4
  describe Queue do
5
- let(:queue_object_with_message) { double "QueueObject", get: message }
6
- let(:queue_object_with_nil_message) { double "QueueObject", get: nil }
5
+ let(:queue_object_with_message) { double "QueueObject", get: message, peek: [message] }
6
+ let(:queue_object_with_nil_message) { double "QueueObject", get: nil, peek: nil }
7
7
  it_should_behave_like "a queue"
8
8
  end
9
9
  end
@@ -9,15 +9,20 @@ describe Queuel do
9
9
  it { should respond_to :<< }
10
10
  it { should respond_to :receive }
11
11
 
12
- describe "configuration" do
13
- before do
14
- subject.configure do
15
- credentials username: "jon"
16
- end
12
+ describe "engine" do
13
+ describe "unset settings" do
14
+ before { subject.instance_variable_set "@config", nil }
15
+ before { subject.configure { log_level 5 } }
16
+ its(:engine) { should == Queuel::Null::Engine }
17
17
  end
18
18
 
19
- it "set the credentials" do
20
- subject.config.credentials.should == { username: "jon" }
19
+ describe "with configured" do
20
+ before do
21
+ subject.configure { engine :iron_mq }
22
+ end
23
+ after { subject.instance_variable_set("@config", nil) }
24
+
25
+ its(:engine) { should == Queuel::IronMq::Engine }
21
26
  end
22
27
  end
23
28
  end
data/spec/spec_helper.rb CHANGED
@@ -15,6 +15,10 @@ RSpec.configure do |config|
15
15
  config.treat_symbols_as_metadata_keys_with_true_values = true
16
16
  config.run_all_when_everything_filtered = true
17
17
  config.filter_run :focus
18
+ config.filter_run_excluding :perf
19
+ config.before do
20
+ Queuel.configure { log_level 5 }
21
+ end
18
22
 
19
23
  # Run specs in random order to surface order dependencies. If you find an
20
24
  # order dependency and want to debug it, you can fix the order by providing
@@ -1,10 +1,12 @@
1
1
  shared_examples "an engine" do
2
2
  let(:client_object) { double "Client Object" }
3
3
  let(:client) { double "#{described_class.name} Client", new: client_object }
4
- let(:queue_const) { Object.module_eval("#{described_class.to_s.split("::")[0..-2].join("::")}::Queue",__FILE__,__LINE__) }
4
+ let(:queue_const) do
5
+ Object.module_eval("#{described_class.to_s.split("::")[0..-2].join("::")}::Queue",__FILE__,__LINE__)
6
+ end
5
7
 
6
8
  before do
7
- subject.stub client_proper: client
9
+ subject.stub client_klass: client
8
10
  end
9
11
 
10
12
  it { should respond_to :queue }