queuel 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,40 @@
1
+ require 'queuel/iron_mq/poller'
2
+ module Queuel
3
+ module IronMq
4
+ class Queue
5
+ def initialize(client, queue_name)
6
+ self.client = client
7
+ self.name = queue_name
8
+ end
9
+
10
+ # For IronMQ it should just be (message)
11
+ def push(*args)
12
+ queue_connection.post *args
13
+ end
14
+
15
+ def pop(*args, &block)
16
+ bare_message = queue_connection.get(*args)
17
+ unless bare_message.nil?
18
+ Message.new_from_iron_mq_object(bare_message).tap { |message|
19
+ if block_given? && !message.nil?
20
+ yield message
21
+ message.delete
22
+ end
23
+ }
24
+ end
25
+ end
26
+
27
+ def receive(options = {}, &block)
28
+ Poller.new(self, options, block).poll
29
+ end
30
+
31
+ private
32
+ attr_accessor :client
33
+ attr_accessor :name
34
+
35
+ def queue_connection
36
+ @queue_connection ||= client.queue(name)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,12 @@
1
+ module Queuel
2
+ module Null
3
+ class Engine
4
+ def initialize(*)
5
+ end
6
+
7
+ def queue(*)
8
+ Queue.new
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,21 @@
1
+ require 'forwardable'
2
+ module Queuel
3
+ 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
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,120 @@
1
+ require 'timeout'
2
+ module Queuel
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
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,20 @@
1
+ require 'queuel/null/poller'
2
+ module Queuel
3
+ module Null
4
+ class Queue
5
+ def initialize(*)
6
+ end
7
+
8
+ # For IronMQ it should just be (message)
9
+ def push(*)
10
+ end
11
+
12
+ def pop(*args, &block)
13
+ end
14
+
15
+ def receive(options = {}, &block)
16
+ Poller.new(options, block).poll
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module Queuel
2
+ VERSION = "0.0.1"
3
+ end
data/queuel.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'queuel/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "queuel"
8
+ spec.version = Queuel::VERSION
9
+ spec.authors = ["Jon Phenow"]
10
+ spec.email = ["j.phenow@gmail.com"]
11
+ spec.description = %q{Light Queue wrapper tool}
12
+ spec.summary = %q{Light Queue wrapper tool}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "simplecov"
25
+ spec.add_development_dependency "iron_mq"
26
+ spec.add_development_dependency "typhoeus"
27
+ spec.add_development_dependency "json", "~> 1.7.7"
28
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+ module Queuel
3
+ describe Client do
4
+ subject { described_class.new IronMq::Engine, {} }
5
+
6
+ it { should respond_to :push }
7
+ it { should respond_to :pop }
8
+ it { should respond_to :receive }
9
+ it { should respond_to :with }
10
+
11
+ describe "queue swapping" do
12
+ before do
13
+ Queuel.stub default_queue: "default"
14
+ end
15
+
16
+ it "can swap queues easily" do
17
+ subject.queue.should == "default"
18
+ subject.with(:new_queue).queue.should == "new_queue"
19
+ subject.queue.should == "default"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ module Queuel
3
+ module IronMq
4
+ describe Engine do
5
+ it_should_behave_like "an engine"
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+ module Queuel
3
+ module IronMq
4
+ describe Message do
5
+ it_should_behave_like "a message"
6
+ describe "initialization with Iron Object" do
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) }
10
+
11
+ its(:id) { should == 1 }
12
+ its(:body) { should == "body" }
13
+ its(:queue) { should == queue_double }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ module Queuel
3
+ module IronMq
4
+ describe Poller do
5
+ it_should_behave_like "a poller"
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ module Queuel
3
+ module IronMq
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 }
7
+ it_should_behave_like "a queue"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ module Queuel
3
+ module Null
4
+ describe Engine do
5
+ it_should_behave_like "an engine"
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+ module Queuel
3
+ module Null
4
+ describe Message do
5
+ let(:null) { true }
6
+ it_should_behave_like "a message"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+ module Queuel
3
+ module Null
4
+ describe Poller do
5
+ let(:null) { true }
6
+ it_should_behave_like "a poller"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+ module Queuel
3
+ module Null
4
+ describe Queue do
5
+ let(:null) { true }
6
+ it_should_behave_like "a queue"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+ describe Queuel do
3
+ it { should respond_to :engine }
4
+ it { should respond_to :configure }
5
+ it { should respond_to :config }
6
+
7
+ it { should respond_to :push }
8
+ it { should respond_to :pop }
9
+ it { should respond_to :<< }
10
+ it { should respond_to :receive }
11
+
12
+ describe "configuration" do
13
+ before do
14
+ subject.configure do
15
+ credentials username: "jon"
16
+ end
17
+ end
18
+
19
+ it "set the credentials" do
20
+ subject.config.credentials.should == { username: "jon" }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ require 'simplecov'
8
+ SimpleCov.start do
9
+ add_filter '/spec/'
10
+ end
11
+
12
+ require 'queuel'
13
+ Dir["./spec/support/**/*.rb"].sort.each {|f| require f}
14
+ RSpec.configure do |config|
15
+ config.treat_symbols_as_metadata_keys_with_true_values = true
16
+ config.run_all_when_everything_filtered = true
17
+ config.filter_run :focus
18
+
19
+ # Run specs in random order to surface order dependencies. If you find an
20
+ # order dependency and want to debug it, you can fix the order by providing
21
+ # the seed, which is printed after each run.
22
+ # --seed 1234
23
+ config.order = 'random'
24
+ end
@@ -0,0 +1,15 @@
1
+ shared_examples "an engine" do
2
+ let(:client_object) { double "Client Object" }
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__) }
5
+
6
+ before do
7
+ subject.stub client_proper: client
8
+ end
9
+
10
+ it { should respond_to :queue }
11
+
12
+ it "can grab a queue" do
13
+ subject.queue("some_queue").should be_a queue_const
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ shared_examples "a message" do
2
+ let(:id) { 1 }
3
+ let(:body) { "test" }
4
+ let(:queue) { nil }
5
+ subject { described_class.new id, body, queue }
6
+
7
+ it { should respond_to :id }
8
+ it { should respond_to :body }
9
+ it { should respond_to :queue }
10
+
11
+ its(:queue) { should be_nil }
12
+ its(:id) { should == 1 }
13
+ its(:body) { should == 'test' }
14
+
15
+ describe "with a given queue" do
16
+ let(:queue) { double "Queue object" }
17
+
18
+ its(:queue) { should == queue }
19
+ end
20
+ end