pwwka 0.16.1 → 0.17.0

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
- SHA1:
3
- metadata.gz: d33c45520c16c18b56efbfcefd70a49252e3bd00
4
- data.tar.gz: dac6fe4120e1dc388e49adb123330b9f8545cbcb
2
+ SHA256:
3
+ metadata.gz: e9a3dc1069389bc19bef4c75f90900dd4580a739fb96865edbaa06a829700ad8
4
+ data.tar.gz: 4463babd7364e8084ebe87bdb57cccc1fdcc1262a435d3cf9540bdd77ef6a58b
5
5
  SHA512:
6
- metadata.gz: 906bc065b933a8bc13525b454f8d6e1259414272cfabd8585305d4bc793f25e01598d4413064e10742fa4a31e7dacfa963418e58975b77763940fba5d5d84519
7
- data.tar.gz: e88311d37274c9fb54c14f516be1f2a333c302380aeb838785c544addc3e0e4543b4cec3749fb4eccd8441b20fc93480cb6696383855231d9e158d27f423670d
6
+ metadata.gz: ddbba8fb8943d7ab931abd2fd38bd8840c30acd43404c51772e4aa0fe3d416afb197aa61dbd2d047d5701669630ec39bbcd41780fcbf5a070c301cbdd2c828ea
7
+ data.tar.gz: 1cba823b9fdccb53cfcbd2bc90e0a909fb428cfd9a763f02696466ccd187f10c8df4d9c6de1c3e2d31e6a7aa3a73e3cfe6b80c17099c25ed43c986b9a6d47aa6
data/.circleci/config.yml CHANGED
@@ -3,105 +3,95 @@
3
3
  ---
4
4
  version: 2
5
5
  jobs:
6
- ruby-2.5.0-rails-5.1:
6
+ ruby-2.5.1-rails-5.2:
7
7
  docker:
8
- - image: circleci/ruby:2.5.0
8
+ - image: circleci/ruby:2.5.1
9
9
  environment:
10
- BUNDLE_GEMFILE: Gemfile.rails-5.1
10
+ BUNDLE_GEMFILE: Gemfile.rails-5.2
11
+ - image: redis:2.8.12
12
+ - image: rabbitmq:3.5.6
11
13
  working_directory: "~/pwwka"
12
14
  steps:
13
15
  - checkout
14
- - run: bundle install
16
+ - run: bundle install --full-index
15
17
  - run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
16
18
  --format=doc
17
19
  - run:
18
- name: Notify Pager Duty
19
- command: bundle exec y-notify eng-platform
20
- when: on_fail
21
- - store_test_results:
22
- path: "/tmp/test-results"
23
- ruby-2.4.3-rails-5.1:
24
- docker:
25
- - image: circleci/ruby:2.4.3
26
- environment:
27
- BUNDLE_GEMFILE: Gemfile.rails-5.1
28
- working_directory: "~/pwwka"
29
- steps:
30
- - checkout
31
- - run: bundle install
32
- - run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
33
- --format=doc
20
+ name: Run Additional CI Steps
21
+ command: if [ -e bin/additional-ci-steps ]; then bin/additional-ci-steps;
22
+ fi
34
23
  - run:
35
24
  name: Notify Pager Duty
36
- command: bundle exec y-notify eng-platform
25
+ command: 'bundle exec y-notify #eng-platform'
37
26
  when: on_fail
38
27
  - store_test_results:
39
28
  path: "/tmp/test-results"
40
- ruby-2.5.0-rails-5.0:
29
+ ruby-2.4.4-rails-5.2:
41
30
  docker:
42
- - image: circleci/ruby:2.5.0
31
+ - image: circleci/ruby:2.4.4
43
32
  environment:
44
- BUNDLE_GEMFILE: Gemfile.rails-5.0
33
+ BUNDLE_GEMFILE: Gemfile.rails-5.2
34
+ - image: redis:2.8.12
35
+ - image: rabbitmq:3.5.6
45
36
  working_directory: "~/pwwka"
46
37
  steps:
47
38
  - checkout
48
- - run: bundle install
39
+ - run: bundle install --full-index
49
40
  - run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
50
41
  --format=doc
51
42
  - run:
