action_subscriber 5.1.5-java → 5.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca5face8fc684985f21cab2d0be98de2e2f6d8c56d08a403c62075291adbda8a
4
- data.tar.gz: 3210c548ea05b9da02a358691434e22d875fcea6d11496959a849fee36223bfa
3
+ metadata.gz: 0f088a473b7415a63fcbd5813b5431bc0948e873a0e12d82f6d1868c1325c98c
4
+ data.tar.gz: b1c54dc689091437f55616fee572d8b01ca5683d713da6a757ecbaff4938434a
5
5
  SHA512:
6
- metadata.gz: 2089e546d6494cf331f658b26d4ff57f35151ddf231e586082dd951e6f635f29d816fe0b3b2d7302f7fd25a5141e56dcc8f1e56909f3973a3b8ba86b908cb64a
7
- data.tar.gz: 7f72c8204ed5bc09a61c1f3b62f6f5fb03bc21b66a6ca388f758c8bea776b93b6e275d99f0c77271652a0f0a3d7a3cb1692c237156d577aa47b67df5d36cbf69
6
+ metadata.gz: 6c852bffa5ac11f671380872ca6a3f10f684dca1089739114c32111b0ea0ee847e26621928862315371ad25e6d8d3d23d39324bf291cb28e97ed7afde77e0cf7
7
+ data.tar.gz: f0c39acea0ec3513b4c910cf428bc31fb36763ec1fbb0f20ceb04396c8bf76fbd73b0d40d6039d13aa6571db7a4a3486f9d01d94f90b3c180cbb6930fb2dda96
@@ -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
@@ -26,35 +26,52 @@ module ActionSubscriber
26
26
 
27
27
  def start_subscribers!
28
28
  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)
29
+ start_subscriber_for_subscription(subscription)
54
30
  end
55
31
  end
56
32
 
57
- private
33
+ private
34
+
35
+ def start_subscriber_for_subscription(subscription)
36
+ route = subscription[:route]
37
+ queue = subscription[:queue]
38
+ channel = queue.channel
39
+ threadpool = ::ActionSubscriber::ThreadPools.threadpools.fetch(route.threadpool_name)
40
+ channel.prefetch(route.prefetch) if route.acknowledgements?
41
+ consumer = ::Bunny::Consumer.new(channel, queue, channel.generate_consumer_tag, !route.acknowledgements?)
42
+
43
+ if ::ActionSubscriber.configuration.resubscribe_on_consumer_cancellation
44
+ # Add cancellation callback to rebuild subscriber on cancel.
45
+ consumer.on_cancellation do
46
+ ::ActionSubscriber.logger.warn "Cancelation received for queue consumer: #{queue.name}, rebuilding subscription..."
47
+ bunny_consumers.delete(consumer)
48
+ channel.close
49
+ queue = subscription[:queue] = setup_queue(route)
50
+ start_subscriber_for_subscription(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,
@@ -4,7 +4,8 @@ module ActionSubscriber
4
4
  include ::ActionSubscriber::Logging
5
5
 
6
6
  def cancel_consumers!
7
- march_hare_consumers.each(&:cancel)
7
+ # Cancel any non-cancelled consumers.
8
+ march_hare_consumers.reject(&:cancelled?).each(&:cancel)
8
9
  ::ActionSubscriber::ThreadPools.threadpools.each do |name, threadpool|
9
10
  threadpool.shutdown
10
11
  end
@@ -26,33 +27,50 @@ module ActionSubscriber
26
27
 
27
28
  def start_subscribers!
28
29
  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)
30
+ start_subscriber_for_subscription(subscription)
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def start_subscriber_for_subscription(subscription)
37
+ route = subscription[:route]
38
+ queue = subscription[:queue]
39
+ queue.channel.prefetch = route.prefetch if route.acknowledgements?
40
+ threadpool = ::ActionSubscriber::ThreadPools.threadpools.fetch(route.threadpool_name)
41
+ opts = route.queue_subscription_options
42
+
43
+ if ::ActionSubscriber.configuration.resubscribe_on_consumer_cancellation
44
+ # Add cancellation callback to rebuild subscriber on cancel.
45
+ opts[:on_cancellation] = lambda do |the_consumer|
46
+ ::ActionSubscriber.logger.warn "Cancelation received for queue consumer: #{queue.name}, rebuilding subscription..."
47
+ march_hare_consumers.delete(the_consumer)
48
+ queue.channel.close
49
+ queue = subscription[:queue] = setup_queue(route)
50
+ start_subscriber_for_subscription(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 }
@@ -1,3 +1,3 @@
1
1
  module ActionSubscriber
2
- VERSION = "5.1.5"
2
+ VERSION = "5.2.0"
3
3
  end
@@ -0,0 +1,83 @@
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
+ def rabbit_consumers
74
+ route_set = ::ActionSubscriber.send(:route_set)
75
+ route_set.try(:bunny_consumers) || route_set.try(:march_hare_consumers)
76
+ end
77
+
78
+ def delete_all_queues!
79
+ http_client.list_queues.each do |queue|
80
+ http_client.delete_queue(queue.vhost, queue.name)
81
+ end
82
+ end
83
+ 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: 5.1.5
4
+ version: 5.2.0
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: 2020-05-15 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  requirement: !ruby/object:Gem::Requirement
@@ -258,6 +258,7 @@ files:
258
258
  - spec/integration/at_most_once_spec.rb
259
259
  - spec/integration/automatic_reconnect_spec.rb
260
260
  - spec/integration/basic_subscriber_spec.rb
261
+ - spec/integration/consumer_cancellation_spec.rb
261
262
  - spec/integration/custom_actions_spec.rb
262
263
  - spec/integration/custom_headers_spec.rb
263
264
  - spec/integration/decoding_payloads_spec.rb
@@ -296,7 +297,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
296
297
  - !ruby/object:Gem::Version
297
298
  version: '0'
298
299
  requirements: []
299
- rubygems_version: 3.1.2
300
+ rubyforge_project:
301
+ rubygems_version: 2.7.9
300
302
  signing_key:
301
303
  specification_version: 4
302
304
  summary: ActionSubscriber is a DSL that allows a rails app to consume messages from
@@ -307,6 +309,7 @@ test_files:
307
309
  - spec/integration/at_most_once_spec.rb
308
310
  - spec/integration/automatic_reconnect_spec.rb
309
311
  - spec/integration/basic_subscriber_spec.rb
312
+ - spec/integration/consumer_cancellation_spec.rb
310
313
  - spec/integration/custom_actions_spec.rb
311
314
  - spec/integration/custom_headers_spec.rb
312
315
  - spec/integration/decoding_payloads_spec.rb