tengine_job 0.6.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +23 -0
  4. data/Gemfile.lock +109 -0
  5. data/README.rdoc +20 -0
  6. data/Rakefile +42 -0
  7. data/VERSION +1 -0
  8. data/examples/0004_retry_one_layer.rb +24 -0
  9. data/examples/0004_retry_one_layer.sh +38 -0
  10. data/examples/0005_retry_two_layer.rb +54 -0
  11. data/examples/0005_retry_two_layer.sh +80 -0
  12. data/examples/0006_retry_three_layer.rb +58 -0
  13. data/examples/0006_retry_three_layer.sh +74 -0
  14. data/examples/0007_simple_jobnet.rb +7 -0
  15. data/examples/0021_dynamic_env.rb +20 -0
  16. data/examples/VERSION +1 -0
  17. data/examples/tengine_job_test.sh +10 -0
  18. data/lib/tengine/job.rb +94 -0
  19. data/lib/tengine/job/category.rb +54 -0
  20. data/lib/tengine/job/connectable.rb +43 -0
  21. data/lib/tengine/job/drivers/job_control_driver.rb +82 -0
  22. data/lib/tengine/job/drivers/job_execution_driver.rb +30 -0
  23. data/lib/tengine/job/drivers/jobnet_control_driver.rb +117 -0
  24. data/lib/tengine/job/drivers/schedule_driver.rb +30 -0
  25. data/lib/tengine/job/dsl_binder.rb +12 -0
  26. data/lib/tengine/job/dsl_evaluator.rb +18 -0
  27. data/lib/tengine/job/dsl_loader.rb +180 -0
  28. data/lib/tengine/job/edge.rb +150 -0
  29. data/lib/tengine/job/element_selector_notation.rb +169 -0
  30. data/lib/tengine/job/end.rb +32 -0
  31. data/lib/tengine/job/executable.rb +74 -0
  32. data/lib/tengine/job/execution.rb +141 -0
  33. data/lib/tengine/job/expansion.rb +37 -0
  34. data/lib/tengine/job/fork.rb +6 -0
  35. data/lib/tengine/job/job.rb +23 -0
  36. data/lib/tengine/job/jobnet.rb +173 -0
  37. data/lib/tengine/job/jobnet/builder.rb +150 -0
  38. data/lib/tengine/job/jobnet/job_state_transition.rb +167 -0
  39. data/lib/tengine/job/jobnet/jobnet_state_transition.rb +110 -0
  40. data/lib/tengine/job/jobnet/state_transition.rb +37 -0
  41. data/lib/tengine/job/jobnet_actual.rb +55 -0
  42. data/lib/tengine/job/jobnet_template.rb +10 -0
  43. data/lib/tengine/job/join.rb +6 -0
  44. data/lib/tengine/job/junction.rb +29 -0
  45. data/lib/tengine/job/killing.rb +30 -0
  46. data/lib/tengine/job/mm_compatibility.rb +6 -0
  47. data/lib/tengine/job/mm_compatibility/connectable.rb +13 -0
  48. data/lib/tengine/job/name_path.rb +31 -0
  49. data/lib/tengine/job/root.rb +16 -0
  50. data/lib/tengine/job/root_jobnet_actual.rb +39 -0
  51. data/lib/tengine/job/root_jobnet_template.rb +49 -0
  52. data/lib/tengine/job/script_executable.rb +235 -0
  53. data/lib/tengine/job/signal.rb +121 -0
  54. data/lib/tengine/job/start.rb +20 -0
  55. data/lib/tengine/job/stoppable.rb +15 -0
  56. data/lib/tengine/job/vertex.rb +172 -0
  57. data/lib/tengine_job.rb +3 -0
  58. data/spec/fixtures/rjn_0001_simple_jobnet_builder.rb +42 -0
  59. data/spec/fixtures/rjn_0002_simple_parallel_jobnet_builder.rb +42 -0
  60. data/spec/fixtures/rjn_0003_fork_join_jobnet_builder.rb +61 -0
  61. data/spec/fixtures/rjn_0004_parallel_jobnet_with_finally_fixture.rb +62 -0
  62. data/spec/fixtures/rjn_0005_retry_two_layer_fixture.rb +153 -0
  63. data/spec/fixtures/rjn_0008_expansion_fixture.rb +32 -0
  64. data/spec/fixtures/rjn_0009_tree_sequential_jobnet_builder.rb +174 -0
  65. data/spec/fixtures/rjn_0010_2jobs_and_1job_parallel_jobnet_builder.rb +39 -0
  66. data/spec/fixtures/rjn_0011_nested_fork_jobnet_builder.rb +96 -0
  67. data/spec/fixtures/rjn_0012_nested_and_finally_builder.rb +157 -0
  68. data/spec/fixtures/rjn_1004_hadoop_job_in_jobnet_fixture.rb +105 -0
  69. data/spec/fixtures/rjn_means_root_jobnet +0 -0
  70. data/spec/fixtures/test_credential_fixture.rb +12 -0
  71. data/spec/fixtures/test_server_fixture.rb +28 -0
  72. data/spec/mongoid.yml +35 -0
  73. data/spec/spec_helper.rb +56 -0
  74. data/spec/sshd/.gitignore +1 -0
  75. data/spec/sshd/id_rsa +51 -0
  76. data/spec/sshd/id_rsa.pub +1 -0
  77. data/spec/sshd/ssh_host_rsa_key +51 -0
  78. data/spec/sshd/ssh_host_rsa_key.pub +1 -0
  79. data/spec/sshd/sshd_config +10 -0
  80. data/spec/sshd/sshd_config.erb +11 -0
  81. data/spec/sshd/tengine_job_test.sh +6 -0
  82. data/spec/support/jobnet_fixture_builder.rb +145 -0
  83. data/spec/support/mongo_index_key_log.rb +91 -0
  84. data/spec/tengine/job/category_spec.rb +193 -0
  85. data/spec/tengine/job/connectable_spec.rb +94 -0
  86. data/spec/tengine/job/drivers/job_controll_driver/connection_error_spec.rb +236 -0
  87. data/spec/tengine/job/drivers/job_controll_driver/duplicated_job_start_spec.rb +302 -0
  88. data/spec/tengine/job/drivers/job_controll_driver/expansion_spec.rb +120 -0
  89. data/spec/tengine/job/drivers/job_controll_driver/stop_spec.rb +159 -0
  90. data/spec/tengine/job/drivers/job_controll_driver_spec.rb +623 -0
  91. data/spec/tengine/job/drivers/job_execution_driver_spec.rb +88 -0
  92. data/spec/tengine/job/drivers/jobnet_control_driver/nested_and_finally_spec.rb +472 -0
  93. data/spec/tengine/job/drivers/jobnet_control_driver/nested_jobnet_spec.rb +231 -0
  94. data/spec/tengine/job/drivers/jobnet_control_driver/stop_jobnet_spec.rb +202 -0
  95. data/spec/tengine/job/drivers/jobnet_control_driver_spec.rb +446 -0
  96. data/spec/tengine/job/drivers/schedule_driver_spec.rb +202 -0
  97. data/spec/tengine/job/dsl_binder_spec.rb +36 -0
  98. data/spec/tengine/job/dsl_loader_spec.rb +403 -0
  99. data/spec/tengine/job/dsls/0013_hadoop_job_run.rb +29 -0
  100. data/spec/tengine/job/dsls/0014_join_and_join.rb +19 -0
  101. data/spec/tengine/job/dsls/0015_fork_and_fork.rb +18 -0
  102. data/spec/tengine/job/dsls/0016_complex_fork_and_join.rb +20 -0
  103. data/spec/tengine/job/dsls/0017_finally.rb +15 -0
  104. data/spec/tengine/job/dsls/0018_expansion.rb +23 -0
  105. data/spec/tengine/job/dsls/0019_execute_job_on_event.rb +16 -0
  106. data/spec/tengine/job/dsls/0020_duplicated_jobnet_name.rb +16 -0
  107. data/spec/tengine/job/dsls/1060_test_dir1/1060_test_dir2/0013_hadoop_job_run.rb +29 -0
  108. data/spec/tengine/job/dsls/2003_expansion/expansion_5.rb +11 -0
  109. data/spec/tengine/job/dsls/VERSION +1 -0
  110. data/spec/tengine/job/dynamic_env_spec.rb +95 -0
  111. data/spec/tengine/job/edge_spec.rb +241 -0
  112. data/spec/tengine/job/element_selector_notation_spec.rb +354 -0
  113. data/spec/tengine/job/examples_spec.rb +62 -0
  114. data/spec/tengine/job/execution_spec.rb +100 -0
  115. data/spec/tengine/job/expansion_spec.rb +116 -0
  116. data/spec/tengine/job/hadoop_job_run_spec.rb +65 -0
  117. data/spec/tengine/job/job_spec.rb +4 -0
  118. data/spec/tengine/job/jobnet/1015_complecated_jobnet_spec.rb +72 -0
  119. data/spec/tengine/job/jobnet_actual_spec.rb +175 -0
  120. data/spec/tengine/job/jobnet_spec.rb +399 -0
  121. data/spec/tengine/job/jobnet_template_spec.rb +240 -0
  122. data/spec/tengine/job/killing_spec.rb +91 -0
  123. data/spec/tengine/job/reset_spec.rb +958 -0
  124. data/spec/tengine/job/reset_spec/4056_1_dump.txt +1 -0
  125. data/spec/tengine/job/root_jobnet_actual_spec.rb +89 -0
  126. data/spec/tengine/job/root_jobnet_template_spec.rb +248 -0
  127. data/spec/tengine/job/script_executable_spec.rb +132 -0
  128. data/spec/tengine/job/stoppable_spec.rb +176 -0
  129. data/spec/tengine/job/vertex_spec.rb +25 -0
  130. data/spec/tengine_job_spec.rb +4 -0
  131. data/tengine_job.gemspec +197 -0
  132. data/tmp/log/.gitignore +1 -0
  133. metadata +296 -0
