announce 0.2.0 → 0.3.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
  SHA1:
3
- metadata.gz: 9789a278d07101dcd8a592549cd616a0d9792577
4
- data.tar.gz: 9bdb61307e9b940ba340bd604a42acee381f0f26
3
+ metadata.gz: c4197e2523a8f2fde2b5c27b19d7ffff59864c21
4
+ data.tar.gz: 447f8331968cedbaa1c11d7e412f1a9d49eaf9f2
5
5
  SHA512:
6
- metadata.gz: 0422db42eed7b943f3fde2133ad9e6b67438eab02b874697d4b39b5cb54b65bda5470e5b262241dfeec49332a2db3d71d137915f78d54cbf44da88a9229130ef
7
- data.tar.gz: 0689cc11bb610d00bbd074bf41924d589a3be572b75f167f1e2a1817b363b8bdcf3298cbfd772847b3b0a8aa328418938ef861e83373b283eaf1a01c211b0c03
6
+ metadata.gz: f96f65e1562900251b14ba50068ec9a2926202250deb371c42be86de5f33fc2e792d071a4c7ae0080286c9a44501646f2c096ae164104d3f14c87a2562908ee5
7
+ data.tar.gz: 3408e11b3d4aa7009532040d42bce7a2f9330771b63412559eea0b04cdd779bd357b572b0004e1d858019b5aa5694729706c30109a1230f9e53a251a2d015336
data/.travis.yml CHANGED
@@ -1,7 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1.2
4
- - 2.2.1
3
+ - 2.1.10
4
+ - 2.2.5
5
+ - 2.3.1
5
6
  env:
6
7
  global:
7
8
  - TRAVIS=true
data/README.md CHANGED
@@ -32,7 +32,7 @@ end
32
32
  ```
33
33
 
34
34
  When building a Ruby app or service to receive messages, subscribe a job class to announcements like this:
35
- ```
35
+ ```ruby
36
36
  require 'announce'
37
37
 
38
38
  class SomeCreateJob < ActiveJob::Base
@@ -223,7 +223,7 @@ Announce.announce(:story, :publish, id: story.id, {})
223
223
  ```
224
224
 
225
225
  There is also a module you can include to get `publish` and `announce` methods:
226
- ```
226
+ ```ruby
227
227
  class SomeController
228
228
  include Announce::Publisher
229
229
 
@@ -247,7 +247,7 @@ Unlike other job libraries which specify the Ruby `Class` for processing as part
247
247
 
248
248
  To designate that a Ruby class will process a message, you must include the `Announce:Subscriber` module and call `subscribe_to` class method.
249
249
 
250
- ```
250
+ ```ruby
251
251
  require 'announce'
252
252
 
253
253
  class SomeCreateJob < ActiveJob::Base
@@ -264,7 +264,7 @@ end
264
264
  This works because the `Announce::Subscriber` adds the `subscribe_to` class method, but also a default `perform(*args)` instance method that delegates message handling to a job instance method named `"receive_#{subject}_#{action}"`.
265
265
 
266
266
  This default `perform` method only passes the message `body` to `receive_subject_action` methods. The `subject`, but `action` and full `message` object are made available as instance properties of the subscriber.
267
- ```
267
+ ```ruby
268
268
  require 'announce'
269
269
 
270
270
  class SomeCreateJob < ActiveJob::Base
@@ -302,6 +302,42 @@ For `shoryuken`, `subscribe_to` registers the worker for the appropriate queue,
302
302
 
303
303
  ## Development
304
304
 
