rocketjob 5.0.0.rc1 → 5.0.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
  SHA256:
3
- metadata.gz: c53fb037073ba38fd229b6a0573a2e0a28a1f28bbb0750bc895f2f2d46b57d44
4
- data.tar.gz: c5ab8fcbe268aa97909448b4e053cf54698b1f690fe537899f1ed4a5c7f7a1ed
3
+ metadata.gz: 601a4455f5e51191440ce959b6325545d51fcaf531d179dfcd78a4ec016b44c6
4
+ data.tar.gz: 7ea8fc1b5cc632461d01e608f5c93cb33e379e14138764fc9e424d15f9c07679
5
5
  SHA512:
6
- metadata.gz: 69973ec5d30e2d9a63a338119121decb9c20ce8b5d0aba3d9a566799f80eaad626bb2055361bda7cbf5e60085b0fd82c68082f499e151d3a982659457173c5ff
7
- data.tar.gz: 8a7b75c3d55fdc1c38c549efc91b8e7cf806ac7aa323a2c0ed1ede9f7e4b7518840d282b172446e5f5f9762685dd5a0639ce9e5fc151d173a59212a0ac5d5ee7
6
+ metadata.gz: 823280f2250aaa7e2bef010b8b7477f1db1d2f04631c9ce133b80545768e23cab98a14cbc597630988b69b02cfc115acf34a647f50f84fc35e61a708af4c2c09
7
+ data.tar.gz: e562aa988c120459637cd11108a4401440faa674d1a3226a8c7e77a91ec31635935349803a9c17ace9b3603c14f8a97ec2e8196ba20a79bf518a429807152dce
@@ -58,14 +58,14 @@ module RocketJob
58
58
  # Searches for the first "\r\n" or "\n" and then uses that as the
59
59
  # delimiter for all subsequent records
60
60
  #
61
- # stream_mode: [:line | :row | :record]
61
+ # stream_mode: [:line | :array | :hash]
62
62
  # :line
63
63
  # Uploads the file a line (String) at a time for processing by workers.
64
- # :row
64
+ # :array
65
65
  # Parses each line from the file as an Array and uploads each array for processing by workers.
66
- # :record
66
+ # :hash
67
67
  # Parses each line from the file into a Hash and uploads each hash for processing by workers.
68
- # See IOStreams::Stream#each_line, IOStreams::Stream#each_row, and IOStreams::Stream#each_record.
68
+ # See IOStreams::Stream#each.
69
69
  #
70
70
  # Example:
71
71
  # # Load plain text records from a file
@@ -118,6 +118,11 @@ module RocketJob
118
118
  def upload(stream = nil, file_name: nil, category: :main, stream_mode: :line, on_first: nil, **args, &block)
119
119
  raise(ArgumentError, 'Either stream, or a block must be supplied') unless stream || block
120
120
 
121
+ stream_mode = stream_mode.to_sym
122
+ # Backward compatibility with existing v4 jobs
123
+ stream_mode = :array if stream_mode == :row
124
+ stream_mode = :hash if stream_mode == :record
125
+
121
126
  count =
122
127
  if block
123
128
  input(category).upload(on_first: on_first, &block)
@@ -126,7 +131,7 @@ module RocketJob
126
131
  path.file_name = file_name if file_name
127
132
  self.upload_file_name = path.file_name
128
133
  input(category).upload(on_first: on_first) do |io|
129
- path.public_send("each_#{stream_mode}".to_sym, **args) { |line| io << line }
134
+ path.each(stream_mode, **args) { |line| io << line }
130
135
  end
131
136
  end
132
137
  self.record_count = (record_count || 0) + count
@@ -336,7 +341,7 @@ module RocketJob
336
341
  # end
337
342
  #
338
343
  # Example: Add a header and/or trailer record to the downloaded file, letting the line writer add the line breaks:
339
- # IOStreams.path('/tmp/file.txt.gz').line_writer do |writer|
344
+ # IOStreams.path('/tmp/file.txt.gz').writer(:line) do |writer|
340
345
  # writer << "Header"
341
346
  # job.download do |line|
342
347
  # writer << line
@@ -352,7 +357,7 @@ module RocketJob
352
357
 
353
358
  return output(category).download(header_line: header_line, &block) if block
354
359
 
