rocketjob 1.1.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0791ec0844d63115ea5d7b5a1205fe21e72a635c
4
- data.tar.gz: 1898e2c267dce737cfa546796d700c72a06bcad7
3
+ metadata.gz: c742a1c093d122fbb2d6d9b194607d1ebd6743f3
4
+ data.tar.gz: 2998a334bf98a4624ac3c42b69c70c1a4a4dcaf8
5
5
  SHA512:
6
- metadata.gz: 14da955ecac4f0b1316c343de006c53d1df296c24c9982c72c48e4ca12631d1283e89e64b999d488a26907503e7b46801c5ace72096dd4b0d3f02c6631f4e001
7
- data.tar.gz: f97236b79cfab5ade58b30afebbd8ef05e462ef3f264c70860ab9cc8c2061257f6789bbc3b8d339f80a7d9ca1b17c7e6834678ca1b44958296683543e8adb32f
6
+ metadata.gz: b032a72a38db2aeb1f121cd65e5835fce438d77c1f6248560c40086fe4fb47f69815c83b8ac491188819ad0b4fea2a93e661015d7e38e0ccb1474e9b3e6c9505
7
+ data.tar.gz: f152e0cbd1af97f02674a5b47e8f9854f7cfac1c5fc509489b5ab30cd3c464ba11fc6ba41809687720a2caa18fd8dc2b7eaebc5a33fac2c6df7f411777089960
@@ -1,23 +1,27 @@
1
1
  require 'optparse'
2
+ require 'yaml'
2
3
  module RocketJob
3
4
  # Command Line Interface parser for RocketJob
4
5
  class CLI
5
- attr_reader :name, :threads, :environment, :pidfile, :directory, :quiet
6
+ include SemanticLogger::Loggable
7
+ attr_accessor :name, :threads, :environment, :pidfile, :directory, :quiet, :log_level
6
8
 
7
9
  def initialize(argv)
8
10
  @name = nil
9
11
  @threads = nil
10
12
  @quiet = false
11
- @environment = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
13
+ @environment = nil
12
14
  @pidfile = nil
13
15
  @directory = '.'
16
+ @log_level = nil
14
17
  parse(argv)
15
18
  end
16
19
 
17
20
  # Run a RocketJob::Worker from the command line
18
21
  def run
19
- SemanticLogger.add_appender(STDOUT, &SemanticLogger::Appender::Base.colorized_formatter) unless quiet
20
- boot_rails if defined?(:Rails)
22
+ setup_environment
23
+ setup_logger
24
+ boot_standalone unless boot_rails
21
25
  write_pidfile
22
26
 
23
27
  opts = {}
@@ -27,14 +31,28 @@ module RocketJob
27
31
  end
28
32
 
29
33
  # Initialize the Rails environment
34
+ # Returns [true|false] whether Rails is present
30
35
  def boot_rails
31
- require File.expand_path("#{directory}/config/environment.rb")
36
+ boot_file = Pathname.new(directory).join('config/environment.rb').expand_path
37
+ return false unless boot_file.file?
38
+
39
+ logger.info 'Booting Rails'
40
+ require boot_file.to_s
32
41
  if Rails.configuration.eager_load
33
42
  RocketJob::Worker.logger.benchmark_info('Eager loaded Rails and all Engines') do
34
43
  Rails.application.eager_load!
35
44
  Rails::Engine.subclasses.each(&:eager_load!)
36
45
  end
37
46
  end
47
+
48
+ self.class.load_config(Rails.env)
49
+ true
50
+ end
51
+
52
+ def boot_standalone
53
+ logger.info 'Rails not detected. Running standalone.'
54
+ self.class.load_config(environment)
55
+ self.class.eager_load_jobs
38
56
  end
39
57
 
40
58
  # Create a PID file if requested
@@ -49,6 +67,44 @@ module RocketJob
49
67
  end
50
68
  end
51
69
 
