pheme 3.1.3 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43b82532ae9c2d1e266860d9553d1b9e6c47fba937de781431f50f87921fa8b6
4
- data.tar.gz: 14cd293a8fdbabab40154bf10a6e1cee36d4c609749a7ca4f0ee44d4df1780ee
3
+ metadata.gz: 5ead3f77e54732d0ec25696ec63984cca421f38a96f398c36c886f575ef05270
4
+ data.tar.gz: 62af0c6807a8fcec1f00f8a1e2217b056bd3307d99a5a191f35512acac352afa
5
5
  SHA512:
6
- metadata.gz: 1b1da30552e2ba5fb12a898c1af86a0f48654a6c3a3bca615ae00d7a762bd4a7db6f660bcfd99149d00ec0ebeaccdd4b115c06ce5233b382706045aa5d470d9e
7
- data.tar.gz: d86bfe1b06f0d5040e4461a24bfc5cfe2e264c8014563b26c8e0e49912834f3db03286f49dd042f65b6f13a38547c8866406ff04a8f82814bfb644ef5b24c288
6
+ metadata.gz: 2570dcdd9712acc03aa8ae0b25d6744e6aa2c2594aa2566cae59fb9e9b35c3143cf879a83fa4968026b1e47ee4d6a245f1122c673b354167e1421b928168a0d7
7
+ data.tar.gz: 828eca04402d568ed88fe5deb4b89320feea9961089a6218f8efc8d0ac989bf82ab30b89cea2fb711919cf1ace55d9fe91b67aee43eabc3f9eab3272991b3413
@@ -1,3 +1,5 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
1
3
  inherit_gem:
2
4
  ws-style:
3
5
  - default.yml
@@ -34,6 +36,9 @@ Metrics/LineLength:
34
36
  Metrics/MethodLength:
35
37
  Max: 22
36
38
 
39
+ RSpec/FilePath:
40
+ Enabled: false
41
+
37
42
  # Offense count: 1
38
43
  # Configuration parameters: MinBodyLength.
39
44
  Style/GuardClause:
@@ -0,0 +1,53 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2019-05-29 15:19:13 -0400 using RuboCop version 0.70.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 12
10
+ # Configuration parameters: Prefixes.
11
+ # Prefixes: when, with, without
12
+ RSpec/ContextWording:
13
+ Exclude:
14
+ - 'spec/configuration_spec.rb'
15
+ - 'spec/message_handler_spec.rb'
16
+ - 'spec/queue_poller_spec.rb'
17
+ - 'spec/topic_publisher_spec.rb'
18
+
19
+ # Offense count: 5
20
+ # Configuration parameters: CustomTransform, IgnoreMethods.
21
+ RSpec/FilePath:
22
+ Exclude:
23
+ - 'spec/configuration_spec.rb'
24
+ - 'spec/logger_spec.rb'
25
+ - 'spec/message_handler_spec.rb'
26
+ - 'spec/message_type/aws_event_spec.rb'
27
+ - 'spec/message_type/sns_message_spec.rb'
28
+ - 'spec/queue_poller_spec.rb'
29
+ - 'spec/rollbar_spec.rb'
30
+ - 'spec/topic_publisher_spec.rb'
31
+ - 'spec/version_spec.rb'
32
+
33
+ # Offense count: 14
34
+ # Configuration parameters: EnforcedStyle.
35
+ # SupportedStyles: have_received, receive
36
+ RSpec/MessageSpies:
37
+ Exclude:
38
+ - 'spec/message_handler_spec.rb'
39
+ - 'spec/queue_poller_spec.rb'
40
+ - 'spec/rollbar_spec.rb'
41
+ - 'spec/topic_publisher_spec.rb'
42
+
43
+ # Offense count: 39
44
+ # Configuration parameters: IgnoreSharedExamples.
45
+ RSpec/NamedSubject:
46
+ Exclude:
47
+ - 'spec/configuration_spec.rb'
48
+ - 'spec/logger_spec.rb'
49
+ - 'spec/message_handler_spec.rb'
50
+ - 'spec/message_type/sns_message_spec.rb'
51
+ - 'spec/queue_poller_spec.rb'
52
+ - 'spec/rollbar_spec.rb'
53
+ - 'spec/topic_publisher_spec.rb'
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 3.2.0 - 2019-05-29
8
+ ### Added
9
+ - Support for Pheme::TopicPublisher to publish to an explicit SNS client.
10
+
7
11
  ## 3.1.3 - 2019-02-14
