action_subscriber 1.6.0 → 1.7.0.pre0

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
  SHA1:
3
- metadata.gz: d313afcc25cfffc3977ac51fd000454a5203a302
4
- data.tar.gz: 6e6b1cef5a1431f8d8b3d1e2f4dc6e11797f21c7
3
+ metadata.gz: 06d750a3ce695babe3b26f24e06284e0461d0654
4
+ data.tar.gz: abdfb7fa508022788480938484238e044cd5b159
5
5
  SHA512:
6
- metadata.gz: 83dba20046583695e060cba67c22cb85effe54a649973d9d08716a25964497214a1496e8f0f7f23f9ed805f999c18ba212dfa1d3551201032eff06f03a9c5d4e
7
- data.tar.gz: 54e4e53b941c3d2f8f7e86e79d24cf0d53bee320161a812f9bf7e501e392277ee900270e3da495c2ab914d288e54abfd086c5383903ba85dfe48631b77ad11e6
6
+ metadata.gz: 75831f62c6cc6652a8e4e99b4716af452e6dbe371bdb4c7057b5bca1c0fe4165a668db899205a79c622b5b7060abc07380951b3192d8f36894fc6099717c99d1
7
+ data.tar.gz: e55a1dcd87c163f673819bb3aeb670c561023f493e7c6e0ad527a418ca4a6cfb52ae700765830c5ba313fb6cdda593cacab2b5d3be6a692e8755f6cb6db36f9b
@@ -5,7 +5,7 @@ rvm:
5
5
  - 2.1
6
6
  - 2.2
7
7
  - jruby-1.7
8
- - jruby-9.0.1.0
8
+ - jruby-9.0.4.0
9
9
  - jruby-head
10
10
  - rbx-2
11
11
  services:
@@ -26,10 +26,10 @@ module ActionSubscriber
26
26
  require options[:app]
27
27
 
28
28
  $0 = "Action Subscriber server #{object_id}"
29
- puts "Loading configuration..."
29
+ ::ActionSubscriber.logger.info "Loading configuration..."
30
30
 
31
31
  ::ActionSubscriber::Configuration.configure_from_yaml_and_cli(options)
32
- puts "Starting server..."
32
+ ::ActionSubscriber.logger.info "Starting server..."
33
33
 
34
34
  case ::ActionSubscriber.configuration.mode
35
35
  when /pop/i then
@@ -14,6 +14,7 @@ require "action_subscriber/version"
14
14
  require "action_subscriber/default_routing"
15
15
  require "action_subscriber/dsl"
16
16
  require "action_subscriber/configuration"
17
+ require "action_subscriber/logging"
17
18
  require "action_subscriber/message_retry"
18
19
  require "action_subscriber/middleware"
19
20
  require "action_subscriber/rabbit_connection"
@@ -61,15 +62,19 @@ module ActionSubscriber
61
62
  @route_set = RouteSet.new(routes)
62
63
  end
63
64
 
65
+ def self.logger
66
+ ::ActionSubscriber::Logging.logger
67
+ end
68
+
64
69
  def self.print_subscriptions
65
- puts configuration.inspect
70
+ logger.info configuration.inspect
66
71
  route_set.routes.group_by(&:subscriber).each do |subscriber, routes|
67
- puts subscriber.name
72
+ logger.info subscriber.name
68
73
  routes.each do |route|
69
- puts " -- method: #{route.action}"
70
- puts " -- exchange: #{route.exchange}"
71
- puts " -- queue: #{route.queue}"
72
- puts " -- routing_key: #{route.routing_key}"
74
+ logger.info " -- method: #{route.action}"
75
+ logger.info " -- exchange: #{route.exchange}"
76
+ logger.info " -- queue: #{route.queue}"
77
+ logger.info " -- routing_key: #{route.routing_key}"
73
78
  end
74
79
  end
75
80
  end
@@ -112,7 +117,7 @@ module ActionSubscriber
112
117
  #