355
- IOStreams.new(stream).line_writer(**args) do |io|
360
+ IOStreams.new(stream).writer(:line, **args) do |io|
356
361
  output(category).download(header_line: header_line) { |record| io << record }
357
362
  end
358
363
  end
@@ -13,18 +13,18 @@ module RocketJob
13
13
  field :tabular_input_header, type: Array, class_attribute: true, user_editable: true
14
14
  field :tabular_input_format, type: Symbol, default: :csv, class_attribute: true, user_editable: true
15
15
 
16
- # tabular_input_mode: [:line | :row | :record]
16
+ # tabular_input_mode: [:line | :array | :hash]
17
17
  # :line
18
18
  # Uploads the file a line (String) at a time for processing by workers.
19
- # :row
19
+ # :array
20
20
  # Parses each line from the file as an Array and uploads each array for processing by workers.
21
- # :record
21
+ # :hash
22
22
  # Parses each line from the file into a Hash and uploads each hash for processing by workers.
23
- # See IOStreams#each_line, IOStreams#each_row, and IOStreams#each_record.
23
+ # See IOStreams#each.
24
24
  field :tabular_input_mode, type: Symbol, default: :line, class_attribute: true, user_editable: true, copy_on_restart: true
25
25
 
26
26
  validates_inclusion_of :tabular_input_format, in: IOStreams::Tabular.registered_formats
27
- validates_inclusion_of :tabular_input_mode, in: %i[line row record]
27
+ validates_inclusion_of :tabular_input_mode, in: %i[line array hash row record]
28
28
  validate :tabular_input_header_present
29
29
 
30
30
  class_attribute :tabular_input_white_list
@@ -72,16 +72,16 @@ module RocketJob
72
72
  tabular_input_cleanse_header
73
73
  self.tabular_input_header = tabular_input.header.columns
74
74
  end
75
- super(input_stream, on_first: parse_header, stream_mode: tabular_input_mode, **args, &block)
76
- when :row
75
+ super(input_stream, on_first: parse_header, stream_mode: :line, **args, &block)
76
+ when :array, :row
77
77
  set_header = -> (row) do
78
78
  tabular_input.header.columns = row
79
79
  tabular_input_cleanse_header
80
80
  self.tabular_input_header = tabular_input.header.columns
81
81
  end
82
- super(input_stream, on_first: set_header, stream_mode: tabular_input_mode, **args, &block)
83
- when :record
84
- super(input_stream, stream_mode: tabular_input_mode, **args, &block)
82
+ super(input_stream, on_first: set_header, stream_mode: :array, **args, &block)
83
+ when :hash, :record
84
+ super(input_stream, stream_mode: :hash, **args, &block)
85
85
  else
86
86
  raise(ArgumentError, "Invalid tabular_input_mode: #{stream_mode.inspect}")
87
87
  end
@@ -113,7 +113,7 @@ module RocketJob
113
113
  end
114
114
 
115
115
  def tabular_input_header_present
116
- return if tabular_input_header.present? || !tabular_input.header? || (tabular_input_mode == :record)
116
+ return if tabular_input_header.present? || !tabular_input.header? || (tabular_input_mode == :hash || tabular_input_mode == :record)
117
117
 
118
118
  errors.add(:tabular_input_header, "is required when tabular_input_format is #{tabular_input_format.inspect}")
119
119
  end
@@ -10,9 +10,11 @@ module RocketJob
10
10
  include SemanticLogger::Loggable
11
11
  attr_accessor :environment, :pidfile, :directory, :quiet,
12
12
  :log_level, :log_file, :mongo_config, :symmetric_encryption_config,
13
- :max_workers, :include_filter, :exclude_filter, :where_filter
13
+ :max_workers, :include_filter, :exclude_filter, :where_filter, :server,
14
+ :stop_server, :kill_server, :pause_server, :resume_server, :thread_dump, :list_servers, :refresh
14
15
 
15
16
  def initialize(argv)
17
+ @server = true
16
18
  @quiet = false
17
19
  @environment = nil
18
20
  @pidfile = nil
@@ -23,13 +25,19 @@ module RocketJob
23
25
  @symmetric_encryption_config = nil
24
26
  @include_filter = nil
25
27
  @exclude_filter = nil
