action_subscriber 1.3.0.rc0-java → 1.4.0-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
  SHA1:
3
- metadata.gz: b86e0cbcf0af1bdd5f25742161fbc643df6f1905
4
- data.tar.gz: 81b0ba3ff06133af583aaff1eed278d5e13e2e36
3
+ metadata.gz: 54f1bedbe81ed4f5f7be1e55396e635804caee90
4
+ data.tar.gz: 98653c65724ab0410128c74fa7d7423fea0d3353
5
5
  SHA512:
6
- metadata.gz: 65411ae99b60937735bd5c6c1a1ee8ecc79be77da3847ccc9bbcbd05d94e16bf6ae7df03eb26ebec507328de30cc424b5b9b633cbc66a5e9b28e15f649e77e4d
7
- data.tar.gz: 997cd52b905f8b8315b1608e5da33dd98c40442bc20f1d86e444d0350d13010d5e1fbd0d36ba021a4536baeb03ad9fc495fa2a5809b8a807ccd036c45f5ce864
6
+ metadata.gz: 34c87c741309e62954644936130e301c3ded6b007190c7ebf6ad9559f43b6bde2fafd3a02918308816ff6b35082442c1b5e1be145263328c2553511c9ac151bc
7
+ data.tar.gz: 294933dfbf85d177f2c14a7ba29c811c8ed8e17a955ce2e638804d8b5097ed983dfd4032d9eaa00cafcaab13889240d1aa39a640a16ff6d0c615786436580e89
@@ -36,6 +36,8 @@ module ActionSubscriber
36
36
  ::ActionSubscriber::Babou.auto_pop!
37
37
  when /subscribe/i then
38
38
  ::ActionSubscriber::Babou.start_subscribers
39
+ else
40
+ fail "ActionSubscriber.configuration.mode must be 'pop' or 'subscribe'. Currently set to '#{::ActionSubscriber.configuration.mode}'"
39
41
  end
40
42
  end
41
43
  end
@@ -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/message_retry"
17
18
  require "action_subscriber/middleware"
18
19
  require "action_subscriber/rabbit_connection"
19
20
  require "action_subscriber/subscribable"
@@ -80,7 +80,8 @@ module ActionSubscriber
80
80
  yield
81
81
  acknowledge
82
82
  rescue => error
83
- reject
83
+ ::ActionSubscriber::MessageRetry.redeliver_message_with_backoff(env)
84
+ acknowledge
84
85
  raise error
85
86
  end
86
87
 
@@ -24,8 +24,10 @@ module ActionSubscriber
24
24
  :content_type => properties[:content_type],
25
25
  :delivery_tag => delivery_info.delivery_tag,
26
26
  :exchange => delivery_info.exchange,
27
+ :headers => properties.headers,
27
28
  :message_id => nil,
28
29
  :routing_key => delivery_info.routing_key,
30
+ :queue => queue.name,
29
31
  }
30
32
  env = ::ActionSubscriber::Middleware::Env.new(self, encoded_payload, properties)
31
33
  enqueue_env(env)
@@ -45,8 +47,10 @@ module ActionSubscriber
45
47
  :content_type => properties.content_type,
46
48
  :delivery_tag => delivery_info.delivery_tag,
47
49
  :exchange => delivery_info.exchange,
50
+ :headers => properties.headers,
48
51
  :message_id => properties.message_id,
49
52
  :routing_key => delivery_info.routing_key,
53
+ :queue => queue.name,
50
54
  }
51
55
  env = ::ActionSubscriber::Middleware::Env.new(self, encoded_payload, properties)
52
56
  enqueue_env(env)
@@ -12,16 +12,18 @@ module ActionSubscriber
12
12
  times_to_pop = [::ActionSubscriber::Threadpool.ready_size, ::ActionSubscriber.config.times_to_pop].min
13
13
  times_to_pop.times do
14
14
  queues.each do |queue|
15
- header, encoded_payload = queue.pop(queue_subscription_options)
15
+ metadata, encoded_payload = queue.pop(queue_subscription_options)
16
16
  next unless encoded_payload
17
17
  ::ActiveSupport::Notifications.instrument "popped_event.action_subscriber", :payload_size => encoded_payload.bytesize, :queue => queue.name