113
118
  def self.route_set
114
119
  @route_set ||= begin
115
- puts "DEPRECATION WARNING: We are inferring your routes by looking at your subscribers. This behavior is deprecated and will be removed in version 2.0. Please see the routing guide at https://github.com/mxenabled/action_subscriber/blob/master/routing.md"
120
+ logger.warn "DEPRECATION WARNING: We are inferring your routes by looking at your subscribers. This behavior is deprecated and will be removed in version 2.0. Please see the routing guide at https://github.com/mxenabled/action_subscriber/blob/master/routing.md"
116
121
  RouteSet.new(self.send(:default_routes))
117
122
  end
118
123
  end
@@ -11,11 +11,11 @@ module ActionSubscriber
11
11
  sleep_time = ::ActionSubscriber.configuration.pop_interval.to_i / 1000.0
12
12
 
13
13
  ::ActionSubscriber.start_queues
14
- puts "\nAction Subscriber is popping messages every #{sleep_time} seconds.\n"
14
+ logger.info "Action Subscriber is popping messages every #{sleep_time} seconds."
15
15
 
16
16
  # How often do we want the timer checking for new pops
17
17
  # since we included an eager popper we decreased the
18
- # default check interval to 100ms
18
+ # default check interval to 100m
19
19
  while true
20
20
  ::ActionSubscriber.auto_pop! unless shutting_down?
21
21
  sleep sleep_time
@@ -33,7 +33,7 @@ module ActionSubscriber
33
33
  load_subscribers unless subscribers_loaded?
34
34
 
35
35
  ::ActionSubscriber.start_subscribers
36
- puts "\nAction Subscriber connected\n"
36
+ logger.info "Action Subscriber connected"
37
37
 
38
38
  while true
39
39
  sleep 1.0 #just hang around waiting for messages
@@ -68,6 +68,10 @@ module ActionSubscriber
68
68
  end
69
69
  end
70
70
 
71
+ def self.logger
72
+ ::ActionSubscriber::Logging.logger
73
+ end
74
+
71
75
  def self.reload_active_record
72
76
  if defined?(::ActiveRecord::Base) && !::ActiveRecord::Base.connected?
73
77
  ::ActiveRecord::Base.establish_connection
@@ -82,11 +86,12 @@ module ActionSubscriber
82
86
  @shutting_down = true
83
87
  ::Thread.new do
84
88
  ::ActionSubscriber.stop_subscribers!
85
- puts "stopped all subscribers"
89
+ logger.info "stopped all subscribers"
86
90
  end.join
87
91
  end
88
92
 
89
93
  def self.stop_server!
94
+ # this method is called from within a TRAP context so we can't use the logger
90
95
  puts "Stopping server..."
91
96
  wait_loops = 0
92
97
  ::ActionSubscriber::Babou.stop_receving_messages!
@@ -1,6 +1,8 @@
1
1
  module ActionSubscriber
2
2
  module Bunny
3
3
  module Subscriber
4
+ include ::ActionSubscriber::Logging
5
+
4
6
  def bunny_consumers
5
7
  @bunny_consumers ||= []
6
8
  end
@@ -29,7 +31,7 @@ module ActionSubscriber
29
31
  :queue => queue.name,
30
32
  }
31
33
  env = ::ActionSubscriber::Middleware::Env.new(route.subscriber, encoded_payload, properties)
32
- enqueue_env(env)
34
+ enqueue_env(route.threadpool, env)
33
35
  end
34
36
  end
35
37
  end
@@ -52,7 +54,7 @@ module ActionSubscriber
52
54
  :queue => queue.name,
53
55
  }
54
56
  env = ::ActionSubscriber::Middleware::Env.new(route.subscriber, encoded_payload, properties)
55
- enqueue_env(env)
57
+ enqueue_env(route.threadpool, env)
56
58
  end
57
59
  bunny_consumers << consumer