70
+ def setup_environment
71
+ # Override Env vars when environment is supplied
72
+ if environment
73
+ ENV['RACK_ENV'] = ENV['RAILS_ENV'] = environment
74
+ else
75
+ self.environment = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
76
+ end
77
+ end
78
+
79
+ def setup_logger
80
+ SemanticLogger.add_appender(STDOUT, &SemanticLogger::Appender::Base.colorized_formatter) unless quiet
81
+ SemanticLogger.default_level = log_level.to_sym if log_level
82
+ end
83
+
84
+ # Configure MongoMapper if it has not already been configured
85
+ def self.load_config(environment='development', file_name=nil)
86
+ return false if MongoMapper.config
87
+
88
+ config_file = file_name ? Pathname.new(file_name) : Pathname.pwd.join('config/mongo.yml')
89
+ if config_file.file?
90
+ config = YAML.load(ERB.new(config_file.read).result)
91
+ log = SemanticLogger::DebugAsTraceLogger.new('Mongo')
92
+ MongoMapper.setup(config, environment, logger: log)
93
+ true
94
+ else
95
+ raise(ArgumentError, "Mongo Configuration file: #{config_file.to_s} not found")
96
+ end
97
+ end
98
+
99
+ # Eager load files in jobs folder
100
+ def self.eager_load_jobs(path = 'jobs')
101
+ Pathname.glob("#{path}/**/*.rb").each do |path|
102
+ next if path.directory?
103
+ logger.debug "Loading #{path.to_s}"
104
+ load path.expand_path.to_s
105
+ end
106
+ end
107
+
52
108
  # Parse command line options placing results in the corresponding instance variables
53
109
  def parse(argv)
54
110
  parser = OptionParser.new do |o|
@@ -57,6 +113,7 @@ module RocketJob
57
113
  o.on('-q', '--quiet', 'Do not write to stdout, only to logfile. Necessary when running as a daemon') { @quiet = true }
58
114
  o.on('-d', '--dir DIR', 'Directory containing Rails app, if not current directory') { |arg| @directory = arg }
59
115
  o.on('-e', '--environment ENVIRONMENT', 'The environment to run the app on (Default: RAILS_ENV || RACK_ENV || development)') { |arg| @environment = arg }
116
+ o.on('-l', '--log_level trace|debug|info|warn|error|fatal', 'The log level to use') { |arg| @log_level = arg }
60
117
  o.on('--pidfile PATH', 'Use PATH as a pidfile') { |arg| @pidfile = arg }
61
118
  o.on('-v', '--version', 'Print the version information') do
62
119
  puts "Rocket Job v#{RocketJob::VERSION}"
@@ -6,9 +6,6 @@ module RocketJob
6
6
  module Worker
7
7
  def self.included(base)
8
8
  base.extend ClassMethods
9
- base.class_eval do
10
- @rocket_job_defaults = nil
11
- end
12
9
  end
13
10
 
14
11
  module ClassMethods
@@ -25,7 +22,13 @@ module RocketJob
25
22
 
26
23
  # Create a job and process it immediately in-line by this thread
27
24
  def now(method, *args, &block)
28
- job = build(method, *args, &block)
25
+ job = build(method, *args, &block)
26
+ # Call validations
27
+ if job.respond_to?(:validate!)
28
+ job.validate!
29
+ elsif job.invalid?
30
+ raise(MongoMapper::DocumentNotValid, "Validation failed: #{job.errors.messages.join(', ')}")
31
+ end
29
32
  worker = RocketJob::Worker.new(name: 'inline')
30
33
  worker.started
31
34
  job.start
@@ -43,7 +46,6 @@ module RocketJob
43
46
  # discarded, call #cleanup! to clear out any partially uploaded data
44
47
  def build(method, *args, &block)
45
48
  job = new(arguments: args, perform_method: method.to_sym)
46
- @rocket_job_defaults.call(job) if @rocket_job_defaults
47
49
  block.call(job) if block
48
50
  job
49
51
  end
@@ -63,12 +65,6 @@ module RocketJob
63
65
  now(:perform, *args, &block)
64
66
  end
65
67
 
66
- # Define job defaults
67
- def rocket_job(&block)
68
- @rocket_job_defaults = block
69
- self
70
- end
71
-
72
68
  # Returns the next job to work on in priority based order
73
69
  # Returns nil if there are currently no queued jobs, or processing batch jobs
74
70
  # with records that require processing
@@ -223,6 +223,12 @@ module RocketJob
223
223
  instance_method(method).arity
224
224
  end
225
225
 
226
+ # Override parent defaults
227
+ def self.rocket_job(&block)
228
+ @rocket_job_defaults = block
229
+ self
230
+ end
231
+
226
232
  # Returns [true|false] whether to collect the results from running this batch
227
233
  def collect_output?
228
234
  collect_output == true
@@ -313,14 +319,6 @@ module RocketJob
313
319
  end
314
320
  end
315
321
 
316
- # After this model is read, convert any hashes in the arguments list to HashWithIndifferentAccess
317
- def load_from_database(*args)
318
- super
319
- if arguments.present?
320
- self.arguments = arguments.collect { |i| i.is_a?(BSON::OrderedHash) ? i.with_indifferent_access : i }
321
- end
322
- end
323
-
324
322
  # Set exception information for this job and fail it