18
18
  properties = {
19
19
  :channel => queue.channel,
20
- :content_type => header.content_type,
21
- :delivery_tag => header.delivery_tag,
22
- :exchange => header.exchange,
23
- :message_id => header.message_id,
24
- :routing_key => header.routing_key,
20
+ :content_type => metadata.content_type,
21
+ :delivery_tag => metadata.delivery_tag,
22
+ :exchange => metadata.exchange,
23
+ :headers => _normalized_headers(metadata),
24
+ :message_id => metadata.message_id,
25
+ :routing_key => metadata.routing_key,
26
+ :queue => queue.name,
25
27
  }
26
28
  env = ::ActionSubscriber::Middleware::Env.new(self, encoded_payload, properties)
27
29
  enqueue_env(env)
@@ -35,15 +37,17 @@ module ActionSubscriber
35
37
  def auto_subscribe!
36
38
  queues.each do |queue|
37
39
  queue.channel.prefetch = ::ActionSubscriber.config.prefetch if acknowledge_messages?
38
- consumer = queue.subscribe(queue_subscription_options) do |header, encoded_payload|
40
+ consumer = queue.subscribe(queue_subscription_options) do |metadata, encoded_payload|
39
41
  ::ActiveSupport::Notifications.instrument "received_event.action_subscriber", :payload_size => encoded_payload.bytesize, :queue => queue.name
40
42
  properties = {
41
43
  :channel => queue.channel,
42
- :content_type => header.content_type,
43
- :delivery_tag => header.delivery_tag,
44
- :exchange => header.exchange,
45
- :message_id => header.message_id,
46
- :routing_key => header.routing_key,
44
+ :content_type => metadata.content_type,
45
+ :delivery_tag => metadata.delivery_tag,
46
+ :exchange => metadata.exchange,
47
+ :headers => _normalized_headers(metadata),
48
+ :message_id => metadata.message_id,
49
+ :routing_key => metadata.routing_key,
50
+ :queue => queue.name,
47
51
  }
48
52
  env = ::ActionSubscriber::Middleware::Env.new(self, encoded_payload, properties)
49
53
  enqueue_env(env)
@@ -66,6 +70,13 @@ module ActionSubscriber
66
70
  end
67
71
  end
68
72
  end
73
+
74
+ def _normalized_headers(metadata)
75
+ return {} unless metadata.headers
76
+ metadata.headers.each_with_object({}) do |(header,value), hash|
77
+ hash[header] = value.to_s
78
+ end
79
+ end
69
80
  end
70
81
  end
71
82
  end
@@ -0,0 +1,60 @@
1
+ module ActionSubscriber
2
+ module MessageRetry
3
+ SCHEDULE = {
4
+ 2 => 100,
5
+ 3 => 500,
6
+ 4 => 2_500,
7
+ 5 => 12_500,
8
+ 6 => 62_500,
9
+ 7 => 312_500,
10
+ 8 => 1_562_500,
11
+ 9 => 7_812_500,
12
+ 10 => 39_062_500,
13
+ }.freeze
14
+
15
+ def self.redeliver_message_with_backoff(env)
16
+ next_attempt = get_last_attempt_number(env) + 1
17
+ ttl = SCHEDULE[next_attempt]
18
+ return unless ttl
19
+ with_exchange(env, ttl) do |exchange|
20
+ exchange.publish(env.encoded_payload, retry_options(env, next_attempt))
21
+ end
22
+ end
23
+
24
+ # Private Implementation
25
+ def self.get_last_attempt_number(env)
26
+ attempt_header = env.headers.fetch("as-attempt", "1")
27
+ attempt_header.to_i
28
+ end
29
+
30
+ def self.retry_headers(env, attempt)
31
+ env.headers.reject do |key, val|
32
+ key == "x-death"
33
+ end.merge({"as-attempt" => attempt.to_s})
34
+ end
35
+
36
+ def self.retry_options(env, attempt)
37
+ {
38
+ :content_type => env.content_type,
39
+ :routing_key => env.routing_key,
40
+ :headers => retry_headers(env, attempt),
41
+ }
42
+ end
43
+
44
+ def self.with_exchange(env, ttl)
45
+ exchange_retry_name = "#{env.exchange}_retry_#{ttl}"
46
+ queue_retry_name = "#{env.queue}_retry_#{ttl}"
47
+ channel = RabbitConnection.subscriber_connection.create_channel
48
+ begin
49
+ channel.confirm_select
50
+ exchange = channel.topic(exchange_retry_name)
51
+ queue = channel.queue(queue_retry_name, :arguments => {"x-dead-letter-exchange" => env.exchange, "x-message-ttl" => ttl})
52
+ queue.bind(exchange, :routing_key => env.routing_key)
53
+ yield(exchange)
54
+ channel.wait_for_confirms
55
+ ensure
56
+ channel.close rescue nil
57
+ end
58
+ end
59
+ end
60
+ end
@@ -6,8 +6,10 @@ module ActionSubscriber
6
6
  attr_reader :content_type,
