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 +4 -4
- data/lib/rocket_job/batch/io.rb +12 -7
- data/lib/rocket_job/batch/tabular/input.rb +11 -11
- data/lib/rocket_job/cli.rb +117 -6
- data/lib/rocket_job/supervisor.rb +2 -2
- data/lib/rocket_job/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 601a4455f5e51191440ce959b6325545d51fcaf531d179dfcd78a4ec016b44c6
|
4
|
+
data.tar.gz: 7ea8fc1b5cc632461d01e608f5c93cb33e379e14138764fc9e424d15f9c07679
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 823280f2250aaa7e2bef010b8b7477f1db1d2f04631c9ce133b80545768e23cab98a14cbc597630988b69b02cfc115acf34a647f50f84fc35e61a708af4c2c09
|
7
|
+
data.tar.gz: e562aa988c120459637cd11108a4401440faa674d1a3226a8c7e77a91ec31635935349803a9c17ace9b3603c14f8a97ec2e8196ba20a79bf518a429807152dce
|
data/lib/rocket_job/batch/io.rb
CHANGED
@@ -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 | :
|
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
|
-
# :
|
64
|
+
# :array
|
65
65
|
# Parses each line from the file as an Array and uploads each array for processing by workers.
|
66
|
-
# :
|
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#
|
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.
|
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').
|
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).
|
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 | :
|
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
|
-
# :
|
19
|
+
# :array
|
20
20
|
# Parses each line from the file as an Array and uploads each array for processing by workers.
|
21
|
-
# :
|
21
|
+
# :hash
|
22
22
|
# Parses each line from the file into a Hash and uploads each hash for processing by workers.
|
23
|
-
# See IOStreams#
|
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:
|
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:
|
83
|
-
when :record
|
84
|
-
super(input_stream, stream_mode:
|
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
|
data/lib/rocket_job/cli.rb
CHANGED
@@ -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 ||=
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
|
data/lib/rocket_job/version.rb
CHANGED
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
|
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:
|
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
|
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
|
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:
|
197
|
+
version: '0'
|
198
198
|
requirements: []
|
199
199
|
rubygems_version: 3.0.6
|
200
200
|
signing_key:
|