action_subscriber 2.5.0.pre2 → 3.0.0.pre1
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/action_subscriber.gemspec +1 -0
- data/lib/action_subscriber/babou.rb +2 -29
- data/lib/action_subscriber/base.rb +0 -4
- data/lib/action_subscriber/bunny/subscriber.rb +14 -4
- data/lib/action_subscriber/configuration.rb +1 -11
- data/lib/action_subscriber/default_routing.rb +6 -4
- data/lib/action_subscriber/march_hare/subscriber.rb +14 -4
- data/lib/action_subscriber/message_retry.rb +1 -1
- data/lib/action_subscriber/middleware/env.rb +3 -1
- data/lib/action_subscriber/middleware/error_handler.rb +11 -4
- data/lib/action_subscriber/rabbit_connection.rb +23 -34
- data/lib/action_subscriber/route.rb +5 -1
- data/lib/action_subscriber/route_set.rb +12 -11
- data/lib/action_subscriber/router.rb +13 -2
- data/lib/action_subscriber/version.rb +1 -1
- data/lib/action_subscriber.rb +11 -24
- data/spec/integration/around_filters_spec.rb +1 -1
- data/spec/integration/at_least_once_spec.rb +1 -1
- data/spec/integration/at_most_once_spec.rb +1 -1
- data/spec/integration/automatic_reconnect_spec.rb +3 -4
- data/spec/integration/basic_subscriber_spec.rb +2 -2
- data/spec/integration/custom_actions_spec.rb +1 -1
- data/spec/integration/custom_headers_spec.rb +2 -2
- data/spec/integration/decoding_payloads_spec.rb +2 -2
- data/spec/integration/manual_acknowledgement_spec.rb +1 -1
- data/spec/integration/multiple_connections_spec.rb +36 -0
- data/spec/integration/multiple_threadpools_spec.rb +3 -3
- data/spec/lib/action_subscriber/configuration_spec.rb +1 -5
- data/spec/spec_helper.rb +7 -4
- metadata +18 -14
- data/lib/action_subscriber/publisher/async/in_memory_adapter.rb +0 -153
- data/lib/action_subscriber/publisher/async.rb +0 -31
- data/lib/action_subscriber/publisher.rb +0 -46
- data/lib/action_subscriber/synchronizer.rb +0 -15
- data/spec/integration/inferred_routes_spec.rb +0 -53
- data/spec/lib/action_subscriber/publisher/async/in_memory_adapter_spec.rb +0 -135
- data/spec/lib/action_subscriber/publisher/async_spec.rb +0 -40
- data/spec/lib/action_subscriber/publisher_spec.rb +0 -35
@@ -13,7 +13,7 @@ describe "A Basic Subscriber", :integration => true do
|
|
13
13
|
|
14
14
|
context "ActionSubscriber.auto_pop!" do
|
15
15
|
it "routes messages to the right place" do
|
16
|
-
::
|
16
|
+
::ActivePublisher.publish("basic_push.booked", "Ohai Booked", "events")
|
17
17
|
|
18
18
|
verify_expectation_within(2.0) do
|
19
19
|
::ActionSubscriber.auto_pop!
|
@@ -25,7 +25,7 @@ describe "A Basic Subscriber", :integration => true do
|
|
25
25
|
context "ActionSubscriber.auto_subscribe!" do
|
26
26
|
it "routes messages to the right place" do
|
27
27
|
::ActionSubscriber.auto_subscribe!
|
28
|
-
::
|
28
|
+
::ActivePublisher.publish("basic_push.booked", "Ohai Booked", "events")
|
29
29
|
|
30
30
|
verify_expectation_within(2.0) do
|
31
31
|
expect($messages).to eq(Set.new(["Ohai Booked"]))
|
@@ -15,7 +15,7 @@ describe "A subscriber with a custom action", :integration => true do
|
|
15
15
|
|
16
16
|
it "routes the message to the selected action" do
|
17
17
|
::ActionSubscriber.auto_subscribe!
|
18
|
-
::
|
18
|
+
::ActivePublisher.publish("react.javascript_framework", "Another?!?!", "events")
|
19
19
|
|
20
20
|
verify_expectation_within(2.0) do
|
21
21
|
expect($messages).to eq(Set.new(["Another?!?!"]))
|
@@ -15,7 +15,7 @@ describe "Custom Headers Are Published and Received", :integration => true do
|
|
15
15
|
let(:headers) { { "Custom" => "content/header" } }
|
16
16
|
|
17
17
|
it "works for auto_pop!" do
|
18
|
-
::
|
18
|
+
::ActivePublisher.publish("pikitis.prank.pulled", "Yo Knope!", "events", :headers => headers)
|
19
19
|
verify_expectation_within(2.0) do
|
20
20
|
::ActionSubscriber.auto_pop!
|
21
21
|
expect($messages).to eq(Set.new([headers]))
|
@@ -24,7 +24,7 @@ describe "Custom Headers Are Published and Received", :integration => true do
|
|
24
24
|
|
25
25
|
it "works for auto_subscriber!" do
|
26
26
|
::ActionSubscriber.auto_subscribe!
|
27
|
-
::
|
27
|
+
::ActivePublisher.publish("pikitis.prank.pulled", "Yo Knope!", "events", :headers => headers)
|
28
28
|
verify_expectation_within(2.0) do
|
29
29
|
expect($messages).to eq(Set.new([headers]))
|
30
30
|
end
|
@@ -20,7 +20,7 @@ describe "Payload Decoding", :integration => true do
|
|
20
20
|
|
21
21
|
it "decodes json by default" do
|
22
22
|
::ActionSubscriber.auto_subscribe!
|
23
|
-
::
|
23
|
+
::ActivePublisher.publish("twitter.tweet", json_string, "events", :content_type => "application/json")
|
24
24
|
|
25
25
|
verify_expectation_within(2.0) do
|
26
26
|
expect($messages).to eq Set.new([{
|
@@ -38,7 +38,7 @@ describe "Payload Decoding", :integration => true do
|
|
38
38
|
|
39
39
|
it "it decodes the payload using the custom decoder" do
|
40
40
|
::ActionSubscriber.auto_subscribe!
|
41
|
-
::
|
41
|
+
::ActivePublisher.publish("twitter.tweet", json_string, "events", :content_type => content_type)
|
42
42
|
|
43
43
|
verify_expectation_within(2.0) do
|
44
44
|
expect($messages).to eq Set.new([{
|
@@ -22,7 +22,7 @@ describe "Manual Message Acknowledgment", :integration => true do
|
|
22
22
|
|
23
23
|
it "retries rejected messages and stops retrying acknowledged messages" do
|
24
24
|
::ActionSubscriber.auto_subscribe!
|
25
|
-
::
|
25
|
+
::ActivePublisher.publish("bacon.served", "BACON!", "events")
|
26
26
|
|
27
27
|
verify_expectation_within(2.0) do
|
28
28
|
expect($messages).to eq(Set.new(["BACON!::0", "BACON!::1", "BACON!::2"]))
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class MultipleConnectionsSubscriber < ::ActionSubscriber::Base
|
2
|
+
MUTEX = ::Mutex.new
|
3
|
+
at_least_once!
|
4
|
+
|
5
|
+
def burp
|
6
|
+
MUTEX.synchronize do
|
7
|
+
$messages << payload
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "Separate connections to get multiple threadpools", :integration => true do
|
13
|
+
let(:draw_routes) do
|
14
|
+
::ActionSubscriber.draw_routes do
|
15
|
+
connection(:background_work, :thread_pool_size => 20) do
|
16
|
+
route MultipleConnectionsSubscriber, :burp,
|
17
|
+
:acknowledgements => true,
|
18
|
+
:concurrency => 20
|
19
|
+
end
|
20
|
+
route MultipleConnectionsSubscriber, :burp,
|
21
|
+
:acknowledgements => true,
|
22
|
+
:concurrency => 8 # match the default threadpool size
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "spreads the load across multiple threadpools and consumer" do
|
27
|
+
::ActionSubscriber.auto_subscribe!
|
28
|
+
1.upto(10).each do |i|
|
29
|
+
::ActivePublisher.publish("multiple_connections.burp", "belch#{i}", "events")
|
30
|
+
end
|
31
|
+
|
32
|
+
verify_expectation_within(5.0) do
|
33
|
+
expect($messages).to eq(Set.new(["belch1", "belch2", "belch3", "belch4", "belch5", "belch6", "belch7", "belch8", "belch9", "belch10"]))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -18,11 +18,11 @@ describe "Separate Threadpools for Different Message", :integration => true do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it "processes messages in separate threadpools based on the routes" do
|
21
|
-
::
|
22
|
-
::
|
23
|
-
::ActionSubscriber::Publisher.publish("different_threadpools.two", "TWO", "events")
|
21
|
+
::ActivePublisher.publish("different_threadpools.one", "ONE", "events")
|
22
|
+
::ActivePublisher.publish("different_threadpools.two", "TWO", "events")
|
24
23
|
|
25
24
|
verify_expectation_within(2.0) do
|
25
|
+
::ActionSubscriber.auto_pop!
|
26
26
|
expect($messages).to eq(Set.new(["ONE","TWO"]))
|
27
27
|
end
|
28
28
|
end
|
@@ -1,17 +1,13 @@
|
|
1
1
|
describe ::ActionSubscriber::Configuration do
|
2
2
|
describe "default values" do
|
3
3
|
specify { expect(subject.allow_low_priority_methods).to eq(false) }
|
4
|
-
specify { expect(subject.async_publisher).to eq("memory") }
|
5
|
-
specify { expect(subject.async_publisher_drop_messages_when_queue_full).to eq(false) }
|
6
|
-
specify { expect(subject.async_publisher_max_queue_size).to eq(1_000_000) }
|
7
|
-
specify { expect(subject.async_publisher_supervisor_interval).to eq(200) }
|
8
4
|
specify { expect(subject.default_exchange).to eq("events") }
|
9
5
|
specify { expect(subject.heartbeat).to eq(5) }
|
10
6
|
specify { expect(subject.host).to eq("localhost") }
|
11
7
|
specify { expect(subject.mode).to eq('subscribe') }
|
12
8
|
specify { expect(subject.pop_interval).to eq(100) }
|
13
9
|
specify { expect(subject.port).to eq(5672) }
|
14
|
-
specify { expect(subject.prefetch).to eq(
|
10
|
+
specify { expect(subject.prefetch).to eq(2) }
|
15
11
|
specify { expect(subject.seconds_to_wait_for_graceful_shutdown).to eq(30) }
|
16
12
|
specify { expect(subject.threadpool_size).to eq(8) }
|
17
13
|
specify { expect(subject.timeout).to eq(1) }
|
data/spec/spec_helper.rb
CHANGED
@@ -15,6 +15,7 @@ require 'action_subscriber/rspec'
|
|
15
15
|
# Silence the Logger
|
16
16
|
$TESTING = true
|
17
17
|
::ActionSubscriber::Logging.initialize_logger(nil)
|
18
|
+
::ActionSubscriber.setup_default_connection!
|
18
19
|
|
19
20
|
RSpec.configure do |config|
|
20
21
|
config.mock_with :rspec do |mocks|
|
@@ -23,14 +24,16 @@ RSpec.configure do |config|
|
|
23
24
|
|
24
25
|
config.before(:each, :integration => true) do
|
25
26
|
$messages = Set.new
|
26
|
-
draw_routes
|
27
|
-
::ActionSubscriber
|
28
|
-
::ActionSubscriber.setup_queues!
|
27
|
+
draw_routes
|
28
|
+
::ActionSubscriber.setup_subscriptions!
|
29
29
|
end
|
30
30
|
config.after(:each, :integration => true) do
|
31
31
|
::ActionSubscriber.stop_subscribers!
|
32
|
-
::ActionSubscriber::RabbitConnection.subscriber_disconnect!
|
33
32
|
::ActionSubscriber.instance_variable_set("@route_set", nil)
|
33
|
+
::ActionSubscriber.instance_variable_set("@route_set_block", nil)
|
34
|
+
end
|
35
|
+
config.after(:suite) do
|
36
|
+
::ActionSubscriber::RabbitConnection.subscriber_disconnect!
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
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:
|
4
|
+
version: 3.0.0.pre1
|
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: 2016-09-
|
15
|
+
date: 2016-09-15 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: activesupport
|
@@ -84,6 +84,20 @@ dependencies:
|
|
84
84
|
- - ">="
|
85
85
|
- !ruby/object:Gem::Version
|
86
86
|
version: '0'
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
name: active_publisher
|
89
|
+
requirement: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - "~>"
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.1.5
|
94
|
+
type: :development
|
95
|
+
prerelease: false
|
96
|
+
version_requirements: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - "~>"
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 0.1.5
|
87
101
|
- !ruby/object:Gem::Dependency
|
88
102
|
name: activerecord
|
89
103
|
requirement: !ruby/object:Gem::Requirement
|
@@ -214,9 +228,6 @@ files:
|
|
214
228
|
- lib/action_subscriber/middleware/router.rb
|
215
229
|
- lib/action_subscriber/middleware/runner.rb
|
216
230
|
- lib/action_subscriber/preload.rb
|
217
|
-
- lib/action_subscriber/publisher.rb
|
218
|
-
- lib/action_subscriber/publisher/async.rb
|
219
|
-
- lib/action_subscriber/publisher/async/in_memory_adapter.rb
|
220
231
|
- lib/action_subscriber/rabbit_connection.rb
|
221
232
|
- lib/action_subscriber/railtie.rb
|
222
233
|
- lib/action_subscriber/route.rb
|
@@ -224,7 +235,6 @@ files:
|
|
224
235
|
- lib/action_subscriber/router.rb
|
225
236
|
- lib/action_subscriber/rspec.rb
|
226
237
|
- lib/action_subscriber/subscribable.rb
|
227
|
-
- lib/action_subscriber/synchronizer.rb
|
228
238
|
- lib/action_subscriber/threadpool.rb
|
229
239
|
- lib/action_subscriber/uri.rb
|
230
240
|
- lib/action_subscriber/version.rb
|
@@ -237,8 +247,8 @@ files:
|
|
237
247
|
- spec/integration/custom_actions_spec.rb
|
238
248
|
- spec/integration/custom_headers_spec.rb
|
239
249
|
- spec/integration/decoding_payloads_spec.rb
|
240
|
-
- spec/integration/inferred_routes_spec.rb
|
241
250
|
- spec/integration/manual_acknowledgement_spec.rb
|
251
|
+
- spec/integration/multiple_connections_spec.rb
|
242
252
|
- spec/integration/multiple_threadpools_spec.rb
|
243
253
|
- spec/lib/action_subscriber/base_spec.rb
|
244
254
|
- spec/lib/action_subscriber/configuration_spec.rb
|
@@ -250,9 +260,6 @@ files:
|
|
250
260
|
- spec/lib/action_subscriber/middleware/error_handler_spec.rb
|
251
261
|
- spec/lib/action_subscriber/middleware/router_spec.rb
|
252
262
|
- spec/lib/action_subscriber/middleware/runner_spec.rb
|
253
|
-
- spec/lib/action_subscriber/publisher/async/in_memory_adapter_spec.rb
|
254
|
-
- spec/lib/action_subscriber/publisher/async_spec.rb
|
255
|
-
- spec/lib/action_subscriber/publisher_spec.rb
|
256
263
|
- spec/lib/action_subscriber/router_spec.rb
|
257
264
|
- spec/lib/action_subscriber/subscribable_spec.rb
|
258
265
|
- spec/lib/action_subscriber/threadpool_spec.rb
|
@@ -292,8 +299,8 @@ test_files:
|
|
292
299
|
- spec/integration/custom_actions_spec.rb
|
293
300
|
- spec/integration/custom_headers_spec.rb
|
294
301
|
- spec/integration/decoding_payloads_spec.rb
|
295
|
-
- spec/integration/inferred_routes_spec.rb
|
296
302
|
- spec/integration/manual_acknowledgement_spec.rb
|
303
|
+
- spec/integration/multiple_connections_spec.rb
|
297
304
|
- spec/integration/multiple_threadpools_spec.rb
|
298
305
|
- spec/lib/action_subscriber/base_spec.rb
|
299
306
|
- spec/lib/action_subscriber/configuration_spec.rb
|
@@ -305,9 +312,6 @@ test_files:
|
|
305
312
|
- spec/lib/action_subscriber/middleware/error_handler_spec.rb
|
306
313
|
- spec/lib/action_subscriber/middleware/router_spec.rb
|
307
314
|
- spec/lib/action_subscriber/middleware/runner_spec.rb
|
308
|
-
- spec/lib/action_subscriber/publisher/async/in_memory_adapter_spec.rb
|
309
|
-
- spec/lib/action_subscriber/publisher/async_spec.rb
|
310
|
-
- spec/lib/action_subscriber/publisher_spec.rb
|
311
315
|
- spec/lib/action_subscriber/router_spec.rb
|
312
316
|
- spec/lib/action_subscriber/subscribable_spec.rb
|
313
317
|
- spec/lib/action_subscriber/threadpool_spec.rb
|
@@ -1,153 +0,0 @@
|
|
1
|
-
require "thread"
|
2
|
-
|
3
|
-
module ActionSubscriber
|
4
|
-
module Publisher
|
5
|
-
module Async
|
6
|
-
class InMemoryAdapter
|
7
|
-
include ::ActionSubscriber::Logging
|
8
|
-
|
9
|
-
attr_reader :async_queue
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
logger.info "Starting in-memory publisher adapter."
|
13
|
-
|
14
|
-
@async_queue = AsyncQueue.new
|
15
|
-
end
|
16
|
-
|
17
|
-
def publish(route, payload, exchange_name, options = {})
|
18
|
-
message = Message.new(route, payload, exchange_name, options)
|
19
|
-
async_queue.push(message)
|
20
|
-
nil
|
21
|
-
end
|
22
|
-
|
23
|
-
def shutdown!
|
24
|
-
max_wait_time = ::ActionSubscriber.configuration.seconds_to_wait_for_graceful_shutdown
|
25
|
-
started_shutting_down_at = ::Time.now
|
26
|
-
|
27
|
-
logger.info "Draining async publisher in-memory adapter queue before shutdown. Current queue size: #{async_queue.size}."
|
28
|
-
while async_queue.size > 0
|
29
|
-
if (::Time.now - started_shutting_down_at) > max_wait_time
|
30
|
-
logger.info "Forcing async publisher adapter shutdown because graceful shutdown period of #{max_wait_time} seconds was exceeded. Current queue size: #{async_queue.size}."
|
31
|
-
break
|
32
|
-
end
|
33
|
-
|
34
|
-
sleep 0.1
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
class Message
|
39
|
-
attr_reader :route, :payload, :exchange_name, :options
|
40
|
-
|
41
|
-
def initialize(route, payload, exchange_name, options)
|
42
|
-
@route = route
|
43
|
-
@payload = payload
|
44
|
-
@exchange_name = exchange_name
|
45
|
-
@options = options
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
class UnableToPersistMessageError < ::StandardError
|
50
|
-
end
|
51
|
-
|
52
|
-
class AsyncQueue
|
53
|
-
include ::ActionSubscriber::Logging
|
54
|
-
|
55
|
-
attr_reader :consumer, :queue, :supervisor
|
56
|
-
|
57
|
-
if ::RUBY_PLATFORM == "java"
|
58
|
-
NETWORK_ERRORS = [::MarchHare::Exception, ::Java::ComRabbitmqClient::AlreadyClosedException, ::Java::JavaIo::IOException].freeze
|
59
|
-
else
|
60
|
-
NETWORK_ERRORS = [::Bunny::Exception, ::Timeout::Error, ::IOError].freeze
|
61
|
-
end
|
62
|
-
|
63
|
-
def initialize
|
64
|
-
@queue = ::Queue.new
|
65
|
-
create_and_supervise_consumer!
|
66
|
-
end
|
67
|
-
|
68
|
-
def push(message)
|
69
|
-
# Default of 1_000_000 messages.
|
70
|
-
if queue.size > ::ActionSubscriber.configuration.async_publisher_max_queue_size
|
71
|
-
# Drop Messages if the queue is full and we were configured to do so.
|
72
|
-
return if ::ActionSubscriber.configuration.async_publisher_drop_messages_when_queue_full
|
73
|
-
|
74
|
-
# By default we will raise an error to push the responsibility onto the caller.
|
75
|
-
fail UnableToPersistMessageError, "Queue is full, messages will be dropped."
|
76
|
-
end
|
77
|
-
|
78
|
-
queue.push(message)
|
79
|
-
end
|
80
|
-
|
81
|
-
def size
|
82
|
-
queue.size
|
83
|
-
end
|
84
|
-
|
85
|
-
private
|
86
|
-
|
87
|
-
def await_network_reconnect
|
88
|
-
sleep ::ActionSubscriber::RabbitConnection::NETWORK_RECOVERY_INTERVAL
|
89
|
-
end
|
90
|
-
|
91
|
-
def create_and_supervise_consumer!
|
92
|
-
@consumer = create_consumer
|
93
|
-
@supervisor = ::Thread.new do
|
94
|
-
loop do
|
95
|
-
unless consumer.alive?
|
96
|
-
# Why might need to requeue the last message.
|
97
|
-
queue.push(@current_message) if @current_message.present?
|
98
|
-
consumer.kill
|
99
|
-
@consumer = create_consumer
|
100
|
-
end
|
101
|
-
|
102
|
-
# Pause before checking the consumer again.
|
103
|
-
sleep supervisor_interval
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def create_consumer
|
109
|
-
::Thread.new do
|
110
|
-
loop do
|
111
|
-
# Write "current_message" so we can requeue should something happen to the consumer. I don't love this, but it's
|
112
|
-
# better than writing my own `#peek' method.
|
113
|
-
@current_message = message = queue.pop
|
114
|
-
|
115
|
-
begin
|
116
|
-
::ActionSubscriber::Publisher.publish(message.route, message.payload, message.exchange_name, message.options)
|
117
|
-
|
118
|
-
# Reset
|
119
|
-
@current_message = nil
|
120
|
-
rescue *NETWORK_ERRORS
|
121
|
-
# Sleep because the connection is down.
|
122
|
-
await_network_reconnect
|
123
|
-
|
124
|
-
# Requeue and try again.
|
125
|
-
queue.push(message)
|
126
|
-
rescue => unknown_error
|
127
|
-
# Do not requeue the message because something else horrible happened.
|
128
|
-
@current_message = nil
|
129
|
-
|
130
|
-
# Log the error.
|
131
|
-
logger.info unknown_error.class
|
132
|
-
logger.info unknown_error.message
|
133
|
-
logger.info unknown_error.backtrace.join("\n")
|
134
|
-
|
135
|
-
# TODO: Find a way to bubble this out of the thread for logging purposes.
|
136
|
-
# Reraise the error out of the publisher loop. The Supervisor will restart the consumer.
|
137
|
-
raise unknown_error
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
def supervisor_interval
|
144
|
-
@supervisor_interval ||= begin
|
145
|
-
interval_in_milliseconds = ::ActionSubscriber.configuration.async_publisher_supervisor_interval
|
146
|
-
interval_in_milliseconds / 1000.0
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module ActionSubscriber
|
2
|
-
module Publisher
|
3
|
-
# Publish a message asynchronously to RabbitMQ.
|
4
|
-
#
|
5
|
-
# Asynchronous is designed to do two things:
|
6
|
-
# 1. Introduce the idea of a durable retry should the RabbitMQ connection disconnect.
|
7
|
-
# 2. Provide a higher-level pattern for fire-and-forget publishing.
|
8
|
-
#
|
9
|
-
# @param [String] route The routing key to use for this message.
|
10
|
-
# @param [String] payload The message you are sending. Should already be encoded as a string.
|
11
|
-
# @param [String] exchange The exchange you want to publish to.
|
12
|
-
# @param [Hash] options hash to set message parameters (e.g. headers).
|
13
|
-
def self.publish_async(route, payload, exchange_name, options = {})
|
14
|
-
Async.publisher_adapter.publish(route, payload, exchange_name, options)
|
15
|
-
end
|
16
|
-
|
17
|
-
module Async
|
18
|
-
def self.publisher_adapter
|
19
|
-
@publisher_adapter ||= case ::ActionSubscriber.configuration.async_publisher
|
20
|
-
when /memory/i then
|
21
|
-
require "action_subscriber/publisher/async/in_memory_adapter"
|
22
|
-
InMemoryAdapter.new
|
23
|
-
when /redis/i then
|
24
|
-
fail "Not yet implemented"
|
25
|
-
else
|
26
|
-
fail "Unknown adapter '#{::ActionSubscriber.configuration.async_publisher}' provided"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
module ActionSubscriber
|
2
|
-
module Publisher
|
3
|
-
# Publish a message to RabbitMQ
|
4
|
-
#
|
5
|
-
# @param [String] route The routing key to use for this message.
|
6
|
-
# @param [String] payload The message you are sending. Should already be encoded as a string.
|
7
|
-
# @param [String] exchange The exchange you want to publish to.
|
8
|
-
# @param [Hash] options hash to set message parameters (e.g. headers)
|
9
|
-
def self.publish(route, payload, exchange_name, options = {})
|
10
|
-
with_exchange(exchange_name) do |exchange|
|
11
|
-
exchange.publish(payload, publishing_options(route, options))
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.with_exchange(exchange_name)
|
16
|
-
connection = RabbitConnection.publisher_connection
|
17
|
-
channel = connection.create_channel
|
18
|
-
begin
|
19
|
-
channel.confirm_select if ActionSubscriber.configuration.publisher_confirms
|
20
|
-
exchange = channel.topic(exchange_name)
|
21
|
-
yield(exchange)
|
22
|
-
channel.wait_for_confirms if ActionSubscriber.configuration.publisher_confirms
|
23
|
-
ensure
|
24
|
-
channel.close rescue nil
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.publishing_options(route, in_options = {})
|
29
|
-
options = {
|
30
|
-
:mandatory => false,
|
31
|
-
:persistent => false,
|
32
|
-
:routing_key => route,
|
33
|
-
}.merge(in_options)
|
34
|
-
|
35
|
-
if ::RUBY_PLATFORM == "java"
|
36
|
-
java_options = {}
|
37
|
-
java_options[:mandatory] = options.delete(:mandatory)
|
38
|
-
java_options[:routing_key] = options.delete(:routing_key)
|
39
|
-
java_options[:properties] = options
|
40
|
-
java_options
|
41
|
-
else
|
42
|
-
options
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require "thread"
|
2
|
-
module ActionSubscriber
|
3
|
-
class Synchronizer
|
4
|
-
def initialize(delegate)
|
5
|
-
@delegate = delegate
|
6
|
-
@mutex = ::Mutex.new
|
7
|
-
end
|
8
|
-
|
9
|
-
def method_missing(name, *args, &block)
|
10
|
-
@mutex.synchronize do
|
11
|
-
@delegate.public_send(name, *args, &block)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
class InferenceSubscriber < ActionSubscriber::Base
|
2
|
-
publisher :kyle
|
3
|
-
|
4
|
-
def yo
|
5
|
-
$messages << payload
|
6
|
-
end
|
7
|
-
|
8
|
-
queue_for :hey, "some_other_queue.hey"
|
9
|
-
routing_key_for :hey, "other_routing_key.hey"
|
10
|
-
def hey
|
11
|
-
$messages << payload
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
describe "A Subscriber With Inferred Routes", :integration => true do
|
16
|
-
context "explicit routing with default_routes_for helper" do
|
17
|
-
let(:draw_routes) do
|
18
|
-
::ActionSubscriber.draw_routes do
|
19
|
-
default_routes_for InferenceSubscriber
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
it "registers the routes and sets up the queues" do
|
24
|
-
::ActionSubscriber.auto_subscribe!
|
25
|
-
::ActionSubscriber::Publisher.publish("kyle.inference.yo", "YO", "events")
|
26
|
-
::ActionSubscriber::Publisher.publish("other_routing_key.hey", "HEY", "events")
|
27
|
-
|
28
|
-
verify_expectation_within(2.0) do
|
29
|
-
expect($messages).to eq(Set.new(["YO","HEY"]))
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# This is the deprecated behavior we want to keep until version 2.0
|
35
|
-
context "no explicit routes" do
|
36
|
-
before do
|
37
|
-
# TEST HACK: Bust any memoized routes.
|
38
|
-
::ActionSubscriber.instance_variable_set(:@route_set, nil)
|
39
|
-
::ActionSubscriber.instance_variable_set(:@draw_routes_block, nil)
|
40
|
-
::ActionSubscriber.setup_queues!
|
41
|
-
end
|
42
|
-
|
43
|
-
it "registers the routes and sets up the queues" do
|
44
|
-
::ActionSubscriber.auto_subscribe!
|
45
|
-
::ActionSubscriber::Publisher.publish("kyle.inference.yo", "YO", "events")
|
46
|
-
::ActionSubscriber::Publisher.publish("other_routing_key.hey", "HEY", "events")
|
47
|
-
|
48
|
-
verify_expectation_within(2.0) do
|
49
|
-
expect($messages).to eq(Set.new(["YO","HEY"]))
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|