sneakers_exponential_retry 0.1.0 → 0.2.0

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
  SHA1:
3
- metadata.gz: af906d8bafee5024ee77370c828d92a22628ecdc
4
- data.tar.gz: 20a9007c85f5317d311f65a9a4f7a4988aebe6ae
3
+ metadata.gz: 383c16547be12323af1e50d4a68895cf6b9b0468
4
+ data.tar.gz: 4791aa18b3aa580856516226dc6bf5f440e281d3
5
5
  SHA512:
6
- metadata.gz: a6df19505aeff4c55d4c13d32686543da6ad73a4ee4b2fe2ac7de38eb44c911c8b2becf996acbc01e31ac6734b3c98a4a43b184bfe1ab2b5d00d020cb7b5a9c0
7
- data.tar.gz: f6ec2b59258761e81d0ca4f378762aa6129f278fcde47204ddd0b07c132dc4ae74ac1466730f0bd223dfec7752ae5c691fade4e74444bc9ab7a52c9fe4916037
6
+ metadata.gz: f33ce2504df5dc2bf284dbb38aa45a9605f5146e95915439ecb91f4eaac3315303da7ef6692e6cd7ad13bdc28963569bae827f295a63f3c99269eb5f818c7ab0
7
+ data.tar.gz: d8597d129e0a9bb472dec754f6181f1a13956204444dc3c7df3b0cf58941fbb404a349cc5b76b947a1680ebc1058a7474d345b8d31d9d4b5ad441adbec7bdbd3
data/README.md CHANGED
@@ -2,22 +2,6 @@
2
2
 
