action_subscriber 5.2.2 → 5.3.0

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: 341fae9698b9a950fe6dcbc2263fcfba9f8f2b87de7156753714a2f5459dc6d0
4
- data.tar.gz: 4ee41e85aab759a85339aaa174b499d34ba3967b90220ddfee3e43ada8191282
3
+ metadata.gz: 7e335eb0bfa75bf17d2a27db0851b383dc9e624a621d3e18f1779bd50208a53e
4
+ data.tar.gz: 2d55858d1ebf03f5c42fcb04f7d4ad0e236b5859df9db510db334d9b73524ea3
5
5
  SHA512:
6
- metadata.gz: b21075dc61f36ba0b20923178524030f95d4a62be67275ae5fb16db18175e63e27224640f96a9a11e5e624c0a145d37b092d6b627e1f7fa779c07c6b0ea9229d
7
- data.tar.gz: ea278d62aee15c5bb1d01832c104e33ff1f305aecf373e547a8ff11929b2771167c51e5a4d029e915065113ffc8bfb1a7d445506abb94e0d0026c8dcd045335d
6
+ metadata.gz: c819570924299aa0d39ebced23078bdc48133f125e76e59dd62d408c014919b380862c3ad22c2505f4a379fa66f973ae31c3ff803abf63d2976e75d44204cee8
7
+ data.tar.gz: 1ef6ba00566fa31c58c3eb5dc4fbfc21a30da2810156c0e9f87bf4cb829bc3e408643861fc3a3d8058cb6f3bd8343644e303f596ef71f09b4038e1c6e30eead6
@@ -0,0 +1,61 @@
1
+ # Inspired by: http://mikebian.co/running-tests-against-multiple-ruby-versions-using-circleci/
2
+
3
+ version: 2.1
4
+
5
+ orbs:
6
+ ruby: circleci/ruby@1.1
7
+
8
+
9
+ # If you want to work on `action_subscriber` you will need to have a rabbitmq instance running locally on port 5672 with a management plugin enabled on port 15672. Usually the easiest way to accomplish this is to use docker and run the command:
10
+
11
+ # ```
12
+
13
+ jobs:
14
+ test:
15
+ parallelism: 1
16
+ parameters:
17
+ ruby-image:
18
+ type: string
19
+ docker:
20
+ - image: << parameters.ruby-image >>
21
+ - image: rabbitmq:3.6.6-management
22
+
23
+ steps:
24
+ - checkout
25
+ - run:
26
+ name: install dockerize
27
+ command: wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz
28
+ environment:
29
+ DOCKERIZE_VERSION: v0.3.0
30
+ # - run:
31
+ # name: Wait for rabbitmq
32
+ # command: dockerize -wait tcp://localhost:5672 -timeout 1m
33
+ - run:
34
+ name: Install bundler
35
+ command: gem install bundler
36
+ - run:
37
+ name: Which bundler?
38
+ command: bundle -v
39
+ - run:
40
+ name: bundle install
41
+ command: bundle install
42
+ - run:
43
+ name: rspec
44
+ command: bundle exec rspec
45
+
46
+ # strangely, there seems to be very little documentation about exactly how martix builds work.
47
+ # By defining a param inside your job definition, Circle CI will automatically spawn a job for
48
+ # unique param value passed via `matrix`. Neat!
49
+ # https://circleci.com/blog/circleci-matrix-jobs/
50
+ workflows:
51
+ build_and_test:
52
+ jobs:
53
+ - test:
54
+ matrix:
55
+ parameters:
56
+ ruby-image:
57
+ - circleci/ruby:2.5
58
+ - circleci/ruby:2.6
59
+ - circleci/ruby:2.7
60
+ - circleci/jruby:9.2
61
+ - circleci/jruby:9.3
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  if ENV['PLATFORM'] == "java" || ::RUBY_PLATFORM == 'java'
24
24
  spec.platform = "java"
25
- spec.add_dependency 'march_hare', '>= 2.7.0'
25
+ spec.add_dependency 'march_hare', '~> 4.4'
26
26
  else
27
27
  spec.add_dependency 'bunny', '>= 1.5.0'
28
28
  end
@@ -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
@@ -1,3 +1,5 @@
1
+ require "active_support/notifications"
2
+
1
3
  module ActionSubscriber
2
4
  module Babou
3
5
  ##
@@ -10,7 +12,7 @@ module ActionSubscriber
10
12
  ::ActionSubscriber.print_subscriptions
11
13
  ::ActionSubscriber.start_subscribers!
12
14
  logger.info "Action Subscriber connected"
13
-
15
+ ::ActiveSupport::Notifications.instrument("action_subscriber:server_started")
14
16
  while true
15
17
  sleep 1.0 #just hang around waiting for messages
16
18
  break if shutting_down?
@@ -21,6 +23,7 @@ module ActionSubscriber
21
23
  logger.info "Shutting down"
22
24
  ::ActionSubscriber::RabbitConnection.subscriber_disconnect!
23
25
  logger.info "Shutdown complete"
26
+ ::ActiveSupport::Notifications.instrument("action_subscriber:server_stopped")
24
27
  exit(0)