305
+ ### Testing with Announce
306
+
307
+ There is an Announce::Testing module which provides helper methods useful in your tests.
308
+ To use them add the following lines into your test/spec helper:
309
+ ```ruby
310
+ # use the testing helper
311
+ require 'announce/testing'
312
+
313
+ # include the methods - could also include in your base test class
314
+ include Announce::Testing
315
+
316
+ # this resets announce to use test settings, and clears messages
317
+ reset_announce
318
+
319
+ ```
320
+
321
+ Then you can use the following methods in your test class:
322
+
323
+ `published_messages` - returns the array of published messages
324
+
325
+ `last_message` - returns the last message published to announce
326
+
327
+ `clear_messages` - clears all published messages
328
+
329
+ `subscriptions` - returns the array of all subscriptions
330
+
331
+ `last_subscription` - returns most recently added subscription
332
+
333
+ `clear_subscriptions` - clears all subscriptions
334
+
335
+ `broker_configured?` - returns whether or not the broker has been configured
336
+
337
+ `reset_broker_config` - resets broker
338
+
339
+ `reset_announce` - resets announce to use test adapter, prefix, app, and logging to `/dev/null`
340
+
305
341
  ### Developing an Adapter Class
306
342
 
307
343
  Adapter classes should be named with the following module structure: `Announce::Adapters::SomeBrokerAdapter`
data/announce.gemspec CHANGED
@@ -19,12 +19,13 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ['lib']
21
21
 
22
- spec.add_development_dependency 'shoryuken', '~> 1.0'
22
+ spec.add_development_dependency 'shoryuken', '~> 2.0.5'
23
23
  spec.add_development_dependency 'bundler'
24
24
  spec.add_development_dependency 'rake'
25
25
  spec.add_development_dependency 'growl'
26
26
  spec.add_development_dependency 'minitest'
27
27
  spec.add_development_dependency 'guard'
28
+ spec.add_development_dependency 'listen', '~> 3.2.0'
28
29
  spec.add_development_dependency 'guard-minitest'
29
30
  spec.add_development_dependency 'dotenv'
30
31
  spec.add_development_dependency 'simplecov'
@@ -1,33 +1,37 @@
1
- require 'announce'
2
- require 'announce/message'
1
+ require "announce"
2
+ require "announce/message"
3
3
 
4
- # publish, subscribe, and configure_broker are the 3 required methods for an adapter
5
- # this base adapter also has some helpful base classes, but they are not necessary
6
- # you could write an adapter from scratch so long as the class has these 3 class methods.
4
+ # publish, subscribe, & configure_broker are the 3 required methods for adapters
5
+ # the base adapter also has helpful base classes, but they are not necessary
6
+ # you can write an adapter from scratch, but these 3 class methods are required.
7
7
  module Announce
8
8
  module Adapters
9
9
  class BaseAdapter
10
-
11
10
  class << self
12
-
11
+ # required
13
12
  def publish(subject, action, body, options = {})
14
13
  topic = adapter_constantize(:topic).new(subject, action, options)
15
- msg = Announce::Message.new(subject: subject, action: action, body: body)
14
+ msg =
15
+ Announce::Message.new(subject: subject, action: action, body: body)
16
16
  topic.publish(msg.to_message, options)
17
17
  end
18
18
 
19
+ # required
19
20
  def subscribe(worker_class, subject, actions = [], options = {})
20
21
  subscriber = adapter_constantize(:subscriber).new
21
22
  subscriber.subscribe(worker_class, subject, actions, options)
22
23
  end
23
24
 
25
+ # required
24
26
  def configure_broker(options)
25
27
  broker_manager = adapter_constantize(:broker_manager).new(options)
26
28
  broker_manager.configure
27
29
  end
28
30
 
29
31
  def adapter_constantize(name)
30
- "::Announce::Adapters::#{Announce.options[:adapter].to_s.camelize}Adapter::#{name.to_s.camelize}".constantize
32
+ a_klass = Announce.options[:adapter].to_s.camelize
33
+ klass = name.to_s.camelize
34
+ "::Announce::Adapters::#{a_klass}Adapter::#{klass}".constantize
31
35
  end
32
36
  end
33
37
 
@@ -41,8 +45,8 @@ module Announce
41
45
  attr_accessor :options
42
46
 
43
47
  # uses the configuration
44
- def initialize(options = Announce.options)
45
- @options = options
48
+ def initialize(options = {})
49
+ @options = Announce.options.merge(options)
46
50
  end
47
51
 
48
52
  # actually configure the broker queues, topics, and subscriptions
@@ -62,6 +66,10 @@ module Announce
62
66
  raise NotImplementedError.new("You must implement create.")
63
67
  end