58
60
  queue.subscribe_with(consumer)
@@ -61,8 +63,9 @@ module ActionSubscriber
61
63
 
62
64
  private
63
65
 
64
- def enqueue_env(env)
65
- ::ActionSubscriber::Threadpool.pool.async(env) do |env|
66
+ def enqueue_env(threadpool, env)
67
+ logger.info "RECEIVED #{env.message_id} from #{env.queue}"
68
+ threadpool.async(env) do |env|
66
69
  ::ActiveSupport::Notifications.instrument "process_event.action_subscriber", :subscriber => env.subscriber.to_s, :routing_key => env.routing_key do
67
70
  ::ActionSubscriber.config.middleware.call(env)
68
71
  end
@@ -0,0 +1,27 @@
1
+ # Taken from https://github.com/mperham/sidekiq/blob/7f882787e53d234042ff18099241403300a47585/lib/sidekiq/logging.rb
2
+ require 'time'
3
+ require 'logger'
4
+
5
+ module ActionSubscriber
6
+ module Logging
7
+ def self.initialize_logger(log_target = STDOUT)
8
+ oldlogger = defined?(@logger) ? @logger : nil
9
+ @logger = Logger.new(log_target)
10
+ @logger.level = Logger::INFO
11
+ oldlogger.close if oldlogger && !$TESTING # don't want to close testing's STDOUT logging
12
+ @logger
13
+ end
14
+
15
+ def self.logger
16
+ defined?(@logger) ? @logger : initialize_logger
17
+ end
18
+
19
+ def self.logger=(log)
20
+ @logger = (log ? log : Logger.new('/dev/null'))
21
+ end
22
+
23
+ def logger
24
+ ::ActionSubscriber::Logging.logger
25
+ end
26
+ end
27
+ end
@@ -1,6 +1,8 @@
1
1
  module ActionSubscriber
2
2
  module MarchHare
3
3
  module Subscriber
4
+ include ::ActionSubscriber::Logging
5
+
4
6
  def cancel_consumers!
5
7
  march_hare_consumers.each(&:cancel)
6
8
  end
@@ -25,7 +27,7 @@ module ActionSubscriber
25
27
  :queue => queue.name,
26
28
  }
27
29
  env = ::ActionSubscriber::Middleware::Env.new(route.subscriber, encoded_payload, properties)
28
- enqueue_env(env)
30
+ enqueue_env(route.threadpool, env)
29
31
  end
30
32
  end
31
33
 
@@ -49,7 +51,7 @@ module ActionSubscriber
49
51
  :queue => queue.name,
50
52
  }
51
53
  env = ::ActionSubscriber::Middleware::Env.new(route.subscriber, encoded_payload, properties)
52
- enqueue_env(env)
54
+ enqueue_env(route.threadpool, env)
53
55
  end
54
56
 
55
57
  march_hare_consumers << consumer
@@ -62,8 +64,9 @@ module ActionSubscriber
62
64
 
63
65
  private
64
66
 
65
- def enqueue_env(env)
66
- ::ActionSubscriber::Threadpool.pool.async(env) do |env|
67
+ def enqueue_env(threadpool, env)
68
+ logger.info "RECEIVED #{env.message_id} from #{env.queue}"
69
+ threadpool.async(env) do |env|
67
70
  ::ActiveSupport::Notifications.instrument "process_event.action_subscriber", :subscriber => env.subscriber.to_s, :routing_key => env.routing_key do
68
71
  ::ActionSubscriber.config.middleware.call(env)
69
72
  end
@@ -30,7 +30,7 @@ module ActionSubscriber
30
30
  @encoded_payload = encoded_payload
31
31
  @exchange = properties.fetch(:exchange)
32
32
  @headers = properties.fetch(:headers) || {}
33
- @message_id = properties.fetch(:message_id)
33
+ @message_id = properties.fetch(:message_id) || ::Random.new.bytes(3).unpack("H*")[0]
34
34
  @queue = properties.fetch(:queue)
