workerholic 0.0.8 → 0.0.9

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/app_test/job_test.rb +1 -6
  4. data/app_test/run.rb +47 -39
  5. data/lib/workerholic/adapters/active_job_adapter.rb +8 -6
  6. data/lib/workerholic/cli.rb +11 -4
  7. data/lib/workerholic/job.rb +3 -2
  8. data/lib/workerholic/job_processor.rb +17 -6
  9. data/lib/workerholic/job_retry.rb +5 -2
  10. data/lib/workerholic/job_scheduler.rb +5 -2
  11. data/lib/workerholic/job_serializer.rb +8 -0
  12. data/lib/workerholic/job_statistics.rb +38 -0
  13. data/lib/workerholic/job_wrapper.rb +14 -5
  14. data/lib/workerholic/manager.rb +5 -0
  15. data/lib/workerholic/statistics_api.rb +77 -0
  16. data/lib/workerholic/statistics_storage.rb +19 -0
  17. data/lib/workerholic/storage.rb +25 -0
  18. data/lib/workerholic/version.rb +1 -1
  19. data/lib/workerholic/worker.rb +3 -0
  20. data/lib/workerholic/worker_balancer.rb +0 -1
  21. data/lib/workerholic.rb +7 -1
  22. data/pkg/workerholic-0.0.8.gem +0 -0
  23. data/spec/integration/enqueuing_jobs_spec.rb +5 -3
  24. data/spec/job_processor_spec.rb +7 -7
  25. data/spec/{statistics_spec.rb → job_statistics.rb} +10 -5
  26. data/spec/job_wrapper_spec.rb +7 -4
  27. data/spec/worker_spec.rb +2 -2
  28. data/web/application.rb +13 -6
  29. data/web/public/javascripts/application.js +109 -0
  30. data/web/public/stylesheets/application.css +30 -14
  31. data/web/views/details.erb +48 -31
  32. data/web/views/failed.erb +27 -0
  33. data/web/views/index.erb +38 -33
  34. data/web/views/layout.erb +36 -0
  35. data/web/views/queues.erb +31 -0
  36. data/web/views/scheduled.erb +27 -0
  37. data/web/views/workers.erb +41 -41
  38. metadata +13 -5
  39. data/lib/workerholic/statistics.rb +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: '02909e2b39a8d03796f21f57c2914f56a4b58a7b'
4
- data.tar.gz: 7696ea1dd34cf1df6c6ed21b5a627ea1ce1e4f48
3
+ metadata.gz: c3ace2785bcb5ca82bc4e0d0d5c738410140f3f6
4
+ data.tar.gz: 5829d09c00b963cff402dbe34126564b28af1386
5
5
  SHA512:
6
- metadata.gz: '03138c50a4edcc225af7d17b9a55cc7cf3799ac3a8612864768629b3685bfc2d67a8a798edcc758130b2543c1e04469338fbbe4129f0fd4b1bd61f3272f49b22'
7
- data.tar.gz: ff0cff28763276952f390d9b2263eb399a2c3910133f28d16d2015aea6c8f12c6dea1f0ac30b438f493e50af8c63ef30af4e1c81ad314d53b966764984a8c9e3
6
+ metadata.gz: 4d310181c5f824813425a6e6c3b249d27ee0baf0e27970cf4a40d6be3529237f95567b62f96a5e58904736e4d2a816c777379eb3bb4cd95593f6bc23c2b535cc
7
+ data.tar.gz: eabb0f28a65a6a6e46757fd58e136dfa9e628bc7ab00c544bd147cd54638bfdba5c2e046ca6ccc75593ee2f5ee42cd6acfd4bd01ab3b7a4d5bc6045e1a7542fb
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- workerholic (0.0.7)
4
+ workerholic (0.0.8)
5
5
  connection_pool (~> 2.2, >= 2.2.0)
6
6
  redis (~> 3.3, >= 3.3.3)
7
7
  sinatra
data/app_test/job_test.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'workerholic'
2
+ require 'prime'
2
3
 
3
4
  class JobTestFast
4
5
  include Workerholic::Job
@@ -15,7 +16,6 @@ class JobTestSlow
15
16
 
16
17
  def perform(str, num)
17
18
  sleep(0.5)
18
- puts "#{num} - #{str}"
19
19
  end
20
20
  end
21
21
 
@@ -23,7 +23,6 @@ class ThreadKiller
23
23
  include Workerholic::Job
24
24
 
25
25
  def perform(string, n)
26
- puts "#{n}. #{string}"
27
26
  Thread.main.kill
