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.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +7 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +161 -0
  8. data/Rakefile +12 -0
  9. data/bench/compare.rb +52 -0
  10. data/demo/Gemfile +7 -0
  11. data/demo/README.md +37 -0
  12. data/demo/Rakefile +99 -0
  13. data/demo/app/workers/a_worker.rb +8 -0
  14. data/demo/app/workers/b_worker.rb +8 -0
  15. data/demo/app/workers/c_worker.rb +9 -0
  16. data/demo/app/workers/fast_worker.rb +8 -0
  17. data/demo/app/workers/slow_worker.rb +8 -0
  18. data/demo/config/application.rb +11 -0
  19. data/demo/config/boot.rb +2 -0
  20. data/demo/config/environment.rb +2 -0
  21. data/demo/config/environments/development.rb +9 -0
  22. data/lib/sidekiq/extensions/manager.rb +16 -0
  23. data/lib/sidekiq/extensions/queue.rb +23 -0
  24. data/lib/sidekiq/limit_fetch/global/monitor.rb +72 -0
  25. data/lib/sidekiq/limit_fetch/global/selector.rb +125 -0
  26. data/lib/sidekiq/limit_fetch/global/semaphore.rb +175 -0
  27. data/lib/sidekiq/limit_fetch/instances.rb +19 -0
  28. data/lib/sidekiq/limit_fetch/queues.rb +124 -0
  29. data/lib/sidekiq/limit_fetch/unit_of_work.rb +24 -0
  30. data/lib/sidekiq/limit_fetch.rb +58 -0
  31. data/lib/sidekiq-limit_fetch.rb +1 -0
  32. data/rcgt-sidekiq-limit_fetch.gemspec +24 -0
  33. data/spec/sidekiq/extensions/queue_spec.rb +94 -0
  34. data/spec/sidekiq/limit_fetch/global/monitor_spec.rb +33 -0
  35. data/spec/sidekiq/limit_fetch/queues_spec.rb +100 -0
  36. data/spec/sidekiq/limit_fetch/semaphore_spec.rb +63 -0
  37. data/spec/sidekiq/limit_fetch_spec.rb +48 -0
  38. data/spec/spec_helper.rb +28 -0
  39. 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
@@ -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