35
35
  @routing_key = properties.fetch(:routing_key)
36
36
  @subscriber = subscriber
@@ -1,6 +1,8 @@
1
1
  module ActionSubscriber
2
2
  module Middleware
3
3
  class ErrorHandler
4
+ include ::ActionSubscriber::Logging
5
+
4
6
  def initialize(app)
5
7
  @app = app
6
8
  end
@@ -8,6 +10,7 @@ module ActionSubscriber
8
10
  def call(env)
9
11
  @app.call(env)
10
12
  rescue => error
13
+ logger.error "FAILED #{env.message_id}"
11
14
  ::ActionSubscriber.configuration.error_handler.call(error, env.to_h)
12
15
  end
13
16
  end
@@ -1,12 +1,16 @@
1
1
  module ActionSubscriber
2
2
  module Middleware
3
3
  class Router
4
+ include ::ActionSubscriber::Logging
5
+
4
6
  def initialize(app)
5
7
  @app = app
6
8
  end
7
9
 
8
10
  def call(env)
11
+ logger.info "START #{env.message_id} #{env.subscriber}##{env.action}"
9
12
  env.subscriber.run_action_with_filters(env, env.action)
13
+ logger.info "FINISHED #{env.message_id}"
10
14
  end
11
15
  end
12
16
  end
@@ -4,18 +4,20 @@ module ActionSubscriber
4
4
  :action,
5
5
  :exchange,
6
6
  :prefetch,
7
+ :queue,
7
8
  :routing_key,
8
9
  :subscriber,
9
- :queue
10
+ :threadpool
10
11
 
11
12
  def initialize(attributes)
12
13
  @acknowledgements = attributes.fetch(:acknowledgements)
13
14
  @action = attributes.fetch(:action)
14
15
  @exchange = attributes.fetch(:exchange).to_s
15
16
  @prefetch = attributes.fetch(:prefetch) { ::ActionSubscriber.config.prefetch }
17
+ @queue = attributes.fetch(:queue)
16
18
  @routing_key = attributes.fetch(:routing_key)
17
19
  @subscriber = attributes.fetch(:subscriber)
18
- @queue = attributes.fetch(:queue)
20
+ @threadpool = attributes.fetch(:threadpool) { ::ActionSubscriber::Threadpool.pool(:default) }
19
21
  end
20
22
 
21
23
  def acknowledgements?
@@ -4,17 +4,29 @@ module ActionSubscriber
4
4
  # Class Methods
5
5
  #
6
6
  def self.busy?
7
- (pool.pool_size == pool.busy_size)
7
+ pools.any? do |_pool_name, pool|
8
+ pool.pool_size == pool.busy_size
9
+ end
8
10
  end
9
11
 
10
- def self.perform_async(*args)
11
- self.pool.async.perform(*args)
12
+ def self.new_pool(name, pool_size = nil)
13
+ fail ArgumentError, "#{name} already exists as a threadpool" if pools.key?(name)
14
+ pool_size ||= ::ActionSubscriber.config.threadpool_size
15
+ pools[name] = ::Lifeguard::InfiniteThreadpool.new(
16
+ :pool_size => pool_size
17
+ )
12
18
  end
13
19
 
14
- def self.pool
15
- @pool ||= ::Lifeguard::InfiniteThreadpool.new(
16
- :pool_size => ::ActionSubscriber.config.threadpool_size
17
- )
20
+ def self.pool(which_pool = :default)
21
+ pools[which_pool]
22
+ end
23
+
24
+ def self.pools
25
+ @pools ||= {
26
+ :default => ::Lifeguard::InfiniteThreadpool.new(
27
+ :pool_size => ::ActionSubscriber.config.threadpool_size
28
+ )
29
+ }
18
30
  end
19
31
 
20
32
  def self.ready?
@@ -22,8 +34,9 @@ module ActionSubscriber
22
34
  end
