sideq 0.1.0

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 (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: []