pwwka 0.10.0 → 0.11.0.RC1

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
  SHA1:
3
- metadata.gz: 9a435465fa3e8dcad13bfed44eddbdf49470ad20
4
- data.tar.gz: 6c9f76ff17f52267f047115c30b7e0859bb5c3e4
3
+ metadata.gz: 3694a0647439ed09e9d80f90aa35d3b16724ad9f
4
+ data.tar.gz: 0d6630ecdf0aa36954b24606378a618fa36f8e38
5
5
  SHA512:
6
- metadata.gz: 7701a24942e9fadb630a02cd6f38fb9ae9309c5a5668085b1c7ae9d32fbce81bee06f74410d5d9b90d2458e3468ccd4e04819ebe36e31134ed3925f7c5a579f1
7
- data.tar.gz: 3c01b9656cdbeaff56c1c56ae1a80e3a567ecb850ad661db646e792851da9a55ebc27f35d52a256909d9d8e11278f3afd8d4acbd687a702f9ae8f3dcb49ebea9
6
+ metadata.gz: 2dcb9350aef4c3f9eaf4b5691d3d39216c0e08e4bd606060565c68cb9bc41ba14f21d8ac5c451950bec1656f0d664fc67cd417263fe88543e4cdef185018a8a7
7
+ data.tar.gz: b4b94ed53542512a8e74bb456c3a845013d94869143cef7fcfa8d883a2153cd057256115e938720c9f2a39694ba52638976db2324800b071abebc23d696a62e3
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.3.1
1
+ 2.4.1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pwwka (0.10.0)
4
+ pwwka (0.11.0.RC1)
5
5
  activemodel
6
6
  activesupport
7
7
  bunny
@@ -10,32 +10,37 @@ PATH
10
10
  GEM
11
11
  remote: https://www.rubygems.org/
12
12
  specs:
13
- activemodel (5.0.1)
14
- activesupport (= 5.0.1)
15
- activesupport (5.0.1)
13
+ activemodel (5.1.1)
14
+ activesupport (= 5.1.1)
15
+ activesupport (5.1.1)
16
16
  concurrent-ruby (~> 1.0, >= 1.0.2)
17
17
  i18n (~> 0.7)
18
18
  minitest (~> 5.1)
19
19
  tzinfo (~> 1.1)
20
- amq-protocol (2.1.0)
21
- bunny (2.6.3)
22
- amq-protocol (>= 2.0.1)
23
- concurrent-ruby (1.0.4)
24
- diff-lcs (1.2.5)
20
+ amq-protocol (2.2.0)
21
+ bunny (2.7.0)
22
+ amq-protocol (>= 2.2.0)
23
+ concurrent-ruby (1.0.5)
24
+ diff-lcs (1.3)
25
25
  docile (1.1.5)
26
- i18n (0.8.0)
27
- json (1.8.3)
28
- minitest (5.10.1)
26
+ et-orbi (1.0.4)
27
+ tzinfo
28
+ i18n (0.8.1)
29
+ json (2.1.0)
30
+ minitest (5.10.2)
29
31
  mono_logger (1.1.0)
30
- multi_json (1.11.2)
31
- rack (1.6.4)
32
- rack-protection (1.5.3)
32
+ multi_json (1.12.1)
33
+ mustermann (1.0.0)
34
+ rack (2.0.3)
35
+ rack-protection (2.0.0)
33
36
  rack
34
- rake (10.5.0)
35
- redis (3.2.2)
36
- redis-namespace (1.5.2)
37
+ rainbow (2.2.2)
38
+ rake
39
+ rake (12.0.0)
40
+ redis (3.3.3)
41
+ redis-namespace (1.5.3)
37
42
  redis (~> 3.0, >= 3.0.4)
38
- resque (1.25.2)
43
+ resque (1.27.4)
39
44
  mono_logger (~> 1.0)
40
45
  multi_json (~> 1.0)
41
46
  redis-namespace (~> 1.3)
@@ -44,40 +49,41 @@ GEM
44
49
  resque-retry (1.5.0)
45
50
  resque (~> 1.25)
46
51
  resque-scheduler (~> 4.0)
47
- resque-scheduler (4.2.0)
52
+ resque-scheduler (4.3.0)
48
53
  mono_logger (~> 1.0)
49
- redis (~> 3.0)
50
- resque (~> 1.25)
54
+ redis (~> 3.3)
55
+ resque (~> 1.26)
51
56
  rufus-scheduler (~> 3.2)
52
- resqutils (1.2.0)
57
+ resqutils (1.2.1)
53
58
  resque
54
- rspec (3.4.0)
55
- rspec-core (~> 3.4.0)
56
- rspec-expectations (~> 3.4.0)
57
- rspec-mocks (~> 3.4.0)
58
- rspec-core (3.4.3)
59
- rspec-support (~> 3.4.0)
60
- rspec-expectations (3.4.0)
59
+ rspec (3.6.0)
60
+ rspec-core (~> 3.6.0)
61
+ rspec-expectations (~> 3.6.0)
62
+ rspec-mocks (~> 3.6.0)
63
+ rspec-core (3.6.0)
64
+ rspec-support (~> 3.6.0)
65
+ rspec-expectations (3.6.0)
61
66
  diff-lcs (>= 1.2.0, < 2.0)
62
- rspec-support (~> 3.4.0)
63
- rspec-mocks (3.4.1)
67
+ rspec-support (~> 3.6.0)
68
+ rspec-mocks (3.6.0)
64
69
  diff-lcs (>= 1.2.0, < 2.0)
65
- rspec-support (~> 3.4.0)
66
- rspec-support (3.4.1)
67
- rufus-scheduler (3.3.1)
68
- tzinfo
69
- simplecov (0.12.0)
70
+ rspec-support (~> 3.6.0)
71
+ rspec-support (3.6.0)
72
+ rufus-scheduler (3.4.2)
73
+ et-orbi (~> 1.0)
74
+ simplecov (0.14.1)
70
75
  docile (~> 1.1.0)
71
76
  json (>= 1.8, < 3)
72
77
  simplecov-html (~> 0.10.0)
73
- simplecov-html (0.10.0)
74
- sinatra (1.4.7)
75
- rack (~> 1.5)
76
- rack-protection (~> 1.4)
77
- tilt (>= 1.3, < 3)
78
- thread_safe (0.3.5)
79
- tilt (2.0.2)
80
- tzinfo (1.2.2)
78
+ simplecov-html (0.10.1)
79
+ sinatra (2.0.0)
80
+ mustermann (~> 1.0)
81
+ rack (~> 2.0)
82
+ rack-protection (= 2.0.0)
83
+ tilt (~> 2.0)
84
+ thread_safe (0.3.6)
85
+ tilt (2.0.7)
86
+ tzinfo (1.2.3)
81
87
  thread_safe (~> 0.1)
