queuel 0.0.1
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.
- data/.gitignore +17 -0
- data/.irbrc +2 -0
- data/.rspec +2 -0
- data/.rvmrc +46 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +101 -0
- data/Rakefile +6 -0
- data/lib/queuel.rb +68 -0
- data/lib/queuel/client.rb +37 -0
- data/lib/queuel/iron_mq/engine.rb +44 -0
- data/lib/queuel/iron_mq/message.rb +43 -0
- data/lib/queuel/iron_mq/poller.rb +123 -0
- data/lib/queuel/iron_mq/queue.rb +40 -0
- data/lib/queuel/null/engine.rb +12 -0
- data/lib/queuel/null/message.rb +21 -0
- data/lib/queuel/null/poller.rb +120 -0
- data/lib/queuel/null/queue.rb +20 -0
- data/lib/queuel/version.rb +3 -0
- data/queuel.gemspec +28 -0
- data/spec/lib/queuel/client_spec.rb +23 -0
- data/spec/lib/queuel/iron_mq/engine_spec.rb +8 -0
- data/spec/lib/queuel/iron_mq/message_spec.rb +17 -0
- data/spec/lib/queuel/iron_mq/poller_spec.rb +8 -0
- data/spec/lib/queuel/iron_mq/queue_spec.rb +10 -0
- data/spec/lib/queuel/null/engine_spec.rb +8 -0
- data/spec/lib/queuel/null/message_spec.rb +9 -0
- data/spec/lib/queuel/null/poller_spec.rb +9 -0
- data/spec/lib/queuel/null/queue_spec.rb +9 -0
- data/spec/lib/queuel_spec.rb +23 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/engine_shared_example.rb +15 -0
- data/spec/support/message_shared_example.rb +20 -0
- data/spec/support/null_behavior.rb +7 -0
- data/spec/support/poller_shared_example.rb +101 -0
- data/spec/support/queue_shared_example.rb +52 -0
- metadata +217 -0
@@ -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,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
|
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,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,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,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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|