pwwka 0.23.0.RC2 → 0.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +26 -26
- data/.ruby-version +1 -1
- data/CODEOWNERS +1 -0
- data/README.md +13 -8
- data/lib/pwwka.rb +0 -1
- data/lib/pwwka/transmitter.rb +38 -12
- data/lib/pwwka/version.rb +2 -1
- data/owners.json +1 -1
- data/spec/integration/send_and_receive_spec.rb +25 -5
- data/spec/unit/transmitter_spec.rb +44 -8
- metadata +6 -9
- data/lib/pwwka/persistent_transmitter.rb +0 -59
- data/spec/unit/persistent_transmitter_spec.rb +0 -153
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 267500c638d786f3a583dd73661818565dcd40b778ee96a788fe9604d3e898ed
|
4
|
+
data.tar.gz: 6e64b966616a2650f7c78702981cc209e571625c554b2da2140d1aa8610fdee6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 997e9a6c703e482ec343e024f72d2ac0b12602b7b7578ee9b66675216a8fa18e6f30bddea80ecc9b1b63f8173f5a73296dc9f847017e7bb3e554216f416c42c3
|
7
|
+
data.tar.gz: 67a92f5b32a3be3d311dad301a15d929b002d5ca347aa1b792c07ce1bf67264929e7f6ed218476a2a4dcf1dc8818b16a3ff6903112de075e02609bab4a370659
|
data/.circleci/config.yml
CHANGED
@@ -5,7 +5,7 @@ version: 2
|
|
5
5
|
jobs:
|
6
6
|
release:
|
7
7
|
docker:
|
8
|
-
- image: circleci/ruby:2.
|
8
|
+
- image: circleci/ruby:2.7.1
|
9
9
|
steps:
|
10
10
|
- checkout
|
11
11
|
- run: bundle config stitchfix01.jfrog.io $ARTIFACTORY_USER:$ARTIFACTORY_TOKEN
|
@@ -17,9 +17,9 @@ jobs:
|
|
17
17
|
- run:
|
18
18
|
name: Build/release gem to artifactory
|
19
19
|
command: bundle exec rake push_artifactory
|
20
|
-
ruby-2.
|
20
|
+
ruby-2.7.1-rails-6.0:
|
21
21
|
docker:
|
22
|
-
- image: circleci/ruby:2.
|
22
|
+
- image: circleci/ruby:2.7.1
|
23
23
|
environment:
|
24
24
|
BUNDLE_GEMFILE: Gemfile.rails-6.0
|
25
25
|
- image: redis:2.8.12
|
@@ -37,13 +37,13 @@ jobs:
|
|
37
37
|
fi
|
38
38
|
- run:
|
39
39
|
name: Notify Pager Duty
|
40
|
-
command: bundle exec y-notify "#eng-
|
40
|
+
command: bundle exec y-notify "#eng-messaging-ops"
|
41
41
|
when: on_fail
|
42
42
|
- store_test_results:
|
43
43
|
path: "/tmp/test-results"
|
44
|
-
ruby-2.
|
44
|
+
ruby-2.6.6-rails-6.0:
|
45
45
|
docker:
|
46
|
-
- image: circleci/ruby:2.
|
46
|
+
- image: circleci/ruby:2.6.6
|
47
47
|
environment:
|
48
48
|
BUNDLE_GEMFILE: Gemfile.rails-6.0
|
49
49
|
- image: redis:2.8.12
|
@@ -61,13 +61,13 @@ jobs:
|
|
61
61
|
fi
|
62
62
|
- run:
|
63
63
|
name: Notify Pager Duty
|
64
|
-
command: bundle exec y-notify "#eng-
|
64
|
+
command: bundle exec y-notify "#eng-messaging-ops"
|
65
65
|
when: on_fail
|
66
66
|
- store_test_results:
|
67
67
|
path: "/tmp/test-results"
|
68
|
-
ruby-2.
|
68
|
+
ruby-2.7.1-rails-5.2:
|
69
69
|
docker:
|
70
|
-
- image: circleci/ruby:2.
|
70
|
+
- image: circleci/ruby:2.7.1
|
71
71
|
environment:
|
72
72
|
BUNDLE_GEMFILE: Gemfile.rails-5.2
|
73
73
|
- image: redis:2.8.12
|
@@ -85,13 +85,13 @@ jobs:
|
|
85
85
|
fi
|
86
86
|
- run:
|
87
87
|
name: Notify Pager Duty
|
88
|
-
command: bundle exec y-notify "#eng-
|
88
|
+
command: bundle exec y-notify "#eng-messaging-ops"
|
89
89
|
when: on_fail
|
90
90
|
- store_test_results:
|
91
91
|
path: "/tmp/test-results"
|
92
|
-
ruby-2.
|
92
|
+
ruby-2.6.6-rails-5.2:
|
93
93
|
docker:
|
94
|
-
- image: circleci/ruby:2.
|
94
|
+
- image: circleci/ruby:2.6.6
|
95
95
|
environment:
|
96
96
|
BUNDLE_GEMFILE: Gemfile.rails-5.2
|
97
97
|
- image: redis:2.8.12
|
@@ -109,7 +109,7 @@ jobs:
|
|
109
109
|
fi
|
110
110
|
- run:
|
111
111
|
name: Notify Pager Duty
|
112
|
-
command: bundle exec y-notify "#eng-
|
112
|
+
command: bundle exec y-notify "#eng-messaging-ops"
|
113
113
|
when: on_fail
|
114
114
|
- store_test_results:
|
115
115
|
path: "/tmp/test-results"
|
@@ -120,31 +120,31 @@ workflows:
|
|
120
120
|
- release:
|
121
121
|
context: org-global
|
122
122
|
requires:
|
123
|
-
- ruby-2.
|
124
|
-
- ruby-2.
|
125
|
-
- ruby-2.
|
126
|
-
- ruby-2.
|
123
|
+
- ruby-2.7.1-rails-6.0
|
124
|
+
- ruby-2.6.6-rails-6.0
|
125
|
+
- ruby-2.7.1-rails-5.2
|
126
|
+
- ruby-2.6.6-rails-5.2
|
127
127
|
filters:
|
128
128
|
tags:
|
129
|
-
only: /^[0-9]+\.[0-9]+\.[0-9]+(\.?RC[-\.]?\d*)?$/
|
129
|
+
only: /^[0-9]+\.[0-9]+\.[0-9]+(\.?(RC|rc)[-\.]?\d*)?$/
|
130
130
|
branches:
|
131
131
|
ignore: /.*/
|
132
|
-
- ruby-2.
|
132
|
+
- ruby-2.7.1-rails-6.0:
|
133
133
|
context: org-global
|
134
134
|
filters:
|
135
135
|
tags:
|
136
136
|
only: &1 /.*/
|
137
|
-
- ruby-2.
|
137
|
+
- ruby-2.6.6-rails-6.0:
|
138
138
|
context: org-global
|
139
139
|
filters:
|
140
140
|
tags:
|
141
141
|
only: *1
|
142
|
-
- ruby-2.
|
142
|
+
- ruby-2.7.1-rails-5.2:
|
143
143
|
context: org-global
|
144
144
|
filters:
|
145
145
|
tags:
|
146
146
|
only: *1
|
147
|
-
- ruby-2.
|
147
|
+
- ruby-2.6.6-rails-5.2:
|
148
148
|
context: org-global
|
149
149
|
filters:
|
150
150
|
tags:
|
@@ -158,11 +158,11 @@ workflows:
|
|
158
158
|
only:
|
159
159
|
- master
|
160
160
|
jobs:
|
161
|
-
- ruby-2.
|
161
|
+
- ruby-2.7.1-rails-6.0:
|
162
162
|
context: org-global
|
163
|
-
- ruby-2.
|
163
|
+
- ruby-2.6.6-rails-6.0:
|
164
164
|
context: org-global
|
165
|
-
- ruby-2.
|
165
|
+
- ruby-2.7.1-rails-5.2:
|
166
166
|
context: org-global
|
167
|
-
- ruby-2.
|
167
|
+
- ruby-2.6.6-rails-5.2:
|
168
168
|
context: org-global
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.7.1
|
data/CODEOWNERS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* @stitchfix/eng-messaging
|
data/README.md
CHANGED
@@ -148,8 +148,8 @@ Pwwka::Transmitter.send_message!(payload, routing_key, on_error: :ignore)
|
|
148
148
|
|
149
149
|
#### Delayed Messages
|
150
150
|
|
151
|
-
You might want to delay sending a message (for example, if you have just created a database
|
152
|
-
record and a race condition keeps catching you out). In that case you can use delayed message
|
151
|
+
You might want to delay sending a message (for example, if you have just created a database
|
152
|
+
record and a race condition keeps catching you out). In that case you can use delayed message
|
153
153
|
options:
|
154
154
|
|
155
155
|
```ruby
|
@@ -176,7 +176,12 @@ Pwwka.configure do |config|
|
|
176
176
|
end
|
177
177
|
```
|
178
178
|
|
179
|
-
Regardless of which processor you use, the name of the queue created is `pwwka_send_message_async`.
|
179
|
+
Regardless of which processor you use, the name of the queue created is `pwwka_send_message_async`. You will need to start a worker process to work the queue. For a `Procfile` setup, with Resque as the processor, that could look something like this:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
pwwka_send_message_async_worker: rake resque:work QUEUE=pwwka_send_message_async
|
183
|
+
```
|
184
|
+
|
180
185
|
|
181
186
|
You can also configure Pwwka to use your own custom job using the `async_job_klass` configuration option. An example might be:
|
182
187
|
```
|
@@ -191,7 +196,7 @@ If you are using Resque and `Resque::Plugins::ExponentialBackoff` is available,
|
|
191
196
|
|
192
197
|
#### Message Queuer
|
193
198
|
|
194
|
-
You can queue up messages and send them in a batch. This is most useful when multiple messages
|
199
|
+
You can queue up messages and send them in a batch. This is most useful when multiple messages
|
195
200
|
need to sent from within a transaction block.
|
196
201
|
|
197
202
|
For example:
|
@@ -255,7 +260,7 @@ Here is an example:
|
|
255
260
|
|
256
261
|
```ruby
|
257
262
|
class ClientIndexMessageHandler
|
258
|
-
|
263
|
+
|
259
264
|
def self.handle!(delivery_info, properties, payload)
|
260
265
|
handler.do_a_thing(payload)
|
261
266
|
end
|
@@ -430,7 +435,7 @@ If you use [Resque][resque], and you wish to handle messages in a resque job, yo
|
|
430
435
|
|
431
436
|
Note that you must provide `@queue` in your job. `QueueResqueJobHandler` doesn't support setting a custom queue at enqueue-time (PRs welcome :).
|
432
437
|
|
433
|
-
Note that if you were using this library before version 0.12.0, your job would only be given the payload. If you change your job to accept exatly three arguments, you will be given the payload, routing key, and message properties. If any of those arguments are optional, you will need to set `PWWKA_QUEUE_EXTENDED_INFO` to `"true"` to force pwwka to pass those along. Without it, your job only gets the payload to avoid breaking legacy consumers.
|
438
|
+
Note that if you were using this library before version 0.12.0, your job would only be given the payload. If you change your job to accept exatly three arguments, you will be given the payload, routing key, and message properties. If any of those arguments are optional, you will need to set `PWWKA_QUEUE_EXTENDED_INFO` to `"true"` to force pwwka to pass those along. Without it, your job only gets the payload to avoid breaking legacy consumers.
|
434
439
|
|
435
440
|
3. Profit!
|
436
441
|
|
@@ -454,9 +459,9 @@ describe "my integration test" do
|
|
454
459
|
@test_handler.test_setup
|
455
460
|
end
|
456
461
|
|
457
|
-
after(:all) do
|
462
|
+
after(:all) do
|
458
463
|
# this clears out any messages, so you have a clean test environment next time
|
459
|
-
@test_handler.test_teardown
|
464
|
+
@test_handler.test_teardown
|
460
465
|
end
|
461
466
|
|
462
467
|
it "uses the message bus" do
|
data/lib/pwwka.rb
CHANGED
@@ -27,7 +27,6 @@ require 'pwwka/channel_connector'
|
|
27
27
|
require 'pwwka/handling'
|
28
28
|
require 'pwwka/receiver'
|
29
29
|
require 'pwwka/transmitter'
|
30
|
-
require 'pwwka/persistent_transmitter'
|
31
30
|
require 'pwwka/message_queuer'
|
32
31
|
require 'pwwka/error_handlers'
|
33
32
|
require 'pwwka/configuration'
|
data/lib/pwwka/transmitter.rb
CHANGED
@@ -23,13 +23,20 @@ module Pwwka
|
|
23
23
|
|
24
24
|
DEFAULT_DELAY_BY_MS = 5000
|
25
25
|
|
26
|
+
attr_reader :caller_manages_connector
|
26
27
|
attr_reader :channel_connector
|
27
28
|
|
28
|
-
def initialize
|
29
|
-
|
29
|
+
def initialize(channel_connector: nil)
|
30
|
+
if channel_connector
|
31
|
+
@caller_manages_connector = true
|
32
|
+
@channel_connector = channel_connector
|
33
|
+
else
|
34
|
+
@caller_manages_connector = false
|
35
|
+
@channel_connector = ChannelConnector.new(connection_name: "p: #{Pwwka.configuration.app_id} #{Pwwka.configuration.process_name}".strip)
|
36
|
+
end
|
30
37
|
end
|
31
38
|
|
32
|
-
# Send an important message that must go through. This method allows any raised exception
|
39
|
+
# Send an important message that must go through. This method allows any raised exception
|
33
40
|
# to pass through.
|
34
41
|
#
|
35
42
|
# payload:: Hash of what you'd like to include in your message
|
@@ -54,11 +61,13 @@ module Pwwka
|
|
54
61
|
delay_by: nil,
|
55
62
|
type: nil,
|
56
63
|
message_id: :auto_generate,
|
57
|
-
headers: nil
|
64
|
+
headers: nil,
|
65
|
+
channel_connector: nil
|
66
|
+
)
|
58
67
|
if delayed
|
59
|
-
new.send_delayed_message!(*[payload, routing_key, delay_by].compact, type: type, headers: headers, message_id: message_id)
|
68
|
+
new(channel_connector: channel_connector).send_delayed_message!(*[payload, routing_key, delay_by].compact, type: type, headers: headers, message_id: message_id)
|
60
69
|
else
|
61
|
-
new.send_message!(payload, routing_key, type: type, headers: headers, message_id: message_id)
|
70
|
+
new(channel_connector: channel_connector).send_message!(payload, routing_key, type: type, headers: headers, message_id: message_id)
|
62
71
|
end
|
63
72
|
logf "AFTER Transmitting Message on %{routing_key} -> %{payload}",routing_key: routing_key, payload: payload
|
64
73
|
true
|
@@ -95,11 +104,24 @@ module Pwwka
|
|
95
104
|
job = Pwwka.configuration.async_job_klass
|
96
105
|
|
97
106
|
if background_job_processor == :resque
|
98
|
-
|
99
|
-
|
100
|
-
|
107
|
+
resque_args = [job, payload, routing_key]
|
108
|
+
|
109
|
+
unless type == nil && message_id == :auto_generate && headers == nil
|
110
|
+
# NOTE: (jdlubrano)
|
111
|
+
# Why can't we pass these options all of the time? Well, if a user
|
112
|
+
# of pwwka has configured their own async_job_klass that only has an
|
113
|
+
# arity of 2 (i.e. payload and routing key), then passing these options
|
114
|
+
# as an additional argument would break the user's application. In
|
115
|
+
# order to maintain compatibility with preceding versions of Pwwka,
|
116
|
+
# we need to ensure that the same arguments passed into this method
|
117
|
+
# result in compatible calls to enqueue any Resque jobs.
|
118
|
+
resque_args << { type: type, message_id: message_id, headers: headers }
|
119
|
+
end
|
120
|
+
|
121
|
+
if delay_by_ms.zero?
|
122
|
+
Resque.enqueue(*resque_args)
|
101
123
|
else
|
102
|
-
Resque.enqueue_in(delay_by_ms/1000,
|
124
|
+
Resque.enqueue_in(delay_by_ms/1000, *resque_args)
|
103
125
|
end
|
104
126
|
elsif background_job_processor == :sidekiq
|
105
127
|
options = { delay_by_ms: delay_by_ms, type: type, message_id: message_id, headers: headers }
|
@@ -134,7 +156,9 @@ module Pwwka
|
|
134
156
|
logf "END Transmitting Message on id[%{id}] %{routing_key} -> %{payload}", id: publish_options.message_id, routing_key: routing_key, payload: payload
|
135
157
|
true
|
136
158
|
ensure
|
137
|
-
|
159
|
+
unless caller_manages_connector
|
160
|
+
channel_connector.connection_close
|
161
|
+
end
|
138
162
|
end
|
139
163
|
|
140
164
|
|
@@ -154,7 +178,9 @@ module Pwwka
|
|
154
178
|
logf "END Transmitting Delayed Message on id[%{id}] %{routing_key} -> %{payload}", id: publish_options.message_id, routing_key: routing_key, payload: payload
|
155
179
|
true
|
156
180
|
ensure
|
157
|
-
|
181
|
+
unless caller_manages_connector
|
182
|
+
channel_connector.connection_close
|
183
|
+
end
|
158
184
|
end
|
159
185
|
|
160
186
|
end
|
data/lib/pwwka/version.rb
CHANGED
data/owners.json
CHANGED
@@ -11,6 +11,9 @@ describe "sending and receiving messages", :integration do
|
|
11
11
|
include IntegrationTestHelpers
|
12
12
|
include Resqutils::Spec::ResqueHelpers
|
13
13
|
|
14
|
+
let(:async_resque_queue) { 'pwwka_send_message_async' }
|
15
|
+
let(:delayed_resque_queue) { :delayed }
|
16
|
+
|
14
17
|
before do
|
15
18
|
ENV["JOB_KLASS"] = MyTestJob.name
|
16
19
|
ENV["PWWKA_QUEUE_EXTENDED_INFO"] = "true"
|
@@ -30,7 +33,8 @@ describe "sending and receiving messages", :integration do
|
|
30
33
|
FooReceiver.reset!
|
31
34
|
MultiRoutingReceived.reset!
|
32
35
|
OtherFooReceiver.reset!
|
33
|
-
clear_queue(
|
36
|
+
clear_queue(async_resque_queue)
|
37
|
+
clear_queue(delayed_resque_queue)
|
34
38
|
clear_queue(MyTestJob)
|
35
39
|
end
|
36
40
|
|
@@ -144,7 +148,7 @@ describe "sending and receiving messages", :integration do
|
|
144
148
|
|
145
149
|
expect(AllReceiver.messages_received.size).to eq(0)
|
146
150
|
|
147
|
-
process_resque_job(Pwwka::SendMessageAsyncJob
|
151
|
+
process_resque_job(Pwwka::SendMessageAsyncJob, async_resque_queue)
|
148
152
|
|
149
153
|
allow_receivers_to_process_queues
|
150
154
|
|
@@ -166,7 +170,7 @@ describe "sending and receiving messages", :integration do
|
|
166
170
|
|
167
171
|
expect(AllReceiver.messages_received.size).to eq(0)
|
168
172
|
|
169
|
-
process_resque_job(Pwwka::SendMessageAsyncJob
|
173
|
+
process_resque_job(Pwwka::SendMessageAsyncJob, async_resque_queue)
|
170
174
|
|
171
175
|
allow_receivers_to_process_queues
|
172
176
|
|
@@ -186,12 +190,28 @@ describe "sending and receiving messages", :integration do
|
|
186
190
|
|
187
191
|
allow(Pwwka).to receive(:configuration).and_return(configuration)
|
188
192
|
|
189
|
-
allow(Resque).to receive(:
|
193
|
+
allow(Resque).to receive(:enqueue)
|
190
194
|
|
191
195
|
Pwwka::Transmitter.send_message_async({ sample: "payload", has: { deeply: true, nested: 4 }},
|
192
196
|
"pwwka.testing.bar")
|
193
197
|
|
194
|
-
expect(Resque).to have_received(:
|
198
|
+
expect(Resque).to have_received(:enqueue).with(async_job_klass, anything, anything)
|
199
|
+
end
|
200
|
+
|
201
|
+
it "can queue a job to send a message with a delay" do
|
202
|
+
Pwwka::Transmitter.send_message_async({ sample: "payload" },
|
203
|
+
"pwwka.testing.bar",
|
204
|
+
delay_by_ms: 1)
|
205
|
+
|
206
|
+
allow_receivers_to_process_queues # not expecting anything to be processed
|
207
|
+
|
208
|
+
expect(AllReceiver.messages_received.size).to eq(0)
|
209
|
+
|
210
|
+
process_resque_job(Pwwka::SendMessageAsyncJob, delayed_resque_queue)
|
211
|
+
|
212
|
+
allow_receivers_to_process_queues
|
213
|
+
|
214
|
+
expect(AllReceiver.messages_received.size).to eq(1)
|
195
215
|
end
|
196
216
|
end
|
197
217
|
|
@@ -312,19 +312,19 @@ describe Pwwka::Transmitter do
|
|
312
312
|
end
|
313
313
|
context "on_error: :resque" do
|
314
314
|
it "queues a Resque job" do
|
315
|
-
allow(Resque).to receive(:
|
315
|
+
allow(Resque).to receive(:enqueue)
|
316
316
|
described_class.send_message!(payload,routing_key, on_error: :resque)
|
317
|
-
expect(Resque).to have_received(:
|
317
|
+
expect(Resque).to have_received(:enqueue).with(Pwwka::SendMessageAsyncJob,payload,routing_key)
|
318
318
|
end
|
319
319
|
context "when there is a problem queueing the resque job" do
|
320
320
|
it "raises the original exception job" do
|
321
|
-
allow(Resque).to receive(:
|
321
|
+
allow(Resque).to receive(:enqueue).and_raise("NOPE")
|
322
322
|
expect {
|
323
323
|
described_class.send_message!(payload,routing_key, on_error: :resque)
|
324
324
|
}.to raise_error(/OH NOES/)
|
325
325
|
end
|
326
326
|
it "logs the Resque error as a warning" do
|
327
|
-
allow(Resque).to receive(:
|
327
|
+
allow(Resque).to receive(:enqueue).and_raise("NOPE")
|
328
328
|
begin
|
329
329
|
described_class.send_message!(payload,routing_key, on_error: :resque)
|
330
330
|
rescue => ex
|
@@ -338,18 +338,18 @@ describe Pwwka::Transmitter do
|
|
338
338
|
context "when configured background_job_processor is Resque" do
|
339
339
|
context "when the job is queued successfully" do
|
340
340
|
before do
|
341
|
-
allow(Resque).to receive(:
|
341
|
+
allow(Resque).to receive(:enqueue)
|
342
342
|
end
|
343
343
|
|
344
344
|
it "queues a Resque job" do
|
345
345
|
described_class.send_message!(payload, routing_key, on_error: :retry_async)
|
346
|
-
expect(Resque).to have_received(:
|
346
|
+
expect(Resque).to have_received(:enqueue).with(Pwwka::SendMessageAsyncJob, payload, routing_key)
|
347
347
|
end
|
348
348
|
end
|
349
349
|
|
350
350
|
context "when there is a problem queueing the Resque job" do
|
351
351
|
before do
|
352
|
-
allow(Resque).to receive(:
|
352
|
+
allow(Resque).to receive(:enqueue).and_raise("NOPE")
|
353
353
|
end
|
354
354
|
|
355
355
|
it "raises the original exception job" do
|
@@ -576,5 +576,41 @@ describe Pwwka::Transmitter do
|
|
576
576
|
end
|
577
577
|
end
|
578
578
|
end
|
579
|
-
end
|
580
579
|
|
580
|
+
context "application manages connection" do
|
581
|
+
let(:managed_connector) { instance_double(Pwwka::ChannelConnector,
|
582
|
+
topic_exchange: double(:topic_exchange).as_null_object,
|
583
|
+
delayed_exchange: double(:delayed_exchange).as_null_object
|
584
|
+
).as_null_object }
|
585
|
+
describe ".send_message!" do
|
586
|
+
|
587
|
+
context "send immediate" do
|
588
|
+
it "doesn't open a new connection" do
|
589
|
+
described_class.send_message!(payload, routing_key, delayed: false, channel_connector: managed_connector)
|
590
|
+
|
591
|
+
expect(Pwwka::ChannelConnector).not_to have_received(:new)
|
592
|
+
end
|
593
|
+
|
594
|
+
it "doesn't close a passed in connection" do
|
595
|
+
described_class.send_message!(payload, routing_key, delayed: false, channel_connector: managed_connector)
|
596
|
+
|
597
|
+
expect(managed_connector).not_to have_received(:connection_close)
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
context "send delayed" do
|
602
|
+
it "doesn't open a new connection" do
|
603
|
+
described_class.send_message!(payload, routing_key, delayed: true, channel_connector: managed_connector)
|
604
|
+
|
605
|
+
expect(Pwwka::ChannelConnector).not_to have_received(:new)
|
606
|
+
end
|
607
|
+
|
608
|
+
it "doesn't close a passed in connection" do
|
609
|
+
described_class.send_message!(payload, routing_key, delayed: true, channel_connector: managed_connector)
|
610
|
+
|
611
|
+
expect(managed_connector).not_to have_received(:connection_close)
|
612
|
+
end
|
613
|
+
end
|
614
|
+
end
|
615
|
+
end
|
616
|
+
end
|
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.23.0
|
4
|
+
version: 0.23.0
|
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:
|
18
|
+
date: 2020-07-01 00:00:00.000000000 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: bunny
|
@@ -235,6 +235,7 @@ files:
|
|
235
235
|
- ".ruby-gemset"
|
236
236
|
- ".ruby-version"
|
237
237
|
- ".travis.yml"
|
238
|
+
- CODEOWNERS
|
238
239
|
- CODE_OF_CONDUCT.md
|
239
240
|
- CONTRIBUTING.md
|
240
241
|
- Gemfile
|
@@ -264,7 +265,6 @@ files:
|
|
264
265
|
- lib/pwwka/handling.rb
|
265
266
|
- lib/pwwka/logging.rb
|
266
267
|
- lib/pwwka/message_queuer.rb
|
267
|
-
- lib/pwwka/persistent_transmitter.rb
|
268
268
|
- lib/pwwka/publish_options.rb
|
269
269
|
- lib/pwwka/queue_resque_job_handler.rb
|
270
270
|
- lib/pwwka/receiver.rb
|
@@ -294,7 +294,6 @@ files:
|
|
294
294
|
- spec/unit/configuration_spec.rb
|
295
295
|
- spec/unit/logging_spec.rb
|
296
296
|
- spec/unit/message_queuer_spec.rb
|
297
|
-
- spec/unit/persistent_transmitter_spec.rb
|
298
297
|
- spec/unit/queue_resque_job_handler_spec.rb
|
299
298
|
- spec/unit/receiver_spec.rb
|
300
299
|
- spec/unit/send_message_async_job_spec.rb
|
@@ -316,12 +315,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
316
315
|
version: '0'
|
317
316
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
318
317
|
requirements:
|
319
|
-
- - "
|
318
|
+
- - ">="
|
320
319
|
- !ruby/object:Gem::Version
|
321
|
-
version:
|
320
|
+
version: '0'
|
322
321
|
requirements: []
|
323
|
-
|
324
|
-
rubygems_version: 2.7.6
|
322
|
+
rubygems_version: 3.1.2
|
325
323
|
signing_key:
|
326
324
|
specification_version: 4
|
327
325
|
summary: Send and receive messages via RabbitMQ
|
@@ -344,7 +342,6 @@ test_files:
|
|
344
342
|
- spec/unit/configuration_spec.rb
|
345
343
|
- spec/unit/logging_spec.rb
|
346
344
|
- spec/unit/message_queuer_spec.rb
|
347
|
-
- spec/unit/persistent_transmitter_spec.rb
|
348
345
|
- spec/unit/queue_resque_job_handler_spec.rb
|
349
346
|
- spec/unit/receiver_spec.rb
|
350
347
|
- spec/unit/send_message_async_job_spec.rb
|
@@ -1,59 +0,0 @@
|
|
1
|
-
require_relative "publish_options"
|
2
|
-
|
3
|
-
begin # optional dependency
|
4
|
-
require 'resque'
|
5
|
-
require 'resque-retry'
|
6
|
-
rescue LoadError
|
7
|
-
end
|
8
|
-
|
9
|
-
module Pwwka
|
10
|
-
# Primary interface for sending messages.
|
11
|
-
#
|
12
|
-
# Example:
|
13
|
-
#
|
14
|
-
# # Send a message, blowing up if there's any problem
|
15
|
-
# Pwwka::PersistentTransmitter.batch do |transmitter|
|
16
|
-
# transmitter.send_message!({ user_id: @user.id }, "users.user.activated")
|
17
|
-
# end
|
18
|
-
|
19
|
-
class PersistentTransmitter
|
20
|
-
|
21
|
-
extend Pwwka::Logging
|
22
|
-
include Pwwka::Logging
|
23
|
-
|
24
|
-
DEFAULT_DELAY_BY_MS = 5000
|
25
|
-
|
26
|
-
attr_reader :channel_connector
|
27
|
-
|
28
|
-
def initialize
|
29
|
-
@channel_connector = ChannelConnector.new(connection_name: "p: #{Pwwka.configuration.app_id} #{Pwwka.configuration.process_name}".strip)
|
30
|
-
end
|
31
|
-
|
32
|
-
def send_message!(payload, routing_key, type: nil, headers: nil, message_id: :auto_generate)
|
33
|
-
publish_options = Pwwka::PublishOptions.new(
|
34
|
-
routing_key: routing_key,
|
35
|
-
message_id: message_id,
|
36
|
-
type: type,
|
37
|
-
headers: headers
|
38
|
-
)
|
39
|
-
logf "START Transmitting Message on id[%{id}] %{routing_key} -> %{payload}", id: publish_options.message_id, routing_key: routing_key, payload: payload
|
40
|
-
channel_connector.topic_exchange.publish(payload.to_json, publish_options.to_h)
|
41
|
-
# if it gets this far it has succeeded
|
42
|
-
logf "END Transmitting Message on id[%{id}] %{routing_key} -> %{payload}", id: publish_options.message_id, routing_key: routing_key, payload: payload
|
43
|
-
true
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
class << self
|
48
|
-
private :new
|
49
|
-
|
50
|
-
def batch
|
51
|
-
transmitter = new
|
52
|
-
yield(transmitter)
|
53
|
-
ensure
|
54
|
-
transmitter.channel_connector.connection_close
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
@@ -1,153 +0,0 @@
|
|
1
|
-
require 'spec_helper.rb'
|
2
|
-
|
3
|
-
describe Pwwka::PersistentTransmitter do
|
4
|
-
let(:topic_exchange) { double("topic exchange") }
|
5
|
-
let(:delayed_exchange) { double("delayed exchange") }
|
6
|
-
let(:channel_connector) { instance_double(Pwwka::ChannelConnector, topic_exchange: topic_exchange, delayed_exchange: delayed_exchange) }
|
7
|
-
let(:logger) { double(Logger) }
|
8
|
-
let(:payload) {
|
9
|
-
{
|
10
|
-
foo: { bar: "blah" },
|
11
|
-
crud: 12,
|
12
|
-
}
|
13
|
-
}
|
14
|
-
let(:routing_key) { "sf.foo.bar" }
|
15
|
-
|
16
|
-
|
17
|
-
before do
|
18
|
-
@original_logger = Pwwka.configuration.logger
|
19
|
-
Pwwka.configuration.logger = logger
|
20
|
-
allow(logger).to receive(:info)
|
21
|
-
allow(logger).to receive(:warn)
|
22
|
-
allow(logger).to receive(:error)
|
23
|
-
allow(Pwwka::ChannelConnector).to receive(:new).with(connection_name: "p: MyAwesomeApp my_awesome_process").and_return(channel_connector)
|
24
|
-
allow(channel_connector).to receive(:connection_close)
|
25
|
-
allow(topic_exchange).to receive(:publish)
|
26
|
-
allow(delayed_exchange).to receive(:publish)
|
27
|
-
end
|
28
|
-
|
29
|
-
after do
|
30
|
-
Pwwka.configuration.logger = @original_logger
|
31
|
-
end
|
32
|
-
|
33
|
-
|
34
|
-
shared_examples "it sends standard and overridden data to the exchange" do
|
35
|
-
it "publishes to the topic exchange" do
|
36
|
-
expect(exchange).to have_received(:publish).with(payload.to_json, kind_of(Hash))
|
37
|
-
end
|
38
|
-
|
39
|
-
it "passes the routing key" do
|
40
|
-
expect(exchange).to have_received(:publish).with(
|
41
|
-
payload.to_json,
|
42
|
-
hash_including(routing_key: routing_key))
|
43
|
-
end
|
44
|
-
|
45
|
-
it "sets the type" do
|
46
|
-
expect(exchange).to have_received(:publish).with(
|
47
|
-
payload.to_json,
|
48
|
-
hash_including(type: "Customer"))
|
49
|
-
end
|
50
|
-
|
51
|
-
it "sets the headers" do
|
52
|
-
expect(exchange).to have_received(:publish).with(
|
53
|
-
payload.to_json,
|
54
|
-
hash_including(headers: { "custom" => "value", "other_custom" => "other_value" }))
|
55
|
-
end
|
56
|
-
|
57
|
-
it "uses the overridden message id" do
|
58
|
-
expect(exchange).to have_received(:publish).with(
|
59
|
-
payload.to_json,
|
60
|
-
hash_including(message_id: "snowflake id that is likely a bad idea, but if you must"))
|
61
|
-
end
|
62
|
-
|
63
|
-
it "sets the app id to what's configured" do
|
64
|
-
expect(exchange).to have_received(:publish).with(
|
65
|
-
payload.to_json,
|
66
|
-
hash_including(app_id: "MyAwesomeApp"))
|
67
|
-
end
|
68
|
-
|
69
|
-
it "sets the content type to JSON with a version" do
|
70
|
-
expect(exchange).to have_received(:publish).with(
|
71
|
-
payload.to_json,
|
72
|
-
hash_including(content_type: "application/json; version=1"))
|
73
|
-
end
|
74
|
-
|
75
|
-
it "sets persistent true" do
|
76
|
-
expect(exchange).to have_received(:publish).with(
|
77
|
-
payload.to_json,
|
78
|
-
hash_including(persistent: true))
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
|
83
|
-
context "no new instance creation" do
|
84
|
-
it "doesn't allow creation of new instances unless inside the batch method" do
|
85
|
-
expect{ Pwwka::PersistentTransmitter.new }.to raise_error
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
describe "#batch" do
|
90
|
-
context "Logging" do
|
91
|
-
it "logs the start and end of the transmission" do
|
92
|
-
described_class.batch do |transmitter|
|
93
|
-
transmitter.send_message!(payload,routing_key)
|
94
|
-
end
|
95
|
-
expect(logger).to have_received(:info).with(/START Transmitting Message on id\[[\w\-\d]+\] #{routing_key} ->/)
|
96
|
-
expect(logger).to have_received(:info).with(/END Transmitting Message on id\[[\w\-\d]+\] #{routing_key} ->/)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
it "closes the channel connector" do
|
101
|
-
described_class.batch do |transmitter|
|
102
|
-
transmitter.send_message!(payload,routing_key)
|
103
|
-
end
|
104
|
-
expect(channel_connector).to have_received(:connection_close)
|
105
|
-
end
|
106
|
-
|
107
|
-
it "only uses one connection" do
|
108
|
-
described_class.batch do |transmitter|
|
109
|
-
10.times do
|
110
|
-
transmitter.send_message!(payload,routing_key)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
expect(channel_connector).to have_received(:connection_close).once
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
context 'when an error is raised' do
|
118
|
-
|
119
|
-
let(:error) { 'oh no' }
|
120
|
-
|
121
|
-
before do
|
122
|
-
allow(topic_exchange).to receive(:publish).and_raise(error)
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'should raise the error and still close the channel_connector' do
|
126
|
-
expect { described_class.batch do |transmitter|
|
127
|
-
transmitter.send_message!(payload,routing_key)
|
128
|
-
end } .to raise_error(error)
|
129
|
-
expect(channel_connector).to have_received(:connection_close)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
context "with everything overridden" do
|
134
|
-
before do
|
135
|
-
described_class.batch do |transmitter|
|
136
|
-
transmitter.send_message!(
|
137
|
-
payload,
|
138
|
-
routing_key,
|
139
|
-
message_id: "snowflake id that is likely a bad idea, but if you must",
|
140
|
-
type: "Customer",
|
141
|
-
headers: {
|
142
|
-
"custom" => "value",
|
143
|
-
"other_custom" => "other_value",
|
144
|
-
})
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
it_behaves_like "it sends standard and overridden data to the exchange" do
|
149
|
-
let(:exchange) { topic_exchange }
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
end
|