la_gear 1.0.0 → 1.0.1

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: c9032fff24daef2ea6715eea71af92dd857df1ba
4
- data.tar.gz: 796b9f276b8c9a10cd8b00246bcd28f1c4ad3b9d
3
+ metadata.gz: b62e4d929c376e9f9cd7c5ca3d392cbd5e12bb4c
4
+ data.tar.gz: 768d2fd1ebe3ea28b79c2c44c7204117d6ae72ef
5
5
  SHA512:
6
- metadata.gz: 555b893cbe1b96557ec9f287031eee4862c68c6f65942996d2a70dc9e723ee89a3326354ce4fcd789a7dd8485964a893a27d2a135b13f84fc5da3e187c12c3e1
7
- data.tar.gz: 6c6f996560da05964ac20ae75afe5b402c0b7d3d79aa5cddf774ce2839030acde384b5012a51aedb339d2c6870c97ec1a4b431e7778ad632a3e9193b6f8efd85
6
+ metadata.gz: be2c62218f88ca5aa12080f6aacc453b52e87191ce4db8f2056a21239a269d01bc511bc1142d2beda7ce2127ba3cf1f29b6f09c18eab268ba2f7e436626a719e
7
+ data.tar.gz: dce9d6675fde75df927ee0a4307b30cf6eba2c3d2933b677254655e54d5b730f70d361419f2cafc4c7754f5abcf1c9d246d2ffe11c9a975f093ad833a6d6f225
data/la_gear.gemspec CHANGED
@@ -18,8 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
  spec.add_dependency 'json', '~> 1.8'
21
- spec.add_dependency 'bunny', '~> 1.6.3'
22
- spec.add_dependency 'sneakers', '~> 1.0'
21
+ spec.add_dependency 'bunny', '~> 1.6'
22
+ spec.add_dependency 'sneakers', '~> 1.0.4'
23
23
  spec.add_dependency 'activesupport', '~> 4.2'
24
24
  spec.add_dependency 'sidekiq', '~> 3.3'
25
25
  spec.add_dependency 'connection_pool', '~> 2.1'
@@ -0,0 +1,121 @@
1
+ module LaGear
2
+ module Sneakers
3
+ module Handlers
4
+ class ExponentialBackoff
5
+ def initialize(channel, _queue, opts)
6
+ @channel = channel
7
+ @opts = opts
8
+
9
+ exchange = @opts.fetch(:exchange)
10
+ @handler_opts = @opts.fetch(:handler_opts, {})
11
+
12
+ retry_name = @handler_opts.fetch(:retryexchange, "#{exchange}.retry")
13
+ error_name = @handler_opts.fetch(:errorexchange, "#{exchange}.error")
14
+
15
+ @publish_channel = setup_publish_channel
16
+ @retry_exchange = setup_retry(@publish_channel, retry_name, exchange)
17
+ @error_exchange = setup_error(@publish_channel, error_name)
18
+
19
+ @max_retries = @handler_opts.fetch(:max_retries, 5)
20
+ @expiration = @handler_opts.fetch(:expiration, 1000)
21
+ end
22
+
23
+ def acknowledge(hdr)
24
+ @channel.acknowledge(hdr.delivery_tag, false)
25
+ end
26
+
27
+ def reject(hdr, props, msg, _requeue = false)
28
+ retry_or_error(hdr, props, msg, "rejected")
29
+ end
30
+
31
+ def error(hdr, props, msg, err)
32
+ retry_or_error(hdr, props, msg, err)
33
+ end
34
+
35
+ def timeout(hdr, props, msg)
36
+ error(hdr, props, msg, "Timeout: Sneakers worker timedout.")
37
+ end
38
+
39
+ def noop(_hdr); end
40
+
41
+ private
42
+
43
+ def retry_or_error(hdr, props, msg, reason, _requeue=false)
44
+ retries = get_retries(props[:headers])
45
+ if retries >= @max_retries
46
+ @error_exchange.publish(
47
+ msg,
48
+ routing_key: @handler_opts.fetch(:routing_key, hdr.routing_key),
49
+ headers: { "sneakers-error-reason" => (reason || "Doh! No reason given. :(").inspect }
50
+ )
51
+ else
52
+ expire_delay = get_expire_delay(retries)
53
+
54
+ @retry_exchange.publish(msg,
55
+ routing_key: @handler_opts.fetch(:routing_key, hdr.routing_key),
56
+ expiration: expire_delay,
57
+ headers: {
58
+ "sneakers-retries" => retries + 1,
59
+ "sneakers-retry-reason" => (reason || "Doh! No reason given.").inspect
60
+ })
61
+ end
62
+ @channel.acknowledge(hdr.delivery_tag, false)
63
+ rescue => e
64
+ logger.fatal "#{self} #{e}, hdr.routing_key #{hdr.routing_key}, props #{props}, msg #{msg}, reason #{reason}, handler_opts #{@handler_opts}, retries #{retries}"
65
+ end
66
+
67
+ def setup_retry(publish_channel, retry_name, exchange)
68
+ retry_exchange = publish_channel.exchange(retry_name,
69
+ type: "topic",
70
+ durable: "true")
71
+ retry_queue = publish_channel.queue(retry_name,
72
+ durable: "true",
73
+ arguments: {
74
+ :"x-dead-letter-exchange" => exchange,
75
+ })
76
+ retry_queue.bind(retry_exchange, routing_key: "#")
77
+ trace(retry_queue, "#{self} retry queue created.")
78
+ retry_exchange
79
+ end
80
+
81
+ def setup_error(publish_channel, error_name)
82
+ error_exchange = publish_channel.exchange(error_name,
83
+ type: "topic",
84
+ durable: "true")
85
+ error_queue = publish_channel.queue(error_name, durable: "true")
86
+ error_queue.bind(error_exchange, routing_key: "#")
87
+ trace(error_queue, "#{self} error queue created.")
88
+ error_exchange
89
+ end
90
+
91
+ def setup_publish_channel
92
+ return @channel unless @opts.to_hash.include?(:amqp_publish)
93
+ publish_bunny = Bunny.new(@opts[:amqp_publish], vhost: @opts[:vhost], heartbeat: @opts[:heartbeat])
94
+ publish_bunny.start
95
+ publish_channel = publish_bunny.create_channel
96
+ publish_channel.prefetch(@opts[:prefetch])
97
+ logger.warn "#{self} publish endpoint used: #{@opts[:amqp_publish]}, vhost #{@opts[:vhost]}"
98
+ publish_channel
99
+ end
100
+
101
+ def trace(queue, msg)
102
+ logger.debug "[#{Thread.current}][#{queue.name}][#{queue.options}] #{msg}"
103
+ end
104
+
105
+ def logger
106
+ ::Sneakers.logger
107
+ end
108
+
109
+ def get_expire_delay(failures = 0)
110
+ failures = failures.to_i + 1
111
+ @expiration * (2**failures)
112
+ end
113
+
114
+ def get_retries(headers)
115
+ headers ||= {}
116
+ headers.fetch("sneakers-retries", 0).to_i
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,39 @@
1
+ $: << File.expand_path('../lib', File.dirname(__FILE__))
2
+
3
+ require 'sneakers'
4
+ require 'sneakers/runner'
5
+ require_relative 'exponential_backoff'
6
+ require 'logger'
7
+
8
+ Sneakers.configure(handler: LaGear::Sneakers::Handlers::ExponentialBackoff, workers: 1, threads: 1, prefetch: 1)
9
+ Sneakers.logger.level = Logger::INFO
10
+
11
+ class ExponentialBackoffWorker
12
+ include Sneakers::Worker
13
+ from_queue 'sneakers',
14
+ ack: true,
15
+ threads: 1,
16
+ prefetch: 1,
17
+ timeout_job_after: 60,
18
+ exchange: "sneakers",
19
+ heartbeat: 5,
20
+ arguments: {
21
+ :"x-dead-letter-exchange" => "sneakers-retry"
22
+ }
23
+
24
+ def work(msg)
25
+ puts "Got message #{msg} and rejecting now"
26
+
27
+ return reject!
28
+ end
29
+ end
30
+
31
+ messages = 1
32
+ puts "Feeding messages in"
33
+
34
+ messages.times { ExponentialBackoffWorker.enqueue("{}") }
35
+
36
+ puts "Done"
37
+
38
+ r = Sneakers::Runner.new([ExponentialBackoffWorker])
39
+ r.run
@@ -0,0 +1 @@
1
+ require "la_gear/sneakers/exponential_backoff"
@@ -1,3 +1,3 @@
1
1
  module LaGear
