action_subscriber 5.1.5-java → 5.2.3-java

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca5face8fc684985f21cab2d0be98de2e2f6d8c56d08a403c62075291adbda8a
4
- data.tar.gz: 3210c548ea05b9da02a358691434e22d875fcea6d11496959a849fee36223bfa
3
+ metadata.gz: 70428c30ef852da7b3e5678f2e9bbf43dbaaac46a0280a865e9aa314efb43fc3
4
+ data.tar.gz: 67d69b8f403eba527f180e9c0ea7d5eb49faabfe2adc91f8e42c192d4600e97c
5
5
  SHA512:
6
- metadata.gz: 2089e546d6494cf331f658b26d4ff57f35151ddf231e586082dd951e6f635f29d816fe0b3b2d7302f7fd25a5141e56dcc8f1e56909f3973a3b8ba86b908cb64a
7
- data.tar.gz: 7f72c8204ed5bc09a61c1f3b62f6f5fb03bc21b66a6ca388f758c8bea776b93b6e275d99f0c77271652a0f0a3d7a3cb1692c237156d577aa47b67df5d36cbf69
6
+ metadata.gz: 1eb8b21638811db8325eb6ccf27091aef00d9394324b2e46c41ce2ef2dfa3ac90be2a4b4e448afc8d910e0325e37e033b5fa071cb1545fdae28fb5e264dc2527
7
+ data.tar.gz: c3895c215507a1e61712ef071cf96ce4dfaca092df3172d044c3a97933970dd317260bac8c9aef791efb52f58cbdc027521fee07365a2254b8d08dd049ea6f53
data/.travis.yml CHANGED
@@ -4,11 +4,10 @@ os:
4
4
  dist:
5
5
  trusty
6
6
  rvm:
7
- - 2.2.6
8
- - 2.3.3
9
- - jruby-9.0.5.0
10
- - jruby-9.1.7.0
7
+ - 2.3.8
8
+ - 2.5.7
11
9
  - jruby-9.1.12.0
10
+ - jruby-9.2.7.0
12
11
  - jruby-head
13
12
  services:
14
13
  - rabbitmq
data/README.md CHANGED
@@ -135,6 +135,7 @@ Other configuration options include :
135
135
  * config.network_recovery_interval - reconnection interval for TCP connection failures (default 1)
136
136
  * config.password - RabbitMQ password (default "guest")
137
137
  * config.prefetch - number of messages to hold in the local queue in subscriber mode
138
+ * config.resubscribe_on_consumer_cancellation - resubscribe when the consumer is cancelled (queue deleted or cluster fails, default true)
138
139
  * config.seconds_to_wait_for_graceful_shutdown - time to wait before force stopping server after shutdown signal
139
140
  * config.threadpool_size - set the number of threads available to action_subscriber
140
141
  * config.timeout - how many seconds to allow rabbit to respond before timing out
@@ -33,9 +33,9 @@ Gem::Specification.new do |spec|
33
33
  spec.add_development_dependency "active_publisher", "~> 0.1.5"
34
34
  spec.add_development_dependency "activerecord", ">= 3.2"
35
35
  spec.add_development_dependency "bundler", ">= 1.6"
36
- spec.add_development_dependency "pry-coolline"
37
36
  spec.add_development_dependency "pry-nav"
38
37
  spec.add_development_dependency "rabbitmq_http_api_client", "~> 1.2.0"
39
38
  spec.add_development_dependency "rspec", "~> 3.0"
40
39
  spec.add_development_dependency "rake"
40
+ spec.add_development_dependency "simplecov"
41
41
  end
@@ -2,6 +2,7 @@ module ActionSubscriber
2
2
  module Bunny
3
3
  module Subscriber
4
4
  include ::ActionSubscriber::Logging
5
+ include ::ActionSubscriber::Subscriber
5
6
 
6
7
  def bunny_consumers
7
8
  @bunny_consumers ||= []
@@ -26,35 +27,51 @@ module ActionSubscriber
26
27
 
27
28
  def start_subscribers!
28
29
  subscriptions.each do |subscription|