64
68
 
69
+ def verify
70
+ raise NotImplementedError.new("You must implement verify.")
71
+ end
72
+
65
73
  def self.name_for(subject, action)
66
74
  [prefix, namespace, subject, action].join(delimiter)
67
75
  end
@@ -93,8 +101,7 @@ module Announce
93
101
  end
94
102
  end
95
103
 
96
- class Topic < Destination
97
- end
104
+ class Topic < Destination; end
98
105
 
99
106
  class Queue < Destination
100
107
  def self.name_for(subject, action)
@@ -1,9 +1,8 @@
1
- require 'announce/adapters/base_adapter'
1
+ require "announce/adapters/base_adapter"
2
2
 
3
3
  module Announce
4
4
  module Adapters
5
5
  class InlineAdapter < BaseAdapter
6
-
7
6
  def self.subscriptions
8
7
  @@subscriptions ||= {}
9
8
  end
@@ -34,8 +33,7 @@ module Announce
34
33
  end
35
34
  end
36
35
 
37
- class Queue < BaseAdapter::Queue
38
- end
36
+ class Queue < BaseAdapter::Queue; end
39
37
  end
40
38
  end
41
39
  end
@@ -1,27 +1,24 @@
1
- require 'shoryuken'
2
- require 'announce/adapters/base_adapter'
1
+ require "shoryuken"
2
+ require "announce/adapters/base_adapter"
3
3
 
4
4
  module Announce
5
5
  module Adapters
6
6
  class ShoryukenAdapter < BaseAdapter
7
-
8
7
  class AnnounceWorker #:nodoc:
9
8
  include Shoryuken::Worker
10
9
 
11
10
  shoryuken_options body_parser: :json, auto_delete: true
12
11
 
13
12
  # overriden in register_class
14
- def job_class
15
- end
13
+ def job_class; end
16
14
 
17
15
  def perform(sqs_msg, hash)
18
16
  job = job_class.new(hash)
19
- Base.execute(job.serialize)
17
+ ActiveJob::Base.execute(job.serialize)
20
18
  end
21
19
  end
22
20
 
23
21
  class Subscriber < BaseAdapter::Subscriber
24
-
25
22
  def subscribe(worker_class, subject, actions, options)
26
23
  Array(actions).each do |action|
27
24
  queue_name = Queue.name_for(subject, action)
@@ -42,22 +39,31 @@ module Announce
42
39
 
43
40
  def active_job?
44
41
  defined?(::ActiveJob) &&
45
- defined?(ActiveJob::QueueAdapters::ShoryukenAdapter) &&
46
- ActiveJob::Base.queue_adapter == ActiveJob::QueueAdapters::ShoryukenAdapter
42
+ defined?(ActiveJob::QueueAdapters::ShoryukenAdapter) &&
43
+ ActiveJob::Base.queue_adapter ==
44
+ ActiveJob::QueueAdapters::ShoryukenAdapter
47
45
  end
48
46
  end
49
47
 
50
48
  class BrokerManager < BaseAdapter::BrokerManager
51
-
52
49
  # actually configure the broker queues, topics, and subscriptions
53
50
  def configure
51
+ if options[:verify_only]
52
+ Announce.logger.warn(
53
+ "Running Announce BrokerManager configure in verify_only mode."
54
+ )
55
+ Announce.logger.warn(
56
+ "Resources will be logged, not created; please verify they exist."
57
+ )
58
+ end
54
59
  configure_publishing && configure_subscribing
55
60
  end
56
61
 
57
62
  def configure_publishing
58
63
  (options[:publish] || {}).each do |subject, actions|
59
64
  Array(actions).each do |action|
60
- ShoryukenAdapter::Topic.new(subject, action, options).create
65
+ topic = ShoryukenAdapter::Topic.new(subject, action, options)
66
+ options[:verify_only] ? topic.verify : topic.create
61
67
  end
62
68
  end
63
69
  true
@@ -68,9 +74,15 @@ module Announce
68
74
  Array(actions).each do |action|
69
75
  topic = ShoryukenAdapter::Topic.new(subject, action, options)
