reqless 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1042e561166bf47c7938f8d372d6ff1b69e6cdf999577b44e3c4a2ac3326cf1
4
- data.tar.gz: 983e5f31909dca78405b16208064460f830048c9a277fdbc76f9a4b5b8ea194c
3
+ metadata.gz: d89345ee8de2c77b0083cd7c93eb4aff552d57a298f6c0f55953093e5c69bd98
4
+ data.tar.gz: c41fac4baeaebe950d1f72fc69647b4aeca870b31bdd8b595cb821f1cea4bce5
5
5
  SHA512:
6
- metadata.gz: 89613e228c2b8bc014c25125eb65db6bd60816397b6e6df712e433d7901f4b21bd1b9444d73e8583d63209baeee513aca5e75f4c6a554008d9b78be0ac1bc9aa
7
- data.tar.gz: fa149f59031bc460de0395bc1c5b768129f741ba4a646b6772049be60fb491e04df9584c8ba42293b88810c35180559b33292922fa855d9380d33873a9672978
6
+ metadata.gz: b60f2d5e8d40f41179b418a09397dd2669126c351108fffc3781907793e3b4dee25dfa970b0bed8de2e7c05466bd1d10d1b53e0b4bb5b5f891327e8b63c688f2
7
+ data.tar.gz: 8afc28f017ec955c72994a1eeca4f7402c294603ab8a62ef991c1955a763614e66f3cdf0567728a80eeb45b6eeecbe3511c114e277bedde338ebf88bb82a476b
@@ -0,0 +1,30 @@
1
+ module Reqless::JobReservers
2
+ # @param [Enumerable] reservers - a set of reservers
3
+ # to check for work.
4
+ class Delegating < Struct.new(:reservers)
5
+ def description
6
+ "Delegating Reserver"
7
+ end
8
+
9
+ def prep_for_work!
10
+ # nothing here on purpose
11
+ end
12
+
13
+ def queues
14
+ Enumerator.new do |yielder|
15
+ reservers.each do |reserver|
16
+ reserver.queues.each {|queue| yielder << queue}
17
+ end
18
+ end
19
+ end
20
+
21
+ def reserve
22
+ reservers.each do |reserver|
23
+ if (job = reserver.reserve)
24
+ return job
25
+ end
26
+ end
27
+ nil
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,42 @@
1
+ require 'reqless/queue_patterns_helper'
2
+
3
+ module Reqless
4
+ module JobReservers
5
+ module Strategies
6
+ end
7
+ end
8
+ end
9
+
10
+ module Reqless::JobReservers::Strategies::Filtering
11
+ # @param [Enumerable] queues - a source of queues
12
+ # @param [Array] regexes - a list of regexes to match against.
13
+ # Return an enumerator of the filtered queues in
14
+ # in prioritized order.
15
+ def self.default(
16
+ queues,
17
+ regexes,
18
+ queue_identifier_patterns,
19
+ queue_priority_patterns
20
+ )
21
+ Enumerator.new do |yielder|
22
+ # Map queues to their names
23
+ mapped_queues = queues.reduce({}) do |hash,queue|
24
+ hash[queue.name] = queue
25
+ hash
26
+ end
27
+
28
+ # Filter the queue names against the regexes provided.
29
+ matches = Reqless::QueuePatternsHelper.expand_queues(regexes, mapped_queues.keys, queue_identifier_patterns)
30
+
31
+ # Prioritize the queues.
32
+ prioritized_names = Reqless::QueuePatternsHelper.prioritize_queues(queue_priority_patterns, matches)
33
+
34
+ prioritized_names.each do |name|
35
+ queue = mapped_queues[name]
36
+ if queue
37
+ yielder << queue
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,31 @@
1
+ module Reqless
2
+ module JobReservers
3
+ module Strategies
4
+ end
5
+ end
6
+ end
7
+
8
+ module Reqless::JobReservers::Strategies::Ordering
9
+ # Shuffles the underlying enumerable
10
+ # for each iteration.
11
+ # @param [Enumerable] enumerable - underlying enumerator to iterate over
12
+ def self.shuffled(enumerable)
13
+ Enumerator.new do |yielder|
14
+ enumerable.to_a.shuffle.each do |e|
15
+ yielder << e
16
+ end
17
+ end
18
+ end
19
+
20
+ # Samples a subset of the underlying enumerable
21
+ # for each iteration.
22
+ # @param [Enumerable] enumerable - underlying enumerator to iterate over
23
+ # @param [Integer] sample_size - number of items to take per iteration
24
+ def self.sampled(enumerable, sample_size = 5)
25
+ Enumerator.new do |yielder|
26
+ enumerable.to_a.sample(sample_size).each do |e|
27
+ yielder << e
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,63 @@
1
+ module Reqless
2
+ module JobReservers
3
+ module Strategies
4
+ end
5
+ end
6
+ end
7
+
8
+ # This module provides the different kinds of queue sources used by qmore
9
+ module Reqless::JobReservers::Strategies::Sources
10
+ # Direct source uses a client to generate the queues we should
11
+ # pull work from. Ignores any queues that do not have tasks available.
12
+ def self.direct(client)
13
+ Enumerator.new do |yielder|
14
+ queues = client.queues.counts.select do |queue|
15
+ %w(waiting recurring depends stalled scheduled).any? {|state| queue[state].to_i > 0 }
16
+ end
17
+
18
+ queues.each do |queue|
19
+ yielder << client.queues[queue['name']]
20
+ end
21
+ end
22
+ end
23
+
24
+ # Background Queue source runs in a background thread
25
+ # to periodically update the queues available.
26
+ class Background
27
+ include Enumerable
28
+ attr_reader :delegate, :delay
29
+ # @param [Enumerator] delegate queue source to load the queues from.
30
+ # @param [Integer] delay - how long between updates
31
+ def initialize(delegate, delay)
32
+ @delegate = delegate
33
+ @delay = delay
34
+ end
35
+
36
+ # Spawns a thread to periodically update the
37
+ # queues.
38
+ # @return [Thread] returns the spawned thread.
39
+ def start
40
+ @stop = false
41
+ @queues = delegate.to_a
42
+ Thread.new do
43
+ begin
44
+ loop do
45
+ sleep delay
46
+ break if @stop
47
+ @queues = delegate.to_a
48
+ end
49
+ rescue => e
50
+ retry
51
+ end
52
+ end
53
+ end
54
+
55
+ def stop
56
+ @stop = true
57
+ end
58
+
59
+ def each(&block)
60
+ @queues.each { |q| block.call(q) }
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,7 @@
1
+ module Reqless::JobReservers
2
+ module Strategies
3
+ require 'reqless/job_reservers/strategies/filtering'
4
+ require 'reqless/job_reservers/strategies/ordering'
5
+ require 'reqless/job_reservers/strategies/sources'
6
+ end
7
+ end
@@ -0,0 +1,113 @@
1
+ module Reqless
2
+ module QueuePatternsHelper
3
+ extend self
4
+
5
+ # Returns a list of queues to use when searching for a job.
6
+ #
7
+ # A splat ("*") means you want every queue (in alpha order) - this
8
+ # can be useful for dynamically adding new queues.
9
+ #
10
+ # The splat can also be used as a wildcard within a queue name,
11
+ # e.g. "*high*", and negation can be indicated with a prefix of "!"
12
+ #
13
+ # An @key can be used to dynamically look up the queue list for key from redis.
14
+ # If no key is supplied, it defaults to the worker's hostname, and wildcards
15
+ # and negations can be used inside this dynamic queue list.
16
+ def expand_queues(queue_patterns, real_queues, queue_identifier_patterns)
17
+ queue_patterns = queue_patterns.dup
18
+ real_queues = real_queues.dup
19
+
20
+ matched_queues = []
21
+
22
+ while q = queue_patterns.shift
23
+ q = q.to_s
24
+ negated = false
25
+
26
+ if q =~ /^(!)?@(.*)/
27
+ key = $2.strip
28
+ key = Socket.gethostname if key.size == 0
29
+
30
+ add_queues = queue_identifier_patterns.fetch(key, nil) ||
31
+ queue_identifier_patterns.fetch('default', ['*'])
32
+ add_queues = add_queues.map { |q| q.gsub!(/^!/, '') || q.gsub!(/^/, '!') } if $1
33
+
34
+ queue_patterns.concat(add_queues)
35
+ next
36
+ end
37
+
38
+ if q =~ /^!/
39
+ negated = true
40
+ q = q[1..-1]
41
+ end
42
+
43
+ patstr = q.gsub(/\*/, ".*")
44
+ pattern = /^#{patstr}$/
45
+ if negated
46
+ matched_queues -= matched_queues.grep(pattern)
47
+ else
48
+ matches = real_queues.grep(/^#{pattern}$/)
49
+ matches = [q] if matches.size == 0 && q == patstr
50
+ matched_queues.concat(matches)
51
+ end
52
+ end
53
+
54
+ return matched_queues.uniq.sort
55
+ end
56
+
57
+ def prioritize_queues(priority_buckets, real_queues)
58
+ real_queues = real_queues.dup
59
+ priority_buckets = priority_buckets.dup
60
+
61
+ result = []
62
+ default_idx = -1
63
+ default_fairly = false
64
+
65
+ # Walk the priority patterns, extract each into its own bucket
66
+ priority_buckets.each do |bucket|
67
+ bucket_pattern = bucket.pattern
68
+ fairly = bucket.should_distribute_fairly
69
+
70
+ # note the position of the default bucket for inserting the remaining queues at that location
71
+ if bucket_pattern == ['default']
72
+ default_idx = result.size
73
+ default_fairly = fairly
74
+ next
75
+ end
76
+
77
+ bucket_queues, remaining = [], []
78
+
79
+ bucket_pattern.each do |pattern|
80
+ pattern = pattern.strip
81
+
82
+ if pattern =~ /^!/
83
+ negated = true
84
+ pattern = pattern[1..-1]
85
+ end
86
+
87
+ patstr = pattern.gsub(/\*/, ".*")
88
+ pattern = /^#{patstr}$/
89
+
90
+ if negated
91
+ bucket_queues -= bucket_queues.grep(pattern)
92
+ else
93
+ bucket_queues.concat(real_queues.grep(pattern))
94
+ end
95
+
96
+ end
97
+
98
+ bucket_queues.uniq!
99
+ bucket_queues.shuffle! if fairly
100
+ real_queues = real_queues - bucket_queues
101
+
102
+ result << bucket_queues
103
+ end
104
+
105
+ # insert the remaining queues at the position the default item was at (or last)
106
+ real_queues.shuffle! if default_fairly
107
+ result.insert(default_idx, real_queues)
108
+ result.flatten!
109
+
110
+ return result
111
+ end
112
+ end
113
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'sinatra/base'
4
4
  require 'reqless'
5
+ require 'reqless/queue_patterns_helper'
5
6
 
6
7
  module Reqless
7
8
  # The Reqless web interface
@@ -158,60 +159,6 @@ module Reqless
158
159
  formatted
159
160
  end
160
161
  end
161
-
162
- # Returns a list of queues to use when searching for a job.
163
- #
164
- # A splat ("*") means you want every queue (in alpha order) - this
165
- # can be useful for dynamically adding new queues.
166
- #
167
- # The splat can also be used as a wildcard within a queue name,
168
- # e.g. "*high*", and negation can be indicated with a prefix of "!"
169
- #
170
- # An @key can be used to dynamically look up the queue list for key from redis.
171
- # If no key is supplied, it defaults to the worker's hostname, and wildcards
172
- # and negations can be used inside this dynamic queue list. Set the queue
173
- # list for a key with set_dynamic_queue(key, ["q1", "q2"]
174
- #
175
- def expand_queues(queue_patterns, real_queues)
176
- queue_patterns = queue_patterns.dup
177
- real_queues = real_queues.dup
178
- dynamic_queues = client.queue_patterns.get_queue_identifier_patterns
179
-
180
- matched_queues = []
181
-
182
- while q = queue_patterns.shift
183
- q = q.to_s
184
- negated = false
185
-
186
- if q =~ /^(!)?@(.*)/
187
- key = $2.strip
188
- key = Socket.gethostname if key.size == 0
189
-
190
- add_queues = dynamic_queues[key]
191
- add_queues.map! { |q| q.gsub!(/^!/, '') || q.gsub!(/^/, '!') } if $1
192
-
193
- queue_patterns.concat(add_queues)
194
- next
195
- end
196
-
197
- if q =~ /^!/
198
- negated = true
199
- q = q[1..-1]
200
- end
201
-
202
- patstr = q.gsub(/\*/, ".*")
203
- pattern = /^#{patstr}$/
204
- if negated
205
- matched_queues -= matched_queues.grep(pattern)
206
- else
207
- matches = real_queues.grep(/^#{pattern}$/)
208
- matches = [q] if matches.size == 0 && q == patstr
209
- matched_queues.concat(matches)
210
- end
211
- end
212
-
213
- return matched_queues.uniq.sort
214
- end
215
162
  end
216
163
 
217
164
  get '/?' do
@@ -603,9 +550,11 @@ module Reqless
603
550
  @queues = []
604
551
  real_queues = client.queues.counts.collect {|q| q['name'] }
605
552
 
606
- dqueues = client.queue_patterns.get_queue_identifier_patterns
607
- dqueues.each do |k, v|
608
- expanded = expand_queues(["@#{k}"], real_queues)
553
+ queue_identifier_patterns = client.queue_patterns.get_queue_identifier_patterns
554
+ queue_identifier_patterns.each do |k, v|
555
+ expanded = QueuePatternsHelper.expand_queues(
556
+ ["@#{k}"], real_queues, queue_identifier_patterns
557
+ )
609
558
  expanded = expanded.collect { |q| q.split(":").last }
610
559
  view_data = {
611
560
  'name' => k,
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Reqless
4
4
  # VERSION is overwritten dynamically as part of the release process.
5
- VERSION = '0.0.4'
5
+ VERSION = '0.0.5'
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reqless
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Lecocq
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2024-08-28 00:00:00.000000000 Z
13
+ date: 2024-08-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: redis
@@ -303,9 +303,14 @@ files:
303
303
  - lib/reqless/config.rb
304
304
  - lib/reqless/failure_formatter.rb
305
305
  - lib/reqless/job.rb
306
+ - lib/reqless/job_reservers/delegating.rb
306
307
  - lib/reqless/job_reservers/ordered.rb
307
308
  - lib/reqless/job_reservers/round_robin.rb
308
309
  - lib/reqless/job_reservers/shuffled_round_robin.rb
310
+ - lib/reqless/job_reservers/strategies.rb
311
+ - lib/reqless/job_reservers/strategies/filtering.rb
312
+ - lib/reqless/job_reservers/strategies/ordering.rb
313
+ - lib/reqless/job_reservers/strategies/sources.rb
309
314
  - lib/reqless/lua/reqless-lib.lua
310
315
  - lib/reqless/lua/reqless.lua
311
316
  - lib/reqless/lua_script.rb
@@ -314,6 +319,7 @@ files:
314
319
  - lib/reqless/middleware/sentry.rb
315
320
  - lib/reqless/middleware/timeout.rb
316
321
  - lib/reqless/queue.rb
322
+ - lib/reqless/queue_patterns_helper.rb
317
323
  - lib/reqless/queue_priority_pattern.rb
318
324
  - lib/reqless/server.rb
319
325
  - lib/reqless/server/static/css/bootstrap-responsive.css