29
- route = subscription[:route]
30
- queue = subscription[:queue]
31
- channel = queue.channel
32
- threadpool = ::ActionSubscriber::ThreadPools.threadpools.fetch(route.threadpool_name)
33
- channel.prefetch(route.prefetch) if route.acknowledgements?
34
- consumer = ::Bunny::Consumer.new(channel, queue, channel.generate_consumer_tag, !route.acknowledgements?)
35
- consumer.on_delivery do |delivery_info, properties, encoded_payload|
36
- ::ActiveSupport::Notifications.instrument "received_event.action_subscriber", :payload_size => encoded_payload.bytesize, :queue => queue.name
37
- properties = {
38
- :action => route.action,
39
- :channel => queue.channel,
40
- :content_type => properties.content_type,
41
- :delivery_tag => delivery_info.delivery_tag,
42
- :exchange => delivery_info.exchange,
43
- :headers => properties.headers,
44
- :message_id => properties.message_id,
45
- :routing_key => delivery_info.routing_key,
46
- :queue => queue.name,
47
- :uses_acknowledgements => route.acknowledgements?,
48
- }
49
- env = ::ActionSubscriber::Middleware::Env.new(route.subscriber, encoded_payload, properties)
50
- run_env(env, threadpool)
51
- end
52
- bunny_consumers << consumer
53
- queue.subscribe_with(consumer)
30
+ start_subscriber_for_subscription(subscription)
54
31
  end
55
32
  end
56
33
 
57
- private
34
+ private
35
+
36
+ def start_subscriber_for_subscription(subscription)
37
+ route = subscription[:route]
38
+ queue = subscription[:queue]
39
+ channel = queue.channel
40
+ threadpool = ::ActionSubscriber::ThreadPools.threadpools.fetch(route.threadpool_name)
41
+ channel.prefetch(route.prefetch) if route.acknowledgements?
42
+ consumer = ::Bunny::Consumer.new(channel, queue, channel.generate_consumer_tag, !route.acknowledgements?)
43
+
44
+ if ::ActionSubscriber.configuration.resubscribe_on_consumer_cancellation
45
+ # Add cancellation callback to rebuild subscriber on cancel.
46
+ consumer.on_cancellation do
47
+ ::ActionSubscriber.logger.warn "Cancellation received for queue consumer: #{queue.name}, rebuilding subscription..."
48
+ bunny_consumers.delete(consumer)
49
+ channel.close
50
+ safely_restart_subscriber(subscription)
51
+ end
52
+ end
53
+
54
+ consumer.on_delivery do |delivery_info, properties, encoded_payload|
55
+ ::ActiveSupport::Notifications.instrument "received_event.action_subscriber", :payload_size => encoded_payload.bytesize, :queue => queue.name
56
+ properties = {
57
+ :action => route.action,
58
+ :channel => queue.channel,
59
+ :content_type => properties.content_type,
60
+ :delivery_tag => delivery_info.delivery_tag,
61
+ :exchange => delivery_info.exchange,
62
+ :headers => properties.headers,
63
+ :message_id => properties.message_id,
64
+ :routing_key => delivery_info.routing_key,
65
+ :queue => queue.name,
66
+ :uses_acknowledgements => route.acknowledgements?,
67
+ }
68
+ env = ::ActionSubscriber::Middleware::Env.new(route.subscriber, encoded_payload, properties)
69
+ run_env(env, threadpool)
70
+ end
71
+
72
+ bunny_consumers << consumer
73
+ queue.subscribe_with(consumer)
74
+ end
58
75
 
59
76
  def setup_queue(route)
60
77
  channel = ::ActionSubscriber::RabbitConnection.with_connection{|connection| connection.create_channel(nil, 1) }
@@ -16,6 +16,7 @@ module ActionSubscriber
16
16
  :password,
17
17
  :port,
18
18
  :prefetch,
19
+ :resubscribe_on_consumer_cancellation,
19
20
  :seconds_to_wait_for_graceful_shutdown,
20
21
  :threadpool_size,
21
22
  :timeout,
@@ -42,6 +43,7 @@ module ActionSubscriber
42
43
  :password => "guest",
43
44
  :port => 5672,
44
45
  :prefetch => 2,
46
+ :resubscribe_on_consumer_cancellation => true,
45
47
  :seconds_to_wait_for_graceful_shutdown => 30,
