tengine_job 0.6.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +23 -0
- data/Gemfile.lock +109 -0
- data/README.rdoc +20 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/examples/0004_retry_one_layer.rb +24 -0
- data/examples/0004_retry_one_layer.sh +38 -0
- data/examples/0005_retry_two_layer.rb +54 -0
- data/examples/0005_retry_two_layer.sh +80 -0
- data/examples/0006_retry_three_layer.rb +58 -0
- data/examples/0006_retry_three_layer.sh +74 -0
- data/examples/0007_simple_jobnet.rb +7 -0
- data/examples/0021_dynamic_env.rb +20 -0
- data/examples/VERSION +1 -0
- data/examples/tengine_job_test.sh +10 -0
- data/lib/tengine/job.rb +94 -0
- data/lib/tengine/job/category.rb +54 -0
- data/lib/tengine/job/connectable.rb +43 -0
- data/lib/tengine/job/drivers/job_control_driver.rb +82 -0
- data/lib/tengine/job/drivers/job_execution_driver.rb +30 -0
- data/lib/tengine/job/drivers/jobnet_control_driver.rb +117 -0
- data/lib/tengine/job/drivers/schedule_driver.rb +30 -0
- data/lib/tengine/job/dsl_binder.rb +12 -0
- data/lib/tengine/job/dsl_evaluator.rb +18 -0
- data/lib/tengine/job/dsl_loader.rb +180 -0
- data/lib/tengine/job/edge.rb +150 -0
- data/lib/tengine/job/element_selector_notation.rb +169 -0
- data/lib/tengine/job/end.rb +32 -0
- data/lib/tengine/job/executable.rb +74 -0
- data/lib/tengine/job/execution.rb +141 -0
- data/lib/tengine/job/expansion.rb +37 -0
- data/lib/tengine/job/fork.rb +6 -0
- data/lib/tengine/job/job.rb +23 -0
- data/lib/tengine/job/jobnet.rb +173 -0
- data/lib/tengine/job/jobnet/builder.rb +150 -0
- data/lib/tengine/job/jobnet/job_state_transition.rb +167 -0
- data/lib/tengine/job/jobnet/jobnet_state_transition.rb +110 -0
- data/lib/tengine/job/jobnet/state_transition.rb +37 -0
- data/lib/tengine/job/jobnet_actual.rb +55 -0
- data/lib/tengine/job/jobnet_template.rb +10 -0
- data/lib/tengine/job/join.rb +6 -0
- data/lib/tengine/job/junction.rb +29 -0
- data/lib/tengine/job/killing.rb +30 -0
- data/lib/tengine/job/mm_compatibility.rb +6 -0
- data/lib/tengine/job/mm_compatibility/connectable.rb +13 -0
- data/lib/tengine/job/name_path.rb +31 -0
- data/lib/tengine/job/root.rb +16 -0
- data/lib/tengine/job/root_jobnet_actual.rb +39 -0
- data/lib/tengine/job/root_jobnet_template.rb +49 -0
- data/lib/tengine/job/script_executable.rb +235 -0
- data/lib/tengine/job/signal.rb +121 -0
- data/lib/tengine/job/start.rb +20 -0
- data/lib/tengine/job/stoppable.rb +15 -0
- data/lib/tengine/job/vertex.rb +172 -0
- data/lib/tengine_job.rb +3 -0
- data/spec/fixtures/rjn_0001_simple_jobnet_builder.rb +42 -0
- data/spec/fixtures/rjn_0002_simple_parallel_jobnet_builder.rb +42 -0
- data/spec/fixtures/rjn_0003_fork_join_jobnet_builder.rb +61 -0
- data/spec/fixtures/rjn_0004_parallel_jobnet_with_finally_fixture.rb +62 -0
- data/spec/fixtures/rjn_0005_retry_two_layer_fixture.rb +153 -0
- data/spec/fixtures/rjn_0008_expansion_fixture.rb +32 -0
- data/spec/fixtures/rjn_0009_tree_sequential_jobnet_builder.rb +174 -0
- data/spec/fixtures/rjn_0010_2jobs_and_1job_parallel_jobnet_builder.rb +39 -0
- data/spec/fixtures/rjn_0011_nested_fork_jobnet_builder.rb +96 -0
- data/spec/fixtures/rjn_0012_nested_and_finally_builder.rb +157 -0
- data/spec/fixtures/rjn_1004_hadoop_job_in_jobnet_fixture.rb +105 -0
- data/spec/fixtures/rjn_means_root_jobnet +0 -0
- data/spec/fixtures/test_credential_fixture.rb +12 -0
- data/spec/fixtures/test_server_fixture.rb +28 -0
- data/spec/mongoid.yml +35 -0
- data/spec/spec_helper.rb +56 -0
- data/spec/sshd/.gitignore +1 -0
- data/spec/sshd/id_rsa +51 -0
- data/spec/sshd/id_rsa.pub +1 -0
- data/spec/sshd/ssh_host_rsa_key +51 -0
- data/spec/sshd/ssh_host_rsa_key.pub +1 -0
- data/spec/sshd/sshd_config +10 -0
- data/spec/sshd/sshd_config.erb +11 -0
- data/spec/sshd/tengine_job_test.sh +6 -0
- data/spec/support/jobnet_fixture_builder.rb +145 -0
- data/spec/support/mongo_index_key_log.rb +91 -0
- data/spec/tengine/job/category_spec.rb +193 -0
- data/spec/tengine/job/connectable_spec.rb +94 -0
- data/spec/tengine/job/drivers/job_controll_driver/connection_error_spec.rb +236 -0
- data/spec/tengine/job/drivers/job_controll_driver/duplicated_job_start_spec.rb +302 -0
- data/spec/tengine/job/drivers/job_controll_driver/expansion_spec.rb +120 -0
- data/spec/tengine/job/drivers/job_controll_driver/stop_spec.rb +159 -0
- data/spec/tengine/job/drivers/job_controll_driver_spec.rb +623 -0
- data/spec/tengine/job/drivers/job_execution_driver_spec.rb +88 -0
- data/spec/tengine/job/drivers/jobnet_control_driver/nested_and_finally_spec.rb +472 -0
- data/spec/tengine/job/drivers/jobnet_control_driver/nested_jobnet_spec.rb +231 -0
- data/spec/tengine/job/drivers/jobnet_control_driver/stop_jobnet_spec.rb +202 -0
- data/spec/tengine/job/drivers/jobnet_control_driver_spec.rb +446 -0
- data/spec/tengine/job/drivers/schedule_driver_spec.rb +202 -0
- data/spec/tengine/job/dsl_binder_spec.rb +36 -0
- data/spec/tengine/job/dsl_loader_spec.rb +403 -0
- data/spec/tengine/job/dsls/0013_hadoop_job_run.rb +29 -0
- data/spec/tengine/job/dsls/0014_join_and_join.rb +19 -0
- data/spec/tengine/job/dsls/0015_fork_and_fork.rb +18 -0
- data/spec/tengine/job/dsls/0016_complex_fork_and_join.rb +20 -0
- data/spec/tengine/job/dsls/0017_finally.rb +15 -0
- data/spec/tengine/job/dsls/0018_expansion.rb +23 -0
- data/spec/tengine/job/dsls/0019_execute_job_on_event.rb +16 -0
- data/spec/tengine/job/dsls/0020_duplicated_jobnet_name.rb +16 -0
- data/spec/tengine/job/dsls/1060_test_dir1/1060_test_dir2/0013_hadoop_job_run.rb +29 -0
- data/spec/tengine/job/dsls/2003_expansion/expansion_5.rb +11 -0
- data/spec/tengine/job/dsls/VERSION +1 -0
- data/spec/tengine/job/dynamic_env_spec.rb +95 -0
- data/spec/tengine/job/edge_spec.rb +241 -0
- data/spec/tengine/job/element_selector_notation_spec.rb +354 -0
- data/spec/tengine/job/examples_spec.rb +62 -0
- data/spec/tengine/job/execution_spec.rb +100 -0
- data/spec/tengine/job/expansion_spec.rb +116 -0
- data/spec/tengine/job/hadoop_job_run_spec.rb +65 -0
- data/spec/tengine/job/job_spec.rb +4 -0
- data/spec/tengine/job/jobnet/1015_complecated_jobnet_spec.rb +72 -0
- data/spec/tengine/job/jobnet_actual_spec.rb +175 -0
- data/spec/tengine/job/jobnet_spec.rb +399 -0
- data/spec/tengine/job/jobnet_template_spec.rb +240 -0
- data/spec/tengine/job/killing_spec.rb +91 -0
- data/spec/tengine/job/reset_spec.rb +958 -0
- data/spec/tengine/job/reset_spec/4056_1_dump.txt +1 -0
- data/spec/tengine/job/root_jobnet_actual_spec.rb +89 -0
- data/spec/tengine/job/root_jobnet_template_spec.rb +248 -0
- data/spec/tengine/job/script_executable_spec.rb +132 -0
- data/spec/tengine/job/stoppable_spec.rb +176 -0
- data/spec/tengine/job/vertex_spec.rb +25 -0
- data/spec/tengine_job_spec.rb +4 -0
- data/tengine_job.gemspec +197 -0
- data/tmp/log/.gitignore +1 -0
- metadata +296 -0
@@ -0,0 +1,150 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tsort'
|
3
|
+
|
4
|
+
class Tengine::Job::Jobnet::Builder
|
5
|
+
include TSort
|
6
|
+
|
7
|
+
def initialize(client, boot_job_names, redirections)
|
8
|
+
@client, @boot_job_names, @redirections = client, boot_job_names, redirections.dup
|
9
|
+
@graph = Hash.new do |h, k| h[k] = Array.new end
|
10
|
+
@redirections.each do |(x, y)|
|
11
|
+
@graph[x] << y
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def children; @client.children; end
|
16
|
+
def child_by_name(*args); @client.child_by_name(*args); end
|
17
|
+
def new_edge(*args); @client.new_edge(*args); end
|
18
|
+
def prepare_end(*args, &block); @client.prepare_end(*args, &block); end
|
19
|
+
|
20
|
+
def process
|
21
|
+
tsort
|
22
|
+
rescue TSort::Cyclic
|
23
|
+
raise Tengine::Job::DslError, "circular dependency found in jobnet ``#{@client.name}''"
|
24
|
+
else
|
25
|
+
build_start_edges
|
26
|
+
build_edge_by_redirections
|
27
|
+
prepare_end do |_end|
|
28
|
+
build_end_edges(_end, @boot_job_names.map{|jn| [:start, jn]} + @redirections)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def tsort_each_child node, &block
|
35
|
+
@graph.fetch(node, Array.new).each(&block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def tsort_each_node(&block)
|
39
|
+
@graph.each_key(&block)
|
40
|
+
end
|
41
|
+
|
42
|
+
def build_start_edges
|
43
|
+
start = children.first
|
44
|
+
case @boot_job_names.length
|
45
|
+
when 0 then raise "Must be a bug!!!"
|
46
|
+
when 1 then
|
47
|
+
new_edge(start, child_by_name(@boot_job_names.first))
|
48
|
+
else
|
49
|
+
fork = Tengine::Job::Fork.new
|
50
|
+
children << fork
|
51
|
+
new_edge(start, fork)
|
52
|
+
@boot_job_names.each do |boot_job_name|
|
53
|
+
new_edge(fork, child_by_name(boot_job_name))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def build_edge_by_redirections
|
59
|
+
prepare_to_build_edge_by_redirections # 処理の準備
|
60
|
+
build_forks_and_edges # Forkを生成して特異edge以外を繋ぐ
|
61
|
+
build_joins_and_edges # Joinを生成して特異edge以外を繋ぐ
|
62
|
+
build_fork_to_join_edges # 特異edgeの両端になるforkとjoinは生成されているのでそれらを繋ぐ
|
63
|
+
build_normal_edges # Fork、Join、特異edgeなどに関係しなかった普通のedgeを繋ぐ
|
64
|
+
end
|
65
|
+
|
66
|
+
def prepare_to_build_edge_by_redirections
|
67
|
+
# 各vertexがstartあるいはendとしてそれぞれ何回使われているのかを集計
|
68
|
+
start_vertex_counts = @redirections.inject({}){|d, (_start, _)| d[_start] ||= 0; d[_start] += 1; d}
|
69
|
+
end_vertex_counts = @redirections.inject({}){|d, (_, _end)| d[_end ] ||= 0; d[_end ] += 1; d}
|
70
|
+
# 2回以上startに使われているやつはforkの元、2回以上endに使われているやつはjoinの先になる
|
71
|
+
@fork_origins = start_vertex_counts.delete_if{|_,v| v < 2}.keys
|
72
|
+
@join_destinations = end_vertex_counts.delete_if{|_,v| v < 2}.keys
|
73
|
+
# ForkからJoinへedgeで結ばれる箇所を「特異edge」と呼び、特別扱いする
|
74
|
+
@fork_to_join = []
|
75
|
+
@redirections.each do |(_start, _end)|
|
76
|
+
if @fork_origins.include?(_start) && @join_destinations.include?(_end)
|
77
|
+
@fork_to_join << [_start, _end]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
# puts "=" * 100
|
81
|
+
# puts "fork origins : " << @fork_origins.inspect
|
82
|
+
# puts "join_destinations: " << @join_destinations.inspect
|
83
|
+
# puts "fork_to_join : " << @fork_to_join.inspect
|
84
|
+
@no_edge_redirections = @redirections.dup
|
85
|
+
end
|
86
|
+
|
87
|
+
def build_forks_and_edges
|
88
|
+
@fork_origin_to_fork = {}
|
89
|
+
@fork_origins.each do |fork_origin|
|
90
|
+
children << fork = Tengine::Job::Fork.new
|
91
|
+
@fork_origin_to_fork[fork_origin] = fork
|
92
|
+
new_edge(child_by_name(fork_origin), fork)
|
93
|
+
@redirections.dup.
|
94
|
+
delete_if{|r| @fork_to_join.include?(r)}.
|
95
|
+
select{|(_start,_)| _start == fork_origin}.
|
96
|
+
each{|(_, _end)| new_edge(fork, child_by_name(_end))}
|
97
|
+
@no_edge_redirections.delete_if{|_start, _| _start == fork_origin}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def build_joins_and_edges
|
102
|
+
@join_destination_to_join = {}
|
103
|
+
@join_destinations.each do |join_destination|
|
104
|
+
children << join = Tengine::Job::Join.new
|
105
|
+
@join_destination_to_join[join_destination] = join
|
106
|
+
@redirections.dup.
|
107
|
+
delete_if{|r| @fork_to_join.include?(r)}.
|
108
|
+
select{|(_, _end)| _end == join_destination}.
|
109
|
+
each{|(_start, _)| new_edge(child_by_name(_start), join)}
|
110
|
+
new_edge(join, child_by_name(join_destination))
|
111
|
+
@no_edge_redirections.delete_if{|_, _end| _end == join_destination}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def build_fork_to_join_edges
|
116
|
+
@fork_to_join.each do |fork_origin, join_destination|
|
117
|
+
new_edge(
|
118
|
+
@fork_origin_to_fork[fork_origin],
|
119
|
+
@join_destination_to_join[join_destination])
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def build_normal_edges
|
124
|
+
@no_edge_redirections.each do |(_start, _end)|
|
125
|
+
new_edge(child_by_name(_start), child_by_name(_end))
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def build_end_edges(_end, redirections)
|
130
|
+
end_points = select_end_points(redirections)
|
131
|
+
case end_points.length
|
132
|
+
when 0 then raise "Must be a bug!!!"
|
133
|
+
when 1 then new_edge(child_by_name(end_points.first), _end)
|
134
|
+
else
|
135
|
+
join = Tengine::Job::Join.new
|
136
|
+
children << join
|
137
|
+
end_points.each{|point| new_edge(child_by_name(point), join)}
|
138
|
+
new_edge(join, _end)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def select_end_points(redirections)
|
143
|
+
vertexes = redirections.flatten.uniq
|
144
|
+
redirections.each do |(_start, _end)|
|
145
|
+
vertexes.delete(_start)
|
146
|
+
end
|
147
|
+
vertexes
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tengine/job/jobnet'
|
3
|
+
|
4
|
+
module Tengine::Job::Jobnet::JobStateTransition
|
5
|
+
include Tengine::Job::Jobnet::StateTransition
|
6
|
+
|
7
|
+
# ハンドリングするドライバ: ジョブネット制御ドライバ
|
8
|
+
def job_transmit(signal)
|
9
|
+
self.phase_key = :ready
|
10
|
+
self.started_at = signal.event.occurred_at
|
11
|
+
signal.fire(self, :"start.job.job.tengine", {
|
12
|
+
:target_jobnet_id => parent.id,
|
13
|
+
:target_jobnet_name_path => parent.name_path,
|
14
|
+
:target_job_id => self.id,
|
15
|
+
:target_job_name_path => self.name_path,
|
16
|
+
})
|
17
|
+
end
|
18
|
+
available(:job_transmit, :on => :initialized,
|
19
|
+
:ignored => [:ready, :starting, :running, :dying, :success, :error, :stuck])
|
20
|
+
|
21
|
+
# ハンドリングするドライバ: ジョブ制御ドライバ
|
22
|
+
def job_activate(signal)
|
23
|
+
case phase_key
|
24
|
+
when :initialized then
|
25
|
+
# 特別ルール「starting直前stop」
|
26
|
+
# initializedに戻されたジョブに対して、:readyになる際にtransmitで送信されたイベントを受け取って、
|
27
|
+
# activateしようとすると状態は遷移しないが、後続のエッジを実行する。
|
28
|
+
# (エッジを実行しようとした際、エッジがclosedならばそのジョブネットのEndに遷移する。)
|
29
|
+
next_edges.first.transmit(signal)
|
30
|
+
when :ready then
|
31
|
+
complete_origin_edge(signal)
|
32
|
+
self.phase_key = :starting
|
33
|
+
self.started_at = signal.event.occurred_at
|
34
|
+
execution = signal.execution
|
35
|
+
if execution.retry
|
36
|
+
if execution.target_actual_ids.include?(self.id.to_s)
|
37
|
+
execution.ack(signal)
|
38
|
+
elsif execution.target_actuals.map{|t| t.parent.id.to_s if t.parent }.include?(self.parent.id.to_s)
|
39
|
+
# 自身とTengine::Job::Execution#target_actual_idsに含まれるジョブ/ジョブネットと親が同じならば、ackしない
|
40
|
+
else
|
41
|
+
parent.ack(signal)
|
42
|
+
end
|
43
|
+
else
|
44
|
+
parent.ack(signal) # 再実行でない場合
|
45
|
+
end
|
46
|
+
# このコールバックはjob_control_driverでupdate_with_lockの外側から
|
47
|
+
# 再度呼び出してもらうためにcallbackを設定しています
|
48
|
+
signal.callback = lambda{ root.vertex(self.id).activate(signal) }
|
49
|
+
when :starting then
|
50
|
+
# 実際にSSHでスクリプトを実行
|
51
|
+
execution = signal.execution
|
52
|
+
execution.signal = signal # ackを呼び返してもらうための苦肉の策
|
53
|
+
begin
|
54
|
+
run(execution)
|
55
|
+
rescue Tengine::Job::ScriptExecutable::Error => e
|
56
|
+
signal.callback = lambda do
|
57
|
+
job_fail(signal, :message => e.message)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
available(:job_activate, :on => [:initialized, :ready, :starting],
|
63
|
+
:ignored => [:running, :dying, :success, :error, :stuck])
|
64
|
+
|
65
|
+
# ハンドリングするドライバ: ジョブ制御ドライバ
|
66
|
+
# スクリプトのプロセスのPIDを取得できたときに実行されます
|
67
|
+
def job_ack(signal)
|
68
|
+
self.executing_pid = (signal.data || {})[:executing_pid]
|
69
|
+
self.phase_key = :running
|
70
|
+
end
|
71
|
+
available(:job_ack, :on => :starting,
|
72
|
+
:ignored => [:running, :dying, :success, :error, :stuck])
|
73
|
+
|
74
|
+
def job_finish(signal)
|
75
|
+
self.exit_status = signal.event[:exit_status]
|
76
|
+
self.finished_at = signal.event.occurred_at
|
77
|
+
(self.exit_status.to_s == '0') ?
|
78
|
+
job_succeed(signal) :
|
79
|
+
job_fail(signal)
|
80
|
+
end
|
81
|
+
|
82
|
+
# ハンドリングするドライバ: ジョブ制御ドライバ
|
83
|
+
def job_succeed(signal)
|
84
|
+
self.phase_key = :success
|
85
|
+
self.finished_at = signal.event.occurred_at
|
86
|
+
signal.fire(self, :"success.job.job.tengine", {
|
87
|
+
:exit_status => self.exit_status,
|
88
|
+
:target_jobnet_id => parent.id,
|
89
|
+
:target_jobnet_name_path => parent.name_path,
|
90
|
+
:target_job_id => self.id,
|
91
|
+
:target_job_name_path => self.name_path,
|
92
|
+
})
|
93
|
+
end
|
94
|
+
available :job_succeed, :on => [:starting, :running, :dying, :stuck], :ignored => [:success]
|
95
|
+
|
96
|
+
# ハンドリングするドライバ: ジョブ制御ドライバ
|
97
|
+
def job_fail(signal, options = nil)
|
98
|
+
self.phase_key = :error
|
99
|
+
if msg = signal.event[:message]
|
100
|
+
self.error_messages ||= []
|
101
|
+
self.error_messages += [msg]
|
102
|
+
end
|
103
|
+
if options && (msg = options[:message])
|
104
|
+
self.error_messages ||= []
|
105
|
+
self.error_messages += [msg]
|
106
|
+
end
|
107
|
+
self.finished_at = signal.event.occurred_at
|
108
|
+
event_options = {
|
109
|
+
:exit_status => self.exit_status,
|
110
|
+
:target_jobnet_id => parent.id,
|
111
|
+
:target_jobnet_name_path => parent.name_path,
|
112
|
+
:target_job_id => self.id,
|
113
|
+
:target_job_name_path => self.name_path,
|
114
|
+
}
|
115
|
+
event_options.update(options) if options
|
116
|
+
signal.fire(self, :"error.job.job.tengine", event_options)
|
117
|
+
end
|
118
|
+
available :job_fail, :on => [:starting, :running, :dying, :stuck], :ignored => [:error]
|
119
|
+
|
120
|
+
def job_fire_stop(signal)
|
121
|
+
signal.fire(self, :"stop.job.job.tengine", {
|
122
|
+
:stop_reason => signal.event[:stop_reason],
|
123
|
+
:target_jobnet_id => parent.id,
|
124
|
+
:target_jobnet_name_path => parent.name_path,
|
125
|
+
:target_job_id => self.id,
|
126
|
+
:target_job_name_path => self.name_path,
|
127
|
+
})
|
128
|
+
end
|
129
|
+
available :job_fire_stop, :on => [:ready, :starting, :running], :ignored => [:initialized, :dying, :success, :error, :stuck]
|
130
|
+
|
131
|
+
def job_stop(signal, &block)
|
132
|
+
case phase_key
|
133
|
+
when :ready then
|
134
|
+
self.phase_key = :initialized
|
135
|
+
self.stopped_at = signal.event.occurred_at
|
136
|
+
self.stop_reason = signal.event[:stop_reason]
|
137
|
+
next_edges.first.transmit(signal)
|
138
|
+
when :starting then
|
139
|
+
job = nil
|
140
|
+
loop do
|
141
|
+
root = self.root.reload # class.find(self.root.id)
|
142
|
+
job = root.find_descendant(self.id)
|
143
|
+
break unless job.phase_key == :starting
|
144
|
+
yield if block_given? # テストの為にyieldしています
|
145
|
+
sleep(0.1)
|
146
|
+
end
|
147
|
+
job.stop(signal, &block)
|
148
|
+
when :running then
|
149
|
+
self.phase_key = :dying
|
150
|
+
self.stopped_at = signal.event.occurred_at
|
151
|
+
self.stop_reason = signal.event[:stop_reason]
|
152
|
+
signal.callback = lambda do
|
153
|
+
kill(signal.execution)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
available :job_stop, :on => [:ready, :starting, :running], :ignored => [:initialized, :dying, :success, :error, :stuck]
|
158
|
+
|
159
|
+
def job_reset(signal, &block)
|
160
|
+
self.phase_key = :initialized
|
161
|
+
if signal.execution.in_scope?(self)
|
162
|
+
next_edges.first.reset(signal)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
available :job_reset, :on => [:initialized, :success, :error, :stuck]
|
166
|
+
|
167
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tengine/job/jobnet'
|
3
|
+
|
4
|
+
module Tengine::Job::Jobnet::JobnetStateTransition
|
5
|
+
include Tengine::Job::Jobnet::StateTransition
|
6
|
+
|
7
|
+
# ハンドリングするドライバ: ジョブネット制御ドライバ or ジョブ起動ドライバ
|
8
|
+
def jobnet_transmit(signal)
|
9
|
+
self.phase_key = :ready
|
10
|
+
signal.fire(self, :"start.jobnet.job.tengine", {
|
11
|
+
:target_jobnet_id => self.id,
|
12
|
+
:target_jobnet_name_path => self.name_path,
|
13
|
+
})
|
14
|
+
end
|
15
|
+
available(:jobnet_transmit, :on => :initialized,
|
16
|
+
:ignored => [:ready, :starting, :running, :dying, :success, :error, :stuck])
|
17
|
+
|
18
|
+
# ハンドリングするドライバ: ジョブネット制御ドライバ
|
19
|
+
def jobnet_activate(signal)
|
20
|
+
self.phase_key = :starting
|
21
|
+
self.started_at = signal.event.occurred_at
|
22
|
+
complete_origin_edge(signal) if prev_edges && !prev_edges.empty?
|
23
|
+
(parent || signal.execution).ack(signal)
|
24
|
+
signal.paths << self
|
25
|
+
self.start_vertex.transmit(signal)
|
26
|
+
end
|
27
|
+
available(:jobnet_activate, :on => :ready,
|
28
|
+
:ignored => [:starting, :running, :dying, :success, :error, :stuck])
|
29
|
+
|
30
|
+
# ハンドリングするドライバ: ジョブネット制御ドライバ
|
31
|
+
# このackは、子要素のTengine::Job::Start#activateから呼ばれます
|
32
|
+
def jobnet_ack(signal)
|
33
|
+
self.phase_key = :running
|
34
|
+
end
|
35
|
+
available(:jobnet_ack, :on => [:initialized, :ready, :starting],
|
36
|
+
:ignored => [:running, :dying, :success, :error, :stuck])
|
37
|
+
|
38
|
+
# ハンドリングするドライバ: ジョブネット制御ドライバ
|
39
|
+
# このackは、子要素のTengine::Job::End#activateから呼ばれます
|
40
|
+
def jobnet_finish(signal)
|
41
|
+
edge = end_vertex.prev_edges.first
|
42
|
+
edge.closed? ?
|
43
|
+
jobnet_fail(signal) :
|
44
|
+
jobnet_succeed(signal)
|
45
|
+
end
|
46
|
+
|
47
|
+
# ハンドリングするドライバ: ジョブネット制御ドライバ
|
48
|
+
def jobnet_succeed(signal)
|
49
|
+
self.phase_key = :success
|
50
|
+
self.finished_at = signal.event.occurred_at
|
51
|
+
signal.fire(self, :"success.jobnet.job.tengine", {
|
52
|
+
:target_jobnet_id => self.id,
|
53
|
+
:target_jobnet_name_path => self.name_path,
|
54
|
+
})
|
55
|
+
end
|
56
|
+
available :jobnet_succeed, :on => [:starting, :running, :dying, :stuck, :error], :ignored => [:success]
|
57
|
+
|
58
|
+
# ハンドリングするドライバ: ジョブネット制御ドライバ
|
59
|
+
def jobnet_fail(signal)
|
60
|
+
return if self.edges.any?(&:alive?)
|
61
|
+
self.phase_key = :error
|
62
|
+
self.finished_at = signal.event.occurred_at
|
63
|
+
signal.fire(self, :"error.jobnet.job.tengine", {
|
64
|
+
:target_jobnet_id => self.id,
|
65
|
+
:target_jobnet_name_path => self.name_path,
|
66
|
+
})
|
67
|
+
end
|
68
|
+
available :jobnet_fail, :on => [:starting, :running, :dying, :stuck, :success], :ignored => [:error]
|
69
|
+
|
70
|
+
def jobnet_fire_stop(signal)
|
71
|
+
return if self.phase_key == :initialized
|
72
|
+
signal.fire(self, :"stop.jobnet.job.tengine", {
|
73
|
+
:target_jobnet_id => self.id,
|
74
|
+
:target_jobnet_name_path => self.name_path,
|
75
|
+
:stop_reason => signal.event[:stop_reason]
|
76
|
+
})
|
77
|
+
end
|
78
|
+
|
79
|
+
def jobnet_stop(signal)
|
80
|
+
self.phase_key = :dying
|
81
|
+
self.stopped_at = signal.event.occurred_at
|
82
|
+
self.stop_reason = signal.event[:stop_reason]
|
83
|
+
close(signal)
|
84
|
+
children.each do |child|
|
85
|
+
child.fire_stop(signal) if child.respond_to?(:fire_stop)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
available :jobnet_stop, :on => [:initialized, :ready, :starting, :running], :ignored => [:dying, :success, :error, :stuck]
|
89
|
+
|
90
|
+
def close(signal)
|
91
|
+
self.edges.each{|edge| edge.close(signal)}
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def jobnet_reset(signal, &block)
|
96
|
+
# children.each{|c| c.reset(signal) }
|
97
|
+
self.phase_key = :initialized
|
98
|
+
if s = start_vertex
|
99
|
+
s.reset(signal)
|
100
|
+
end
|
101
|
+
if edge = (next_edges || []).first
|
102
|
+
edge.reset(signal)
|
103
|
+
end
|
104
|
+
rescue Exception => e
|
105
|
+
puts "#{self.name_path} [#{e.class}] #{e.message}"
|
106
|
+
raise
|
107
|
+
end
|
108
|
+
available :jobnet_reset, :on => [:initialized, :success, :error, :stuck]
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tengine/job/jobnet'
|
3
|
+
|
4
|
+
module Tengine::Job::Jobnet::StateTransition
|
5
|
+
|
6
|
+
def self.included(mod)
|
7
|
+
mod.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def available(method_name, options = {})
|
12
|
+
original_method = :"__#{method_name}_without_ignore_and_na"
|
13
|
+
available_phase_keys = Array(options[:on])
|
14
|
+
ignored_phase_keys = Array(options[:ignored])
|
15
|
+
ignore_case = ignored_phase_keys.empty? ? "" :
|
16
|
+
"when #{ignored_phase_keys.map(&:inspect).join(', ')} then return"
|
17
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
18
|
+
if method_defined?(:#{original_method})
|
19
|
+
raise "Already available_on #{method_name}"
|
20
|
+
end
|
21
|
+
alias #{original_method} #{method_name}
|
22
|
+
|
23
|
+
def #{method_name}(*args, &block)
|
24
|
+
case self.phase_key
|
25
|
+
when #{available_phase_keys.map(&:inspect).join(', ')} then
|
26
|
+
#{original_method}(*args, &block)
|
27
|
+
#{ignore_case}
|
28
|
+
else
|
29
|
+
raise Tengine::Job::Executable::PhaseError, "\#{name_path} \#{self.class.name}##{method_name} not available when the phase_key of \#{self.name_path.inspect} is \#{self.phase_key.inspect}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
EOS
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|