8
12
  ### Fixed
9
13
  - Increase code coverage to 100%.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # pheme [![CircleCI](https://circleci.com/gh/wealthsimple/pheme.svg?style=svg&circle-token=76942be0b1712ac066627be264886ee18039ad11)](https://circleci.com/gh/wealthsimple/pheme) [![Coverage Status](https://coveralls.io/repos/github/wealthsimple/pheme/badge.svg)](https://coveralls.io/github/wealthsimple/pheme?branch=3.1.0-rc)
1
+ # pheme [![CircleCI](https://circleci.com/gh/wealthsimple/pheme.svg?style=svg&circle-token=76942be0b1712ac066627be264886ee18039ad11)](https://circleci.com/gh/wealthsimple/pheme) [![Coverage Status](https://coveralls.io/repos/github/wealthsimple/pheme/badge.svg)](https://coveralls.io/github/wealthsimple/pheme)
2
2
 
3
3
  Ruby SNS publisher + SQS poller & message handler
4
4
 
@@ -34,7 +34,7 @@ module Pheme
34
34
  raise NotImplementedError
35
35
  end
36
36
 
37
- def publish(message)
37
+ def publish(message, sns_client: Pheme.configuration.sns_client)
38
38
  payload = {
39
39
  message: "#{self.class} publishing message to #{topic_arn}",
40
40
  body: message,
@@ -42,7 +42,7 @@ module Pheme
42
42
  topic_arn: topic_arn,
43
43
  }
44
44
  Pheme.logger.info(payload.to_json)
45
- Pheme.configuration.sns_client.publish(topic_arn: topic_arn, message: serialize(message))
45
+ sns_client.publish(topic_arn: topic_arn, message: serialize(message))
46
46
  end
47
47
 
48
48
  def serialize(message)
@@ -1,3 +1,3 @@
1
1
  module Pheme
2
- VERSION = '3.1.3'.freeze
2
+ VERSION = '3.2.0'.freeze
3
3
  end
@@ -3,6 +3,7 @@ describe Pheme do
3
3
  let(:sns_client) { double }
4
4
  let(:sqs_client) { double }
5
5
  let(:custom_logger) { double }
6
+
6
7
  it "sets global configuration" do
7
8
  expect(described_class.configuration.sns_client).to be_nil
8
9
  expect(described_class.configuration.sqs_client).to be_nil
@@ -1,10 +1,10 @@
1
1
  RSpec.describe Pheme do
2
2
  describe '.log' do
3
+ subject { described_class.log(method, text) }
4
+
3
5
  let(:method) { 'info' }
4
6
  let(:text) { 'Some informational message' }
5
7
 
6
- subject { Pheme.log(method, text) }
7
-
8
8
  it { subject }
9
9
  end
10
10
  end
@@ -1,8 +1,10 @@
1
1
  describe Pheme::MessageHandler do
2
- before(:each) { use_default_configuration! }
2
+ subject { ExampleMessageHandler.new(message: message, metadata: { timestamp: timestamp }) }
3
+
4
+ before { use_default_configuration! }
5
+
3
6
  let(:message) { RecursiveOpenStruct.new(status: status) }
4
7
  let(:timestamp) { '2018-04-17T21:45:05.915Z' }
5
- subject { ExampleMessageHandler.new(message: message, metadata: { timestamp: timestamp }) }
6
8
 
7
9
  describe "#handle" do
8
10
  context 'complete message' do
@@ -15,6 +15,7 @@ describe Pheme::MessageType::AwsEvent do
15
15
 
16
16
  context "with JSON message" do
17
17
  let!(:records) { [{ 'eventVersion' => '2.0' }] }
18
+
18
19
  its('first.eventVersion') { is_expected.to eq('2.0') }
19
20
  end
20
21
  end
@@ -15,7 +15,7 @@ describe Pheme::MessageType::SnsMessage do
15
15
  poller
16
16
  end
17
17
 
18
- before(:each) do
18
+ before do
19
19
  use_default_configuration!
20
20
  allow(Aws::SQS::QueuePoller).to receive(:new) { poller }
21
21
  end
@@ -24,7 +24,7 @@ describe Pheme::MessageType::SnsMessage do
24
24
  context "with JSON message" do
25
25
  let!(:message) { OpenStruct.new({ body: '{"Message":"{\"test\":\"test\"}"}' }) }
26
26
 
27
- it 'should parse the message correctly' do
27
+ it 'parses the message correctly' do
28
28
  expect(subject.parse_body(message).test).to eq("test")
