sidekiq-limit_fetch 1.1 → 1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 49c36141cff8fd8e6ad664f6a2fbe07af64f21ce
4
+ data.tar.gz: bcd3045d1127d419892b6d917363cfaf6462c9f3
5
+ SHA512:
6
+ metadata.gz: 014d8dd3ff1dfedbf226c0e5fc58fdb57a34e0329b0ad56f3d607276d39c45317697fde7c13cfeb33efa86c16a14db8df7a30eb3103f70691dd93c183ba15201
7
+ data.tar.gz: a6c5d5c6c19a03fb727384dee9ac0119ae018ae0ce517922442b4f45dcc576cb7f9566385af3b1d6a5696f57837b0b3475796c0338f1cd38883bbf85bd5ed18b
data/.travis.yml CHANGED
@@ -8,5 +8,5 @@ services:
8
8
  - redis-server
9
9
  matrix:
10
10
  allow_failures:
11
- - rvm: 2.0.0
11
+ - rvm: jruby-19mode
12
12
  - rvm: rbx-19mode
data/Gemfile CHANGED
@@ -1,2 +1,2 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
  gemspec
data/README.md CHANGED
@@ -3,14 +3,10 @@
3
3
  Sidekiq strategy to restrict number of workers
4
4
  which are able to run specified queues simultaneously.
5
5
 