2
- VERSION = '1.0.0'
2
+ VERSION = '1.0.1'
3
3
  end
@@ -23,7 +23,7 @@ module LaGear
23
23
 
24
24
  module SneakersClassMethods
25
25
  def default_queue_name
26
- "#{Sneakers::Config.fetch(:app_name, 'sneakers_app').underscore}.#{routing_key}"
26
+ "#{Sneakers::CONFIG.fetch(:app_name, 'sneakers_app').underscore}.#{routing_key}"
27
27
  end
28
28
 
29
29
  def default_queue_opts
@@ -46,7 +46,7 @@ module LaGear
46
46
  end
47
47
 
48
48
  def default_queue_args
49
- { 'x-dead-letter-exchange' => "#{Sneakers::Config.fetch(:exchange, 'sneakers').underscore}.retry" }
49
+ { 'x-dead-letter-exchange' => "#{Sneakers::CONFIG.fetch(:exchange, 'sneakers').underscore}.retry" }
50
50
  end
51
51
  end
52
52
 
data/lib/la_gear.rb CHANGED
@@ -6,6 +6,7 @@ require 'bunny'
6
6
 
7
7
  require 'sneakers'
8
8
  require 'sneakers/worker'
9
+ require "la_gear/sneakers"
9
10
  require 'la_gear/worker'
10
11
  require 'la_gear/publisher'
11
12
  require 'la_gear/bus'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: la_gear
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriel Chaney
@@ -32,28 +32,28 @@ dependencies:
32
32
  requirements:
33
33
  - - "~>"
34
34
  - !ruby/object:Gem::Version
35
- version: 1.6.3
35
+ version: '1.6'
36
36
  type: :runtime
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
40
  - - "~>"
41
41
  - !ruby/object:Gem::Version
42
- version: 1.6.3
42
+ version: '1.6'
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: sneakers
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - "~>"
48
48
  - !ruby/object:Gem::Version
49
- version: '1.0'
49
+ version: 1.0.4
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
54
  - - "~>"
55
55
  - !ruby/object:Gem::Version
56
- version: '1.0'
56
+ version: 1.0.4
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: activesupport
59
59
  requirement: !ruby/object:Gem::Requirement
@@ -134,6 +134,9 @@ files:
134
134
  - lib/la_gear/bus.rb
135
135
  - lib/la_gear/engine.rb
136
136
  - lib/la_gear/publisher.rb
137
+ - lib/la_gear/sneakers.rb
138
+ - lib/la_gear/sneakers/exponential_backoff.rb
139
+ - lib/la_gear/sneakers/exponential_backoff_handler.rb
137
140
  - lib/la_gear/sneakers_configurer.rb
138
141
  - lib/la_gear/uri_parser.rb
139
142
  - lib/la_gear/version.rb