46
48
  :threadpool_size => 8,
47
49
  :timeout => 1,
@@ -75,8 +77,8 @@ module ActionSubscriber
75
77
  end
76
78
 
77
79
  ::ActionSubscriber::Configuration::DEFAULTS.each_pair do |key, value|
78
- setting = cli_options[key] || yaml_config[key.to_s]
79
- ::ActionSubscriber.config.__send__("#{key}=", setting) if setting
80
+ exists, setting = fetch_config_value(key, cli_options, yaml_config)
81
+ ::ActionSubscriber.config.__send__("#{key}=", setting) if exists
80
82
  end
81
83
 
82
84
  true
@@ -84,6 +86,15 @@ module ActionSubscriber
84
86
  end
85
87
  end
86
88
 
89
+ def self.fetch_config_value(key, cli_options, yaml_config)
90
+ return [true, cli_options[key]] if cli_options.key?(key)
91
+ return [true, cli_options[key.to_s]] if cli_options.key?(key.to_s)
92
+ return [true, yaml_config[key]] if yaml_config.key?(key)
93
+ return [true, yaml_config[key.to_s]] if yaml_config.key?(key.to_s)
94
+ [false, nil]
95
+ end
96
+ private_class_method :fetch_config_value
97
+
87
98
  ##
88
99
  # Instance Methods
89
100
  #
@@ -2,9 +2,11 @@ module ActionSubscriber
2
2
  module MarchHare
3
3
  module Subscriber
4
4
  include ::ActionSubscriber::Logging
5
+ include ::ActionSubscriber::Subscriber
5
6
 
6
7
  def cancel_consumers!
7
- march_hare_consumers.each(&:cancel)
8
+ # Cancel any non-cancelled consumers.
9
+ march_hare_consumers.reject(&:cancelled?).each(&:cancel)
8
10
  ::ActionSubscriber::ThreadPools.threadpools.each do |name, threadpool|
9
11
  threadpool.shutdown
10
12
  end
@@ -26,33 +28,49 @@ module ActionSubscriber
26
28
 
27
29
  def start_subscribers!
28
30
  subscriptions.each do |subscription|
29
- route = subscription[:route]
30
- queue = subscription[:queue]
31
- queue.channel.prefetch = route.prefetch if route.acknowledgements?
32
- threadpool = ::ActionSubscriber::ThreadPools.threadpools.fetch(route.threadpool_name)
33
- consumer = queue.subscribe(route.queue_subscription_options) do |metadata, encoded_payload|
34
- ::ActiveSupport::Notifications.instrument "received_event.action_subscriber", :payload_size => encoded_payload.bytesize, :queue => queue.name
35
- properties = {
36
- :action => route.action,
37
- :channel => queue.channel,
38
- :content_type => metadata.content_type,
39
- :delivery_tag => metadata.delivery_tag,
40
- :exchange => metadata.exchange,
41
- :headers => _normalized_headers(metadata),
42
- :message_id => metadata.message_id,
43
- :routing_key => metadata.routing_key,
44
- :queue => queue.name,
45
- :uses_acknowledgements => route.acknowledgements?,
46
- }
47
- env = ::ActionSubscriber::Middleware::Env.new(route.subscriber, encoded_payload, properties)
48
- run_env(env, threadpool)
31
+ start_subscriber_for_subscription(subscription)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def start_subscriber_for_subscription(subscription)
38
+ route = subscription[:route]
39
+ queue = subscription[:queue]
40
+ queue.channel.prefetch = route.prefetch if route.acknowledgements?
41
+ threadpool = ::ActionSubscriber::ThreadPools.threadpools.fetch(route.threadpool_name)
42
+ opts = route.queue_subscription_options
43
+
44
+ if ::ActionSubscriber.configuration.resubscribe_on_consumer_cancellation
45
+ # Add cancellation callback to rebuild subscriber on cancel.
46
+ opts[:on_cancellation] = lambda do |the_consumer|
47
+ ::ActionSubscriber.logger.warn "Cancellation received for queue consumer: #{queue.name}, rebuilding subscription..."
48
+ march_hare_consumers.delete(the_consumer)
49
+ queue.channel.close
50
+ safely_restart_subscriber(subscription)
49
51
  end
