action_subscriber 1.0.3 → 1.0.4
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.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.travis.yml +12 -0
- data/Gemfile +0 -1
- data/README.md +10 -4
- data/action_subscriber.gemspec +2 -2
- data/lib/action_subscriber/base.rb +13 -0
- data/lib/action_subscriber/dsl.rb +16 -6
- data/lib/action_subscriber/middleware/error_handler.rb +0 -1
- data/lib/action_subscriber/middleware/router.rb +1 -5
- data/lib/action_subscriber/rabbit_connection.rb +10 -0
- data/lib/action_subscriber/version.rb +1 -1
- data/spec/integration/around_filters_spec.rb +38 -0
- data/spec/integration/at_least_once_spec.rb +23 -0
- data/spec/integration/at_most_once_spec.rb +23 -0
- data/spec/integration/automatic_reconnect_spec.rb +43 -0
- data/spec/integration/basic_subscriber_spec.rb +25 -19
- data/spec/integration/decoding_payloads_spec.rb +48 -0
- data/spec/integration/manual_acknowledgement_spec.rb +27 -0
- data/spec/lib/action_subscriber/base_spec.rb +0 -2
- data/spec/lib/action_subscriber/configuration_spec.rb +0 -2
- data/spec/lib/action_subscriber/dsl_spec.rb +0 -42
- data/spec/lib/action_subscriber/middleware/active_record/connection_management_spec.rb +0 -1
- data/spec/lib/action_subscriber/middleware/active_record/query_cache_spec.rb +0 -1
- data/spec/lib/action_subscriber/middleware/decoder_spec.rb +0 -2
- data/spec/lib/action_subscriber/middleware/env_spec.rb +0 -2
- data/spec/lib/action_subscriber/middleware/error_handler_spec.rb +0 -13
- data/spec/lib/action_subscriber/middleware/router_spec.rb +0 -14
- data/spec/lib/action_subscriber/middleware/runner_spec.rb +0 -2
- data/spec/lib/action_subscriber/subscribable_spec.rb +0 -2
- data/spec/lib/action_subscriber/threadpool_spec.rb +0 -2
- data/spec/spec_helper.rb +12 -6
- metadata +26 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a9be445a43340a38817ee6efe76c6c3063dcca4
|
4
|
+
data.tar.gz: 4f33caa19d68cfcf1e8b2b6732e3e82e5396ea5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a7b01e0746d3266a66fb1487b6ea495ea9cfa13553df1d91cb7b27173bff2e61627c893bdd9cbe44ff5391d1623f73cb781afb2675e060a2d8b728b9713cdda
|
7
|
+
data.tar.gz: e7df2fa7ffa73affb739a4fa9f7f5b2d0abd093fd58638c610b3bc783a1f9a1ad5ef7d14473c9777e84424a575a029d2440788e7b715c05a2f9c4f71385bb766
|
data/.rspec
CHANGED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
[](https://travis-ci.org/moneydesktop/action_subscriber)
|
2
|
+
[](https://codeclimate.com/github/moneydesktop/action_subscriber)
|
3
|
+
[](https://gemnasium.com/moneydesktop/action_subscriber)
|
4
|
+
|
1
5
|
ActionSubscriber
|
2
6
|
=================
|
3
7
|
ActionSubscriber is a DSL for for easily intergrating your Rails app with a RabbitMQ messaging server.
|
@@ -66,19 +70,21 @@ ActionSubscriber needs to know how to connect to your rabbit server to start get
|
|
66
70
|
In an initializer, you can set the host and the port like this :
|
67
71
|
|
68
72
|
ActionSubscriber::Configuration.configure do |config|
|
69
|
-
config.
|
73
|
+
config.hosts = ["rabbit1", "rabbit2", "rabbit3"]
|
70
74
|
config.port = 5672
|
71
75
|
end
|
72
76
|
|
73
77
|
Other configuration options include :
|
74
78
|
|
79
|
+
* config.add_decoder - add a custom decoder for a custom content type
|
75
80
|
* config.allow_low_priority_methods - subscribe to queues for methods suffixed with "_low"
|
76
81
|
* config.default_exchange - set the default exchange that your queues will use, using the default RabbitMQ exchange is not recommended
|
82
|
+
* config.error_handler - handle error like you want to handle them!
|
83
|
+
* config.heartbeat - number of seconds between hearbeats (default 5) [see bunny documentation for more details](http://rubybunny.info/articles/connecting.html)
|
77
84
|
* config.hosts - an array of hostnames in your cluster
|
78
|
-
* config.times_to_pop - when using RabbitMQ's pull API, the number of messages we will grab each time we pool the broker
|
79
85
|
* config.threadpool_size - set the number of threads availiable to action_subscriber
|
80
|
-
* config.
|
81
|
-
* config.
|
86
|
+
* config.timeout - how many seconds to allow rabbit to respond before timing out
|
87
|
+
* config.times_to_pop - when using RabbitMQ's pull API, the number of messages we will grab each time we pool the broker
|
82
88
|
|
83
89
|
Message Acknowledgment
|
84
90
|
----------------------
|
data/action_subscriber.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["brianastien@gmail.com","liveh2o@gmail.com","brandonsdewitt@gmail.com","quixoten@gmail.com","michael@riesd.com"]
|
11
11
|
spec.description = %q{ActionSubscriber is a DSL that allows a rails app to consume messages from a RabbitMQ broker.}
|
12
12
|
spec.summary = %q{ActionSubscriber is a DSL that allows a rails app to consume messages from a RabbitMQ broker.}
|
13
|
-
spec.homepage = ""
|
13
|
+
spec.homepage = "https://github.com/moneydesktop/action_subscriber"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_development_dependency "activerecord", ">= 3.2"
|
33
33
|
spec.add_development_dependency "bundler", ">= 1.6"
|
34
34
|
spec.add_development_dependency "pry-nav"
|
35
|
+
spec.add_development_dependency "rabbitmq_http_api_client", "~> 1.2.0"
|
35
36
|
spec.add_development_dependency "rspec", "~> 3.0"
|
36
37
|
spec.add_development_dependency "rake"
|
37
|
-
spec.add_development_dependency "simplecov"
|
38
38
|
end
|
@@ -76,6 +76,19 @@ module ActionSubscriber
|
|
76
76
|
env.acknowledge
|
77
77
|
end
|
78
78
|
|
79
|
+
def _at_least_once_filter
|
80
|
+
yield
|
81
|
+
acknowledge
|
82
|
+
rescue => error
|
83
|
+
reject
|
84
|
+
raise error
|
85
|
+
end
|
86
|
+
|
87
|
+
def _at_most_once_filter
|
88
|
+
acknowledge
|
89
|
+
yield
|
90
|
+
end
|
91
|
+
|
79
92
|
def reject
|
80
93
|
env.reject
|
81
94
|
end
|
@@ -2,24 +2,24 @@ module ActionSubscriber
|
|
2
2
|
module DSL
|
3
3
|
def at_least_once!
|
4
4
|
@_acknowledge_messages = true
|
5
|
-
|
5
|
+
around_filter :_at_least_once_filter
|
6
6
|
end
|
7
7
|
|
8
8
|
def at_most_once!
|
9
9
|
@_acknowledge_messages = true
|
10
|
-
|
10
|
+
around_filter :_at_most_once_filter
|
11
11
|
end
|
12
12
|
|
13
13
|
def acknowledge_messages?
|
14
14
|
!!@_acknowledge_messages
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
|
17
|
+
def around_filter(filter_method)
|
18
|
+
around_filters << filter_method
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
22
|
-
|
21
|
+
def around_filters
|
22
|
+
@_around_filters ||= []
|
23
23
|
end
|
24
24
|
|
25
25
|
# Explicitly set the name of the exchange
|
@@ -79,5 +79,15 @@ module ActionSubscriber
|
|
79
79
|
def routing_key_names
|
80
80
|
@_routing_key_names ||= {}
|
81
81
|
end
|
82
|
+
|
83
|
+
def run_action_with_filters(env, action)
|
84
|
+
subscriber_instance = self.new(env)
|
85
|
+
final_block = Proc.new { subscriber_instance.public_send(action) }
|
86
|
+
|
87
|
+
first_proc = around_filters.reverse.reduce(final_block) do |block, filter|
|
88
|
+
Proc.new { subscriber_instance.send(filter, &block) }
|
89
|
+
end
|
90
|
+
first_proc.call
|
91
|
+
end
|
82
92
|
end
|
83
93
|
end
|
@@ -6,11 +6,7 @@ module ActionSubscriber
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def call(env)
|
9
|
-
|
10
|
-
|
11
|
-
env.acknowledge if env.subscriber.acknowledge_messages_before_processing?
|
12
|
-
subscriber.public_send(env.action)
|
13
|
-
env.acknowledge if env.subscriber.acknowledge_messages_after_processing?
|
9
|
+
env.subscriber.run_action_with_filters(env, env.action)
|
14
10
|
end
|
15
11
|
end
|
16
12
|
end
|
@@ -36,5 +36,15 @@ module ActionSubscriber
|
|
36
36
|
:recover_from_connection_close => true,
|
37
37
|
}
|
38
38
|
end
|
39
|
+
|
40
|
+
def self.disconnect!
|
41
|
+
CONNECTION_MUTEX.synchronize do
|
42
|
+
if @connection && @connection.connected?
|
43
|
+
@connection.close
|
44
|
+
end
|
45
|
+
|
46
|
+
@connection = nil
|
47
|
+
end
|
48
|
+
end
|
39
49
|
end
|
40
50
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class InstaSubscriber < ActionSubscriber::Base
|
2
|
+
around_filter :whisper
|
3
|
+
around_filter :yell
|
4
|
+
|
5
|
+
def first
|
6
|
+
$messages << payload
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def whisper
|
12
|
+
$messages << :whisper_before
|
13
|
+
yield
|
14
|
+
$messages << :whisper_after
|
15
|
+
end
|
16
|
+
|
17
|
+
def yell
|
18
|
+
$messages << :yell_before
|
19
|
+
yield
|
20
|
+
$messages << :yell_after
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "subscriber filters", :integration => true do
|
25
|
+
let(:connection) { subscriber.connection }
|
26
|
+
let(:subscriber) { InstaSubscriber }
|
27
|
+
|
28
|
+
it "runs multiple around filters" do
|
29
|
+
$messages = [] #testing the order of things
|
30
|
+
::ActionSubscriber.auto_subscribe!
|
31
|
+
channel = connection.create_channel
|
32
|
+
exchange = channel.topic("events")
|
33
|
+
exchange.publish("hEY Guyz!", :routing_key => "insta.first")
|
34
|
+
sleep 0.1
|
35
|
+
|
36
|
+
expect($messages).to eq [:whisper_before, :yell_before, "hEY Guyz!", :yell_after, :whisper_after]
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class GorbyPuffSubscriber < ActionSubscriber::Base
|
2
|
+
at_least_once!
|
3
|
+
|
4
|
+
def grumpy
|
5
|
+
$messages << "#{payload}::#{$messages.size}"
|
6
|
+
raise RuntimeError.new("what do I do now?") unless $messages.size > 2
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "at_least_once! mode", :integration => true do
|
11
|
+
let(:connection) { subscriber.connection }
|
12
|
+
let(:subscriber) { GorbyPuffSubscriber }
|
13
|
+
|
14
|
+
it "retries a failed job until it succeeds" do
|
15
|
+
::ActionSubscriber.auto_subscribe!
|
16
|
+
channel = connection.create_channel
|
17
|
+
exchange = channel.topic("events")
|
18
|
+
exchange.publish("GrumpFace", :routing_key => "gorby_puff.grumpy")
|
19
|
+
sleep 0.1
|
20
|
+
|
21
|
+
expect($messages).to eq Set.new(["GrumpFace::0","GrumpFace::1","GrumpFace::2"])
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class PokemonSubscriber < ActionSubscriber::Base
|
2
|
+
at_most_once!
|
3
|
+
|
4
|
+
def caught_em_all
|
5
|
+
$messages << "DONE::#{$messages.size}"
|
6
|
+
raise RuntimeError.new("what do I do now?")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "at_most_once! mode", :integration => true do
|
11
|
+
let(:connection) { subscriber.connection }
|
12
|
+
let(:subscriber) { PokemonSubscriber }
|
13
|
+
|
14
|
+
it "does not retry a failed message" do
|
15
|
+
::ActionSubscriber.auto_subscribe!
|
16
|
+
channel = connection.create_channel
|
17
|
+
exchange = channel.topic("events")
|
18
|
+
exchange.publish("All Pokemon have been caught", :routing_key => "pokemon.caught_em_all")
|
19
|
+
sleep 0.1
|
20
|
+
|
21
|
+
expect($messages.size).to eq 1
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "rabbitmq/http/client"
|
2
|
+
|
3
|
+
class GusSubscriber < ActionSubscriber::Base
|
4
|
+
def spoke
|
5
|
+
$messages << payload
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "Automatically reconnect on connection failure", :integration => true, :slow => true do
|
10
|
+
let(:connection) { subscriber.connection }
|
11
|
+
let(:http_client) { RabbitMQ::HTTP::Client.new("http://127.0.0.1:15672") }
|
12
|
+
let(:subscriber) { GusSubscriber }
|
13
|
+
|
14
|
+
it "reconnects when a connection drops" do
|
15
|
+
::ActionSubscriber::auto_subscribe!
|
16
|
+
channel = connection.create_channel
|
17
|
+
exchange = channel.topic("events")
|
18
|
+
exchange.publish("First", :routing_key => "gus.spoke")
|
19
|
+
sleep 0.1
|
20
|
+
|
21
|
+
close_all_connections!
|
22
|
+
sleep_until_reconnected
|
23
|
+
|
24
|
+
exchange.publish("Second", :routing_key => "gus.spoke")
|
25
|
+
sleep 0.1
|
26
|
+
|
27
|
+
expect($messages).to eq(Set.new(["First", "Second"]))
|
28
|
+
end
|
29
|
+
|
30
|
+
def close_all_connections!
|
31
|
+
http_client.list_connections.each do |conn_info|
|
32
|
+
http_client.close_connection(conn_info.name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def sleep_until_reconnected
|
37
|
+
100.times do
|
38
|
+
sleep 0.1
|
39
|
+
break if connection.open?
|
40
|
+
end
|
41
|
+
sleep 0.2
|
42
|
+
end
|
43
|
+
end
|
@@ -1,42 +1,48 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
1
|
class BasicPushSubscriber < ActionSubscriber::Base
|
4
|
-
BOOKED_MESSAGES = []
|
5
|
-
CANCELLED_MESSAGES = []
|
6
|
-
|
7
2
|
publisher :greg
|
8
3
|
|
9
4
|
# queue => alice.greg.basic_push.booked
|
10
5
|
# routing_key => greg.basic_push.booked
|
11
6
|
def booked
|
12
|
-
|
7
|
+
$messages << payload
|
13
8
|
end
|
14
9
|
|
15
10
|
queue_for :cancelled, "basic.cancelled"
|
16
11
|
routing_key_for :cancelled, "basic.cancelled"
|
17
12
|
|
18
13
|
def cancelled
|
19
|
-
|
14
|
+
$messages << payload
|
20
15
|
end
|
21
16
|
end
|
22
17
|
|
23
|
-
describe "A Basic Subscriber
|
18
|
+
describe "A Basic Subscriber", :integration => true do
|
24
19
|
let(:connection) { subscriber.connection }
|
25
20
|
let(:subscriber) { BasicPushSubscriber }
|
26
21
|
|
27
|
-
|
28
|
-
|
22
|
+
context "ActionSubscriber.auto_pop!" do
|
23
|
+
it "routes messages to the right place" do
|
24
|
+
channel = connection.create_channel
|
25
|
+
exchange = channel.topic("events")
|
26
|
+
exchange.publish("Ohai Booked", :routing_key => "greg.basic_push.booked")
|
27
|
+
exchange.publish("Ohai Cancelled", :routing_key => "basic.cancelled")
|
28
|
+
sleep 0.1
|
29
29
|
|
30
|
-
|
31
|
-
exchange = channel.topic("events")
|
32
|
-
exchange.publish("Ohai Booked", :routing_key => "greg.basic_push.booked")
|
33
|
-
exchange.publish("Ohai Cancelled", :routing_key => "basic.cancelled")
|
30
|
+
::ActionSubscriber.auto_pop!
|
34
31
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
expect(subscriber::CANCELLED_MESSAGES).to eq(["Ohai Cancelled"])
|
32
|
+
expect($messages).to eq(Set.new(["Ohai Booked", "Ohai Cancelled"]))
|
33
|
+
end
|
34
|
+
end
|
39
35
|
|
40
|
-
|
36
|
+
context "ActionSubscriber.auto_subscribe!" do
|
37
|
+
it "routes messages to the right place" do
|
38
|
+
::ActionSubscriber.auto_subscribe!
|
39
|
+
channel = connection.create_channel
|
40
|
+
exchange = channel.topic("events")
|
41
|
+
exchange.publish("Ohai Booked", :routing_key => "greg.basic_push.booked")
|
42
|
+
exchange.publish("Ohai Cancelled", :routing_key => "basic.cancelled")
|
43
|
+
sleep 0.1
|
44
|
+
|
45
|
+
expect($messages).to eq(Set.new(["Ohai Booked", "Ohai Cancelled"]))
|
46
|
+
end
|
41
47
|
end
|
42
48
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class TwitterSubscriber < ActionSubscriber::Base
|
2
|
+
def tweet
|
3
|
+
$messages << {
|
4
|
+
:decoded => payload,
|
5
|
+
:raw => raw_payload,
|
6
|
+
}
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
describe "Payload Decoding", :integration => true do
|
12
|
+
let(:connection) { subscriber.connection }
|
13
|
+
let(:subscriber) { TwitterSubscriber }
|
14
|
+
let(:json_string) { '{"foo": "bar"}' }
|
15
|
+
|
16
|
+
it "decodes json by default" do
|
17
|
+
::ActionSubscriber.auto_subscribe!
|
18
|
+
channel = connection.create_channel
|
19
|
+
exchange = channel.topic("events")
|
20
|
+
exchange.publish(json_string, :routing_key => "twitter.tweet", :content_type => "application/json")
|
21
|
+
sleep 0.1
|
22
|
+
|
23
|
+
expect($messages).to eq Set.new([{
|
24
|
+
:decoded => JSON.parse(json_string),
|
25
|
+
:raw => json_string,
|
26
|
+
}])
|
27
|
+
end
|
28
|
+
|
29
|
+
context "Custom Decoder" do
|
30
|
+
let(:content_type) { "foo/type" }
|
31
|
+
|
32
|
+
before { ::ActionSubscriber.config.add_decoder(content_type => lambda{ |payload| :foo }) }
|
33
|
+
after { ::ActionSubscriber.config.decoder.delete(content_type) }
|
34
|
+
|
35
|
+
it "it decodes the payload using the custom decoder" do
|
36
|
+
::ActionSubscriber.auto_subscribe!
|
37
|
+
channel = connection.create_channel
|
38
|
+
exchange = channel.topic("events")
|
39
|
+
exchange.publish(json_string, :routing_key => "twitter.tweet", :content_type => content_type)
|
40
|
+
sleep 0.1
|
41
|
+
|
42
|
+
expect($messages).to eq Set.new([{
|
43
|
+
:decoded => :foo,
|
44
|
+
:raw => json_string,
|
45
|
+
}])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class BaconSubscriber < ActionSubscriber::Base
|
2
|
+
manual_acknowledgement!
|
3
|
+
|
4
|
+
def served
|
5
|
+
$messages << "#{payload}::#{$messages.size}"
|
6
|
+
if $messages.size > 2
|
7
|
+
acknowledge
|
8
|
+
else
|
9
|
+
reject
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "Manual Message Acknowledgment", :integration => true do
|
15
|
+
let(:connection) { subscriber.connection }
|
16
|
+
let(:subscriber) { BaconSubscriber }
|
17
|
+
|
18
|
+
it "retries rejected messages and stops retrying acknowledged messages" do
|
19
|
+
::ActionSubscriber.auto_subscribe!
|
20
|
+
channel = connection.create_channel
|
21
|
+
exchange = channel.topic("events")
|
22
|
+
exchange.publish("BACON!", :routing_key => "bacon.served")
|
23
|
+
sleep 0.1
|
24
|
+
|
25
|
+
expect($messages).to eq(Set.new(["BACON!::0", "BACON!::1", "BACON!::2"]))
|
26
|
+
end
|
27
|
+
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
1
|
describe ::ActionSubscriber::DSL do
|
4
2
|
let(:subscriber) { Object.new }
|
5
3
|
before { subscriber.extend(::ActionSubscriber::DSL) }
|
@@ -15,14 +13,6 @@ describe ::ActionSubscriber::DSL do
|
|
15
13
|
it "returns expected queue subscription options" do
|
16
14
|
expect(subscriber.queue_subscription_options).to eq( :manual_ack => true )
|
17
15
|
end
|
18
|
-
|
19
|
-
it "does not acknowledge messages after processing them" do
|
20
|
-
expect(subscriber.acknowledge_messages_after_processing?).to eq(false)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "does not acknowledge messages before processing them" do
|
24
|
-
expect(subscriber.acknowledge_messages_before_processing?).to eq(false)
|
25
|
-
end
|
26
16
|
end
|
27
17
|
|
28
18
|
context "when at_most_once! is set" do
|
@@ -31,14 +21,6 @@ describe ::ActionSubscriber::DSL do
|
|
31
21
|
it "acknowledges messages" do
|
32
22
|
expect(subscriber.acknowledge_messages?).to eq(true)
|
33
23
|
end
|
34
|
-
|
35
|
-
it "acknowledges messages before processing them" do
|
36
|
-
expect(subscriber.acknowledge_messages_before_processing?).to eq(true)
|
37
|
-
end
|
38
|
-
|
39
|
-
it "does not acknowledge messages after processing them" do
|
40
|
-
expect(subscriber.acknowledge_messages_after_processing?).to eq(false)
|
41
|
-
end
|
42
24
|
end
|
43
25
|
|
44
26
|
context "when at_least_once! is set" do
|
@@ -47,14 +29,6 @@ describe ::ActionSubscriber::DSL do
|
|
47
29
|
it "acknowledges messages" do
|
48
30
|
expect(subscriber.acknowledge_messages?).to eq(true)
|
49
31
|
end
|
50
|
-
|
51
|
-
it "does not acknowledge messages before processing them" do
|
52
|
-
expect(subscriber.acknowledge_messages_before_processing?).to eq(false)
|
53
|
-
end
|
54
|
-
|
55
|
-
it "acknowledges messages after processing them" do
|
56
|
-
expect(subscriber.acknowledge_messages_after_processing?).to eq(true)
|
57
|
-
end
|
58
32
|
end
|
59
33
|
|
60
34
|
context "when no_acknowledgement! is set" do
|
@@ -63,28 +37,12 @@ describe ::ActionSubscriber::DSL do
|
|
63
37
|
it "does not acknowledge messages" do
|
64
38
|
expect(subscriber.acknowledge_messages?).to eq(false)
|
65
39
|
end
|
66
|
-
|
67
|
-
it "does not acknowledge messages after processing them" do
|
68
|
-
expect(subscriber.acknowledge_messages_after_processing?).to eq(false)
|
69
|
-
end
|
70
|
-
|
71
|
-
it "does not acknowledge messages before processing them" do
|
72
|
-
expect(subscriber.acknowledge_messages_before_processing?).to eq(false)
|
73
|
-
end
|
74
40
|
end
|
75
41
|
|
76
42
|
context "default" do
|
77
43
|
it "does not acknowledge messages" do
|
78
44
|
expect(subscriber.acknowledge_messages?).to eq(false)
|
79
45
|
end
|
80
|
-
|
81
|
-
it "does not acknowledge messages after processing them" do
|
82
|
-
expect(subscriber.acknowledge_messages_after_processing?).to eq(false)
|
83
|
-
end
|
84
|
-
|
85
|
-
it "does not acknowledge messages before processing them" do
|
86
|
-
expect(subscriber.acknowledge_messages_before_processing?).to eq(false)
|
87
|
-
end
|
88
46
|
end
|
89
47
|
end
|
90
48
|
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'spec_helper'
|
2
1
|
require 'action_subscriber/middleware/error_handler'
|
3
2
|
|
4
3
|
describe ActionSubscriber::Middleware::ErrorHandler do
|
@@ -19,17 +18,5 @@ describe ActionSubscriber::Middleware::ErrorHandler do
|
|
19
18
|
|
20
19
|
subject.call(env)
|
21
20
|
end
|
22
|
-
|
23
|
-
context "when the subscriber was expecting to acknowledge the message" do
|
24
|
-
before { allow(env.subscriber).to receive(:acknowledge_messages_after_processing?).and_return(true) }
|
25
|
-
|
26
|
-
it "calls the exception handler and rejects the message" do
|
27
|
-
handler = ::ActionSubscriber.configuration.error_handler
|
28
|
-
expect(handler).to receive(:call).with(error, env.to_h)
|
29
|
-
expect(env).to receive(:reject).with(no_args)
|
30
|
-
|
31
|
-
subject.call(env)
|
32
|
-
end
|
33
|
-
end
|
34
21
|
end
|
35
22
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
1
|
describe ActionSubscriber::Middleware::Router do
|
4
2
|
include_context 'action subscriber middleware env'
|
5
3
|
|
@@ -9,16 +7,4 @@ describe ActionSubscriber::Middleware::Router do
|
|
9
7
|
allow_any_instance_of(env.subscriber).to receive(env.action)
|
10
8
|
subject.call(env)
|
11
9
|
end
|
12
|
-
|
13
|
-
it "acknowledges messages after processing if the subscriber flag is set" do
|
14
|
-
allow(env.subscriber).to receive(:acknowledge_messages_after_processing?).and_return(true)
|
15
|
-
expect(env).to receive(:acknowledge)
|
16
|
-
subject.call(env)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "acknowledges messages before processing if the subscriber flag is set" do
|
20
|
-
allow(env.subscriber).to receive(:acknowledge_messages_before_processing?).and_return(true)
|
21
|
-
expect(env).to receive(:acknowledge)
|
22
|
-
subject.call(env)
|
23
|
-
end
|
24
10
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,14 +1,8 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'bundler'
|
3
3
|
|
4
|
-
require 'simplecov'
|
5
4
|
ENV['APP_NAME'] = 'Alice'
|
6
5
|
|
7
|
-
|
8
|
-
SimpleCov.start do
|
9
|
-
add_filter 'spec'
|
10
|
-
end
|
11
|
-
|
12
6
|
Bundler.require(:default, :development, :test)
|
13
7
|
|
14
8
|
require 'action_subscriber'
|
@@ -23,4 +17,16 @@ RSpec.configure do |config|
|
|
23
17
|
config.mock_with :rspec do |mocks|
|
24
18
|
mocks.verify_partial_doubles = true
|
25
19
|
end
|
20
|
+
|
21
|
+
config.before(:each, :integration => true) do
|
22
|
+
$messages = Set.new
|
23
|
+
::ActionSubscriber::RabbitConnection.connect!
|
24
|
+
::ActionSubscriber.setup_queues!
|
25
|
+
end
|
26
|
+
config.after(:each, :integration => true) do
|
27
|
+
::ActionSubscriber::RabbitConnection.disconnect!
|
28
|
+
::ActionSubscriber::Base.inherited_classes.each do |klass|
|
29
|
+
klass.instance_variable_set("@_queues", nil)
|
30
|
+
end
|
31
|
+
end
|
26
32
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: action_subscriber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Stien
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date:
|
15
|
+
date: 2015-02-03 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: activesupport
|
@@ -113,35 +113,35 @@ dependencies:
|
|
113
113
|
- !ruby/object:Gem::Version
|
114
114
|
version: '0'
|
115
115
|
- !ruby/object:Gem::Dependency
|
116
|
-
name:
|
116
|
+
name: rabbitmq_http_api_client
|
117
117
|
requirement: !ruby/object:Gem::Requirement
|
118
118
|
requirements:
|
119
119
|
- - "~>"
|
120
120
|
- !ruby/object:Gem::Version
|
121
|
-
version:
|
121
|
+
version: 1.2.0
|
122
122
|
type: :development
|
123
123
|
prerelease: false
|
124
124
|
version_requirements: !ruby/object:Gem::Requirement
|
125
125
|
requirements:
|
126
126
|
- - "~>"
|
127
127
|
- !ruby/object:Gem::Version
|
128
|
-
version:
|
128
|
+
version: 1.2.0
|
129
129
|
- !ruby/object:Gem::Dependency
|
130
|
-
name:
|
130
|
+
name: rspec
|
131
131
|
requirement: !ruby/object:Gem::Requirement
|
132
132
|
requirements:
|
133
|
-
- - "
|
133
|
+
- - "~>"
|
134
134
|
- !ruby/object:Gem::Version
|
135
|
-
version: '0'
|
135
|
+
version: '3.0'
|
136
136
|
type: :development
|
137
137
|
prerelease: false
|
138
138
|
version_requirements: !ruby/object:Gem::Requirement
|
139
139
|
requirements:
|
140
|
-
- - "
|
140
|
+
- - "~>"
|
141
141
|
- !ruby/object:Gem::Version
|
142
|
-
version: '0'
|
142
|
+
version: '3.0'
|
143
143
|
- !ruby/object:Gem::Dependency
|
144
|
-
name:
|
144
|
+
name: rake
|
145
145
|
requirement: !ruby/object:Gem::Requirement
|
146
146
|
requirements:
|
147
147
|
- - ">="
|
@@ -168,6 +168,7 @@ extra_rdoc_files: []
|
|
168
168
|
files:
|
169
169
|
- ".gitignore"
|
170
170
|
- ".rspec"
|
171
|
+
- ".travis.yml"
|
171
172
|
- Gemfile
|
172
173
|
- LICENSE
|
173
174
|
- LICENSE.txt
|
@@ -199,7 +200,13 @@ files:
|
|
199
200
|
- lib/action_subscriber/subscribable.rb
|
200
201
|
- lib/action_subscriber/threadpool.rb
|
201
202
|
- lib/action_subscriber/version.rb
|
203
|
+
- spec/integration/around_filters_spec.rb
|
204
|
+
- spec/integration/at_least_once_spec.rb
|
205
|
+
- spec/integration/at_most_once_spec.rb
|
206
|
+
- spec/integration/automatic_reconnect_spec.rb
|
202
207
|
- spec/integration/basic_subscriber_spec.rb
|
208
|
+
- spec/integration/decoding_payloads_spec.rb
|
209
|
+
- spec/integration/manual_acknowledgement_spec.rb
|
203
210
|
- spec/lib/action_subscriber/base_spec.rb
|
204
211
|
- spec/lib/action_subscriber/configuration_spec.rb
|
205
212
|
- spec/lib/action_subscriber/dsl_spec.rb
|
@@ -214,7 +221,7 @@ files:
|
|
214
221
|
- spec/lib/action_subscriber/threadpool_spec.rb
|
215
222
|
- spec/spec_helper.rb
|
216
223
|
- spec/support/user_subscriber.rb
|
217
|
-
homepage:
|
224
|
+
homepage: https://github.com/moneydesktop/action_subscriber
|
218
225
|
licenses:
|
219
226
|
- MIT
|
220
227
|
metadata: {}
|
@@ -234,13 +241,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
234
241
|
version: '0'
|
235
242
|
requirements: []
|
236
243
|
rubyforge_project:
|
237
|
-
rubygems_version: 2.4.
|
244
|
+
rubygems_version: 2.4.5
|
238
245
|
signing_key:
|
239
246
|
specification_version: 4
|
240
247
|
summary: ActionSubscriber is a DSL that allows a rails app to consume messages from
|
241
248
|
a RabbitMQ broker.
|
242
249
|
test_files:
|
250
|
+
- spec/integration/around_filters_spec.rb
|
251
|
+
- spec/integration/at_least_once_spec.rb
|
252
|
+
- spec/integration/at_most_once_spec.rb
|
253
|
+
- spec/integration/automatic_reconnect_spec.rb
|
243
254
|
- spec/integration/basic_subscriber_spec.rb
|
255
|
+
- spec/integration/decoding_payloads_spec.rb
|
256
|
+
- spec/integration/manual_acknowledgement_spec.rb
|
244
257
|
- spec/lib/action_subscriber/base_spec.rb
|
245
258
|
- spec/lib/action_subscriber/configuration_spec.rb
|
246
259
|
- spec/lib/action_subscriber/dsl_spec.rb
|