23
35
 
24
36
  def self.ready_size
25
- ready_size = pool.pool_size - pool.busy_size
26
- return ready_size >= 0 ? ready_size : 0
37
+ pools.inject(0) do |total_ready, (_pool_name, pool)|
38
+ total_ready + [0, pool.pool_size - pool.busy_size].max
39
+ end
27
40
  end
28
41
  end
29
42
  end
@@ -1,3 +1,3 @@
1
1
  module ActionSubscriber
2
- VERSION = "1.6.0"
2
+ VERSION = "1.7.0.pre0"
3
3
  end
@@ -22,15 +22,17 @@ class InstaSubscriber < ActionSubscriber::Base
22
22
  end
23
23
 
24
24
  describe "subscriber filters", :integration => true do
25
- let(:connection) { subscriber.connection }
25
+ let(:draw_routes) do
26
+ ::ActionSubscriber.draw_routes do
27
+ default_routes_for InstaSubscriber
28
+ end
29
+ end
26
30
  let(:subscriber) { InstaSubscriber }
27
31
 
28
32
  it "runs multiple around filters" do
29
33
  $messages = [] #testing the order of things
30
34
  ::ActionSubscriber.auto_subscribe!
31
- channel = connection.create_channel
32
- exchange = channel.topic("events")
33
- exchange.publish("hEY Guyz!", :routing_key => "insta.first")
35
+ ::ActionSubscriber::Publisher.publish("insta.first", "hEY Guyz!", "events")
34
36
 
35
37
  verify_expectation_within(1.0) do
36
38
  expect($messages).to eq [:whisper_before, :yell_before, "hEY Guyz!", :yell_after, :whisper_after]
@@ -8,14 +8,16 @@ class GorbyPuffSubscriber < ActionSubscriber::Base
8
8
  end
9
9
 
10
10
  describe "at_least_once! mode", :integration => true do
11
- let(:connection) { subscriber.connection }
11
+ let(:draw_routes) do
12
+ ::ActionSubscriber.draw_routes do
13
+ default_routes_for GorbyPuffSubscriber
14
+ end
15
+ end
12
16
  let(:subscriber) { GorbyPuffSubscriber }
13
17
 
14
18
  it "retries a failed job until it succeeds" do
15
19
  ::ActionSubscriber.auto_subscribe!
16
- channel = connection.create_channel
17
- exchange = channel.topic("events")
18
- exchange.publish("GrumpFace", :routing_key => "gorby_puff.grumpy")
20
+ ::ActionSubscriber::Publisher.publish("gorby_puff.grumpy", "GrumpFace", "events")
19
21
 
20
22
  verify_expectation_within(2.0) do
21
23
  expect($messages).to eq Set.new(["GrumpFace::0","GrumpFace::1","GrumpFace::2"])
@@ -8,14 +8,16 @@ class PokemonSubscriber < ActionSubscriber::Base
8
8
  end
9
9
 
10
10
  describe "at_most_once! mode", :integration => true do
11
- let(:connection) { subscriber.connection }
11
+ let(:draw_routes) do
12
+ ::ActionSubscriber.draw_routes do
13
+ default_routes_for PokemonSubscriber
14
+ end
15
+ end
12
16
  let(:subscriber) { PokemonSubscriber }
13
17
 
14
18
  it "does not retry a failed message" do
15
19
  ::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")
20
+ ::ActionSubscriber::Publisher.publish("pokemon.caught_em_all", "All Pokemon have been caught", "events")
19
21
 
20
22
  verify_expectation_within(1.0) do
21
23
  expect($messages.size).to eq 1
@@ -8,14 +8,17 @@ end
8
8
 
9
9
  describe "Automatically reconnect on connection failure", :integration => true, :slow => true do
10
10
  let(:connection) { subscriber.connection }