52
+ end
50
53
 
51
- march_hare_consumers << consumer
54
+ consumer = queue.subscribe(opts) do |metadata, encoded_payload|
55
+ ::ActiveSupport::Notifications.instrument "received_event.action_subscriber", :payload_size => encoded_payload.bytesize, :queue => queue.name
56
+ properties = {
57
+ :action => route.action,
58
+ :channel => queue.channel,
59
+ :content_type => metadata.content_type,
60
+ :delivery_tag => metadata.delivery_tag,
61
+ :exchange => metadata.exchange,
62
+ :headers => _normalized_headers(metadata),
63
+ :message_id => metadata.message_id,
64
+ :routing_key => metadata.routing_key,
65
+ :queue => queue.name,
66
+ :uses_acknowledgements => route.acknowledgements?,
67
+ }
68
+ env = ::ActionSubscriber::Middleware::Env.new(route.subscriber, encoded_payload, properties)
69
+ run_env(env, threadpool)
52
70
  end
53
- end
54
71
 
55
- private
72
+ march_hare_consumers << consumer
73
+ end
56
74
 
57
75
  def setup_queue(route)
58
76
  channel = ::ActionSubscriber::RabbitConnection.with_connection{|connection| connection.create_channel }
@@ -30,9 +30,22 @@ module ActionSubscriber
30
30
  ::MarchHare::ThreadPools.fixed_of_size(options[:threadpool_size])
31
31
  end
32
32
  connection = ::MarchHare.connect(options)
33
+ connection.on_blocked do |reason|
34
+ on_blocked(reason)
35
+ end
36
+ connection.on_unblocked do
37
+ on_unblocked
38
+ end
39
+ connection
33
40
  else
34
41
  connection = ::Bunny.new(options)
35
42
  connection.start
43
+ connection.on_blocked do |blocked_message|
44
+ on_blocked(blocked_message.reason)
45
+ end
46
+ connection.on_unblocked do
47
+ on_unblocked
48
+ end
36
49
  connection
37
50
  end
38
51
  end
@@ -59,5 +72,15 @@ module ActionSubscriber
59
72
  }
60
73
  end
61
74
  private_class_method :connection_options
75
+
76
+ def self.on_blocked(reason)
77
+ ::ActiveSupport::Notifications.instrument("connection_blocked.action_subscriber", :reason => reason)
78
+ end
79
+ private_class_method :on_blocked
80
+
81
+ def self.on_unblocked
82
+ ::ActiveSupport::Notifications.instrument("connection_unblocked.action_subscriber")
83
+ end
84
+ private_class_method :on_unblocked
62
85
  end
63
86
  end
@@ -0,0 +1,18 @@
1
+ module ActionSubscriber
2
+ module Subscriber
3
+ # resubscribes to queue, continuously retrying to subscribe in the event of a potentially recoverable error while
4
+ # also calling the error handler to surface that a subscription failure happened
5
+ def safely_restart_subscriber(subscription)
6
+ subscription[:queue] = setup_queue(subscription[:route])
7
+ start_subscriber_for_subscription(subscription)
8
+ rescue StandardError => e
9
+ ::ActionSubscriber.configuration.error_handler.call(e)
10
+ raise e unless e.message =~ /queue .* process is stopped by supervisor/
11
+
12
+ nap_time = rand(2.0..5.0)
13
+ ::ActionSubscriber.logger.error("Failed to resubscribe to #{subscription[:queue].name}, retrying again in #{nap_time} seconds...")
14
+ sleep(nap_time)
15
+ retry
16
+ end
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
1
  module ActionSubscriber
2
- VERSION = "5.1.5"
2
+ VERSION = "5.2.3"
3
3
  end
@@ -21,6 +21,7 @@ require "action_subscriber/message_retry"
21
21
  require "action_subscriber/middleware"
22
22
  require "action_subscriber/rabbit_connection"
23
23
  require "action_subscriber/subscribable"
24
+ require "action_subscriber/subscriber"
24
25
  require "action_subscriber/thread_pools"
25
26
  require "action_subscriber/bunny/subscriber"
