circuitry 2.1.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/README.md +107 -59
  4. data/circuitry.gemspec +2 -2
  5. data/lib/circuitry.rb +32 -15
  6. data/lib/circuitry/cli.rb +32 -32
  7. data/lib/circuitry/config/file_loader.rb +24 -0
  8. data/lib/circuitry/config/publisher_settings.rb +16 -0
  9. data/lib/circuitry/config/shared_settings.rb +39 -0
  10. data/lib/circuitry/config/subscriber_settings.rb +32 -0
  11. data/lib/circuitry/locks/base.rb +3 -3
  12. data/lib/circuitry/locks/memory.rb +4 -4
  13. data/lib/circuitry/locks/noop.rb +1 -1
  14. data/lib/circuitry/locks/redis.rb +1 -1
  15. data/lib/circuitry/middleware/chain.rb +1 -1
  16. data/lib/circuitry/processor.rb +12 -10
  17. data/lib/circuitry/processors/forker.rb +1 -1
  18. data/lib/circuitry/processors/threader.rb +1 -1
  19. data/lib/circuitry/provisioning.rb +9 -0
  20. data/lib/circuitry/provisioning/provisioner.rb +71 -0
  21. data/lib/circuitry/provisioning/queue_creator.rb +64 -0
  22. data/lib/circuitry/provisioning/subscription_creator.rb +65 -0
  23. data/lib/circuitry/provisioning/topic_creator.rb +31 -0
  24. data/lib/circuitry/publisher.rb +5 -6
  25. data/lib/circuitry/queue.rb +25 -3
  26. data/lib/circuitry/railtie.rb +9 -0
  27. data/lib/circuitry/services/sns.rb +1 -1
  28. data/lib/circuitry/services/sqs.rb +1 -1
  29. data/lib/circuitry/subscriber.rb +8 -8
  30. data/lib/circuitry/tasks.rb +3 -3
  31. data/lib/circuitry/topic.rb +24 -2
  32. data/lib/circuitry/version.rb +1 -1
  33. metadata +11 -7
  34. data/lib/circuitry/configuration.rb +0 -64
  35. data/lib/circuitry/provisioner.rb +0 -60
  36. data/lib/circuitry/queue_creator.rb +0 -50
  37. data/lib/circuitry/subscription_creator.rb +0 -60
  38. data/lib/circuitry/topic_creator.rb +0 -25
@@ -0,0 +1,31 @@
1
+ require 'circuitry/services/sns'
2
+ require 'circuitry/topic'
3
+
4
+ module Circuitry
5
+ module Provisioning
6
+ class TopicCreator
7
+ include Services::SNS
8
+
9
+ attr_reader :topic_name
10
+
11
+ def self.find_or_create(topic_name)
12
+ new(topic_name).topic
13
+ end
14
+
15
+ def initialize(topic_name)
16
+ self.topic_name = topic_name
17
+ end
18
+
19
+ def topic
20
+ return @_topic if defined?(@_topic)
21
+
22
+ response = sns.create_topic(name: topic_name)
23
+ @_topic = Topic.new(response.topic_arn)
24
+ end
25
+
26
+ private
27
+
28
+ attr_writer :topic_name
29
+ end
30
+ end
31
+ end
@@ -2,7 +2,6 @@ require 'json'
2
2
  require 'timeout'
3
3
  require 'circuitry/concerns/async'
4
4
  require 'circuitry/services/sns'
5
- require 'circuitry/topic_creator'
6
5
 
7
6
  module Circuitry
8
7
  class PublishError < StandardError; end
@@ -40,7 +39,7 @@ module Circuitry
40
39
  end
41
40
 
42
41
  def self.default_async_strategy
43
- Circuitry.config.publish_async_strategy
42
+ Circuitry.publisher_config.async_strategy
44
43
  end
45
44
 
46
45
  protected
@@ -52,7 +51,7 @@ module Circuitry
52
51
  Timeout.timeout(timeout) do
53
52
  logger.info("Publishing message to #{topic_name}")
54
53
 
55
- topic = TopicCreator.find_or_create(topic_name)
54
+ topic = Topic.find(topic_name)
56
55
  sns.publish(topic_arn: topic.arn, message: message)
57
56
  end
58
57
  end
@@ -63,17 +62,17 @@ module Circuitry
63
62
  private
64
63
 
65
64
  def logger
66
- Circuitry.config.logger
65
+ Circuitry.publisher_config.logger
67
66
  end
68
67
 
69
68
  def can_publish?