325
323
  def fail(worker_name='user', exc_or_message='Job failed through user action')
326
324
  if exc_or_message.is_a?(Exception)
@@ -360,7 +358,6 @@ module RocketJob
360
358
  aasm_fire_event(:requeue, persist: false)
361
359
  end
362
360
 
363
- ############################################################################
364
361
  protected
365
362
 
366
363
  # Before events that can be overridden by child classes
@@ -382,7 +379,7 @@ module RocketJob
382
379
 
383
380
  def before_retry
384
381
  self.completed_at = nil
385
- self.exception = nil
382
+ self.exception = nil
386
383
  end
387
384
 
388
385
  def before_pause
@@ -404,5 +401,26 @@ module RocketJob
404
401
  self.worker_name = nil
405
402
  end
406
403
 
404
+ private
405
+
406
+ # After this model is loaded, convert any hashes in the arguments list to HashWithIndifferentAccess
407
+ def load_from_database(*args)
408
+ super
409
+ if arguments.present?
410
+ self.arguments = arguments.collect { |i| i.is_a?(BSON::OrderedHash) ? i.with_indifferent_access : i }
411
+ end
412
+ end
413
+
414
+ def self.apply_defaults(job)
415
+ @rocket_job_defaults.call(job) if @rocket_job_defaults
416
+ end
417
+
418
+ # Apply RocketJob defaults after initializing default values
419
+ # but before setting attributes
420
+ def initialize_default_values(except = {})
421
+ super
422
+ self.class.apply_defaults(self)
423
+ end
424
+
407
425
  end
408
426
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: UTF-8
2
2
  module RocketJob #:nodoc
3
- VERSION = '1.1.3'
3
+ VERSION = '1.2.0'
4
4
  end
@@ -102,7 +102,9 @@ module RocketJob
102
102
  worker.save!
103
103
  create_indexes
104
104
  register_signal_handlers
105
- raise 'The RocketJob configuration is being applied after the system has been initialized' unless RocketJob::Job.database.name == RocketJob::SlicedJob.database.name
105
+ if defined?(RocketJobPro) && (RocketJob::Job.database.name != RocketJob::SlicedJob.database.name)
106
+ raise 'The RocketJob configuration is being applied after the system has been initialized'
107
+ end
106
108
  logger.info "Using MongoDB Database: #{RocketJob::Job.database.name}"
107
109
  worker.run
108
110
  end
@@ -245,9 +245,9 @@ class DirmonEntryTest < Minitest::Test
245
245
 
246
246
  describe '#later' do
247
247
  it 'enqueue job' do
248
- @entry.arguments = [{}]
248
+ @entry.arguments = [{}]
249
249
  @entry.perform_method = :event
250
- job = @entry.later(@pathname)
250
+ job = @entry.later(@pathname)
251
251
  assert_equal File.join(@archive_directory, "#{job.id}_#{File.basename(@file_name)}"), job.arguments.first[:full_file_name]
252
252
  assert job.queued?
253
253
  end
@@ -117,7 +117,7 @@ class DirmonJobTest < Minitest::Test
117
117
 
118
118
  it 'skip files in archive directory' do
119
119
  @entry.archive_directory = nil
120
- @entry.pattern = "#{@directory}/abc/**/*"
120
+ @entry.pattern = "#{@directory}/abc/**/*"
121
121
 
122
122
  create_file("#{@directory}/abc/file1", 5)
123
123
  create_file("#{@directory}/abc/file2", 10)
@@ -139,7 +139,7 @@ class DirmonJobTest < Minitest::Test
139
139
  "#{@directory}/abc/file1" => 5,
140
140
  "#{@directory}/abc/file2" => 10,
141
141
  }
