jiggler 0.1.0.rc2

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 (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