29
29
  end
30
30
  end
@@ -2,6 +2,16 @@ describe Pheme::QueuePoller do
2
2
  let(:queue_url) { "https://sqs.us-east-1.amazonaws.com/whatever" }
3
3
  let(:timestamp) { '2018-04-17T21:45:05.915Z' }
4
4
 
5
+ let!(:queue_message) do
6
+ OpenStruct.new(
7
+ body: { Message: message }.to_json,
8
+ message_id: message_id,
9
+ )
10
+ end
11
+ let(:message) { nil }
12
+ let(:message_id) { SecureRandom.uuid }
13
+ let(:poller) { ExampleQueuePoller.new(queue_url: queue_url, format: format) }
14
+
5
15
  context 'base poller' do
6
16
  subject { described_class.new(queue_url: 'https://sqs.aws.com').handle(nil, nil) }
7
17
 
@@ -24,7 +34,7 @@ describe Pheme::QueuePoller do
24
34
  end
25
35
 
26
36
  context "when initialized with max_messages" do
27
- it "should set max_messages" do
37
+ it "sets max_messages" do
28
38
  expect(ExampleQueuePoller.new(queue_url: "queue_url", max_messages: 5).max_messages).to eq(5)
29
39
  end
30
40
  end
@@ -32,13 +42,15 @@ describe Pheme::QueuePoller do
32
42
  context "when initialized with sqs_client" do
33
43
  let(:sqs_client) { Object.new }
34
44
 
35
- it "should set custom sqs_client" do
45
+ it "sets custom sqs_client" do
36
46
  expect(Aws::SQS::QueuePoller).to receive(:new).with("queue_url", client: sqs_client)
37
47
  ExampleQueuePoller.new(queue_url: "queue_url", sqs_client: sqs_client)
38
48
  end
39
49
  end
40
50
 
41
51
  context 'received too many messages' do
52
+ subject { described_class.new(queue_url: 'http://sqs.aws.com', max_messages: max_messages) }
53
+
42
54
  let(:aws_poller) { instance_double('Aws::SQS::QueuePoller') }
43
55
  let(:max_messages) { 50 }
44
56
 
@@ -47,30 +59,19 @@ describe Pheme::QueuePoller do
47
59
  allow(aws_poller).to receive(:before_request).and_yield(OpenStruct.new(received_message_count: max_messages))
48
60
  end
49
61
 
50
- subject { described_class.new(queue_url: 'http://sqs.aws.com', max_messages: max_messages) }
51
-
52
62
  it 'throws error' do
53
63
  expect { subject }.to raise_error(UncaughtThrowError, /stop_polling/)
54
64
  end
55
65
  end
56
66
  end
57
67
 
58
- let(:poller) { ExampleQueuePoller.new(queue_url: queue_url, format: format) }
59
- let(:message_id) { SecureRandom.uuid }
60
- let(:message) { nil }
61
- let!(:queue_message) do
62
- OpenStruct.new(
63
- body: { Message: message }.to_json,
64
- message_id: message_id,
65
- )
66
- end
67
-
68
68
  describe "#parse_body" do
69
69
  subject { poller.parse_body(queue_message) }
70
70
 
71
71
  context "message is JSON string" do
72
72
  let(:format) { :json }
73
73
  let!(:message) { { test: 'test' }.to_json }
74
+
74
75
  its([:test]) { is_expected.to eq('test') }
75
76
  end
76
77
 
@@ -98,7 +99,7 @@ describe Pheme::QueuePoller do
98
99
  let(:format) { :invalid_format }
99
100
  let(:message) { 'unkonwn' }
100
101
 
101
- it "should raise error" do
102
+ it "raises error" do
102
103
  expect { subject }.to raise_error(ArgumentError)
103
104
  end
104
105
  end
@@ -128,7 +129,7 @@ describe Pheme::QueuePoller do
128
129
  end
129
130
 
130
131
  describe "#poll" do
131
- before(:each) do
132
+ before do
132
133
  module ActiveRecord
133
134
  class Base
134
135
  def self.connection_pool; end
@@ -137,8 +138,10 @@ describe Pheme::QueuePoller do
137
138
  end
138
139
 
139
140
  context "with connection pool block" do
140
- let(:mock_connection_pool) { double }
141
141
  subject { ExampleQueuePoller.new(queue_url: queue_url, connection_pool_block: true) }
