jiggler 0.1.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +6 -0
  3. data/LICENSE +4 -0
  4. data/README.md +423 -0
  5. data/bin/jiggler +31 -0
  6. data/lib/jiggler/cleaner.rb +130 -0
  7. data/lib/jiggler/cli.rb +263 -0
  8. data/lib/jiggler/config.rb +165 -0
  9. data/lib/jiggler/core.rb +22 -0
  10. data/lib/jiggler/errors.rb +5 -0
  11. data/lib/jiggler/job.rb +116 -0
  12. data/lib/jiggler/launcher.rb +69 -0
  13. data/lib/jiggler/manager.rb +73 -0
  14. data/lib/jiggler/redis_store.rb +55 -0
  15. data/lib/jiggler/retrier.rb +122 -0
  16. data/lib/jiggler/scheduled/enqueuer.rb +78 -0
  17. data/lib/jiggler/scheduled/poller.rb +97 -0
  18. data/lib/jiggler/stats/collection.rb +26 -0
  19. data/lib/jiggler/stats/monitor.rb +103 -0
  20. data/lib/jiggler/summary.rb +101 -0
  21. data/lib/jiggler/support/helper.rb +35 -0
  22. data/lib/jiggler/version.rb +5 -0
  23. data/lib/jiggler/web/assets/stylesheets/application.css +64 -0
  24. data/lib/jiggler/web/views/application.erb +329 -0
  25. data/lib/jiggler/web.rb +80 -0
  26. data/lib/jiggler/worker.rb +179 -0
  27. data/lib/jiggler.rb +10 -0
  28. data/spec/examples.txt +79 -0
  29. data/spec/fixtures/config/jiggler.yml +4 -0
  30. data/spec/fixtures/jobs.rb +5 -0
  31. data/spec/fixtures/my_failed_job.rb +10 -0
  32. data/spec/fixtures/my_job.rb +9 -0
  33. data/spec/fixtures/my_job_with_args.rb +18 -0
  34. data/spec/jiggler/cleaner_spec.rb +171 -0
  35. data/spec/jiggler/cli_spec.rb +87 -0
  36. data/spec/jiggler/config_spec.rb +56 -0
  37. data/spec/jiggler/core_spec.rb +34 -0
  38. data/spec/jiggler/job_spec.rb +99 -0
  39. data/spec/jiggler/launcher_spec.rb +66 -0
  40. data/spec/jiggler/manager_spec.rb +52 -0
  41. data/spec/jiggler/redis_store_spec.rb +20 -0
  42. data/spec/jiggler/retrier_spec.rb +55 -0
  43. data/spec/jiggler/scheduled/enqueuer_spec.rb +81 -0
  44. data/spec/jiggler/scheduled/poller_spec.rb +40 -0
  45. data/spec/jiggler/stats/monitor_spec.rb +40 -0
  46. data/spec/jiggler/summary_spec.rb +168 -0
  47. data/spec/jiggler/web_spec.rb +37 -0
  48. data/spec/jiggler/worker_spec.rb +110 -0
  49. data/spec/spec_helper.rb +54 -0
  50. metadata +230 -0