28
27
  end
29
28
  end
@@ -32,7 +31,6 @@ class LargeArg
32
31
  include Workerholic::Job
33
32
 
34
33
  def perform(arr, n)
35
- puts n
36
34
  end
37
35
  end
38
36
 
@@ -40,7 +38,6 @@ class ManyArgs
40
38
  include Workerholic::Job
41
39
 
42
40
  def perform(n, *args)
43
- puts "#{n}: #{args}"
44
41
  end
45
42
  end
46
43
 
@@ -50,7 +47,6 @@ class HeavyCalculation
50
47
 
51
48
  def perform(n, arr)
52
49
  arr = bubble_sort(arr)
53
- puts "#{n}: #{arr[0..9]}"
54
50
  end
55
51
 
56
52
  def bubble_sort(array)
@@ -79,6 +75,5 @@ class GetPrimes
79
75
  Prime.each(max) do |prime|
80
76
  prime
81
77
  end
82
- puts n
83
78
  end
84
79
  end
data/app_test/run.rb CHANGED
@@ -1,43 +1,51 @@
1
1
  require_relative 'job_test'
2
2
 
3
- # 100000.times do |n|
4
- # JobTestFast.new.perform_async('NONBLOCKING', n)
5
- # # sleep(0.0015)
6
- # end
7
-
8
- # 10000.times do |n|
9
- # JobTestSlow.new.perform_async('BLOCKING', n)
10
- # sleep(0.0015)
11
- # end
12
-
13
- # 100000.times do |n|
14
- # ThreadKiller.new.perform_async('Kill', n)
15
- # end
16
-
17
- # arg = Array.new(10000, 'string')
18
- # 10000.times do |n|
19
- # LargeArg.new.perform_async(arg, n)
20
- # end
21
-
22
- # unsorted_array = (1..10000).to_a.shuffle
23
- unsorted_array = (1..1000).to_a.shuffle
24
- 1000.times do |n|
25
- HeavyCalculation.new.perform_async(n, unsorted_array)
3
+ module TestRunner
4
+ def self.non_blocking(num_of_cycles)
5
+ num_of_cycles.times do |n|
6
+ JobTestFast.new.perform_async('NONBLOCKING', n)
7
+ end
8
+ end
9
+
10
+ def self.blocking(num_of_cycles)
11
+ num_of_cycles.times do |n|
12
+ JobTestSlow.new.perform_async('BLOCKING', n)
13
+ end
14
+ end
15
+
16
+ def self.thread_killer(num_of_cycles)
17
+ num_of_cycles.times do |n|
18
+ ThreadKiller.new.perform_async('Kill', n)
19
+ end
20
+ end
21
+
22
+ def self.large_arg(num_of_cycles)
23
+ arg = Array.new(10000, 'string')
24
+
25
+ num_of_cycles.times do |n|
26
+ LargeArg.new.perform_async(arg, n)
27
+ end
28
+ end
29
+
30
+ def self.sort_array(num_of_cycles, array_size)
31
+ unsorted_array = (0..array_size).to_a.shuffle
32
+
33
+ num_of_cycles.times do |n|
34
+ HeavyCalculation.new.perform_async(n, unsorted_array)
35
+ end
36
+ end
37
+
38
+ def self.many_args(num_of_cycles)
39
+ num_of_cycles.times do |n|
40
+ ManyArgs.new.perform_async(n, [1, 2, 3], { key: 'value'}, :symb, 'string', 22, false)
41
+ end
42
+ end
43
+
44
+ def self.calculate_primes(num_of_cycles)
45
+ num_of_cycles.times do |n|
46
+ GetPrimes.new.perform_async(n, 10)
47
+ end
48
+ end
26
49
  end
27
50
 
28
- 5_000.times do |n|
29
- JobTestFast.new.perform_async('NON BLOCKING', n)
30
- JobTestFast.new.perform_async('NON BLOCKING', n)
31
- # JobTestFast.new.perform_async('NON BLOCKING', n)
32
- # JobTestFast.new.perform_async('NON BLOCKING', n)
33
- # # JobTestSlow.new.perform_async('BLOCKING', n)
34
- JobTestSlow.new.perform_async('BLOCKING', n)
35
- end
36
-
37
- # 100000.times do |n|
38
- # ManyArgs.new.perform_async(n, [1, 2, 3], { key: 'value'}, :symb, 'string', 22, false)
39
- # end
40
-
41
- # 100000.times do |n|
42
- # GetPrimes.new.perform_async(n, 1000000)
43
- # end
51
+ TestRunner.non_blocking(2)
@@ -3,11 +3,15 @@ module ActiveJob
3
3
  class WorkerholicAdapter