11
+ let(:draw_routes) do
12
+ ::ActionSubscriber.draw_routes do
13
+ default_routes_for GusSubscriber
14
+ end
15
+ end
11
16
  let(:http_client) { RabbitMQ::HTTP::Client.new("http://127.0.0.1:15672") }
12
17
  let(:subscriber) { GusSubscriber }
13
18
 
14
19
  it "reconnects when a connection drops" do
15
20
  ::ActionSubscriber::auto_subscribe!
16
- channel = connection.create_channel
17
- exchange = channel.topic("events")
18
- exchange.publish("First", :routing_key => "gus.spoke")
21
+ ::ActionSubscriber::Publisher.publish("gus.spoke", "First", "events")
19
22
  verify_expectation_within(5.0) do
20
23
  expect($messages).to eq(Set.new(["First"]))
21
24
  end
@@ -26,9 +29,7 @@ describe "Automatically reconnect on connection failure", :integration => true,
26
29
  expect(connection).to be_open
27
30
  end
28
31
 
29
- channel = connection.create_channel
30
- exchange = channel.topic("events")
31
- exchange.publish("Second", :routing_key => "gus.spoke")
32
+ ::ActionSubscriber::Publisher.publish("gus.spoke", "Second", "events")
32
33
  verify_expectation_within(5.0) do
33
34
  expect($messages).to eq(Set.new(["First", "Second"]))
34
35
  end
@@ -1,32 +1,23 @@
1
1
  class BasicPushSubscriber < ActionSubscriber::Base
2
- publisher :greg
3
-
4
- # queue => alice.greg.basic_push.booked
5
- # routing_key => greg.basic_push.booked
6
2
  def booked
7
3
  $messages << payload
8
4
  end
9
-
10
- queue_for :cancelled, "basic.cancelled"
11
- routing_key_for :cancelled, "basic.cancelled"
12
-
13
- def cancelled
14
- $messages << payload
15
- end
16
5
  end
17
6
 
18
7
  describe "A Basic Subscriber", :integration => true do
19
- let(:connection) { subscriber.connection }
20
- let(:subscriber) { BasicPushSubscriber }
8
+ let(:draw_routes) do
9
+ ::ActionSubscriber.draw_routes do
10
+ route ::BasicPushSubscriber, :booked
11
+ end
12
+ end
21
13
 
22
14
  context "ActionSubscriber.auto_pop!" do
23
15
  it "routes messages to the right place" do
24
- ::ActionSubscriber::Publisher.publish("greg.basic_push.booked", "Ohai Booked", "events")
25
- ::ActionSubscriber::Publisher.publish("basic.cancelled", "Ohai Cancelled", "events")
16
+ ::ActionSubscriber::Publisher.publish("basic_push.booked", "Ohai Booked", "events")
26
17
 
27
18
  verify_expectation_within(2.0) do
28
19
  ::ActionSubscriber.auto_pop!
29
- expect($messages).to eq(Set.new(["Ohai Booked", "Ohai Cancelled"]))
20
+ expect($messages).to eq(Set.new(["Ohai Booked"]))
30
21
  end
31
22
  end
32
23
  end
@@ -34,13 +25,10 @@ describe "A Basic Subscriber", :integration => true do
34
25
  context "ActionSubscriber.auto_subscribe!" do
35
26
  it "routes messages to the right place" do
36
27
  ::ActionSubscriber.auto_subscribe!
37
- channel = connection.create_channel
38
- exchange = channel.topic("events")
39
- exchange.publish("Ohai Booked", :routing_key => "greg.basic_push.booked")
40
- exchange.publish("Ohai Cancelled", :routing_key => "basic.cancelled")
28
+ ::ActionSubscriber::Publisher.publish("basic_push.booked", "Ohai Booked", "events")
41
29
 
42
30
  verify_expectation_within(2.0) do
43
- expect($messages).to eq(Set.new(["Ohai Booked", "Ohai Cancelled"]))
31
+ expect($messages).to eq(Set.new(["Ohai Booked"]))
44
32
  end
