sidekiq-reliable-fetch 0.1.0 → 0.2.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: 35c020c4d73f87e39a4b5fa52930e42505c8e866
4
- data.tar.gz: 1d344483e74a309efe9db2355450f20a0d5f4487
3
+ metadata.gz: 803136d2fb9cf9eb4f60b0b54618e489616d763a
4
+ data.tar.gz: 8371867f1f2ce011d710d91dd0d2a3a09ab1c739
5
5
  SHA512:
6
- metadata.gz: 755c4623df1d7d672bb4c857ca53cb4b2e12d9d3e0f1cbbb37b7eb42a4f93dbba639bf91f8588607e7570eef27d50996e637f3a71d6920a8aaacdb62b9d273f5
7
- data.tar.gz: 6c76f3015bfc44f03285d151625cf3ee88024b97c8df6c970b72140290948b8625a550fccbf93f90f3291483175dd382d63f8527742269b54046271ac3be62e6
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 = 60 * 30 # 30 minutes
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
- @strictly_ordered_queues = !!options[:strict]
16
- @queues = options[:queues].map { |q| "queue:#{q}" }
17
- @unique_queues = @queues.uniq
18
- @last_clean = Time.now.to_i
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 && Time.now.to_i - @last_clean > @cleaning_interval
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
- queue = pick_queue
27
- work = Sidekiq.redis { |conn| conn.brpoplpush(queue, "#{queue}:#{WORKING_QUEUE}", Sidekiq::Fetcher::TIMEOUT) }
28
- UnitOfWork.new(queue, work) if work
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
- @last_clean = Time.now.to_i
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 > @consider_dead_after
125
- Sidekiq.logger.info "Requeued a dead job found in #{queue}:#{WORKING_QUEUE}"
130
+ next if job_duration < @consider_dead_after
126
131
 
127
- conn.rpush("#{queue}", job)
128
- conn.lrem("#{queue}:#{WORKING_QUEUE}", 1, job)
129
- end
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
@@ -7,7 +7,6 @@ module SidekiqReliableFetch
7
7
 
8
8
  def self.registered(app)
9
9
  app.get '/working' do
10
- puts VIEW_PATH.inspect
11
10
  @queues = SidekiqReliableFetch::WorkingQueue.all
12
11
  erb File.read(File.join(VIEW_PATH, 'working_queues.erb'))
13
12
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'sidekiq-reliable-fetch'
3
- s.version = '0.1.0'
3
+ s.version = '0.2.0'
4
4
  s.authors = ['TEA']
5
5
  s.email = 'technique@tea-ebook.com'
6
6
  s.license = 'LGPL-3.0'
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.1.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-05-26 00:00:00.000000000 Z
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