4
4
  def enqueue(job)
5
5
  job_data = job.serialize
6
+ queue_name = "workerholic:queue:#{job_data['queue_name']}"
6
7
 
7
- JobWrapper.new.perform_async(
8
- class: job_data[:job_class],
9
- arguments: job_data[:arguments]
10
- )
8
+ job = JobWrapper.new
9
+ job.instance_variable_set(:@queue_name, queue_name)
10
+
11
+ # capture job class so it can be passed to `Base.execute` in `JobWrapper#perform`
12
+ job.instance_variable_set(:@class, job_data['job_class'])
13
+
14
+ job.perform_async(*job_data['arguments'])
11
15
  end
12
16
 
13
17
  class JobWrapper
@@ -19,6 +23,4 @@ module ActiveJob
19
23
  end
20
24
  end
21
25
  end
22
-
23
- autoload :WorkerholicAdapter
24
26
  end
@@ -29,7 +29,7 @@ module Workerholic
29
29
  OptionParser.new do |opts|
30
30
  opts.banner = 'Usage: workerholic [options]'
31
31
 
32
- opts.on '-ab', '--auto-balance', 'auto-balance workers based on number of jobs in each queue' do
32
+ opts.on '-a', '--auto-balance', 'auto-balance workers based on number of jobs in each queue' do
33
33
  options[:auto_balance] = true
34
34
  end
35
35
 
@@ -55,12 +55,19 @@ module Workerholic
55
55
  def load_app
56
56
  if File.exist?('./config/environment.rb')
57
57
  require File.expand_path('./config/environment.rb')
58
+
58
59
  require 'workerholic/adapters/active_job_adapter'
60
+
61
+ ActiveSupport.run_load_hooks(:before_eager_load, Rails.application)
62
+ Rails.application.config.eager_load_namespaces.each(&:eager_load!)
59
63
  elsif options[:require]
60
- if File.exist?(options[:require])
61
- require File.expand_path(options[:require])
64
+ file_path = File.expand_path(options[:require])
65
+
66
+ if File.exist?(file_path)
67
+ require file_path
62
68
  else
63
- log.info('The file you specified to load your application is not valid!')
69
+ logger.info('The file you specified to load your application is not valid!')
70
+
64
71
  exit
65
72
  end
66
73
  else
@@ -19,7 +19,7 @@ module Workerholic
19
19
  def perform_async(*args)
20
20
  serialized_job, queue_name = prepare_job_for_enqueueing(args)
21
21
 
22
- Queue.new(queue_name).enqueue(serialized_job)
22
+ Queue.new(@queue_name || queue_name).enqueue(serialized_job)
23
23
  end
24
24
 
25
25
  def perform_delayed(*args)
@@ -40,7 +40,8 @@ module Workerholic
40
40
  def prepare_job_for_enqueueing(args)
41
41
  raise ArgumentError if self.method(:perform).arity != args.size
42
42
 
43
- job = JobWrapper.new(class: self.class, arguments: args)
43
+ job = JobWrapper.new(klass: @class || self.class, arguments: args, wrapper: self.class)
44
+
44
45
  job.statistics.enqueued_at = Time.now.to_f
45
46
 
46
47
  [JobSerializer.serialize(job), specified_job_options[:queue_name]]
@@ -1,29 +1,40 @@
1
1
  module Workerholic
2
2
  class JobProcessor
3
+ attr_reader :serialized_job
4
+
3
5
  def initialize(serialized_job)
4
6
  @serialized_job = serialized_job
5
7
  @logger = LogManager.new
6
8
  end
7
9
 
8
10
  def process
9
- job = JobSerializer.deserialize(@serialized_job)
11
+ job = JobSerializer.deserialize(serialized_job)
10
12
 
11
13
  begin
12
14
  job.statistics.started_at = Time.now.to_f
13
15
  job_result = job.perform
14
16
  job.statistics.completed_at = Time.now.to_f
15
17
 
16
- # @logger.info("Completed: your job from class #{job.klass} was completed on #{job.statistics.completed_at}.")
18
+ StatsStorage.save_job('completed_jobs', job)
17
19
 
18
- job_result
20
+ @logger.info("Completed: your job from class #{job.klass} was completed on #{job.statistics.completed_at}.")
19
21
  rescue Exception => e
