boy_band 0.1.7 → 0.1.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/boy_band.rb +133 -23
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ffb5fe1ca9cf6df69908f6d6e950041be2f31d7336ad327e9381b9065933a3f
4
- data.tar.gz: 32406d34eaea92673d35fc7384104044d63d91f3e66e63e0971f317c8ef26312
3
+ metadata.gz: b6d040e078153295146fa37e5781a107ad5aea4dd16727dc3d63bcd4e25821d2
4
+ data.tar.gz: ea5ae60dc466b1a660666d4db41d6c0a0e1b690f8ee2b9d2c1830936f9faae8a
5
5
  SHA512:
6
- metadata.gz: 588c0aee54c064f87a9213faa3d1dd13a9d649a49b74a882a6afe095b4eef4f953ef521911c30cf72ed9c3f7455653b5455c5bcff15d4cd280d5e45c97e38d93
7
- data.tar.gz: 225a3091fca7f2535d54fec0477b8c538ddb5ff8a290b36a80f9756ef80ed98591d2b2567679f0779221e819908850ec769d4268a3bf284082fcaebd3ded8db6
6
+ metadata.gz: db4df288e482fb66d80d370d522a64bb60c7d32d2aeb14eaaa2ddb03742cd78b00ed3455acb151f00168a0dcc6339c4ae44e4758293ba1085a9009cc42b3ea1c
7
+ data.tar.gz: 57ea5a67822e98c108c30ff200c971b68136f4a459069353d1899705ecc47eca1193829b701a8f56a36c8b49962c2f018edd179137110f3be5d3f673af045932
@@ -39,12 +39,22 @@ module BoyBand
39
39
  def set_job_chain(val)
40
40
  @@job_chain = val
41
41
  end
42
+
43
+ def queue_size(queue)
44
+ size = Resque.redis.get("sizeof/#{queue}").to_i
45
+ if !size || size == 0
46
+ size = Resque.size(queue)
47
+ Resque.redis.setex("sizeof/#{queue}", 30.seconds.to_i, size)
48
+ end
49
+ size
50
+ end
42
51
 
43
52
  def schedule_for(queue, klass, method_name, *args)
53
+ queue = queue.to_sym
44
54
  @queue = queue.to_s
45
55
  job_hash = Digest::MD5.hexdigest(args.to_json)
46
56
  note_job(job_hash)
47
- size = Resque.size(queue)
57
+ size = queue_size(queue)
48
58
  args.push("domain::#{self.domain_id}")