70
76
  queue = ShoryukenAdapter::Queue.new(subject, action, options)
71
- topic.create
72
- queue.create
73
- topic.subscribe(queue)
77
+ if options[:verify_only]
78
+ topic.verify
79
+ queue.verify
80
+ topic.verify_subscription(queue)
81
+ else
82
+ topic.create
83
+ queue.create
84
+ topic.subscribe(queue)
85
+ end
74
86
  end
75
87
  end
76
88
  true
@@ -78,7 +90,6 @@ module Announce
78
90
  end
79
91
 
80
92
  class Topic < BaseAdapter::Topic
81
-
82
93
  def publish(message, options = {})
83
94
  Shoryuken::Client.topics(name).send_message(message, options)
84
95
  end
@@ -87,17 +98,28 @@ module Announce
87
98
  sns.create_topic(name: name)[:topic_arn]
88
99
  end
89
100
 
101
+ def verify
102
+ Announce.logger.warn("Verify SNS Topic: #{arn}")
103
+ end
104
+
105
+ def verify_subscription(queue)
106
+ Announce.logger.warn(
107
+ "Verify Subscription:\n"\
108
+ " from SNS Topic: #{arn}\n"\
109
+ " to SQS Queue: #{queue.arn}"
110
+ )
111
+ end
112
+
90
113
  def subscribe(queue)
91
- subscription_arn = sns.subscribe(
92
- topic_arn: arn,
93
- protocol: 'sqs',
94
- endpoint: queue.arn
95
- )[:subscription_arn]
114
+ subscription_arn =
115
+ sns.subscribe(topic_arn: arn, protocol: "sqs", endpoint: queue.arn)[
116
+ :subscription_arn
117
+ ]
96
118
 
97
119
  sns.set_subscription_attributes(
98
120
  subscription_arn: subscription_arn,
99
- attribute_name: 'RawMessageDelivery',
100
- attribute_value: 'true'
121
+ attribute_name: "RawMessageDelivery",
122
+ attribute_value: "true"
101
123
  )
102
124
  subscription_arn
103
125
  end
@@ -114,14 +136,25 @@ module Announce
114
136
  end
115
137
 
116
138
  class Queue < BaseAdapter::Queue
139
+ DLQ_SUFFIX = "failures".freeze
117
140
 
118
141
  def create
119
- create_attributes = default_options.merge((options[:queues] || {}).stringify_keys)
120
-
121
142
  dlq_arn = create_dlq
