osbourne 0.1.3 → 0.2.2

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
  SHA256:
3
- metadata.gz: 94cc1a3817307ef19a415268a6a00f8a68240191259e3f26f8a1576741d57378
4
- data.tar.gz: fa5ed1ced8f45f6aa568aaaf66c59bb670e7df2952b55322d989175776c89a42
3
+ metadata.gz: 699bb698e3dae6272c3038bdc052597e0a6677e8f380bc1f64c12ae1c18c63a0
4
+ data.tar.gz: ca0bf27de44bff4a2e96755d0c041a73bbb75bc941c7166c44dfdd144630d3e1
5
5
  SHA512:
6
- metadata.gz: '009ae71c9cd7c3d9e37920fe48ac5a5f66b9fb2f4b96e86ad4681d33358a2b8bad7d4dab5b165ac1313f866d86b449440a14b4095e7d27ae8d0d1303b5e27e42'
7
- data.tar.gz: 825664fc5c5f5fca4b72e7757dbc47e7faae7aa67794260497c52c370ce8b51cdbf86e97e9c86d7cb0617294f16d6848259dc8af40df96263339905641e9610a
6
+ metadata.gz: b464098af275a72c4aa7a2ba600b1bdb709485f4ddaac98462f6513b8c2ae6930c9e8b8bdb478cf58618e39f1d224070957af61fa4633a4032e53ea0e10c3c9e
7
+ data.tar.gz: 32b5e08de9d525e95408525e0d9c0723383a33d3ac8aa688e323af9c49db1bbb15023e2fde9de099750e10a166770d58e3aba8826392702f61355bfd715bb308
data/README.md CHANGED
@@ -1,5 +1,18 @@
1
1
  [![Maintainability](https://api.codeclimate.com/v1/badges/295897ee565c04ad1aa5/maintainability)](https://codeclimate.com/github/stevenallen05/osbourne/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/295897ee565c04ad1aa5/test_coverage)](https://codeclimate.com/github/stevenallen05/osbourne/test_coverage)
2
2
 
3
+ - [Osbourne](#osbourne)
4
+ + [Features](#features)
5
+ * [Installation](#installation)
6
+ + [AWS credentials](#aws-credentials)
7
+ + [Production AWS](#production-aws)
8
+ + [Mock AWS for local devlopment](#mock-aws-for-local-devlopment)
9
+ + [RSpec](#rspec)
10
+ * [Usage](#usage)
11
+ + [Publishing a message](#publishing-a-message)
12
+ + [Generating a worker](#generating-a-worker)
13
+ + [Running workers](#running-workers)
14
+ * [License](#license)
15
+
3
16
  # Osbourne
4
17
 
5
18
  A fan-out pubsub message implementation for Rails 5. Named after the world's most famous plumber, Ozzy Osbourne.
@@ -11,6 +24,7 @@ A fan-out pubsub message implementation for Rails 5. Named after the world's mos
11
24
  * Worker generator via `rails g osbourne:worker worker_name topic`
12
25
  * Auto-provisioning of SQS queues, SNS topics, and subscriptions between them
13
26
  * Built-in support for locking to prevent accidental duplicate message delivery
27
+ * Test helpers
14
28
 
15
29
  Inspired heavily by the excellent Shoryuken & Circuitry gems
16
30
 
@@ -71,6 +85,51 @@ AWS_REGION=us-east-1
71
85
 
72
86
  There must be a region set. Use whichever is appropriate for your situation.
73
87
 
88
+ ### RSpec
89
+
90
+ To turn on test mode, in your spec helper:
91
+
92
+ ```ruby
93
+ require 'osbourne/test'
94
+ ```
95
+
96
+ This will enable test mode for provisioning and publishing. Example:
97
+
98
+ ```ruby
99
+ class TestWorker < Osbourne::WorkerBase
100
+ worker_config topics: %w[test_topic]
101
+
102
+ def process(message)
103
+ # Do stuff here...
104
+ end
105
+ end
106
+
107
+ RSpec.describe TestWorker do
108
+ subject(:worker) { described_class.new }
109
+
110
+ before do
111
+ # This will call `#publish` on `TestWorker`
112
+ Osbourne.publish('test_topic', 'message')
113
+ end
114
+ end
115
+
116
+ ```
117
+
118
+ There is also a test `Message` object you can use and pass directly into your workers. It stubs out the message validation, and creates a mock `message` as if it had been broadcast from SNS.
119
+
120
+ Example:
121
+
122
+ ```ruby
123
+
124
+ let(:test_worker) { TestWorker.new }
125
+ let(:message) { Osbourne::Test::Message.new(topic: "test", body: "thing") }
126
+
127
+ # Now you can use `test_worker.process(message)` in your specs
128
+
129
+ ```
130
+
131
+
132
+
74
133
  ## Usage
75
134
 
76
135
  ### Publishing a message
@@ -5,7 +5,6 @@ class <%= name.singularize.camelcase %>Worker < Osbourne::WorkerBase
5
5
  worker_config topics: %w[<%= topic.join(" ") %>] #, max_batch_size: 10, max_wait: 10
6
6
 
7
7
  def process(message)
8
- puts message.raw_body # This will always be a string, representing the entirety of the message
9
8
  puts message.parsed_body # If the message came from a SNS broadcast,
10
9
  # as opposed to a direct SQS message, it will come from here
11
10
  puts message.topic # The topic this message was published to.
data/lib/osbourne.rb CHANGED
@@ -25,10 +25,14 @@ module Osbourne
25
25
  attr_writer :sns_client, :sqs_client
26
26
 
27
27
  def sns_client
28
+ return if Osbourne.test_mode?
29
+
28
30
  @sns_client ||= Aws::SNS::Client.new(Osbourne.config.sns_config)
29
31
  end
30
32
 
31
33
  def sqs_client
34
+ return if Osbourne.test_mode?
35
+
32
36
  @sqs_client ||= Aws::SQS::Client.new(Osbourne.config.sqs_config)
33
37
  end
34
38
 
@@ -8,7 +8,7 @@ module Osbourne
8
8
  module Config
9
9
  module FileLoader
10
10
  def self.load(cfile, environment="development")
11
- return nil unless File.exist?(cfile)
11
+ return false unless should_run?(cfile)
12
12
 
13
13
  base_opts = YAML.safe_load(ERB.new(IO.read(cfile)).result) || {}
14
14
  env_opts = base_opts[environment] || {}
@@ -17,6 +17,10 @@ module Osbourne
17
17
  Osbourne.config.sqs_config = env_opts["subscriber"].symbolize_keys || {}
18
18
  true
19
19
  end
20
+
21
+ def self.should_run?(cfile)
22
+ File.exist?(cfile) && !Osbourne.test_mode?
23
+ end
20
24
  end
21
25
  end
22
26
  end
@@ -13,6 +13,18 @@ module Osbourne
13
13
  config.cache ||= ActiveSupport::Cache::NullStore.new
14
14
  end
15
15
 
16
+ def test_mode?
17
+ false
18
+ end
19
+
20
+ def test_mode!
21
+ @test_mode = true
22
+ end
23
+
24
+ def test_mode=(test_mode)
25
+ @test_mode = test_mode
26
+ end
27
+
16
28
  def dead_letter
17
29
  config.dead_letter ||= true
18
30
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "osbourne"
4
- require "byebug"
5
4
 
6
5
  module Osbourne
7
6
  class Launcher
@@ -13,8 +13,6 @@ module Osbourne
13
13
  %w[config/osbourne.yml.erb config/osbourne.yml].find do |filename|
14
14
  Osbourne::Config::FileLoader.load(filename, env)
15
15
  end
16
-
17
- Osbourne.provision_worker_queues
18
16
  end
19
17
  end
20
18
  end
@@ -29,6 +29,7 @@ module Osbourne
29
29
  @launcher = Osbourne::Launcher.new
30
30
 
31
31
  begin
32
+ Osbourne.provision_worker_queues
32
33
  @launcher.start!
33
34
 
34
35
  while readable_io = IO.select([self_read]) # rubocop:disable Lint/AssignmentInCondition
@@ -4,6 +4,8 @@ module Osbourne
4
4
  module Services
5
5
  module QueueProvisioner
6
6
  def provision_worker_queues
7
+ return if Osbourne.test_mode?
8
+
7
9
  Osbourne.logger.info "Workers found: #{Osbourne::WorkerBase.descendants.map(&:name).join(', ')}"
8
10
  Osbourne.logger.info "Provisioning queues for all workers"
9
11
 
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "osbourne/test/mock_pubsub"
4
+ require "osbourne/test/message"
5
+
6
+ module Osbourne
7
+ class << self
8
+ def test_mode?
9
+ true
10
+ end
11
+
12
+ def publish(topic, message)
13
+ Osbourne::Test::MockPubsub.mock_publish(topic, message)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osbourne
4
+ module Test
5
+ class Message
6
+ attr_reader :topic, :parsed_body
7
+ def initialize(topic:, body:)
8
+ @topic = topic
9
+ @parsed_body = body
10
+ end
11
+
12
+ def id
13
+ @id ||= SecureRandom.uuid
14
+ end
15
+
16
+ def valid?
17
+ true
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "osbourne/test/message"
4
+ module Osbourne
5
+ module Test
6
+ class MockPubsub
7
+ class << self
8
+ def mock_publish(topic, message)
9
+ Osbourne::WorkerBase.descendants.each do |worker|
10
+ msg = Osbourne::Test::Message.new(topic: topic, body: message)
11
+ worker.new.process(msg) if worker.config[:topic_names].include? topic
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -14,6 +14,8 @@ module Osbourne
14
14
  end
15
15
 
16
16
  def publish(message)
17
+ return if Osbourne.test_mode?
18
+
17
19
  Osbourne.logger.info "[PUB] TOPIC: `#{name}` MESSAGE: `#{message}`"
18
20
  sns.publish(topic_arn: arn, message: message.is_a?(String) ? message : message.to_json)
19
21
  end
@@ -21,6 +23,8 @@ module Osbourne
21
23
  private
22
24
 
23
25
  def ensure_topic
26
+ return if Osbourne.test_mode?
27
+
24
28
  Osbourne.logger.debug "Ensuring topic `#{name}` exists"
25
29
  Osbourne.cache.fetch("osbourne_existing_topic_arn_for_#{name}") do
26
30
  sns.create_topic(name: name).topic_arn
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Osbourne
4
- VERSION = "0.1.3"
4
+ VERSION = "0.2.2"
5
5
  end
metadata CHANGED
@@ -1,85 +1,109 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: osbourne
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Allen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-09 00:00:00.000000000 Z
11
+ date: 2018-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-core
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '4'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '3'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '4'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: aws-sdk-sns
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
- - - "~>"
37
+ - - ">="
32
38
  - !ruby/object:Gem::Version
33
- version: '1'
39
+ version: '1.5'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '2'
34
43
  type: :runtime
35
44
  prerelease: false
36
45
  version_requirements: !ruby/object:Gem::Requirement
37
46
  requirements:
38
- - - "~>"
47
+ - - ">="
39
48
  - !ruby/object:Gem::Version
40
- version: '1'
49
+ version: '1.5'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '2'
41
53
  - !ruby/object:Gem::Dependency
42
54
  name: aws-sdk-sqs
43
55
  requirement: !ruby/object:Gem::Requirement
44
56
  requirements:
45
- - - "~>"
57
+ - - ">="
46
58
  - !ruby/object:Gem::Version
47
- version: '1'
59
+ version: '1.6'
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: '2'
48
63
  type: :runtime
49
64
  prerelease: false
50
65
  version_requirements: !ruby/object:Gem::Requirement
51
66
  requirements:
52
- - - "~>"
67
+ - - ">="
53
68
  - !ruby/object:Gem::Version
54
- version: '1'
69
+ version: '1.6'
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '2'
55
73
  - !ruby/object:Gem::Dependency
56
74
  name: rails
57
75
  requirement: !ruby/object:Gem::Requirement
58
76
  requirements:
59
- - - "~>"
77
+ - - ">="
60
78
  - !ruby/object:Gem::Version
61
79
  version: '5'
80
+ - - "<"
81
+ - !ruby/object:Gem::Version
82
+ version: '6'
62
83
  type: :runtime
63
84
  prerelease: false
64
85
  version_requirements: !ruby/object:Gem::Requirement
65
86
  requirements:
66
- - - "~>"
87
+ - - ">="
67
88
  - !ruby/object:Gem::Version
68
89
  version: '5'
90
+ - - "<"
91
+ - !ruby/object:Gem::Version
92
+ version: '6'
69
93
  - !ruby/object:Gem::Dependency
70
94
  name: thor
71
95
  requirement: !ruby/object:Gem::Requirement
72
96
  requirements:
73
- - - "~>"
97
+ - - ">="
74
98
  - !ruby/object:Gem::Version
75
- version: '0'
99
+ version: '0.19'
76
100
  type: :runtime
77
101
  prerelease: false
78
102
  version_requirements: !ruby/object:Gem::Requirement
79
103
  requirements:
80
- - - "~>"
104
+ - - ">="
81
105
  - !ruby/object:Gem::Version
82
- version: '0'
106
+ version: '0.19'
83
107
  - !ruby/object:Gem::Dependency
84
108
  name: bundler
85
109
  requirement: !ruby/object:Gem::Requirement
@@ -112,30 +136,30 @@ dependencies:
112
136
  name: guard
113
137
  requirement: !ruby/object:Gem::Requirement
114
138
  requirements:
115
- - - "~>"
139
+ - - ">="
116
140
  - !ruby/object:Gem::Version
117
141
  version: '2'
118
142
  type: :development
119
143
  prerelease: false
120
144
  version_requirements: !ruby/object:Gem::Requirement
121
145
  requirements:
122
- - - "~>"
146
+ - - ">="
123
147
  - !ruby/object:Gem::Version
124
148
  version: '2'
125
149
  - !ruby/object:Gem::Dependency
126
150
  name: guard-bundler
127
151
  requirement: !ruby/object:Gem::Requirement
128
152
  requirements:
129
- - - "~>"
153
+ - - ">="
130
154
  - !ruby/object:Gem::Version
131
- version: '2.1'
155
+ version: '2'
132
156
  type: :development
133
157
  prerelease: false
134
158
  version_requirements: !ruby/object:Gem::Requirement
135
159
  requirements:
136
- - - "~>"
160
+ - - ">="
137
161
  - !ruby/object:Gem::Version
138
- version: '2.1'
162
+ version: '2'
139
163
  - !ruby/object:Gem::Dependency
140
164
  name: guard-rspec
141
165
  requirement: !ruby/object:Gem::Requirement
@@ -154,86 +178,98 @@ dependencies:
154
178
  name: mock_redis
155
179
  requirement: !ruby/object:Gem::Requirement
156
180
  requirements:
157
- - - "~>"
181
+ - - ">="
158
182
  - !ruby/object:Gem::Version
159
- version: '0'
183
+ version: '0.19'
160
184
  type: :development
161
185
  prerelease: false
162
186
  version_requirements: !ruby/object:Gem::Requirement
163
187
  requirements:
164
- - - "~>"
188
+ - - ">="
165
189
  - !ruby/object:Gem::Version
166
- version: '0'
190
+ version: '0.19'
167
191
  - !ruby/object:Gem::Dependency
168
192
  name: pry-byebug
169
193
  requirement: !ruby/object:Gem::Requirement
170
194
  requirements:
171
- - - "~>"
195
+ - - ">="
172
196
  - !ruby/object:Gem::Version
173
197
  version: '3.6'
174
198
  type: :development
175
199
  prerelease: false
176
200
  version_requirements: !ruby/object:Gem::Requirement
177
201
  requirements:
178
- - - "~>"
202
+ - - ">="
179
203
  - !ruby/object:Gem::Version
180
204
  version: '3.6'
181
205
  - !ruby/object:Gem::Dependency
182
206
  name: rake
183
207
  requirement: !ruby/object:Gem::Requirement
184
208
  requirements:
185
- - - "~>"
209
+ - - ">="
186
210
  - !ruby/object:Gem::Version
187
- version: '10.0'
211
+ version: '10'
188
212
  type: :development
189
213
  prerelease: false
190
214
  version_requirements: !ruby/object:Gem::Requirement
191
215
  requirements:
192
- - - "~>"
216
+ - - ">="
193
217
  - !ruby/object:Gem::Version
194
- version: '10.0'
218
+ version: '10'
195
219
  - !ruby/object:Gem::Dependency
196
220
  name: redis
197
221
  requirement: !ruby/object:Gem::Requirement
198
222
  requirements:
199
- - - "~>"
223
+ - - ">="
200
224
  - !ruby/object:Gem::Version
201
225
  version: '4'
226
+ - - "<"
227
+ - !ruby/object:Gem::Version
228
+ version: '5'
202
229
  type: :development
203
230
  prerelease: false
204
231
  version_requirements: !ruby/object:Gem::Requirement
205
232
  requirements:
206
- - - "~>"
233
+ - - ">="
207
234
  - !ruby/object:Gem::Version
208
235
  version: '4'
236
+ - - "<"
237
+ - !ruby/object:Gem::Version
238
+ version: '5'
209
239
  - !ruby/object:Gem::Dependency
210
240
  name: rspec
211
241
  requirement: !ruby/object:Gem::Requirement
212
242
  requirements:
213
- - - "~>"
243
+ - - ">="
214
244
  - !ruby/object:Gem::Version
215
- version: '3'
245
+ version: '3.2'
246
+ - - "<"
247
+ - !ruby/object:Gem::Version
248
+ version: '4'
216
249
  type: :development
217
250
  prerelease: false
218
251
  version_requirements: !ruby/object:Gem::Requirement
219
252
  requirements:
220
- - - "~>"
253
+ - - ">="
221
254
  - !ruby/object:Gem::Version
222
- version: '3'
255
+ version: '3.2'
256
+ - - "<"
257
+ - !ruby/object:Gem::Version
258
+ version: '4'
223
259
  - !ruby/object:Gem::Dependency
224
260
  name: rubocop
225
261
  requirement: !ruby/object:Gem::Requirement
226
262
  requirements:
227
- - - "~>"
263
+ - - ">="
228
264
  - !ruby/object:Gem::Version
229
- version: '0'
265
+ version: '0.50'
230
266
  type: :development
231
267
  prerelease: false
232
268
  version_requirements: !ruby/object:Gem::Requirement
233
269
  requirements:
234
- - - "~>"
270
+ - - ">="
235
271
  - !ruby/object:Gem::Version
236
- version: '0'
272
+ version: '0.50'
237
273
  - !ruby/object:Gem::Dependency
238
274
  name: rubocop-rspec
239
275
  requirement: !ruby/object:Gem::Requirement
@@ -316,6 +352,9 @@ files:
316
352
  - lib/osbourne/services/sns.rb
317
353
  - lib/osbourne/services/sqs.rb
318
354
  - lib/osbourne/subscription.rb
355
+ - lib/osbourne/test.rb
356
+ - lib/osbourne/test/message.rb
357
+ - lib/osbourne/test/mock_pubsub.rb
319
358
  - lib/osbourne/topic.rb
320
359
  - lib/osbourne/version.rb
321
360
  - lib/osbourne/worker_base.rb