22
+
20
23
  job.statistics.errors.push([e.class, e.message])
21
- JobRetry.new(job: job)
24
+ retry_job(job)
22
25
 
23
- # @logger.error("Failed: your job from class #{job.class} was unsuccessful. Retrying in 10 seconds.")
26
+ @logger.error("Failed: your job from class #{job.class} was unsuccessful. Retrying in 10 seconds.")
24
27
  end
28
+ job_result
29
+ end
25
30
 
26
- # Push job into some collection
31
+ private
32
+
33
+ def retry_job(job)
34
+ limit_reached = JobRetry.new(job: job)
35
+ if limit_reached
36
+ job.statistics.failed_on = Time.now.to_f
37
+ end
27
38
  end
28
39
  end
29
40
  end
@@ -1,6 +1,6 @@
1
1
  module Workerholic
2
2
  class JobRetry
3
- attr_reader :job, :sorted_set
3
+ attr_reader :job, :sorted_set, :stats_storage
4
4
 
5
5
  def initialize(options={})
6
6
  @job = options[:job]
@@ -12,7 +12,10 @@ module Workerholic
12
12
  protected
13
13
 
14
14
  def retry
15
- return if job.retry_count >= 5
15
+ if job.retry_count >= 5
16
+ StatsStorage.save_job('failed_jobs', job)
17
+ return false
18
+ end
16
19
 
17
20
  increment_retry_count
18
21
  schedule_job_for_retry
@@ -5,7 +5,7 @@ module Workerholic
5
5
 
6
6
  def initialize(opts={})
7
7
  @sorted_set = SortedSet.new(opts[:set_name] || 'workerholic:scheduled_jobs')
8
- @queue = Queue.new(opts[:queue_name] || 'workerholic:main')
8
+ @queue = Queue.new(opts[:queue_name] || 'workerholic:queue:main')
9
9
  @alive = true
10
10
  end
11
11
 
@@ -35,12 +35,15 @@ module Workerholic
35
35
  queue.enqueue(serialized_job)
36
36
  end
37
37
  else
38
- sleep(5)
38
+ sleep(2)
39
39
  end
40
40
  end
41
41
 
42
42
  def kill
43
43
  self.alive = false
44
+ end
45
+
46
+ def join
44
47
  scheduler_thread.join if scheduler_thread
45
48
  end
46
49
  end
@@ -8,5 +8,13 @@ module Workerholic
8
8
  job_info = YAML.load(yaml_job)
9
9
  JobWrapper.new(job_info)
10
10
  end
11
+
12
+ def self.serialize_stats(stat)
13
+ YAML.dump(stat)
14
+ end
15
+
16
+ def self.deserialize_stats(yaml_stat)
17
+ YAML.load(yaml_stat)
18
+ end
11
19
  end
12
20
  end
@@ -0,0 +1,38 @@
1
+ module Workerholic
2
+ class JobStatistics
3
+
4
+ attr_accessor :enqueued_at,
5
+ :errors,
6
+ :started_at,
7
+ :completed_at,
8
+ :failed_on
9
+
10
+ def initialize(options={})
11
+ @enqueued_at = options[:enqueued_at]
12
+ @errors = options[:errors] || []
13
+ @started_at = options[:started_at]
14
+ @completed_at = options[:completed_at]
15
+ end
16
+
17
+ def to_hash
18
+ {
19
+ enqueued_at: enqueued_at,
20
+ errors: errors,
21
+ started_at: started_at,
22
+ completed_at: completed_at,
23
+ elapsed_time: elapsed_time,
24
+ failed_on: failed_on
25
+ }
26
+ end
27
+
28
+ def elapsed_time
29
+ if completed_at && started_at
30
+ format_elapsed_time(completed_at - started_at)
31
+ end
32
+ end
33
+
34
+ def format_elapsed_time(time)
35
+ '%.10f' % time
36
+ end
37
+ end
38
+ end
@@ -1,19 +1,21 @@
1
1
  module Workerholic
2
2
  class JobWrapper
3
3
  attr_accessor :retry_count, :execute_at
4
- attr_reader :klass, :arguments, :statistics
4
+ attr_reader :klass, :arguments, :statistics, :wrapper
5
5
 
6
6
  def initialize(options={})
7
- @klass = options[:class]
7
+ @klass = options[:klass]
8
+ @wrapper = options[:wrapper]
8
9
  @arguments = options[:arguments]
9
10
  @execute_at = options[:execute_at]
10
11
  @retry_count = options[:retry_count] || 0