6
- [![Build
7
- Status](https://secure.travis-ci.org/brainopia/sidekiq-limit_fetch.png)](http://travis-ci.org/brainopia/sidekiq-limit_fetch)
8
- [![Gem
9
- Version](https://badge.fury.io/rb/sidekiq-limit_fetch.png)](http://badge.fury.io/rb/sidekiq-limit_fetch)
10
- [![Dependency
11
- Status](https://gemnasium.com/brainopia/sidekiq-limit_fetch.png)](https://gemnasium.com/brainopia/sidekiq-limit_fetch)
12
- [![Code
13
- Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/brainopia/sidekiq-limit_fetch)
6
+ [![Build Status](https://secure.travis-ci.org/brainopia/sidekiq-limit_fetch.png)](http://travis-ci.org/brainopia/sidekiq-limit_fetch)
7
+ [![Gem Version](https://badge.fury.io/rb/sidekiq-limit_fetch.png)](http://badge.fury.io/rb/sidekiq-limit_fetch)
8
+ [![Dependency Status](https://gemnasium.com/brainopia/sidekiq-limit_fetch.png)](https://gemnasium.com/brainopia/sidekiq-limit_fetch)
9
+ [![Code Climate](https://codeclimate.com/github/brainopia/sidekiq-limit_fetch.png)](https://codeclimate.com/github/brainopia/sidekiq-limit_fetch)
14
10
 
15
11
  ## Installation
16
12
 
@@ -43,6 +39,13 @@ workers simultaneously.
43
39
  Ability to set limits dynamically allows you to resize worker
44
40
  distribution among queues any time you want.
45
41
 
42
+ ### Busy workers by queue
43
+
44
+ You can see how many workers currently handling a queue:
45
+
46
+ ```ruby
47
+ Sidekiq::Queue['name'].busy # number of busy workers
48
+ ```
46
49
 
47
50
  ### Pauses
48
51
 
@@ -55,13 +58,6 @@ will be preserved.
55
58
  Sidekiq::Queue['name'].unpause # allows workers to use the queue
56
59
  ```
57
60
 
58
-
59
- You can see how many workers currently handling a queue:
60
-
61
- ```ruby
62
- Sidekiq::Queue['name'].busy # number of busy workers
63
- ```
64
-
65
61
  ### Multiple processes
66
62
 
67
63
  Limits are applied per process. In case you have several worker
@@ -106,6 +102,29 @@ You can also enable and disable blocking mode for queues on the fly:
106
102
  Sidekiq::Queue['name'].unblock
107
103
  ```
108
104
 
105
+ ### Advanced blocking queues
106
+
107
+ You can also block on array of queues. It means when any of them is
108
+ running only queues higher and queues from their blocking group can
109
+ run. It will be easier to understand with an example:
110
+
111
+ ```yaml
112
+ :queues:
113
+ - a
114
+ - b
115
+ - c
116
+ - d
117
+ :blocking:
118
+ - [b, c]
119
+ ```
120
+
121
+ In this case tasks from `d` will be blocked when a task from queue `b` or `c` is executed.
122
+
123
+ You can dynamically set exceptions for queue blocking:
124
+
125
+ ```ruby
126
+ Sidekiq::Queue['queue1'].block_except 'queue2'
127
+ ```
109
128
 
110
129
  ### Thanks
111
130
 
@@ -3,11 +3,12 @@ module Sidekiq
3
3
  extend LimitFetch::Singleton, Forwardable
4
4
 
5
5
  def_delegators :lock,
6
- :limit, :limit=,
7
- :acquire, :release,
8
- :pause, :unpause,
9
- :block, :unblock,
10
- :paused?, :blocking?,
6
+ :limit, :limit=,
7
+ :acquire, :release,
8
+ :pause, :unpause,
9
+ :block, :unblock,
10
+ :paused?, :blocking?,
11
+ :unblocked, :block_except,
11
12
  :busy
12
13
 
13
14
  def lock
@@ -11,7 +11,13 @@ module Sidekiq::LimitFetch::Global
11
11
  end
12
12
 
13
13
  def uuid
14
- @uuid ||= SecureRandom.uuid
14
+ # - if we'll remove "@uuid ||=" from inside of mutex
15
+ # then @uuid can be overwritten
16
+ # - if we'll remove "@uuid ||=" from outside of mutex
17
+ # then each read will lead to mutex
18
+ @uuid ||= Thread.exclusive do
19
+ @uuid ||= SecureRandom.uuid
20
+ end
15
21
  end
16
22
 
17
23
  private
@@ -48,11 +54,12 @@ module Sidekiq::LimitFetch::Global
48
54
  local worker_name = table.remove(ARGV, 1)
49
55
  local queues = ARGV
50
56
  local available = {}
57
+ local unblocked = {}
51
58
  local queue_locks
52
- local blocked
59
+ local blocking_mode
53
60
 
54
61
  for _, queue in ipairs(queues) do
55
- if not blocked then
62
+ if not blocking_mode or unblocked[queue] then
56
63
  local busy_key = namespace..'busy:'..queue
57
64
  local pause_key = namespace..'pause:'..queue
58
65
  local paused = redis.call('get', pause_key)
@@ -68,7 +75,13 @@ module Sidekiq::LimitFetch::Global
68
75
  queue_locks = redis.call('llen', busy_key)
69
76
  end
70
77
 
71
- blocked = can_block and queue_locks > 0
78
+ blocking_mode = can_block and queue_locks > 0
79
+
80
+ if blocking_mode and can_block ~= 'true' then
81
+ for unblocked_queue in string.gmatch(can_block, "[^,]+") do
82
+ unblocked[unblocked_queue] = true
83
+ end
84
+ end
72
85
 
73
86
  if not queue_limit or queue_limit > queue_locks then
74
87
  redis.call('rpush', busy_key, worker_name)
@@ -46,6 +46,11 @@ module Sidekiq::LimitFetch::Global
46
46
  redis {|it| it.set "#{PREFIX}:block:#@name", true }
47
47
  end
48
48
 
49
+ def block_except(*queues)
50
+ raise ArgumentError if queues.empty?
51
+ redis {|it| it.set "#{PREFIX}:block:#@name", queues.join(',') }
52
+ end
53
+
49
54
  def unblock
50
55
  redis {|it| it.del "#{PREFIX}:block:#@name" }
51
56
  end
@@ -3,10 +3,17 @@ module Sidekiq::LimitFetch::Local
3
3
  extend self
4
4
 
5
5
  def acquire(names)
6
- blocked = false
6
+ blocked = false
7
+ unblocked = []
8
+
7
9
  queues(names).select {|queue|
8
- next false if blocked
9
- blocked = true if not queue.paused? and queue.blocking? and queue.busy > 0
10
+ next false if blocked and not unblocked.include?(queue.name)
11
+
12
+ if not queue.paused? and queue.blocking? and queue.busy > 0
13
+ blocked = true
14
+ unblocked = queue.unblocked || []
15
+ end
16
+
10
17
  queue.acquire
11
18
  }.map(&:name)
12
19
  end
@@ -1,6 +1,6 @@
1
1
  module Sidekiq::LimitFetch::Local
2
2
  class Semaphore
3
- attr_reader :limit, :busy
3
+ attr_reader :limit, :busy, :unblocked
4
4
 
5
5
  def initialize(name)
6
6
  @name = name
@@ -44,6 +44,12 @@ module Sidekiq::LimitFetch::Local
44
44
  @block = true
45
45
  end
46
46
 
47
+ def block_except(*queues)
48
+ raise ArgumentError if queues.empty?
49
+ @unblocked = queues
50
+ @block = true
51
+ end
52
+
47
53
  def unblock
48
54
  @block = false
49
55
  end
@@ -36,8 +36,12 @@ class Sidekiq::LimitFetch
36
36
  end
37
37
 
38
38
  def set_blocks(blocks)
39
- blocks.to_a.each do |name|
40
- Sidekiq::Queue[name].block
39
+ blocks.to_a.each do |it|
40
+ if it.is_a? Array
41
+ it.each {|name| Sidekiq::Queue[name].block_except it }
42
+ else
43
+ Sidekiq::Queue[it].block
44
+ end
41
45
  end
42
46
  end
43
47
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = 'sidekiq-limit_fetch'
3
- gem.version = '1.1'
3
+ gem.version = '1.2'
4
4
  gem.authors = 'brainopia'
5
5
  gem.email = 'brainopia@evilmartians.com'
6
6
  gem.summary = 'Sidekiq strategy to support queue limits'
@@ -40,6 +40,18 @@ describe Sidekiq::LimitFetch::Queues do
40
40
  Sidekiq::Queue['queue2'].busy.should == 1
41
41
  end
42
42
 
43
+ it 'should block except given queues' do
44
+ Sidekiq::Queue['queue1'].block_except 'queue2'
45
+ subject.acquire
46
+ Sidekiq::Queue['queue1'].busy.should == 1
47
+ Sidekiq::Queue['queue2'].busy.should == 1
48
+
49
+ Sidekiq::Queue['queue1'].block_except 'queue404'
50
+ subject.acquire
51
+ Sidekiq::Queue['queue1'].busy.should == 2
52
+ Sidekiq::Queue['queue2'].busy.should == 1
53
+ end
54
+
43
55
  it 'should release queues' do
44
56
  subject.acquire
45
57
  subject.release_except nil
@@ -14,7 +14,7 @@ describe Sidekiq::LimitFetch do
14
14
  let(:options) {{ queues: queues, limits: limits, global: global }}
15
15
  let(:queues) { %w(queue1 queue1 queue2 queue2) }
16
16
  let(:limits) {{ 'queue1' => 1, 'queue2' => 2 }}
17
-
17
+
18
18
  shared_examples_for :strategy do
19
19
  it 'should acquire lock on queue for execution' do
20
20
  work = subject.retrieve_work
metadata CHANGED
@@ -1,22 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-limit_fetch
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.1'
5
- prerelease:
4
+ version: '1.2'
6
5
  platform: ruby
7
6
  authors:
8
7
  - brainopia
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-01-28 00:00:00.000000000 Z
11
+ date: 2013-03-10 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: sidekiq
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: 2.6.5
22
20
  - - <
@@ -25,9 +23,8 @@ dependencies:
25
23
  type: :runtime
26
24
  prerelease: false
27
25
  version_requirements: !ruby/object:Gem::Requirement
28
- none: false
29
26
  requirements:
30
- - - ! '>='
27
+ - - '>='
31
28
  - !ruby/object:Gem::Version
32
29
  version: 2.6.5
33
30
  - - <
@@ -36,37 +33,34 @@ dependencies:
36
33
  - !ruby/object:Gem::Dependency
37
34
  name: rspec
38
35
  requirement: !ruby/object:Gem::Requirement
39
- none: false
40
36
  requirements:
41
- - - ! '>='
37
+ - - '>='
42
38
  - !ruby/object:Gem::Version
43
39
  version: '0'
44
40
  type: :development
45
41
  prerelease: false
46
42
  version_requirements: !ruby/object:Gem::Requirement
47
- none: false
48
43
  requirements:
49
- - - ! '>='
44
+ - - '>='
50
45
  - !ruby/object:Gem::Version
51
46
  version: '0'
52
47
  - !ruby/object:Gem::Dependency
53
48
  name: rake
54
49
  requirement: !ruby/object:Gem::Requirement
55
- none: false
56
50
  requirements:
57
- - - ! '>='
51
+ - - '>='
58
52
  - !ruby/object:Gem::Version
59
53
  version: '0'
60
54
  type: :development
61
55
  prerelease: false
62
56
  version_requirements: !ruby/object:Gem::Requirement
63
- none: false
64
57
  requirements:
65
- - - ! '>='
58
+ - - '>='
66
59
  - !ruby/object:Gem::Version
67
60
  version: '0'
68
- description: ! " Sidekiq strategy to restrict number of workers\n which are
69
- able to run specified queues simultaneously.\n"
61
+ description: |2
62
+ Sidekiq strategy to restrict number of workers
63
+ which are able to run specified queues simultaneously.
70
64
  email: brainopia@evilmartians.com
71
65
  executables: []
72
66
  extensions: []
@@ -97,33 +91,26 @@ files:
97
91
  - spec/spec_helper.rb
98
92
  homepage: https://github.com/brainopia/sidekiq-limit_fetch
99
93
  licenses: []
94
+ metadata: {}
100
95
  post_install_message:
101
96
  rdoc_options: []
102
97
  require_paths:
103
98
  - lib
104
99
  required_ruby_version: !ruby/object:Gem::Requirement
105
- none: false
106
100
  requirements:
107
- - - ! '>='
101
+ - - '>='
108
102
  - !ruby/object:Gem::Version
109
103
  version: '0'
110
- segments:
111
- - 0
112
- hash: -3014276428821981336
113
104
  required_rubygems_version: !ruby/object:Gem::Requirement
114
- none: false
115
105
  requirements:
116
- - - ! '>='
106
+ - - '>='
117
107
  - !ruby/object:Gem::Version
118
108
  version: '0'
119
- segments:
120
- - 0
121
- hash: -3014276428821981336
122
109
  requirements: []
123
110
  rubyforge_project:
124
- rubygems_version: 1.8.24
111
+ rubygems_version: 2.0.0
125
112
  signing_key:
126
- specification_version: 3
113
+ specification_version: 4
127
114
  summary: Sidekiq strategy to support queue limits
128
115
  test_files:
129
116
  - spec/sidekiq/extensions/queue_spec.rb