rocketjob 5.0.0.rc1 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|