7
7
  :encoded_payload,
8
8
  :exchange,
9
+ :headers,
9
10
  :message_id,
10
11
  :routing_key,
12
+ :queue,
11
13
  :subscriber
12
14
 
13
15
  ##
@@ -18,16 +20,18 @@ module ActionSubscriber
18
20
  # :content_type => String
19
21
  # :delivery_tag => String (the message identifier to send back to rabbitmq for acknowledgement)
20
22
  # :exchange => String
23
+ # :headers => Hash[ String => String ]
21
24
  # :message_id => String
22
25
  # :routing_key => String
23
-
24
26
  def initialize(subscriber, encoded_payload, properties)
25
27
  @channel = properties.fetch(:channel)
26
28
  @content_type = properties.fetch(:content_type)
27
29
  @delivery_tag = properties.fetch(:delivery_tag)
28
30
  @encoded_payload = encoded_payload
29
31
  @exchange = properties.fetch(:exchange)
32
+ @headers = properties.fetch(:headers) || {}
30
33
  @message_id = properties.fetch(:message_id)
34
+ @queue = properties.fetch(:queue)
31
35
  @routing_key = properties.fetch(:routing_key)
32
36
  @subscriber = subscriber
33
37
  end
@@ -25,10 +25,12 @@ module ActionSubscriber
25
25
  end
26
26
  end
27
27
 
28
- def self.publishing_options(route, options = {})
29
- options[:mandatory] = false unless options.key(:mandatory)
30
- options[:persistent] = false unless options.key(:persistent)
31
- options[:routing_key] = route
28
+ def self.publishing_options(route, in_options = {})
29
+ options = {
30
+ :mandatory => false,
31
+ :persistent => false,
32
+ :routing_key => route,
33
+ }.merge(in_options)
32
34
 
33
35
  if ::RUBY_PLATFORM == "java"
34
36
  java_options = {}
@@ -17,8 +17,10 @@ module ActionSubscriber
17
17
  :content_type => "text/plain",
18
18
  :delivery_tag => "XYZ",
19
19
  :exchange => "events",
20
+ :headers => {},
20
21
  :message_id => "MSG-123",
21
22
  :routing_key => "amigo.user.created",
23
+ :queue => "test.amigo.user.created",
22
24
  }.freeze
23
25
 
24
26
  # Create a new subscriber instance. Available options are:
@@ -73,8 +75,10 @@ end
73
75
  :content_type => "text/plain",
74
76
  :delivery_tag => "XYZ",
75
77
  :exchange => "events",
78
+ :headers => {},
76
79
  :message_id => "MSG-123",
77
80
  :routing_key => "amigo.user.created",
81
+ :queue => "test.amigo.user.created",
78
82
  }}
79
83
  end
80
84
 
@@ -1,3 +1,3 @@
1
1
  module ActionSubscriber
2
- VERSION = "1.3.0.rc0"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -17,7 +17,7 @@ describe "at_least_once! mode", :integration => true do
17
17
  exchange = channel.topic("events")
18
18
  exchange.publish("GrumpFace", :routing_key => "gorby_puff.grumpy")
19
19
 
20
- verify_expectation_within(1.0) do
20
+ verify_expectation_within(2.0) do
21
21
  expect($messages).to eq Set.new(["GrumpFace::0","GrumpFace::1","GrumpFace::2"])
22
22
  end
23
23
  end
