patriot-workflow-scheduler 0.7.0 → 0.7.1
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 +8 -8
- data/lib/patriot/command/composite.rb +1 -1
- data/lib/patriot/command/post_processor/retrial.rb +3 -0
- data/lib/patriot/job_store/in_memory_store.rb +2 -2
- data/lib/patriot/job_store/rdb_job_store.rb +9 -7
- data/lib/patriot/tool/patriot_commands/register.rb +1 -1
- data/lib/patriot/tool/patriot_commands/worker.rb +47 -10
- data/lib/patriot/worker/base.rb +24 -13
- data/lib/patriot/worker/info_server.rb +6 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZDBiZjc1ZDU4YjBkNzIzZjlhODliMmE2NzVhM2YyZTQxMzY1ZGZhMA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YzliMTkzNDg4NDAzNTJjNGRhOGM0ZWZiY2VmNzQ3OTNhNDQyMmEyMQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NjgxNmU0ZTJiZTk0MzFhMmE4NzAxOTliY2I2YmQ2ZjJlMDM5OWUyYjQ1YjJh
|
10
|
+
NWQ3OTVmOWUyZGJiYzY5OTViNThhNTExZTRiMWRhOWQ1ZThjMGVlNmFmOTdk
|
11
|
+
MzZmMmY3ZTlkYTkzYjVlMTU5YTYyNGRlYmQzMTRlYjZjYmY5YmY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NGRmZDU1ZmVmZjJlNGE4ZTg0MmJkNjc2NzI5OTk2MDZkYTNkOWRjZGIzMjdm
|
14
|
+
MjBmZDVlNjU2ZTAzZTQzMjAzYWVhMDhhZTA3NjkwOGJkNzY3OWY1YzYzNDU4
|
15
|
+
ZDdmMmZiNTJmMWU0ODJlZmUwYTM1OGM0OWFjY2I0M2M5NzJiYTc=
|
@@ -25,6 +25,9 @@ module Patriot
|
|
25
25
|
cmd.start_datetime = Time.now + pp.props[INTERVAL_PROP_KEY]
|
26
26
|
end
|
27
27
|
job = cmd.to_job
|
28
|
+
current_config = worker.job_store.get_job(job.job_id)
|
29
|
+
job[Patriot::Command::PRODUCTS_ATTR] = current_config[Patriot::Command::PRODUCTS_ATTR]
|
30
|
+
job[Patriot::Command::REQUISITES_ATTR] = current_config[Patriot::Command::REQUISITES_ATTR]
|
28
31
|
job[Patriot::Command::STATE_ATTR] = Patriot::JobStore::JobState::WAIT
|
29
32
|
worker.job_store.register(Time.now.to_i, [job])
|
30
33
|
end
|
@@ -39,8 +39,8 @@ module Patriot
|
|
39
39
|
job[Patriot::Command::STATE_ATTR] ||= Patriot::JobStore::JobState::INIT
|
40
40
|
end
|
41
41
|
@jobs[job_id] = job
|
42
|
-
@producers[job_id] = job[Patriot::Command::PRODUCTS_ATTR]
|
43
|
-
@consumers[job_id] = job[Patriot::Command::REQUISITES_ATTR]
|
42
|
+
@producers[job_id] = job[Patriot::Command::PRODUCTS_ATTR] || []
|
43
|
+
@consumers[job_id] = job[Patriot::Command::REQUISITES_ATTR] || []
|
44
44
|
if job[Patriot::Command::STATE_ATTR] == Patriot::JobStore::JobState::INIT
|
45
45
|
_set_state(job_id, Patriot::JobStore::JobState::WAIT)
|
46
46
|
else
|
@@ -21,7 +21,7 @@ module Patriot
|
|
21
21
|
HISTORY_TABLE = 'job_histories'
|
22
22
|
|
23
23
|
# date format of execution history
|
24
|
-
|
24
|
+
DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
|
25
25
|
|
26
26
|
# attributes included in job_ticket
|
27
27
|
TICKET_COLUMNS = ['job_id', 'update_id', 'node']
|
@@ -72,18 +72,20 @@ module Patriot
|
|
72
72
|
|
73
73
|
def upsert_job(update_id, job, c)
|
74
74
|
new_vals = {:job_id => job.job_id, :update_id => update_id, :priority => DEFAULT_PRIORITY}
|
75
|
+
job_attr = job.attributes.dup
|
75
76
|
# extract and remove comman attributes
|
76
|
-
requisites =
|
77
|
-
products =
|
77
|
+
requisites = job_attr.delete(Patriot::Command::REQUISITES_ATTR) || []
|
78
|
+
products = job_attr.delete(Patriot::Command::PRODUCTS_ATTR) || []
|
78
79
|
|
79
80
|
prev_vals = c.select(JOB_TABLE, {:job_id => job.job_id})
|
80
81
|
ATTR_TO_COLUMN.each do |a,c|
|
81
|
-
val =
|
82
|
+
val = job_attr.delete(a)
|
82
83
|
next if val.nil? && c == :state
|
84
|
+
val = val.strftime(DATE_FORMAT) if !val.nil? && a == Patriot::Command::START_DATETIME_ATTR
|
83
85
|
new_vals[c] = val
|
84
86
|
end
|
85
87
|
# serialize remaining attributes
|
86
|
-
new_vals[:content] = JSON.generate(
|
88
|
+
new_vals[:content] = JSON.generate(job_attr)
|
87
89
|
|
88
90
|
if prev_vals.empty?
|
89
91
|
new_vals[:state] ||= Patriot::JobStore::JobState::INIT # set default state
|
@@ -184,7 +186,7 @@ END_OB_QUERY
|
|
184
186
|
:node => job_ticket.exec_node,
|
185
187
|
:host => job_ticket.exec_host,
|
186
188
|
:thread => job_ticket.exec_thread,
|
187
|
-
:begin_at => Time.now.strftime(
|
189
|
+
:begin_at => Time.now.strftime(DATE_FORMAT)})
|
188
190
|
record = c.select(JOB_TABLE, {:job_id => job_ticket.job_id})
|
189
191
|
raise "duplicated entry found for #{job_ticket}" if record.size > 1
|
190
192
|
raise "no entry found for #{job_ticket}" if record.empty?
|
@@ -205,7 +207,7 @@ END_OB_QUERY
|
|
205
207
|
post_state = Patriot::JobStore::EXIT_CODE_TO_STATE[exit_code]
|
206
208
|
raise "illegal exit_code #{exit_code}" if post_state.nil?
|
207
209
|
connect(@db_config) do |c|
|
208
|
-
if c.update(HISTORY_TABLE, {:end_at => Time.now.strftime(
|
210
|
+
if c.update(HISTORY_TABLE, {:end_at => Time.now.strftime(DATE_FORMAT), :exit_code => exit_code, :description => job_ticket.description}, {:id => job_ticket.execution_id}) != 1
|
209
211
|
@logger.warn "illegal state of history for #{job_ticket.job_id}"
|
210
212
|
end
|
211
213
|
return _check_and_set_state(job_ticket, Patriot::JobStore::JobState::RUNNING, post_state, c)
|
@@ -57,7 +57,7 @@ module Patriot
|
|
57
57
|
jobs << job
|
58
58
|
end
|
59
59
|
return if opts[:debug]
|
60
|
-
|
60
|
+
job_store.register(opts[:update_id], jobs)
|
61
61
|
if opts[:retry_dep]
|
62
62
|
job_store.process_subsequent(jobs.map(&:job_id)) do |job_store, jobs|
|
63
63
|
job_store.set_state(opts[:update_id], jobs.map(&:job_id), Patriot::JobStore::JobState::WAIT)
|
@@ -15,19 +15,56 @@ module Patriot
|
|
15
15
|
opts = symbolize_options(options)
|
16
16
|
conf = {:type => 'worker'}
|
17
17
|
conf[:path] = opts[:config] if opts.has_key?(:config)
|
18
|
+
opts[:forground] = false unless sub_cmd == 'start'
|
19
|
+
return if sub_cmd == 'start' && !bootable?(conf)
|
18
20
|
Process.daemon unless opts[:foreground]
|
19
|
-
config
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
21
|
+
config = load_config(conf)
|
22
|
+
logger = Patriot::Util::Logger::Factory.create_logger(self.class.to_s, config)
|
23
|
+
begin
|
24
|
+
worker_cls = config.get("worker_class", "Patriot::Worker::MultiNodeWorker")
|
25
|
+
worker = eval(worker_cls).new(config)
|
26
|
+
case sub_cmd
|
27
|
+
when "start"
|
28
|
+
worker.start_worker
|
29
|
+
when "stop"
|
30
|
+
worker.request_shutdown
|
31
|
+
else
|
32
|
+
raise "unknown sub command #{sub_cmd}"
|
33
|
+
end
|
34
|
+
rescue Exception => e
|
35
|
+
logger.error(e)
|
36
|
+
raise e
|
29
37
|
end
|
30
38
|
end
|
39
|
+
|
40
|
+
no_tasks do
|
41
|
+
# check resources and judge whether this worker is bootable
|
42
|
+
# @return true if this worker is bootable,
|
43
|
+
# false if the worker has been already running,
|
44
|
+
# otherwize raise error
|
45
|
+
def bootable?(conf)
|
46
|
+
conf = conf.merge(:ignore_plugin => true)
|
47
|
+
config = load_config(conf)
|
48
|
+
pid = Patriot::Worker.get_pid(config)
|
49
|
+
unless pid.nil?
|
50
|
+
puts "worker running as #{pid}, stop it first"
|
51
|
+
return false
|
52
|
+
end
|
53
|
+
logger = Patriot::Util::Logger::Factory.create_logger(self.class.to_s, config)
|
54
|
+
pid_file = Patriot::Worker.get_pid_file(config)
|
55
|
+
# check log dir permission by writing a log message
|
56
|
+
logger.info("checking whether this worker is bootable")
|
57
|
+
raise "#{pid_file} is not writable" unless writable_or_creatable?(pid_file)
|
58
|
+
return true
|
59
|
+
end
|
60
|
+
|
61
|
+
def writable_or_creatable?(file)
|
62
|
+
file = File.dirname(file) unless File.exist?(file)
|
63
|
+
return File.writable?(file)
|
64
|
+
end
|
65
|
+
private :writable_or_creatable?
|
66
|
+
|
67
|
+
end
|
31
68
|
end
|
32
69
|
end
|
33
70
|
end
|
data/lib/patriot/worker/base.rb
CHANGED
@@ -4,6 +4,27 @@ require 'patriot/command'
|
|
4
4
|
module Patriot
|
5
5
|
module Worker
|
6
6
|
|
7
|
+
def get_pid(config)
|
8
|
+
pid_file = get_pid_file(config)
|
9
|
+
return nil unless File.exists?(pid_file)
|
10
|
+
pid = nil
|
11
|
+
File.open(pid_file,'r'){|f| pid = f.read.strip.to_i }
|
12
|
+
begin
|
13
|
+
Process.getpgid(pid)
|
14
|
+
rescue Errno::ESRCH
|
15
|
+
@logger.warn("process #{pid} not exist but pid file remains") if @logger
|
16
|
+
return nil
|
17
|
+
end
|
18
|
+
return pid
|
19
|
+
end
|
20
|
+
module_function :get_pid
|
21
|
+
|
22
|
+
def get_pid_file(config)
|
23
|
+
worker_name = config.get('worker_name', Patriot::Worker::DEFAULT_WORKER_NAME)
|
24
|
+
return File.join($home, 'run', "patriot-worker_#{worker_name}.pid")
|
25
|
+
end
|
26
|
+
module_function :get_pid_file
|
27
|
+
|
7
28
|
# @abstract
|
8
29
|
# base class for worker implementations
|
9
30
|
class Base
|
@@ -24,7 +45,6 @@ module Patriot
|
|
24
45
|
@cycle = config.get('fetch_cycle', Patriot::Worker::DEFAULT_FETCH_CYCLE).to_i
|
25
46
|
@fetch_limit = config.get('fetch_limit', Patriot::Worker::DEFAULT_FETCH_LIMIT).to_i
|
26
47
|
@worker_name = config.get('worker_name', Patriot::Worker::DEFAULT_WORKER_NAME)
|
27
|
-
@pid_file = File.join($home, 'run', "patriot-worker_#{@worker_name}.pid")
|
28
48
|
@info_server = Patriot::Worker::InfoServer.new(self,@config)
|
29
49
|
end
|
30
50
|
|
@@ -79,16 +99,7 @@ module Patriot
|
|
79
99
|
|
80
100
|
# @return [Integer] pid if the worker is running, otherwise nil
|
81
101
|
def get_pid
|
82
|
-
return
|
83
|
-
pid = nil
|
84
|
-
File.open(@pid_file,'r'){|f| pid = f.read.strip.to_i }
|
85
|
-
begin
|
86
|
-
Process.getpgid(pid)
|
87
|
-
rescue Errno::ESRCH
|
88
|
-
@logger.warn("process #{pid} not exist but pid file remains")
|
89
|
-
return nil
|
90
|
-
end
|
91
|
-
return pid
|
102
|
+
return Patriot::Worker.get_pid(@config)
|
92
103
|
end
|
93
104
|
|
94
105
|
# send a request graceful shutdown to a running worker
|
@@ -106,9 +117,9 @@ module Patriot
|
|
106
117
|
# main entry point of worker processing
|
107
118
|
def start_worker
|
108
119
|
return unless get_pid.nil?
|
109
|
-
|
110
120
|
@logger.info "starting worker #{@node}@#{@host}"
|
111
|
-
|
121
|
+
pid_file = Patriot::Worker.get_pid_file(@config)
|
122
|
+
File.open(pid_file, 'w') {|f| f.write($$)} # save pid for shutdown
|
112
123
|
set_traps
|
113
124
|
@info_server.start_server
|
114
125
|
@logger.info "initiating worker #{@node}@#{@host}"
|
@@ -21,19 +21,21 @@ module Patriot
|
|
21
21
|
include Patriot::Util::Config
|
22
22
|
include Patriot::Util::Logger
|
23
23
|
|
24
|
+
attr_accessor :port
|
25
|
+
|
24
26
|
# @param worker [Patriot::Worker::Base] worker managed through this server
|
25
27
|
# @param config [Patriot::Util::Config::Bae]
|
26
28
|
def initialize(worker, config)
|
27
29
|
@logger = create_logger(config)
|
28
30
|
@worker = worker
|
29
31
|
@config = config
|
32
|
+
@port = @config.get(Patriot::Worker::InfoServer::PORT_KEY,
|
33
|
+
Patriot::Worker::InfoServer::DEFAULT_PORT)
|
30
34
|
end
|
31
35
|
|
32
36
|
# start the server
|
33
37
|
def start_server
|
34
|
-
|
35
|
-
Patriot::Worker::InfoServer::DEFAULT_PORT)
|
36
|
-
if port.nil?
|
38
|
+
if @port.nil?
|
37
39
|
@logger.info("port is not set. starting info server is skipped")
|
38
40
|
return
|
39
41
|
end
|
@@ -42,7 +44,7 @@ module Patriot
|
|
42
44
|
@handler = eval(@config.get(RACK_HANDLER_KEY, DEFAULT_RACK_HANDLER))
|
43
45
|
app = Rack::URLMap.new(get_url_map)
|
44
46
|
app = Rack::CommonLogger.new(app, build_access_logger)
|
45
|
-
@handler.run app, {:Port => port, :Host => '0.0.0.0'}
|
47
|
+
@handler.run app, {:Port => @port, :Host => '0.0.0.0'}
|
46
48
|
rescue => e
|
47
49
|
@logger.error e
|
48
50
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: patriot-workflow-scheduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Teruyoshi Zenmyo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|