3
3
  Exponential Retry Handler for [Sneakers](https://github.com/jondot/sneakers) that just works.
4
4
 
5
- ## Installation
6
-
7
- Add this line to your application's Gemfile:
8
-
9
- ```ruby
10
- gem 'sneakers_exponential_retry'
11
- ```
12
-
13
- And then execute:
14
-
15
- $ bundle
16
-
17
- Or install it yourself as:
18
-
19
- $ gem install sneakers_exponential_retry
20
-
21
5
  ## Usage
22
6
 
23
7
  Configure your Sneakers by the following:
@@ -25,7 +9,7 @@ Configure your Sneakers by the following:
25
9
  ```ruby
26
10
  require 'sneakers_exponential_retry'
27
11
 
28
- Sneakers.configure :handler => SneakersExponentialRetry,
12
+ Sneakers.configure :handler => SneakersExponentialRetry::Handler,
29
13
  :handler_options => {
30
14
  :max_retry_count => 3,
31
15
  :logger => Sneakers.logger
@@ -41,9 +25,44 @@ Sneakers.configure :handler => SneakersExponentialRetry,
41
25
  - `max_retry_count`: (optional) Max retry count, default to 14
42
26
  - `logger`: (optional) logger instance, default to nil, which would not log anything related to retrying.
43
27
 
28
+
29
+ ## Installation
30
+
31
+ Add this line to your application's Gemfile:
32
+
33
+ ```ruby
34
+ gem 'sneakers_exponential_retry'
35
+ ```
36
+
37
+ And then execute:
38
+
39
+ $ bundle
40
+
41
+ Or install it yourself as:
42
+
43
+ $ gem install sneakers_exponential_retry
44
+
45
+
44
46
  ## How it works:
45
47
 
46
- TODO
48
+ (`SneakersExponentialRetry` is inspired by [this blogpost](https://gagnechris.wordpress.com/2015/09/19/easy-retries-with-rabbitmq/))
49
+
50
+ `SneakersExponentialRetry` handles the behavior of retrying failed jobs exponentially by:
51
+
52
+ 1. On initializing:
53
+ - Create a retry exchange, which is named as `#{queue_name}-retry-ex`
54
+ - Create a retry queue, which is named as `#{queue_name}-retry-queue`
55
+ - Set the `x-dead-letter-exchange` of retry queue to the original job exchange
56
+ - Bind the retry queue to the retry exchange
57
+
58
+ 2. Whenever a job fails, `SneakersExponentialRetry` would:
59
+ - if retry count <= `max_retry_count`
60
+ - publish the job to retry exchange, with an exponential expiration timeout
61
+ - the retry exchange would push the job into our retry queue
62
+ - after the timeout, the job would be published back to the `dead-letter-exchange` of the retry queue, which is our original exchange, so that the job would be retried
63
+
64
+ - if retry count > `max_retry_count`
65
+ - reject the job
47
66
 
48
67
  ## Testing:
49
68
 
@@ -1,97 +1,100 @@
1
1
  require "sneakers_exponential_retry/version"
2
2
 
3
- class ExponentialRetry
4
- MINUTE = 60 * 1000
5
- DEFAULT_MAX_RETRY_COUNT = 14
6
-
7
- def initialize(channel, queue, opts)
8
- @channel = channel
9
- @max_retry_count = calculate_max_retry_count(opts)
10
- @retry_exchange = create_retry_exchange(queue.name)
11
- @logger = opts[:handler_options] ? opts[:handler_options][:logger] : nil
12
-
13
- create_retry_queue(queue.name, opts[:exchange])
14
- .bind(@retry_exchange, :routing_key => '#')
15
- end
16
-
17
- def calculate_max_retry_count opts
18
- handler_options = opts[:handler_options] || {}
19
- ( handler_options[:max_retry_count] || DEFAULT_MAX_RETRY_COUNT ).to_i
20
- end
21
- private :calculate_max_retry_count
22
-
23
- def create_retry_exchange queue_name
24
- @channel.exchange("#{queue_name}-retry-ex",
25
- :type => 'topic',
26
- :durable => true)
27
- end
28
- private :create_retry_exchange
29
-
30
- def create_retry_queue queue_name, exchange_name
31
- @channel.queue(
32
- "#{queue_name}-retry-queue",
33
- durable: true,
34
- arguments: {
35
- :'x-dead-letter-exchange' => exchange_name
36
- }
37
- )
38
- end
39
- private :create_retry_queue
3
+ module SneakersExponentialRetry
4
+ class Handler
5
+ MINUTE = 60 * 1000
6
+ DEFAULT_MAX_RETRY_COUNT = 14
7
+
8
+ def initialize(channel, queue, opts)
9
+ @channel = channel
10
+ @max_retry_count = calculate_max_retry_count(opts)
11
+ @retry_exchange = create_retry_exchange(queue.name)
12
+ @logger = opts[:handler_options] ? opts[:handler_options][:logger] : nil
13
+
14
+ create_retry_queue(queue.name, opts[:exchange])
15
+ .bind(@retry_exchange, :routing_key => '#')
16
+ end
40
17
 
41
- def acknowledge(hdr, props, msg)
42
- @channel.acknowledge(hdr.delivery_tag, false)
43
- end
18
+ def calculate_max_retry_count opts
19
+ handler_options = opts[:handler_options] || {}
20
+ ( handler_options[:max_retry_count] || DEFAULT_MAX_RETRY_COUNT ).to_i
21
+ end
22
+ private :calculate_max_retry_count
44
23
 
45
- def reject(hdr, props, msg, requeue=false)
46
- @channel.reject(hdr.delivery_tag, requeue)
47
- end
24
+ def create_retry_exchange queue_name
25
+ @channel.exchange("#{queue_name}-retry-ex",
26
+ :type => 'topic',
27
+ :durable => true)
28
+ end
29
+ private :create_retry_exchange
30
+
31
+ def create_retry_queue queue_name, exchange_name
32
+ @channel.queue(
33
+ "#{queue_name}-retry-queue",
34
+ durable: true,
35
+ arguments: {
36
+ :'x-dead-letter-exchange' => exchange_name
37
+ }
38
+ )
39
+ end
40
+ private :create_retry_queue
48
41
 
49
- def error(hdr, props, msg, err)
50
- handle_failing_message(hdr, props, msg, err)
51
- end
42
+ def acknowledge(hdr, props, msg)
43
+ @channel.acknowledge(hdr.delivery_tag, false)
44
+ end
52
45
 
53
- def handle_failing_message hdr, props, msg, error
54
- retry_count = get_retry_count(props[:headers])
55
- if retry_count >= @max_retry_count
56
- reject(hdr, props, msg)
57
- return
46
+ def reject(hdr, props, msg, requeue=false)
47
+ @channel.reject(hdr.delivery_tag, requeue)
58
48
  end
59
49
 
50
+ def error(hdr, props, msg, err)
51
+ handle_failing_message(hdr, props, msg, err)
52
+ end
60
53
 
61
- @retry_exchange.publish(msg,
62
- :headers => {
63
- 'retry-count' => retry_count + 1
64
- },
65
- :routing_key => hdr.routing_key,
66
- :expiration => expiration_time(retry_count))
67
- log_retry(retry_count)
68
- acknowledge(hdr, props, msg)
69
- end
70
- private :handle_failing_message
54
+ def handle_failing_message hdr, props, msg, error
55
+ retry_count = get_retry_count(props[:headers])
56
+ if retry_count >= @max_retry_count
57
+ reject(hdr, props, msg)
58
+ return
59
+ end
60
+
61
+
62
+ @retry_exchange.publish(msg,
63
+ :headers => {
64
+ 'retry-count' => retry_count + 1
65
+ },
66
+ :routing_key => hdr.routing_key,
67
+ :expiration => expiration_time(retry_count))
68
+ log_retry(retry_count)
69
+ acknowledge(hdr, props, msg)
70
+ end
71
+ private :handle_failing_message
71
72
 
72
- def log_retry count
73
- return unless @logger
74
- @logger.info do
75
- "retry_count: #{count + 1}"
73
+ def log_retry count
74
+ return unless @logger
75
+ @logger.info do
76
+ "retry_count: #{count + 1}"
77
+ end
76
78
  end
77
- end
78
- private :log_retry
79
+ private :log_retry
79
80
 
80
- def get_retry_count headers
81
- return 0 unless headers
82
- headers['retry-count'].to_i
83
- end
84
- private :get_retry_count
81
+ def get_retry_count headers
82
+ return 0 unless headers
83
+ headers['retry-count'].to_i
84
+ end
85
+ private :get_retry_count
85
86
 
86
- def expiration_time retry_count
87
- (2 ** retry_count) * MINUTE
88
- end
89
- private :expiration_time
87
+ def expiration_time retry_count
88
+ (2 ** retry_count) * MINUTE
89
+ end
90
+ private :expiration_time
90
91
 
91
- def timeout(hdr, props, msg)
92
- reject(hdr, props, msg)
93
- end
92
+ def timeout(hdr, props, msg)
93
+ reject(hdr, props, msg)
94
+ end
94
95
 
95
- def noop(hdr, props, msg)
96
+ def noop(hdr, props, msg)
97
+ end
96
98
  end
97
99
  end
100
+
@@ -1,3 +1,3 @@
1
1
  module SneakersExponentialRetry
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sneakers_exponential_retry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yang-Hsing Lin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-18 00:00:00.000000000 Z
11
+ date: 2016-09-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler