reqless 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +8 -0
  3. data/README.md +648 -0
  4. data/Rakefile +117 -0
  5. data/bin/docker-build-and-test +22 -0
  6. data/exe/reqless-web +11 -0
  7. data/lib/reqless/config.rb +31 -0
  8. data/lib/reqless/failure_formatter.rb +43 -0
  9. data/lib/reqless/job.rb +496 -0
  10. data/lib/reqless/job_reservers/ordered.rb +29 -0
  11. data/lib/reqless/job_reservers/round_robin.rb +46 -0
  12. data/lib/reqless/job_reservers/shuffled_round_robin.rb +21 -0
  13. data/lib/reqless/lua/reqless-lib.lua +2965 -0
  14. data/lib/reqless/lua/reqless.lua +2545 -0
  15. data/lib/reqless/lua_script.rb +90 -0
  16. data/lib/reqless/middleware/requeue_exceptions.rb +94 -0
  17. data/lib/reqless/middleware/retry_exceptions.rb +72 -0
  18. data/lib/reqless/middleware/sentry.rb +66 -0
  19. data/lib/reqless/middleware/timeout.rb +63 -0
  20. data/lib/reqless/queue.rb +189 -0
  21. data/lib/reqless/queue_priority_pattern.rb +16 -0
  22. data/lib/reqless/server/static/css/bootstrap-responsive.css +686 -0
  23. data/lib/reqless/server/static/css/bootstrap-responsive.min.css +12 -0
  24. data/lib/reqless/server/static/css/bootstrap.css +3991 -0
  25. data/lib/reqless/server/static/css/bootstrap.min.css +689 -0
  26. data/lib/reqless/server/static/css/codemirror.css +112 -0
  27. data/lib/reqless/server/static/css/docs.css +839 -0
  28. data/lib/reqless/server/static/css/jquery.noty.css +105 -0
  29. data/lib/reqless/server/static/css/noty_theme_twitter.css +137 -0
  30. data/lib/reqless/server/static/css/style.css +200 -0
  31. data/lib/reqless/server/static/favicon.ico +0 -0
  32. data/lib/reqless/server/static/img/glyphicons-halflings-white.png +0 -0
  33. data/lib/reqless/server/static/img/glyphicons-halflings.png +0 -0
  34. data/lib/reqless/server/static/js/bootstrap-alert.js +94 -0
  35. data/lib/reqless/server/static/js/bootstrap-scrollspy.js +125 -0
  36. data/lib/reqless/server/static/js/bootstrap-tab.js +130 -0
  37. data/lib/reqless/server/static/js/bootstrap-tooltip.js +270 -0
  38. data/lib/reqless/server/static/js/bootstrap-typeahead.js +285 -0
  39. data/lib/reqless/server/static/js/bootstrap.js +1726 -0
  40. data/lib/reqless/server/static/js/bootstrap.min.js +6 -0
  41. data/lib/reqless/server/static/js/codemirror.js +2972 -0
  42. data/lib/reqless/server/static/js/jquery.noty.js +220 -0
  43. data/lib/reqless/server/static/js/mode/javascript.js +360 -0
  44. data/lib/reqless/server/static/js/theme/cobalt.css +18 -0
  45. data/lib/reqless/server/static/js/theme/eclipse.css +25 -0
  46. data/lib/reqless/server/static/js/theme/elegant.css +10 -0
  47. data/lib/reqless/server/static/js/theme/lesser-dark.css +45 -0
  48. data/lib/reqless/server/static/js/theme/monokai.css +28 -0
  49. data/lib/reqless/server/static/js/theme/neat.css +9 -0
  50. data/lib/reqless/server/static/js/theme/night.css +21 -0
  51. data/lib/reqless/server/static/js/theme/rubyblue.css +21 -0
  52. data/lib/reqless/server/static/js/theme/xq-dark.css +46 -0
  53. data/lib/reqless/server/views/_job.erb +259 -0
  54. data/lib/reqless/server/views/_job_list.erb +8 -0
  55. data/lib/reqless/server/views/_pagination.erb +7 -0
  56. data/lib/reqless/server/views/about.erb +130 -0
  57. data/lib/reqless/server/views/completed.erb +11 -0
  58. data/lib/reqless/server/views/config.erb +14 -0
  59. data/lib/reqless/server/views/failed.erb +48 -0
  60. data/lib/reqless/server/views/failed_type.erb +18 -0
  61. data/lib/reqless/server/views/job.erb +17 -0
  62. data/lib/reqless/server/views/layout.erb +451 -0
  63. data/lib/reqless/server/views/overview.erb +137 -0
  64. data/lib/reqless/server/views/queue.erb +125 -0
  65. data/lib/reqless/server/views/queues.erb +45 -0
  66. data/lib/reqless/server/views/tag.erb +6 -0
  67. data/lib/reqless/server/views/throttles.erb +38 -0
  68. data/lib/reqless/server/views/track.erb +75 -0
  69. data/lib/reqless/server/views/worker.erb +34 -0
  70. data/lib/reqless/server/views/workers.erb +14 -0
  71. data/lib/reqless/server.rb +549 -0
  72. data/lib/reqless/subscriber.rb +74 -0
  73. data/lib/reqless/test_helpers/worker_helpers.rb +55 -0
  74. data/lib/reqless/throttle.rb +57 -0
  75. data/lib/reqless/version.rb +5 -0
  76. data/lib/reqless/worker/base.rb +237 -0
  77. data/lib/reqless/worker/forking.rb +215 -0
  78. data/lib/reqless/worker/serial.rb +41 -0
  79. data/lib/reqless/worker.rb +5 -0
  80. data/lib/reqless.rb +309 -0
  81. metadata +399 -0