@@ -0,0 +1,27 @@
1
+ class PrankSubscriber < ActionSubscriber::Base
2
+ publisher :pikitis
3
+
4
+ def pulled
5
+ $messages << env.headers
6
+ end
7
+ end
8
+
9
+ describe "Custom Headers Are Published and Received", :integration => true do
10
+ let(:headers) { { "Custom" => "content/header" } }
11
+
12
+ it "works for auto_pop!" do
13
+ ::ActionSubscriber::Publisher.publish("pikitis.prank.pulled", "Yo Knope!", "events", :headers => headers)
14
+ verify_expectation_within(2.0) do
15
+ ::ActionSubscriber.auto_pop!
16
+ expect($messages).to eq(Set.new([headers]))
17
+ end
18
+ end
19
+
20
+ it "works for auto_subscriber!" do
21
+ ::ActionSubscriber.auto_subscribe!
22
+ ::ActionSubscriber::Publisher.publish("pikitis.prank.pulled", "Yo Knope!", "events", :headers => headers)
23
+ verify_expectation_within(2.0) do
24
+ expect($messages).to eq(Set.new([headers]))
25
+ end
26
+ end
27
+ end
@@ -7,8 +7,10 @@ describe ActionSubscriber::Middleware::Env do
7
7
  :delivery_tag => "XYZ",
8
8
  :encoded_payload => encoded_payload,
9
9
  :exchange => "events",
10
+ :headers => {},
10
11
  :message_id => "MSG-1234",
11
12
  :routing_key => "amigo.user.created",
13
+ :queue => "test.amigo.user.created",
12
14
  } }
13
15
  let(:subscriber) { UserSubscriber }
14
16
 
@@ -17,8 +19,10 @@ describe ActionSubscriber::Middleware::Env do
17
19
  specify { expect(subject.action).to eq("created") }
18
20
  specify { expect(subject.content_type).to eq(properties[:content_type]) }
19
21
  specify { expect(subject.exchange).to eq(properties[:exchange]) }
22
+ specify { expect(subject.headers).to eq(properties[:headers]) }
20
23
  specify { expect(subject.message_id).to eq(properties[:message_id]) }
21
24
  specify { expect(subject.routing_key).to eq(properties[:routing_key]) }
25
+ specify { expect(subject.queue).to eq(properties[:queue]) }
22
26
 
23
27
  describe "#acknowledge" do
24
28
  it "sends an acknowledgement to rabbitmq" do
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.3.0.rc0
4
+ version: 1.4.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: 2015-10-14 00:00:00.000000000 Z
15
+ date: 2015-10-28 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  requirement: !ruby/object:Gem::Requirement
@@ -202,6 +202,7 @@ files:
202
202
  - lib/action_subscriber/default_routing.rb
203
203
  - lib/action_subscriber/dsl.rb
204
204
  - lib/action_subscriber/march_hare/subscriber.rb
205
+ - lib/action_subscriber/message_retry.rb
205
206
  - lib/action_subscriber/middleware.rb
206
207
  - lib/action_subscriber/middleware/active_record/connection_management.rb
207
208
  - lib/action_subscriber/middleware/active_record/query_cache.rb
@@ -222,6 +223,7 @@ files:
222
223
  - spec/integration/at_most_once_spec.rb
223
224
  - spec/integration/automatic_reconnect_spec.rb
224
225
  - spec/integration/basic_subscriber_spec.rb
226
+ - spec/integration/custom_headers_spec.rb
225
227
  - spec/integration/decoding_payloads_spec.rb
226
228
  - spec/integration/manual_acknowledgement_spec.rb
227
229
  - spec/lib/action_subscriber/base_spec.rb
@@ -254,9 +256,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
254
256
  version: '0'
255
257
  required_rubygems_version: !ruby/object:Gem::Requirement
256
258
  requirements:
257
- - - ">"
259
+ - - ">="
258
260
  - !ruby/object:Gem::Version
259
- version: 1.3.1
261
+ version: '0'
260
262
  requirements: []
261
263
  rubyforge_project:
262
264
  rubygems_version: 2.4.8
@@ -269,6 +271,7 @@ test_files:
269
271
  - spec/integration/at_most_once_spec.rb
270
272
  - spec/integration/automatic_reconnect_spec.rb
271
273
  - spec/integration/basic_subscriber_spec.rb
274
+ - spec/integration/custom_headers_spec.rb
272
275
  - spec/integration/decoding_payloads_spec.rb
273
276
  - spec/integration/manual_acknowledgement_spec.rb
274
277
  - spec/lib/action_subscriber/base_spec.rb