queuel 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 }