sidekiq-reliable-fetch 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 +4 -4
- data/README.md +32 -0
- data/lib/sidekiq/reliable_fetcher.rb +31 -25
- data/lib/sidekiq-reliable-fetch/web.rb +0 -1
- data/sidekiq-reliable-fetch.gemspec +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 803136d2fb9cf9eb4f60b0b54618e489616d763a
|
4
|
+
data.tar.gz: 8371867f1f2ce011d710d91dd0d2a3a09ab1c739
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac47ebe55522819896e610f2b8bc59f69026d23967fe5611c32e6383c13ac14732ebd4f7d1884368ac43e967f958ff4b3441178407e2bdedbb8cecb00f9d55f8
|
7
|
+
data.tar.gz: 2a8f9651f266ddb272fbba06f149b7879b9f406f92a90ea74b09f9772048f900c147a48832dc7d47374093742281073065b72aeb2a660165e067b3eb0170d7c8
|
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
sidekiq-reliable-fetch
|
2
|
+
======================
|
3
|
+
|
4
|
+
sidekiq-reliable-fetch is an extension to Sidekiq that adds support for reliable
|
5
|
+
fetches from Redis.
|
6
|
+
|
7
|
+
It implements in Sidekiq the reliable queue pattern using [Redis' rpoplpush
|
8
|
+
command](http://redis.io/commands/rpoplpush#pattern-reliable-queue).
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add the following to your `Gemfile`:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem 'sidekiq-reliable-fetch'
|
16
|
+
```
|
17
|
+
|
18
|
+
## Configuration
|
19
|
+
|
20
|
+
Enable reliable fetches by calling this gem from your Sidekiq configuration:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
Sidekiq.configure_server do |config|
|
24
|
+
Sidekiq::ReliableFetcher.setup_reliable_fetch!(config)
|
25
|
+
|
26
|
+
# …
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
## License
|
31
|
+
|
32
|
+
LGPL-3.0, see the LICENSE file.
|
@@ -2,7 +2,8 @@ module Sidekiq
|
|
2
2
|
class ReliableFetcher
|
3
3
|
WORKING_QUEUE = 'working'
|
4
4
|
DEFAULT_DEAD_AFTER = 60 * 60 * 24 # 24 hours
|
5
|
-
DEFAULT_CLEANING_INTERVAL =
|
5
|
+
DEFAULT_CLEANING_INTERVAL = 5000 # clean each N processed jobs
|
6
|
+
IDLE_TIMEOUT = 5 # seconds
|
6
7
|
|
7
8
|
def self.setup_reliable_fetch!(config)
|
8
9
|
config.options[:fetch] = Sidekiq::ReliableFetcher
|
@@ -12,20 +13,35 @@ module Sidekiq
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def initialize(options)
|
15
|
-
|
16
|
-
|
17
|
-
@unique_queues =
|
18
|
-
@
|
16
|
+
queues = options[:queues].map { |q| "queue:#{q}" }
|
17
|
+
|
18
|
+
@unique_queues = queues.uniq
|
19
|
+
@queues_iterator = queues.shuffle.cycle
|
20
|
+
@queues_size = queues.size
|
21
|
+
|
22
|
+
@nb_fetched_jobs = 0
|
19
23
|
@cleaning_interval = options[:cleaning_interval] || DEFAULT_CLEANING_INTERVAL
|
20
24
|
@consider_dead_after = options[:consider_dead_after] || DEFAULT_DEAD_AFTER
|
21
25
|
end
|
22
26
|
|
23
27
|
def retrieve_work
|
24
|
-
clean_working_queues! if @cleaning_interval != -1 &&
|
28
|
+
clean_working_queues! if @cleaning_interval != -1 && @nb_fetched_jobs >= @cleaning_interval
|
29
|
+
|
30
|
+
for i in 0..@queues_size
|
31
|
+
queue = @queues_iterator.next
|
32
|
+
work = Sidekiq.redis { |conn| conn.rpoplpush(queue, "#{queue}:#{WORKING_QUEUE}") }
|
33
|
+
|
34
|
+
if work
|
35
|
+
@nb_fetched_jobs += 1
|
36
|
+
return UnitOfWork.new(queue, work)
|
37
|
+
end
|
38
|
+
end
|
25
39
|
|
26
|
-
|
27
|
-
|
28
|
-
|
40
|
+
# We didn't find a job in any of the configured queues. Let's sleep a bit
|
41
|
+
# to avoid uselessly burning too much CPU
|
42
|
+
sleep(IDLE_TIMEOUT)
|
43
|
+
|
44
|
+
nil
|
29
45
|
end
|
30
46
|
|
31
47
|
def self.requeue_on_startup!(queues)
|
@@ -90,16 +106,6 @@ module Sidekiq
|
|
90
106
|
|
91
107
|
private
|
92
108
|
|
93
|
-
# Creating the Redis#brpoplpush command takes into account any
|
94
|
-
# configured queue weights. By default Redis#brpoplpush returns
|
95
|
-
# data from the first queue that has pending elements. We
|
96
|
-
# choose the queue each time we invoke Redis#brpoplpush to honor weights
|
97
|
-
# and avoid queue starvation.
|
98
|
-
def pick_queue
|
99
|
-
queues = @strictly_ordered_queues ? @unique_queues.dup : @queues.shuffle.uniq
|
100
|
-
queues.first
|
101
|
-
end
|
102
|
-
|
103
109
|
# Detect "old" jobs and requeue them because the worker they were assigned
|
104
110
|
# to probably failed miserably.
|
105
111
|
# NOTE Potential problem here if a specific job always make a worker
|
@@ -111,7 +117,7 @@ module Sidekiq
|
|
111
117
|
clean_working_queue!(queue)
|
112
118
|
end
|
113
119
|
|
114
|
-
@
|
120
|
+
@nb_fetched_jobs = 0
|
115
121
|
end
|
116
122
|
|
117
123
|
def clean_working_queue!(queue)
|
@@ -121,12 +127,12 @@ module Sidekiq
|
|
121
127
|
enqueued_at = Sidekiq.load_json(job)['enqueued_at'].to_i
|
122
128
|
job_duration = Time.now.to_i - enqueued_at
|
123
129
|
|
124
|
-
if job_duration
|
125
|
-
Sidekiq.logger.info "Requeued a dead job found in #{queue}:#{WORKING_QUEUE}"
|
130
|
+
next if job_duration < @consider_dead_after
|
126
131
|
|
127
|
-
|
128
|
-
|
129
|
-
|
132
|
+
Sidekiq.logger.info "Requeued a dead job from #{queue}:#{WORKING_QUEUE}"
|
133
|
+
|
134
|
+
conn.rpush("#{queue}", job)
|
135
|
+
conn.lrem("#{queue}:#{WORKING_QUEUE}", 1, job)
|
130
136
|
end
|
131
137
|
end
|
132
138
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-reliable-fetch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- TEA
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sidekiq
|
@@ -32,6 +32,7 @@ extra_rdoc_files: []
|
|
32
32
|
files:
|
33
33
|
- ".gitignore"
|
34
34
|
- LICENSE
|
35
|
+
- README.md
|
35
36
|
- lib/sidekiq-reliable-fetch.rb
|
36
37
|
- lib/sidekiq-reliable-fetch/api.rb
|
37
38
|
- lib/sidekiq-reliable-fetch/web.rb
|