52
- name: Notify Pager Duty
53
- command: bundle exec y-notify eng-platform
54
- when: on_fail
55
- - store_test_results:
56
- path: "/tmp/test-results"
57
- ruby-2.4.3-rails-5.0:
58
- docker:
59
- - image: circleci/ruby:2.4.3
60
- environment:
61
- BUNDLE_GEMFILE: Gemfile.rails-5.0
62
- working_directory: "~/pwwka"
63
- steps:
64
- - checkout
65
- - run: bundle install
66
- - run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
67
- --format=doc
43
+ name: Run Additional CI Steps
44
+ command: if [ -e bin/additional-ci-steps ]; then bin/additional-ci-steps;
45
+ fi
68
46
  - run:
69
47
  name: Notify Pager Duty
70
- command: bundle exec y-notify eng-platform
48
+ command: 'bundle exec y-notify #eng-platform'
71
49
  when: on_fail
72
50
  - store_test_results:
73
51
  path: "/tmp/test-results"
74
- ruby-2.5.0-rails-4.2:
52
+ ruby-2.5.1-rails-5.1:
75
53
  docker:
76
- - image: circleci/ruby:2.5.0
54
+ - image: circleci/ruby:2.5.1
77
55
  environment:
78
- BUNDLE_GEMFILE: Gemfile.rails-4.2
56
+ BUNDLE_GEMFILE: Gemfile.rails-5.1
57
+ - image: redis:2.8.12
58
+ - image: rabbitmq:3.5.6
79
59
  working_directory: "~/pwwka"
80
60
  steps:
81
61
  - checkout
82
- - run: bundle install
62
+ - run: bundle install --full-index
83
63
  - run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
84
64
  --format=doc
65
+ - run:
66
+ name: Run Additional CI Steps
67
+ command: if [ -e bin/additional-ci-steps ]; then bin/additional-ci-steps;
68
+ fi
85
69
  - run:
86
70
  name: Notify Pager Duty
87
- command: bundle exec y-notify eng-platform
71
+ command: 'bundle exec y-notify #eng-platform'
88
72
  when: on_fail
89
73
  - store_test_results:
90
74
  path: "/tmp/test-results"
91
- ruby-2.4.3-rails-4.2:
75
+ ruby-2.4.4-rails-5.1:
92
76
  docker:
93
- - image: circleci/ruby:2.4.3
77
+ - image: circleci/ruby:2.4.4
94
78
  environment:
95
- BUNDLE_GEMFILE: Gemfile.rails-4.2
79
+ BUNDLE_GEMFILE: Gemfile.rails-5.1
80
+ - image: redis:2.8.12
81
+ - image: rabbitmq:3.5.6
96
82
  working_directory: "~/pwwka"
97
83
  steps:
98
84
  - checkout
99
- - run: bundle install
85
+ - run: bundle install --full-index
100
86
  - run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
101
87
  --format=doc
88
+ - run:
89
+ name: Run Additional CI Steps
90
+ command: if [ -e bin/additional-ci-steps ]; then bin/additional-ci-steps;
91
+ fi
102
92
  - run:
103
93
  name: Notify Pager Duty
104
- command: bundle exec y-notify eng-platform
94
+ command: 'bundle exec y-notify #eng-platform'
105
95
  when: on_fail
106
96
  - store_test_results:
107
97
  path: "/tmp/test-results"
@@ -109,17 +99,13 @@ workflows:
109
99
  version: 2
110
100
  on-commit:
111
101
  jobs:
112
- - ruby-2.5.0-rails-5.1:
102
+ - ruby-2.5.1-rails-5.2:
113
103
  context: org-global
114
- - ruby-2.4.3-rails-5.1:
104
+ - ruby-2.4.4-rails-5.2:
115
105
  context: org-global
116
- - ruby-2.5.0-rails-5.0:
106
+ - ruby-2.5.1-rails-5.1:
117
107
  context: org-global
118
- - ruby-2.4.3-rails-5.0:
119
- context: org-global
120
- - ruby-2.5.0-rails-4.2:
121
- context: org-global
122
- - ruby-2.4.3-rails-4.2:
108
+ - ruby-2.4.4-rails-5.1:
123
109
  context: org-global
124
110
  scheduled:
125
111
  triggers:
@@ -130,15 +116,11 @@ workflows:
130
116
  only:
131
117
  - master
132
118
  jobs:
133
- - ruby-2.5.0-rails-5.1:
134
- context: org-global
135
- - ruby-2.4.3-rails-5.1:
136
- context: org-global
137
- - ruby-2.5.0-rails-5.0:
119
+ - ruby-2.5.1-rails-5.2:
138
120
  context: org-global
139
- - ruby-2.4.3-rails-5.0:
121
+ - ruby-2.4.4-rails-5.2:
140
122
  context: org-global