data/lib/reqless.rb ADDED
@@ -0,0 +1,309 @@
1
+ # Encoding: utf-8
2
+
3
+ require 'socket'
4
+ require 'redis'
5
+ require 'json'
6
+ require 'securerandom'
7
+
8
+ module Reqless
9
+ # Define our error base class before requiring the other files so they can
10
+ # define subclasses.
11
+ Error = Class.new(StandardError)
12
+ end
13
+
14
+ require 'reqless/version'
15
+ require 'reqless/config'
16
+ require 'reqless/queue'
17
+ require 'reqless/queue_priority_pattern'
18
+ require 'reqless/throttle'
19
+ require 'reqless/job'
20
+ require 'reqless/lua_script'
21
+ require 'reqless/failure_formatter'
22
+
23
+ module Reqless
24
+ UnsupportedRedisVersionError = Class.new(Error)
25
+
26
+ def generate_jid
27
+ SecureRandom.uuid.gsub('-', '')
28
+ end
29
+
30
+ def stringify_hash_keys(hash)
31
+ hash.each_with_object({}) do |(key, value), result|
32
+ result[key.to_s] = value
33
+ end
34
+ end
35
+
36
+ def failure_formatter
37
+ @failure_formatter ||= FailureFormatter.new
38
+ end
39
+
40
+ module_function :generate_jid, :stringify_hash_keys, :failure_formatter
41
+
42
+ # A class for interacting with jobs. Not meant to be instantiated directly,
43
+ # it's accessed through Client#jobs
44
+ class ClientJobs
45
+ def initialize(client)
46
+ @client = client
47
+ end
48
+
49
+ def complete(offset = 0, count = 25)
50
+ JSON.parse(@client.call('jobs.completed', offset, count))
51
+ end
52
+
53
+ def tracked
54
+ results = JSON.parse(@client.call('jobs.tracked'))
55
+ results['jobs'] = results['jobs'].map { |j| Job.new(@client, j) }
56
+ results
57
+ end
58
+
59
+ def tagged(tag, offset = 0, count = 25)
60
+ results = JSON.parse(@client.call('jobs.tagged', tag, offset, count))
61
+ # Should be an empty array instead of an empty hash
62
+ results['jobs'] = [] if results['jobs'] == {}
63
+ results
64
+ end
65
+
66
+ def failed(t = nil, start = 0, limit = 25)
67
+ if !t
68
+ return JSON.parse(@client.call('failureGroups.counts'))
69
+ else
70
+ results = JSON.parse(@client.call('jobs.failedByGroup', t, start, limit))
71
+ results['jobs'] = multiget(*results['jobs'])
72
+ results
73
+ end
74
+ end
75
+
76
+ def [](id)
77
+ get(id)
78
+ end
79
+
80
+ def get(jid)
81
+ results = @client.call('job.get', jid)
82
+ if results.nil?
83
+ results = @client.call('recurringJob.get', jid)
84
+ return nil if results.nil?
85
+ return RecurringJob.new(@client, JSON.parse(results))
86
+ end
87
+ Job.new(@client, JSON.parse(results))
88
+ end
89
+
90
+ def multiget(*jids)
91
+ results = JSON.parse(@client.call('job.getMulti', *jids))
92
+ results.map do |data|
93
+ Job.new(@client, data)
94
+ end
95
+ end
96
+ end
97
+
98
+ # A class for interacting with workers. Not meant to be instantiated
99
+ # directly, it's accessed through Client#workers
100
+ class ClientWorkers
101
+ def initialize(client)
102
+ @client = client
103
+ end
104
+
105
+ def counts
106
+ JSON.parse(@client.call('workers.counts'))
107
+ end
108
+
109
+ def [](name)
110
+ JSON.parse(@client.call('worker.jobs', name))
111
+ end
112
+ end
113
+
114
+ # A class for interacting with queues. Not meant to be instantiated directly,
115
+ # it's accessed through Client#queues
116
+ class ClientQueues
117
+ def initialize(client)
118
+ @client = client
119
+ end
120
+
121
+ def counts
122
+ JSON.parse(@client.call('queues.counts'))
123
+ end
124
+
125
+ def [](name)
126
+ Queue.new(name, @client)
127
+ end
128
+ end
129
+
130
+ # A class for interacting with throttles. Not meant to be instantiated directly,
131
+ # it's accessed through Client#throttles
132
+ class ClientThrottles
133
+ def initialize(client)
134
+ @client = client
135
+ end
136
+
137
+ def [](name)
138
+ Throttle.new(name, @client)
139
+ end
140
+
141
+ def counts
142
+ @client.queues.counts.map do |queue|
143
+ Queue.new(queue['name'], @client).throttle
144
+ end
145
+ end
146
+ end
147
+
148
+ class ClientQueuePatterns
149
+ def initialize(client)
150
+ @client = client
151
+ end
152
+
153
+ def get_queue_identifier_patterns
154
+ serialized_patterns = @client.call('queueIdentifierPatterns.getAll')
155
+ identifiers_with_serialized_patterns = JSON.parse(serialized_patterns)
156
+ Hash[
157
+ identifiers_with_serialized_patterns.map do |identifier, serialized_pattern|
158
+ [identifier, JSON.parse(serialized_pattern)]
159
+ end
160
+ ]
161
+ end
162
+
163
+ def set_queue_identifier_patterns(identifier_patterns)
164
+ args = identifier_patterns.flat_map do |identifier, pattern|
165
+ [identifier, JSON.dump(pattern)]
166
+ end
167
+ @client.call('queueIdentifierPatterns.setAll', *args)
168
+ end
169
+
170
+ def get_queue_priority_patterns
171
+ serialized_priority_patterns_json = @client.call('queuePriorityPatterns.getAll')
172
+ serialized_priority_patterns = JSON.parse(serialized_priority_patterns_json)
173
+ serialized_priority_patterns.map do |serialized_priority_pattern|
174
+ priority_pattern = JSON.parse(serialized_priority_pattern)
175
+ QueuePriorityPattern.new(
176
+ priority_pattern['pattern'],
177
+ priority_pattern.fetch('fairly', false),
178
+ )
179
+ end
180
+ end
181
+
182
+ def set_queue_priority_patterns(queue_priority_patterns)
183
+ serialized_patterns = queue_priority_patterns.map do |queue_priority_pattern|
184
+ JSON.dump({
185
+ 'pattern': queue_priority_pattern.pattern,
186
+ 'fairly': queue_priority_pattern.should_distribute_fairly,
187
+ })
188
+ end
189
+ @client.call('queuePriorityPatterns.setAll', *serialized_patterns)
190
+ end
191
+ end
192
+
193
+ # A class for interacting with events. Not meant to be instantiated directly,
194
+ # it's accessed through Client#events
195
+ class ClientEvents
196
+ EVENTS = %w{canceled completed failed popped stalled put track untrack}
197
+ EVENTS.each do |method|
198
+ define_method(method.to_sym) do |&block|
199
+ @actions[method.to_sym] = block
200
+ end
201
+ end
202
+
203
+ def initialize(redis)
204
+ @redis = redis
205
+ @actions = {}
206
+ end
207
+
208
+ def listen
209
+ yield(self) if block_given?
210
+ channels = EVENTS.map { |event| "ql:#{event}" }
211
+ @redis.subscribe(channels) do |on|
212
+ on.message do |channel, message|
213
+ callback = @actions[channel.sub('ql:', '').to_sym]
214
+ callback.call(message) unless callback.nil?
215
+ end
216
+ end
217
+ end
218
+
219
+ def stop
220
+ @redis.unsubscribe
221
+ end
222
+ end
223
+
224
+ # The client for interacting with Reqless
225
+ class Client
226
+ attr_reader :_reqless, :config, :redis, :jobs, :queue_patterns, :queues, :throttles, :workers
227
+ attr_accessor :worker_name
228
+
229
+ def initialize(options = {})
230
+ default_options = {:ensure_minimum_version => true}
231
+ options = default_options.merge(options)
232
+
233
+ should_ensure_minimum_redis_version = options.delete(:ensure_minimum_version)
234
+ # This is the redis instance we're connected to. Use connect so REDIS_URL
235
+ # will be honored
236
+ @redis = options[:redis] || Redis.new(options)
237
+ @options = options
238
+ assert_minimum_redis_version('2.5.5') if should_ensure_minimum_redis_version
239
+ @config = Config.new(self)
240
+ @_reqless = Reqless::LuaScript.new('reqless', @redis, :on_reload_callback => @options[:on_lua_script_reload_callback])
241
+
242
+ @jobs = ClientJobs.new(self)
243
+ @queues = ClientQueues.new(self)
244
+ @throttles = ClientThrottles.new(self)
245
+ @queue_patterns = ClientQueuePatterns.new(self)
246
+ @workers = ClientWorkers.new(self)
247
+ @worker_name = [Socket.gethostname, Process.pid.to_s].join('-')
248
+ end
249
+
250
+ def inspect
251
+ "<Reqless::Client #{@options} >"
252
+ end
253
+
254
+ def events
255
+ # Events needs its own redis instance of the same configuration, because
256
+ # once it's subscribed, we can only use pub-sub-like commands. This way,
257
+ # we still have access to the client in the normal case
258
+ @events ||= ClientEvents.new(Redis.new(@options))
259
+ end
260
+
261
+ def call(command, *argv)
262
+ @_reqless.call(command, Time.now.to_f, *argv)
263
+ end
264
+
265
+ def track(jid)
266
+ call('job.track', jid)
267
+ end
268
+
269
+ def untrack(jid)
270
+ call('job.untrack', jid)
271
+ end
272
+
273
+ def tags(offset = 0, count = 100)
274
+ JSON.parse(call('tags.top', offset, count))
275
+ end
276
+
277
+ def deregister_workers(*worker_names)
278
+ call('worker.forget', *worker_names)
279
+ end
280
+
281
+ def bulk_cancel(jids)
282
+ call('job.cancel', jids)
283
+ end
284
+
285
+ def new_redis_connection
286
+ @redis.dup
287
+ end
288
+
289
+ def ==(other)
290
+ self.class == other.class && redis.id == other.redis.id
291
+ end
292
+ alias eql? ==
293
+
294
+ def hash
295
+ self.class.hash ^ redis.id.hash
296
+ end
297
+
298
+ private
299
+
300
+ def assert_minimum_redis_version(version)
301
+ # remove the "-pre2" from "2.6.8-pre2"
302
+ redis_version = @redis.info.fetch('redis_version').split('-').first
303
+ return if Gem::Version.new(redis_version) >= Gem::Version.new(version)
304
+
305
+ raise UnsupportedRedisVersionError,
306
+ "Reqless requires #{version} or better, not #{redis_version}"
307
+ end
308
+ end
309
+ end
metadata ADDED
@@ -0,0 +1,399 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: reqless
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dan Lecocq
8
+ - Myron Marston
9
+ - Danny Guinther
10
+ autorequire:
11
+ bindir: exe
12
+ cert_chain: []
13
+ date: 2024-08-25 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: redis
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: 5.1.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: 5.1.0
29
+ - !ruby/object:Gem::Dependency
30
+ name: capybara
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - "~>"
34
+ - !ruby/object:Gem::Version
35
+ version: 3.40.0
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - "~>"
41
+ - !ruby/object:Gem::Version
42
+ version: 3.40.0
43
+ - !ruby/object:Gem::Dependency
44
+ name: faye-websocket
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: 0.11.3
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: 0.11.3
57
+ - !ruby/object:Gem::Dependency
58
+ name: gem-release
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: 2.2.2
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: 2.2.2
71
+ - !ruby/object:Gem::Dependency
72
+ name: launchy
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: 3.0.0
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - "~>"
83
+ - !ruby/object:Gem::Version
84
+ version: 3.0.0
85
+ - !ruby/object:Gem::Dependency
86
+ name: metriks
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '0.9'
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - "~>"
97
+ - !ruby/object:Gem::Version
98
+ version: '0.9'
99
+ - !ruby/object:Gem::Dependency
100
+ name: pry
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - "~>"
104
+ - !ruby/object:Gem::Version
105
+ version: 0.14.2
106
+ type: :development
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - "~>"
111
+ - !ruby/object:Gem::Version
112
+ version: 0.14.2
113
+ - !ruby/object:Gem::Dependency
114
+ name: puma
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: 6.4.2
120
+ type: :development
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - "~>"
125
+ - !ruby/object:Gem::Version
126
+ version: 6.4.2
127
+ - !ruby/object:Gem::Dependency
128
+ name: rack
129
+ requirement: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - "~>"
132
+ - !ruby/object:Gem::Version
133
+ version: 3.0.10
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - "~>"
139
+ - !ruby/object:Gem::Version
140
+ version: 3.0.10
141
+ - !ruby/object:Gem::Dependency
142
+ name: rackup
143
+ requirement: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - "~>"
146
+ - !ruby/object:Gem::Version
147
+ version: 2.1.0
148
+ type: :development
149
+ prerelease: false
150
+ version_requirements: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - "~>"
153
+ - !ruby/object:Gem::Version
154
+ version: 2.1.0
155
+ - !ruby/object:Gem::Dependency
156
+ name: rake
157
+ requirement: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - "~>"
160
+ - !ruby/object:Gem::Version
161
+ version: '13.2'
162
+ type: :development
163
+ prerelease: false
164
+ version_requirements: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - "~>"
167
+ - !ruby/object:Gem::Version
168
+ version: '13.2'
169
+ - !ruby/object:Gem::Dependency
170
+ name: rspec
171
+ requirement: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - "~>"
174
+ - !ruby/object:Gem::Version
175
+ version: '3.13'
176
+ type: :development
177
+ prerelease: false
178
+ version_requirements: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - "~>"
181
+ - !ruby/object:Gem::Version
182
+ version: '3.13'
183
+ - !ruby/object:Gem::Dependency
184
+ name: rubocop
185
+ requirement: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - "~>"
188
+ - !ruby/object:Gem::Version
189
+ version: 0.13.1
190
+ type: :development
191
+ prerelease: false
192
+ version_requirements: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - "~>"
195
+ - !ruby/object:Gem::Version
196
+ version: 0.13.1
197
+ - !ruby/object:Gem::Dependency
198
+ name: rusage
199
+ requirement: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - "~>"
202
+ - !ruby/object:Gem::Version
203
+ version: 0.2.0
204
+ type: :development
205
+ prerelease: false
206
+ version_requirements: !ruby/object:Gem::Requirement
207
+ requirements:
208
+ - - "~>"
209
+ - !ruby/object:Gem::Version
210
+ version: 0.2.0
211
+ - !ruby/object:Gem::Dependency
212
+ name: selenium-webdriver
213
+ requirement: !ruby/object:Gem::Requirement
214
+ requirements:
215
+ - - "~>"
216
+ - !ruby/object:Gem::Version
217
+ version: 4.23.0
218
+ type: :development
219
+ prerelease: false
220
+ version_requirements: !ruby/object:Gem::Requirement
221
+ requirements:
222
+ - - "~>"
223
+ - !ruby/object:Gem::Version
224
+ version: 4.23.0
225
+ - !ruby/object:Gem::Dependency
226
+ name: sentry-raven
227
+ requirement: !ruby/object:Gem::Requirement
228
+ requirements:
229
+ - - "~>"
230
+ - !ruby/object:Gem::Version
231
+ version: '0.15'
232
+ type: :development
233
+ prerelease: false
234
+ version_requirements: !ruby/object:Gem::Requirement
235
+ requirements:
236
+ - - "~>"
237
+ - !ruby/object:Gem::Version
238
+ version: '0.15'
239
+ - !ruby/object:Gem::Dependency
240
+ name: simplecov
241
+ requirement: !ruby/object:Gem::Requirement
242
+ requirements:
243
+ - - "~>"
244
+ - !ruby/object:Gem::Version
245
+ version: 0.22.0
246
+ type: :development
247
+ prerelease: false
248
+ version_requirements: !ruby/object:Gem::Requirement
249
+ requirements:
250
+ - - "~>"
251
+ - !ruby/object:Gem::Version
252
+ version: 0.22.0
253
+ - !ruby/object:Gem::Dependency
254
+ name: sinatra
255
+ requirement: !ruby/object:Gem::Requirement
256
+ requirements:
257
+ - - "~>"
258
+ - !ruby/object:Gem::Version
259
+ version: 4.0.0
260
+ type: :development
261
+ prerelease: false
262
+ version_requirements: !ruby/object:Gem::Requirement
263
+ requirements:
264
+ - - "~>"
265
+ - !ruby/object:Gem::Version
266
+ version: 4.0.0
267
+ - !ruby/object:Gem::Dependency
268
+ name: timecop
269
+ requirement: !ruby/object:Gem::Requirement
270
+ requirements:
271
+ - - "~>"
272
+ - !ruby/object:Gem::Version
273
+ version: 0.9.8
274
+ type: :development
275
+ prerelease: false
276
+ version_requirements: !ruby/object:Gem::Requirement
277
+ requirements:
278
+ - - "~>"
279
+ - !ruby/object:Gem::Version
280
+ version: 0.9.8
281
+ description: "\n`reqless` is meant to be a performant alternative to other queueing\nsystems,
282
+ with statistics collection, a browser interface, and\nstrong guarantees about job
283
+ losses.\n\nIt's written as a collection of Lua scipts that are loaded into the\nRedis
284
+ instance to be used, and then executed by the client library.\nAs such, it's intended
285
+ to be extremely easy to port to other languages,\nwithout sacrificing performance
286
+ and not requiring a lot of logic\nreplication between clients. Keep the Lua scripts
287
+ updated, and your\nlanguage-specific extension will also remain up to date.\n "
288
+ email:
289
+ - dan@moz.com
290
+ - myron@moz.com
291
+ - dannyguinther@gmail.com
292
+ executables:
293
+ - reqless-web
294
+ extensions: []
295
+ extra_rdoc_files: []
296
+ files:
297
+ - Gemfile
298
+ - README.md
299
+ - Rakefile
300
+ - bin/docker-build-and-test
301
+ - exe/reqless-web
302
+ - lib/reqless.rb
303
+ - lib/reqless/config.rb
304
+ - lib/reqless/failure_formatter.rb
305
+ - lib/reqless/job.rb
306
+ - lib/reqless/job_reservers/ordered.rb
307
+ - lib/reqless/job_reservers/round_robin.rb
308
+ - lib/reqless/job_reservers/shuffled_round_robin.rb
309
+ - lib/reqless/lua/reqless-lib.lua
310
+ - lib/reqless/lua/reqless.lua
311
+ - lib/reqless/lua_script.rb
312
+ - lib/reqless/middleware/requeue_exceptions.rb
313
+ - lib/reqless/middleware/retry_exceptions.rb
314
+ - lib/reqless/middleware/sentry.rb
315
+ - lib/reqless/middleware/timeout.rb
316
+ - lib/reqless/queue.rb
317
+ - lib/reqless/queue_priority_pattern.rb
318
+ - lib/reqless/server.rb
319
+ - lib/reqless/server/static/css/bootstrap-responsive.css
320
+ - lib/reqless/server/static/css/bootstrap-responsive.min.css
321
+ - lib/reqless/server/static/css/bootstrap.css
322
+ - lib/reqless/server/static/css/bootstrap.min.css
323
+ - lib/reqless/server/static/css/codemirror.css
324
+ - lib/reqless/server/static/css/docs.css
325
+ - lib/reqless/server/static/css/jquery.noty.css
326
+ - lib/reqless/server/static/css/noty_theme_twitter.css
327
+ - lib/reqless/server/static/css/style.css
328
+ - lib/reqless/server/static/favicon.ico
329
+ - lib/reqless/server/static/img/glyphicons-halflings-white.png
330
+ - lib/reqless/server/static/img/glyphicons-halflings.png
331
+ - lib/reqless/server/static/js/bootstrap-alert.js
332
+ - lib/reqless/server/static/js/bootstrap-scrollspy.js
333
+ - lib/reqless/server/static/js/bootstrap-tab.js
334
+ - lib/reqless/server/static/js/bootstrap-tooltip.js
335
+ - lib/reqless/server/static/js/bootstrap-typeahead.js
336
+ - lib/reqless/server/static/js/bootstrap.js
337
+ - lib/reqless/server/static/js/bootstrap.min.js
338
+ - lib/reqless/server/static/js/codemirror.js
339
+ - lib/reqless/server/static/js/jquery.noty.js
340
+ - lib/reqless/server/static/js/mode/javascript.js
341
+ - lib/reqless/server/static/js/theme/cobalt.css
342
+ - lib/reqless/server/static/js/theme/eclipse.css
343
+ - lib/reqless/server/static/js/theme/elegant.css
344
+ - lib/reqless/server/static/js/theme/lesser-dark.css
345
+ - lib/reqless/server/static/js/theme/monokai.css
346
+ - lib/reqless/server/static/js/theme/neat.css
347
+ - lib/reqless/server/static/js/theme/night.css
348
+ - lib/reqless/server/static/js/theme/rubyblue.css
349
+ - lib/reqless/server/static/js/theme/xq-dark.css
350
+ - lib/reqless/server/views/_job.erb
351
+ - lib/reqless/server/views/_job_list.erb
352
+ - lib/reqless/server/views/_pagination.erb
353
+ - lib/reqless/server/views/about.erb
354
+ - lib/reqless/server/views/completed.erb
355
+ - lib/reqless/server/views/config.erb
356
+ - lib/reqless/server/views/failed.erb
357
+ - lib/reqless/server/views/failed_type.erb
358
+ - lib/reqless/server/views/job.erb
359
+ - lib/reqless/server/views/layout.erb
360
+ - lib/reqless/server/views/overview.erb
361
+ - lib/reqless/server/views/queue.erb
362
+ - lib/reqless/server/views/queues.erb
363
+ - lib/reqless/server/views/tag.erb
364
+ - lib/reqless/server/views/throttles.erb
365
+ - lib/reqless/server/views/track.erb
366
+ - lib/reqless/server/views/worker.erb
367
+ - lib/reqless/server/views/workers.erb
368
+ - lib/reqless/subscriber.rb
369
+ - lib/reqless/test_helpers/worker_helpers.rb
370
+ - lib/reqless/throttle.rb
371
+ - lib/reqless/version.rb
372
+ - lib/reqless/worker.rb
373
+ - lib/reqless/worker/base.rb
374
+ - lib/reqless/worker/forking.rb
375
+ - lib/reqless/worker/serial.rb
376
+ homepage: http://github.com/tdg5/reqless-rb
377
+ licenses:
378
+ - MIT
379
+ metadata: {}
380
+ post_install_message:
381
+ rdoc_options: []
382
+ require_paths:
383
+ - lib
384
+ required_ruby_version: !ruby/object:Gem::Requirement
385
+ requirements:
386
+ - - ">="
387
+ - !ruby/object:Gem::Version
388
+ version: '3.0'
389
+ required_rubygems_version: !ruby/object:Gem::Requirement
390
+ requirements:
391
+ - - ">="
392
+ - !ruby/object:Gem::Version
393
+ version: '0'
394
+ requirements: []
395
+ rubygems_version: 3.5.3
396
+ signing_key:
397
+ specification_version: 4
398
+ summary: A Redis-Based Queueing System
399
+ test_files: []