49
59
  chain = self.job_chain.split(/##/)
50
60
  job_id = "j#{Time.now.iso8601}_#{rand(9999)}"
@@ -53,10 +63,15 @@ module BoyBand
53
63
  Resque.redis.incr("jobs_from_#{chain[0]}")
54
64
  Resque.redis.expire("jobs_from_#{chain[0]}", 24.hours.to_i)
55
65
  end
56
- chain.push("#{klass.to_s},#{method_name.to_s},#{args.join('+')}")
66
+ Resque.redis.setex("scheduled/#{klass.to_s}/#{job_hash}", 6.hours, "t")
67
+ chain_args = args[0..-2]
68
+ if chain_args.length == 1 && chain_args[0].is_a?(Hash)
69
+ chain_args = [chain_args[0]['method'],chain_args[0]['id'],chain_args[0]['arguments'].to_s[0, 20]]
70
+ end
71
+ chain.push("#{klass.to_s},#{method_name.to_s},#{chain_args.join('+')}")
57
72
  Rails.logger.warn("jobchain set, #{chain[0]} #{chain.join('##')}") if chain.length > 2
58
73
  if chain.length > 5
59
- Rails.logger.error("jobchain too long: #{chain[0]}, #{chain.length} entries")
74
+ Rails.logger.error("jobchain too deep: #{chain[0]}, #{chain.length} entries")
60
75
  end
61
76
  job_count = Resque.redis.get("jobs_from_#{chain[0]}")
62
77
  if job_count && job_count.to_i > 50
@@ -79,21 +94,21 @@ module BoyBand
79
94
  end
80
95
 
81
96
  def note_job(hash)
82
- if Resque.redis
83
- timestamps = JSON.parse(Resque.redis.hget('hashed_jobs', hash) || "[]")
84
- cutoff = 6.hours.ago.to_i
85
- timestamps = timestamps.select{|ts| ts > cutoff }
86
- timestamps.push(Time.now.to_i)
87
- # Resque.redis.hset('hashed_jobs', hash, timestamps.to_json)
88
- end
97
+ # if Resque.redis
98
+ # timestamps = JSON.parse(Resque.redis.hget('hashed_jobs', hash) || "[]")
99
+ # cutoff = 6.hours.ago.to_i
100
+ # timestamps = timestamps.select{|ts| ts > cutoff }
101
+ # timestamps.push(Time.now.to_i)
102
+ # # Resque.redis.hset('hashed_jobs', hash, timestamps.to_json)
103
+ # end
89
104
  end
90
105
 
91
106
  def clear_job(hash)
92
- if Resque.redis
93
- timestamps = JSON.parse(Resque.redis.hget('hashed_jobs', hash) || "[]")
94
- timestamps.shift
95
- # Resque.redis.hset('hashed_jobs', hash, timestamps.to_json)
96
- end
107
+ # if Resque.redis
108
+ # timestamps = JSON.parse(Resque.redis.hget('hashed_jobs', hash) || "[]")
109
+ # timestamps.shift
110
+ # # Resque.redis.hset('hashed_jobs', hash, timestamps.to_json)
111
+ # end
97
112
  end
98
113
 
99
114
  def schedule(klass, method_name, *args)
@@ -111,8 +126,13 @@ module BoyBand
111
126
  def in_worker_process?
112
127
  BoyBand.job_instigator.match(/^job/)
113
128
  end
129
+
130
+ def current_speed
131
+ @speed
132
+ end
114
133
 
115
134
  def perform_at(speed, *args)
135
+ @speed = speed
116
136
  args_copy = [] + args
117
137
  if args_copy[-1].is_a?(String) && args_copy[-1].match(/^chain::/)
118
138
  set_job_chain(args_copy.pop.split(/::/, 2)[1])
@@ -124,6 +144,7 @@ module BoyBand
124
144
  klass = Object.const_get(klass_string)
125
145
  method_name = args_copy.shift
126
146
  job_hash = Digest::MD5.hexdigest(args_copy.to_json)
147
+ Resque.redis.del("scheduled/#{klass_string}/#{method_name}/#{job_hash}")
127
148
  hash = args_copy[0] if args_copy[0].is_a?(Hash)
128
149
  hash ||= {'method' => method_name}
129
150
  action = "#{klass_string} . #{hash['method']} (#{hash['id']})"
@@ -144,6 +165,7 @@ module BoyBand
144
165
  set_job_chain("none")
145
166
  BoyBand.set_job_instigator(pre_whodunnit)
146
167
  clear_job(job_hash)
168
+ @speed = nil
147
169
  rescue Resque::TermException
148
170
  Resque.enqueue(self, *args)
149
171
  end
@@ -178,6 +200,68 @@ module BoyBand
178
200
  end
179
201
  res
180
202
  end
203
+
204
+ def root_actions(queue='default')
205
+ idx = Resque.size(queue)
206
+ job_ids = {}
207
+ idx.times do |i|
208
+ item = Resque.peek(queue, i)
209
+ chain = nil
210
+ if item && item['args'] && item['args'][-1].match(/^chain::/)
211
+ chain = item['args'].pop
212
+ end
213
+ if chain
214
+ parts = chain.split(/##/)
215
+ job_ids[parts[0]] ||= [parts[1], 0, []]
216
+ job_ids[parts[0]][1] += 1
217
+ job_ids[parts[0]][2] << parts.length - 2
218
+ end
219
+ end
220
+ job_ids.each{|k, v| job_ids.delete(k) if v[1] <= 5}.length
221
+ job_ids
222
+ end
223
+
224
+ def action_types(queue='default')
225
+ idx = Resque.size(queue)
226
+ list = []
227
+ idx.times do |i|
228
+ item = Resque.peek(queue, i)
229
+ chain = nil
230
+ if item && item['args'] && item['args'][-1].match(/^chain::/)
231
+ chain = item['args'].pop
232
+ end
233
+ if chain
234
+ match = chain.scan(/##/)
235
+ if match && match.length == 1
236
+ item['root'] = true
237
+ list << item
238
+ elsif match && match.length > 1
239
+ list << item
240
+ end
241
+ end
242
+ end
243
+ count = {'root' => {}, 'non_root' => {}}
244
+ list.each do |item|
245
+ key = "#{item['args'][0]}::#{item['args'][2].is_a?(Hash) ? item['args'][2]['method'] : item['args'][1]}"
246
+ count[item['root'] ? 'root' : 'non_root'][key] ||= 0
247
+ count[item['root'] ? 'root' : 'non_root'][key] += 1
248
+ end.length
249
+ count
250
+ end
251
+
252
+ def find_actions(method)
253
+ queue = 'default'
254
+ idx = Resque.size(queue)
255
+ list = []
256
+ idx.times do |i|
257
+ item = Resque.peek(queue, i)
258
+ if item['args'] && item['args'][2].is_a?(Hash) && item['args'][2]['method'] == method
259
+ list << item
260
+ puts item.to_json
261
+ end
262
+ end
263
+ list
264
+ end
181
265
 
182
266
  def scheduled_for?(queue, klass, method_name, *args)
183
267
  args_copy = [] + args
@@ -188,6 +272,10 @@ module BoyBand
188
272
  set_domain_id(args_copy.pop.split(/::/, 2)[1])
189
273
  end
190
274
 
275
+ idx = queue_size(queue)
276
+ job_hash = args_copy.to_json
277
+ return true if Resque.redis.get("scheduled/#{klass.to_s}/#{method_name}/#{job_hash}") == "t"
278
+ return false if idx > 500 # big queues mustn't be searched this way
191
279
  idx = Resque.size(queue)
192
280
  queue_class = (queue == :slow ? 'SlowWorker' : 'Worker')
193
281
  if false
@@ -312,6 +400,10 @@ module BoyBand
312
400
 
313
401
  module AsyncInstanceMethods
314
402
  def schedule(method, *args)
403
+ schedule_for('default', method, *args)
404
+ end
405
+
406
+ def schedule_for(queue, method, *args)
315
407
  return nil unless method
316
408
  id = self.id
317
409
  settings = {
@@ -320,19 +412,23 @@ module BoyBand
320
412
  'scheduled' => self.class.scheduled_stamp,
321
413
  'arguments' => args
322
414
  }
323
- Worker.schedule(self.class, :perform_action, settings)
415
+ Worker.schedule_for(queue, self.class, :perform_action, settings)
324
416
  end
325
-
417
+
326
418
  def schedule_once(method, *args)
419
+ schedule_once_for('default', method, *args)
420
+ end
421
+
422
+ def schedule_once_for(queue, method, *args)
327
423
  return nil unless method && id
328
- already_scheduled = Worker.scheduled?(self.class, :perform_action, {
424
+ already_scheduled = Worker.scheduled_for?(queue, self.class, :perform_action, {
329
425
  'id' => id,
330
426
  'method' => method,
331
427
  'scheduled' => self.class.scheduled_stamp,
332
428
  'arguments' => args
333
429
  })
334
430
  if !already_scheduled
335
- schedule(method, *args)
431
+ schedule_for(queue, method, *args)
336
432
  else
337
433
  false
338
434
  end
@@ -357,23 +453,37 @@ module BoyBand
357
453
  'scheduled' => self.scheduled_stamp,
358
454
  'arguments' => args
359
455
  }
360
- Worker.schedule(self, :perform_action, settings)
456
+ schedule_for('default', method, *args)
361
457
  end
362
458
 
459
+ def schedule_for(queue, method, *args)
460
+ return nil unless method
461
+ settings = {
462
+ 'method' => method,
463
+ 'scheduled' => self.scheduled_stamp,
464
+ 'arguments' => args
465
+ }
466
+ Worker.schedule_for(queue, self, :perform_action, settings)
467
+ end
468
+
363
469
  def schedule_once(method, *args)
470
+ schedule_once_for('default', method, *args)
471
+ end
472
+
473
+ def schedule_once_for(queue, method, *args)
364
474
  return nil unless method
365
- already_scheduled = Worker.scheduled?(self, :perform_action, {
475
+ already_scheduled = Worker.scheduled_for?(queue, self, :perform_action, {
366
476
  'method' => method,
367
477
  'scheduled' => self.scheduled_stamp,
368
478
  'arguments' => args
369
479
  })
370
480
  if !already_scheduled
371
- schedule(method, *args)
481
+ schedule_for(queue, method, *args)
372
482
  else
373
483
  false
374
484
  end
375
485
  end
376
-
486
+
377
487
  def perform_action(settings)
378
488
  obj = self
379
489
  if settings['id']
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: boy_band
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Whitmer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-13 00:00:00.000000000 Z
11
+ date: 2020-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails