-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathloop_list_step.xml
120 lines (104 loc) · 4.74 KB
/
loop_list_step.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<workflow-app name="loop_${loop_name}_(${loop_value})" xmlns="uri:oozie:workflow:0.4">
<start to="check_fork"/>
<decision name="check_fork">
<switch>
<case to="fork">${loop_parallel eq "true"}</case>
<case to="run_serial">${loop_parallel eq "false"}</case>
<default to="error"/>
</switch>
</decision>
<!-- _______________________________________________________________________________ -->
<!-- We implement parallelism through a recursively-built tree of two-pronged forks
where the left prong is the action we want to loop over and the right prong is the
next fork down the tree. -->
<fork name="fork">
<path start="run_parallel"/>
<path start="check_continue_parallel"/>
</fork>
<action name="run_parallel">
<sub-workflow>
<app-path>${loop_action}</app-path>
<propagate-configuration/>
</sub-workflow>
<ok to="join"/>
<error to="error"/>
</action>
<decision name="check_continue_parallel">
<switch>
<case to="continue_parallel">${loop_list ne "--ENDOFLIST--"}</case>
<default to="join"/>
</switch>
</decision>
<action name="continue_parallel">
<sub-workflow>
<app-path>${wf:appPath()}</app-path>
<propagate-configuration/>
<configuration>
<property>
<name>loop_value</name>
<!-- Pull out the first entry of the remaining list and use that as the next
iteration's value -->
<value>${replaceAll(replaceAll(loop_list, "([^,]*),?(.*)", "$1"),
<!-- Oozie has forsaken us and will ignore empty string properties, which is a
pretty big problem for us. Instead, we make a sacrifice to the ugly
hack gods by using a special value in its place. -->
"^$", "--NOVALUE--")}</value>
</property>
<property>
<name>loop_list</name>
<!-- Pull out the non-first entries of the remaining list and use that as the
next iteration's list. In this way the list gets shorter each iteration,
so we can detect the end when the list is empty. -->
<value>${replaceAll(replaceAll(loop_list,"([^,]*),?(.*)", "$2"),
<!-- Use a special string if the list is empty, for the same reason as above -->
"^$", "--ENDOFLIST--")}</value>
</property>
</configuration>
</sub-workflow>
<ok to="join"/>
<error to="error"/>
</action>
<join name="join" to="end"/>
<!-- _______________________________________________________________________________ -->
<!-- We implement serial looping (as like a traditional for loop) by recursively
running the action until we reach the end of the range. -->
<action name="run_serial">
<sub-workflow>
<app-path>${loop_action}</app-path>
<propagate-configuration/>
</sub-workflow>
<ok to="check_continue_serial"/>
<error to="error"/>
</action>
<decision name="check_continue_serial">
<switch>
<case to="continue_serial">${loop_list ne "--ENDOFLIST--"}</case>
<default to="end"/>
</switch>
</decision>
<action name="continue_serial">
<sub-workflow>
<app-path>${wf:appPath()}</app-path>
<propagate-configuration/>
<configuration>
<property>
<name>loop_value</name>
<value>${replaceAll(replaceAll(loop_list, "([^,]*),?(.*)", "$1"),
"^$", "--NOVALUE--")}</value>
</property>
<property>
<name>loop_list</name>
<value>${replaceAll(replaceAll(loop_list,"([^,]*),?(.*)", "$2"),
"^$", "--ENDOFLIST--")}</value>
</property>
</configuration>
</sub-workflow>
<ok to="end"/>
<error to="error"/>
</action>
<!-- _______________________________________________________________________________ -->
<kill name="error">
<message>Oops!</message>
</kill>
<end name="end"/>
</workflow-app>