82
88
  vegas (0.1.11)
83
89
  rack (>= 1.0.0)
@@ -87,6 +93,7 @@ PLATFORMS
87
93
 
88
94
  DEPENDENCIES
89
95
  pwwka!
96
+ rainbow
90
97
  rake
91
98
  resque
92
99
  resque-retry
@@ -95,4 +102,4 @@ DEPENDENCIES
95
102
  simplecov
96
103
 
97
104
  BUNDLED WITH
98
- 1.13.6
105
+ 1.14.6
data/README.md CHANGED
@@ -91,6 +91,35 @@ Pwwka::Transmitter.send_message!(payload, routing_key)
91
91
 
92
92
  The payload should be a simple hash containing primitives. Don't send objects because the payload will be converted to JSON for sending.
93
93
 
94
+ #### AMQP Attributes
95
+
96
+ By default, pwwka will set the following [AMQP Attributes](http://stackoverflow.com/questions/18403623/rabbitmq-amqp-basicproperties-builder-values/18447385#18447385):
97
+
98
+ * `message_id` - a GUID
99
+ * `timestamp` - The time the message is sent
100
+ * `app_id` - the name of your Rails app or, if you aren't using rails, the value of `app_id` given to the configuration
101
+ * `content_type` - `application/json; version=1`
102
+
103
+ You may optionally set the following when sending a message to set these additional attributes:
104
+
105
+ * `message_id` - to override the GUID. Generally don't do this.
106
+ * `type` - a String to define the data type you are sending. Useful for languages with static types to know how to
107
+ deserialize. You should ensure that the combo of `app_id` and `type` are unique to your entire ecosystem or consumers won't
108
+ know what they are receiving.
109
+ * `headers` - a hash of arbitrary headers.
110
+
111
+ A fuller example:
112
+
113
+ ```ruby
114
+ Pwwka::Transmitter.send_message!(
115
+ { "customer_id" => 12345, "active" => true },
116
+ "customers.customer.created",
117
+ type: "Customer",
118
+ headers: {
119
+ "RAILS_VERSION" => "5.1.1"
120
+ }
121
+ )
122
+ ```
94
123
 
95
124
  #### Error Handling
96
125
 
@@ -12,6 +12,7 @@ module Pwwka
12
12
  attr_accessor :async_job_klass
13
13
  attr_accessor :send_message_resque_backoff_strategy
14
14
  attr_accessor :requeue_on_error
15
+ attr_writer :app_id
15
16
  attr_writer :keep_alive_on_handler_klass_exceptions
16
17
 
17
18
  def initialize
@@ -32,6 +33,22 @@ module Pwwka
32
33
  @keep_alive_on_handler_klass_exceptions
33
34
  end
34
35
 
36
+ def app_id
37
+ if @app_id.to_s.strip == ""
38
+ if defined?(Rails)
39
+ if Rails.respond_to?(:application)
40
+ Rails.application.class.parent.name
41
+ else
42
+ raise "'Rails' is defined, but it doesn't respond to #application, so could not derive the app_id; you must explicitly set it"
43
+ end
44
+ else
45
+ raise "Could not derive the app_id; you must explicitly set it"
46
+ end
47
+ else
48
+ @app_id
49
+ end
50
+ end
51
+
35
52
  def payload_logging
36
53
  @payload_logging || :info
37
54
  end
@@ -0,0 +1,30 @@
1
+ require "securerandom"
2
+ module Pwwka
3
+ # Encaspulates the options we pass to `topic_exchange.publish` as well
4
+ # as the various defaults and auto-generated values.
5
+ class PublishOptions
6
+ def initialize(routing_key: ,
7
+ message_id: :auto_generate,
8
+ type: ,
9
+ headers:,
10
+ expiration: nil)
11
+ @options_hash = {
12
+ routing_key: routing_key,
13
+ message_id: message_id.to_s == "auto_generate" ? SecureRandom.uuid : message_id,
14
+ content_type: "application/json; version=1",
15
+ persistent: true,
16
+ app_id: Pwwka.configuration.app_id
17
+ }
18
+ @options_hash[:type] = type unless type.nil?
19
+ @options_hash[:headers] = headers unless headers.nil?
20
+ @options_hash[:expiration] = expiration unless expiration.nil?
21
+ end
22
+
23
+ def message_id
24
+ @options_hash[:message_id]
25
+ end
26
+ def to_h
27
+ @options_hash.merge(timestamp: Time.now.to_i)
28
+ end
29
+ end
30
+ end
@@ -8,9 +8,21 @@ module Pwwka
8
8
  extend Resque::Plugins::ExponentialBackoff rescue nil # Optional
9
9
  @backoff_strategy = Pwwka.configuration.send_message_resque_backoff_strategy
10
10
 
11
- def self.perform(payload, routing_key)
11
+ def self.perform(payload, routing_key, options = {})
12
+
13
+ type = options["type"]
14
+ message_id = options["message_id"] || "auto_generate"
15
+ headers = options["headers"]
16
+
12
17
  info("Sending message async #{routing_key}, #{payload}")
13
- Pwwka::Transmitter.send_message!(payload, routing_key, on_error: :raise)
18
+ message_id = message_id.to_sym if message_id == "auto_generate"
19
+ Pwwka::Transmitter.send_message!(
20
+ payload,
21
+ routing_key,
22
+ type: type,
23
+ message_id: message_id,
24
+ headers: headers,
25
+ on_error: :raise)
14
26
  end
15
27
  end
16
28
  end
@@ -1,3 +1,5 @@
1
+ require_relative "publish_options"
2
+
1
3
  begin # optional dependency
2
4
  require 'resque'
3
5
  require 'resque-retry'
@@ -34,6 +36,9 @@ module Pwwka
34
36
  # routing_key:: String routing key for the message
35
37
  # delayed:: Boolean send this message later
36
38
  # delay_by:: Integer milliseconds to delay the message
39
+ # type:: A string describing the type. This + your configured app_id should be unique to your entire ecosystem.
40
+ # message_id:: If specified (which generally you should not do), sets the id of the message. If omitted, a GUID is used.
41
+ # headers:: A hash of arbitrary headers to include in the AMQP attributes
37
42
  # on_error:: What is the behavior of
38
43
  # - :ignore (aka as send_message_safely)
39
44
  # - :raise
@@ -42,12 +47,17 @@ module Pwwka
42
47
  # Returns true
43
48
  #
44
49
  # Raises any exception generated by the innerworkings of this library.
45
- def self.send_message!(payload, routing_key, on_error: :raise,
46
- delayed: false, delay_by: nil)
50
+ def self.send_message!(payload, routing_key,
51
+ on_error: :raise,
52
+ delayed: false,
53
+ delay_by: nil,
54
+ type: nil,
55
+ message_id: :auto_generate,
56
+ headers: nil)
47
57
  if delayed
48
- new.send_delayed_message!(*[payload, routing_key, delay_by].compact)
58
+ new.send_delayed_message!(*[payload, routing_key, delay_by].compact, type: type, headers: headers, message_id: message_id)
49
59
  else
50
- new.send_message!(payload, routing_key)
60
+ new.send_message!(payload, routing_key, type: type, headers: headers, message_id: message_id)
51
61
  end
52
62
  logf "AFTER Transmitting Message on %{routing_key} -> %{payload}",routing_key: routing_key, payload: payload
53
63
  true
@@ -74,9 +84,18 @@ module Pwwka
74
84
 
75
85
  # Use Resque to enqueue the message.
76
86
  # - :delay_by_ms:: Integer milliseconds to delay the message. Default is 0.
77
- def self.send_message_async(payload, routing_key, delay_by_ms: 0)
87
+ def self.send_message_async(payload, routing_key,
88
+ delay_by_ms: 0,
89
+ type: nil,
90
+ message_id: :auto_generate,
91
+ headers: nil)
78
92
  job = Pwwka.configuration.async_job_klass
79
- Resque.enqueue_in(delay_by_ms/1000, job, payload, routing_key)
93
+ # Be perhaps too carefully making sure we queue jobs in the legacy way
94
+ if type == nil && message_id == :auto_generate && headers == nil
95
+ Resque.enqueue_in(delay_by_ms/1000, job, payload, routing_key)
96
+ else
97
+ Resque.enqueue_in(delay_by_ms/1000, job, payload, routing_key, type: type, message_id: message_id, headers: headers)
98
+ end
80
99
  end
81
100
 
82
101
  # Send a less important message that doesn't have to go through. This eats
@@ -89,35 +108,41 @@ module Pwwka
89
108
  #
90
109
  # Returns true if the message was sent, false otherwise
91
110
  # @deprecated This is ignoring a message. ::send_message supports this explicitly.
92
- def self.send_message_safely(payload, routing_key, delayed: false, delay_by: nil)
111
+ def self.send_message_safely(payload, routing_key, delayed: false, delay_by: nil, message_id: message_id)
93
112
  send_message!(payload, routing_key, delayed: delayed, delay_by: delay_by, on_error: :ignore)
94
113
  end
95
114
 
96
- def send_message!(payload, routing_key)
97
- logf "START Transmitting Message on %{routing_key} -> %{payload}", routing_key: routing_key, payload: payload
98
- channel_connector.topic_exchange.publish(
99
- payload.to_json,
100
- routing_key: routing_key,
101
- persistent: true)
115
+ def send_message!(payload, routing_key, type: nil, headers: nil, message_id: :auto_generate)
116
+ publish_options = Pwwka::PublishOptions.new(
117
+ routing_key: routing_key,
118
+ message_id: message_id,
119
+ type: type,
120
+ headers: headers
121
+ )
122
+ logf "START Transmitting Message on id[%{id}] %{routing_key} -> %{payload}", id: publish_options.message_id, routing_key: routing_key, payload: payload
123
+ channel_connector.topic_exchange.publish(payload.to_json, publish_options.to_h)
102
124
  channel_connector.connection_close
103
125
  # if it gets this far it has succeeded
104
- logf "END Transmitting Message on %{routing_key} -> %{payload}", routing_key: routing_key, payload: payload
126
+ logf "END Transmitting Message on id[%{id}] %{routing_key} -> %{payload}", id: publish_options.message_id, routing_key: routing_key, payload: payload
105
127
  true
106
128
  end
107
129
 
108
130
 
109
- def send_delayed_message!(payload, routing_key, delay_by = DEFAULT_DELAY_BY_MS)
131
+ def send_delayed_message!(payload, routing_key, delay_by = DEFAULT_DELAY_BY_MS, type: nil, headers: nil, message_id: :auto_generate)
110
132
  channel_connector.raise_if_delayed_not_allowed
111
- logf "START Transmitting Delayed Message on %{routing_key} -> %{payload}", routing_key: routing_key, payload: payload
133
+ publish_options = Pwwka::PublishOptions.new(
134
+ routing_key: routing_key,
135
+ message_id: message_id,
136
+ type: type,
137
+ headers: headers,
138
+ expiration: delay_by
139
+ )
140
+ logf "START Transmitting Delayed Message on id[%{id}] %{routing_key} -> %{payload}", id: publish_options.message_id, routing_key: routing_key, payload: payload
112
141
  channel_connector.create_delayed_queue
113
- channel_connector.delayed_exchange.publish(
114
- payload.to_json,
115
- routing_key: routing_key,
116
- expiration: delay_by,
117
- persistent: true)
142
+ channel_connector.delayed_exchange.publish(payload.to_json,publish_options.to_h)
118
143
  channel_connector.connection_close
119
144
  # if it gets this far it has succeeded
120
- logf "END Transmitting Delayed Message on %{routing_key} -> %{payload}", routing_key: routing_key, payload: payload
145
+ logf "END Transmitting Delayed Message on id[%{id}] %{routing_key} -> %{payload}", id: publish_options.message_id, routing_key: routing_key, payload: payload
121
146
  true
122
147
  end
123
148
 
data/lib/pwwka/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Pwwka
2
- VERSION = '0.10.0'
2
+ VERSION = '0.11.0.RC1'
3
3
  end
data/pwwka.gemspec CHANGED
@@ -29,4 +29,5 @@ Gem::Specification.new do |s|
29
29
  s.add_development_dependency("resque-retry")
30
30
  s.add_development_dependency("simplecov")
31
31
  s.add_development_dependency("resqutils")
32
+ s.add_development_dependency("rainbow")
32
33
  end
@@ -31,79 +31,177 @@ describe "sending and receiving messages", :integration do
31
31
  @testing_setup.kill_threads_and_clear_queues
32
32
  end
33
33
 
34
- it "can send a message that gets routed to all receivers" do
35
- Pwwka::Transmitter.send_message!({ sample: "payload", has: { deeply: true, nested: 4 }},
36
- "pwwka.testing.foo")
37
- allow_receivers_to_process_queues
38
-
39
- expect(AllReceiver.messages_received.size).to eq(1)
40
- expect(FooReceiver.messages_received.size).to eq(1)
41
- expect(OtherFooReceiver.messages_received.size).to eq(1)
42
- @testing_setup.queues.each do |queue|
43
- expect(queue.message_count).to eq(0)
34
+ context "routing" do
35
+ it "can send a message that gets routed to all receivers" do
36
+ Pwwka::Transmitter.send_message!({ sample: "payload", has: { deeply: true, nested: 4 }},
37
+ "pwwka.testing.foo")
38
+ allow_receivers_to_process_queues
39
+
40
+ expect(AllReceiver.messages_received.size).to eq(1)
41
+ expect(FooReceiver.messages_received.size).to eq(1)
42
+ expect(OtherFooReceiver.messages_received.size).to eq(1)
43
+ @testing_setup.queues.each do |queue|
44
+ expect(queue.message_count).to eq(0)
45
+ end
46
+ end
47
+ it "can send a message that is only delivered to some handlers based on routing key" do
48
+ Pwwka::Transmitter.send_message!({ sample: "payload", has: { deeply: true, nested: 4 }},
49
+ "pwwka.testing.bar")
50
+ allow_receivers_to_process_queues
51
+
52
+ expect(AllReceiver.messages_received.size).to eq(1)
53
+ expect(FooReceiver.messages_received.size).to eq(0)
54
+ expect(OtherFooReceiver.messages_received.size).to eq(0)
55
+ @testing_setup.queues.each do |queue|
56
+ expect(queue.message_count).to eq(0)
57
+ end
44
58
  end
45
59
  end
46
60
 
47
- it "can send a message delayed" do
48
- Pwwka::Transmitter.send_message!({ sample: "payload", has: { deeply: true, nested: 4 }},
49
- "pwwka.testing.foo",
50
- delayed: true,
51
- delay_by: 5_000)
52
- allow_receivers_to_process_queues(1_000)
61
+ context "metadata" do
62
+ it "can access standard metadata" do
63
+ Pwwka::Transmitter.send_message!({ sample: "payload", has: { deeply: true, nested: 4 }},
64
+ "pwwka.testing.foo")
65
+ allow_receivers_to_process_queues
53
66
 
54
- expect(AllReceiver.messages_received.size).to eq(0)
55
- expect(FooReceiver.messages_received.size).to eq(0)
56
- expect(OtherFooReceiver.messages_received.size).to eq(0)
67
+ expect(AllReceiver.metadata[0].message_id).not_to be_nil
68
+ expect(AllReceiver.metadata[0].timestamp).to be_within(2.minutes).of(Time.now)
69
+ expect(AllReceiver.metadata[0].content_type).to eq("application/json; version=1")
70
+ expect(AllReceiver.metadata[0].app_id).to eq("MyAwesomeApp")
71
+ end
57
72
 
58
- allow_receivers_to_process_queues(5_000)
59
- expect(AllReceiver.messages_received.size).to eq(1)
60
- expect(FooReceiver.messages_received.size).to eq(1)
61
- expect(OtherFooReceiver.messages_received.size).to eq(1)
62
- end
73
+ it "can access standard metadata on delayed jobs" do
74
+ Pwwka::Transmitter.send_message!({ sample: "payload", has: { deeply: true, nested: 4 }},
75
+ "pwwka.testing.foo",
76
+ delayed: true,
77
+ delay_by: 100)
78
+ allow_receivers_to_process_queues(200)
79
+
80
+ expect(AllReceiver.metadata[0].message_id).not_to be_nil
81
+ expect(AllReceiver.metadata[0].timestamp).to be_within(2.minutes).of(Time.now)
82
+ expect(AllReceiver.metadata[0].content_type).to eq("application/json; version=1")
83
+ expect(AllReceiver.metadata[0].app_id).to eq("MyAwesomeApp")
84
+ end
63
85
 
64
- it "can send a message that is only delivered to some handlers based on routing key" do
65
- Pwwka::Transmitter.send_message!({ sample: "payload", has: { deeply: true, nested: 4 }},
66
- "pwwka.testing.bar")
67
- allow_receivers_to_process_queues
86
+ it "can access explicitly-provided metadata" do
87
+ Pwwka::Transmitter.send_message!({ sample: "payload", has: { deeply: true, nested: 4 }},
88
+ "pwwka.testing.foo",
89
+ type: "Customer",
90
+ headers: {
91
+ foo: "bar",
92
+ blah: 42,
93
+ })
94
+ allow_receivers_to_process_queues
95
+
96
+ expect(AllReceiver.metadata[0].message_id).not_to be_nil
97
+ expect(AllReceiver.metadata[0].timestamp).to be_within(2.minutes).of(Time.now)
98
+ expect(AllReceiver.metadata[0].content_type).to eq("application/json; version=1")
99
+ expect(AllReceiver.metadata[0].app_id).to eq("MyAwesomeApp")
100
+ expect(AllReceiver.metadata[0].type).to eq("Customer")
101
+ expect(AllReceiver.metadata[0].headers["foo"]).to eq("bar")
102
+ expect(AllReceiver.metadata[0].headers["blah"]).to eq(42)
103
+ end
68
104
 
69
- expect(AllReceiver.messages_received.size).to eq(1)
70
- expect(FooReceiver.messages_received.size).to eq(0)
71
- expect(OtherFooReceiver.messages_received.size).to eq(0)
72
- @testing_setup.queues.each do |queue|
73
- expect(queue.message_count).to eq(0)
105
+ it "can access explicitly-provided metadata on delayed jobs" do
106
+ Pwwka::Transmitter.send_message!({ sample: "payload", has: { deeply: true, nested: 4 }},
107
+ "pwwka.testing.foo",
108
+ type: "Customer",
109
+ headers: {
110
+ foo: "bar",
111
+ blah: 42,
112
+ },
113
+ delayed: true,
114
+ delay_by: 100)
115
+ allow_receivers_to_process_queues(200)
116
+
117
+ expect(AllReceiver.metadata[0].message_id).not_to be_nil
118
+ expect(AllReceiver.metadata[0].timestamp).to be_within(2.minutes).of(Time.now)
119
+ expect(AllReceiver.metadata[0].content_type).to eq("application/json; version=1")
120
+ expect(AllReceiver.metadata[0].type).to eq("Customer")
121
+ expect(AllReceiver.metadata[0].app_id).to eq("MyAwesomeApp")
122
+ expect(AllReceiver.metadata[0].headers["foo"]).to eq("bar")
123
+ expect(AllReceiver.metadata[0].headers["blah"]).to eq(42)
74
124
  end
75
125
  end
76
126
 
77
- it "can queue a job to send a message from a Resque job" do
78
- Pwwka::Transmitter.send_message_async({ sample: "payload", has: { deeply: true, nested: 4 }},
79
- "pwwka.testing.bar")
127
+ context "sending messages from a background job" do
128
+ it "can queue a job to send a message from a Resque job" do
129
+ Pwwka::Transmitter.send_message_async({ sample: "payload", has: { deeply: true, nested: 4 }},
130
+ "pwwka.testing.bar")
80
131
 
81
- allow_receivers_to_process_queues # not expecting anything to be processed
132
+ allow_receivers_to_process_queues # not expecting anything to be processed
82
133
 
83
- expect(AllReceiver.messages_received.size).to eq(0)
134
+ expect(AllReceiver.messages_received.size).to eq(0)
84
135
 
85
- process_resque_job(Pwwka::SendMessageAsyncJob,:delayed)
136
+ process_resque_job(Pwwka::SendMessageAsyncJob,:delayed)
86
137
 
87
- allow_receivers_to_process_queues
138
+ allow_receivers_to_process_queues
88
139
 
89
- expect(AllReceiver.messages_received.size).to eq(1)
90
- end
140
+ expect(AllReceiver.messages_received.size).to eq(1)
141
+ end
142
+
143
+ it "can queue a job with optional arguments to send a message from a Resque job" do
144
+ Pwwka::Transmitter.send_message_async(
145
+ { sample: "payload", has: { deeply: true, nested: 4 }},
146
+ "pwwka.testing.bar",
147
+ message_id: "setting this is a bad idea, but you can do it",
148
+ headers: {
149
+ "FOO" => "bar"
150
+ },
151
+ type: "Customer"
152
+ )
153
+
154
+ allow_receivers_to_process_queues # not expecting anything to be processed
155
+
156
+ expect(AllReceiver.messages_received.size).to eq(0)
157
+
158
+ process_resque_job(Pwwka::SendMessageAsyncJob,:delayed)
159
+
160
+ allow_receivers_to_process_queues
91
161
 
92
- it "can queue a job to send a message to a specified Resque job queue" do
93
- async_job_klass = double(:async_job_klass)
94
- configuration = Pwwka::Configuration.new
95
- configuration.async_job_klass = async_job_klass
162
+ expect(AllReceiver.messages_received.size).to eq(1)
163
+ expect(AllReceiver.metadata[0].message_id).to eq("setting this is a bad idea, but you can do it")
164
+ expect(AllReceiver.metadata[0].timestamp).to be_within(2.minutes).of(Time.now)
165
+ expect(AllReceiver.metadata[0].content_type).to eq("application/json; version=1")
166
+ expect(AllReceiver.metadata[0].type).to eq("Customer")
167
+ expect(AllReceiver.metadata[0].app_id).to eq("MyAwesomeApp")
168
+ expect(AllReceiver.metadata[0].headers["FOO"]).to eq("bar")
169
+ end
170
+
171
+ it "can queue a job to send a message to a specified Resque job queue" do
172
+ async_job_klass = double(:async_job_klass)
173
+ configuration = Pwwka::Configuration.new
174
+ configuration.async_job_klass = async_job_klass
175
+
176
+ allow(Pwwka).to receive(:configuration).and_return(configuration)
177
+
178
+ allow(Resque).to receive(:enqueue_in)
96
179
 
97
- allow(Pwwka).to receive(:configuration).and_return(configuration)
180
+ Pwwka::Transmitter.send_message_async({ sample: "payload", has: { deeply: true, nested: 4 }},
181
+ "pwwka.testing.bar")
182
+
183
+ expect(Resque).to have_received(:enqueue_in).with(anything, async_job_klass, anything, anything)
184
+ end
185
+ end
98
186
 
99
- allow(Resque).to receive(:enqueue_in)
187
+ it "can send a message delayed" do
188
+ Pwwka::Transmitter.send_message!({ sample: "payload", has: { deeply: true, nested: 4 }},
189
+ "pwwka.testing.foo",
190
+ delayed: true,
191
+ delay_by: 5_000)
192
+ allow_receivers_to_process_queues(1_000)
100
193
 
101
- Pwwka::Transmitter.send_message_async({ sample: "payload", has: { deeply: true, nested: 4 }},
102
- "pwwka.testing.bar")
194
+ expect(AllReceiver.messages_received.size).to eq(0)
195
+ expect(FooReceiver.messages_received.size).to eq(0)
196
+ expect(OtherFooReceiver.messages_received.size).to eq(0)
103
197
 
104
- expect(Resque).to have_received(:enqueue_in).with(anything, async_job_klass, anything, anything)
198
+ allow_receivers_to_process_queues(5_000)
199
+ expect(AllReceiver.messages_received.size).to eq(1)
200
+ expect(FooReceiver.messages_received.size).to eq(1)
201
+ expect(OtherFooReceiver.messages_received.size).to eq(1)
105
202
  end
106
203
 
204
+
107
205
  class AllReceiver < LoggingReceiver
108
206
  end
109
207
  class FooReceiver < AllReceiver
@@ -1,10 +1,17 @@
1
1
  class LoggingReceiver
2
- def self.reset!; @messages_received = []; end
2
+
3
+ def self.reset!
4
+ @messages_received = []
5
+ @metadata = []
6
+ end
7
+
3
8
  def self.messages_received; @messages_received ||= []; end
9
+ def self.metadata; @metadata ||= []; end
4
10
 
5
11
  reset!
6
12
 
7
13
  def self.handle!(delivery_info,properties,payload)
8
14
  messages_received << [ delivery_info,properties,payload ]
15
+ metadata << properties
9
16
  end
10
17
  end
data/spec/spec_helper.rb CHANGED
@@ -34,6 +34,7 @@ RSpec.configure do |config|
34
34
  c.options[:allow_delayed] = true
35
35
  c.requeue_on_error = false
36
36
  c.rabbit_mq_host = "amqp://guest:guest@localhost:#{test_configuration.rabbit_port}"
37
+ c.app_id = "MyAwesomeApp"
37
38
 
38
39
  unless ENV["SHOW_PWWKA_LOG"] == "true"
39
40
  c.logger = MonoLogger.new("/dev/null")
@@ -41,7 +42,16 @@ RSpec.configure do |config|
41
42
  end
42
43
  Resque.redis = Redis.new(port: test_configuration.resque_redis_port)
43
44
  end
44
-
45
+ config.around(:each) do |example|
46
+ if example.metadata[:integration]
47
+ result = test_configuration.check_services
48
+ unless result.up?
49
+ puts "\n\n" + Rainbow(result.error).yellow.bright + "\n\n"
50
+ exit 1
51
+ end
52
+ end
53
+ example.run
54
+ end
45
55
  config.order = :random
46
56
  config.filter_run_excluding :legacy
47
57
  end
@@ -1,4 +1,8 @@
1
- require 'yaml'
1
+ require "yaml"
2
+ require "socket"
3
+ require "timeout"
4
+ require "rainbow"
5
+
2
6
  class TestConfiguration
3
7
  attr_reader :resque_redis_port, :rabbit_port
4
8
  def initialize(docker_compose_file)
@@ -7,4 +11,34 @@ class TestConfiguration
7
11
  @resque_redis_port = (ENV["PWWKA_RESQUE_REDIS_PORT"] || yaml["services"]["resque"]["ports"].first.split(/:/)[0]).to_i
8
12
  @rabbit_port = (ENV["PWWKA_RABBIT_PORT"] || yaml["services"]["rabbit"]["ports"].first.split(/:/)[0]).to_i
9
13
  end
14
+
15
+ def check_services
16
+ redis_running = is_port_open?("localhost",@resque_redis_port)
17
+ rabbit_running = is_port_open?("localhost",@rabbit_port)
18
+ if !(redis_running && rabbit_port)
19
+ OpenStruct.new(error: "Rabbit and/or Redis is not running - you need to run `docker-compose up` in the root dir",
20
+ up?: false)
21
+ else
22
+ OpenStruct.new(up?: true)
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def is_port_open?(ip, port)
29
+ begin
30
+ Timeout::timeout(1) do
31
+ begin
32
+ s = TCPSocket.new(ip, port)
33
+ s.close
34
+ return true
35
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
36
+ return false
37
+ end
38
+ end
39
+ rescue Timeout::Error
40
+ end
41
+
42
+ return false
43
+ end
10
44
  end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper.rb'
2
+
3
+ module MyAmazingApp
4
+ class Application
5
+ end
6
+ end
7
+ describe Pwwka::Configuration do
8
+
9
+ subject(:configuration) { described_class.new }
10
+ before do
11
+ @env = ENV["RAILS_ENV"]
12
+ ENV["RAILS_ENV"] = "production"
13
+ end
14
+ after do
15
+ ENV["RAILS_ENV"] = @env
16
+ end
17
+
18
+ describe "#topic_exchange_name" do
19
+ it "is based on the Pwwka.environment" do
20
+ expect(configuration.topic_exchange_name).to eq("pwwka.topics.production")
21
+ end
22
+ end
23
+ describe "#delayed_exchange_name" do
24
+ it "is based on the Pwwka.environment" do
25
+ expect(configuration.delayed_exchange_name).to eq("pwwka.delayed.production")
26
+ end
27
+ end
28
+
29
+ describe "#payload_logging" do
30
+ it "is info by default" do
31
+ expect(configuration.payload_logging).to eq(:info)
32
+ end
33
+
34
+ it "can be overridden" do
35
+ configuration.payload_logging = :debug
36
+ expect(configuration.payload_logging).to eq(:debug)
37
+ end
38
+ end
39
+
40
+ describe "#app_id" do
41
+ it "returns the value set explicitly" do
42
+ configuration.app_id = "MyApp"
43
+ expect(configuration.app_id).to eq("MyApp")
44
+ end
45
+ it "blows up when not set" do
46
+ expect {
47
+ configuration.app_id
48
+ }.to raise_error(/Could not derive the app_id; you must explicitly set it/)
49
+ end
50
+ context "when inside a Rails app" do
51
+ before do
52
+ rails = Class.new do
53
+ def self.application
54
+ MyAmazingApp::Application.new
55
+ end
56
+ end
57
+ Object.const_set("Rails",rails)
58
+ end
59
+ after do
60
+ Object.send(:remove_const,"Rails")
61
+ end
62
+ it "uses the Rails app name" do
63
+ expect(configuration.app_id).to eq("MyAmazingApp")
64
+ end
65
+ end
66
+
67
+ context "when Rails is defined, but not how we expect" do
68
+ before do
69
+ rails = Class.new
70
+ Object.const_set("Rails",rails)
71
+ end
72
+ after do
73
+ Object.send(:remove_const,"Rails")
74
+ end
75
+ it "blows up when not set" do
76
+ expect {
77
+ configuration.app_id
78
+ }.to raise_error(/'Rails' is defined, but it doesn't respond to #application, so could not derive the app_id; you must explicitly set it/)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Pwwka::SendMessageAsyncJob do
4
+ describe "::perform" do
5
+ before do
6
+ allow(Pwwka::Transmitter).to receive(:send_message!)
7
+ end
8
+ context "with just two arguments" do
9
+ it "calls through to Pwwka::Transmitter, setting error handling to 'raise'" do
10
+ described_class.perform({ "foo" => "bar"} , "some.routing.key")
11
+ expect(Pwwka::Transmitter).to have_received(:send_message!).with(
12
+ { "foo" => "bar" },
13
+ "some.routing.key",
14
+ type: nil,
15
+ message_id: :auto_generate,
16
+ headers: nil,
17
+ on_error: :raise
18
+ )
19
+ end
20
+ end
21
+ context "with optional values" do
22
+ it "passes them through to Pwwka::Transmitter" do
23
+ described_class.perform(
24
+ { "foo" => "bar"},
25
+ "some.routing.key",
26
+ "type" => "Customer",
27
+ "message_id" => "foobar",
28
+ "headers" => { "x" => "y" }
29
+ )
30
+ expect(Pwwka::Transmitter).to have_received(:send_message!).with(
31
+ { "foo" => "bar" },
32
+ "some.routing.key",
33
+ type: "Customer",
34
+ message_id: "foobar",
35
+ headers: { "x" => "y" },
36
+ on_error: :raise
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
@@ -36,18 +36,46 @@ describe Pwwka::Transmitter do
36
36
  before do
37
37
  allow(Resque).to receive(:enqueue_in)
38
38
  end
39
-
40
- it "queues a Resque job" do
41
- delay_by_ms = 3_000
42
- described_class.send_message_async(payload,routing_key,delay_by_ms: delay_by_ms)
43
- expect(Resque).to have_received(:enqueue_in).with(delay_by_ms/1_000,Pwwka::SendMessageAsyncJob,payload,routing_key)
39
+ context "with only basic required arguments" do
40
+ it "queues a Resque job with no extra args" do
41
+ delay_by_ms = 3_000
42
+ described_class.send_message_async(payload,routing_key,delay_by_ms: delay_by_ms)
43
+ expect(Resque).to have_received(:enqueue_in).with(delay_by_ms/1_000,Pwwka::SendMessageAsyncJob,payload,routing_key)
44
+ end
45
+ end
46
+ context "with everything overridden" do
47
+ it "queues a Resque job with the various arguments" do
48
+ delay_by_ms = 3_000
49
+ described_class.send_message_async(
50
+ payload,routing_key,
51
+ delay_by_ms: delay_by_ms,
52
+ message_id: "snowflake id that is likely a bad idea, but if you must",
53
+ type: "Customer",
54
+ headers: {
55
+ "custom" => "value",
56
+ "other_custom" => "other_value",
57
+ }
58
+ )
59
+ expect(Resque).to have_received(:enqueue_in).with(
60
+ delay_by_ms/1_000,
61
+ Pwwka::SendMessageAsyncJob,
62
+ payload,
63
+ routing_key,
64
+ message_id: "snowflake id that is likely a bad idea, but if you must",
65
+ type: "Customer",
66
+ headers: {
67
+ "custom" => "value",
68
+ "other_custom" => "other_value",
69
+ }
70
+ )
71
+ end
44
72
  end
45
73
  end
46
74
 
47
75
  shared_examples "it passes through to an instance" do
48
76
  context "not using delayed flag" do
49
77
  it "calls through to send_message!" do
50
- expect_any_instance_of(described_class).to receive(:send_message!).with(payload,routing_key)
78
+ expect_any_instance_of(described_class).to receive(:send_message!).with(payload,routing_key, type: nil, headers: nil, message_id: :auto_generate)
51
79
  described_class.send(method,payload,routing_key)
52
80
  end
53
81
  it "logs after sending" do
@@ -66,19 +94,140 @@ describe Pwwka::Transmitter do
66
94
  context "explicitly setting delay time" do
67
95
  it "calls through to send_delayed_message! using the given delay time" do
68
96
  delay_by = 1_000
69
- expect_any_instance_of(described_class).to receive(:send_delayed_message!).with(payload,routing_key,delay_by)
97
+ expect_any_instance_of(described_class).to receive(:send_delayed_message!).with(payload,routing_key,delay_by, type: nil, headers: nil, message_id: :auto_generate)
70
98
  described_class.send(method,payload,routing_key,delayed: true, delay_by: delay_by)
71
99
  end
72
100
  end
73
101
  context "using the default delay time" do
74
102
  it "calls through to send_delayed_message! using its default delay time" do
75
- expect_any_instance_of(described_class).to receive(:send_delayed_message!).with(payload,routing_key)
103
+ expect_any_instance_of(described_class).to receive(:send_delayed_message!).with(payload,routing_key, type: nil, headers: nil, message_id: :auto_generate)
76
104
  described_class.send(method,payload,routing_key,delayed: true)
77
105
  end
78
106
  end
79
107
  end
80
108
  end
81
109
 
110
+ shared_examples "it sends standard and overridden data to the exchange" do
111
+ it "publishes to the topic exchange" do
112
+ expect(exchange).to have_received(:publish).with(payload.to_json, kind_of(Hash))
113
+ end
114
+
115
+ it "passes the routing key" do
116
+ expect(exchange).to have_received(:publish).with(
117
+ payload.to_json,
118
+ hash_including(routing_key: routing_key))
119
+ end
120
+
121
+ it "sets the type" do
122
+ expect(exchange).to have_received(:publish).with(
123
+ payload.to_json,
124
+ hash_including(type: "Customer"))
125
+ end
126
+
127
+ it "sets the headers" do
128
+ expect(exchange).to have_received(:publish).with(
129
+ payload.to_json,
130
+ hash_including(headers: { "custom" => "value", "other_custom" => "other_value" }))
131
+ end
132
+
133
+ it "uses the overridden message id" do
134
+ expect(exchange).to have_received(:publish).with(
135
+ payload.to_json,
136
+ hash_including(message_id: "snowflake id that is likely a bad idea, but if you must"))
137
+ end
138
+
139
+ it "sets the timestamp to now" do
140
+ expect(exchange).to have_received(:publish).with(
141
+ payload.to_json,
142
+ hash_including(timestamp: a_timestamp_about_now))
143
+ end
144
+
145
+ it "sets the app id to what's configured" do
146
+ expect(exchange).to have_received(:publish).with(
147
+ payload.to_json,
148
+ hash_including(app_id: "MyAwesomeApp"))
149
+ end
150
+
151
+ it "sets the content type to JSON with a version" do
152
+ expect(exchange).to have_received(:publish).with(
153
+ payload.to_json,
154
+ hash_including(content_type: "application/json; version=1"))
155
+ end
156
+
157
+ it "sets persistent true" do
158
+ expect(exchange).to have_received(:publish).with(
159
+ payload.to_json,
160
+ hash_including(persistent: true))
161
+ end
162
+ end
163
+
164
+ shared_examples "it sends standard attributes and the payload to the exchange" do
165
+ it "publishes to the topic exchange" do
166
+ expect(exchange).to have_received(:publish).with(payload.to_json, kind_of(Hash))
167
+ end
168
+
169
+ it "passes the routing key" do
170
+ expect(exchange).to have_received(:publish).with(
171
+ payload.to_json,
172
+ hash_including(routing_key: routing_key))
173
+ end
174
+
175
+ it "sets a default message id" do
176
+ expect(exchange).to have_received(:publish).with(
177
+ payload.to_json,
178
+ hash_including(message_id: a_uuid))
179
+ end
180
+
181
+ it "sets the timestamp to now" do
182
+ expect(exchange).to have_received(:publish).with(
183
+ payload.to_json,
184
+ hash_including(timestamp: a_timestamp_about_now))
185
+ end
186
+
187
+ it "sets the app id to what's configured" do
188
+ expect(exchange).to have_received(:publish).with(
189
+ payload.to_json,
190
+ hash_including(app_id: "MyAwesomeApp"))
191
+ end
192
+
193
+ it "sets the content type to JSON with a version" do
194
+ expect(exchange).to have_received(:publish).with(
195
+ payload.to_json,
196
+ hash_including(content_type: "application/json; version=1"))
197
+ end
198
+
199
+ it "sets persistent true" do
200
+ expect(exchange).to have_received(:publish).with(
201
+ payload.to_json,
202
+ hash_including(persistent: true))
203
+ end
204
+
205
+ it "does not set the type" do
206
+ expect(exchange).to have_received(:publish).with(
207
+ payload.to_json,
208
+ hash_excluding(:type))
209
+ end
210
+
211
+ it "does not set headers" do
212
+ expect(exchange).to have_received(:publish).with(
213
+ payload.to_json,
214
+ hash_excluding(:headers))
215
+ end
216
+ end
217
+
218
+ RSpec::Matchers.define :a_uuid do |x|
219
+ match { |actual|
220
+ actual =~ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
221
+ }
222
+ end
223
+
224
+ RSpec::Matchers.define :a_timestamp_about_now do |x|
225
+ match { |actual|
226
+ (actual - Time.now.to_i).abs < 1000
227
+ }
228
+ end
229
+
230
+
82
231
  describe ".send_message!" do
83
232
  context "no errors" do
84
233
  it_behaves_like "it passes through to an instance" do
@@ -165,21 +314,45 @@ describe Pwwka::Transmitter do
165
314
  expect(transmitter.send_message!(payload,routing_key)).to eq(true)
166
315
  end
167
316
 
168
- it "publishes the message" do
169
- transmitter.send_message!(payload,routing_key)
170
- expect(topic_exchange).to have_received(:publish).with(payload.to_json,routing_key: routing_key, persistent: true)
171
- end
172
-
173
317
  it "logs the start and end of the transmission" do
174
318
  transmitter.send_message!(payload,routing_key)
175
- expect(logger).to have_received(:info).with(/START Transmitting Message on #{routing_key} ->/)
176
- expect(logger).to have_received(:info).with(/END Transmitting Message on #{routing_key} ->/)
319
+ expect(logger).to have_received(:info).with(/START Transmitting Message on id\[[\w\-\d]+\] #{routing_key} ->/)
320
+ expect(logger).to have_received(:info).with(/END Transmitting Message on id\[[\w\-\d]+\] #{routing_key} ->/)
177
321
  end
178
322
 
179
323
  it "closes the channel connector" do
180
324
  transmitter.send_message!(payload,routing_key)
181
325
  expect(channel_connector).to have_received(:connection_close)
182
326
  end
327
+
328
+ context "with only basic required arguments" do
329
+
330
+ before do
331
+ transmitter.send_message!(payload,routing_key)
332
+ end
333
+
334
+ it_behaves_like "it sends standard attributes and the payload to the exchange" do
335
+ let(:exchange) { topic_exchange }
336
+ end
337
+ end
338
+ context "with everything overridden" do
339
+ before do
340
+ transmitter.send_message!(
341
+ payload,
342
+ routing_key,
343
+ message_id: "snowflake id that is likely a bad idea, but if you must",
344
+ type: "Customer",
345
+ headers: {
346
+ "custom" => "value",
347
+ "other_custom" => "other_value",
348
+ }
349
+ )
350
+ end
351
+
352
+ it_behaves_like "it sends standard and overridden data to the exchange" do
353
+ let(:exchange) { topic_exchange }
354
+ end
355
+ end
183
356
  end
184
357
 
185
358
  describe "#send_delayed_message!" do
@@ -189,29 +362,44 @@ describe Pwwka::Transmitter do
189
362
  allow(channel_connector).to receive(:create_delayed_queue)
190
363
  end
191
364
 
192
- it "returns true" do
193
- expect(transmitter.send_delayed_message!(payload,routing_key)).to eq(true)
194
- end
195
-
196
365
  it "creates the delayed queue" do
197
366
  transmitter.send_delayed_message!(payload,routing_key)
198
367
  expect(channel_connector).to have_received(:create_delayed_queue)
199
368
  end
200
369
 
201
- it "publishes the message to the delayed exchange" do
202
- delay_by = 12345
203
- transmitter.send_delayed_message!(payload,routing_key, delay_by)
204
- expect(delayed_exchange).to have_received(:publish).with(payload.to_json,routing_key: routing_key, expiration: delay_by, persistent: true)
205
- end
370
+ context "with only basic required arguments" do
371
+ before do
372
+ transmitter.send_delayed_message!(payload,routing_key,5_000)
373
+ end
206
374
 
207
- it "logs the start and end of the transmission" do
208
- transmitter.send_delayed_message!(payload,routing_key)
209
- expect(logger).to have_received(:info).with(/START Transmitting Delayed Message on #{routing_key} ->/)
210
- expect(logger).to have_received(:info).with(/END Transmitting Delayed Message on #{routing_key} ->/)
375
+ it_behaves_like "it sends standard attributes and the payload to the exchange" do
376
+ let(:exchange) { delayed_exchange }
377
+ end
378
+
379
+ it "passes an expiration value" do
380
+ expect(delayed_exchange).to have_received(:publish).with(
381
+ payload.to_json,
382
+ hash_including(expiration: 5_000))
383
+ end
211
384
  end
212
- it "closes the channel connector" do
213
- transmitter.send_delayed_message!(payload,routing_key)
214
- expect(channel_connector).to have_received(:connection_close)
385
+
386
+ context "with everything overridden" do
387
+ before do
388
+ transmitter.send_delayed_message!(
389
+ payload,
390
+ routing_key,
391
+ message_id: "snowflake id that is likely a bad idea, but if you must",
392
+ type: "Customer",
393
+ headers: {
394
+ "custom" => "value",
395
+ "other_custom" => "other_value",
396
+ }
397
+ )
398
+ end
399
+
400
+ it_behaves_like "it sends standard and overridden data to the exchange" do
401
+ let(:exchange) { delayed_exchange }
402
+ end
215
403
  end
216
404
  end
217
405
  context "delayed queue not configured" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwwka
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0.RC1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stitch Fix Engineering
@@ -15,7 +15,7 @@ authors:
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
- date: 2017-04-21 00:00:00.000000000 Z
18
+ date: 2017-06-08 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: bunny
@@ -157,6 +157,20 @@ dependencies:
157
157
  - - ">="
158
158
  - !ruby/object:Gem::Version
159
159
  version: '0'
160
+ - !ruby/object:Gem::Dependency
161
+ name: rainbow
162
+ requirement: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ type: :development
168
+ prerelease: false
169
+ version_requirements: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
160
174
  description: |-
161
175
  The purpose of this gem is to normalise the sending and
162
176
  receiving of messages between Rails apps using the shared RabbitMQ
@@ -195,6 +209,7 @@ files:
195
209
  - lib/pwwka/handling.rb
196
210
  - lib/pwwka/logging.rb
197
211
  - lib/pwwka/message_queuer.rb
212
+ - lib/pwwka/publish_options.rb
198
213
  - lib/pwwka/queue_resque_job_handler.rb
199
214
  - lib/pwwka/receiver.rb
200
215
  - lib/pwwka/send_message_async_job.rb
@@ -217,9 +232,11 @@ files:
217
232
  - spec/spec_helper.rb
218
233
  - spec/support/test_configuration.rb
219
234
  - spec/unit/channel_connector_spec.rb
235
+ - spec/unit/configuration_spec.rb
220
236
  - spec/unit/logging_spec.rb
221
237
  - spec/unit/message_queuer_spec.rb
222
238
  - spec/unit/queue_resque_job_handler_spec.rb
239
+ - spec/unit/send_message_async_job_spec.rb
223
240
  - spec/unit/test_handler_message_spec.rb
224
241
  - spec/unit/transmitter_spec.rb
225
242
  homepage: https://github.com/stitchfix/pwwka
@@ -237,12 +254,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
237
254
  version: '0'
238
255
  required_rubygems_version: !ruby/object:Gem::Requirement
239
256
  requirements:
240
- - - ">="
257
+ - - ">"
241
258
  - !ruby/object:Gem::Version
242
- version: '0'
259
+ version: 1.3.1
243
260
  requirements: []
244
261
  rubyforge_project:
245
- rubygems_version: 2.5.1
262
+ rubygems_version: 2.6.11
246
263
  signing_key:
247
264
  specification_version: 4
248
265
  summary: Send and receive messages via RabbitMQ
@@ -261,8 +278,10 @@ test_files:
261
278
  - spec/spec_helper.rb
262
279
  - spec/support/test_configuration.rb
263
280
  - spec/unit/channel_connector_spec.rb
281
+ - spec/unit/configuration_spec.rb
264
282
  - spec/unit/logging_spec.rb
265
283
  - spec/unit/message_queuer_spec.rb
266
284
  - spec/unit/queue_resque_job_handler_spec.rb
285
+ - spec/unit/send_message_async_job_spec.rb
267
286
  - spec/unit/test_handler_message_spec.rb
268
287
  - spec/unit/transmitter_spec.rb