11
- @statistics = Statistics.new(options[:statistics] || {})
12
+ @statistics = JobStatistics.new(options[:statistics] || {})
12
13
  end
13
14
 
14
15
  def to_hash
15
16
  {
16
- class: klass,
17
+ klass: klass,
18
+ wrapper: wrapper,
17
19
  arguments: arguments,
18
20
  retry_count: retry_count,
19
21
  execute_at: execute_at,
@@ -22,7 +24,14 @@ module Workerholic
22
24
  end
23
25
 
24
26
  def perform
25
- klass.new.perform(*arguments)
27
+ if wrapper == ActiveJob::QueueAdapters::WorkerholicAdapter::JobWrapper
28
+ wrapper.new.perform(
29
+ 'job_class' => klass,
30
+ 'arguments' => arguments
31
+ )
32
+ else
33
+ klass.new.perform(*arguments)
34
+ end
26
35
  end
27
36
 
28
37
  def ==(other)
@@ -26,8 +26,13 @@ module Workerholic
26
26
  workers.each(&:kill)
27
27
  worker_balancer.kill
28
28
  scheduler.kill
29
+
30
+ workers.each(&:join)
31
+ scheduler.join
29
32
  end
30
33
 
34
+ private
35
+
31
36
  =begin
32
37
  def regenerate_workers
33
38
  inactive_workers = WORKERS_COUNT - workers.size
@@ -0,0 +1,77 @@
1
+ module Workerholic
2
+ class StatsAPI
3
+ CATEGORIES = %w(completed_jobs failed_jobs)
4
+
5
+ def self.job_statistics(options={})
6
+ if CATEGORIES.include? options[:category]
7
+ job_classes = storage.keys_for_namespace(options[:category])
8
+
9
+ if options[:count_only]
10
+ self.parse_job_classes(job_classes)
11
+ else
12
+ self.parse_job_classes(job_classes, false)
13
+ end
14
+ else
15
+ logger("Invalid arguments. Please specify one of the following categories:\n'completed_jobs', 'failed_jobs'.")
16
+ end
17
+ end
18
+
19
+ def self.jobs_classes
20
+ classes = storage.available_keys
21
+
22
+ parsed_classes = classes.map do |klass|
23
+ klass.split(':').last
24
+ end.uniq
25
+
26
+ parsed_classes.empty? ? 'No class data is available yet.' : parsed_classes
27
+ end
28
+
29
+ def self.queue_names
30
+ fetched_queues = storage.fetch_queue_names
31
+ parsed_queues = fetched_queues.map do |queue|
32
+ queue_data = [queue.name, queue.size]
33
+ queues << queue_data
34
+ end
35
+
36
+ (parsed_queues.empty? ? 'No queues data is available yet.': parsed_queues)
37
+ end
38
+
39
+ class << self
40
+ private
41
+
42
+ def storage
43
+ @storage ||= Storage::RedisWrapper.new
44
+ end
45
+
46
+ def logger(message)
47
+ @log ||= LogManager.new
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def self.parse_job_classes(job_classes, count_only = true)
54
+ job_classes.map do |job_class|
55
+ if count_only
56
+ self.jobs_per_class(job_class)
57
+ else
58
+ self.get_jobs_for_class(job_class)
59
+ end
60
+ end
61
+ end
62
+
63
+ def self.get_jobs_for_class(job_class)
64
+ serialized_jobs = storage.peek_namespace(job_class)
65
+ deserialized_stats = serialized_jobs.map do |serialized_job|
66
+ JobSerializer.deserialize_stats(serialized_job)
67
+ end
68
+
69
+ deserialized_stats << deserialized_stats.size
70
+ end
71
+
72
+ def self.jobs_per_class(job_class)
73
+ clean_class_name = job_class.split(':').last
74
+ [clean_class_name, storage.list_length(job_class)]
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,19 @@
1
+ module Workerholic
2
+ class StatsStorage
3
+
4
+ def self.save_job(category, job)
5
+ serialized_job_stats = JobSerializer.serialize(job)
6
+
7
+ namespace = "workerholic:stats:#{category}:#{job.klass}"
8
+ storage.push(namespace, serialized_job_stats)
9
+ end
10
+
11
+ class << self
12
+ private
13
+
14
+ def storage
15
+ @storage ||= Storage::RedisWrapper.new
16
+ end
17
+ end
18
+ end
19
+ end
@@ -42,12 +42,37 @@ module Workerholic
42
42
  execute(retry_delay) { |conn| conn.zcount(key, 0, '+inf') }
43
43
  end
44
44
 
45
+ def keys_count(namespace, retry_delay = 5)
46
+ execute(retry_delay) { |conn| conn.keys(namespace + ':*').size }
47
+ end
48
+
45
49
  def fetch_queue_names(retry_delay = 5)
46
50
  queue_name_pattern = $TESTING ? 'workerholic:testing:queue*' : 'workerholic:queue*'
47
51
 
48
52
  execute(retry_delay) { |conn| conn.scan(0, match: queue_name_pattern).last }
49
53
  end
50
54
 
55
+ def available_keys(retry_delay = 5)
56
+ execute(retry_delay) { |conn| conn.keys('workerholic:stats:*') }
57
+ end
58
+
59
+ def keys_for_namespace(namespace, retry_delay = 5)
60
+ execute(retry_delay) { |conn| conn.keys('workerholic:stats:' + namespace + ':*') }
61
+ end
62
+
63
+ def peek_namespace(key, retry_delay = 5)
64
+ execute(retry_delay) { |conn| conn.lrange(key, 0, -1) }
65
+ end
66
+
67
+ def peek_namespaces(keys, retry_delay = 5)
68
+ execute(retry_delay) do |conn|
69
+ keys.select do |namespace|
70
+ full_namespace = 'workerholic:stats:' + namespace
71
+ conn.keys(full_namespace + ':*').size > 0
72
+ end
73
+ end
74
+ end
75
+
51
76
  class RedisCannotRecover < Redis::CannotConnectError; end
52
77
 
53
78
  private
@@ -1,3 +1,3 @@
1
1
  module Workerholic
2
- VERSION = '0.0.8'
2
+ VERSION = '0.0.9'
3
3
  end
@@ -26,6 +26,9 @@ module Workerholic
26
26
 
27
27
  def kill
28
28
  self.alive = false
29
+ end
30
+
31
+ def join
29
32
  thread.join if thread
30
33
  end
31
34
 
@@ -22,7 +22,6 @@ module Workerholic
22
22
 
23
23
  def kill
24
24
  thread.kill
25
- thread.join
26
25
  end
27
26
 
28
27
  private
data/lib/workerholic.rb CHANGED
@@ -18,11 +18,17 @@ require 'workerholic/job_retry'
18
18
  require 'workerholic/storage'
19
19
  require 'workerholic/sorted_set'
20
20
  require 'workerholic/queue'
21
+ require 'workerholic/statistics_storage'
21
22
 
22
23
  require 'workerholic/job_serializer'
23
- require 'workerholic/statistics'
24
+ require 'workerholic/job_statistics'
24
25
  require 'workerholic/log_manager'
25
26
 
27
+ require 'workerholic/statistics_api'
28
+ require 'workerholic/statistics_storage'
29
+
30
+ require 'workerholic/adapters/active_job_adapter' if defined?(Rails)
31
+
26
32
  module Workerholic
27
33
  def self.workers_count
28
34
  @workers_count || 25
Binary file
@@ -9,7 +9,7 @@ describe 'enqueuing jobs to Redis' do
9
9
  serialized_job = redis.lpop(TEST_QUEUE)
10
10
  job_from_redis = Workerholic::JobSerializer.deserialize(serialized_job)
11
11
 
12
- expected_job = Workerholic::JobWrapper.new(class: SimpleJobTest, arguments: ['test job'])
12
+ expected_job = Workerholic::JobWrapper.new(klass: SimpleJobTest, arguments: ['test job'], wrapper: SimpleJobTest)
13
13
  expected_job.statistics.enqueued_at = job_from_redis.statistics.enqueued_at
14
14
 
15
15
  expect(job_from_redis.to_hash).to eq(expected_job.to_hash)
@@ -21,9 +21,11 @@ describe 'enqueuing jobs to Redis' do
21
21
  job_from_redis = Workerholic::JobSerializer.deserialize(serialized_job)
22
22
 
23
23
  expected_job = Workerholic::JobWrapper.new(
24
- class: ComplexJobTest,
25
- arguments: ['test job', { a: 1, b: 2 }, [1, 2, 3]]
24
+ klass: ComplexJobTest,
25
+ arguments: ['test job', { a: 1, b: 2 }, [1, 2, 3]],
26
+ wrapper: ComplexJobTest
26
27
  )
28
+
27
29
  expected_job.statistics.enqueued_at = job_from_redis.statistics.enqueued_at
28
30
 
29
31
  expect(job_from_redis.to_hash).to eq(expected_job.to_hash)