rocketjob 0.8.0 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0ce24994db3b436019267874436049b46226fe54
4
- data.tar.gz: b34a433d970dab95a6f37fcf4d1db25002e17bf6
3
+ metadata.gz: c01cfe6dbadea5f8d327a520b68c7262b1bcff96
4
+ data.tar.gz: 4e52926f26dc216852bae81f780b48103a5625fe
5
5
  SHA512:
6
- metadata.gz: d9f00987987456c79446bab56247fc3c23cb91263d42e1d30957b539851952a5564c9f744e165132120ade41529834d949c1af6918d960c546e2cd76dafc5b74
7
- data.tar.gz: 77b5a354059d60f59b1f9c8f2f138f02a6817dd391ec7e05d8915998bfa0d98ae6aa1296c97dadc88ff8597e47aeb56122a1e8b526792b28e99b27dd662ff702
6
+ metadata.gz: 3286460b8ce4f27c31c47226b5d157c62541114f0c645b1260ff6cbe86cdd23f985bd6c180024b2812bf8b0ca650634e186f28faf0f5a87c0648a2cdd3edcff3
7
+ data.tar.gz: 26af31595e81983ab38e70fbc2b2d1c5101a876bfa2fcfdf9a465648e87269f42c70ee9fb580b9bfda6cfbacec18d67d36d502d235d3a22e0e7e8d5a372947af
data/README.md CHANGED
@@ -80,7 +80,7 @@ This differs from the traditional approach of separate queues for jobs which
80
80
  quickly becomes cumbersome when there are for example over a hundred different
81
81
  types of jobs.
82
82
 
83
- The global priority based queue ensures that the servers are utilized to their
83
+ The global priority based queue ensures that the workers are utilized to their
84
84
  capacity without requiring constant manual intervention.
85
85
 
86
86
  `rocketjob` is designed to handle hundreds of millions of concurrent jobs
@@ -15,7 +15,7 @@ module RocketJob
15
15
  parse(argv)
16
16
  end
17
17
 
18
- # Run a RocketJob::Server from the command line
18
+ # Run a RocketJob::Worker from the command line
19
19
  def run
20
20
  SemanticLogger.add_appender(STDOUT, &SemanticLogger::Appender::Base.colorized_formatter) unless quiet
21
21
  boot_rails if defined?(:Rails)
@@ -24,14 +24,14 @@ module RocketJob
24
24
  opts = {}
25
25
  opts[:name] = name if name
26
26
  opts[:max_threads] = threads if threads
27
- Server.run(opts)
27
+ Worker.run(opts)
28
28
  end
29
29
 
30
30
  # Initialize the Rails environment
31
31
  def boot_rails
32
32
  require File.expand_path("#{directory}/config/environment.rb")
33
33
  if Rails.configuration.eager_load
34
- RocketJob::Server.logger.benchmark_info('Eager loaded Rails and all Engines') do
34
+ RocketJob::Worker.logger.benchmark_info('Eager loaded Rails and all Engines') do
35
35
  Rails.application.eager_load!
36
36
  Rails::Engine.subclasses.each { |engine| engine.eager_load! }
37
37
  end
@@ -53,7 +53,7 @@ module RocketJob
53
53
  # Parse command line options placing results in the corresponding instance variables
54
54
  def parse(argv)
55
55
  parser = OptionParser.new do |o|
56
- o.on('-n', '--name NAME', 'Unique Name of this server instance (Default: hostname:PID)') { |arg| @name = arg }
56
+ o.on('-n', '--name NAME', 'Unique Name of this worker instance (Default: hostname:PID)') { |arg| @name = arg }
57
57
  o.on('-t', '--threads COUNT', 'Number of worker threads to start') { |arg| @threads = arg.to_i }
58
58
  o.on('-q', '--quiet', 'Do not write to stdout, only to logfile. Necessary when running as a daemon') { @quiet = true }
59
59
  o.on('-d', '--dir DIR', 'Directory containing Rails app, if not current directory') { |arg| @directory = arg }
@@ -29,10 +29,10 @@ module RocketJob
29
29
  # Create a job and process it immediately in-line by this thread
30
30
  def now(method, *args, &block)
31
31
  job = build(method, *args, &block)
32
- server = Server.new(name: 'inline')
33
- server.started
32
+ worker = RocketJob::Worker.new(name: 'inline')
33
+ worker.started
34
34
  job.start
35
- while job.running? && !job.work(server)
35
+ while job.running? && !job.work(worker)
36
36
  end
37
37
  job
38
38
  end
@@ -86,7 +86,7 @@ module RocketJob
86
86
  # is set in the job itself.
87
87
  #
88
88
  # Thread-safe, can be called by multiple threads at the same time
89
- def work(server)
89
+ def work(worker)
90
90
  raise 'Job must be started before calling #work' unless running?
91
91
  begin
92
92
  # before_perform
@@ -102,7 +102,7 @@ module RocketJob
102
102
  call_method(perform_method, arguments, event: :after, log_level: log_level)
103
103
  complete!
104
104
  rescue Exception => exc
105
- set_exception(server.name, exc)
105
+ set_exception(worker.name, exc)
106
106
  raise exc if RocketJob::Config.inline_mode
107
107
  end
108
108
  false
@@ -21,16 +21,16 @@ module RocketJob
21
21
  end
22
22
 
23
23
  # By enabling inline_mode jobs will be called in-line
24
- # No server processes will be created, nor threads created
24
+ # No worker processes will be created, nor threads created
25
25
  sync_cattr_accessor(:inline_mode) { false }
26
26
 
