qup 1.2.0 → 1.4.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.
- data/HISTORY.rdoc +35 -2
- data/Manifest.txt +4 -0
- data/README.rdoc +12 -2
- data/Rakefile +92 -32
- data/lib/qup.rb +4 -2
- data/lib/qup/adapter/kestrel.rb +10 -7
- data/lib/qup/adapter/kestrel/destination.rb +7 -23
- data/lib/qup/adapter/kestrel/queue.rb +20 -15
- data/lib/qup/adapter/kestrel/topic.rb +23 -8
- data/lib/qup/adapter/redis/queue.rb +2 -1
- data/lib/qup/backoff_sleeper.rb +52 -0
- data/lib/qup/batch_consumer.rb +132 -0
- data/lib/qup/consumer.rb +7 -0
- data/lib/qup/session.rb +5 -1
- data/spec/qup/adapter/kestrel_spec.rb +1 -0
- data/spec/qup/adapter/redis/queue_spec.rb +2 -2
- data/spec/qup/backoff_sleeper_sleeper_spec.rb +73 -0
- data/spec/qup/batch_consumer_spec.rb +140 -0
- data/spec/qup/consumer_spec.rb +7 -0
- data/spec/qup/session_spec.rb +7 -0
- data/spec/qup/shared_queue_examples.rb +16 -4
- data/spec/qup/shared_topic_examples.rb +8 -0
- data/spec/spec_helper.rb +8 -1
- metadata +31 -57
@@ -0,0 +1,140 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "tmpdir"
|
3
|
+
require "timeout"
|
4
|
+
|
5
|
+
module Qup
|
6
|
+
describe BatchConsumer do
|
7
|
+
class Client
|
8
|
+
include Qup::BatchConsumerAPI
|
9
|
+
|
10
|
+
def process(message)
|
11
|
+
messages << message.data
|
12
|
+
end
|
13
|
+
|
14
|
+
def messages
|
15
|
+
@messages ||= []
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#new" do
|
20
|
+
it "passes options[:session_options] to the session" do
|
21
|
+
session_options = double
|
22
|
+
batch_consumer = BatchConsumer.new({
|
23
|
+
:session_options => session_options,
|
24
|
+
:queue_uri => "maildir://#{Dir.mktmpdir}"
|
25
|
+
})
|
26
|
+
batch_consumer.session.options.should == session_options
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#run" do
|
31
|
+
let(:queue_uri) { "maildir://#{Dir.mktmpdir}" }
|
32
|
+
let(:queue_name) { "test" }
|
33
|
+
let(:queue) { Session.new(queue_uri).queue(queue_name) }
|
34
|
+
|
35
|
+
it "doesn't blow up if #setup or #teardown is not defined" do
|
36
|
+
queue.producer.produce("A")
|
37
|
+
|
38
|
+
empty_client = Class.new do
|
39
|
+
include Qup::BatchConsumerAPI
|
40
|
+
|
41
|
+
def process(*)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
batch_consumer = BatchConsumer.new({
|
46
|
+
:max_size => 1,
|
47
|
+
:client => empty_client.new,
|
48
|
+
:queue_uri => queue_uri,
|
49
|
+
:queue_name => queue_name
|
50
|
+
})
|
51
|
+
|
52
|
+
batch_consumer.run
|
53
|
+
end
|
54
|
+
|
55
|
+
it "does blow up if #process isn't defined" do
|
56
|
+
queue.producer.produce("A")
|
57
|
+
|
58
|
+
empty_client = Class.new do
|
59
|
+
include Qup::BatchConsumerAPI
|
60
|
+
end
|
61
|
+
|
62
|
+
batch_consumer = BatchConsumer.new({
|
63
|
+
:max_size => 1,
|
64
|
+
:client => empty_client.new,
|
65
|
+
:queue_uri => queue_uri,
|
66
|
+
:queue_name => queue_name
|
67
|
+
})
|
68
|
+
|
69
|
+
expect { batch_consumer.run }.to raise_error(NotImplementedError)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "calls process until max_size is met" do
|
73
|
+
["A", "B", "C"].each { |d| queue.producer.produce(d) }
|
74
|
+
|
75
|
+
client = Client.new
|
76
|
+
batch_consumer = BatchConsumer.new({
|
77
|
+
:client => client,
|
78
|
+
:max_size => 2,
|
79
|
+
:queue_uri => queue_uri,
|
80
|
+
:queue_name => queue_name
|
81
|
+
})
|
82
|
+
|
83
|
+
batch_consumer.run
|
84
|
+
client.messages.should == ["A", "B"]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "returns when max_age is met" do
|
88
|
+
client = Client.new
|
89
|
+
batch_consumer = BatchConsumer.new({
|
90
|
+
:client => client,
|
91
|
+
:max_size => 1,
|
92
|
+
:max_age => 0.001,
|
93
|
+
:queue_uri => queue_uri,
|
94
|
+
:queue_name => queue_name
|
95
|
+
})
|
96
|
+
|
97
|
+
Timeout.timeout(1) { batch_consumer.run } # Does not hang
|
98
|
+
end
|
99
|
+
|
100
|
+
it "returns when max_age and max_size are present and one of the values is met" do
|
101
|
+
|
102
|
+
client = Client.new
|
103
|
+
|
104
|
+
["A", "B", "C"].each { |d| queue.producer.produce(d) }
|
105
|
+
|
106
|
+
batch_consumer = BatchConsumer.new({
|
107
|
+
:client => client,
|
108
|
+
:max_size => 1,
|
109
|
+
:max_age => 5,
|
110
|
+
:queue_uri => queue_uri,
|
111
|
+
:queue_name => queue_name
|
112
|
+
})
|
113
|
+
|
114
|
+
batch_consumer.run
|
115
|
+
client.messages.should == ["A"]
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
it "calls the #setup, #process and #teardown in the correct order" do
|
121
|
+
queue.producer.produce("A")
|
122
|
+
|
123
|
+
client = Client.new
|
124
|
+
|
125
|
+
batch_consumer = BatchConsumer.new({
|
126
|
+
:max_size => 1,
|
127
|
+
:client => client,
|
128
|
+
:queue_uri => queue_uri,
|
129
|
+
:queue_name => queue_name
|
130
|
+
})
|
131
|
+
|
132
|
+
client.should_receive(:setup).once.ordered
|
133
|
+
client.should_receive(:process).once.ordered
|
134
|
+
client.should_receive(:teardown).once.ordered
|
135
|
+
|
136
|
+
batch_consumer.run
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
data/spec/qup/consumer_spec.rb
CHANGED
@@ -37,4 +37,11 @@ describe Qup::Consumer do
|
|
37
37
|
queue.depth.should eq 0
|
38
38
|
end
|
39
39
|
|
40
|
+
it "knows how deep the consumer's queue is" do
|
41
|
+
consumer.depth.should eq 1
|
42
|
+
consumer.consume do |msg|
|
43
|
+
msg.data.should eq 'consumption'
|
44
|
+
end
|
45
|
+
queue.depth.should eq 0
|
46
|
+
end
|
40
47
|
end
|
data/spec/qup/session_spec.rb
CHANGED
@@ -78,4 +78,11 @@ describe Qup::Session do
|
|
78
78
|
lambda { session.topic( 'boom' ) }.should raise_error( Qup::Session::ClosedError, /Session (.*) is closed/ )
|
79
79
|
end
|
80
80
|
end
|
81
|
+
|
82
|
+
describe '#options' do
|
83
|
+
it "holds the options that are used to initialize the session" do
|
84
|
+
s = Qup::Session.open( uri, { :the => 'Option' } )
|
85
|
+
s.options[:the].should == 'Option'
|
86
|
+
end
|
87
|
+
end
|
81
88
|
end
|
@@ -20,10 +20,17 @@ shared_examples Qup::QueueAPI do
|
|
20
20
|
queue.name.should eq 'foo'
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
|
-
queue
|
25
|
-
|
26
|
-
|
23
|
+
describe "#produce" do
|
24
|
+
it "produces an item on the queue" do
|
25
|
+
queue.depth.should eq 0
|
26
|
+
queue.produce( "a new message" )
|
27
|
+
queue.depth.should eq 1
|
28
|
+
end
|
29
|
+
|
30
|
+
it "does not create multiple messages for newlines" do
|
31
|
+
queue.produce( "one\nsingle\nmessage" )
|
32
|
+
queue.depth.should eq 1
|
33
|
+
end
|
27
34
|
end
|
28
35
|
|
29
36
|
it "#flush" do
|
@@ -49,6 +56,11 @@ shared_examples Qup::QueueAPI do
|
|
49
56
|
msg.data.should eq 'consumeable message'
|
50
57
|
end
|
51
58
|
end
|
59
|
+
|
60
|
+
it 'returns nil if the queue is empty (it is non-blocking)' do
|
61
|
+
queue.consume
|
62
|
+
queue.consume.should == nil
|
63
|
+
end
|
52
64
|
end
|
53
65
|
|
54
66
|
describe "#acknowledge" do
|
@@ -53,5 +53,13 @@ shared_examples Qup::TopicAPI do
|
|
53
53
|
msg.data.should eq 'hi all'
|
54
54
|
end
|
55
55
|
end
|
56
|
+
|
57
|
+
it "only receive a single message for a message containing newlines" do
|
58
|
+
p = @topic.publisher
|
59
|
+
p.publish( "one\nsingle\nmessage" )
|
60
|
+
@subs.each do |sub|
|
61
|
+
sub.depth.should eq 1
|
62
|
+
end
|
63
|
+
end
|
56
64
|
end
|
57
65
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
if RUBY_VERSION >= '1.9.2' then
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start if ENV['COVERAGE']
|
4
|
+
end
|
5
|
+
|
1
6
|
require "rspec/autorun"
|
2
7
|
require 'qup'
|
3
8
|
|
@@ -15,12 +20,14 @@ RSpec.configure do |conf|
|
|
15
20
|
Qup::KNOWN_ADAPTERS.each do |adapter, gemname|
|
16
21
|
begin
|
17
22
|
require "qup/adapter/#{adapter}"
|
18
|
-
rescue LoadError
|
23
|
+
rescue LoadError => e
|
19
24
|
warn "NOTICE:"
|
20
25
|
warn "NOTICE: The tests for the '#{adapter}' will be skipped as the '#{gemname}' is not installed"
|
21
26
|
warn "NOTICE:"
|
27
|
+
warn "LoadError: #{e}"
|
22
28
|
sym = adapter.to_sym
|
23
29
|
conf.filter_run_excluding sym => true
|
24
30
|
end
|
25
31
|
end
|
26
32
|
end
|
33
|
+
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- 0
|
10
|
-
version: 1.
|
10
|
+
version: 1.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jeremy Hinegardner
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-10-31 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: maildir
|
@@ -25,28 +25,28 @@ dependencies:
|
|
25
25
|
requirements:
|
26
26
|
- - ~>
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
hash:
|
28
|
+
hash: 11
|
29
29
|
segments:
|
30
30
|
- 2
|
31
|
+
- 1
|
31
32
|
- 0
|
32
|
-
|
33
|
-
version: 2.0.0
|
33
|
+
version: 2.1.0
|
34
34
|
type: :runtime
|
35
35
|
version_requirements: *id001
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
37
|
+
name: kjess
|
38
38
|
prerelease: false
|
39
39
|
requirement: &id002 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
hash:
|
44
|
+
hash: 23
|
45
45
|
segments:
|
46
|
-
- 0
|
47
|
-
- 7
|
48
46
|
- 1
|
49
|
-
|
47
|
+
- 0
|
48
|
+
- 0
|
49
|
+
version: 1.0.0
|
50
50
|
type: :development
|
51
51
|
version_requirements: *id002
|
52
52
|
- !ruby/object:Gem::Dependency
|
@@ -59,32 +59,16 @@ dependencies:
|
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
hash: 3
|
61
61
|
segments:
|
62
|
+
- 3
|
63
|
+
- 0
|
62
64
|
- 2
|
63
|
-
|
64
|
-
- 2
|
65
|
-
version: 2.2.2
|
65
|
+
version: 3.0.2
|
66
66
|
type: :development
|
67
67
|
version_requirements: *id003
|
68
|
-
- !ruby/object:Gem::Dependency
|
69
|
-
name: SystemTimer
|
70
|
-
prerelease: false
|
71
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
72
|
-
none: false
|
73
|
-
requirements:
|
74
|
-
- - ~>
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
hash: 25
|
77
|
-
segments:
|
78
|
-
- 1
|
79
|
-
- 2
|
80
|
-
- 3
|
81
|
-
version: 1.2.3
|
82
|
-
type: :development
|
83
|
-
version_requirements: *id004
|
84
68
|
- !ruby/object:Gem::Dependency
|
85
69
|
name: rake
|
86
70
|
prerelease: false
|
87
|
-
requirement: &
|
71
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
88
72
|
none: false
|
89
73
|
requirements:
|
90
74
|
- - ~>
|
@@ -97,43 +81,27 @@ dependencies:
|
|
97
81
|
- 2
|
98
82
|
version: 0.9.2.2
|
99
83
|
type: :development
|
100
|
-
version_requirements: *
|
101
|
-
- !ruby/object:Gem::Dependency
|
102
|
-
name: rcov
|
103
|
-
prerelease: false
|
104
|
-
requirement: &id006 !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
|
-
requirements:
|
107
|
-
- - ~>
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
hash: 23
|
110
|
-
segments:
|
111
|
-
- 1
|
112
|
-
- 0
|
113
|
-
- 0
|
114
|
-
version: 1.0.0
|
115
|
-
type: :development
|
116
|
-
version_requirements: *id006
|
84
|
+
version_requirements: *id004
|
117
85
|
- !ruby/object:Gem::Dependency
|
118
86
|
name: rspec
|
119
87
|
prerelease: false
|
120
|
-
requirement: &
|
88
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
121
89
|
none: false
|
122
90
|
requirements:
|
123
91
|
- - ~>
|
124
92
|
- !ruby/object:Gem::Version
|
125
|
-
hash:
|
93
|
+
hash: 35
|
126
94
|
segments:
|
127
95
|
- 2
|
128
|
-
-
|
96
|
+
- 11
|
129
97
|
- 0
|
130
|
-
version: 2.
|
98
|
+
version: 2.11.0
|
131
99
|
type: :development
|
132
|
-
version_requirements: *
|
100
|
+
version_requirements: *id005
|
133
101
|
- !ruby/object:Gem::Dependency
|
134
102
|
name: rdoc
|
135
103
|
prerelease: false
|
136
|
-
requirement: &
|
104
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
137
105
|
none: false
|
138
106
|
requirements:
|
139
107
|
- - ~>
|
@@ -144,7 +112,7 @@ dependencies:
|
|
144
112
|
- 12
|
145
113
|
version: "3.12"
|
146
114
|
type: :development
|
147
|
-
version_requirements: *
|
115
|
+
version_requirements: *id006
|
148
116
|
description: Qup is a generalized API for Message Queue and Publish/Subscribe messaging patterns with the ability to plug in an appropriate messaging infrastructure based upon your needs. Qup ships with support for Kestrel, Redis, and a filesystem infrastructure based on Maildir. Additional Adapters will be developed as needs arise. Please submit an Issue to have a new Adapter created. Pull requests gladly accepted.
|
149
117
|
email: jeremy@copiousfreetime.org
|
150
118
|
executables: []
|
@@ -177,6 +145,8 @@ files:
|
|
177
145
|
- lib/qup/adapter/redis/connection.rb
|
178
146
|
- lib/qup/adapter/redis/queue.rb
|
179
147
|
- lib/qup/adapter/redis/topic.rb
|
148
|
+
- lib/qup/backoff_sleeper.rb
|
149
|
+
- lib/qup/batch_consumer.rb
|
180
150
|
- lib/qup/consumer.rb
|
181
151
|
- lib/qup/message.rb
|
182
152
|
- lib/qup/producer.rb
|
@@ -198,6 +168,8 @@ files:
|
|
198
168
|
- spec/qup/adapter/redis_context.rb
|
199
169
|
- spec/qup/adapter/redis_spec.rb
|
200
170
|
- spec/qup/adapter_spec.rb
|
171
|
+
- spec/qup/backoff_sleeper_sleeper_spec.rb
|
172
|
+
- spec/qup/batch_consumer_spec.rb
|
201
173
|
- spec/qup/consumer_spec.rb
|
202
174
|
- spec/qup/message_spec.rb
|
203
175
|
- spec/qup/producer_spec.rb
|
@@ -241,7 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
241
213
|
requirements: []
|
242
214
|
|
243
215
|
rubyforge_project:
|
244
|
-
rubygems_version: 1.8.
|
216
|
+
rubygems_version: 1.8.24
|
245
217
|
signing_key:
|
246
218
|
specification_version: 3
|
247
219
|
summary: Qup is a generalized API for Message Queue and Publish/Subscribe messaging patterns with the ability to plug in an appropriate messaging infrastructure based upon your needs.
|
@@ -259,6 +231,8 @@ test_files:
|
|
259
231
|
- spec/qup/adapter/redis_context.rb
|
260
232
|
- spec/qup/adapter/redis_spec.rb
|
261
233
|
- spec/qup/adapter_spec.rb
|
234
|
+
- spec/qup/backoff_sleeper_sleeper_spec.rb
|
235
|
+
- spec/qup/batch_consumer_spec.rb
|
262
236
|
- spec/qup/consumer_spec.rb
|
263
237
|
- spec/qup/message_spec.rb
|
264
238
|
- spec/qup/producer_spec.rb
|