142
+
143
+ let(:mock_connection_pool) { double }
144
+
142
145
  let(:message) { { status: 'complete' } }
143
146
  let(:notification) { { 'MessageId' => SecureRandom.uuid, 'Message' => message.to_json, 'Type' => 'Notification', 'Timestamp' => timestamp } }
144
147
  let!(:queue_message) do
@@ -148,7 +151,7 @@ describe Pheme::QueuePoller do
148
151
  )
149
152
  end
150
153
 
151
- before(:each) do
154
+ before do
152
155
  allow(ActiveRecord::Base).to receive(:connection_pool) { mock_connection_pool }
153
156
  allow(mock_connection_pool).to receive(:with_connection).and_yield
154
157
  allow(subject.queue_poller).to receive(:poll).and_yield(queue_message)
@@ -163,6 +166,7 @@ describe Pheme::QueuePoller do
163
166
 
164
167
  context "without connection pool block" do
165
168
  subject { ExampleQueuePoller.new(queue_url: queue_url) }
169
+
166
170
  let(:message) { { status: 'complete' } }
167
171
  let(:notification) { { 'MessageId' => SecureRandom.uuid, 'Message' => message.to_json, 'Type' => 'Notification', 'Timestamp' => timestamp } }
168
172
  let!(:queue_message) do
@@ -172,7 +176,7 @@ describe Pheme::QueuePoller do
172
176
  )
173
177
  end
174
178
 
175
- before(:each) do
179
+ before do
176
180
  allow(subject.queue_poller).to receive(:poll).and_yield(queue_message)
177
181
  allow(subject.queue_poller).to receive(:delete_message).with(queue_message)
178
182
  end
@@ -185,6 +189,7 @@ describe Pheme::QueuePoller do
185
189
 
186
190
  context "when a valid message is yielded" do
187
191
  subject { ExampleQueuePoller.new(queue_url: queue_url) }
192
+
188
193
  let(:message) { { id: "id-123", status: "complete" } }
189
194
  let(:notification) do
190
195
  {
@@ -201,7 +206,7 @@ describe Pheme::QueuePoller do
201
206
  )
202
207
  end
203
208
 
204
- before(:each) do
209
+ before do
205
210
  allow(subject.queue_poller).to receive(:poll).and_yield(queue_message)
206
211
  allow(subject.queue_poller).to receive(:delete_message).with(queue_message)
207
212
  end
@@ -219,6 +224,7 @@ describe Pheme::QueuePoller do
219
224
 
220
225
  context "when an invalid message is yielded" do
221
226
  subject { ExampleQueuePoller.new(queue_url: queue_url) }
227
+
222
228
  let(:message) { { id: "id-123", status: "unknown-abc" } }
223
229
  let(:notification) do
224
230
  {
@@ -235,7 +241,7 @@ describe Pheme::QueuePoller do
235
241
  )
236
242
  end
237
243
 
238
- before(:each) do
244
+ before do
239
245
  allow(subject.queue_poller).to receive(:poll).and_yield(queue_message)
240
246
  allow(subject.queue_poller).to receive(:delete).with(queue_message)
241
247
  allow(Pheme.logger).to receive(:error)
@@ -257,11 +263,13 @@ describe Pheme::QueuePoller do
257
263
 
258
264
  context "AWS-event message" do
259
265
  subject { ExampleAwsEventQueuePoller.new(queue_url: queue_url) }
266
+
260
267
  let(:queue_message) { OpenStruct.new(body: { 'Records' => records }.to_json) }
261
268
  let(:records) do
262
269
  [{ 'eventVersion' => '2.0', 'eventSource': 'aws:s3' }]
263
270
  end
264
- before(:each) do
271
+
272
+ before do
265
273
  allow(subject.queue_poller).to receive(:poll).and_yield(queue_message)
266
274
  allow(subject.queue_poller).to receive(:delete).with(queue_message)
267
275
  end
@@ -272,6 +280,8 @@ describe Pheme::QueuePoller do
272
280
  end
273
281
 
274
282
  context 'SignalException' do
283
+ subject { ExampleQueuePoller.new(queue_url: queue_url) }
284
+
275
285
  let(:message) { { status: 'complete' } }
276
286
  let(:notification) { { 'MessageId' => SecureRandom.uuid, 'Message' => message.to_json, 'Type' => 'Notification', 'Timestamp' => timestamp } }
277
287
  let!(:queue_message) do