26
27
  require "action_subscriber/march_hare/subscriber"
@@ -7,36 +7,36 @@ class GusSubscriber < ActionSubscriber::Base
7
7
  end
8
8
 
9
9
  describe "Automatically reconnect on connection failure", :integration => true, :slow => true do
10
- let(:draw_routes) do
11
- ::ActionSubscriber.draw_routes do
12
- default_routes_for GusSubscriber
13
- end
14
- end
15
- let(:http_client) { RabbitMQ::HTTP::Client.new("http://127.0.0.1:15672") }
16
- let(:subscriber) { GusSubscriber }
10
+ let(:draw_routes) do
11
+ ::ActionSubscriber.draw_routes do
12
+ default_routes_for GusSubscriber
13
+ end
14
+ end
15
+ let(:http_client) { RabbitMQ::HTTP::Client.new("http://127.0.0.1:15672") }
16
+ let(:subscriber) { GusSubscriber }
17
17
 
18
- it "reconnects when a connection drops" do
19
- ::ActionSubscriber::start_subscribers!
20
- ::ActivePublisher.publish("gus.spoke", "First", "events")
21
- verify_expectation_within(5.0) do
22
- expect($messages).to eq(Set.new(["First"]))
23
- end
18
+ it "reconnects when a connection drops" do
19
+ ::ActionSubscriber::start_subscribers!
20
+ ::ActivePublisher.publish("gus.spoke", "First", "events")
21
+ verify_expectation_within(5.0) do
22
+ expect($messages).to eq(Set.new(["First"]))
23
+ end
24
24
 
25
- close_all_connections!
26
- sleep 5.0
27
- verify_expectation_within(5.0) do
28
- expect(::ActionSubscriber::RabbitConnection.with_connection{|connection| connection.open?}).to eq(true)
29
- end
25
+ close_all_connections!
26
+ sleep 5.0
27
+ verify_expectation_within(5.0) do
28
+ expect(::ActionSubscriber::RabbitConnection.with_connection{|connection| connection.open?}).to eq(true)
29
+ end
30
30
 
31
- ::ActivePublisher.publish("gus.spoke", "Second", "events")
32
- verify_expectation_within(5.0) do
33
- expect($messages).to eq(Set.new(["First", "Second"]))
34
- end
35
- end
31
+ ::ActivePublisher.publish("gus.spoke", "Second", "events")
32
+ verify_expectation_within(5.0) do
33
+ expect($messages).to eq(Set.new(["First", "Second"]))
34
+ end
35
+ end
36
36
 
37
- def close_all_connections!
38
- http_client.list_connections.each do |conn_info|
39
- http_client.close_connection(conn_info.name)
40
- end
41
- end
37
+ def close_all_connections!
38
+ http_client.list_connections.each do |conn_info|
39
+ http_client.close_connection(conn_info.name)
40
+ end
41
+ end
42
42
  end