27
- # The maximum number of worker threads to create on any one server
27
+ # The maximum number of worker threads to create on any one worker
28
28
  key :max_worker_threads, Integer, default: 10
29
29
 
30
- # Number of seconds between heartbeats from Rocket Job Server processes
30
+ # Number of seconds between heartbeats from Rocket Job Worker processes
31
31
  key :heartbeat_seconds, Integer, default: 15
32
32
 
33
- # Maximum number of seconds a Server will wait before checking for new jobs
33
+ # Maximum number of seconds a Worker will wait before checking for new jobs
34
34
  key :max_poll_seconds, Integer, default: 5
35
35
 
36
36
  # Number of seconds between checking for:
@@ -44,21 +44,21 @@ module RocketJob
44
44
  # Not all job types support pausing in the middle
45
45
  key :re_check_seconds, Integer, default: 60
46
46
 
47
- # Limit the number of workers per job class per server
47
+ # Limit the number of workers per job class per worker
48
48
  # 'class_name' / group => 100
49
49
  #key :limits, Hash
50
50
 
51
51
  # Replace the MongoMapper default mongo connection for holding jobs
52
52
  def self.mongo_connection=(connection)
53
53
  connection(connection)
54
- Server.connection(connection)
54
+ Worker.connection(connection)
55
55
  Job.connection(connection)
56
56
  Config.connection(connection)
57
57
  DirmonEntry.connection(connection)
58
58
 
59
59
  db_name = connection.db.name
60
60
  set_database_name(db_name)
61
- Server.set_database_name(db_name)
61
+ Worker.set_database_name(db_name)
62
62
  Job.set_database_name(db_name)
63
63
  Config.set_database_name(db_name)
64
64
  DirmonEntry.set_database_name(db_name)
@@ -68,7 +68,7 @@ module RocketJob
68
68
  # Allows the records and results to be stored in a separate Mongo database
69
69
  # from the Jobs themselves.
70
70
  #
71
- # It is recommended to set the work_connection to a local Mongo Server that
71
+ # It is recommended to set the work_connection to a local Mongo Worker that
72
72
  # is not replicated to another data center to prevent flooding the network
73
73
  # with replication of data records and results.
74
74
  # The jobs themselves can/should be replicated across data centers so that
@@ -2,13 +2,13 @@
2
2
  module RocketJob
3
3
  # Heartbeat
4
4
  #
5
- # Information from the server as at it's last heartbeat
5
+ # Information from the worker as at it's last heartbeat
6
6
  class Heartbeat
7
7
  include MongoMapper::EmbeddedDocument
8
8
 
9
- embedded_in :server
9
+ embedded_in :worker
10
10
 
11
- # Time of the last heartbeat received from this server
11
+ # Time of the last heartbeat received from this worker
12
12
  key :updated_at, Time
13
13
 
14
14
  # Number of threads running as at the last heartbeat interval
@@ -21,9 +21,9 @@ module RocketJob
21
21
  # Process Information
22
22
  #
23
23
 
24
- # Percentage utilization for the server process alone
24
+ # Percentage utilization for the worker process alone
25
25
  key :process_cpu, Integer
26
- # Kilo Bytes used by the server process (Virtual & Physical)
26
+ # Kilo Bytes used by the worker process (Virtual & Physical)
27
27
  key :process_mem_phys_kb, Integer
28
28
  key :process_mem_virt_kb, Integer
29
29
 
@@ -94,8 +94,8 @@ module RocketJob
94
94
  # Number of times that this job has failed to process
95
95
  key :failure_count, Integer, default: 0
96
96
 
97
- # This name of the server that this job is being processed by, or was processed by
98
- key :server_name, String
97
+ # This name of the worker that this job is being processed by, or was processed by
98
+ key :worker_name, String
99
99
 
100
100
  #
101
101
  # Values that jobs can update during processing
@@ -196,11 +196,11 @@ module RocketJob
196
196
  ensure_index [[:created_at, 1]]
197
197
  end
198
198
 
199
- # Requeue all jobs for the specified dead server
200
- def self.requeue_dead_server(server_name)
199
+ # Requeue all jobs for the specified dead worker
200
+ def self.requeue_dead_worker(worker_name)
201
201
  collection.update(
202
- { 'server_name' => server_name, 'state' => :running },
203
- { '$unset' => { 'server_name' => true, 'started_at' => true }, '$set' => { 'state' => :queued } },
202
+ { 'worker_name' => worker_name, 'state' => :running },
203
+ { '$unset' => { 'worker_name' => true, 'started_at' => true }, '$set' => { 'state' => :queued } },
204
204
  multi: true
205
205
  )
206
206
  end
@@ -220,17 +220,18 @@ module RocketJob
220
220
  collect_output == true
221
221
  end
222
222
 
223
- # Returns [Time] how long the job has taken to complete
224
- # If not started then it is the time spent waiting in the queue
225
- def duration
226
- seconds = if completed_at
223
+ # Returns [Float] the number of seconds the job has taken
224
+ # - Elapsed seconds to process the job from when a worker first started working on it
225
+ # until now if still running, or until it was completed
226
+ # - Seconds in the queue if queued
227
+ def seconds
228
+ if completed_at
227
229
  completed_at - (started_at || created_at)
228
230
  elsif started_at
229
231
  Time.now - started_at
230
232
  else
231
233
  Time.now - created_at
232
234
  end
233
- Time.at(seconds)
234
235
  end
235
236
 
236
237
  # A job has expired if the expiry time has passed before it is started
@@ -239,28 +240,46 @@ module RocketJob
239
240
  end
240
241
 
241
242
  # Returns [Hash] status of this job