141
- - ruby-2.5.0-rails-4.2:
123
+ - ruby-2.5.1-rails-5.1:
142
124
  context: org-global
143
- - ruby-2.4.3-rails-4.2:
125
+ - ruby-2.4.4-rails-5.1:
144
126
  context: org-global
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.4.1
1
+ 2.5.1
data/Gemfile.rails-5.2 ADDED
@@ -0,0 +1,8 @@
1
+ # DO NOT MODIFY - this is managed by Git Reduce in goro
2
+ #
3
+ source 'https://gem.fury.io/me/'
4
+ source 'https://www.rubygems.org'
5
+
6
+ gemspec
7
+
8
+ gem 'activesupport', '~> 5.2.0'
data/README.md CHANGED
@@ -19,7 +19,7 @@ In your `Gemfile`:
19
19
  gem 'pwwka'
20
20
  ```
21
21
 
22
- (of course, you can always run `gem install pwwka` to install it without Bundler)
22
+ or `gem install pwwka` if you aren't using a `Gemfile`.
23
23
 
24
24
  To run applications locally, you will need Rabbit installed. The [installation guide](https://www.rabbitmq.com/download.html) is a great
25
25
  place to start. This repo includes a `docker-compose.yml` file which will run Rabbit inside a Docker container. It's used by the tests,
@@ -260,6 +260,26 @@ private
260
260
  end
261
261
  ```
262
262
 
263
+ #### Payload Parsing
264
+
265
+ By default, payloads are assumed to be JSON and are parsed before being sent to your `handle!` method (meaning: that method is
266
+ given a `HashWithIndifferentAccess` of your payload).
267
+
268
+ If you don't want this, for example if you are using XML or some other format, you can turn this feature off in your
269
+ initializers:
270
+
271
+ ```ruby
272
+ # config/initialisers/pwwka.rb
273
+ require 'pwwka'
274
+
275
+ Pwwka.configure do |config|
276
+ config.receive_raw_payload = true
277
+ # any other settings you might have
278
+ end
279
+ ```
280
+
281
+ In this case, your handler gets whatever Bunny returns, so you are on your own.
282
+
263
283
  #### Errors From Your Handler
264
284
 
265
285
  By default, handlers will log and ignore garbled payloads (basically payloads that fail to be parsed as JSON). All other errors
data/build-matrix.json CHANGED
@@ -1,4 +1,8 @@
1
1
  {
2
2
  "build_matrix": {
3
+ "additional_docker_images": [
4
+ "redis:2.8.12",
5
+ "rabbitmq:3.5.6"
6
+ ]
3
7
  }
4
8
  }
data/lib/pwwka.rb CHANGED
@@ -11,7 +11,7 @@ module Pwwka
11
11
 
12
12
  def environment
13
13
  ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
14
- end
14
+ end
15
15
  end
16
16
 
17
17
  end
@@ -31,6 +31,7 @@ module Pwwka
31
31
  @keep_alive_on_handler_klass_exceptions = false
32
32
  @async_job_klass = Pwwka::SendMessageAsyncJob
33
33
  @default_prefetch = nil
34
+ @receive_raw_payload = false
34
35
  end
35
36
 
36
37
  def keep_alive_on_handler_klass_exceptions?
@@ -107,5 +108,34 @@ module Pwwka
107
108
  def default_prefetch=(val)
108
109
  @default_prefetch = val.nil? ? val : val.to_i
109
110
  end
111
+
112
+ # Set this if you don't want the payload parsed. This can be useful is you are expecting a lot of malformed
113
+ # JSON or if you aren't using JSON at all. Note that currently, setting this to true will prevent all
114
+ # payloads from being logged
115
+ def receive_raw_payload=(val)
116
+ @receive_raw_payload = val
117
+ @payload_parser = nil
118
+ end
119
+
120
+ # Returns a proc that, when called with the payload, parses it according to the configuration.
121
+ #
122
+ # By default, this will assume the payload is JSON, parse it, and return a HashWithIndifferentAccess.
123
+ def payload_parser
124
+ @payload_parser ||= if @receive_raw_payload
125
+ ->(payload) { payload }
126
+ else
127
+ ->(payload) {
128
+ ActiveSupport::HashWithIndifferentAccess.new(JSON.parse(payload))
129
+ }
130
+ end
131
+ end
132
+
133
+ # True if we should omit the payload from the log
134
+ #
135
+ # ::level_of_message_with_payload the level of the message about to be logged
136
+ def omit_payload_from_log?(level_of_message_with_payload)
137
+ return true if @receive_raw_payload
138
+ Pwwka::Logging::LEVELS[Pwwka.configuration.payload_logging.to_sym] > Pwwka::Logging::LEVELS[level_of_message_with_payload.to_sym]
139
+ end
110
140
  end