45
33
  end
46
34
  end
@@ -7,6 +7,11 @@ class PrankSubscriber < ActionSubscriber::Base
7
7
  end
8
8
 
9
9
  describe "Custom Headers Are Published and Received", :integration => true do
10
+ let(:draw_routes) do
11
+ ::ActionSubscriber.draw_routes do
12
+ default_routes_for PrankSubscriber
13
+ end
14
+ end
10
15
  let(:headers) { { "Custom" => "content/header" } }
11
16
 
12
17
  it "works for auto_pop!" do
@@ -10,14 +10,17 @@ end
10
10
 
11
11
  describe "Payload Decoding", :integration => true do
12
12
  let(:connection) { subscriber.connection }
13
+ let(:draw_routes) do
14
+ ::ActionSubscriber.draw_routes do
15
+ default_routes_for TwitterSubscriber
16
+ end
17
+ end
13
18
  let(:subscriber) { TwitterSubscriber }
14
19
  let(:json_string) { '{"foo": "bar"}' }
15
20
 
16
21
  it "decodes json by default" do
17
22
  ::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")
23
+ ::ActionSubscriber::Publisher.publish("twitter.tweet", json_string, "events", :content_type => "application/json")
21
24
 
22
25
  verify_expectation_within(2.0) do
23
26
  expect($messages).to eq Set.new([{
@@ -35,9 +38,7 @@ describe "Payload Decoding", :integration => true do
35
38
 
36
39
  it "it decodes the payload using the custom decoder" do
37
40
  ::ActionSubscriber.auto_subscribe!
38
- channel = connection.create_channel
39
- exchange = channel.topic("events")
40
- exchange.publish(json_string, :routing_key => "twitter.tweet", :content_type => content_type)
41
+ ::ActionSubscriber::Publisher.publish("twitter.tweet", json_string, "events", :content_type => content_type)
41
42
 
42
43
  verify_expectation_within(2.0) do
43
44
  expect($messages).to eq Set.new([{
@@ -0,0 +1,46 @@
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
+ it "registers the routes and sets up the queues" do
37
+ ::ActionSubscriber.auto_subscribe!
38
+ ::ActionSubscriber::Publisher.publish("kyle.inference.yo", "YO", "events")
39
+ ::ActionSubscriber::Publisher.publish("other_routing_key.hey", "HEY", "events")
40
+
41
+ verify_expectation_within(2.0) do
42
+ expect($messages).to eq(Set.new(["YO","HEY"]))
43
+ end
44
+ end
45
+ end
46
+ end
@@ -13,13 +13,16 @@ end
13
13
 
14
14
  describe "Manual Message Acknowledgment", :integration => true do
15
15
  let(:connection) { subscriber.connection }
16
+ let(:draw_routes) do
17
+ ::ActionSubscriber.draw_routes do
18
+ default_routes_for BaconSubscriber
19
+ end
20
+ end
16
21
  let(:subscriber) { BaconSubscriber }
17
22
 
18
23
  it "retries rejected messages and stops retrying acknowledged messages" do
19
24
  ::ActionSubscriber.auto_subscribe!
20
- channel = connection.create_channel
21
- exchange = channel.topic("events")
22
- exchange.publish("BACON!", :routing_key => "bacon.served")
25
+ ::ActionSubscriber::Publisher.publish("bacon.served", "BACON!", "events")
23
26
 
24
27
  verify_expectation_within(2.0) do
25
28
  expect($messages).to eq(Set.new(["BACON!::0", "BACON!::1", "BACON!::2"]))
@@ -0,0 +1,29 @@
1
+ class DifferentThreadpoolsSubscriber < ActionSubscriber::Base
2
+ def one
3
+ $messages << payload
4
+ end
5
+
6
+ def two
7
+ $messages << payload
8
+ end
9
+ end
10
+
11
+ describe "Separate Threadpools for Different Message", :integration => true do
12
+ let(:draw_routes) do
13
+ low_priority_threadpool = ::ActionSubscriber::Threadpool.new_pool(:low_priority, 1)
14
+ ::ActionSubscriber.draw_routes do
15
+ route DifferentThreadpoolsSubscriber, :one
16
+ route DifferentThreadpoolsSubscriber, :two, :threadpool => low_priority_threadpool
17
+ end
18
+ end
19
+
20
+ it "processes messages in separate threadpools based on the routes" do
21
+ ::ActionSubscriber.auto_subscribe!
22
+ ::ActionSubscriber::Publisher.publish("different_threadpools.one", "ONE", "events")
23
+ ::ActionSubscriber::Publisher.publish("different_threadpools.two", "TWO", "events")
24
+
25
+ verify_expectation_within(2.0) do
26
+ expect($messages).to eq(Set.new(["ONE","TWO"]))
27
+ end
28
+ end
29
+ end
@@ -20,6 +20,7 @@ RSpec.configure do |config|
20
20
 
21
21
  config.before(:each, :integration => true) do
22
22
  $messages = Set.new
23
+ draw_routes if respond_to?(:draw_routes)
23
24
  ::ActionSubscriber::RabbitConnection.subscriber_connection
24
25
  ::ActionSubscriber.setup_queues!
25
26
  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.6.0
4
+ version: 1.7.0.pre0
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: 2015-12-04 00:00:00.000000000 Z
15
+ date: 2015-12-23 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: activesupport
@@ -202,6 +202,7 @@ files:
202
202
  - lib/action_subscriber/configuration.rb
203
203
  - lib/action_subscriber/default_routing.rb
204
204
  - lib/action_subscriber/dsl.rb
205
+ - lib/action_subscriber/logging.rb
205
206
  - lib/action_subscriber/march_hare/subscriber.rb
206
207
  - lib/action_subscriber/message_retry.rb
207
208
  - lib/action_subscriber/middleware.rb
@@ -230,7 +231,9 @@ files:
230
231
  - spec/integration/basic_subscriber_spec.rb
231
232
  - spec/integration/custom_headers_spec.rb
232
233
  - spec/integration/decoding_payloads_spec.rb
234
+ - spec/integration/inferred_routes_spec.rb
233
235
  - spec/integration/manual_acknowledgement_spec.rb
236
+ - spec/integration/multiple_threadpools_spec.rb
234
237
  - spec/lib/action_subscriber/base_spec.rb
235
238
  - spec/lib/action_subscriber/configuration_spec.rb
236
239
  - spec/lib/action_subscriber/dsl_spec.rb
@@ -262,12 +265,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
262
265
  version: '0'
263
266
  required_rubygems_version: !ruby/object:Gem::Requirement
264
267
  requirements:
265
- - - ">="
268
+ - - ">"
266
269
  - !ruby/object:Gem::Version
267
- version: '0'
270
+ version: 1.3.1
268
271
  requirements: []
269
272
  rubyforge_project:
270
- rubygems_version: 2.4.8
273
+ rubygems_version: 2.5.1
271
274
  signing_key:
272
275
  specification_version: 4
273
276
  summary: ActionSubscriber is a DSL that allows a rails app to consume messages from
@@ -280,7 +283,9 @@ test_files:
280
283
  - spec/integration/basic_subscriber_spec.rb
281
284
  - spec/integration/custom_headers_spec.rb
282
285
  - spec/integration/decoding_payloads_spec.rb
286
+ - spec/integration/inferred_routes_spec.rb
283
287
  - spec/integration/manual_acknowledgement_spec.rb
288
+ - spec/integration/multiple_threadpools_spec.rb
284
289
  - spec/lib/action_subscriber/base_spec.rb
285
290
  - spec/lib/action_subscriber/configuration_spec.rb
286
291
  - spec/lib/action_subscriber/dsl_spec.rb