@@ -286,8 +296,6 @@ describe Pheme::QueuePoller do
286
296
  allow(subject.queue_poller).to receive(:delete_message).and_raise(SignalException.new('KILL'))
287
297
  end
288
298
 
289
- subject { ExampleQueuePoller.new(queue_url: queue_url) }
290
-
291
299
  it 'stops polling' do
292
300
  expect { subject.poll }.to raise_error(UncaughtThrowError, /stop_polling/)
293
301
  end
@@ -2,18 +2,18 @@ RSpec.describe Pheme do
2
2
  let(:rollbar) { double }
3
3
 
4
4
  describe '.rollbar' do
5
+ subject { described_class.rollbar(exception, message, data) }
6
+
5
7
  let(:exception) { StandardError }
6
8
  let(:message) { 'Unable to poll for messages' }
7
9
  let(:data) { { sqs_url: 'arn::foo::bar' } }
8
10
 
9
11
  before do
10
- Pheme.configure do |config|
12
+ described_class.configure do |config|
11
13
  config.rollbar = rollbar
12
14
  end
13
15
  end
14
16
 
15
- subject { Pheme.rollbar(exception, message, data) }
16
-
17
17
  it 'sends error message to rollbar' do
18
18
  expect(rollbar).to receive(:error).with(exception, message, data)
19
19
  subject
@@ -24,7 +24,7 @@ RSpec.configure do |config|
24
24
 
25
25
  ENV['AWS_REGION'] = 'us-east-1'
26
26
 
27
- config.before(:each) do
27
+ config.before do
28
28
  Pheme.reset_configuration!
29
29
  end
30
30
  end
@@ -1,5 +1,5 @@
1
1
  describe Pheme::TopicPublisher do
2
- before(:each) { use_default_configuration! }
2
+ before { use_default_configuration! }
3
3
 
4
4
  context 'base publisher' do
5
5
  subject { described_class.new(topic_arn: 'arn::foo::bar').publish_events }
@@ -45,11 +45,11 @@ describe Pheme::TopicPublisher do
45
45
  end
46
46
 
47
47
  context 'with string message' do
48
+ subject { described_class.new(topic_arn: topic_arn) }
49
+
48
50
  let(:topic_arn) { "arn:aws:sns:anything" }
49
51
  let(:message) { "don't touch my string" }
50
52
 
51
- subject { Pheme::TopicPublisher.new(topic_arn: topic_arn) }
52
-
53
53
  it "publishes unchanged message" do
54
54
  expect(Pheme.configuration.sns_client).to receive(:publish).with({
55
55
  topic_arn: topic_arn,
@@ -57,14 +57,26 @@ describe Pheme::TopicPublisher do
57
57
  })
58
58
  subject.publish(message)
59
59
  end
60
+
61
+ context 'with an explicit sns client' do
62
+ let(:sns_client) { double }
63
+
64
+ it "publishes unchanged message" do
65
+ expect(sns_client).to receive(:publish).with({
66
+ topic_arn: topic_arn,
67
+ message: message,
68
+ })
69
+ subject.publish(message, sns_client: sns_client)
70
+ end
71
+ end
60
72
  end
61
73
 
62
74
  context 'with message too large' do
75
+ subject { described_class.new(topic_arn: topic_arn).publish(message) }
76
+
63
77
  let(:topic_arn) { "arn:aws:sns:anything" }
64
78
  let(:message) { 'x' * (described_class::MESSAGE_SIZE_LIMIT + 1) }
65
79
 
66
- subject { Pheme::TopicPublisher.new(topic_arn: topic_arn).publish(message) }
67
-
68
80
  let(:compressed_message) do
69
81
  gz = Zlib::GzipWriter.new(StringIO.new)
70
82
  gz << message
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pheme
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.3
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Graham
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-14 00:00:00.000000000 Z
11
+ date: 2019-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -233,6 +233,7 @@ files:
233
233
  - ".gitignore"
234
234
  - ".rspec"
235
235
  - ".rubocop.yml"
236
+ - ".rubocop_todo.yml"
236
237
  - ".ruby-version"
237
238
  - CHANGELOG.md
238
239
  - Gemfile
@@ -285,7 +286,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
285
286
  - !ruby/object:Gem::Version
286
287
  version: '0'
287
288
  requirements: []
288
- rubygems_version: 3.0.1
289
+ rubyforge_project:
290
+ rubygems_version: 2.7.6
289
291
  signing_key:
290
292
  specification_version: 4
291
293
  summary: Ruby SNS publisher + SQS poller & message handler