@@ -0,0 +1,329 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Jiggler</title>
5
+ <style>
6
+ <%= styles %>
7
+ </style>
8
+ </head>
9
+ <body>
10
+ <h1>Jiggler</h1>
11
+ <div id='content'>
12
+
13
+ <div class='stats-block'>
14
+ <div class='stats-entry' title='Jobs to be retried'>
15
+ <span><%= "To Retry: #{@summary['retry_jobs_count']}" %></span>
16
+ </div>
17
+ <div class='stats-entry' title='Jobs with delayed enqueuing'>
18
+ <span><%= "Scheduled: #{@summary['scheduled_jobs_count']}" %></span>
19
+ </div>
20
+ <div class='stats-entry' title='Completely failed jobs'>
21
+ <span><%= "Dead: #{@summary['dead_jobs_count']}" %></span>
22
+ </div>
23
+ <div class='stats-entry' title='Unsuccessful perform attempts'>
24
+ <span><%= "Failures: #{@summary['failures_count']}" %></span>
25
+ </div>
26
+ <div class='stats-entry' title='Successfully completed jobs'>
27
+ <span><%= "Processed: #{@summary['processed_count']}" %></span>
28
+ </div>
29
+ </div>
30
+
31
+ <table class='main-table processes'>
32
+ <thead>
33
+ <tr>
34
+ <th colspan='5' title='Process'>
35
+ <span>Process</span>
36
+ </th>
37
+ <th colspan='1' title='PID'>
38
+ <span>PID</span>
39
+ </th>
40
+ <th colspan='2' title='Concurrency'>
41
+ <span>Concurrency</span>
42
+ </th>
43
+ <th colspan='2' title='RSS'>
44
+ <span>RSS</span>
45
+ </th>
46
+ <th colspan='1' title='Last Heartbeat'>
47
+ <span>Heartbeat</span>
48
+ </th>
49
+ <th colspan='1' title='Started'>
50
+ <span>Started</span>
51
+ </th>
52
+ </tr>
53
+ </thead>
54
+ <tbody>
55
+ <% @summary['processes'].each do |uuid, data| %>
56
+ <tr class=<%= heartbeat_class(data['heartbeat']) %>>
57
+ <td colspan='5' title='Process'>
58
+ <span><%= "#{data['name']} - #{data['hostname']}" %></span>
59
+ <%= poller_badge(data['poller_enabled']) %>
60
+ </br>
61
+ <span><i><%= data['queues'] %></i></span>
62
+ </td>
63
+ <td colspan='1' title='PID' class='right'>
64
+ <span><%= data['pid'] %></span>
65
+ </td>
66
+ <td colspan='2' title='Concurrency' class='right'>
67
+ <span><%= data['concurrency'] %></span>
68
+ </td>
69
+ <td colspan='2' title=<%= data['rss'] %> class='right'>
70
+ <span><%= format_memory(data['rss']) %></span>
71
+ </td>
72
+ <td colspan='1' title=<%= format_datetime(data['heartbeat']) %> class='right'>
73
+ <span><%= time_ago_in_words(data['heartbeat']) %></span>
74
+ </td>
75
+ <td colspan='1' title=<%= format_datetime(data['started_at']) %> class='right'>
76
+ <span><%= time_ago_in_words(data['started_at']) %></span>
77
+ </td>
78
+ </tr>
79
+ <% end %>
80
+ </tbody>
81
+ </table>
82
+
83
+ <table class='main-table queues'>
84
+ <thead>
85
+ <tr>
86
+ <th colspan='6' title='Queue'>
87
+ <span>Queues</span>
88
+ </th>
89
+ <th colspan='6' title='Size'>
90
+ <span>Size</span>
91
+ </th>
92
+ </tr>
93
+ </thead>
94
+ <tbody>
95
+ <% @summary['queues'].each do |queue| %>
96
+ <tr>
97
+ <td colspan='6' title='Queue'>
98
+ <span><i><%= queue[0] %></i></span>
99
+ </td>
100
+ <td colspan='6' title='Size' class='right'>
101
+ <span><%= queue[1] %></span>
102
+ </td>
103
+ </tr>
104
+ <% end %>
105
+ </tbody>
106
+ </table>
107
+
108
+ <h3>Busy Jobs</h3>
109
+ <table class='main-table jobs'>
110
+ <thead>
111
+ <tr>
112
+ <th colspan='2' title='Process'>
113
+ <span>Process</span>
114
+ </th>
115
+ <th colspan='2' title='Job'>
116
+ <span>Job</span>
117
+ </th>
118
+ <th colspan='1' title='JID'>
119
+ <span>JID</span>
120
+ </th>
121
+ <th colspan='1' title='TID'>
122
+ <span>TID</span>
123
+ </th>
124
+ <th colspan='2' title='Queue'>
125
+ <span>Queue</span>
126
+ </th>
127
+ <th colspan='2' title='Args'>
128
+ <span>Args</span>
129
+ </th>
130
+ <th colspan='2' title='Started'>
131
+ <span>Started</span>
132
+ </th>
133
+ </tr>
134
+ </thead>
135
+ <tbody>
136
+ <% @summary['processes'].each do |uuid, process_data| %>
137
+ <% process_data['current_jobs'].each do |tid, job_data| %>
138
+ <tr>
139
+ <td colspan='2' title='Process'>
140
+ <span><%= uuid %></span></br>
141
+ </td>
142
+ <td colspan='2' title='Job'>
143
+ <span><%= job_data['job_args']['name'] %></span>
144
+ </td>
145
+ <td colspan='1' title='JID'>
146
+ <span><%= job_data['jid'] %></span>
147
+ </td>
148
+ <td colspan='1' title='TID'>
149
+ <span><%= tid %></span>
150
+ </td>
151
+ <td colspan='2' title='Queue'>
152
+ <span><%= job_data['queue'] %></span>
153
+ </td>
154
+ <td colspan='2' title='Arguments'>
155
+ <span><%= format_args(job_data['job_args']['args']) %></span>
156
+ </td>
157
+ <td colspan='2' title=<%= format_datetime(data['started_at']) %>>
158
+ <span><%= time_ago_in_words(data['started_at']) %></span>
159
+ </td>
160
+ </tr>
161
+ <% end %>
162
+ <% end %>
163
+ </tbody>
164
+ </table>
165
+
166
+ <% if @summary['retry_jobs_count'] > 0 %>
167
+ <h3>Last 5 Jobs to Retry</h3>
168
+ <table class='main-table retry_jobs'>
169
+ <thead>
170
+ <tr>
171
+ <th colspan='1' title='Job'>
172
+ <span>Job</span>
173
+ </th>
174
+ <th colspan='1' title='JID'>
175
+ <span>JID</span>
176
+ </th>
177
+ <th colspan='1' title='Queue'>
178
+ <span>Queue</span>
179
+ </th>
180
+ <th colspan='1' title='Error'>
181
+ <span>Error</span>
182
+ </th>
183
+ <th colspan='2' title='Args'>
184
+ <span>Args</span>
185
+ </th>
186
+ <th colspan='1' title='Attempt'>
187
+ <span>Attempt</span>
188
+ </th>
189
+ <th colspan='1' title='Started'>
190
+ <span>Started</span>
191
+ </th>
192
+ <th colspan='1' title='Retried'>
193
+ <span>Retried</span>
194
+ </th>
195
+ <th colspan='1' title='To Retry At'>
196
+ <span>To Retry At</span>
197
+ </th>
198
+ </tr>
199
+ </thead>
200
+ <tbody>
201
+ <% last_5_retry_jobs.each do |data| %>
202
+ <tr>
203
+ <td colspan='1' title='Job'>
204
+ <span><%= data['name'] %></span>
205
+ </td>
206
+ <td colspan='1' title='JID'>
207
+ <span><%= data['jid'] %></span>
208
+ </td>
209
+ <td colspan='1' title='Queue'>
210
+ <span><%= data['queue'] %></span>
211
+ </td>
212
+ <td colspan='1' title='Error'>
213
+ <span><%= "#{data['error_class']}: #{data['error_message']}" %></span>
214
+ </td>
215
+ <td colspan='2' title='Args'>
216
+ <span><%= data['args'] %></span>
217
+ </td>
218
+ <td colspan='1' title='Attempt' class='right'>
219
+ <span><%= data['attempt'] %></span>
220
+ </td>
221
+ <td colspan='1' title=<%= format_datetime(data['started_at']) %> class='right'>
222
+ <span><%= time_ago_in_words(data['started_at']) %></span>
223
+ </td>
224
+ <td colspan='1' title=<%= format_datetime(data['retried_at']) %> class='right'>
225
+ <span><%= time_ago_in_words(data['retried_at']) %></span>
226
+ </td>
227
+ <td colspan='1' title=<%= format_datetime(data['retry_at']) %> class='right'>
228
+ <span><%= format_datetime(data['retry_at']) %></span>
229
+ </td>
230
+ </tr>
231
+ <% end %>
232
+ </tbody>
233
+ </table>
234
+ <% end %>
235
+
236
+ <% if @summary['scheduled_jobs_count'] > 0 %>
237
+ <h3>Last 5 Scheduled Jobs</h3>
238
+ <table class='main-table retry_jobs'>
239
+ <thead>
240
+ <tr>
241
+ <th colspan='4' title='Job'>
242
+ <span>Job</span>
243
+ </th>
244
+ <th colspan='6' title='Args'>
245
+ <span>Args</span>
246
+ </th>
247
+ <th colspan='2' title='Scheduled At'>
248
+ <span>To be enqueued at</span>
249
+ </th>
250
+ </tr>
251
+ </thead>
252
+ <tbody>
253
+ <% last_5_scheduled_jobs.each do |data| %>
254
+ <tr>
255
+ <td colspan='4' title='Job'>
256
+ <span><%= data['name'] %></span>
257
+ </td>
258
+ <td colspan='6' title='Args'>
259
+ <span><%= format_args(data['args']) %></span>
260
+ </td>
261
+ <td colspan='2' title=<%= format_datetime(data['scheduled_at']) %> class='right'>
262
+ <span><%= format_datetime(data['scheduled_at']) %></span>
263
+ </td>
264
+ </tr>
265
+ <% end %>
266
+ </tbody>
267
+ </table>
268
+ <% end %>
269
+
270
+ <% if @summary['dead_jobs_count'] > 0 %>
271
+ <h3>Last 5 Dead Jobs</h3>
272
+ <table class='main-table dead_jobs'>
273
+ <thead>
274
+ <tr>
275
+ <th colspan='2' title='Job'>
276
+ <span>Job</span>
277
+ </th>
278
+ <th colspan='1' title='JID'>
279
+ <span>JID</span>
280
+ </th>
281
+ <th colspan='1' title='Queue'>
282
+ <span>Queue</span>
283
+ </th>
284
+ <th colspan='2' title='Error'>
285
+ <span>Error</span>
286
+ </th>
287
+ <th colspan='2' title='Args'>
288
+ <span>Args</span>
289
+ </th>
290
+ <th colspan='1' title='Started'>
291
+ <span>Started</span>
292
+ </th>
293
+ <th colspan='1' title='Retried'>
294
+ <span>Retried</span>
295
+ </th>
296
+ </tr>
297
+ </thead>
298
+ <tbody>
299
+ <% last_5_dead_jobs.each do |data| %>
300
+ <tr>
301
+ <td colspan='2' title='Job'>
302
+ <span><%= data['name'] %></span>
303
+ </td>
304
+ <td colspan='1' title='JID'>
305
+ <span><%= data['jid'] %></span>
306
+ </td>
307
+ <td colspan='1' title='Queue'>
308
+ <span><%= data['queue'] %></span>
309
+ </td>
310
+ <td colspan='2' title='Error'>
311
+ <span><%= "#{data['error_class']}: #{data['error_message']}" %></span>
312
+ </td>
313
+ <td colspan='2' title='Args'>
314
+ <span><%= format_args(data['args']) %></span>
315
+ </td>
316
+ <td colspan='1' title=<%= format_datetime(data['started_at']) %> class='right'>
317
+ <span><%= time_ago_in_words(data['started_at']) %></span>
318
+ </td>
319
+ <td colspan='1' title=<%= format_datetime(data['retried_at']) %> class='right'>
320
+ <span><%= time_ago_in_words(data['retried_at']) %></span>
321
+ </td>
322
+ </tr>
323
+ <% end %>
324
+ </tbody>
325
+ </table>
326
+ <% end %>
327
+ </div>
328
+ </body>
329
+ </html>
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+
5
+ module Jiggler
6
+ class Web
7
+ WEB_PATH = File.expand_path("#{File.dirname(__FILE__)}/web")
8
+ LAYOUT = "#{WEB_PATH}/views/application.erb"
9
+ STYLESHEET = "#{WEB_PATH}/assets/stylesheets/application.css"
10
+
11
+ def call(env)
12
+ @summary_instance = Jiggler::Summary.new(Jiggler.config)
13
+ @summary = @summary_instance.all
14
+ compiled_template = ERB.new(File.read(LAYOUT)).result(binding)
15
+ [200, {}, [compiled_template]]
16
+ end
17
+
18
+ def last_5_dead_jobs
19
+ @summary_instance.last_dead_jobs(5)
20
+ end
21
+
22
+ def last_5_retry_jobs
23
+ @summary_instance.last_retry_jobs(5)
24
+ end
25
+
26
+ def last_5_scheduled_jobs
27
+ @summary_instance.last_scheduled_jobs(5)
28
+ end
29
+
30
+ def format_datetime(timestamp)
31
+ return if timestamp.nil?
32
+ Time.at(timestamp.to_f).to_datetime
33
+ end
34
+
35
+ def format_memory(kb)
36
+ return '?' if kb.nil?
37
+ "#{(kb/1024.0).round(2)} MB"
38
+ end
39
+
40
+ def time_ago_in_words(timestamp)
41
+ return if timestamp.nil?
42
+ seconds = Time.now.to_i - timestamp.to_i
43
+ case seconds
44
+ when 0..59
45
+ "#{seconds} seconds ago"
46
+ when 60..3599
47
+ "#{(seconds/60).round} minutes ago"
48
+ when 3600..86399
49
+ "#{(seconds/3600).round} hours ago"
50
+ when 86400..604799
51
+ "#{(seconds/86400).round} days ago"
52
+ else
53
+ "#{(seconds/604800).round} weeks ago"
54
+ end
55
+ end
56
+
57
+ def heartbeat_class(timestamp)
58
+ return 'outdated' if outdated_heartbeat?(timestamp)
59
+ end
60
+
61
+ def outdated_heartbeat?(timestamp)
62
+ return true if timestamp.nil?
63
+ seconds = Time.now.to_i - timestamp.to_i
64
+ seconds > Jiggler.config[:stats_interval] * 2
65
+ end
66
+
67
+ def format_args(args)
68
+ return if args.nil?
69
+ args.map { |arg| Oj.dump(arg, mode: :compat) }.join(', ')
70
+ end
71
+
72
+ def poller_badge(poller_enabled)
73
+ poller_enabled ? '<span class=\'badge badge-success\'>Polling</span>' : '<span class=\'badge\'>Polling Disabled</span>'
74
+ end
75
+
76
+ def styles
77
+ @styles ||= File.read(STYLESHEET)
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jiggler
4
+ class Worker
5
+ include Support::Helper
6
+ TIMEOUT = 2 # timeout for brpop
7
+
8
+ CurrentJob = Struct.new(:queue, :args, keyword_init: true)
9
+
10
+ attr_reader :current_job, :config, :done, :collection
11
+
12
+ def initialize(config, collection, &callback)
13
+ @done = false
14
+ @current_job = nil
15
+ @callback = callback
16
+ @config = config
17
+ @collection = collection
18
+ end
19
+
20
+ def run
21
+ reason = nil
22
+ @runner = safe_async('Worker') do
23
+ @tid = tid
24
+ loop do
25
+ if @done
26
+ @runner = nil
27
+ break @callback.call(self)
28
+ end
29
+
30
+ process_job
31
+
32
+ # pass control to other fibers
33
+ Async::Task.current.yield
34
+ rescue Async::Stop
35
+ @runner = nil
36
+ break @callback.call(self)
37
+ rescue => err
38
+ collection.incr_failures
39
+ @runner = nil
40
+ break @callback.call(self, err)
41
+ end
42
+ end
43
+ end
44
+
45
+ def terminate
46
+ @done = true
47
+ @runner&.stop
48
+ end
49
+
50
+ def suspend
51
+ @done = true
52
+ end
53
+
54
+ def wait
55
+ @runner&.wait
56
+ end
57
+
58
+ private
59
+
60
+ def process_job
61
+ @current_job = fetch_one
62
+ return if current_job.nil? # timed out brpop or done
63
+ execute_job
64
+ @current_job = nil
65
+ end
66
+
67
+ def fetch_one
68
+ queue, args = config.with_sync_redis { |conn| conn.blocking_call(false, 'BRPOP', *queues, TIMEOUT) }
69
+ return nil unless queue
70
+
71
+ if @done
72
+ requeue(queue, args)
73
+ nil
74
+ else
75
+ CurrentJob.new(queue: queue, args: args)
76
+ end
77
+ rescue Async::Stop => err
78
+ raise err
79
+ rescue => err
80
+ # error_message='undefined method `zero?' for nil:NilClass' context='Fetch error' tid=1tpj
81
+ # sometimes happens in async-pool-0.3.12/lib/async/pool/controller.rb:213:in `reuse'
82
+ handle_fetch_error(err)
83
+ nil
84
+ end
85
+
86
+ def execute_job
87
+ parsed_args = Oj.load(current_job.args, mode: :compat)
88
+ execute(parsed_args, current_job.queue)
89
+ rescue Async::Stop => err
90
+ raise err
91
+ rescue UnknownJobError => err
92
+ collection.incr_failures
93
+ log_error_short(
94
+ err,
95
+ {
96
+ error_class: err.class.name,
97
+ job: parsed_args,
98
+ tid: @tid
99
+ }
100
+ )
101
+ rescue JSON::ParserError => err
102
+ collection.incr_failures
103
+ logger.error('Worker') { "Failed to parse job: #{current_job.args}" }
104
+ rescue Exception => ex
105
+ log_error(
106
+ ex,
107
+ {
108
+ context: '\'Internal exception\'',
109
+ tid: @tid,
110
+ jid: parsed_args['jid']
111
+ }
112
+ )
113
+ # raise ex
114
+ end
115
+
116
+ def execute(parsed_job, queue)
117
+ instance = constantize(parsed_job['name']).new
118
+ add_current_job_to_collection(parsed_job, parsed_job['queue'])
119
+
120
+ retrier.wrapped(instance, parsed_job, queue) do
121
+ instance.perform(*parsed_job['args'])
122
+ end
123
+
124
+ collection.incr_processed
125
+ ensure
126
+ remove_current_job_from_collection
127
+ end
128
+
129
+ def retrier
130
+ @retrier ||= Jiggler::Retrier.new(config, collection)
131
+ end
132
+
133
+ def requeue(queue, args)
134
+ config.with_async_redis do |conn|
135
+ conn.call('RPUSH', queue, args)
136
+ end
137
+ end
138
+
139
+ def handle_fetch_error(ex)
140
+ log_error_short(
141
+ ex,
142
+ {
143
+ context: '\'Fetch error\'',
144
+ tid: @tid
145
+ }
146
+ )
147
+ sleep(TIMEOUT + rand(5) * config[:concurrency]) # sleep for a while before retrying
148
+ end
149
+
150
+ def add_current_job_to_collection(parsed_job, queue)
151
+ collection.data[:current_jobs][@tid] = {
152
+ job_args: parsed_job,
153
+ queue: queue,
154
+ started_at: Time.now.to_f
155
+ }
156
+ end
157
+
158
+ def remove_current_job_from_collection
159
+ collection.data[:current_jobs].delete(@tid)
160
+ end
161
+
162
+ def queues
163
+ @queues ||= config.prefixed_queues
164
+ end
165
+
166
+ def constantize(str)
167
+ return Object.const_get(str) unless str.include?('::')
168
+
169
+ names = str.split('::')
170
+ names.shift if names.empty? || names.first.empty?
171
+
172
+ names.inject(Object) do |constant, name|
173
+ constant.const_get(name, false)
174
+ end
175
+ rescue => err
176
+ raise UnknownJobError, 'Cannot initialize job'
177
+ end
178
+ end
179
+ end
data/lib/jiggler.rb ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # require only classes which are going to be used on the client side
4
+ require 'jiggler/redis_store'
5
+ require 'jiggler/config'
6
+ require 'jiggler/cleaner'
7
+ require 'jiggler/summary'
8
+ require 'jiggler/version'
9
+ require 'jiggler/core'
10
+ require 'jiggler/job'
data/spec/examples.txt ADDED
@@ -0,0 +1,79 @@
1
+ example_id | status | run_time |
2
+ ------------------------------------------------ | ------- | --------------- |
3
+ ./spec/jiggler/cleaner_spec.rb[1:1:1] | passed | 0.00079 seconds |
4
+ ./spec/jiggler/cleaner_spec.rb[1:2:1] | passed | 0.00104 seconds |
5
+ ./spec/jiggler/cleaner_spec.rb[1:3:1] | passed | 0.00427 seconds |
6
+ ./spec/jiggler/cleaner_spec.rb[1:4:1] | passed | 0.00071 seconds |
7
+ ./spec/jiggler/cleaner_spec.rb[1:5:1] | passed | 0.00079 seconds |
8
+ ./spec/jiggler/cleaner_spec.rb[1:6:1] | passed | 0.00071 seconds |
9
+ ./spec/jiggler/cleaner_spec.rb[1:7:1] | passed | 0.00063 seconds |
10
+ ./spec/jiggler/cleaner_spec.rb[1:8:1] | passed | 0.003 seconds |
11
+ ./spec/jiggler/cleaner_spec.rb[1:9:1] | passed | 0.00077 seconds |
12
+ ./spec/jiggler/cleaner_spec.rb[1:10:1] | passed | 0.00122 seconds |
13
+ ./spec/jiggler/cleaner_spec.rb[1:11:1] | passed | 0.00286 seconds |
14
+ ./spec/jiggler/cli_spec.rb[1:1:1:1] | passed | 0.00403 seconds |
15
+ ./spec/jiggler/cli_spec.rb[1:1:2:1] | passed | 0.76231 seconds |
16
+ ./spec/jiggler/cli_spec.rb[1:1:2:2] | passed | 0.00644 seconds |
17
+ ./spec/jiggler/cli_spec.rb[1:1:2:3] | passed | 0.00535 seconds |
18
+ ./spec/jiggler/cli_spec.rb[1:1:2:4] | passed | 0.0202 seconds |
19
+ ./spec/jiggler/cli_spec.rb[1:1:2:5] | passed | 0.004 seconds |
20
+ ./spec/jiggler/cli_spec.rb[1:1:2:6] | passed | 0.00955 seconds |
21
+ ./spec/jiggler/cli_spec.rb[1:1:2:7] | passed | 0.02139 seconds |
22
+ ./spec/jiggler/cli_spec.rb[1:1:2:8] | passed | 0.00429 seconds |
23
+ ./spec/jiggler/cli_spec.rb[1:1:2:9] | passed | 0.00746 seconds |
24
+ ./spec/jiggler/cli_spec.rb[1:1:3:1] | passed | 0.00336 seconds |
25
+ ./spec/jiggler/cli_spec.rb[1:1:3:2] | passed | 0.00497 seconds |
26
+ ./spec/jiggler/cli_spec.rb[1:1:3:3] | passed | 0.00312 seconds |
27
+ ./spec/jiggler/cli_spec.rb[1:1:3:4] | passed | 0.0086 seconds |
28
+ ./spec/jiggler/cli_spec.rb[1:1:3:5] | unknown | |
29
+ ./spec/jiggler/config_spec.rb[1:1:1] | passed | 0.00055 seconds |
30
+ ./spec/jiggler/config_spec.rb[1:1:2] | passed | 0.00057 seconds |
31
+ ./spec/jiggler/config_spec.rb[1:1:3] | passed | 0.00004 seconds |
32
+ ./spec/jiggler/config_spec.rb[1:1:4] | passed | 0.00004 seconds |
33
+ ./spec/jiggler/core_spec.rb[1:1:1] | passed | 0.00103 seconds |
34
+ ./spec/jiggler/job_spec.rb[1:1:1:1] | passed | 0.00007 seconds |
35
+ ./spec/jiggler/job_spec.rb[1:1:2:1] | passed | 0.0009 seconds |
36
+ ./spec/jiggler/job_spec.rb[1:2:1] | passed | 0.00064 seconds |
37
+ ./spec/jiggler/job_spec.rb[1:3:1] | passed | 0.00341 seconds |
38
+ ./spec/jiggler/job_spec.rb[1:4:1] | passed | 0.00051 seconds |
39
+ ./spec/jiggler/job_spec.rb[1:4:2] | passed | 0.00073 seconds |
40
+ ./spec/jiggler/job_spec.rb[1:5:1] | passed | 0.00051 seconds |
41
+ ./spec/jiggler/launcher_spec.rb[1:1:1] | passed | 0.00598 seconds |
42
+ ./spec/jiggler/launcher_spec.rb[1:2:1] | passed | 2.02 seconds |
43
+ ./spec/jiggler/launcher_spec.rb[1:3:1] | passed | 2.1 seconds |
44
+ ./spec/jiggler/launcher_spec.rb[1:4:1] | passed | 2.02 seconds |
45
+ ./spec/jiggler/manager_spec.rb[1:1] | passed | 0.00094 seconds |
46
+ ./spec/jiggler/manager_spec.rb[1:2:1] | passed | 1.53 seconds |
47
+ ./spec/jiggler/manager_spec.rb[1:3:1] | passed | 2.14 seconds |
48
+ ./spec/jiggler/manager_spec.rb[1:4:1] | passed | 3.56 seconds |
49
+ ./spec/jiggler/redis_store_spec.rb[1:1:1] | passed | 0.00073 seconds |
50
+ ./spec/jiggler/redis_store_spec.rb[1:1:2:1] | passed | 0.00071 seconds |
51
+ ./spec/jiggler/retrier_spec.rb[1:1:1:1] | passed | 0.02616 seconds |
52
+ ./spec/jiggler/retrier_spec.rb[1:1:1:2] | passed | 0.0143 seconds |
53
+ ./spec/jiggler/retrier_spec.rb[1:1:2:1] | passed | 0.01566 seconds |
54
+ ./spec/jiggler/scheduled/enqueuer_spec.rb[1:1:1] | passed | 0.01203 seconds |
55
+ ./spec/jiggler/scheduled/enqueuer_spec.rb[1:1:2] | passed | 0.02395 seconds |
56
+ ./spec/jiggler/scheduled/enqueuer_spec.rb[1:1:3] | passed | 0.0107 seconds |
57
+ ./spec/jiggler/scheduled/enqueuer_spec.rb[1:2:1] | passed | 0.03692 seconds |
58
+ ./spec/jiggler/scheduled/poller_spec.rb[1:1:1] | passed | 1.02 seconds |
59
+ ./spec/jiggler/scheduled/poller_spec.rb[1:2:1] | passed | 1.02 seconds |
60
+ ./spec/jiggler/stats/monitor_spec.rb[1:1:1] | passed | 2.02 seconds |
61
+ ./spec/jiggler/stats/monitor_spec.rb[1:2:1] | passed | 1.03 seconds |
62
+ ./spec/jiggler/summary_spec.rb[1:1:1] | passed | 0.00208 seconds |
63
+ ./spec/jiggler/summary_spec.rb[1:1:2] | passed | 3.04 seconds |
64
+ ./spec/jiggler/summary_spec.rb[1:1:3:1] | passed | 0.0076 seconds |
65
+ ./spec/jiggler/summary_spec.rb[1:2:1] | passed | 1.01 seconds |
66
+ ./spec/jiggler/summary_spec.rb[1:3:1] | passed | 1.01 seconds |
67
+ ./spec/jiggler/summary_spec.rb[1:4:1] | passed | 0.00461 seconds |
68
+ ./spec/jiggler/web_spec.rb[1:1:1] | passed | 0.00004 seconds |
69
+ ./spec/jiggler/web_spec.rb[1:1:2] | passed | 0.0005 seconds |
70
+ ./spec/jiggler/web_spec.rb[1:2:1] | passed | 0.00005 seconds |
71
+ ./spec/jiggler/web_spec.rb[1:2:2] | passed | 0.00044 seconds |
72
+ ./spec/jiggler/web_spec.rb[1:3:1] | passed | 0.00037 seconds |
73
+ ./spec/jiggler/web_spec.rb[1:3:2] | passed | 0.00004 seconds |
74
+ ./spec/jiggler/worker_spec.rb[1:1:1] | passed | 1.01 seconds |
75
+ ./spec/jiggler/worker_spec.rb[1:1:2] | passed | 1.01 seconds |
76
+ ./spec/jiggler/worker_spec.rb[1:1:3] | passed | 1.01 seconds |
77
+ ./spec/jiggler/worker_spec.rb[1:2:1] | passed | 0.00527 seconds |
78
+ ./spec/jiggler/worker_spec.rb[1:3:1:1] | passed | 2.05 seconds |
79
+ ./spec/jiggler/worker_spec.rb[1:3:2:1] | passed | 0.00371 seconds |
@@ -0,0 +1,4 @@
1
+ :concurrency: 1
2
+ :queues:
3
+ - users
4
+ - blep