111
141
  end
data/lib/pwwka/logging.rb CHANGED
@@ -18,11 +18,11 @@ module Pwwka
18
18
  def logf(format,params)
19
19
  level = params.delete(:at) || Pwwka.configuration.log_level
20
20
  params[:payload] = params["payload"] if params["payload"]
21
- params[:payload] = "[omitted]" if params[:payload] && LEVELS[Pwwka.configuration.payload_logging.to_sym] > LEVELS[level.to_sym]
21
+ if Pwwka.configuration.omit_payload_from_log?(level)
22
+ params[:payload] = "[omitted]" if params[:payload]
23
+ end
22
24
  message = format % params
23
25
  logger.send(level,message)
24
26
  end
25
-
26
-
27
27
  end
28
28
  end
@@ -17,14 +17,18 @@ module Pwwka
17
17
  @topic_exchange = @channel_connector.topic_exchange
18
18
  end
19
19
 
20
- def self.subscribe(handler_klass, queue_name, routing_key: "#.#", block: true, prefetch: Pwwka.configuration.default_prefetch)
20
+ def self.subscribe(handler_klass, queue_name,
21
+ routing_key: "#.#",
22
+ block: true,
23
+ prefetch: Pwwka.configuration.default_prefetch,
24
+ payload_parser: Pwwka.configuration.payload_parser)
21
25
  raise "#{handler_klass.name} must respond to `handle!`" unless handler_klass.respond_to?(:handle!)
22
26
  receiver = new(queue_name, routing_key, prefetch: prefetch)
23
27
  begin
24
28
  info "Receiving on #{queue_name}"
25
29
  receiver.topic_queue.subscribe(manual_ack: true, block: block) do |delivery_info, properties, payload|
26
30
  begin
27
- payload = ActiveSupport::HashWithIndifferentAccess.new(JSON.parse(payload))
31
+ payload = payload_parser.(payload)
28
32
  handler_klass.handle!(delivery_info, properties, payload)
29
33
  receiver.ack(delivery_info.delivery_tag)
30
34
  logf "Processed Message on %{queue_name} -> %{payload}, %{routing_key}", queue_name: queue_name, payload: payload, routing_key: delivery_info.routing_key
@@ -78,6 +82,5 @@ module Pwwka
78
82
  topic_exchange.delete
79
83
  channel_connector.connection_close
80
84
  end
81
-
82
85
  end
83
86
  end
data/lib/pwwka/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Pwwka
2
- VERSION = '0.16.1'
2
+ VERSION = '0.17.0'
3
3
  end
@@ -157,6 +157,36 @@ describe Pwwka::Receiver, :legacy do
157
157
 
158
158
  end
159
159
 
160
+ describe "#prepare_payload" do
161
+
162
+ context "when payload is JSON" do
163
+
164
+ it "returns a hash with indifferent access" do
165
+ payload = { something: "interesting" }.to_json
166
+
167
+ result = @receiver.prepare_payload(payload)
168
+
169
+ expect(result).to be_a(Hash)
170
+ expect(result).to have_key("something")
171
+ expect(result).to have_key(:something)
172
+ end
173
+
174
+ end
175
+
176
+ context "when the paylad is not JSON" do
177
+
178
+ it "defers the handling to a handler down the chain" do
179
+ payload = "<>"
180
+
181
+ result = @receiver.prepare_payload(payload)
182
+
183
+ expect(result).to eq(payload)
184
+ end
185
+
186
+ end
187
+
188
+ end
189
+
160
190
  end
161
191
 
162
192
  end
@@ -8,8 +8,13 @@ class TestConfiguration
8
8
  def initialize(docker_compose_file)
9
9
  yaml = YAML.load_file(docker_compose_file)
10
10
 
11
- @resque_redis_port = (ENV["PWWKA_RESQUE_REDIS_PORT"] || yaml["services"]["resque"]["ports"].first.split(/:/)[0]).to_i
12
- @rabbit_port = (ENV["PWWKA_RABBIT_PORT"] || yaml["services"]["rabbit"]["ports"].first.split(/:/)[0]).to_i
11
+ if ENV["CI"] == 'true'
12
+ @resque_redis_port = 6379
13
+ @rabbit_port = 5672
14
+ else
15
+ @resque_redis_port = (ENV["PWWKA_RESQUE_REDIS_PORT"] || yaml["services"]["resque"]["ports"].first.split(/:/)[0]).to_i
16
+ @rabbit_port = (ENV["PWWKA_RABBIT_PORT"] || yaml["services"]["rabbit"]["ports"].first.split(/:/)[0]).to_i
17
+ end
13
18
  end