@@ -0,0 +1,123 @@
1
+ require "spec_helper"
2
+ require "rabbitmq/http/client"
3
+
4
+ class YoloSubscriber < ActionSubscriber::Base
5
+ def created
6
+ $messages << payload
7
+ end
8
+ end
9
+
10
+ describe "Automatically handles consumer cancellation", :integration => true, :slow => true do
11
+ let(:draw_routes) do
12
+ ::ActionSubscriber.draw_routes do
13
+ default_routes_for ::YoloSubscriber
14
+ end
15
+ end
16
+ let(:http_client) { ::RabbitMQ::HTTP::Client.new("http://127.0.0.1:15672") }
17
+ let(:subscriber) { ::YoloSubscriber }
18
+
19
+ it "resubscribes on cancellation" do
20
+ ::ActionSubscriber::start_subscribers!
21
+ ::ActivePublisher.publish("yolo.created", "First", "events")
22
+ verify_expectation_within(5.0) do
23
+ expect($messages).to eq(::Set.new(["First"]))
24
+ end
25
+
26
+ consumers = rabbit_consumers.dup
27
+
28
+ # Signal a cancellation event to all subscribers.
29
+ delete_all_queues!
30
+
31
+ # Give consumers a chance to restart.
32
+ sleep 2.0
33
+
34
+ expect(rabbit_consumers).to_not eq(consumers)
35
+
36
+ ::ActivePublisher.publish("yolo.created", "Second", "events")
37
+ verify_expectation_within(5.0) do
38
+ expect($messages).to eq(Set.new(["First", "Second"]))
39
+ end
40
+ end
41
+
42
+ context "when resubscribe on consumer cancellation is disabled" do
43
+ before do
44
+ allow(::ActionSubscriber.configuration).to receive(:resubscribe_on_consumer_cancellation).and_return(false)
45
+ end
46
+
47
+ it "does not resubscribe on cancellation" do
48
+ ::ActionSubscriber::start_subscribers!
49
+ ::ActivePublisher.publish("yolo.created", "First", "events")
50
+ verify_expectation_within(5.0) do
51
+ expect($messages).to eq(::Set.new(["First"]))
52
+ end
53
+
54
+ consumers = rabbit_consumers.dup
55
+
56
+ # Signal a cancellation event to all subscribers.
57
+ delete_all_queues!
58
+
59
+ # Give consumers a chance to restart.
60
+ sleep 2.0
61
+
62
+ # Verify the consumers did not change.
63
+ expect(rabbit_consumers).to eq(consumers)
64
+
65
+ ::ActivePublisher.publish("yolo.created", "Second", "events")
66
+
67
+ # Force sleep 2 seconds to ensure a resubscribe did not happen and messages were not processed.
68
+ sleep 2.0
69
+ expect($messages).to eq(Set.new(["First"]))
70
+ end
71
+ end
72
+
73
+ describe "resubscription logic" do
74
+ let(:subscription) { subject.send(:subscriptions).first }
75
+ subject { ::ActionSubscriber.send(:route_set) }
76
+
77
+ it "sets up consumers" do
78
+ if ::RUBY_PLATFORM == "java"
79
+ expect { subject.safely_restart_subscriber(subscription) }.to change { subject.march_hare_consumers.count }.from(0).to(1)
80
+ else
81
+ expect { subject.safely_restart_subscriber(subscription) }.to change { subject.bunny_consumers.count }.from(0).to(1)
82
+ end
83
+ end
84
+
85
+ context "when error is raised during resubscription process" do
86
+ context "and error is one that can be retried" do
87
+ let(:error) { ::RuntimeError.new("queue 're.created' in vhost '/' process is stopped by supervisor") }
88
+
89
+ it "retries resubscription process" do
90
+ expect(subject).to receive(:setup_queue).and_raise(error).ordered
91
+ expect(subject).to receive(:setup_queue).and_raise(error).ordered
92
+ expect(subject).to receive(:setup_queue).and_call_original.ordered
93
+ expect(::ActionSubscriber.config.error_handler).to receive(:call).with(error).twice
94
+ expect(::ActionSubscriber.logger).to receive(:error).twice
95
+ expect(subject).to receive(:sleep).twice # mostly to skip the delay
96
+ subject.safely_restart_subscriber(subscription)
97
+ end
98
+ end
99
+
100
+ context "and error is one that can't be retried" do
101
+ let(:error) { ::RuntimeError.new("kaBOOM") }
102
+
103
+ it "calls error handler and raises" do
104
+ expect(subject).to receive(:setup_queue).and_raise(error).ordered
105
+ expect(::ActionSubscriber.config.error_handler).to receive(:call).with(error).once
106
+ expect(subject).to_not receive(:sleep)
107
+ expect { subject.safely_restart_subscriber(subscription) }.to raise_error(error)
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ def rabbit_consumers
114
+ route_set = ::ActionSubscriber.send(:route_set)
115
+ route_set.try(:bunny_consumers) || route_set.try(:march_hare_consumers)
116
+ end
117
+
118
+ def delete_all_queues!
119
+ http_client.list_queues.each do |queue|
120
+ http_client.delete_queue(queue.vhost, queue.name)
121
+ end
122
+ end
123
+ end
@@ -24,6 +24,13 @@ describe ::ActionSubscriber::Configuration do
24
24
  ::ActionSubscriber::Configuration.configure_from_yaml_and_cli({}, true)
25
25
  end
26
26
  end
