sideq 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +34 -0
  3. data/bin/sideq +432 -0
  4. metadata +67 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ef82f3b0fe18b615a00dfc4964fd08ee922ec4d6
4
+ data.tar.gz: 1bd916c2d8de6ccd3dc43f6bfbf148e8fbe9d2f0
5
+ SHA512:
6
+ metadata.gz: 418ef5d4b642057ef8c8c79048ccb9017b701b294a89cb23ab42df93f2a3f6ef11fdb658c1d41c623752963272d94841217281f00ff5a2bc3e26b807f70ce4da
7
+ data.tar.gz: 4b28505a489e29aba7781bc4257efaa7e3c1f27141316c80b0a64a40f9b3794f2562653edf911d3e209d80f29a9226ee596d4c4887da608e780576ee8f1d7233
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # sideq
2
+ A CLI interface to the sidekiq api
3
+
4
+ # usage
5
+ sideq.rb --help
6
+
7
+ Usage: ./sideq.rb [options] command [subcommand]
8
+
9
+ Commands and subcommands:
10
+ stats Print sidekiq statistics
11
+ queue list List all known queues
12
+ retry list List contents of the retry set
13
+ retry show jid [jid ...] Show details of entrie sin the retry set
14
+ retry del jid [jid ...] Delete entries from the retry set
15
+ retry kill jid [jid ...] Move jobs from the retry set to the dead set
16
+ retry now jid [jid ...] Retry jobs in the retry set right now
17
+ retry clear Clears all entries in the retry set
18
+ dead list List contents of the dead set
19
+ dead show jid [jid...] Show details of entries in the dead set
20
+ dead del jid [jid...] Delete jobs from the dead set
21
+ dead now jid [jid...] Retry jobs from the dead set right now
22
+ dead clear Clears all entries of the dead set
23
+ processes list Lists all processes known to sidekiq
24
+ processes quiet Send the quiet signal to all sidekiq processes
25
+ processes kill Send the kill signal to all sidekiq processes
26
+ processes clean Clear dead process entries from the process list
27
+ workers list List all workers
28
+
29
+ Options:
30
+ -n, --database=redisdb Number of the redis database
31
+ -h, --host=hostname Hostname of the redis instance
32
+ -p, --port=port Portnumber of the redis instance
33
+ -u, --url redis_url URL to connect to (redis://host:port/db)
34
+ --help Prints this help
data/bin/sideq ADDED
@@ -0,0 +1,432 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'sidekiq'
5
+ require 'sidekiq/api'
6
+
7
+ RACK_ENV = ENV['RACK_ENV'] || "development"
8
+
9
+ class Parser
10
+ def self.parse(arguments)
11
+ options = { "host" => "localhost",
12
+ "port" => 6379,
13
+ "db" => 0 }
14
+
15
+ opt_parser = OptionParser.new do |opts|
16
+ opts.banner = "Usage: #{$0} [options] command [subcommand]\n" <<
17
+ "\n" <<
18
+ "Commands and subcommands:\n" <<
19
+ "stats Print sidekiq statistics\n" <<
20
+ "queue list List all known queues\n" <<
21
+ "retry list List contents of the retry set\n" <<
22
+ "retry show jid [jid ...] Show details of entrie sin the retry set\n" <<
23
+ "retry del jid [jid ...] Delete entries from the retry set\n" <<
24
+ "retry kill jid [jid ...] Move jobs from the retry set to the dead set\n" <<
25
+ "retry now jid [jid ...] Retry jobs in the retry set right now\n" <<
26
+ "retry clear Clears all entries in the retry set\n" <<
27
+ "dead list List contents of the dead set\n" <<
28
+ "dead show jid [jid...] Show details of entries in the dead set\n" <<
29
+ "dead del jid [jid...] Delete jobs from the dead set\n" <<
30
+ "dead now jid [jid...] Retry jobs from the dead set right now\n" <<
31
+ "dead clear Clears all entries of the dead set\n" <<
32
+ "processes list Lists all processes known to sidekiq\n" <<
33
+ "processes quiet Send the quiet signal to all sidekiq processes\n" <<
34
+ "processes kill Send the kill signal to all sidekiq processes\n" <<
35
+ "processes clean Clear dead process entries from the process list\n" <<
36
+ "workers list List all workers\n"
37
+ opts.separator "\nOptions:\n"
38
+
39
+ opts.on("-n redisdb", "--database=redisdb", "Number of the redis database") do |n|
40
+ options["db"] = n.to_i
41
+ end
42
+
43
+ opts.on("-h hostname", "--host=hostname", "Hostname of the redis instance") do |n|
44
+ options["host"] = n
45
+ end
46
+
47
+ opts.on("-p port", "--port=port", "Portnumber of the redis instance" ) do |n|
48
+ options["port"] = n.to_i
49
+ end
50
+
51
+ opts.on( "-u redis_url", "--url", "URL to connect to (redis://host:port/db)" ) do |n|
52
+ options["url"] = n
53
+ end
54
+
55
+ opts.on("--help", "Prints this help") do
56
+ puts opts
57
+ exit
58
+ end
59
+ end
60
+
61
+ opt_parser.parse!(arguments)
62
+ return options
63
+ end
64
+ end
65
+
66
+ class Stats
67
+ attr_reader :stats, :retry_set, :dead_set
68
+
69
+ def initialize
70
+ @stats = Sidekiq::Stats.new
71
+ @retry_set = Sidekiq::RetrySet.new
72
+ @dead_set = Sidekiq::DeadSet.new
73
+ end
74
+
75
+ def to_s
76
+ stat_ary = [ "Processed: #{stats.processed}",
77
+ "Failed: #{stats.failed}",
78
+ "Scheduled size: #{stats.scheduled_size}",
79
+ "Retry size: #{stats.retry_size}",
80
+ "Dead size: #{stats.dead_size}",
81
+ "Enqueued: #{stats.enqueued}",
82
+ "Processes: #{stats.processes_size}",
83
+ "Workers: #{stats.workers_size}",
84
+ "Default queue latency: #{stats.default_queue_latency}",
85
+
86
+ "Queues: dead: #{dead_set.size}",
87
+ " retry: #{retry_set.size}" ]
88
+ stats.queues.each do |(queue_name, queue_size)|
89
+ stat_ary << " #{queue_name}: #{queue_size}"
90
+ end
91
+
92
+ stat_ary.join( "\n" )
93
+ end
94
+ end
95
+
96
+ class Queues
97
+ attr_reader :retry_set, :dead_set
98
+
99
+ def initialize
100
+ @retry_set = Sidekiq::RetrySet.new
101
+ @dead_set = Sidekiq::DeadSet.new
102
+ end
103
+
104
+ def to_s
105
+ ary = Sidekiq::Queue.all.each_with_object( [] ) do |queue, memo|
106
+ memo << sprintf( "%-30s %5d (%8.2f s latency), %spaused",
107
+ queue.name,
108
+ queue.size,
109
+ queue.latency,
110
+ queue.paused? ? '' : "not " )
111
+ end
112
+ ary << sprintf( "%-30s %5d", "retry", retry_set.size )
113
+ ary << sprintf( "%-30s %5d", "dead", dead_set.size )
114
+ ary.join( "\n" )
115
+ end
116
+ end
117
+
118
+ class Retries
119
+ attr_reader :retry_set
120
+
121
+ def initialize
122
+ @retry_set = Sidekiq::RetrySet.new
123
+ end
124
+
125
+ def to_s
126
+ retry_set.each_with_object( [ "Retry entries: #{retry_set.size}" ] ) do |job, memo|
127
+ memo << sprintf( "%24s - %19s\n %-22s - %-37s\n e: %19s - f: %19s\n retry (%2d) at %-19s Continue retries?: %s\n %s\n",
128
+ job.jid,
129
+ job.created_at.strftime( "%F %T" ),
130
+ job.display_class,
131
+ job.item["error_class"],
132
+ job.enqueued_at.strftime( "%F %T" ),
133
+ Time.at( job.item["failed_at"] ).strftime( "%F %T" ),
134
+ job.item["retry_count"],
135
+ job.item["retried_at"] ? Time.at( job.item["retried_at"] ).strftime( "%F %T" ) : "never",
136
+ job.item["retry"],
137
+ "#{job.item["error_class"]}: #{job.item["error_message"][0,77-job.item["error_class"].size]}" )
138
+ end.join( "\n" )
139
+ end
140
+
141
+ def details( job_ids )
142
+ retry_set.each_with_object( [] ) do |job, memo|
143
+ next unless job_ids.include?( job.jid )
144
+ memo << job_details( job )
145
+ end.join( "\n\n" )
146
+ end
147
+
148
+ def delete_entries( job_ids )
149
+ deleted = 0
150
+ job_ids.each do |job_id|
151
+ # TODO: Inefficient in the free(beer) sidekiq version;
152
+ # find something more efficient here (sr 2016-04-06)
153
+ job = retry_set.find_job( job_id )
154
+ if job
155
+ job.delete
156
+ puts "#{job_id}: deleted"
157
+ deleted += 1
158
+ else
159
+ puts "#{job_id}: not found"
160
+ end
161
+ end
162
+ puts "Retry Set: Deleted #{deleted} entries"
163
+ end
164
+
165
+ def kill_entries( job_ids )
166
+ killed = 0
167
+ job_ids.each do |job_id|
168
+ # TODO: Inefficient in the free(beer) sidekiq version;
169
+ # find something more efficient here (sr 2016-04-06)
170
+ job = retry_set.find_job( job_id )
171
+ if job
172
+ begin
173
+ job.kill
174
+ puts "#{job_id}: moved to dead set"
175
+ killed += 1
176
+ rescue
177
+ puts "#{job_id}: failed - #{$!.message}"
178
+ end
179
+ else
180
+ puts "#{job_id}: not found"
181
+ end
182
+ end
183
+
184
+ puts "Retry Set: Moved #{killed} entries to Dead Set"
185
+ end
186
+
187
+ def retry_entries( job_ids )
188
+ retried = 0
189
+ job_ids.each do |job_id|
190
+ # TODO: Inefficient in the free(beer) sidekiq version;
191
+ # find something more efficient here (sr 2016-04-06)
192
+ job = retry_set.find_job( job_id )
193
+ if job
194
+ begin
195
+ job.retry
196
+ puts "#{job_id}: retrying"
197
+ retried += 1
198
+ rescue
199
+ puts "#{job_id}: failed - #{$!.message}"
200
+ end
201
+ else
202
+ puts "#{job_id}: not found"
203
+ end
204
+ end
205
+
206
+ puts "Retry Set: Retried #{retried} entries"
207
+ end
208
+
209
+ def clear
210
+ puts "Retry Set: Deleted #{retry_set.clear} entries"
211
+ end
212
+
213
+ protected
214
+ def job_details( job )
215
+ [ "JobID: #{job.jid}",
216
+ "Created at: #{job.created_at.strftime( "%F %T" )}",
217
+ "Enqueued at: #{job.enqueued_at.strftime( "%F %T")}",
218
+ "Worker class: #{job.display_class}",
219
+ "Arguments: #{job.display_args}",
220
+ "Failed at: #{Time.at( job.item["failed_at"] ).strftime( "%F %T" )}",
221
+ "Retried at: #{job.item["retried_at"] ? Time.at( job.item["retried_at"] ).strftime( "%F %T" ) : "never"}",
222
+ "Retries: #{job.item["retry_count"]}",
223
+ "Retry?: #{job.item["retry"]}",
224
+ "Error Class: #{job.item["error_class"]}",
225
+ "Error Message: #{job.item["error_message"]}" ].join( "\n" )
226
+ end
227
+ end
228
+
229
+ class Dead
230
+ attr_reader :dead_set
231
+
232
+ def initialize
233
+ @dead_set = Sidekiq::DeadSet.new
234
+ end
235
+
236
+ def to_s
237
+ dead_set.each_with_object( [ "Dead entries: #{dead_set.size}" ] ) do |job, memo|
238
+ memo << sprintf( "%24s - %19s\n %-22s - %-37s\n e: %19s - f: %19s\n retry (%2d) at %-19s Continue retries?: %s\n %s\n",
239
+ job.jid,
240
+ job.created_at.strftime( "%F %T" ),
241
+ job.display_class,
242
+ job.item["error_class"],
243
+ job.enqueued_at.strftime( "%F %T" ),
244
+ Time.at( job.item["failed_at"] ).strftime( "%F %T" ),
245
+ job.item["retry_count"],
246
+ job.item["retried_at"] ? Time.at( job.item["retried_at"] ).strftime( "%F %T" ) : "never",
247
+ job.item["retry"],
248
+ "#{job.item["error_class"]}: #{job.item["error_message"][0,77-job.item["error_class"].size]}" )
249
+ end.join( "\n" )
250
+ end
251
+
252
+ def details( job_ids )
253
+ dead_set.each_with_object( [] ) do |job, memo|
254
+ next unless job_ids.include?( job.jid )
255
+ memo << job_details( job )
256
+ end.join( "\n\n" )
257
+ end
258
+
259
+ def delete_entries( job_ids )
260
+ deleted = 0
261
+ job_ids.each do |job_id|
262
+ # TODO: Inefficient in the free(beer) sidekiq version;
263
+ # find something more efficient here (sr 2016-04-06)
264
+ job = dead_set.find_job( job_id )
265
+ if job
266
+ job.delete
267
+ puts "#{job_id}: deleted"
268
+ deleted += 1
269
+ else
270
+ puts "#{job_id}: not found"
271
+ end
272
+ end
273
+ puts "Dead Set: Deleted #{deleted} entries"
274
+ end
275
+
276
+ def retry_entries( job_ids )
277
+ retried = 0
278
+ job_ids.each do |job_id|
279
+ # TODO: Inefficient in the free(beer) sidekiq version;
280
+ # find something more efficient here (sr 2016-04-06)
281
+ job = dead_set.find_job( job_id )
282
+ if job
283
+ begin
284
+ job.retry
285
+ puts "#{job_id}: retrying"
286
+ retried += 1
287
+ rescue
288
+ puts "#{job_id}: failed - #{$!.message}"
289
+ end
290
+ else
291
+ puts "#{job_id}: not found"
292
+ end
293
+ end
294
+
295
+ puts "Dead Set: Retried #{retried} entries"
296
+ end
297
+
298
+ def clear
299
+ puts "Dead Set: Deleted #{dead_set.clear} entries"
300
+ end
301
+
302
+ protected
303
+ def job_details( job )
304
+ [ "JobID: #{job.jid}",
305
+ "Created at: #{job.created_at.strftime( "%F %T" )}",
306
+ "Enqueued at: #{job.enqueued_at.strftime( "%F %T")}",
307
+ "Worker class: #{job.display_class}",
308
+ "Arguments: #{job.display_args}",
309
+ "Failed at: #{Time.at( job.item["failed_at"] ).strftime( "%F %T" )}",
310
+ "Retried at: #{job.item["retried_at"] ? Time.at( job.item["retried_at"] ).strftime( "%F %T" ) : "never"}",
311
+ "Retries: #{job.item["retry_count"]}",
312
+ "Retry?: #{job.item["retry"]}",
313
+ "Error Class: #{job.item["error_class"]}",
314
+ "Error Message: #{job.item["error_message"]}"
315
+ ].join( "\n" )
316
+ end
317
+ end
318
+
319
+ class Processes
320
+ attr_reader :process_set
321
+
322
+ def initialize
323
+ @process_set = Sidekiq::ProcessSet.new
324
+ end
325
+
326
+ def to_s
327
+ process_set.each_with_object( ["Processes: #{process_set.size}"] ) do |process, memo|
328
+ memo << process.inspect
329
+ end.join( "\n" )
330
+ end
331
+
332
+ def quiet
333
+ size = process_set.size
334
+ process_set.each do |process|
335
+ process.quiet!
336
+ end
337
+ puts "Quieted #{size} processes"
338
+ end
339
+
340
+ def kill
341
+ size = process_set.size
342
+ process_set.each do |process|
343
+ process.kill!
344
+ end
345
+ puts "Killed #{size} processes"
346
+ end
347
+
348
+ def clean
349
+ cleaned_up = Sidekiq::ProcessSet.cleanup
350
+ puts "Cleaned up #{cleaned_up} processes"
351
+ end
352
+ end
353
+
354
+ class Workers
355
+ attr_reader :worker_set
356
+
357
+ def initialize
358
+ @worker_set = Sidekiq::Workers.new
359
+ end
360
+
361
+ def to_s
362
+ ary = [ "Workers: #{worker_set.size}" ]
363
+
364
+ worker_set.each do |key, tid, json|
365
+ ary << sprintf( "%15s %15s %20s\n", key, tid, json )
366
+ end
367
+
368
+ ary.join( "\n" )
369
+ end
370
+ end
371
+
372
+ options = Parser.parse( ARGV )
373
+
374
+ Sidekiq.configure_client do |config|
375
+ url = options["url"] ||"redis://#{options["host"]}:#{options["port"]}/#{options["db"]}"
376
+ config.redis = { :url => url, :size => 1 }
377
+ end
378
+
379
+ case ARGV.shift
380
+ when "stats" then puts Stats.new
381
+
382
+ when "queue"
383
+ case ARGV.shift
384
+ when "list" then puts Queues.new
385
+ else Parser.parse( %w[ --help ] )
386
+ end
387
+
388
+ when "retry"
389
+ retries = Retries.new
390
+
391
+ case ARGV.shift
392
+ when "list" then puts retries
393
+ when "show" then puts retries.details( ARGV )
394
+ when "del" then retries.delete_entries( ARGV )
395
+ when "kill" then retries.kill_entries( ARGV )
396
+ when "now" then retries.retry_entries( ARGV )
397
+ when "clear" then retries.clear
398
+ else Parser.parse( %w[ --help ] )
399
+ end
400
+
401
+ when "dead"
402
+ dead = Dead.new
403
+
404
+ case ARGV.shift
405
+ when "list" then puts dead
406
+ when "show" then puts dead.details( ARGV )
407
+ when "del" then dead.delete_entries( ARGV )
408
+ when "now" then dead.retry_entries( ARGV )
409
+ when "clear" then dead.clear
410
+ else Parser.parse( %w[ --help ] )
411
+ end
412
+
413
+ when "processes"
414
+ processes = Processes.new
415
+
416
+ case ARGV.shift
417
+ when "list" then puts processes
418
+ when "quiet" then processes.quiet
419
+ when "kill" then processes.kill
420
+ when "clean" then processes.clean
421
+ else Parser.parse( %w[ --help ] )
422
+ end
423
+
424
+ when "workers"
425
+ workers = Workers.new
426
+ case ARGV.shift
427
+ when "list" then puts workers
428
+ else Parser.parse( %w[ --help ] )
429
+ end
430
+
431
+ else Parser.parse( %w[ --help ] )
432
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sideq
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sven Riedel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-13 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.1'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 4.1.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '4.1'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 4.1.0
33
+ description: A command line tool to access the sidekiq api methods, making actions
34
+ available to shell scripts and command prompts
35
+ email: sr@gimp.org
36
+ executables:
37
+ - sideq
38
+ extensions: []
39
+ extra_rdoc_files: []
40
+ files:
41
+ - README.md
42
+ - bin/sideq
43
+ homepage: https://github.com/sriedel/sideq
44
+ licenses:
45
+ - GPL-2.0
46
+ metadata: {}
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubyforge_project:
63
+ rubygems_version: 2.5.1
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: Access the sidekiq api from the command line
67
+ test_files: []