142
- new_file_names = {
142
+ new_file_names = {
143
143
  "#{@directory}/abc/file1" => 10,
144
144
  "#{@directory}/abc/file2" => 10,
145
145
  }
@@ -165,28 +165,28 @@ class DirmonJobTest < Minitest::Test
165
165
  new_dirmon_job.destroy
166
166
  end
167
167
 
168
- it 'check directories and reschedule even on exception' do
169
- dirmon_job = nil
170
- RocketJob::Jobs::DirmonJob.destroy_all
171
- RocketJob::Jobs::DirmonJob.stub_any_instance(:check_directories, -> previous { raise RuntimeError.new("Oh no") }) do
172
- # perform_now does not save the job, just runs it
173
- dirmon_job = RocketJob::Jobs::DirmonJob.perform_now do |job|
174
- job.priority = 11
175
- job.check_seconds = 30
176
- end
168
+ it 'check directories and reschedule even on exception' do
169
+ dirmon_job = nil
170
+ RocketJob::Jobs::DirmonJob.destroy_all
171
+ RocketJob::Jobs::DirmonJob.stub_any_instance(:check_directories, -> previous { raise RuntimeError.new("Oh no") }) do
172
+ # perform_now does not save the job, just runs it
173
+ dirmon_job = RocketJob::Jobs::DirmonJob.perform_now do |job|
174
+ job.priority = 11
175
+ job.check_seconds = 30
177
176
  end
178
- assert dirmon_job.failed?, dirmon_job.status.inspect
177
+ end
178
+ assert dirmon_job.failed?, dirmon_job.status.inspect
179
179
 
180
- # It it have enqueued another instance to run in the future
181
- assert_equal 2, RocketJob::Jobs::DirmonJob.count
182
- assert new_dirmon_job = RocketJob::Jobs::DirmonJob.last
183
- assert new_dirmon_job.run_at
184
- assert_equal 11, new_dirmon_job.priority
185
- assert_equal 30, new_dirmon_job.check_seconds
186
- assert new_dirmon_job.queued?
180
+ # It it have enqueued another instance to run in the future
181
+ assert_equal 2, RocketJob::Jobs::DirmonJob.count
182
+ assert new_dirmon_job = RocketJob::Jobs::DirmonJob.last
183
+ assert new_dirmon_job.run_at
184
+ assert_equal 11, new_dirmon_job.priority
185
+ assert_equal 30, new_dirmon_job.check_seconds
186
+ assert new_dirmon_job.queued?
187
187
 
188
- new_dirmon_job.destroy
189
- end
188
+ new_dirmon_job.destroy
189
+ end
190
190
  end
191
191
 
192
192
  def create_file(file_name, size)
@@ -17,7 +17,8 @@ class JobTest < Minitest::Test
17
17
  @job2 = Jobs::TestJob.new(
18
18
  description: "#{@description} 2",
19
19
  arguments: @arguments,
20
- destroy_on_complete: false
20
+ destroy_on_complete: false,
21
+ priority: 52
21
22
  )
22
23
  end
23
24
 
@@ -64,7 +65,7 @@ class JobTest < Minitest::Test
64
65
  assert_nil @job.expires_at
65
66
  assert_equal @arguments, @job.arguments
66
67
  assert_equal 0, @job.percent_complete
67
- assert_equal 50, @job.priority
68
+ assert_equal 51, @job.priority
68
69
  assert_equal 0, @job.failure_count
69
70
  assert_nil @job.run_at
70
71
  assert_nil @job.started_at
@@ -268,6 +269,7 @@ class JobTest < Minitest::Test
268
269
 
269
270
  describe '.requeue_dead_worker' do
270
271
  it 'requeue jobs from dead workers' do
272
+ assert_equal 52, @job2.priority
271
273
  worker_name = 'server:12345'
272
274
  @job.worker_name = worker_name
273
275
  @job.start!
@@ -29,7 +29,7 @@ class WorkerTest < Minitest::Test
29
29
  assert_equal false, @job.destroy_on_complete
30
30
  assert_nil @job.expires_at
31
31
  assert_equal 0, @job.percent_complete
32
- assert_equal 50, @job.priority
32
+ assert_equal 51, @job.priority
33
33
  assert_equal 0, @job.failure_count
34
34
  assert_nil @job.run_at
35
35
  assert_nil @job.started_at
@@ -48,7 +48,7 @@ class WorkerTest < Minitest::Test
48
48
  assert_equal false, @job.destroy_on_complete
49
49
  assert_nil @job.expires_at
50
50
  assert_equal 100, @job.percent_complete
51
- assert_equal 50, @job.priority
51
+ assert_equal 51, @job.priority
52
52
  assert_equal 0, @job.failure_count
53
53
  assert_nil @job.run_at
54
54
  assert @job.started_at
@@ -1,6 +1,10 @@
1
1
  require 'rocketjob'
2
2
  module Jobs
3
3
  class TestJob < RocketJob::Job
4
+ rocket_job do |job|
5
+ job.priority = 51
6
+ end
7
+
4
8
  @@result = nil
5
9
 
6
10
  # For holding test results
@@ -39,4 +43,4 @@ module Jobs
39
43
  end
40
44
 
41
45
  end
42
- end
46
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rocketjob
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reid Morrison
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-02 00:00:00.000000000 Z
11
+ date: 2015-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aasm