27
+
28
+ it "can override a true value with a false value" do
29
+ expect(::ActionSubscriber.configuration.verify_peer).to eq(true)
30
+ expect(::ActionSubscriber.configuration).to receive(:verify_peer=).with(false).and_call_original
31
+ ::ActionSubscriber::Configuration.configure_from_yaml_and_cli({"verify_peer" => false}, true)
32
+ expect(::ActionSubscriber.configuration.verify_peer).to eq(false)
33
+ end
27
34
  end
28
35
 
29
36
  describe "add_decoder" do
@@ -0,0 +1,63 @@
1
+ require "spec_helper"
2
+
3
+ describe ::ActionSubscriber::RabbitConnection do
4
+ let(:reason) { "low on disk" }
5
+
6
+ before { ActionSubscriber.draw_routes {} }
7
+
8
+ context "on_block" do
9
+ if ::RUBY_PLATFORM == "java"
10
+ def trigger_mocked_blocking_event(connection, reason)
11
+ amqp_message = ::Java::ComRabbitmqClient::AMQP::Connection::Blocked::Builder.new.
12
+ reason(reason).build
13
+ amq_command = ::Java::ComRabbitmqClientImpl::AMQCommand.new(amqp_message)
14
+
15
+ connection.send(:processControlCommand, amq_command)
16
+ end
17
+ else
18
+ def trigger_mocked_blocking_event(connection, reason)
19
+ connection.send(:handle_frame, 0, ::AMQ::Protocol::Connection::Blocked.new(reason))
20
+ end
21
+ end
22
+
23
+ it "can deliver an on_blocked message" do
24
+ expect(::ActiveSupport::Notifications).to receive(:instrument).
25
+ with("connection_blocked.action_subscriber", :reason => reason)
26
+
27
+ described_class.with_connection do |connection|
28
+ # NOTE: Trigger the receiving of a blocked message from the broker.
29
+ # It's a bit of a hack but it is a more realistic test without changing
30
+ # memory alarms.
31
+ trigger_mocked_blocking_event(connection, reason)
32
+ end
33
+ end
34
+ end
35
+
36
+ context "on_unblocked" do
37
+ if ::RUBY_PLATFORM == "java"
38
+ def trigger_mocked_unblocked_event(connection, reason)
39
+ amqp_message = ::Java::ComRabbitmqClient::AMQP::Connection::Unblocked::Builder.new.
40
+ build
41
+ amq_command = ::Java::ComRabbitmqClientImpl::AMQCommand.new(amqp_message)
42
+
43
+ connection.send(:processControlCommand, amq_command)
44
+ end
45
+ else
46
+ def trigger_mocked_unblocked_event(connection, reason)
47
+ connection.send(:handle_frame, 0, ::AMQ::Protocol::Connection::Unblocked.new)
48
+ end
49
+ end
50
+
51
+ it "can deliver an on_unblocked message" do
52
+ expect(::ActiveSupport::Notifications).to receive(:instrument).
53
+ with("connection_unblocked.action_subscriber")
54
+
55
+ described_class.with_connection do |connection|
56
+ # NOTE: Trigger the receiving of an unblocked message from the broker.
57
+ # It's a bit of a hack but it is a more realistic test without changing
58
+ # memory alarms.
59
+ trigger_mocked_unblocked_event(connection, reason)
60
+ end
61
+ end
62
+ end
63
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,14 @@
1
1
  require 'rubygems'
2
2
  require 'bundler'
3
3
 
4
+ unless ENV["NO_COV"]
5
+ require "simplecov"
6
+ ::SimpleCov.start do
7
+ enable_coverage :branch
8
+ add_filter "spec"
9
+ end
10
+ end
11
+
4
12
  ENV['APP_NAME'] = 'Alice'
5
13
 
6
14
  Bundler.require(:default, :development, :test)
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: 5.1.5
4
+ version: 5.2.3
5
5
  platform: java
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: 2020-01-10 00:00:00.000000000 Z
15
+ date: 2021-10-05 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  requirement: !ruby/object:Gem::Requirement
@@ -126,20 +126,6 @@ dependencies:
126
126
  - - ">="
127
127
  - !ruby/object:Gem::Version
128
128
  version: '1.6'