28
+ @stop_server = nil
29
+ @kill_server = nil
30
+ @pause_server = nil
31
+ @resume_server = nil
32
+ @thread_dump = nil
33
+ @list_servers = nil
26
34
  parse(argv)
27
35
  end
28
36
 
29
37
  # Run a RocketJob::Server from the command line
30
38
  def run
31
39
  Thread.current.name = 'rocketjob main'
32
- RocketJob.server!
40
+ RocketJob.server! if server
33
41
  setup_environment
34
42
  setup_logger
35
43
  rails? ? boot_rails : boot_standalone
@@ -39,14 +47,22 @@ module RocketJob
39
47
  # In case Rails did not load the Mongoid Config
40
48
  RocketJob::Config.load!(environment, mongo_config, symmetric_encryption_config) if ::Mongoid::Config.clients.empty?
41
49
 
50
+ return perform_server_action(stop_server, :stop) if stop_server
51
+ return perform_server_action(kill_server, :kill) if kill_server
52
+ return perform_server_action(pause_server, :pause) if pause_server
53
+ return perform_server_action(resume_server, :resume) if resume_server
54
+ return perform_server_action(thread_dump, :thread_dump) if thread_dump
55
+ return perform_list_servers(list_servers) if list_servers
56
+
42
57
  Supervisor.run
43
58
  end
44
59
 
45
60
  def rails?
46
- @rails ||= begin
47
- boot_file = Pathname.new(directory).join('config/environment.rb').expand_path
48
- boot_file.file?
49
- end
61
+ @rails ||=
62
+ begin
63
+ boot_file = Pathname.new(directory).join('config/environment.rb').expand_path
64
+ boot_file.file?
65
+ end
50
66
  end
51
67
 
52
68
  # Initialize the Rails environment
@@ -155,6 +171,68 @@ module RocketJob
155
171
  end
156
172
  end
157
173
 