25
28
  end
26
29
 
@@ -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 ||= []
@@ -43,11 +44,10 @@ module ActionSubscriber
43
44
  if ::ActionSubscriber.configuration.resubscribe_on_consumer_cancellation
44
45
  # Add cancellation callback to rebuild subscriber on cancel.
45
46
  consumer.on_cancellation do
46
- ::ActionSubscriber.logger.warn "Cancelation received for queue consumer: #{queue.name}, rebuilding subscription..."
47
+ ::ActionSubscriber.logger.warn "Cancellation received for queue consumer: #{queue.name}, rebuilding subscription..."
47
48
  bunny_consumers.delete(consumer)
48
49
  channel.close
49
- queue = subscription[:queue] = setup_queue(route)
50
- start_subscriber_for_subscription(subscription)
50
+ safely_restart_subscriber(subscription)
51
51
  end
52
52
  end
53
53
 
@@ -2,6 +2,7 @@ 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
8
  # Cancel any non-cancelled consumers.
@@ -43,11 +44,10 @@ module ActionSubscriber
43
44
  if ::ActionSubscriber.configuration.resubscribe_on_consumer_cancellation
44
45
  # Add cancellation callback to rebuild subscriber on cancel.
45
46
  opts[:on_cancellation] = lambda do |the_consumer|
46
- ::ActionSubscriber.logger.warn "Cancelation received for queue consumer: #{queue.name}, rebuilding subscription..."
47
+ ::ActionSubscriber.logger.warn "Cancellation received for queue consumer: #{queue.name}, rebuilding subscription..."
47
48
  march_hare_consumers.delete(the_consumer)
48
49
  queue.channel.close
49
- queue = subscription[:queue] = setup_queue(route)
50
- start_subscriber_for_subscription(subscription)
50
+ safely_restart_subscriber(subscription)
51
51
  end
52
52
  end
53
53
 
@@ -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.2.2"
2
+ VERSION = "5.3.0"
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"
@@ -86,6 +87,18 @@ module ActionSubscriber
86
87
  route_set.wait_to_finish_with_timeout(timeout)
87
88
  end
88
89
 
90
+ def self.after_server_start(&block)
91
+ ::ActiveSupport::Notifications.subscribe("action_subscriber:server_started") do |*args|
92
+ block.call(*args)
93
+ end
94
+ end
95
+
96
+ def self.after_server_stop(&block)
97
+ ::ActiveSupport::Notifications.subscribe("action_subscriber:server_stopped") do |*args|
98
+ block.call(*args)
99
+ end
100
+ end
101
+
89
102
  # Execution is delayed until after app loads when used with bin/action_subscriber
90
103
  require "action_subscriber/railtie" if defined?(Rails)
91
104
  ::ActiveSupport.run_load_hooks(:action_subscriber, Base)
@@ -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
@@ -8,76 +8,116 @@ class YoloSubscriber < ActionSubscriber::Base
8
8
  end
9
9
 
10
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
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
83
123
  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.2.2
4
+ version: 5.3.0
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: 2020-07-29 00:00:00.000000000 Z
15
+ date: 2022-02-22 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: activesupport
@@ -126,20 +126,6 @@ dependencies:
126
126
  - - ">="
127
127
  - !ruby/object:Gem::Version
128
128
  version: '1.6'
129
- - !ruby/object:Gem::Dependency
130
- name: pry-coolline
131
- requirement: !ruby/object:Gem::Requirement
132
- requirements:
133
- - - ">="
134
- - !ruby/object:Gem::Version
135
- version: '0'
136
- type: :development
137
- prerelease: false
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
  name: pry-nav
145
131
  requirement: !ruby/object:Gem::Requirement
@@ -196,6 +182,20 @@ dependencies:
196
182
  - - ">="
197
183
  - !ruby/object:Gem::Version
198
184
  version: '0'
185
+ - !ruby/object:Gem::Dependency
186
+ name: simplecov
187
+ requirement: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - ">="
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
192
+ type: :development
193
+ prerelease: false
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:
@@ -209,6 +209,7 @@ executables:
209
209
  extensions: []
210
210
  extra_rdoc_files: []
211
211
  files:
212
+ - ".circleci/config.yml"
212
213
  - ".gitignore"
213
214
  - ".rspec"
214
215
  - ".travis.yml"
@@ -249,6 +250,7 @@ files:
249
250
  - lib/action_subscriber/router.rb
250
251
  - lib/action_subscriber/rspec.rb
251
252
  - lib/action_subscriber/subscribable.rb
253
+ - lib/action_subscriber/subscriber.rb
252
254
  - lib/action_subscriber/thread_pools.rb
253
255
  - lib/action_subscriber/uri.rb
254
256
  - lib/action_subscriber/version.rb
@@ -298,7 +300,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
298
300
  - !ruby/object:Gem::Version
299
301
  version: '0'
300
302
  requirements: []
301
- rubygems_version: 3.1.2
303
+ rubygems_version: 3.2.3
302
304
  signing_key:
303
305
  specification_version: 4
304
306
  summary: ActionSubscriber is a DSL that allows a rails app to consume messages from