129
- - !ruby/object:Gem::Dependency
130
- requirement: !ruby/object:Gem::Requirement
131
- requirements:
132
- - - ">="
133
- - !ruby/object:Gem::Version
134
- version: '0'
135
- name: pry-coolline
136
- prerelease: false
137
- type: :development
138
- version_requirements: !ruby/object:Gem::Requirement
139
- requirements:
140
- - - ">="
141
- - !ruby/object:Gem::Version
142
- version: '0'
143
129
  - !ruby/object:Gem::Dependency
144
130
  requirement: !ruby/object:Gem::Requirement
145
131
  requirements:
@@ -196,6 +182,20 @@ dependencies:
196
182
  - - ">="
197
183
  - !ruby/object:Gem::Version
198
184
  version: '0'
185
+ - !ruby/object:Gem::Dependency
186
+ requirement: !ruby/object:Gem::Requirement
187
+ requirements:
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ version: '0'
191
+ name: simplecov
192
+ prerelease: false
193
+ type: :development
194
+ version_requirements: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - ">="
197
+ - !ruby/object:Gem::Version
198
+ version: '0'
199
199
  description: ActionSubscriber is a DSL that allows a rails app to consume messages
200
200
  from a RabbitMQ broker.
201
201
  email:
@@ -249,6 +249,7 @@ files:
249
249
  - lib/action_subscriber/router.rb
250
250
  - lib/action_subscriber/rspec.rb
251
251
  - lib/action_subscriber/subscribable.rb
252
+ - lib/action_subscriber/subscriber.rb
252
253
  - lib/action_subscriber/thread_pools.rb
253
254
  - lib/action_subscriber/uri.rb
254
255
  - lib/action_subscriber/version.rb
@@ -258,6 +259,7 @@ files:
258
259
  - spec/integration/at_most_once_spec.rb
259
260
  - spec/integration/automatic_reconnect_spec.rb
260
261
  - spec/integration/basic_subscriber_spec.rb
262
+ - spec/integration/consumer_cancellation_spec.rb
261
263
  - spec/integration/custom_actions_spec.rb
262
264
  - spec/integration/custom_headers_spec.rb
263
265
  - spec/integration/decoding_payloads_spec.rb
@@ -272,6 +274,7 @@ files:
272
274
  - spec/lib/action_subscriber/middleware/error_handler_spec.rb
273
275
  - spec/lib/action_subscriber/middleware/router_spec.rb
274
276
  - spec/lib/action_subscriber/middleware/runner_spec.rb
277
+ - spec/lib/action_subscriber/rabbit_connection_spec.rb
275
278
  - spec/lib/action_subscriber/router_spec.rb
276
279
  - spec/lib/action_subscriber/subscribable_spec.rb
277
280
  - spec/spec_helper.rb
@@ -296,7 +299,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
296
299
  - !ruby/object:Gem::Version
297
300
  version: '0'
298
301
  requirements: []
299
- rubygems_version: 3.1.2
302
+ rubygems_version: 3.2.28
300
303
  signing_key:
301
304
  specification_version: 4
302
305
  summary: ActionSubscriber is a DSL that allows a rails app to consume messages from
@@ -307,6 +310,7 @@ test_files:
307
310
  - spec/integration/at_most_once_spec.rb
308
311
  - spec/integration/automatic_reconnect_spec.rb
309
312
  - spec/integration/basic_subscriber_spec.rb
313
+ - spec/integration/consumer_cancellation_spec.rb
310
314
  - spec/integration/custom_actions_spec.rb
311
315
  - spec/integration/custom_headers_spec.rb
312
316
  - spec/integration/decoding_payloads_spec.rb
@@ -321,6 +325,7 @@ test_files:
321
325
  - spec/lib/action_subscriber/middleware/error_handler_spec.rb
322
326
  - spec/lib/action_subscriber/middleware/router_spec.rb
323
327
  - spec/lib/action_subscriber/middleware/runner_spec.rb
328
+ - spec/lib/action_subscriber/rabbit_connection_spec.rb
324
329
  - spec/lib/action_subscriber/router_spec.rb
325
330
  - spec/lib/action_subscriber/subscribable_spec.rb
326
331
  - spec/spec_helper.rb