70
- Circuitry.config.aws_options.values.all? do |value|
69
+ Circuitry.publisher_config.aws_options.values.all? do |value|
71
70
  !value.nil? && !value.empty?
72
71
  end
73
72
  end
74
73
 
75
74
  def middleware
76
- Circuitry.config.publisher_middleware
75
+ Circuitry.publisher_config.middleware
77
76
  end
78
77
  end
79
78
  end
@@ -4,10 +4,30 @@ module Circuitry
4
4
  class Queue
5
5
  include Services::SQS
6
6
 
7
+ class Finder
8
+ include Services::SQS
9
+
10
+ def initialize(name)
11
+ self.name = name
12
+ end
13
+
14
+ def find
15
+ sqs.get_queue_url(queue_name: name)
16
+ end
17
+
18
+ private
19
+
20
+ attr_accessor :name
21
+ end
22
+
7
23
  attr_reader :url
8
24
 
9
25
  def initialize(url)
10
- @url = url
26
+ self.url = url
27
+ end
28
+
29
+ def self.find(name)
30
+ new(Finder.new(name).find.queue_url)
11
31
  end
12
32
 
13
33
  def name
@@ -18,10 +38,12 @@ module Circuitry
18
38
  @arn ||= attribute('QueueArn')
19
39
  end
20
40
 
21
- private
22
-
23
41
  def attribute(name)
24
42
  sqs.get_queue_attributes(queue_url: url, attribute_names: [name]).attributes[name]
25
43
  end
44
+
45
+ private
46
+
47
+ attr_writer :url
26
48
  end
27
49
  end
@@ -1,9 +1,18 @@
1
1
  require 'rails'
2
+ require 'circuitry/config/file_loader'
2
3
 
3
4
  module Circuitry
4
5
  class Railtie < Rails::Railtie
5
6
  rake_tasks do
6
7
  load 'circuitry/tasks.rb'
7
8
  end
9
+
10
+ initializer 'circuitry' do
11
+ env = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
12
+
13
+ %w[config/circuitry.yml.erb config/circuitry.yml].detect do |filename|
14
+ Circuitry::Config::FileLoader.load(filename, env)
15
+ end
16
+ end
8
17
  end
9
18
  end
@@ -4,7 +4,7 @@ module Circuitry
4
4
  module Services
5
5
  module SNS
6
6
  def sns
7
- @sns ||= Aws::SNS::Client.new(Circuitry.config.aws_options)
7
+ @sns ||= Aws::SNS::Client.new(Circuitry.publisher_config.aws_options)
8
8
  end
9
9
  end
10
10
  end
@@ -4,7 +4,7 @@ module Circuitry
4
4
  module Services
5
5
  module SQS
6
6
  def sqs
7
- @sqs ||= Aws::SQS::Client.new(Circuitry.config.aws_options)
7
+ @sqs ||= Aws::SQS::Client.new(Circuitry.subscriber_config.aws_options)
8
8
  end
9
9
  end
10
10
  end
@@ -1,9 +1,9 @@
1
1
  require 'retries'
2
2
  require 'timeout'
3
- require 'circuitry/queue_creator'
4
3
  require 'circuitry/concerns/async'
5
4
  require 'circuitry/services/sqs'
6
5
  require 'circuitry/message'
6
+ require 'circuitry/queue'
7
7
 
8
8
  module Circuitry
9
9
  class SubscribeError < StandardError; end
@@ -30,8 +30,8 @@ module Circuitry
30
30
  options = DEFAULT_OPTIONS.merge(options)
31
31
 
32
32
  self.subscribed = false
33
+ self.queue = Queue.find(Circuitry.subscriber_config.queue_name).url
33
34
 
34
- self.queue = QueueCreator.find_or_create(Circuitry.config.subscriber_queue_name).url
35
35
  %i[lock async timeout wait_time batch_size].each do |sym|
36
36
  send(:"#{sym}=", options[sym])
37
37
  end
@@ -64,7 +64,7 @@ module Circuitry
64
64
  end
65
65
 
66
66
  def self.default_async_strategy
67
- Circuitry.config.subscribe_async_strategy
67
+ Circuitry.subscriber_config.async_strategy
68
68
  end
69
69
 
70
70
  protected
@@ -74,7 +74,7 @@ module Circuitry
74
74
 
75
75
  def lock=(value)
76
76
  value = case value
77
- when true then Circuitry.config.lock_strategy
77
+ when true then Circuitry.subscriber_config.lock_strategy
78
78
  when false then Circuitry::Locks::NOOP.new