14
19
 
15
20
  def check_services
@@ -20,6 +20,28 @@ describe Pwwka::Configuration do
20
20
  expect(configuration.topic_exchange_name).to eq("pwwka.topics.production")
21
21
  end
22
22
  end
23
+
24
+ describe "#payload_parser" do
25
+ it "parses JSON by default" do
26
+ payload = { foo: { bar: 42 } }
27
+ expect(described_class.new.payload_parser.(payload.to_json)).to eq({ "foo" => { "bar" => 42 } })
28
+ end
29
+
30
+ it "setting receive_raw_payload to true pases through the raw payload" do
31
+ configuration.receive_raw_payload = true
32
+ payload = "<h1>This is some <blink>XML</blink></h1>"
33
+ expect(configuration.payload_parser.(payload)).to eq(payload)
34
+ end
35
+
36
+ it "setting receive_raw_payload to true then false restores the JSON-parsing" do
37
+ configuration.receive_raw_payload = true
38
+ payload = { foo: { bar: 42 } }
39
+ expect(configuration.payload_parser.(payload.to_json)).to eq(payload.to_json)
40
+ configuration.receive_raw_payload = false
41
+ expect(configuration.payload_parser.(payload.to_json)).to eq({ "foo" => { "bar" => 42 } })
42
+ end
43
+ end
44
+
23
45
  describe "#delayed_exchange_name" do
24
46
  it "is based on the Pwwka.environment" do
25
47
  expect(configuration.delayed_exchange_name).to eq("pwwka.delayed.production")
@@ -68,6 +68,7 @@ describe Pwwka::Logging do
68
68
  ].each do |name|
69
69
  it "will strip payload (given as a #{name.class}) if configured" do
70
70
  Pwwka.configuration.payload_logging = :error
71
+ Pwwka.configuration.receive_raw_payload = false
71
72
  ForLogging.logf("This is the payload: %{payload}", name => { foo: "bar" })
72
73
  ForLogging.logf("This is also the payload: %{payload}", name => { foo: "bar" }, at: :error)
73
74
  expect(logger).to have_received(:info).with("This is the payload: [omitted]")
@@ -76,6 +77,16 @@ describe Pwwka::Logging do
76
77
 
77
78
  it "will strip payload (given as a #{name.class}) of errors, too" do
78
79
  Pwwka.configuration.payload_logging = :fatal
80
+ Pwwka.configuration.receive_raw_payload = false
81
+ ForLogging.logf("This is the payload: %{payload}", name => { foo: "bar" })
82
+ ForLogging.logf("This is also the payload: %{payload}", name => { foo: "bar" }, at: :error)
83
+ expect(logger).to have_received(:info).with("This is the payload: [omitted]")
84
+ expect(logger).to have_received(:error).with("This is also the payload: [omitted]")
85
+ end
86
+
87
+ it "will strip payload (given as a #{name.class}) if we AREN'T parsing payloads" do
88
+ Pwwka.configuration.payload_logging = :info
89
+ Pwwka.configuration.receive_raw_payload = true
79
90
  ForLogging.logf("This is the payload: %{payload}", name => { foo: "bar" })
80
91
  ForLogging.logf("This is also the payload: %{payload}", name => { foo: "bar" }, at: :error)
81
92
  expect(logger).to have_received(:info).with("This is the payload: [omitted]")
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.16.1
4
+ version: 0.17.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: 2018-01-11 00:00:00.000000000 Z
18
+ date: 2018-08-30 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: bunny
@@ -213,6 +213,7 @@ files:
213
213
  - Gemfile.rails-4.2
214
214
  - Gemfile.rails-5.0
215
215
  - Gemfile.rails-5.1
216
+ - Gemfile.rails-5.2
216
217
  - LICENSE
217
218
  - README.md
218
219
  - Rakefile
@@ -286,7 +287,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
286
287
  version: '0'
287
288
  requirements: []
288
289
  rubyforge_project:
289
- rubygems_version: 2.6.14
290
+ rubygems_version: 2.7.6
290
291
  signing_key:
291
292
  specification_version: 4
292
293
  summary: Send and receive messages via RabbitMQ