@@ -0,0 +1,231 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+ require 'tengine/rspec'
4
+
5
+ describe 'jobnet_control_driver' do
6
+ include Tengine::RSpec::Extension
7
+
8
+ target_dsl File.expand_path("../../../../../lib/tengine/job/drivers/jobnet_control_driver.rb", File.dirname(__FILE__))
9
+ driver :jobnet_control_driver
10
+
11
+ # in [rjn0011]
12
+ # (S1)--e1-->[j1100]--e2-->(j1200)--e3-->[j1300]--e4-->(E1)
13
+ #
14
+ # in [j1100]
15
+ # (S2)--e5-->(j1110)--e6-->[j1120]--e7-->[j1130]--e8-->(j1140)--e9-->(E2)
16
+ #
17
+ # in [j1120]
18
+ # (S3)--e10-->(j1121)--e11-->(E3)
19
+ #
20
+ # in [j1130]
21
+ # (S4)--e12-->(j1131)--e13-->(E4)
22
+ #
23
+ # in [j1300]
24
+ # (S5)--e14-->(j1310)--e15-->(E5)
25
+ #
26
+ context "rjn0011" do
27
+ before do
28
+ Tengine::Job::Vertex.delete_all
29
+ builder = Rjn0011NestedForkJobnetBuilder.new
30
+ @root = builder.create_actual
31
+ @ctx = builder.context
32
+ @execution = Tengine::Job::Execution.create!({
33
+ :root_jobnet_id => @root.id,
34
+ })
35
+ @base_props = {
36
+ :execution_id => @execution.id.to_s,
37
+ :root_jobnet_id => @root.id.to_s,
38
+ :root_jobnet_name_path => @root.name_path,
39
+ :target_jobnet_id => @root.id.to_s,
40
+ :target_jobnet_name_path => @root.name_path,
41
+ }
42
+ end
43
+
44
+ it "S1から起動" do
45
+ @root.phase_key = :ready
46
+ @root.save!
47
+ tengine.should_fire(:"start.jobnet.job.tengine",
48
+ :source_name => @ctx[:j1100].name_as_resource,
49
+ :properties => @base_props.merge({
50
+ :target_jobnet_id => @ctx[:j1100].id.to_s,
51
+ :target_jobnet_name_path => @ctx[:j1100].name_path,
52
+ }))
53
+ tengine.receive("start.jobnet.job.tengine", :properties => @base_props)
54
+ @root.reload
55
+ @ctx.edge(:e1).phase_key.should == :transmitting
56
+ (2..15).each{|idx| @ctx.edge(:"e#{idx}").phase_key.should == :active }
57
+ @root.phase_key.should == :starting
58
+ @ctx.vertex(:j1100).phase_key.should == :ready
59
+ end
60
+
61
+ context "j1100を起動" do
62
+ it do
63
+ @root.phase_key = :starting
64
+ @ctx.vertex(:j1100).phase_key = :ready
65
+ @ctx[:e1].phase_key = :transmitting
66
+ (2..15).each{|idx| @ctx[:"e#{idx}"].phase_key = :active }
67
+ @root.save!
68
+ tengine.should_fire(:"start.job.job.tengine",
69
+ :source_name => @ctx[:j1110].name_as_resource,
70
+ :properties => @base_props.merge({
71
+ :target_jobnet_id => @ctx[:j1100].id.to_s,
72
+ :target_jobnet_name_path => @ctx[:j1100].name_path,
73
+ :target_job_id => @ctx[:j1110].id.to_s,
74
+ :target_job_name_path => @ctx[:j1110].name_path,
75
+ }))
76
+ tengine.receive(:"start.jobnet.job.tengine", :properties => @base_props.merge({
77
+ :target_jobnet_id => @ctx[:j1100].id.to_s,
78
+ :target_jobnet_name_path => @ctx[:j1100].name_path,
79
+ }))
80
+ @root.reload
81
+ @root.phase_key = :running
82
+ @ctx.edge(:e1).phase_key.should == :transmitted
83
+ @ctx.edge(:e5).phase_key.should == :transmitting
84
+ (2..4).each{|idx| @ctx.edge(:"e#{idx}").phase_key.should == :active }
85
+ (6..15).each{|idx| @ctx.edge(:"e#{idx}").phase_key.should == :active }
86
+ @ctx.vertex(:j1100).phase_key.should == :starting
87
+ end
88
+ end
89
+
90
+ context 'j1110を実行' do
91
+ it "成功した場合" do
92
+ @root.phase_key = :starting
93
+ @ctx.vertex(:j1100).phase_key = :running
94
+ @ctx.vertex(:j1110).phase_key = :success
95
+ @ctx[:e1].phase_key = :transmitted
96
+ @ctx[:e5].phase_key = :transmitted
97
+ @root.save!
98
+ tengine.should_not_fire(:"start.job.job.tengine",
99
+ :source_name => @ctx[:j1110].name_as_resource,
100
+ :properties => @base_props.merge({
101
+ :target_jobnet_id => @ctx[:j1100].id.to_s,
102
+ :target_jobnet_name_path => @ctx[:j1100].name_path,
103
+ :target_job_id => @ctx[:j1110].id.to_s,
104
+ :target_job_name_path => @ctx[:j1110].name_path,
105
+ }))
106
+ tengine.should_fire(:"start.jobnet.job.tengine",
107
+ :source_name => @ctx[:j1120].name_as_resource,
108
+ :properties => @base_props.merge({
109
+ :target_jobnet_id => @ctx[:j1120].id.to_s,
110
+ :target_jobnet_name_path => @ctx[:j1120].name_path,
111
+ }))
112
+ tengine.receive("success.job.job.tengine", :properties => @base_props.merge({
113
+ :target_jobnet_id => @ctx[:j1100].id.to_s,
114
+ :target_jobnet_name_path => @ctx[:j1100].name_path,
115
+ :target_job_id => @ctx[:j1110].id.to_s,
116
+ :target_job_name_path => @ctx[:j1110].name_path,
117
+ }))
118
+ @root.reload
119
+ @root.phase_key = :running
120
+ @ctx.edge(:e1).phase_key.should == :transmitted
121
+ @ctx.edge(:e5).phase_key.should == :transmitted
122
+ @ctx.edge(:e6).phase_key.should == :transmitting
123
+ ((2..15).to_a - [5, 6]).each do |idx|
124
+ [:"e#{idx}", @ctx.edge(:"e#{idx}").phase_key].should == [:"e#{idx}", :active]
125
+ end
126
+ @ctx.vertex(:j1100).phase_key.should == :running
127
+ @ctx.vertex(:j1110).phase_key.should == :success
128
+ @ctx.vertex(:j1120).phase_key.should == :ready
129
+ end
130
+
131
+ it "失敗した場合" do
132
+ @root.phase_key = :running
133
+ @ctx.vertex(:j1100).phase_key = :running
134
+ @ctx.vertex(:j1110).phase_key = :error
135
+ @ctx[:e1].phase_key = :transmitted
136
+ @ctx[:e5].phase_key = :transmitted
137
+ @root.save!
138
+ tengine.should_fire(:"error.jobnet.job.tengine",
139
+ :source_name => @ctx[:j1100].name_as_resource,
140
+ :properties => @base_props.merge({
141
+ :target_jobnet_id => @ctx[:j1100].id.to_s,
142
+ :target_jobnet_name_path => @ctx[:j1100].name_path,
143
+ }))
144
+ tengine.receive("error.job.job.tengine", :properties => @base_props.merge({
145
+ :target_jobnet_id => @ctx[:j1100].id.to_s,
146
+ :target_jobnet_name_path => @ctx[:j1100].name_path,
147
+ :target_job_id => @ctx[:j1110].id.to_s,
148
+ :target_job_name_path => @ctx[:j1110].name_path,
149
+ }))
150
+ @root.reload
151
+ @ctx.edge(:e1).phase_key.should == :transmitted
152
+ @ctx.edge(:e5).phase_key.should == :transmitted
153
+ (2..4).each{|idx| @ctx.edge(:"e#{idx}").phase_key.should == :closing }
154
+ (6..9).each{|idx| @ctx.edge(:"e#{idx}").phase_key.should == :closed }
155
+ (10..15).each{|idx| @ctx.edge(:"e#{idx}").phase_key.should == :active }
156
+ @ctx.vertex(:j1100).phase_key.should == :error
157
+ @ctx.vertex(:j1110).phase_key.should == :error
158
+ end
159
+ end
160
+
161
+
162
+ context 'j1100' do
163
+ it "成功した場合" do
164
+ @root.phase_key = :running
165
+ [:j1100, :j1110, :j1120, :j1130, :j1140].each do |jobnet_name|
166
+ @root.vertex(@ctx[jobnet_name].id).phase_key = :success
167
+ end
168
+ @ctx[:e1].phase_key = :transmitted
169
+ (5..9).each{|idx|@ctx[:"e#{idx}"].phase_key = :transmitted}
170
+ @root.save!
171
+ tengine.should_fire(:"start.job.job.tengine",
172
+ :source_name => @ctx[:j1200].name_as_resource,
173
+ :properties => @base_props.merge({
174
+ :target_jobnet_id => @root.id.to_s,
175
+ :target_jobnet_name_path => @root.name_path,
176
+ :target_job_id => @ctx[:j1200].id.to_s,
177
+ :target_job_name_path => @ctx[:j1200].name_path,
178
+ }))
179
+ tengine.receive("success.jobnet.job.tengine", :properties => @base_props.merge({
180
+ :target_jobnet_id => @ctx[:j1100].id.to_s,
181
+ }))
182
+ @root.reload
183
+ @root.edge(@ctx[:e1].id).phase_key.should == :transmitted
184
+ @root.edge(@ctx[:e2].id).phase_key.should == :transmitting
185
+ (3..4).each{|idx| @ctx.edge(:"e#{idx}").phase_key.should == :active }
186
+ (5..9).each{|idx| @ctx.edge(:"e#{idx}").phase_key.should == :transmitted }
187
+ (10..15).each{|idx| @ctx.edge(:"e#{idx}").phase_key.should == :active }
188
+ @root.vertex(@ctx[:j1100].id).phase_key.should == :success
189
+ @root.vertex(@ctx[:j1110].id).phase_key.should == :success
190
+ end
191
+
192
+ it "失敗した場合" do
193
+ @root.phase_key = :running
194
+ [:j1100, :j1110].each do |jobnet_name|
195
+ @root.vertex(@ctx[jobnet_name].id).phase_key = :error
196
+ end
197
+ [:j1120, :j1130, :j1140].each do |jobnet_name|
198
+ @root.vertex(@ctx[jobnet_name].id).phase_key = :ready
199
+ end
200
+ @ctx[:e1].phase_key = :transmitted
201
+ @ctx[:e5].phase_key = :transmitted
202
+ (6..9).each{|idx|@ctx[:"e#{idx}"].phase_key = :closed}
203
+ @root.save!
204
+
205
+ tengine.should_fire(:"error.jobnet.job.tengine",
206
+ :source_name => @root.name_as_resource,
207
+ :properties => @base_props.merge({
208
+ :target_jobnet_id => @root.id.to_s,
209
+ :target_jobnet_name_path => @root.name_path,
210
+ }))
211
+ tengine.receive("error.jobnet.job.tengine", :properties => @base_props.merge({
212
+ :target_jobnet_id => @ctx[:j1100].id.to_s,
213
+ :target_jobnet_name_path => @ctx[:j1100].name_path,
214
+ }))
215
+ @root.reload
216
+ @root.edge(@ctx[:e1].id).phase_key.should == :transmitted
217
+ (2..4).each do |idx|
218
+ [:"e#{idx}", @root.edge(@ctx[:"e#{idx}"].id).phase_key].should == [:"e#{idx}", :closed]
219
+ end
220
+ @root.edge(@ctx[:e5].id).phase_key.should == :transmitted
221
+ (6..9).each do |idx|
222
+ [:"e#{idx}", @root.edge(@ctx[:"e#{idx}"].id).phase_key].should == [:"e#{idx}", :closed]
223
+ end
224
+ @root.vertex(@ctx[:j1100].id).phase_key.should == :error
225
+ @root.vertex(@ctx[:j1110].id).phase_key.should == :error
226
+ end
227
+ end
228
+
229
+ end
230
+
231
+ end
@@ -0,0 +1,202 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+ require 'tengine/rspec'
4
+
5
+ describe 'stop.jobnet.job.tengine' do
6
+ include Tengine::RSpec::Extension
7
+
8
+ target_dsl File.expand_path("../../../../../lib/tengine/job/drivers/jobnet_control_driver.rb", File.dirname(__FILE__))
9
+ driver :jobnet_control_driver
10
+
11
+ context "rjn0011" do
12
+ before do
13
+ Tengine::Job::Vertex.delete_all
14
+ builder = Rjn0011NestedForkJobnetBuilder.new
15
+ @root = builder.create_actual
16
+ @ctx = builder.context
17
+ @execution = Tengine::Job::Execution.create!({
18
+ :root_jobnet_id => @root.id,
19
+ })
20
+ end
21
+
22
+ context "j1120" do
23
+ before do
24
+ @ctx[:root].tap{|j| j.phase_key = :running}
25
+ @ctx[:j1100].tap{|j| j.phase_key = :running}
26
+ @ctx[:j1110].tap{|j| j.phase_key = :success; j.executing_pid = "1110"}
27
+ [:e1, :e5, :e6].each{|name| @ctx[name].phase_key = :transmitted}
28
+ @base_props = {
29
+ :execution_id => @execution.id.to_s,
30
+ :root_jobnet_id => @root.id.to_s,
31
+ :root_jobnet_name_path => @root.name_path.to_s,
32
+ :target_jobnet_id => @ctx[:j1120].id.to_s,
33
+ :target_jobnet_name_path => @ctx[:j1120].name_path,
34
+ }
35
+ end
36
+
37
+ context "runningの場合" do
38
+ before do
39
+ @ctx[:j1120].tap{|j| j.phase_key = :running}
40
+ end
41
+
42
+ context "j1121がinitialized" do
43
+ before do
44
+ @ctx[:j1121].tap{|j| j.phase_key = :initialized}
45
+ [:e10].each{|name| @ctx[name].phase_key = :active}
46
+ @root.save!
47
+ end
48
+
49
+ it "j1120をstopすると自身をdyingにして、エッジをcloseして、j1121については何もしません" do
50
+ tengine.should_not_fire
51
+ tengine.receive(:"stop.jobnet.job.tengine",
52
+ :source_name => @ctx[:j1120].name_as_resource,
53
+ :properties => @base_props)
54
+ @root.reload
55
+ @root.phase_key.should == :running
56
+ @ctx.vertex(:j1100).tap{|j| j.phase_key.should == :running}
57
+ @ctx.vertex(:j1110).tap{|j| j.phase_key.should == :success}
58
+ @ctx.vertex(:j1120).tap{|j| j.phase_key.should == :dying}
59
+ @ctx.vertex(:j1121).tap{|j| j.phase_key.should == :initialized}
60
+ [:e1, :e5, :e6].each{|name| @ctx.edge(name).phase_key.should == :transmitted }
61
+ (2..4).each{|idx| [:"e#{idx}", @ctx.edge(:"e#{idx}").phase_key].should == [:"e#{idx}", :active] }
62
+ (7..9).each{|idx| [:"e#{idx}", @ctx.edge(:"e#{idx}").phase_key].should == [:"e#{idx}", :active] }
63
+ (10..11).each{|idx| [:"e#{idx}", @ctx.edge(:"e#{idx}").phase_key].should == [:"e#{idx}", :closing] }
64
+ (12..15).each{|idx| [:"e#{idx}", @ctx.edge(:"e#{idx}").phase_key].should == [:"e#{idx}", :active] }
65
+ end
66
+ end
67
+
68
+ [
69
+ [:ready , :transmitting, :closing],
70
+ [:starting, :transmitted , :transmitted],
71
+ [:running , :transmitted , :transmitted],
72
+ ].each do |(j1121_phase_key, e10_phase_key, e10_new_phase_key)|
73
+
74
+ context "j1121が#{j1121_phase_key}" do
75
+ before do
76
+ @ctx[:j1121].tap{|j| j.phase_key = j1121_phase_key}
77
+ [:e10].each{|name| @ctx[name].phase_key = e10_phase_key}
78
+ @root.save!
79
+ end
80
+
81
+ [nil, 'user_stop', 'timeout'].each do |stop_reason|
82
+ context "stop_reason: #{stop_reason.inspect}" do
83
+ it "j1120をstopすると自身をdyingにして、エッジをcloseして、j1121についてはstop.job.job.tengineを発火します" do
84
+ tengine.should_fire(:"stop.job.job.tengine",
85
+ :source_name => @ctx[:j1121].name_as_resource,
86
+ :properties => @base_props.merge({
87
+ :stop_reason => stop_reason,
88
+ :target_job_id => @ctx[:j1121].id.to_s,
89
+ :target_job_name_path => @ctx[:j1121].name_path,
90
+ }))
91
+ tengine.receive(:"stop.jobnet.job.tengine",
92
+ :source_name => @ctx[:j1120].name_as_resource,
93
+ :properties => @base_props.merge({
94
+ :target_jobnet_id => @ctx[:j1120].id.to_s,
95
+ :target_jobnet_name_path => @ctx[:j1120].name_path,
96
+ :stop_reason=>stop_reason,
97
+ }))
98
+ @root.reload
99
+ @root.phase_key.should == :running
100
+ @ctx.vertex(:j1100).tap{|j| j.phase_key.should == :running}
101
+ @ctx.vertex(:j1110).tap{|j| j.phase_key.should == :success}
102
+ @ctx.vertex(:j1120).tap{|j| j.phase_key.should == :dying}
103
+ @ctx.vertex(:j1121).tap{|j| j.phase_key.should == j1121_phase_key}
104
+ [:e1, :e5, :e6].each{|name| @ctx.edge(name).phase_key.should == :transmitted }
105
+ [:e10].each{|name| @ctx.edge(name).phase_key.should == e10_new_phase_key }
106
+ [:e11].each{|name| @ctx.edge(name).phase_key.should == :closing }
107
+ (2..4).each{|idx| [:"e#{idx}", @ctx.edge(:"e#{idx}").phase_key].should == [:"e#{idx}", :active] }
108
+ (7..9).each{|idx| [:"e#{idx}", @ctx.edge(:"e#{idx}").phase_key].should == [:"e#{idx}", :active] }
109
+ (12..15).each{|idx| [:"e#{idx}", @ctx.edge(:"e#{idx}").phase_key].should == [:"e#{idx}", :active] }
110
+ end
111
+ end
112
+ end
113
+
114
+ end
115
+ end
116
+
117
+ end
118
+ end
119
+
120
+ end
121
+
122
+
123
+ # in [jn0004]
124
+ # |--e3-->(j2)--e5-->|
125
+ # (S1)--e1-->(j1)--e2-->[F1] [J1]--e7-->(j4)--e8-->(E1)
126
+ # |--e4-->(j3)--e6-->|
127
+ #
128
+ # in [jn0004/finally]
129
+ # (S2) --e9-->(jn0004_f)-e10-->(E2)
130
+ #
131
+ context "jn0004" do
132
+ before do
133
+ Tengine::Job::Vertex.delete_all
134
+ builder = Rjn0004ParallelJobnetWithFinally.new
135
+ @root = builder.create_actual
136
+ @ctx = builder.context
137
+ @execution = Tengine::Job::Execution.create!({
138
+ :root_jobnet_id => @root.id,
139
+ })
140
+ end
141
+
142
+ context "ジョブネットが強制停止された場合" do
143
+ before do
144
+ @ctx[:root].tap{|j| j.phase_key = :dying}
145
+ @ctx[:j1].tap{|j| j.phase_key = :error}
146
+ [:e1, ].each{|name| @ctx[name].phase_key = :transmitted}
147
+ @base_props = {
148
+ :execution_id => @execution.id.to_s,
149
+ :root_jobnet_id => @root.id.to_s,
150
+ :root_jobnet_name_path => @root.name_path.to_s,
151
+ :target_jobnet_id => @root.id.to_s,
152
+ :target_jobnet_name_path => @root.name_path,
153
+ }
154
+ @root.save!
155
+ end
156
+
157
+ it "finallyの親のジョブネットは強制停止中であるため、finallyは動かない" do
158
+ tengine.should_fire(:"error.jobnet.job.tengine",
159
+ :source_name => @ctx[:root].name_as_resource,
160
+ :properties => @base_props)
161
+ tengine.receive(:"error.job.job.tengine",
162
+ :source_name => @ctx[:j1].name_as_resource,
163
+ :properties => @base_props.merge({
164
+ :target_job_id => @ctx[:j1].id.to_s,
165
+ :target_job_name_path => @ctx[:j1].name_path,
166
+ }))
167
+ end
168
+ end
169
+
170
+ context "ジョブネットではなくジョブj1が強制停止された場合" do
171
+ before do
172
+ @ctx[:root].tap{|j| j.phase_key = :running} # ジョブネットは強制停止されていません
173
+ @ctx[:j1].tap{|j| j.phase_key = :error}
174
+ [:e1, ].each{|name| @ctx[name].phase_key = :transmitted}
175
+ @base_props = {
176
+ :execution_id => @execution.id.to_s,
177
+ :root_jobnet_id => @root.id.to_s,
178
+ :root_jobnet_name_path => @root.name_path.to_s,
179
+ :target_jobnet_id => @root.id.to_s,
180
+ :target_jobnet_name_path => @root.name_path,
181
+ }
182
+ end
183
+
184
+ it "finallyの親のジョブネットは実行中であるため、finallyは実行される" do
185
+ @root.save!
186
+ tengine.should_fire(:"start.jobnet.job.tengine",
187
+ :source_name => @root.finally_vertex.name_as_resource,
188
+ :properties => @base_props.merge({
189
+ :target_jobnet_id => @root.finally_vertex.id.to_s,
190
+ :target_jobnet_name_path => @root.finally_vertex.name_path,
191
+ }))
192
+ tengine.receive(:"error.job.job.tengine",
193
+ :source_name => @ctx[:j1].name_as_resource,
194
+ :properties => @base_props.merge({
195
+ :target_job_id => @ctx[:j1].id.to_s,
196
+ :target_job_name_path => @ctx[:j1].name_path,
197
+ }))
198
+ end
199
+ end
200
+ end
201
+
202
+ end
@@ -0,0 +1,446 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+ require 'tengine/rspec'
4
+
5
+ describe 'job_control_driver' do
6
+ include Tengine::RSpec::Extension
7
+
8
+ target_dsl File.expand_path("../../../../lib/tengine/job/drivers/jobnet_control_driver.rb", File.dirname(__FILE__))
9
+ driver :jobnet_control_driver
10
+
11
+ before do
12
+ @now = Time.now
13
+ Time.stub!(:now).and_return(@now)
14
+ end
15
+
16
+ # in [rjn0001]
17
+ # (S1) --e1-->(j11)--e2-->(j12)--e3-->(E1)
18
+ context "rjn0001" do
19
+ before do
20
+ Tengine::Job::Vertex.delete_all
21
+ builder = Rjn0001SimpleJobnetBuilder.new
22
+ @root = builder.create_actual
23
+ @ctx = builder.context
24
+ @execution = Tengine::Job::Execution.create!({
25
+ :root_jobnet_id => @root.id,
26
+ })
27
+ @base_props = {
28
+ :execution_id => @execution.id.to_s,
29
+ :root_jobnet_id => @root.id.to_s,
30
+ :root_jobnet_name_path => @root.name_path,
31
+ :target_jobnet_id => @root.id.to_s,
32
+ :target_jobnet_name_path => @root.name_path,
33
+ }
34
+ end
35
+
36
+ it "ジョブネット起動イベントを受信したら" do
37
+ @execution.phase_key = :starting
38
+ @execution.save!
39
+ @root.phase_key = :ready
40
+ @root.save!
41
+ tengine.should_fire(:"start.job.job.tengine",
42
+ :source_name => @ctx[:j11].name_as_resource,
43
+ :properties => {
44
+ :target_job_id => @ctx[:j11].id.to_s,
45
+ :target_job_name_path => @ctx[:j11].name_path,
46
+ }.update(@base_props))
47
+ tengine.receive("start.jobnet.job.tengine", :properties => @base_props)
48
+ @execution.reload
49
+ @execution.phase_key.should == :running
50
+ @root.reload
51
+ @root.phase_key.should == :starting
52
+ @root.started_at.utc.iso8601.should == @now.utc.iso8601
53
+ @ctx.edge(:e1).phase_key.should == :transmitting
54
+ @ctx.vertex(:j11).phase_key.should == :ready
55
+ end
56
+
57
+
58
+ context 'j11を実行' do
59
+ it "成功した場合" do
60
+ @root.phase_key = :running
61
+ @ctx[:e1].phase_key = :transmitted
62
+ @ctx[:j11].phase_key = :success
63
+ @root.save!
64
+ tengine.should_fire(:"start.job.job.tengine",
65
+ :source_name => @ctx[:j12].name_as_resource,
66
+ :properties => {
67
+ :target_job_id => @ctx[:j12].id.to_s,
68
+ :target_job_name_path => @ctx[:j12].name_path,
69
+ }.update(@base_props))
70
+ tengine.receive("success.job.job.tengine",
71
+ :source_name => @ctx[:j11].name_as_resource,
72
+ :properties => {
73
+ :target_job_id => @ctx[:j11].id.to_s,
74
+ :target_job_name_path => @ctx[:j11].name_path,
75
+ }.update(@base_props))
76
+ @root.reload
77
+ @root.phase_key.should == :running
78
+ @ctx.vertex(:j12).phase_key.should == :ready
79
+ @ctx.edge(:e2).phase_key.should == :transmitting
80
+ @ctx.edge(:e3).phase_key.should == :active
81
+ end
82
+
83
+ it "ルートジョブネットの成功を受けてそのexecutionが成功する" do
84
+ @execution.phase_key = :running
85
+ @execution.save!
86
+ @root.phase_key = :success
87
+ @ctx[:e1].phase_key = :transmitted
88
+ @ctx[:e2].phase_key = :transmitted
89
+ @ctx[:e3].phase_key = :transmitted
90
+ @ctx[:j11].phase_key = :success
91
+ @ctx[:j12].phase_key = :success
92
+ @root.save!
93
+ tengine.should_fire(:"success.execution.job.tengine",
94
+ :source_name => @execution.name_as_resource,
95
+ :properties => @base_props)
96
+ tengine.receive("success.jobnet.job.tengine", :properties => @base_props)
97
+ @execution.reload
98
+ @execution.phase_key.should == :success
99
+ end
100
+
101
+
102
+ it "失敗した場合" do
103
+ @root.phase_key = :running
104
+ @ctx[:e1].phase_key = :transmitted
105
+ @ctx[:j11].phase_key = :error
106
+ @root.save!
107
+ tengine.should_fire(:"error.jobnet.job.tengine",
108
+ :source_name => @root.name_as_resource,
109
+ :properties => @base_props)
110
+ tengine.receive("error.job.job.tengine", :properties => {
111
+ :target_job_id => @ctx[:j11].id.to_s
112
+ }.update(@base_props))
113
+ @root.reload
114
+ @ctx.vertex(:j11).phase_key.should == :error
115
+ @ctx.vertex(:j12).phase_key.should == :initialized
116
+ @ctx.edge(:e2).phase_key.should == :closed
117
+ @ctx.edge(:e3).phase_key.should == :closed
118
+ @root.phase_key.should == :error
119
+ @root.finished_at.utc.iso8601.should == @now.utc.iso8601
120
+ end
121
+
122
+ it "ルートジョブネットの失敗を受けてそのexecutionが失敗する" do
123
+ @execution.phase_key = :running
124
+ @execution.save!
125
+ @root.phase_key = :error
126
+ @ctx[:e1].phase_key = :transmitted
127
+ @ctx[:e2].phase_key = :closed
128
+ @ctx[:e3].phase_key = :closed
129
+ @ctx[:j11].phase_key = :error
130
+ @ctx[:j12].phase_key = :initialized
131
+ @root.save!
132
+ tengine.should_fire(:"error.execution.job.tengine",
133
+ :source_name => @execution.name_as_resource,
134
+ :properties => @base_props)
135
+ tengine.receive("error.jobnet.job.tengine", :properties => @base_props)
136
+ @execution.reload
137
+ @execution.phase_key.should == :error
138
+ end
139
+
140
+ end
141
+
142
+ context 'j12を実行' do
143
+ it "成功した場合" do
144
+ @root.phase_key = :running
145
+ @ctx[:e1].phase_key = :transmitted
146
+ @ctx[:e2].phase_key = :transmitted
147
+ @ctx[:j11].phase_key = :success
148
+ @ctx[:j12].phase_key = :success
149
+ @root.save!
150
+ tengine.should_fire(:"success.jobnet.job.tengine",
151
+ :source_name => @root.name_as_resource,
152
+ :properties => @base_props)
153
+ tengine.receive("success.job.job.tengine", :properties => {
154
+ :target_job_id => @ctx[:j12].id.to_s
155
+ }.update(@base_props))
156
+ @root.reload
157
+ @ctx.edge(:e3).phase_key.should == :transmitted
158
+ @root.phase_key.should == :success
159
+ @root.finished_at.utc.iso8601.should == @now.utc.iso8601
160
+ end
161
+
162
+ it "失敗した場合" do
163
+ @root.phase_key = :running
164
+ @ctx[:e1].phase_key = :transmitted
165
+ @ctx[:e2].phase_key = :transmitted
166
+ @ctx[:j11].phase_key = :success
167
+ @ctx[:j12].phase_key = :error
168
+ @root.save!
169
+ tengine.should_fire(:"error.jobnet.job.tengine",
170
+ :source_name => @root.name_as_resource,
171
+ :properties => @base_props)
172
+ tengine.receive("error.job.job.tengine", :properties => {
173
+ :target_job_id => @ctx[:j12].id.to_s
174
+ }.update(@base_props))
175
+ @root.reload
176
+ @ctx.edge(:e3).phase_key.should == :closed
177
+ @root.phase_key.should == :error
178
+ @root.finished_at.utc.iso8601.should == @now.utc.iso8601
179
+ end
180
+ end
181
+
182
+ end
183
+
184
+ # in [rjn0002]
185
+ # |--e2-->(j11)--e4-->|
186
+ # (S1)--e1-->[F1] [J1]--e6-->(E1)
187
+ # |--e3-->(j12)--e5-->|
188
+ context "rjn0002" do
189
+ before do
190
+ Tengine::Job::Vertex.delete_all
191
+ builder = Rjn0002SimpleParallelJobnetBuilder.new
192
+ @root = builder.create_actual
193
+ @ctx = builder.context
194
+ @execution = Tengine::Job::Execution.create!({
195
+ :root_jobnet_id => @root.id,
196
+ })
197
+ @base_props = {
198
+ :execution_id => @execution.id.to_s,
199
+ :root_jobnet_id => @root.id.to_s,
200
+ :root_jobnet_name_path => @root.name_path,
201
+ :target_jobnet_id => @root.id.to_s,
202
+ :target_jobnet_name_path => @root.name_path,
203
+ }
204
+ end
205
+
206
+ it "最初のリクエスト" do
207
+ [:e1, :e2, :e3, :e4, :e5, :e6].each{|name| @ctx[name].phase_key = :active}
208
+ @root.phase_key = :ready
209
+ @root.save!
210
+ tengine.should_fire(:"start.job.job.tengine",
211
+ :source_name => @ctx.vertex(:j11).name_as_resource,
212
+ :properties => {
213
+ :target_job_id => @ctx[:j11].id.to_s,
214
+ :target_job_name_path => @ctx[:j11].name_path,
215
+ }.update(@base_props))
216
+ tengine.should_fire(:"start.job.job.tengine",
217
+ :source_name => @ctx.vertex(:j12).name_as_resource,
218
+ :properties => {
219
+ :target_job_id => @ctx[:j12].id.to_s,
220
+ :target_job_name_path => @ctx[:j12].name_path,
221
+ }.update(@base_props))
222
+ tengine.receive("start.jobnet.job.tengine", :properties => @base_props)
223
+ @root.reload
224
+ @root.phase_key.should == :starting
225
+ @root.started_at.utc.iso8601.should == @now.utc.iso8601
226
+ @ctx.vertex(:j11).phase_key.should == :ready
227
+ @ctx.vertex(:j12).phase_key.should == :ready
228
+ @ctx.edge(:e1).phase_key.should == :transmitted
229
+ @ctx.edge(:e2).phase_key.should == :transmitting
230
+ @ctx.edge(:e3).phase_key.should == :transmitting
231
+ @ctx.edge(:e4).phase_key.should == :active
232
+ @ctx.edge(:e5).phase_key.should == :active
233
+ @ctx.edge(:e6).phase_key.should == :active
234
+ end
235
+
236
+ context 'j11を実行' do
237
+ before do
238
+ @root.phase_key = :running
239
+ # j12は実行中
240
+ @ctx[:e1].phase_key = :transmitted
241
+ @ctx[:e2].phase_key = :transmitted
242
+ @ctx[:e3].phase_key = :transmitted
243
+ @ctx[:j11].phase_key = :running
244
+ @ctx[:j12].phase_key = :running
245
+ @root.save!
246
+ end
247
+
248
+ it "成功した場合" do
249
+ @ctx[:j11].phase_key = :success
250
+ @root.save!
251
+ tengine.should_not_fire
252
+ tengine.receive("success.job.job.tengine", :properties => {
253
+ :target_job_id => @ctx[:j11].id.to_s,
254
+ :target_job_name_path => @ctx[:j11].name_path,
255
+ }.update(@base_props))
256
+ @root.reload
257
+ @ctx.vertex(:j12).phase_key.should == :running
258
+ @ctx.edge(:e4).phase_key.should == :transmitted
259
+ @ctx.edge(:e5).phase_key.should == :active
260
+ @ctx.edge(:e6).phase_key.should == :active
261
+ end
262
+
263
+ it "失敗した場合" do
264
+ @ctx[:j11].phase_key = :error
265
+ @root.save!
266
+ tengine.should_not_fire
267
+ tengine.receive("error.job.job.tengine", :properties => {
268
+ :target_job_id => @ctx[:j11].id.to_s,
269
+ :target_job_name_path => @ctx[:j11].name_path,
270
+ }.update(@base_props))
271
+ @root.reload
272
+ @ctx.vertex(:j12).phase_key.should == :running
273
+ @ctx.edge(:e4).phase_key.should == :closed
274
+ @ctx.edge(:e5).phase_key.should == :active
275
+ @ctx.edge(:e6).phase_key.should == :closing
276
+ end
277
+ end
278
+
279
+ context 'j12を実行' do
280
+ context "j11は成功した場合" do
281
+ before do
282
+ @root.phase_key = :running
283
+ @ctx[:e1].phase_key = :transmitted
284
+ @ctx[:e2].phase_key = :transmitted
285
+ @ctx[:e3].phase_key = :transmitted
286
+ @ctx[:e4].phase_key = :transmitted
287
+ @ctx[:j11].phase_key = :success
288
+ @ctx[:j12].phase_key = :running
289
+ @root.save!
290
+ end
291
+
292
+ it "成功した場合" do
293
+ @ctx[:j12].phase_key = :success
294
+ @root.save!
295
+ tengine.should_fire(:"success.jobnet.job.tengine",
296
+ :source_name => @root.name_as_resource,
297
+ :properties => @base_props)
298
+ tengine.receive("success.job.job.tengine", :properties => {
299
+ :target_job_id => @ctx[:j12].id.to_s,
300
+ }.update(@base_props))
301
+ @root.reload
302
+ @root.phase_key.should == :success
303
+ @root.finished_at.utc.iso8601.should == @now.utc.iso8601
304
+ @ctx.edge(:e5).phase_key.should == :transmitted
305
+ @ctx.edge(:e6).phase_key.should == :transmitted
306
+ end
307
+
308
+ it "失敗した場合" do
309
+ @ctx[:j12].phase_key = :error
310
+ @root.save!
311
+ tengine.should_fire(:"error.jobnet.job.tengine",
312
+ :source_name => @root.name_as_resource,
313
+ :properties => @base_props)
314
+ tengine.receive("error.job.job.tengine", :properties => {
315
+ :target_job_id => @ctx[:j12].id.to_s
316
+ }.update(@base_props))
317
+ @root.reload
318
+ @root.phase_key.should == :error
319
+ @root.finished_at.utc.iso8601.should == @now.utc.iso8601
320
+ @ctx.edge(:e5).phase_key.should == :closed
321
+ @ctx.edge(:e6).phase_key.should == :closed
322
+ end
323
+ end
324
+
325
+ context "j11は失敗した場合" do
326
+ before do
327
+ @root.phase_key = :running
328
+ @ctx[:e1].phase_key = :transmitted
329
+ @ctx[:e2].phase_key = :transmitted
330
+ @ctx[:e3].phase_key = :transmitted
331
+ @ctx[:e4].phase_key = :closed
332
+ @ctx[:e5].phase_key = :active
333
+ @ctx[:e6].phase_key = :closing
334
+ @ctx[:j11].phase_key = :error
335
+ @ctx[:j12].phase_key = :running
336
+ @root.save!
337
+ end
338
+
339
+ it "成功した場合" do
340
+ @ctx[:j12].phase_key = :success
341
+ @root.save!
342
+ tengine.should_fire(:"error.jobnet.job.tengine",
343
+ :source_name => @root.name_as_resource,
344
+ :properties => @base_props)
345
+ tengine.receive("success.job.job.tengine", :properties => {
346
+ :target_job_id => @ctx[:j12].id.to_s,
347
+ }.update(@base_props))
348
+ @root.reload
349
+ @root.phase_key.should == :error
350
+ @root.finished_at.utc.iso8601.should == @now.utc.iso8601
351
+ @ctx.edge(:e5).phase_key.should == :transmitted
352
+ @ctx.edge(:e6).phase_key.should == :closed
353
+ end
354
+
355
+
356
+ it "失敗した場合" do
357
+ @ctx[:j12].phase_key = :error
358
+ @root.save!
359
+ tengine.should_fire(:"error.jobnet.job.tengine",
360
+ :source_name => @root.name_as_resource,
361
+ :properties => @base_props)
362
+ tengine.receive("error.job.job.tengine", :properties => {
363
+ :target_job_id => @ctx[:j12].id.to_s,
364
+ :target_job_name_path => @ctx[:j12].name_path,
365
+ }.update(@base_props))
366
+ @root.reload
367
+ @root.phase_key.should == :error
368
+ @root.finished_at.utc.iso8601.should == @now.utc.iso8601
369
+ @ctx.edge(:e5).phase_key.should == :closed
370
+ @ctx.edge(:e6).phase_key.should == :closed
371
+ end
372
+ end
373
+ end
374
+
375
+ end
376
+
377
+ # in [rjn0010]
378
+ # |-----e2----->(j11)-----e4----->|
379
+ # [S1]--e1-->[F1] [J1]--e7-->[E1]
380
+ # |--e3-->(j12)--e5-->(j13)--e6-->|
381
+ context "rjn0010" do
382
+ before do
383
+ Tengine::Job::Vertex.delete_all
384
+ builder = Rjn00102jobsAnd1jobParallelJobnetBuilder.new
385
+ @root = builder.create_actual
386
+ @ctx = builder.context
387
+ @execution = Tengine::Job::Execution.create!({
388
+ :root_jobnet_id => @root.id,
389
+ })
390
+ @base_props = {
391
+ :execution_id => @execution.id.to_s,
392
+ :root_jobnet_id => @root.id.to_s,
393
+ :target_jobnet_id => @root.id.to_s,
394
+ }
395
+ end
396
+
397
+ # j11, j12の実行は Rjn0002SimpleParallelJobnetBuilder と同じなので省略。
398
+
399
+ # j11が失敗した際に、タイミングが悪くj12からj13へ処理が遷移する瞬間で、
400
+ # j10にはactiveなvertexがない状態になった場合でも、j13が実行されてから
401
+ # j10のfinished.jobnet.job.tengineイベントが発火されなければならない。
402
+
403
+ # 動作としては j11が失敗すると、j11からE1までの間のe4とe7をclosedにする。
404
+ # その後j12が終了すると、e5はclosedされていないので、transmitされてj13が動く。
405
+ # その後j13が実行された後、e6をtransmitした際に、j10の全てのedgeがactiveで
406
+ # なくなるので、j10は終了したと見なされる。
407
+
408
+ context 'j11が失敗' do
409
+ context "j12が同時に成功" do
410
+ before do
411
+ @root.phase_key = :running
412
+ @ctx[:e1].phase_key = :transmitted
413
+ @ctx[:e2].phase_key = :transmitted
414
+ @ctx[:e3].phase_key = :transmitted
415
+ @ctx[:j11].phase_key = :running
416
+ @ctx[:j12].phase_key = :running
417
+ @ctx[:j13].phase_key = :ready
418
+ @root.save!
419
+ end
420
+
421
+ it do
422
+ # j12が成功したという、finished.job.job.tengineイベントが投げられて、j13のstart.job.job.tengineが受信されるまでの間に、
423
+ @ctx[:j12].phase_key = :success
424
+ @ctx[:e5].phase_key = :active
425
+ # j11が失敗したという finished.job.job.tengineイベントが受信された場合
426
+ @ctx[:j11].phase_key = :error
427
+ @root.save!
428
+ tengine.should_not_fire # j13が動いていないので、e5,e6はactiveなので、ジョブネットは終了しません。
429
+ tengine.receive("error.job.job.tengine", :properties => {
430
+ :target_job_id => @ctx[:j11].id.to_s,
431
+ }.update(@base_props))
432
+ @root.reload
433
+ @root.phase_key.should == :running
434
+ @root.finished_at.should == nil
435
+ @ctx.edge(:e4).phase_key.should == :closed
436
+ @ctx.edge(:e5).phase_key.should == :active
437
+ @ctx.edge(:e6).phase_key.should == :active
438
+ @ctx.edge(:e7).phase_key.should == :closing
439
+ end
440
+ end
441
+
442
+ end
443
+
444
+ end
445
+
446
+ end