122
- create_attributes['RedrivePolicy'] = %Q{{"maxReceiveCount":"10", "deadLetterTargetArn":"#{dlq_arn}"}"}
123
143
 
124
- sqs.create_queue(queue_name: name, attributes: create_attributes)[:queue_url]
144
+ create_attributes =
145
+ default_options.merge((options[:queues] || {}).stringify_keys)
146
+ create_attributes["RedrivePolicy"] =
147
+ '{"maxReceiveCount":"10", "deadLetterTargetArn":"' + dlq_arn + '"}'
148
+
149
+ sqs.create_queue(queue_name: name, attributes: create_attributes)[
150
+ :queue_url
151
+ ]
152
+ end
153
+
154
+ def verify
155
+ Announce.logger.warn(
156
+ "Verify SQS Queue: #{arn}\n\t with DLQ: #{dlq_arn}"
157
+ )
125
158
  end
126
159
 
127
160
  def arn
@@ -131,34 +164,40 @@ module Announce
131
164
  end
132
165
 
133
166
  def create_dlq
134
- dlq_name = "#{name}_failures"
135
-
136
167
  dlq_options = {
137
- 'MaximumMessageSize' => "#{(256 * 1024)}",
138
- 'MessageRetentionPeriod' => "#{2 * 7 * 24 * 60 * 60}" # 2 weeks in seconds
168
+ "MaximumMessageSize" => (256 * 1024).to_s,
169
+ "MessageRetentionPeriod" => (2 * 7 * 24 * 60 * 60).to_s
170
+ # 2 weeks in seconds
139
171
  }
140
172
 
141
- dlq = sqs.create_queue(
142
- queue_name: dlq_name,
143
- attributes: dlq_options
144
- )
173
+ dlq = sqs.create_queue(queue_name: dlq_name, attributes: dlq_options)
145
174
 
146
- attrs = sqs.get_queue_attributes(
147
- queue_url: dlq[:queue_url],
148
- attribute_names: ['QueueArn']
149
- )
175
+ attrs =
176
+ sqs.get_queue_attributes(
177
+ queue_url: dlq[:queue_url], attribute_names: %w[QueueArn]
178
+ )
179
+
180
+ attrs.attributes["QueueArn"]
181
+ end
150
182
 
151
- attrs.attributes['QueueArn']
183
+ def dlq_arn
184
+ [arn, DLQ_SUFFIX].join(self.class.delimiter)
185
+ end
186
+
187
+ def dlq_name
188
+ [name, DLQ_SUFFIX].join(self.class.delimiter)
152
189
  end
153
190
 
154
191
  def default_options
155
192
  {
156
- 'DelaySeconds' => '0',
157
- 'MaximumMessageSize' => "#{256 * 1024}",
158
- 'VisibilityTimeout' => "#{60 * 60}", # 1 hour in seconds
159
- 'ReceiveMessageWaitTimeSeconds' => '0',
160
- 'MessageRetentionPeriod' => "#{7 * 24 * 60 * 60}", # 1 week in seconds
161
- 'Policy' => policy
193
+ "DelaySeconds" => "0",
194
+ "MaximumMessageSize" => (256 * 1024).to_s,
195
+ "VisibilityTimeout" => (60 * 60).to_s,
196
+ # 1 hour in seconds
197
+ "ReceiveMessageWaitTimeSeconds" => "0",
198
+ "MessageRetentionPeriod" => (7 * 24 * 60 * 60).to_s,
199
+ # 1 week in seconds
200
+ "Policy" => policy
162
201
  }
163
202
  end
164
203
 
@@ -172,9 +211,7 @@ module Announce
172
211
  {
173
212
  "Sid" => "1",
174
213
  "Effect" => "Allow",
175
- "Principal" => {
176
- "AWS" => "*"
177
- },
214
+ "Principal" => { "AWS" => "*" },
178
215
  "Action" => "sqs:*",
179
216
  "Resource" => arn,
180
217
  "Condition" => {
@@ -195,4 +232,6 @@ module Announce
195
232
  end
196
233
  end
197
234
 
198
- Shoryuken::Client.account_id = ENV['AWS_ACCOUNT_ID'] unless Shoryuken::Client.account_id
235
+ unless Shoryuken::Client.account_id
236
+ Shoryuken::Client.account_id = ENV["AWS_ACCOUNT_ID"]
237
+ end
@@ -1,11 +1,9 @@
1
- require 'announce/adapters/base_adapter'
1
+ require "announce/adapters/base_adapter"
2
2
 
3
3
  module Announce
4
4
  module Adapters
5
5
  class TestAdapter < BaseAdapter
6
-
7
6
  class Subscriber < BaseAdapter::Subscriber
8
-
9
7
  @@subscriptions = []
10
8
 
11
9
  def self.subscriptions
@@ -35,7 +33,6 @@ module Announce
35
33
  end
36
34
 
37
35
  class Topic < BaseAdapter::Topic
38
-
39
36
  @@published_messages = []
40
37
 
41
38
  def self.published_messages
@@ -50,12 +47,22 @@ module Announce
50
47
  def create
51
48
  true
52
49
  end
50
+
51
+ def verify
52
+ Announce.logger.debug("#{self.class.name}: verify #{name}")
53
+ true
54
+ end
53
55
  end
54
56
 
55
57
  class Queue < BaseAdapter::Queue
56
58
  def create
57
59
  true
58
60
  end
61
+
62
+ def verify
63
+ Announce.logger.debug("#{self.class.name}: verify #{name}")
64
+ true
65
+ end
59
66
  end
60
67
  end
61
68
  end
@@ -1,5 +1,5 @@
1
- require 'yaml'
2
- require 'erb'
1
+ require "yaml"
2
+ require "erb"
3
3
 
4
4
  module Announce
5
5
  class Configuration
@@ -14,16 +14,18 @@ module Announce
14
14
  {}.tap do |defaults|
15
15
  if defined?(ActiveJob)
16
16
  defaults[:queue_name_prefix] = ::ActiveJob::Base.queue_name_prefix
17
- defaults[:queue_name_delimiter] = ::ActiveJob::Base.queue_name_delimiter
17
+ defaults[:queue_name_delimiter] =
18
+ ::ActiveJob::Base.queue_name_delimiter
18
19
  defaults[:adapter] = aj_queue_adapter_name
19
20
  else
20
- defaults[:queue_name_prefix] = ENV['RAILS_ENV'] || ENV['APP_ENV'] || 'development'
21
- defaults[:queue_name_delimiter] = '_'
21
+ defaults[:queue_name_prefix] =
22
+ ENV["RAILS_ENV"] || ENV["APP_ENV"] || "development"
23
+ defaults[:queue_name_delimiter] = "_"
22
24
  defaults[:adapter] = :inline
23
25
  end
24
26
 
25
- defaults[:app_name] = 'app'
26
- defaults[:namespace] = 'announce'
27
+ defaults[:app_name] = "app"
28
+ defaults[:namespace] = "announce"
27
29
  end
28
30
  end
29
31
 
@@ -35,7 +37,7 @@ module Announce
35
37
  def initialize(options)
36
38
  @options = options
37
39
  base = defined?(Rails) ? Rails.root : Dir.pwd
38
- options[:config_file] ||= File.join(base, 'config', 'announce.yml')
40
+ options[:config_file] ||= File.join(base, "config", "announce.yml")
39
41
  end
40
42
 
41
43
  def config_file
@@ -45,7 +47,9 @@ module Announce
45
47
  def configure
46
48
  defaults = self.class.default_options
47
49
  if File.exist?(config_file)
48
- defaults.merge(YAML.load(ERB.new(IO.read(config_file)).result).symbolize_keys)
50
+ defaults.merge(
51
+ YAML.safe_load(ERB.new(IO.read(config_file)).result).symbolize_keys
52
+ )
49
53
  else
50
54
  Announce.logger.warn "PubSub file #{config_file} does not exist"
51
55
  defaults
@@ -1,7 +1,7 @@
1
1
  begin
2
- require 'active_support/core_ext/hash/keys'
3
- require 'active_support/core_ext/hash/deep_merge'
4
- require 'active_support/core_ext/hash/slice'
2
+ require "active_support/core_ext/hash/keys"
3
+ require "active_support/core_ext/hash/deep_merge"
4
+ require "active_support/core_ext/hash/slice"
5
5
  rescue LoadError
6
6
  class Hash
7
7
  def stringify_keys
@@ -36,11 +36,11 @@ rescue LoadError
36
36
  end
37
37
 
38
38
  begin
39
- require 'active_support/core_ext/string/inflections'
39
+ require "active_support/core_ext/string/inflections"
40
40
  rescue LoadError
41
41
  class String
42
42
  def constantize
43
- names = self.split('::')
43
+ names = self.split("::")
44
44
  names.shift if names.empty? || names.first.empty?
45
45
 
46
46
  constant = Object
@@ -54,14 +54,14 @@ rescue LoadError
54
54
  string = self
55
55
  string = string.sub(/^[a-z\d]*/) { $&.capitalize }
56
56
  string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
57
- string.gsub!(/\//, '::')
57
+ string.gsub!(/\//, "::")
58
58
  string
59
59
  end
60
60
 
61
61
  def underscore
62
62
  camel_cased_word = self
63
63
  return camel_cased_word unless camel_cased_word =~ /[A-Z-]|::/
64
- word = camel_cased_word.to_s.gsub(/::/, '/')
64
+ word = camel_cased_word.to_s.gsub(/::/, "/")
65
65
  word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
66
66
  word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
67
67
  word.tr!("-", "_")
@@ -1,16 +1,17 @@
1
- require 'json'
1
+ require "securerandom"
2
+ require "json"
2
3
 
3
4
  module Announce
4
5
  class Message
5
-
6
6
  attr_accessor :options
7
7
 
8
- def initialize(options={})
9
- @options = {
10
- 'message_id' => SecureRandom.uuid,
11
- 'app' => app,
12
- 'sent_at' => Time.now.utc
13
- }.merge(options).stringify_keys
8
+ def initialize(options = {})
9
+ @options =
10
+ {
11
+ "message_id" => ::SecureRandom.uuid,
12
+ "app" => app,
13
+ "sent_at" => Time.now.utc
14
+ }.merge(options).stringify_keys
14
15
  end
15
16
 
16
17
  def app
@@ -1,6 +1,5 @@
1
- require 'shoryuken'
2
- require 'announce'
3
- require 'announce/message'
1
+ require "shoryuken"
2
+ require "announce/message"
4
3
 
5
4
  module Announce
6
5
  module Publisher
@@ -1,8 +1,5 @@
1
1
  module Announce
2
2
  class Railtie < Rails::Railtie
3
-
4
- rake_tasks do
5
- load "tasks/announce.rake"
6
- end
3
+ rake_tasks { load "tasks/announce.rake" }
7
4
  end
8
- end
5
+ end
@@ -1,16 +1,13 @@
1
1
  module Announce
2
2
  module Subscriber
3
-
4
3
  def self.included(base)
5
- base.class_eval do
6
- attr_accessor :subject, :action, :message
7
- end
4
+ base.class_eval { attr_accessor :subject, :action, :message }
8
5
 
9
6
  base.extend(ClassMethods)
10
7
  end
11
8
 
12
9
  module ClassMethods
13
- def subscribe_to(subject, actions=[], options = {})
10
+ def subscribe_to(subject, actions = [], options = {})
14
11
  Announce.subscribe(self, subject, actions, options)
15
12
  end
16
13
  end
@@ -25,19 +22,20 @@ module Announce
25
22
  @subject = message[:subject]
26
23
  @action = message[:action]
27
24
 
28
- if [message, subject, action].any? { |a| a.nil? }
29
- raise "Message, subject, and action are not all specified for '#{event.inspect}'"
25
+ if [message, subject, action].any?(&:nil?)
26
+ raise "Missing message, subject, or action for '#{event.inspect}'"
30
27
  end
31
28
 
32
29
  if respond_to?(delegate_method)
33
30
  public_send(delegate_method, message[:body])
34
31
  else
35
- raise "`#{self.class.name}` is subscribed, but doesn't implement `#{delegate_method}` for '#{event.inspect}'"
32
+ raise "`#{self.class.name}` subscribed, but doesn't implement " \
33
+ "`#{delegate_method}` for '#{event.inspect}'"
36
34
  end
37
35
  end
38
36
 
39
37
  def delegate_method(message = @message)
40
- ['receive', message[:subject], message[:action]].join('_')
38
+ ["receive", message[:subject], message[:action]].join("_")
41
39
  end
42
40
  end
43
41
  end
@@ -0,0 +1,45 @@
1
+ require 'announce/adapters/test_adapter'
2
+
3
+ module Announce
4
+ module Testing
5
+ def published_messages
6
+ Announce::Adapters::TestAdapter::Topic.published_messages
7
+ end
8
+
9
+ def last_message
10
+ published_messages.last
11
+ end
12
+
13
+ def clear_messages
14
+ published_messages.clear
15
+ end
16
+
17
+ def subscriptions
18
+ Announce::Adapters::TestAdapter::Subscriber.subscriptions
19
+ end
20
+
21
+ def last_subscription
22
+ subscriptions.last
23
+ end
24
+
25
+ def clear_subscriptions
26
+ subscriptions.clear
27
+ end
28
+
29
+ def broker_configured?
30
+ Announce::Adapters::TestAdapter::BrokerManager.configured?
31
+ end
32
+
33
+ def reset_broker_config
34
+ Announce::Adapters::TestAdapter::BrokerManager.reset
35
+ end
36
+
37
+ def reset_announce
38
+ Announce.logger = Logger.new('/dev/null')
39
+ Announce.options[:adapter] = 'test'
40
+ Announce.options[:queue_name_prefix] = 'test'
41
+ Announce.options[:app_name] = 'app'
42
+ clear_messages
43
+ end
44
+ end
45
+ end
@@ -1,3 +1,3 @@
1
1
  module Announce
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/announce.rb CHANGED
@@ -1,17 +1,16 @@
1
- require 'logger'
1
+ require "logger"
2
2
 
3
- require 'announce/configuration'
4
- require 'announce/core_ext'
5
- require 'announce/message'
6
- require 'announce/publisher'
7
- require 'announce/subscriber'
8
- require 'announce/version'
9
- require 'announce/railtie' if defined?(Rails)
3
+ require "announce/configuration"
4
+ require "announce/core_ext"
5
+ require "announce/message"
6
+ require "announce/publisher"
7
+ require "announce/subscriber"
8
+ require "announce/version"
9
+ require "announce/railtie" if defined?(Rails)
10
10
 
11
11
  module Announce
12
12
  class << self
13
-
14
- def publish(subject, action, message, options={})
13
+ def publish(subject, action, message, options = {})
15
14
  adapter_class.publish(subject, action, message, options)
16
15
  end
17
16
 
@@ -21,8 +20,8 @@ module Announce
21
20
  adapter_class.subscribe(worker_class, subject, actions, options)
22
21
  end
23
22
 
24
- def configure_broker
25
- adapter_class.configure_broker(options)
23
+ def configure_broker(opts = {})
24
+ adapter_class.configure_broker(options.merge(opts))
26
25
  end
27
26
 
28
27
  def options
@@ -37,15 +36,12 @@ module Announce
37
36
  def adapter_class
38
37
  announce_adapter = Announce.options[:adapter]
39
38
  require "announce/adapters/#{announce_adapter.to_s.downcase}_adapter"
40
- "::Announce::Adapters::#{announce_adapter.to_s.camelize}Adapter".constantize
39
+ "::Announce::Adapters::#{announce_adapter.to_s.camelize}Adapter"
40
+ .constantize
41
41
  end
42
42
 
43
43
  def logger
44
- @logger ||= if defined?(Rails)
45
- Rails.logger
46
- else
47
- Logger.new(STDOUT)
48
- end
44
+ @logger ||= defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
49
45
  end
50
46
 
51
47
  def logger=(l)
@@ -1,8 +1,13 @@
1
1
  namespace :announce do
2
2
 
3
3
  desc 'Configure the broker destinations'
4
- task :configure_broker => [:environment] do |t, args|
4
+ task configure_broker: [:environment] do
5
5
  Announce.configure
6
6
  Announce.configure_broker
7
7
  end
8
+
9
+ task verify_config: [:environment] do
10
+ Announce.configure
11
+ Announce.configure_broker(verify_only: true)
12
+ end
8
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: announce
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kuklewicz
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-05-15 00:00:00.000000000 Z
11
+ date: 2021-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: shoryuken
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: 2.0.5
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
26
+ version: 2.0.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: listen
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 3.2.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 3.2.0
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: guard-minitest
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -181,13 +195,14 @@ files:
181
195
  - lib/announce/publisher.rb
182
196
  - lib/announce/railtie.rb
183
197
  - lib/announce/subscriber.rb
198
+ - lib/announce/testing.rb
184
199
  - lib/announce/version.rb
185
200
  - lib/tasks/announce.rake
186
201
  homepage: https://github.com/PRX/announce
187
202
  licenses:
188
203
  - MIT
189
204
  metadata: {}
190
- post_install_message:
205
+ post_install_message:
191
206
  rdoc_options: []
192
207
  require_paths:
193
208
  - lib
@@ -202,9 +217,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
202
217
  - !ruby/object:Gem::Version
203
218
  version: '0'
204
219
  requirements: []
205
- rubyforge_project:
206
- rubygems_version: 2.2.3
207
- signing_key:
220
+ rubyforge_project:
221
+ rubygems_version: 2.5.1
222
+ signing_key:
208
223
  specification_version: 4
209
224
  summary: Announce is for pubsub of messages
210
225
  test_files: []