79
79
  when Circuitry::Locks::Base then value
80
80
  else raise ArgumentError, lock_value_error(value)
@@ -181,21 +181,21 @@ module Circuitry
181
181
  end
182
182
 
183
183
  def logger
184
- Circuitry.config.logger
184
+ Circuitry.subscriber_config.logger
185
185
  end
186
186
 
187
187
  def error_handler
188
- Circuitry.config.error_handler
188
+ Circuitry.subscriber_config.error_handler
189
189
  end
190
190
 
191
191
  def can_subscribe?
192
- Circuitry.config.aws_options.values.all? do |value|
192
+ Circuitry.subscriber_config.aws_options.values.all? do |value|
193
193
  !value.nil? && !value.empty?
194
194
  end
195
195
  end
196
196
 
197
197
  def middleware
198
- Circuitry.config.subscriber_middleware
198
+ Circuitry.subscriber_config.middleware
199
199
  end
200
200
  end
201
201
  end
@@ -1,11 +1,11 @@
1
1
  namespace :circuitry do
2
2
  desc 'Create subscriber queues and subscribe queue to topics'
3
3
  task setup: :environment do
4
- require 'circuitry/provisioner'
5
-
4
+ require 'circuitry/provisioning'
5
+
6
6
  logger = Logger.new(STDOUT)
7
7
  logger.level = Logger::INFO
8
8
 
9
- Circuitry::Provisioner.new(Circuitry.config, logger: logger).run
9
+ Circuitry::Provisioning.provision(logger: logger)
10
10
  end
11
11
  end
@@ -1,17 +1,39 @@
1
+ require 'circuitry/services/sns'
2
+
1
3
  module Circuitry
2
4
  class Topic
5
+ class Finder
6
+ include Services::SNS
7
+
8
+ def initialize(name)
9
+ self.name = name
10
+ end
11
+
12
+ def find
13
+ sns.create_topic(name: name)
14
+ end
15
+
16
+ private
17
+
18
+ attr_accessor :name
19
+ end
20
+
3
21
  attr_reader :arn
4
22
 
5
23
  def initialize(arn)
6
24
  @arn = arn
7
25
  end
8
26
 
27
+ def self.find(name)
28
+ new(Finder.new(name).find.topic_arn)
29
+ end
30
+
9
31
  def name
10
32
  @name ||= arn.split(':').last
11
33
  end
12
34
 
13
- def ==(obj)
14
- obj.hash == self.hash
35
+ def ==(other)
36
+ other.hash == hash
15
37
  end
16
38
 
17
39
  def hash
@@ -1,3 +1,3 @@
1
1
  module Circuitry
2
- VERSION = '2.1.1'
2
+ VERSION = '3.0.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: circuitry
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Huggins
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2016-01-30 00:00:00.000000000 Z
12
+ date: 2016-02-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aws-sdk
@@ -247,7 +247,10 @@ files:
247
247
  - lib/circuitry.rb
248
248
  - lib/circuitry/cli.rb
249
249
  - lib/circuitry/concerns/async.rb
250
- - lib/circuitry/configuration.rb
250
+ - lib/circuitry/config/file_loader.rb
251
+ - lib/circuitry/config/publisher_settings.rb
252
+ - lib/circuitry/config/shared_settings.rb
253
+ - lib/circuitry/config/subscriber_settings.rb
251
254
  - lib/circuitry/locks/base.rb
252
255
  - lib/circuitry/locks/memcache.rb
253
256
  - lib/circuitry/locks/memory.rb
@@ -260,18 +263,19 @@ files:
260
263
  - lib/circuitry/processors/batcher.rb
261
264
  - lib/circuitry/processors/forker.rb
262
265
  - lib/circuitry/processors/threader.rb
263
- - lib/circuitry/provisioner.rb
266
+ - lib/circuitry/provisioning.rb
267
+ - lib/circuitry/provisioning/provisioner.rb
268
+ - lib/circuitry/provisioning/queue_creator.rb
269
+ - lib/circuitry/provisioning/subscription_creator.rb
270
+ - lib/circuitry/provisioning/topic_creator.rb
264
271
  - lib/circuitry/publisher.rb
265
272
  - lib/circuitry/queue.rb
266
- - lib/circuitry/queue_creator.rb
267
273
  - lib/circuitry/railtie.rb
268
274
  - lib/circuitry/services/sns.rb
269
275
  - lib/circuitry/services/sqs.rb