242
- def status(time_zone='Eastern Time (US & Canada)')
243
- h = {
244
- state: state,
245
- description: description
246
- }
247
- h[:started_at] = started_at.in_time_zone(time_zone) if started_at
248
-
243
+ def as_json
244
+ attrs = serializable_hash(methods: :seconds)
245
+ attrs.delete('result') unless collect_output?
249
246
  case
250
- when running? || paused?
251
- h[:paused_at] = completed_at.in_time_zone(time_zone) if paused?
252
- h[:percent_complete] = percent_complete if percent_complete
253
- when completed?
254
- h[:completed_at] = completed_at.in_time_zone(time_zone)
247
+ when running?
248
+ attrs.delete('completed_at')
249
+ attrs.delete('result')
250
+ attrs
251
+ when paused?
252
+ attrs.delete('completed_at')
253
+ attrs.delete('result')
254
+ # Ensure 'paused_at' appears first in the hash
255
+ { 'paused_at' => completed_at }.merge(attrs)
255
256
  when aborted?
256
- h[:aborted_at] = completed_at.in_time_zone(time_zone)
257
- h[:percent_complete] = percent_complete if percent_complete
257
+ attrs.delete('completed_at')
258
+ attrs.delete('result')
259
+ { 'aborted_at' => completed_at }.merge(attrs)
258
260
  when failed?
259
- h[:failed_at] = completed_at.in_time_zone(time_zone)
260
- h[:percent_complete] = percent_complete if percent_complete
261
- h[:exception] = exception.nil? ? {} : exception.attributes
261
+ attrs.delete('completed_at')
262
+ attrs.delete('result')
263
+ { 'failed_at' => completed_at }.merge(attrs)
264
+ else
265
+ attrs
266
+ end
267
+ end
268
+
269
+ def status(time_zone='Eastern Time (US & Canada)')
270
+ h = as_json
271
+ if seconds = h.delete('seconds')
272
+ h['duration'] = seconds_as_duration(seconds)
273
+ end
274
+ h.delete('perform_method') if h['perform_method'] == :perform
275
+ h.dup.each_pair do |k,v|
276
+ case
277
+ when v.kind_of?(Time)
278
+ h[k] = v.in_time_zone(time_zone).to_s
279
+ when v.kind_of?(BSON::ObjectId)
280
+ h[k] = v.to_s
281
+ end
262
282
  end
263
- h[:duration] = duration.strftime('%H:%M:%S')
264
283
  h
265
284
  end
266
285
 
@@ -288,6 +307,7 @@ module RocketJob
288
307
  self.arguments = arguments.collect {|i| i.is_a?(BSON::OrderedHash) ? i.with_indifferent_access : i } if arguments.present?
289
308
  end
290
309
 
310
+ ############################################################################
291
311
  protected
292
312
 
293
313
  # Before events that can be overridden by child classes
@@ -320,23 +340,34 @@ module RocketJob
320
340
  self.completed_at = Time.now
321
341
  end
322
342
 
323
- ############################################################################
324
- protected
343
+ # Returns a human readable duration from the supplied [Float] number of seconds
344
+ def seconds_as_duration(seconds)
345
+ time = Time.at(seconds)
346
+ if seconds >= 1.day
347
+ "#{seconds / 1.day}d #{time.strftime('%-Hh %-Mm %-Ss')}"
348
+ elsif seconds >= 1.hour
349
+ time.strftime('%-Hh %-Mm %-Ss')
350
+ elsif seconds >= 1.minute
351
+ time.strftime('%-Mm %-Ss')
352
+ else
353
+ time.strftime('%-Ss')
354
+ end
355
+ end
325
356
 
326
357
  # Returns the next job to work on in priority based order
327
358
  # Returns nil if there are currently no queued jobs, or processing batch jobs
328
359
  # with records that require processing
329
360
  #
330
361
  # Parameters
331
- # server_name [String]
332
- # Name of the server that will be processing this job
362
+ # worker_name [String]
363
+ # Name of the worker that will be processing this job
333
364
  #
334
365
  # skip_job_ids [Array<BSON::ObjectId>]
335
366
  # Job ids to exclude when looking for the next job
336
367
  #
337
368
  # Note:
338
369
  # If a job is in queued state it will be started
