rcgt-sidekiq-limit_fetch 3.4.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 +7 -0
- data/.gitignore +3 -0
- data/.rspec +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +161 -0
- data/Rakefile +12 -0
- data/bench/compare.rb +52 -0
- data/demo/Gemfile +7 -0
- data/demo/README.md +37 -0
- data/demo/Rakefile +99 -0
- data/demo/app/workers/a_worker.rb +8 -0
- data/demo/app/workers/b_worker.rb +8 -0
- data/demo/app/workers/c_worker.rb +9 -0
- data/demo/app/workers/fast_worker.rb +8 -0
- data/demo/app/workers/slow_worker.rb +8 -0
- data/demo/config/application.rb +11 -0
- data/demo/config/boot.rb +2 -0
- data/demo/config/environment.rb +2 -0
- data/demo/config/environments/development.rb +9 -0
- data/lib/sidekiq/extensions/manager.rb +16 -0
- data/lib/sidekiq/extensions/queue.rb +23 -0
- data/lib/sidekiq/limit_fetch/global/monitor.rb +72 -0
- data/lib/sidekiq/limit_fetch/global/selector.rb +125 -0
- data/lib/sidekiq/limit_fetch/global/semaphore.rb +175 -0
- data/lib/sidekiq/limit_fetch/instances.rb +19 -0
- data/lib/sidekiq/limit_fetch/queues.rb +124 -0
- data/lib/sidekiq/limit_fetch/unit_of_work.rb +24 -0
- data/lib/sidekiq/limit_fetch.rb +58 -0
- data/lib/sidekiq-limit_fetch.rb +1 -0
- data/rcgt-sidekiq-limit_fetch.gemspec +24 -0
- data/spec/sidekiq/extensions/queue_spec.rb +94 -0
- data/spec/sidekiq/limit_fetch/global/monitor_spec.rb +33 -0
- data/spec/sidekiq/limit_fetch/queues_spec.rb +100 -0
- data/spec/sidekiq/limit_fetch/semaphore_spec.rb +63 -0
- data/spec/sidekiq/limit_fetch_spec.rb +48 -0
- data/spec/spec_helper.rb +28 -0
- metadata +149 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
RSpec.describe Sidekiq::LimitFetch::Queues do
|
2
|
+
let(:queues) { %w[queue1 queue2] }
|
3
|
+
let(:limits) {{ 'queue1' => 3 }}
|
4
|
+
let(:strict) { true }
|
5
|
+
let(:blocking) {}
|
6
|
+
let(:process_limits) {{ 'queue2' => 3 }}
|
7
|
+
|
8
|
+
let(:options) do
|
9
|
+
{ queues: queues,
|
10
|
+
limits: limits,
|
11
|
+
strict: strict,
|
12
|
+
blocking: blocking,
|
13
|
+
process_limits: process_limits }
|
14
|
+
end
|
15
|
+
|
16
|
+
before { subject.start options }
|
17
|
+
|
18
|
+
it 'should acquire queues' do
|
19
|
+
subject.acquire
|
20
|
+
expect(Sidekiq::Queue['queue1'].probed).to eq 1
|
21
|
+
expect(Sidekiq::Queue['queue2'].probed).to eq 1
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should acquire dynamically blocking queues' do
|
25
|
+
subject.acquire
|
26
|
+
expect(Sidekiq::Queue['queue1'].probed).to eq 1
|
27
|
+
expect(Sidekiq::Queue['queue2'].probed).to eq 1
|
28
|
+
|
29
|
+
Sidekiq::Queue['queue1'].block
|
30
|
+
|
31
|
+
subject.acquire
|
32
|
+
expect(Sidekiq::Queue['queue1'].probed).to eq 2
|
33
|
+
expect(Sidekiq::Queue['queue2'].probed).to eq 1
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should block except given queues' do
|
37
|
+
Sidekiq::Queue['queue1'].block_except 'queue2'
|
38
|
+
subject.acquire
|
39
|
+
expect(Sidekiq::Queue['queue1'].probed).to eq 1
|
40
|
+
expect(Sidekiq::Queue['queue2'].probed).to eq 1
|
41
|
+
|
42
|
+
Sidekiq::Queue['queue1'].block_except 'queue404'
|
43
|
+
subject.acquire
|
44
|
+
expect(Sidekiq::Queue['queue1'].probed).to eq 2
|
45
|
+
expect(Sidekiq::Queue['queue2'].probed).to eq 1
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should release queues' do
|
49
|
+
subject.acquire
|
50
|
+
subject.release_except nil
|
51
|
+
expect(Sidekiq::Queue['queue1'].probed).to eq 0
|
52
|
+
expect(Sidekiq::Queue['queue2'].probed).to eq 0
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should release queues except selected' do
|
56
|
+
subject.acquire
|
57
|
+
subject.release_except 'queue:queue1'
|
58
|
+
expect(Sidekiq::Queue['queue1'].probed).to eq 1
|
59
|
+
expect(Sidekiq::Queue['queue2'].probed).to eq 0
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should release when no queues was acquired' do
|
63
|
+
queues.each {|name| Sidekiq::Queue[name].pause }
|
64
|
+
subject.acquire
|
65
|
+
expect { subject.release_except nil }.not_to raise_exception
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'blocking' do
|
69
|
+
let(:blocking) { %w(queue1) }
|
70
|
+
|
71
|
+
it 'should acquire blocking queues' do
|
72
|
+
3.times { subject.acquire }
|
73
|
+
expect(Sidekiq::Queue['queue1'].probed).to eq 3
|
74
|
+
expect(Sidekiq::Queue['queue2'].probed).to eq 1
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should set limits' do
|
79
|
+
subject
|
80
|
+
expect(Sidekiq::Queue['queue1'].limit).to eq 3
|
81
|
+
expect(Sidekiq::Queue['queue2'].limit).not_to be
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should set process_limits' do
|
85
|
+
subject
|
86
|
+
expect(Sidekiq::Queue['queue2'].process_limit).to eq 3
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'without strict flag' do
|
90
|
+
let(:strict) { false }
|
91
|
+
|
92
|
+
it 'should retrieve weighted queues' do
|
93
|
+
expect(subject.ordered_queues).to match_array(%w(queue1 queue2))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'with strict flag should retrieve strictly ordered queues' do
|
98
|
+
expect(subject.ordered_queues).to eq %w(queue1 queue2)
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
RSpec.describe 'semaphore' do
|
2
|
+
let(:name) { 'default' }
|
3
|
+
subject { Sidekiq::LimitFetch::Global::Semaphore.new name }
|
4
|
+
|
5
|
+
it 'should have no limit by default' do
|
6
|
+
expect(subject.limit).not_to be
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should set limit' do
|
10
|
+
subject.limit = 4
|
11
|
+
expect(subject.limit).to eq 4
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should acquire and count active tasks' do
|
15
|
+
3.times { subject.acquire }
|
16
|
+
expect(subject.probed).to eq 3
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should acquire tasks with regard to limit' do
|
20
|
+
subject.limit = 4
|
21
|
+
6.times { subject.acquire }
|
22
|
+
expect(subject.probed).to eq 4
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should acquire tasks with regard to process limit' do
|
26
|
+
subject.process_limit = 4
|
27
|
+
6.times { subject.acquire }
|
28
|
+
expect(subject.probed).to eq 4
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should release active tasks' do
|
32
|
+
6.times { subject.acquire }
|
33
|
+
3.times { subject.release }
|
34
|
+
expect(subject.probed).to eq 3
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should pause tasks' do
|
38
|
+
3.times { subject.acquire }
|
39
|
+
subject.pause
|
40
|
+
2.times { subject.acquire }
|
41
|
+
expect(subject.probed).to eq 3
|
42
|
+
2.times { subject.release }
|
43
|
+
expect(subject.probed).to eq 1
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should unpause tasks' do
|
47
|
+
subject.pause
|
48
|
+
3.times { subject.acquire }
|
49
|
+
subject.unpause
|
50
|
+
2.times { subject.acquire }
|
51
|
+
expect(subject.probed).to eq 2
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should pause tasks for a limited time' do
|
55
|
+
3.times { subject.acquire }
|
56
|
+
subject.pause_for_ms 50
|
57
|
+
2.times { subject.acquire }
|
58
|
+
expect(subject.probed).to eq 3
|
59
|
+
sleep(100.0 / 1000)
|
60
|
+
2.times { subject.acquire }
|
61
|
+
expect(subject.probed).to eq 5
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
Thread.abort_on_exception = true
|
2
|
+
|
3
|
+
RSpec.describe Sidekiq::LimitFetch do
|
4
|
+
let(:options) {{ queues: queues, limits: limits }}
|
5
|
+
let(:queues) { %w(queue1 queue1 queue2 queue2) }
|
6
|
+
let(:limits) {{ 'queue1' => 1, 'queue2' => 2 }}
|
7
|
+
|
8
|
+
before do
|
9
|
+
subject::Queues.start options
|
10
|
+
|
11
|
+
Sidekiq.redis do |it|
|
12
|
+
it.del 'queue:queue1'
|
13
|
+
it.lpush 'queue:queue1', 'task1'
|
14
|
+
it.lpush 'queue:queue1', 'task2'
|
15
|
+
it.expire 'queue:queue1', 30
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should acquire lock on queue for execution' do
|
20
|
+
work = subject.retrieve_work
|
21
|
+
expect(work.queue_name).to eq 'queue1'
|
22
|
+
expect(work.job).to eq 'task1'
|
23
|
+
|
24
|
+
expect(Sidekiq::Queue['queue1'].busy).to eq 1
|
25
|
+
expect(Sidekiq::Queue['queue2'].busy).to eq 0
|
26
|
+
|
27
|
+
expect(subject.retrieve_work).not_to be
|
28
|
+
work.requeue
|
29
|
+
|
30
|
+
expect(Sidekiq::Queue['queue1'].busy).to eq 0
|
31
|
+
expect(Sidekiq::Queue['queue2'].busy).to eq 0
|
32
|
+
|
33
|
+
work = subject.retrieve_work
|
34
|
+
expect(work.job).to eq 'task1'
|
35
|
+
|
36
|
+
expect(Sidekiq::Queue['queue1'].busy).to eq 1
|
37
|
+
expect(Sidekiq::Queue['queue2'].busy).to eq 0
|
38
|
+
|
39
|
+
expect(subject.retrieve_work).not_to be
|
40
|
+
work.acknowledge
|
41
|
+
|
42
|
+
expect(Sidekiq::Queue['queue1'].busy).to eq 0
|
43
|
+
expect(Sidekiq::Queue['queue2'].busy).to eq 0
|
44
|
+
|
45
|
+
work = subject.retrieve_work
|
46
|
+
expect(work.job).to eq 'task2'
|
47
|
+
end
|
48
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'sidekiq/limit_fetch'
|
2
|
+
|
3
|
+
Sidekiq.logger = nil
|
4
|
+
Sidekiq.redis = { namespace: ENV['namespace'] }
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.order = :random
|
8
|
+
config.disable_monkey_patching!
|
9
|
+
config.raise_errors_for_deprecations!
|
10
|
+
config.before do
|
11
|
+
Sidekiq::Queue.reset_instances!
|
12
|
+
Sidekiq.redis do |it|
|
13
|
+
clean_redis = ->(queue) do
|
14
|
+
it.pipelined do
|
15
|
+
it.del "limit_fetch:limit:#{queue}"
|
16
|
+
it.del "limit_fetch:process_limit:#{queue}"
|
17
|
+
it.del "limit_fetch:busy:#{queue}"
|
18
|
+
it.del "limit_fetch:probed:#{queue}"
|
19
|
+
it.del "limit_fetch:pause:#{queue}"
|
20
|
+
it.del "limit_fetch:block:#{queue}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
clean_redis.call(name) if defined?(name)
|
25
|
+
queues.each(&clean_redis) if defined?(queues) and queues.is_a? Array
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rcgt-sidekiq-limit_fetch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 3.4.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- RCGT Consulting Inc.
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-02-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sidekiq
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: redis-namespace
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.5'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 1.5.2
|
37
|
+
type: :development
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.5'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.5.2
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rake
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
description: " A fork of https://github.com/brainopia/sidekiq-limit_fetch\n \n
|
76
|
+
\ Sidekiq strategy to restrict number of workers\n which are able to run specified
|
77
|
+
queues simultaneously.\n"
|
78
|
+
email: kumanan.yogaratnam@rcgtconsulting.com
|
79
|
+
executables: []
|
80
|
+
extensions: []
|
81
|
+
extra_rdoc_files: []
|
82
|
+
files:
|
83
|
+
- ".gitignore"
|
84
|
+
- ".rspec"
|
85
|
+
- ".travis.yml"
|
86
|
+
- Gemfile
|
87
|
+
- LICENSE.txt
|
88
|
+
- README.md
|
89
|
+
- Rakefile
|
90
|
+
- bench/compare.rb
|
91
|
+
- demo/Gemfile
|
92
|
+
- demo/README.md
|
93
|
+
- demo/Rakefile
|
94
|
+
- demo/app/workers/a_worker.rb
|
95
|
+
- demo/app/workers/b_worker.rb
|
96
|
+
- demo/app/workers/c_worker.rb
|
97
|
+
- demo/app/workers/fast_worker.rb
|
98
|
+
- demo/app/workers/slow_worker.rb
|
99
|
+
- demo/config/application.rb
|
100
|
+
- demo/config/boot.rb
|
101
|
+
- demo/config/environment.rb
|
102
|
+
- demo/config/environments/development.rb
|
103
|
+
- lib/sidekiq-limit_fetch.rb
|
104
|
+
- lib/sidekiq/extensions/manager.rb
|
105
|
+
- lib/sidekiq/extensions/queue.rb
|
106
|
+
- lib/sidekiq/limit_fetch.rb
|
107
|
+
- lib/sidekiq/limit_fetch/global/monitor.rb
|
108
|
+
- lib/sidekiq/limit_fetch/global/selector.rb
|
109
|
+
- lib/sidekiq/limit_fetch/global/semaphore.rb
|
110
|
+
- lib/sidekiq/limit_fetch/instances.rb
|
111
|
+
- lib/sidekiq/limit_fetch/queues.rb
|
112
|
+
- lib/sidekiq/limit_fetch/unit_of_work.rb
|
113
|
+
- rcgt-sidekiq-limit_fetch.gemspec
|
114
|
+
- spec/sidekiq/extensions/queue_spec.rb
|
115
|
+
- spec/sidekiq/limit_fetch/global/monitor_spec.rb
|
116
|
+
- spec/sidekiq/limit_fetch/queues_spec.rb
|
117
|
+
- spec/sidekiq/limit_fetch/semaphore_spec.rb
|
118
|
+
- spec/sidekiq/limit_fetch_spec.rb
|
119
|
+
- spec/spec_helper.rb
|
120
|
+
homepage: https://github.com/RCGTConsulting/sidekiq-limit_fetch
|
121
|
+
licenses:
|
122
|
+
- MIT
|
123
|
+
metadata: {}
|
124
|
+
post_install_message:
|
125
|
+
rdoc_options: []
|
126
|
+
require_paths:
|
127
|
+
- lib
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
requirements: []
|
139
|
+
rubygems_version: 3.1.6
|
140
|
+
signing_key:
|
141
|
+
specification_version: 4
|
142
|
+
summary: Sidekiq strategy to support queue limits
|
143
|
+
test_files:
|
144
|
+
- spec/sidekiq/extensions/queue_spec.rb
|
145
|
+
- spec/sidekiq/limit_fetch/global/monitor_spec.rb
|
146
|
+
- spec/sidekiq/limit_fetch/queues_spec.rb
|
147
|
+
- spec/sidekiq/limit_fetch/semaphore_spec.rb
|
148
|
+
- spec/sidekiq/limit_fetch_spec.rb
|
149
|
+
- spec/spec_helper.rb
|