flow_core 0.0.3 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -0
- data/app/models/flow_core/arc.rb +8 -0
- data/app/models/flow_core/arc_guard.rb +27 -2
- data/app/models/flow_core/branch.rb +48 -0
- data/app/models/flow_core/instance.rb +10 -1
- data/app/models/flow_core/pipeline.rb +58 -0
- data/app/models/flow_core/place.rb +2 -1
- data/app/models/flow_core/step.rb +337 -0
- data/app/models/flow_core/steps/end.rb +32 -0
- data/app/models/flow_core/steps/exclusive_choice.rb +72 -0
- data/app/models/flow_core/steps/parallel_split.rb +42 -0
- data/app/models/flow_core/steps/redirection.rb +39 -0
- data/app/models/flow_core/steps/task.rb +25 -0
- data/app/models/flow_core/task.rb +21 -8
- data/app/models/flow_core/transition.rb +44 -6
- data/app/models/flow_core/transition_callback.rb +19 -2
- data/app/models/flow_core/transition_trigger.rb +19 -2
- data/app/models/flow_core/workflow.rb +11 -4
- data/db/migrate/{20200130200532_create_flow_core_tables.rb → 20200130200532_create_workflow_tables.rb} +32 -29
- data/db/migrate/20200130200533_create_pipeline_tables.rb +64 -0
- data/lib/flow_core.rb +3 -4
- data/lib/flow_core/definition/net.rb +6 -4
- data/lib/flow_core/definition/transition.rb +37 -25
- data/lib/flow_core/engine.rb +5 -0
- data/lib/flow_core/locale/en.yml +9 -4
- data/lib/flow_core/task_executable.rb +4 -0
- data/lib/flow_core/version.rb +1 -1
- data/lib/flow_core/workflow_callbacks.rb +2 -0
- metadata +41 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 743fbfab50000cf6b47c17fe0d90d962faad47fb8eeb0cb44df1e777b56fff0d
|
4
|
+
data.tar.gz: 67d9e0a9f7e7f47d0d958116f4e10d5e885e80ce6b929aa49c49ae844cdc2c18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e7b941b64b50e8d083832c3faf1c22f729473fbf1ac7ed1a0ba67f0831bb9d1a7078f95c008f18ae77138358be376124c47c094fb97d6b41ecf18e99f78a0c68
|
7
|
+
data.tar.gz: 35f944cd17e0b9d07afc0903198ffa9cc43f7d74858fa778112ae4a7c69a0de6a59e21354ab9c4460e2eafb8800f790aa12270dce06ffc85e1bfcafd643e5fca
|
data/README.md
CHANGED
data/app/models/flow_core/arc.rb
CHANGED
@@ -19,6 +19,14 @@ module FlowCore
|
|
19
19
|
uniqueness: {
|
20
20
|
scope: %i[workflow transition direction]
|
21
21
|
}
|
22
|
+
validates :fallback_arc,
|
23
|
+
uniqueness: {
|
24
|
+
scope: %i[workflow transition direction]
|
25
|
+
}, if: :fallback_arc?
|
26
|
+
|
27
|
+
before_validation on: :create do
|
28
|
+
self.workflow ||= place&.workflow || transition&.workflow
|
29
|
+
end
|
22
30
|
|
23
31
|
before_destroy :prevent_destroy
|
24
32
|
after_create :reset_workflow_verification
|
@@ -4,13 +4,38 @@ module FlowCore
|
|
4
4
|
class ArcGuard < FlowCore::ApplicationRecord
|
5
5
|
self.table_name = "flow_core_arc_guards"
|
6
6
|
|
7
|
-
belongs_to :workflow, class_name: "FlowCore::Workflow"
|
8
|
-
belongs_to :arc, class_name: "FlowCore::Arc"
|
7
|
+
belongs_to :workflow, class_name: "FlowCore::Workflow", optional: true
|
8
|
+
belongs_to :arc, class_name: "FlowCore::Arc", optional: true
|
9
9
|
|
10
10
|
has_one :transition, through: :arc, class_name: "FlowCore::Transition"
|
11
11
|
|
12
|
+
belongs_to :pipeline, class_name: "FlowCore::Pipeline", optional: true
|
13
|
+
belongs_to :branch, class_name: "FlowCore::Branch", optional: true
|
14
|
+
|
15
|
+
validates :arc,
|
16
|
+
presence: true,
|
17
|
+
if: ->(r) { r.workflow }
|
18
|
+
validates :branch,
|
19
|
+
presence: true,
|
20
|
+
if: ->(r) { r.pipeline }
|
21
|
+
validates :workflow,
|
22
|
+
presence: true,
|
23
|
+
if: ->(r) { !r.pipeline }
|
24
|
+
validates :pipeline,
|
25
|
+
presence: true,
|
26
|
+
if: ->(r) { !r.workflow }
|
27
|
+
|
12
28
|
before_validation do
|
13
29
|
self.workflow ||= arc&.workflow
|
30
|
+
self.pipeline ||= branch&.pipeline
|
31
|
+
end
|
32
|
+
|
33
|
+
def configurable?
|
34
|
+
false
|
35
|
+
end
|
36
|
+
|
37
|
+
def type_key
|
38
|
+
self.class.to_s.split("::").last.underscore
|
14
39
|
end
|
15
40
|
|
16
41
|
include FlowCore::ArcGuardable
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlowCore
|
4
|
+
class Branch < FlowCore::ApplicationRecord
|
5
|
+
self.table_name = "flow_core_branches"
|
6
|
+
|
7
|
+
belongs_to :pipeline, class_name: "FlowCore::Pipeline"
|
8
|
+
belongs_to :step, class_name: "FlowCore::Step"
|
9
|
+
|
10
|
+
has_many :arc_guards, class_name: "FlowCore::ArcGuard", dependent: :destroy
|
11
|
+
|
12
|
+
has_many :steps, -> { order(position: :asc) },
|
13
|
+
class_name: "FlowCore::Step", inverse_of: :branch,
|
14
|
+
dependent: :destroy
|
15
|
+
|
16
|
+
validates :name,
|
17
|
+
presence: true
|
18
|
+
|
19
|
+
validates :fallback_branch,
|
20
|
+
uniqueness: {
|
21
|
+
scope: %i[step_id]
|
22
|
+
}, if: :fallback_branch?
|
23
|
+
|
24
|
+
before_validation do
|
25
|
+
self.pipeline ||= step.pipeline
|
26
|
+
end
|
27
|
+
|
28
|
+
def user_destroyable?
|
29
|
+
!fallback_branch || (fallback_branch? && !step.fallback_branch_required?)
|
30
|
+
end
|
31
|
+
|
32
|
+
def arc_guard_attachable?
|
33
|
+
!fallback_branch? && step.branch_arc_guard_attachable?
|
34
|
+
end
|
35
|
+
|
36
|
+
def copy_arc_guards_to(arc)
|
37
|
+
return unless arc_guard_attachable?
|
38
|
+
|
39
|
+
arc_guards.find_each do |arc_guard|
|
40
|
+
new_guard = arc_guard.dup
|
41
|
+
new_guard.arc = arc
|
42
|
+
new_guard.pipeline = nil
|
43
|
+
new_guard.branch = nil
|
44
|
+
new_guard.save!
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -27,6 +27,8 @@ module FlowCore
|
|
27
27
|
scope :errored, -> { where.not(errored_at: nil) }
|
28
28
|
scope :suspended, -> { where.not(suspended_at: nil) }
|
29
29
|
|
30
|
+
validate :on_create_validation, on: :create
|
31
|
+
|
30
32
|
after_initialize do
|
31
33
|
self.payload ||= {}
|
32
34
|
end
|
@@ -66,10 +68,11 @@ module FlowCore
|
|
66
68
|
return false unless can_activate?
|
67
69
|
|
68
70
|
with_transaction_returning_status do
|
69
|
-
tokens.create! place: workflow.start_place
|
70
71
|
update! stage: :activated, activated_at: Time.zone.now
|
71
72
|
workflow.on_instance_activate(self)
|
72
73
|
|
74
|
+
tokens.create! place: workflow.start_place
|
75
|
+
|
73
76
|
true
|
74
77
|
end
|
75
78
|
end
|
@@ -117,5 +120,11 @@ module FlowCore
|
|
117
120
|
def terminate!(reason:)
|
118
121
|
terminate(reason: reason) || raise(FlowCore::InvalidTransition, "Can't terminate Instance##{id}")
|
119
122
|
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def on_create_validation
|
127
|
+
workflow.on_instance_create_validation(self)
|
128
|
+
end
|
120
129
|
end
|
121
130
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlowCore
|
4
|
+
class Pipeline < FlowCore::ApplicationRecord
|
5
|
+
self.table_name = "flow_core_pipelines"
|
6
|
+
|
7
|
+
has_many :generated_workflows,
|
8
|
+
class_name: "FlowCore::Workflow", foreign_key: :generated_by_pipeline_id,
|
9
|
+
inverse_of: :generated_by, dependent: :nullify
|
10
|
+
|
11
|
+
has_many :steps, -> { where(branch_id: nil).order(position: :asc) },
|
12
|
+
class_name: "FlowCore::Step", inverse_of: :pipeline,
|
13
|
+
dependent: :destroy
|
14
|
+
|
15
|
+
has_many :branches, class_name: "FlowCore::Branch", dependent: :restrict_with_exception
|
16
|
+
has_many :whole_steps, class_name: "FlowCore::Step", inverse_of: :pipeline, dependent: :restrict_with_exception
|
17
|
+
|
18
|
+
validates :name,
|
19
|
+
presence: true
|
20
|
+
|
21
|
+
def deploy_workflow
|
22
|
+
return if steps.empty?
|
23
|
+
return if whole_steps.exists? verified: false
|
24
|
+
|
25
|
+
workflow = nil
|
26
|
+
transaction do
|
27
|
+
workflow = generated_workflows.new name: name, type: workflow_class.to_s
|
28
|
+
on_build_workflow(workflow)
|
29
|
+
workflow.save!
|
30
|
+
|
31
|
+
end_place = workflow.create_end_place!
|
32
|
+
|
33
|
+
place_or_transition = nil
|
34
|
+
steps.each do |step|
|
35
|
+
place_or_transition = step.deploy_to_workflow!(workflow, place_or_transition)
|
36
|
+
end
|
37
|
+
|
38
|
+
if place_or_transition.is_a? FlowCore::Place
|
39
|
+
place_or_transition.input_arcs.update place: end_place
|
40
|
+
place_or_transition.reload.destroy!
|
41
|
+
else
|
42
|
+
end_place.input_transitions << place_or_transition
|
43
|
+
end
|
44
|
+
end
|
45
|
+
workflow&.verify!
|
46
|
+
|
47
|
+
workflow
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def on_build_workflow(_workflow); end
|
53
|
+
|
54
|
+
def workflow_class
|
55
|
+
FlowCore::Workflow
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -10,10 +10,11 @@ module FlowCore
|
|
10
10
|
|
11
11
|
# NOTE: Place - out -> Transition - in -> Place
|
12
12
|
has_many :input_arcs, -> { where direction: :out },
|
13
|
-
class_name: "FlowCore::Arc", inverse_of: :place, dependent: :
|
13
|
+
class_name: "FlowCore::Arc", inverse_of: :place, dependent: :destroy
|
14
14
|
has_many :output_arcs, -> { where direction: :in },
|
15
15
|
class_name: "FlowCore::Arc", inverse_of: :place, dependent: :delete_all
|
16
16
|
|
17
|
+
has_many :input_transitions, through: :input_arcs, class_name: "FlowCore::Transition", source: :transition
|
17
18
|
has_many :output_transitions, through: :output_arcs, class_name: "FlowCore::Transition", source: :transition
|
18
19
|
|
19
20
|
before_destroy :prevent_destroy
|
@@ -0,0 +1,337 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlowCore
|
4
|
+
class Step < FlowCore::ApplicationRecord
|
5
|
+
self.table_name = "flow_core_steps"
|
6
|
+
|
7
|
+
has_many :generated_transitions,
|
8
|
+
class_name: "FlowCore::Transition", foreign_key: :generated_by_step_id,
|
9
|
+
inverse_of: :generated_by, dependent: :nullify
|
10
|
+
|
11
|
+
belongs_to :pipeline, class_name: "FlowCore::Pipeline"
|
12
|
+
belongs_to :branch, class_name: "FlowCore::Branch", optional: true
|
13
|
+
|
14
|
+
has_many :branches, class_name: "FlowCore::Branch", inverse_of: :step, dependent: :destroy
|
15
|
+
belongs_to :redirect_to_step, class_name: "FlowCore::Step", optional: true
|
16
|
+
has_one :transition_trigger, class_name: "FlowCore::TransitionTrigger", dependent: :destroy
|
17
|
+
has_many :transition_callbacks, class_name: "FlowCore::TransitionCallback", dependent: :destroy
|
18
|
+
|
19
|
+
extend Ancestry::HasAncestry
|
20
|
+
has_ancestry orphan_strategy: :restrict
|
21
|
+
|
22
|
+
extend ActiveRecord::Acts::List::ClassMethods
|
23
|
+
acts_as_list scope: %i[pipeline_id branch_id]
|
24
|
+
|
25
|
+
validates :name,
|
26
|
+
presence: true
|
27
|
+
|
28
|
+
validates :type,
|
29
|
+
presence: true
|
30
|
+
|
31
|
+
validates :redirect_to_step,
|
32
|
+
inclusion: {
|
33
|
+
in: :redirectable_steps
|
34
|
+
},
|
35
|
+
allow_nil: true
|
36
|
+
|
37
|
+
validate do
|
38
|
+
if branch && branch.pipeline_id != pipeline_id
|
39
|
+
errors.add :branch, :invalid
|
40
|
+
end
|
41
|
+
|
42
|
+
if redirect_to_step && redirect_to_step.pipeline_id != pipeline_id
|
43
|
+
errors.add :redirect_to_step, :invalid
|
44
|
+
end
|
45
|
+
|
46
|
+
if redirection_step?
|
47
|
+
if !branch
|
48
|
+
errors.add :type, :invalid
|
49
|
+
elsif branch.fallback_branch?
|
50
|
+
errors.add :type, :invalid
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
before_validation do
|
56
|
+
self.pipeline ||= branch&.pipeline
|
57
|
+
end
|
58
|
+
|
59
|
+
before_save :update_parent
|
60
|
+
before_save :update_verified
|
61
|
+
|
62
|
+
after_create :reorder_by_append_to_on_create
|
63
|
+
after_destroy :recheck_redirection_steps_on_destroy
|
64
|
+
|
65
|
+
attr_accessor :append_to
|
66
|
+
|
67
|
+
def deploy_to_workflow!(_workflow, _input_place_or_transition)
|
68
|
+
raise NotImplementedError
|
69
|
+
end
|
70
|
+
|
71
|
+
def redirection_step?
|
72
|
+
self.class.redirection_step?
|
73
|
+
end
|
74
|
+
|
75
|
+
def multi_branch_step?
|
76
|
+
self.class.multi_branch_step?
|
77
|
+
end
|
78
|
+
|
79
|
+
def barrier_step?
|
80
|
+
self.class.barrier_step?
|
81
|
+
end
|
82
|
+
|
83
|
+
def transition_trigger_attachable?
|
84
|
+
self.class.transition_trigger_attachable?
|
85
|
+
end
|
86
|
+
|
87
|
+
def transition_callback_attachable?
|
88
|
+
self.class.transition_callback_attachable?
|
89
|
+
end
|
90
|
+
|
91
|
+
def branch_arc_guard_attachable?
|
92
|
+
self.class.branch_arc_guard_attachable?
|
93
|
+
end
|
94
|
+
|
95
|
+
def fallback_branch_required?
|
96
|
+
self.class.fallback_branch_required?
|
97
|
+
end
|
98
|
+
|
99
|
+
def transition_trigger_required?
|
100
|
+
self.class.transition_trigger_required?
|
101
|
+
end
|
102
|
+
|
103
|
+
def redirection_configurable?
|
104
|
+
self.class.redirection_configurable?
|
105
|
+
end
|
106
|
+
|
107
|
+
def branch_configurable?
|
108
|
+
self.class.branch_configurable?
|
109
|
+
end
|
110
|
+
|
111
|
+
def redirectable_steps
|
112
|
+
return [] unless redirection_step?
|
113
|
+
|
114
|
+
redirectable_steps = []
|
115
|
+
|
116
|
+
# Barrier step is the stop point, beyond if can't ensure the workflow valid
|
117
|
+
# e.g. consider there's a redirection step in one of branch of a parallel branch step,
|
118
|
+
# the parallel branch step is the barrier step, if redirect beyond the barrier step,
|
119
|
+
# it will multiplex all branches again and again
|
120
|
+
# Barrier step 是保障流程的边界,如果重定向到边界外的节点,就无法保证流程合法,
|
121
|
+
# 一个例子是假设并发分支步骤的某个分支里有一个重定向节点,并发分支步骤就是一个 Barrier Step,
|
122
|
+
# 如果可以重定向到并发分支步骤外,重定向到步骤后会重新执行这个并发分支步骤,导致其他分支的步骤会被无限重复执行
|
123
|
+
ancestors.reverse_each do |step|
|
124
|
+
break if step.barrier_step?
|
125
|
+
|
126
|
+
redirectable_steps << step
|
127
|
+
end
|
128
|
+
|
129
|
+
# return an empty array if there's no safe ancestor,
|
130
|
+
# redirect to steps which in current branch in not safe, because it will infinite loop
|
131
|
+
# 如果一个安全的祖先步骤都没有,就返回空集,跳到当前分支的步骤会导致死循环或者死代码,没有意义
|
132
|
+
return [] if redirectable_steps.empty?
|
133
|
+
|
134
|
+
# if the redirection step is the first step of a branch,
|
135
|
+
# avoiding redirect to parent and ancestors which are first step (of a branch) and without a transition trigger,
|
136
|
+
# because it will lead infinite loop,
|
137
|
+
# 如果重定向步骤是分支的第一步,那么父步骤和其他也是处于(分支)第一步的祖先,也都要避免跳转,因为会导致死循环
|
138
|
+
if position == 1 && redirectable_steps.any?
|
139
|
+
if redirectable_steps.first.multi_branch_step? && !redirectable_steps.first.transition_trigger
|
140
|
+
redirectable_steps.shift
|
141
|
+
end
|
142
|
+
|
143
|
+
while redirectable_steps.any?
|
144
|
+
step = redirectable_steps.first
|
145
|
+
if step.multi_branch_step? && !redirectable_steps.first.transition_trigger
|
146
|
+
redirectable_steps.shift
|
147
|
+
|
148
|
+
if step.position > 1
|
149
|
+
break
|
150
|
+
end
|
151
|
+
else
|
152
|
+
break
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# It's safe to redirect to any top level (or main branch) steps,
|
158
|
+
# just avoiding the redirect step's ancestor, because it may lead infinite loop
|
159
|
+
# 跳到顶层(或者说主干)步骤都是安全的,只是要去掉跳转步骤的祖先,因为会导致死循环
|
160
|
+
if redirectable_steps.reject!(&:root?)
|
161
|
+
redirectable_steps.concat(pipeline.steps)
|
162
|
+
elsif redirectable_steps.empty?
|
163
|
+
redirectable_steps.concat(pipeline.steps - ancestors)
|
164
|
+
end
|
165
|
+
|
166
|
+
# It's also safe to redirect to any of children steps,
|
167
|
+
# just avoid current branch which the redirection step belongs to.
|
168
|
+
# 跳转到任何步骤的分支也都是安全的,就是要避免分支是当前跳转步骤的祖先步骤
|
169
|
+
redirectable_steps.map! do |s|
|
170
|
+
if s.parent_of? self
|
171
|
+
[s].concat s.children.where.not(branch_id: branch_id)
|
172
|
+
else
|
173
|
+
[s].concat s.children
|
174
|
+
end
|
175
|
+
end
|
176
|
+
redirectable_steps.flatten!
|
177
|
+
redirectable_steps.uniq!
|
178
|
+
redirectable_steps.reject!(&:redirection_step?)
|
179
|
+
|
180
|
+
redirectable_steps
|
181
|
+
end
|
182
|
+
|
183
|
+
class << self
|
184
|
+
def multi_branch_step?
|
185
|
+
false
|
186
|
+
end
|
187
|
+
|
188
|
+
def redirection_step?
|
189
|
+
false
|
190
|
+
end
|
191
|
+
|
192
|
+
def barrier_step?
|
193
|
+
false
|
194
|
+
end
|
195
|
+
|
196
|
+
def transition_trigger_attachable?
|
197
|
+
!multi_branch_step? && !redirection_step?
|
198
|
+
end
|
199
|
+
|
200
|
+
def transition_callback_attachable?
|
201
|
+
!multi_branch_step?
|
202
|
+
end
|
203
|
+
|
204
|
+
def branch_arc_guard_attachable?
|
205
|
+
false
|
206
|
+
end
|
207
|
+
|
208
|
+
def redirection_configurable?
|
209
|
+
false
|
210
|
+
end
|
211
|
+
|
212
|
+
def branch_configurable?
|
213
|
+
false
|
214
|
+
end
|
215
|
+
|
216
|
+
def transition_trigger_required?
|
217
|
+
false
|
218
|
+
end
|
219
|
+
|
220
|
+
def fallback_branch_required?
|
221
|
+
false
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
private
|
226
|
+
|
227
|
+
def update_verified
|
228
|
+
self.verified = valid?
|
229
|
+
end
|
230
|
+
|
231
|
+
def find_or_create_input_place(workflow, input_place_or_transition)
|
232
|
+
if input_place_or_transition.is_a? FlowCore::Transition
|
233
|
+
input_place_or_transition.output_places.create! workflow: workflow
|
234
|
+
elsif input_place_or_transition.is_a? FlowCore::Place
|
235
|
+
input_place_or_transition
|
236
|
+
elsif workflow.start_place
|
237
|
+
workflow.start_place
|
238
|
+
else
|
239
|
+
workflow.create_start_place!
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def copy_transition_trigger_to(transition)
|
244
|
+
return unless transition_trigger_attachable?
|
245
|
+
return unless transition_trigger
|
246
|
+
|
247
|
+
trigger = transition_trigger.dup
|
248
|
+
trigger.transition = transition
|
249
|
+
trigger.pipeline = nil
|
250
|
+
trigger.step = nil
|
251
|
+
|
252
|
+
trigger.save!
|
253
|
+
end
|
254
|
+
|
255
|
+
def copy_transition_callbacks_to(transition)
|
256
|
+
return unless transition_callback_attachable?
|
257
|
+
|
258
|
+
transition_callbacks.find_each do |cb|
|
259
|
+
new_cb = cb.dup
|
260
|
+
new_cb.transition = transition
|
261
|
+
new_cb.pipeline = nil
|
262
|
+
new_cb.step = nil
|
263
|
+
new_cb.save!
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def deploy_branches_to(workflow, input_transition, append_to_place_or_transition)
|
268
|
+
return unless multi_branch_step?
|
269
|
+
|
270
|
+
branches.includes(:steps, :arc_guards).find_each do |branch|
|
271
|
+
if branch.steps.empty?
|
272
|
+
if append_to_place_or_transition.is_a?(FlowCore::Place)
|
273
|
+
arc = input_transition.output_arcs.create! place: append_to_place_or_transition, fallback_arc: branch.fallback_branch?
|
274
|
+
else
|
275
|
+
place = workflow.places.create! workflow: workflow
|
276
|
+
arc = append_to_place_or_transition.input_arcs.create! place: place, fallback_arc: branch.fallback_branch?
|
277
|
+
end
|
278
|
+
branch.copy_arc_guards_to arc
|
279
|
+
|
280
|
+
next
|
281
|
+
end
|
282
|
+
|
283
|
+
place = workflow.places.create! workflow: workflow
|
284
|
+
arc = input_transition.output_arcs.create! place: place, fallback_arc: branch.fallback_branch?
|
285
|
+
branch.copy_arc_guards_to arc
|
286
|
+
|
287
|
+
place_or_transition = nil
|
288
|
+
branch.steps.each do |step|
|
289
|
+
place_or_transition = step.deploy_to_workflow!(workflow, place_or_transition || place)
|
290
|
+
end
|
291
|
+
next unless place_or_transition
|
292
|
+
|
293
|
+
if place_or_transition.is_a? FlowCore::Transition
|
294
|
+
if append_to_place_or_transition.is_a?(FlowCore::Place)
|
295
|
+
place_or_transition.output_places << append_to_place_or_transition
|
296
|
+
else
|
297
|
+
place = place_or_transition.output_places.create! workflow: workflow
|
298
|
+
place.output_transitions << append_to_place_or_transition
|
299
|
+
end
|
300
|
+
elsif append_to_place_or_transition.is_a?(FlowCore::Place)
|
301
|
+
place_or_transition.input_arcs.update place: append_to_place_or_transition
|
302
|
+
place_or_transition.reload.destroy!
|
303
|
+
else
|
304
|
+
place_or_transition.output_places << append_to_place_or_transition
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def reorder_by_append_to_on_create
|
310
|
+
return unless append_to
|
311
|
+
|
312
|
+
if append_to.to_s == "start"
|
313
|
+
move_to_top
|
314
|
+
return
|
315
|
+
end
|
316
|
+
|
317
|
+
append_to_step = self.class.find_by id: append_to
|
318
|
+
return unless append_to_step && append_to_step.branch_id == branch_id
|
319
|
+
|
320
|
+
insert_at(append_to_step.position + 1)
|
321
|
+
end
|
322
|
+
|
323
|
+
def recheck_redirection_steps_on_destroy
|
324
|
+
return unless branch
|
325
|
+
|
326
|
+
branch.steps.to_a.select(&:redirection_step?).each do |step|
|
327
|
+
unless step.redirectable_steps.include? step.redirect_to_step
|
328
|
+
step.update! redirect_to_step: nil
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
def update_parent
|
334
|
+
self.parent = branch&.step
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|