339
- def self.next_job(server_name, skip_job_ids = nil)
370
+ def self.next_job(worker_name, skip_job_ids = nil)
340
371
  query = {
341
372
  '$and' => [
342
373
  {
@@ -358,7 +389,7 @@ module RocketJob
358
389
  while doc = find_and_modify(
359
390
  query: query,
360
391
  sort: [['priority', 'asc'], ['created_at', 'asc']],
361
- update: { '$set' => { 'server_name' => server_name, 'state' => 'running' } }
392
+ update: { '$set' => { 'worker_name' => worker_name, 'state' => 'running' } }
362
393
  )
363
394
  job = load(doc)
364
395
  if job.running?
@@ -381,11 +412,11 @@ module RocketJob
381
412
  private
382
413
 
383
414
  # Set exception information for this job
384
- def set_exception(server_name, exc)
385
- self.server_name = nil
415
+ def set_exception(worker_name, exc)
416
+ self.worker_name = nil
386
417
  self.failure_count += 1
387
418
  self.exception = JobException.from_exception(exc)
388
- exception.server_name = server_name
419
+ exception.worker_name = worker_name
389
420
  fail! unless failed?
390
421
  logger.error("Exception running #{self.class.name}##{perform_method}", exc)
391
422
  end
@@ -2,7 +2,7 @@
2
2
  module RocketJob
3
3
  # Heartbeat
4
4
  #
5
- # Information from the server as at it's last heartbeat
5
+ # Information from the worker as at it's last heartbeat
6
6
  class JobException
7
7
  include MongoMapper::EmbeddedDocument
8
8
 
@@ -15,8 +15,8 @@ module RocketJob
15
15
  # Exception Backtrace [Array<String>]
16
16
  key :backtrace, Array
17
17
 
18
- # Name of the server on which this exception occurred
19
- key :server_name, String
18
+ # Name of the worker on which this exception occurred
19
+ key :worker_name, String
20
20
 
21
21
  # The record within which this exception occurred
22
22
  key :record_number, Integer
@@ -1,4 +1,4 @@
1
1
  # encoding: UTF-8
2
2
  module RocketJob #:nodoc
3
- VERSION = "0.8.0"
3
+ VERSION = "0.9.0"
4
4
  end
@@ -3,31 +3,31 @@ require 'socket'
3
3
  require 'sync_attr'
4
4
  require 'aasm'
5
5
  module RocketJob
6
- # Server
6
+ # Worker
7
7
  #
8
- # On startup a server instance will automatically register itself
8
+ # On startup a worker instance will automatically register itself
9
9
  # if not already present
10
10
  #
11
- # Starting a server in the foreground:
11
+ # Starting a worker in the foreground:
12
12
  # - Using a Rails runner:
13
13
  # bin/rocketjob
14
14
  #
15
- # Starting a server in the background:
15
+ # Starting a worker in the background:
16
16
  # - Using a Rails runner:
17
17
  # nohup bin/rocketjob --quiet 2>&1 1>output.log &
18
18
  #
19
- # Stopping a server:
20
- # - Stop the server via the Web UI
19
+ # Stopping a worker:
20
+ # - Stop the worker via the Web UI
21
21
  # - Send a regular kill signal to make it shutdown once all active work is complete
22
22
  # kill <pid>
23
23
  # - Or, use the following Ruby code:
24
- # server = RocketJob::Server.where(name: 'server name').first
25
- # server.stop!
24
+ # worker = RocketJob::Worker.where(name: 'worker name').first
25
+ # worker.stop!
26
26
  #
27
27
  # Sending the kill signal locally will result in starting the shutdown process
28
- # immediately. Via the UI or Ruby code the server can take up to 15 seconds
28
+ # immediately. Via the UI or Ruby code the worker can take up to 15 seconds
29
29
  # (the heartbeat interval) to start shutting down.
30
- class Server
30
+ class Worker
31
31
  include MongoMapper::Document
32
32
  include AASM
33
33
  include SyncAttr
@@ -36,21 +36,21 @@ module RocketJob
36
36
  # Prevent data in MongoDB from re-defining the model behavior
37
37
  #self.static_keys = true
38
38
 
39
- # Unique Name of this server instance
40
- # Defaults to the `hostname` but _must_ be overriden if mutiple Server instances
39
+ # Unique Name of this worker instance
40
+ # Defaults to the `hostname` but _must_ be overriden if mutiple Worker instances
41
41
  # are started on the same host
42
42
  # The unique name is used on re-start to re-queue any jobs that were being processed
43
- # at the time the server or host unexpectedly terminated, if any
43
+ # at the time the worker or host unexpectedly terminated, if any
44
44
  key :name, String, default: -> { "#{Socket.gethostname}:#{$$}" }
45
45
 
46
46
  # The maximum number of threads that this worker should use
47
47
  # If set, it will override the default value in RocketJob::Config
48
48
  key :max_threads, Integer, default: -> { Config.instance.max_worker_threads }
49
49
 
50
- # When this server process was started
50
+ # When this worker process was started
51
51
  key :started_at, Time
52
52
 
53
- # The heartbeat information for this server
53
+ # The heartbeat information for this worker
54
54
  one :heartbeat, class_name: 'RocketJob::Heartbeat'
55
55
 
56
56
  # Current state
@@ -89,20 +89,20 @@ module RocketJob
89
89
 
90
90
  attr_reader :thread_pool
91
91
 
92
- # Requeue any jobs being worked by this server when it is destroyed
92
+ # Requeue any jobs being worked by this worker when it is destroyed
93
93
  before_destroy :requeue_jobs
94
94
 
95
- # Run the server process
95
+ # Run the worker process
96
96
  # Attributes supplied are passed to #new
97
97
  def self.run(attrs={})
98
- server = new(attrs)
99
- server.build_heartbeat
100
- server.save!
98
+ worker = new(attrs)
99
+ worker.build_heartbeat
100
+ worker.save!
101
101
  create_indexes
102
102
  register_signal_handlers
103
103
  raise "The RocketJob configuration is being applied after the system has been initialized" unless RocketJob::Job.database.name == RocketJob::SlicedJob.database.name
104
104
  logger.info "Using MongoDB Database: #{RocketJob::Job.database.name}"
105
- server.run
105
+ worker.run
106
106
  end
107
107
 
108
108
  # Create indexes
@@ -112,40 +112,40 @@ module RocketJob
112
112
  Job.create_indexes
113
113
  end
114
114
 
115
- # Destroy dead servers ( missed at least the last 4 heartbeats )
116
- # Requeue jobs assigned to dead servers
117
- # Destroy dead servers
118
- def self.destroy_dead_servers
115
+ # Destroy dead workers ( missed at least the last 4 heartbeats )
116
+ # Requeue jobs assigned to dead workers
117
+ # Destroy dead workers
118
+ def self.destroy_dead_workers
119
119
  dead_seconds = Config.instance.heartbeat_seconds * 4
120
- each do |server|
121
- next if (Time.now - server.heartbeat.updated_at) < dead_seconds
122
- logger.warn "Destroying server #{server.name}, and requeueing its jobs"
123
- server.destroy
120
+ each do |worker|
121
+ next if (Time.now - worker.heartbeat.updated_at) < dead_seconds
122
+ logger.warn "Destroying worker #{worker.name}, and requeueing its jobs"
123
+ worker.destroy
124
124
  end
125
125
  end
126
126
 
127
- # Stop all running, paused, or starting servers
127
+ # Stop all running, paused, or starting workers
128
128
  def self.stop_all
129
- where(state: ['running', 'paused', 'starting']).each { |server| server.stop! }
129
+ where(state: ['running', 'paused', 'starting']).each { |worker| worker.stop! }
130
130
  end
131
131
 
132
- # Pause all running servers
132
+ # Pause all running workers
133
133
  def self.pause_all
134
- where(state: 'running').each { |server| server.pause! }
134
+ where(state: 'running').each { |worker| worker.pause! }
135
135
  end
136
136
 
137
- # Resume all paused servers
137
+ # Resume all paused workers
138
138
  def self.resume_all
139
- each { |server| server.resume! if server.paused? }
139
+ each { |worker| worker.resume! if worker.paused? }
140
140
  end
141
141
 
142
- # Register a handler to perform cleanups etc. whenever a server is
142
+ # Register a handler to perform cleanups etc. whenever a worker is
143
143
  # explicitly destroyed
144
144
  def self.register_destroy_handler(&block)
145
145
  @@destroy_handlers << block
146
146
  end
147
147
 
148
- # Returns [Boolean] whether the server is shutting down
148
+ # Returns [Boolean] whether the worker is shutting down
149
149
  def shutting_down?
150
150
  if self.class.shutdown
151
151
  stop! if running?
@@ -160,7 +160,7 @@ module RocketJob
160
160
  @thread_pool ||= []
161
161
  end
162
162
 
163
- # Run this instance of the server
163
+ # Run this instance of the worker
164
164
  def run
165
165
  Thread.current.name = 'RocketJob main'
166
166
  build_heartbeat unless heartbeat
@@ -168,17 +168,17 @@ module RocketJob
168
168
  started
169
169
  adjust_thread_pool(true)
170
170
  save
171
- logger.info "RocketJob Server started with #{max_threads} workers running"
171
+ logger.info "RocketJob Worker started with #{max_threads} workers running"
172
172
 
173
173
  count = 0
174
174
  loop do
175
- # Update heartbeat so that monitoring tools know that this server is alive
175
+ # Update heartbeat so that monitoring tools know that this worker is alive
176
176
  set(
177
177
  'heartbeat.updated_at' => Time.now,
178
178
  'heartbeat.current_threads' => thread_pool_count
179
179
  )
180
180
 
181
- # Reload the server model every 10 heartbeats in case its config was changed
181
+ # Reload the worker model every 10 heartbeats in case its config was changed
182
182
  # TODO make 3 configurable
183
183
  if count >= 3
184
184
  reload
@@ -188,7 +188,7 @@ module RocketJob
188
188
  count += 1
189
189
  end
190
190
 
191
- # Stop server if shutdown signal was raised
191
+ # Stop worker if shutdown signal was raised
192
192
  stop! if self.class.shutdown && !stopping?
193
193
 
194
194
  break if stopping?
@@ -204,9 +204,9 @@ module RocketJob
204
204
  thread_pool.each { |t| t.join }
205
205
  logger.info 'Shutdown'
206
206
  rescue Exception => exc
207
- logger.error('RocketJob::Server is stopping due to an exception', exc)
207
+ logger.error('RocketJob::Worker is stopping due to an exception', exc)
208
208
  ensure
209
- # Destroy this server instance
209
+ # Destroy this worker instance
210
210
  destroy
211
211
  end
212
212
 
@@ -258,7 +258,7 @@ module RocketJob
258
258
  end
259
259
  end
260
260
 
261
- # Keep processing jobs until server stops running
261
+ # Keep processing jobs until worker stops running
262
262
  def worker(worker_id)
263
263
  Thread.current.name = "rocketjob #{worker_id}"
264
264
  logger.info 'Started'
@@ -271,7 +271,7 @@ module RocketJob
271
271
  sleep RocketJob::Config.instance.max_poll_seconds
272
272
  end
273
273
  end
274
- logger.info "Stopping. Server state: #{state.inspect}"
274
+ logger.info "Stopping. Worker state: #{state.inspect}"
275
275
  rescue Exception => exc
276
276
  logger.fatal('Unhandled exception in job processing thread', exc)
277
277
  end
@@ -294,7 +294,7 @@ module RocketJob
294
294
  false
295
295
  end
296
296
 
297
- # Requeue any jobs assigned to this server
297
+ # Requeue any jobs assigned to this worker
298
298
  def requeue_jobs
299
299
  stop! if running? || paused?
300
300
  @@destroy_handlers.each { |handler| handler.call(name) }
data/lib/rocketjob.rb CHANGED
@@ -12,7 +12,7 @@ module RocketJob
12
12
  autoload :Heartbeat, 'rocket_job/heartbeat'
13
13
  autoload :Job, 'rocket_job/job'
14
14
  autoload :JobException, 'rocket_job/job_exception'
15
- autoload :Server, 'rocket_job/server'
15
+ autoload :Worker, 'rocket_job/worker'
16
16
  module Concerns
17
17
  autoload :Worker, 'rocket_job/concerns/worker'
18
18
  end
@@ -5,8 +5,8 @@ require_relative 'jobs/test_job'
5
5
  class DirmonJobTest < Minitest::Test
6
6
  context RocketJob::Jobs::DirmonJob do
7
7
  setup do
8
- @server = RocketJob::Server.new
9
- @server.started
8
+ @worker = RocketJob::Worker.new
9
+ @worker.started
10
10
  @dirmon_job = RocketJob::Jobs::DirmonJob.new
11
11
  @archive_directory = '/tmp/archive_directory'
12
12
  @entry = RocketJob::DirmonEntry.new(
data/test/job_test.rb CHANGED
@@ -5,8 +5,8 @@ require_relative 'jobs/test_job'
5
5
  class JobTest < Minitest::Test
6
6
  context RocketJob::Job do
7
7
  setup do
8
- @server = RocketJob::Server.new
9
- @server.started
8
+ @worker = RocketJob::Worker.new
9
+ @worker.started
10
10
  @description = 'Hello World'
11
11
  @arguments = [ 1 ]
12
12
  @job = Jobs::TestJob.new(
@@ -46,7 +46,7 @@ class JobTest < Minitest::Test
46
46
  context '#save!' do
47
47
  should 'save a blank job' do
48
48
  @job.save!
49
- assert_nil @job.server_name
49
+ assert_nil @job.worker_name
50
50
  assert_nil @job.completed_at
51
51
  assert @job.created_at
52
52
  assert_equal @description, @job.description
@@ -66,8 +66,8 @@ class JobTest < Minitest::Test
66
66
  should 'return status for a queued job' do
67
67
  assert_equal true, @job.queued?
68
68
  h = @job.status
69
- assert_equal :queued, h[:state]
70
- assert_equal @description, h[:description]
69
+ assert_equal :queued, h['state']
70
+ assert_equal @description, h['description']
71
71
  end
72
72
 
73
73
  should 'return status for a failed job' do
@@ -79,17 +79,17 @@ class JobTest < Minitest::Test
79
79
  @job.fail!
80
80
  assert_equal true, @job.failed?
81
81
  h = @job.status
82
- assert_equal :failed, h[:state]
83
- assert_equal @description, h[:description]
84
- assert_equal 'Test', h[:exception][:class_name], h
85
- assert_equal 'hello world', h[:exception][:message], h
82
+ assert_equal :failed, h['state']
83
+ assert_equal @description, h['description']
84
+ assert_equal 'Test', h['exception']['class_name'], h
85
+ assert_equal 'hello world', h['exception']['message'], h
86
86
  end
87
87
  end
88
88
 
89
89
  context '#work' do
90
90
  should 'call default perform method' do
91
91
  @job.start!
92
- assert_equal false, @job.work(@server)
92
+ assert_equal false, @job.work(@worker)
93
93
  assert_equal true, @job.completed?, @job.state
94
94
  assert_equal 2, Jobs::TestJob.result
95
95
  end
@@ -98,7 +98,7 @@ class JobTest < Minitest::Test
98
98
  @job.perform_method = :sum
99
99
  @job.arguments = [ 23, 45 ]
100
100
  @job.start!
101
- assert_equal false, @job.work(@server)
101
+ assert_equal false, @job.work(@worker)
102
102
  assert_equal true, @job.completed?
103
103
  assert_equal 68, Jobs::TestJob.result
104
104
  end
@@ -106,7 +106,7 @@ class JobTest < Minitest::Test
106
106
  should 'destroy on complete' do
107
107
  @job.destroy_on_complete = true
108
108
  @job.start!
109
- assert_equal false, @job.work(@server)
109
+ assert_equal false, @job.work(@worker)
110
110
  assert_equal nil, RocketJob::Job.find_by_id(@job.id)
111
111
  end
112
112
 
@@ -118,7 +118,7 @@ class JobTest < Minitest::Test
118
118
  @job.start!
119
119
  logged = false
120
120
  Jobs::TestJob.logger.stub(:log_internal, -> level, index, message, payload, exception { logged = true if message.include?('some very noisy logging')}) do
121
- assert_equal false, @job.work(@server), @job.inspect
121
+ assert_equal false, @job.work(@worker), @job.inspect
122
122
  end
123
123
  assert_equal false, logged
124
124
  end
@@ -133,7 +133,7 @@ class JobTest < Minitest::Test
133
133
  # Raise global log level to :info
134
134
  SemanticLogger.stub(:default_level_index, 3) do
135
135
  Jobs::TestJob.logger.stub(:log_internal, -> { logged = true }) do
136
- assert_equal false, @job.work(@server)
136
+ assert_equal false, @job.work(@worker)
137
137
  end
138
138
  end
139
139
  assert_equal false, logged
@@ -144,7 +144,7 @@ class JobTest < Minitest::Test
144
144
  @job.perform_method = :event
145
145
  @job.arguments = [ named_parameters ]
146
146
  @job.start!
147
- assert_equal false, @job.work(@server), @job.inspect
147
+ assert_equal false, @job.work(@worker), @job.inspect
148
148
  assert_equal true, @job.completed?
149
149
  assert_equal named_parameters.merge('before_event' => true, 'after_event' => true), @job.arguments.first
150
150
  end
@@ -157,25 +157,25 @@ class JobTest < Minitest::Test
157
157
  end
158
158
 
159
159
  should 'return nil when no jobs available' do
160
- assert_equal nil, RocketJob::Job.next_job(@server.name)
160
+ assert_equal nil, RocketJob::Job.next_job(@worker.name)
161
161
  end
162
162
 
163
163
  should 'return the first job' do
164
164
  @job.save!
165
- assert job = RocketJob::Job.next_job(@server.name), "Failed to find job"
165
+ assert job = RocketJob::Job.next_job(@worker.name), "Failed to find job"
166
166
  assert_equal @job.id, job.id
167
167
  end
168
168
 
169
169
  should 'Ignore future dated jobs' do
170
170
  @job.run_at = Time.now + 1.hour
171
171
  @job.save!
172
- assert_equal nil, RocketJob::Job.next_job(@server.name)
172
+ assert_equal nil, RocketJob::Job.next_job(@worker.name)
173
173
  end
174
174
 
175
175
  should 'Process future dated jobs when time is now' do
176
176
  @job.run_at = Time.now
177
177
  @job.save!
178
- assert job = RocketJob::Job.next_job(@server.name), "Failed to find future job"
178
+ assert job = RocketJob::Job.next_job(@worker.name), "Failed to find future job"
179
179
  assert_equal @job.id, job.id
180
180
  end
181
181
 
@@ -183,7 +183,7 @@ class JobTest < Minitest::Test
183
183
  count = RocketJob::Job.count
184
184
  @job.expires_at = Time.now - 100
185
185
  @job.save!
186
- assert_equal nil, RocketJob::Job.next_job(@server.name)
186
+ assert_equal nil, RocketJob::Job.next_job(@worker.name)
187
187
  assert_equal count, RocketJob::Job.count
188
188
  end
189
189
 
@@ -0,0 +1,85 @@
1
+ require_relative 'test_helper'
2
+ require_relative 'jobs/test_job'
3
+
4
+ # Unit Test for RocketJob::Job
5
+ class WorkerTest < Minitest::Test
6
+ context RocketJob::Job do
7
+ [true, false].each do |inline_mode|
8
+ setup do
9
+ RocketJob::Config.inline_mode = inline_mode
10
+ @worker = RocketJob::Worker.new
11
+ @worker.started
12
+ end
13
+
14
+ teardown do
15
+ @job.destroy if @job && !@job.new_record?
16
+ RocketJob::Config.inline_mode = false
17
+ end
18
+
19
+ context '.perform_later' do
20
+ should "process single request (inline_mode=#{inline_mode})" do
21
+ @job = Jobs::TestJob.perform_later(1) do |job|
22
+ job.destroy_on_complete = false
23
+ end
24
+ assert_nil @job.worker_name
25
+ assert_nil @job.completed_at
26
+ assert @job.created_at
27
+ assert_nil @job.description
28
+ assert_equal false, @job.destroy_on_complete
29
+ assert_nil @job.expires_at
30
+ assert_equal 0, @job.percent_complete
31
+ assert_equal 50, @job.priority
32
+ assert_equal 0, @job.failure_count
33
+ assert_nil @job.run_at
34
+ assert_nil @job.started_at
35
+ assert_equal :queued, @job.state
36
+
37
+ @job.worker_name = 'me'
38
+ @job.start
39
+ assert_equal false, @job.work(@worker), @job.exception.inspect
40
+ assert_equal true, @job.completed?
41
+ assert_equal 2, Jobs::TestJob.result
42
+
43
+ assert @job.worker_name
44
+ assert @job.completed_at
45
+ assert @job.created_at
46
+ assert_nil @job.description
47
+ assert_equal false, @job.destroy_on_complete
48
+ assert_nil @job.expires_at
49
+ assert_equal 100, @job.percent_complete
50
+ assert_equal 50, @job.priority
51
+ assert_equal 0, @job.failure_count
52
+ assert_nil @job.run_at
53
+ assert @job.started_at
54
+ end
55
+ end
56
+
57
+ context '.later' do
58
+ should "process non default method (inline_mode=#{inline_mode})" do
59
+ @job = Jobs::TestJob.later(:sum, 23, 45)
60
+ @job.start
61
+ assert_equal false, @job.work(@worker), @job.exception.inspect
62
+ assert_equal true, @job.completed?
63
+ assert_equal 68, Jobs::TestJob.result
64
+ end
65
+ end
66
+
67
+ context '.perform_now' do
68
+ should "process perform (inline_mode=#{inline_mode})" do
69
+ @job = Jobs::TestJob.perform_now(5)
70
+ assert_equal true, @job.completed?
71
+ assert_equal 6, Jobs::TestJob.result
72
+ end
73
+ end
74
+
75
+ context '.now' do
76
+ should "process non default method (inline_mode=#{inline_mode})" do
77
+ @job = Jobs::TestJob.now(:sum, 23, 45)
78
+ assert_equal true, @job.completed?, @job.inspect
79
+ assert_equal 68, Jobs::TestJob.result
80
+ end
81
+ end
82
+
83
+ end
84
+ end
85
+ end
data/test/worker_test.rb CHANGED
@@ -1,85 +1,39 @@
1
1
  require_relative 'test_helper'
2
2
  require_relative 'jobs/test_job'
3
3
 
4
- # Unit Test for RocketJob::Job
4
+ # Unit Test for RocketJob::Worker
5
5
  class WorkerTest < Minitest::Test
6
- context RocketJob::Job do
7
- [true, false].each do |inline_mode|
8
- setup do
9
- RocketJob::Config.inline_mode = inline_mode
10
- @server = RocketJob::Server.new
11
- @server.started
12
- end
13
-
14
- teardown do
15
- @job.destroy if @job && !@job.new_record?
16
- RocketJob::Config.inline_mode = false
17
- end
18
-
19
- context '.perform_later' do
20
- should "process single request (inline_mode=#{inline_mode})" do
21
- @job = Jobs::TestJob.perform_later(1) do |job|
22
- job.destroy_on_complete = false
23
- end
24
- assert_nil @job.server_name
25
- assert_nil @job.completed_at
26
- assert @job.created_at
27
- assert_nil @job.description
28
- assert_equal false, @job.destroy_on_complete
29
- assert_nil @job.expires_at
30
- assert_equal 0, @job.percent_complete
31
- assert_equal 50, @job.priority
32
- assert_equal 0, @job.failure_count
33
- assert_nil @job.run_at
34
- assert_nil @job.started_at
35
- assert_equal :queued, @job.state
36
-
37
- @job.server_name = 'me'
38
- @job.start
39
- assert_equal false, @job.work(@server), @job.exception.inspect
40
- assert_equal true, @job.completed?
41
- assert_equal 2, Jobs::TestJob.result
42
-
43
- assert @job.server_name
44
- assert @job.completed_at
45
- assert @job.created_at
46
- assert_nil @job.description
47
- assert_equal false, @job.destroy_on_complete
48
- assert_nil @job.expires_at
49
- assert_equal 100, @job.percent_complete
50
- assert_equal 50, @job.priority
51
- assert_equal 0, @job.failure_count
52
- assert_nil @job.run_at
53
- assert @job.started_at
54
- end
55
- end
6
+ context RocketJob::Worker do
7
+ setup do
8
+ RocketJob::Config.instance.heartbeat_seconds = 0.1
9
+ RocketJob::Config.instance.max_poll_seconds = 0.1
10
+ @worker = RocketJob::Worker.new
11
+ @description = 'Hello World'
12
+ @arguments = [ 1 ]
13
+ @job = Jobs::TestJob.new(
14
+ description: @description,
15
+ arguments: @arguments,
16
+ destroy_on_complete: false
17
+ )
18
+ end
56
19
 
57
- context '.later' do
58
- should "process non default method (inline_mode=#{inline_mode})" do
59
- @job = Jobs::TestJob.later(:sum, 23, 45)
60
- @job.start
61
- assert_equal false, @job.work(@server), @job.exception.inspect
62
- assert_equal true, @job.completed?
63
- assert_equal 68, Jobs::TestJob.result
64
- end
65
- end
20
+ teardown do
21
+ @job.destroy if @job && !@job.new_record?
22
+ end
66
23
 
67
- context '.perform_now' do
68
- should "process perform (inline_mode=#{inline_mode})" do
69
- @job = Jobs::TestJob.perform_now(5)
70
- assert_equal true, @job.completed?
71
- assert_equal 6, Jobs::TestJob.result
72
- end
24
+ context '.config' do
25
+ should 'support multiple databases' do
26
+ assert_equal 'test_rocketjob', RocketJob::Job.collection.db.name
73
27
  end
28
+ end
74
29
 
75
- context '.now' do
76
- should "process non default method (inline_mode=#{inline_mode})" do
77
- @job = Jobs::TestJob.now(:sum, 23, 45)
78
- assert_equal true, @job.completed?, @job.inspect
79
- assert_equal 68, Jobs::TestJob.result
80
- end
30
+ context '#run' do
31
+ should 'run a worker' do
32
+ Thread.new { sleep 1; @worker.stop!}
33
+ @worker.run
34
+ assert_equal :stopping, @worker.state, @worker.inspect
81
35
  end
82
-
83
36
  end
37
+
84
38
  end
85
- end
39
+ 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: 0.8.0
4
+ version: 0.9.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-07-20 00:00:00.000000000 Z
11
+ date: 2015-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aasm
@@ -128,14 +128,14 @@ files:
128
128
  - lib/rocket_job/job.rb
129
129
  - lib/rocket_job/job_exception.rb
130
130
  - lib/rocket_job/jobs/dirmon_job.rb
131
- - lib/rocket_job/server.rb
132
131
  - lib/rocket_job/version.rb
132
+ - lib/rocket_job/worker.rb
133
133
  - lib/rocketjob.rb
134
134
  - test/config/mongo.yml
135
135
  - test/dirmon_job_test.rb
136
136
  - test/job_test.rb
137
+ - test/job_worker_test.rb
137
138
  - test/jobs/test_job.rb
138
- - test/server_test.rb
139
139
  - test/test_helper.rb
140
140
  - test/worker_test.rb
141
141
  homepage: https://github.com/rocketjob/rocketjob
@@ -166,7 +166,7 @@ test_files:
166
166
  - test/config/mongo.yml
167
167
  - test/dirmon_job_test.rb
168
168
  - test/job_test.rb
169
+ - test/job_worker_test.rb
169
170
  - test/jobs/test_job.rb
170
- - test/server_test.rb
171
171
  - test/test_helper.rb
172
172
  - test/worker_test.rb
data/test/server_test.rb DELETED
@@ -1,39 +0,0 @@
1
- require_relative 'test_helper'
2
- require_relative 'jobs/test_job'
3
-
4
- # Unit Test for RocketJob::Server
5
- class ServerTest < Minitest::Test
6
- context RocketJob::Server do
7
- setup do
8
- RocketJob::Config.instance.heartbeat_seconds = 0.1
9
- RocketJob::Config.instance.max_poll_seconds = 0.1
10
- @server = RocketJob::Server.new
11
- @description = 'Hello World'
12
- @arguments = [ 1 ]
13
- @job = Jobs::TestJob.new(
14
- description: @description,
15
- arguments: @arguments,
16
- destroy_on_complete: false
17
- )
18
- end
19
-
20
- teardown do
21
- @job.destroy if @job && !@job.new_record?
22
- end
23
-
24
- context '.config' do
25
- should 'support multiple databases' do
26
- assert_equal 'test_rocketjob', RocketJob::Job.collection.db.name
27
- end
28
- end
29
-
30
- context '#run' do
31
- should 'run a server' do
32
- Thread.new { sleep 1; @server.stop!}
33
- @server.run
34
- assert_equal :stopping, @server.state, @server.inspect
35
- end
36
- end
37
-
38
- end
39
- end