270
276
  - lib/circuitry/subscriber.rb
271
- - lib/circuitry/subscription_creator.rb
272
277
  - lib/circuitry/tasks.rb
273
278
  - lib/circuitry/topic.rb
274
- - lib/circuitry/topic_creator.rb
275
279
  - lib/circuitry/version.rb
276
280
  homepage: https://github.com/kapost/circuitry
277
281
  licenses:
@@ -1,64 +0,0 @@
1
- require 'logger'
2
- require 'virtus'
3
-
4
- module Circuitry
5
- class Configuration
6
- include Virtus::Model
7
-
8
- attribute :subscriber_queue_name, String
9
- attribute :subscriber_dead_letter_queue_name, String
10
- attribute :publisher_topic_names, Array[String]
11
-
12
- attribute :access_key, String
13
- attribute :secret_key, String
14
- attribute :region, String, default: 'us-east-1'
15
- attribute :logger, Logger, default: Logger.new(STDERR)
16
- attribute :error_handler
17
- attribute :lock_strategy, Object, default: ->(_page, _attribute) { Circuitry::Locks::Memory.new }
18
- attribute :publish_async_strategy, Symbol, default: ->(_page, _attribute) { :fork }
19
- attribute :subscribe_async_strategy, Symbol, default: ->(_page, _attribute) { :fork }
20
- attribute :on_thread_exit
21
- attribute :on_fork_exit
22
-
23
- def publish_async_strategy=(value)
24
- validate(value, Publisher.async_strategies)
25
- super
26
- end
27
-
28
- def subscribe_async_strategy=(value)
29
- validate(value, Subscriber.async_strategies)
30
- super
31
- end
32
-
33
- def subscriber_dead_letter_queue_name
34
- super || "#{subscriber_queue_name}-failures"
35
- end
36
-
37
- def subscriber_middleware
38
- @subscriber_middleware ||= Circuitry::Middleware::Chain.new
39
- yield @subscriber_middleware if block_given?
40
- @subscriber_middleware
41
- end
42
-
43
- def publisher_middleware
44
- @publisher_middleware ||= Circuitry::Middleware::Chain.new
45
- yield @publisher_middleware if block_given?
46
- @publisher_middleware
47
- end
48
-
49
- def aws_options
50
- {
51
- access_key_id: access_key,
52
- secret_access_key: secret_key,
53
- region: region
54
- }
55
- end
56
-
57
- private
58
-
59
- def validate(value, permitted_values)
60
- return if permitted_values.include?(value)
61
- raise ArgumentError, "invalid value `#{value}`, must be one of #{permitted_values.inspect}"
62
- end
63
- end
64
- end
@@ -1,60 +0,0 @@
1
- require 'circuitry/queue_creator'
2
- require 'circuitry/topic_creator'
3
- require 'circuitry/subscription_creator'
4
-
5
- module Circuitry
6
- class Provisioner
7
- attr_reader :config, :logger
8
-
9
- def initialize(config, logger: Logger.new(STDOUT))
10
- self.config = config
11
- self.logger = logger
12
- end
13
-
14
- def run
15
- queue = create_queue
16
- topics = create_topics if queue
17
- subscribe_topics(queue, topics) if queue && topics
18
- end
19
-
20
- private
21
-
22
- attr_writer :config, :logger
23
-
24
- def create_queue
25
- safe_aws('Create Queue') do
26
- queue = Circuitry::QueueCreator.find_or_create(
27
- config.subscriber_queue_name,
28
- dead_letter_queue_name: config.subscriber_dead_letter_queue_name
29
- )
30
- logger.info "Created queue #{queue.url}"
31
- queue
32
- end
33
- end
34
-
35
- def create_topics
36
- safe_aws('Create Topics') do
37
- config.publisher_topic_names.map do |topic_name|
38
- topic = Circuitry::TopicCreator.find_or_create(topic_name)
39
- logger.info "Created topic #{topic.name}"
40
- topic
41
- end
42
- end
43
- end
44
-
45
- def subscribe_topics(queue, topics)
46
- safe_aws('Subscribe Topics') do
47
- Circuitry::SubscriptionCreator.subscribe_all(queue, topics)
48
- logger.info "Subscribed all topics to #{queue.name}"
49
- true
50
- end
51
- end
52
-
53
- def safe_aws(desc)
54
- yield
55
- rescue Aws::SQS::Errors::AccessDenied
56
- logger.fatal("#{desc}: Access denied. Check your configured credentials.")
57
- nil
58
- end
59
- end
60
- end