174
+ def perform_list_servers(filter)
175
+ return list_the_servers(filter) unless refresh
176
+
177
+ while true
178
+ list_the_servers(filter)
179
+ sleep(refresh)
180
+ puts
181
+ end
182
+ end
183
+
184
+ def list_the_servers(filter)
185
+ format = "%50.50s %20.20s %20.20s %20.20s %10.10s"
186
+ puts format % %w[Server\ Name Workers(Current/Max) Started Heartbeat State]
187
+ header = "=" * 50
188
+ puts format % [header, header, header, header, header]
189
+ query = filter == :all ? RocketJob::Server.all : RocketJob::Server.where(name: /#{filter}/)
190
+ query.each do |server|
191
+ workers = "#{server&.heartbeat&.workers}/#{server.max_workers}"
192
+ duration = Time.now - (server.started_at || Time.now)
193
+ started = "#{RocketJob.seconds_as_duration(duration)} ago"
194
+ duration = Time.now - (server&.heartbeat&.updated_at || Time.now)
195
+ heartbeat = "#{RocketJob.seconds_as_duration(duration)} ago"
196
+ puts format % [server.name, workers, started, heartbeat, server.state]
197
+ end
198
+ 0
199
+ end
200
+
201
+ def perform_server_action(server_name, action)
202
+ server_ids(server_name).each { |server_id| RocketJob::Subscribers::Server.publish(action, server_id: server_id) }
203
+ #RocketJob::Subscribers::Worker.publish(:stop, worker_id: 1, server_id: RocketJob::Server.running.last.id)
204
+ 0
205
+ end
206
+
207
+ # Returns server ids for the supplied exact server name, or partial match.
208
+ #
209
+ # When no ':' is supplied a partial hostname lookup is performed.
210
+ #
211
+ # Example: Exact server name (hostname and pid) match:
212
+ # "9cdbe7e995bc:1"
213
+ #
214
+ # Example: Matches all servers that contain the string '.batch.user.org':
215
+ # ".batch.user.org"
216
+ def server_ids(server_name)
217
+ raise(ArgumentError, "Missing server name") unless server_name
218
+
219
+ return [nil] if server_name == :all
220
+
221
+ hostname, pid = server_name.split(":")
222
+ raise(ArgumentError, "Missing server name in: #{server_name}") unless hostname
223
+
224
+ if pid
225
+ server = RocketJob::Server.where(name: server_name).first
226
+ raise(ArgumentError, "No server with exact name: #{server_name} was found.") unless server
227
+ return [server.id]
228
+ end
229
+
230
+ server_ids = RocketJob::Server.where(name: /#{hostname}/).collect(&:id)
231
+ raise(ArgumentError, "No server with partial name: #{server_name} was found.") if server_ids.empty?
232
+
233
+ server_ids
234
+ end
235
+
158
236
  # Parse command line options placing results in the corresponding instance variables
159
237
  def parse(argv)
160
238
  parser = OptionParser.new do |o|
@@ -201,6 +279,39 @@ module RocketJob
201
279
  o.on('-s', '--symmetric-encryption SYMMETRIC_ENCRYPTION_CONFIG_FILE_NAME', 'Path and filename of Symmetric Encryption config file. Default: config/symmetric-encryption.yml') do |arg|
202
280
  @symmetric_encryption_config = arg
203
281
  end
282
+ o.on('--list [FILTER]', "List active servers. Supply either an exact server name or a partial name as a filter.") do |filter|
283
+ @quiet = true
284
+ @server = false
285
+ @list_servers = filter || :all
286
+ end
287
+ o.on('--refresh [SECONDS]', "When listing active servers, update the list by this number of seconds. Defaults to every 1 second.") do |seconds|
288
+ @refresh = (seconds || 1).to_s.to_f
289
+ end
290
+ o.on('--stop [SERVER_NAME]', "Send event to stop a server once all in-process workers have completed. Optionally supply the complete or partial name of the server(s) to stop. Default: All servers.") do |server_name|
291
+ @quiet = true
292
+ @server = false
293
+ @stop_server = server_name || :all
294
+ end
295
+ o.on('--kill [SERVER_NAME]', "Send event to hard kill a server. Optionally supply the complete or partial name of the server(s) to kill. Default: All servers.") do |server_name|
296
+ @quiet = true
297
+ @server = false
298
+ @kill_server = server_name || :all
299
+ end
300
+ o.on('--pause [SERVER_NAME]', "Send event to pause a server. Optionally supply the complete or partial name of the server(s) to pause. Default: All servers.") do |server_name|
301
+ @quiet = true
302
+ @server = false
303
+ @pause_server = server_name || :all
304
+ end
305
+ o.on('--resume [SERVER_NAME]', "Send event to resume a server. Optionally supply the complete or partial name of the server(s) to resume. Default: All servers.") do |server_name|
306
+ @quiet = true
307
+ @server = false
308
+ @resume_server = server_name || :all
309
+ end
310
+ o.on('--dump [SERVER_NAME]', "Send event for a server to send a worker thread dump to its log file. Optionally supply the complete or partial name of the server(s). Default: All servers.") do |server_name|
311
+ @quiet = true
312
+ @server = false
313
+ @thread_dump = server_name || :all
314
+ end
204
315
  o.on('-v', '--version', 'Print the version information') do
205
316
  puts "Rocket Job v#{RocketJob::VERSION}"
206
317
  exit 1
@@ -81,11 +81,11 @@ module RocketJob
81
81
  end
82
82
  end
83
83
 
84
+ synchronize { server.refresh(worker_pool.living_count) }
85
+
84
86
  self.class.wait_for_event(Config.heartbeat_seconds)
85
87
 
86
88
  break if self.class.shutdown?
87
-
88
- synchronize { server.refresh(worker_pool.living_count) }
89
89
  end
90
90
  end
91
91
 
@@ -1,3 +1,3 @@
1
1
  module RocketJob
2
- VERSION = '5.0.0.rc1'.freeze
2
+ VERSION = '5.0.0'.freeze
3
3
  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: 5.0.0.rc1
4
+ version: 5.0.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: 2019-12-09 00:00:00.000000000 Z
11
+ date: 2020-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aasm
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.0.0.beta2
47
+ version: '1.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 1.0.0.beta2
54
+ version: '1.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: mongoid
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -192,9 +192,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
192
192
  version: '2.3'
193
193
  required_rubygems_version: !ruby/object:Gem::Requirement
194
194
  requirements:
195
- - - ">"
195
+ - - ">="
196
196
  - !ruby/object:Gem::Version
197
- version: 1.3.1
197
+ version: '0'
198
198
  requirements: []
199
199
  rubygems_version: 3.0.6
200
200
  signing_key: