dynflow 0.8.15 → 0.8.16
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 +4 -4
- data/Gemfile +5 -1
- data/doc/pages/source/documentation/index.md +7 -5
- data/lib/dynflow/execution_plan.rb +8 -2
- data/lib/dynflow/execution_plan/steps/abstract.rb +1 -1
- data/lib/dynflow/persistence.rb +6 -0
- data/lib/dynflow/persistence_adapters/sequel.rb +15 -3
- data/lib/dynflow/version.rb +1 -1
- data/lib/dynflow/world.rb +4 -1
- data/test/abnormal_states_recovery_test.rb +3 -0
- data/web/views/layout.erb +5 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6082a4e18537f19b13eaf0409be81baaf334a5c
|
4
|
+
data.tar.gz: 5c9d56842579de336c97b7f00d4284ef254ba196
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d24e6111ffac1b44316a31784afbe1ace05fd130e9c087bff718adfb33335fe2a7c747f176557b15999fd0b7900af1367128606452a7ce94c345894f5707f02
|
7
|
+
data.tar.gz: d7d3655784db8d993018d5c5e00c3dbebaf4679ae2bacf971eb129ea3e306854b97a803fa6098694ad5d79102aea2f70b456e481ec1af4a90469da71efe0f0a4
|
data/Gemfile
CHANGED
@@ -143,8 +143,8 @@ end
|
|
143
143
|
In example above, it seems that `plan_self` is just shortcut to
|
144
144
|
`plan_action MyActions::File::Destroy, filename` but it's not entirely true.
|
145
145
|
Note that `plan_action` always triggers `plan` of a given action while `plan_self`
|
146
|
-
plans only the `run` of Action, so by using `plan_action`
|
147
|
-
endless loop.
|
146
|
+
plans only the `run` and `finalize` of Action, so by using `plan_action`
|
147
|
+
we'd end up in endless loop.
|
148
148
|
|
149
149
|
Also note, that run method does not take any input. In fact, it can use
|
150
150
|
`input` method that refers to arguments, that were used in `plan_self`.
|
@@ -154,8 +154,9 @@ After that some finalizing steps can be taken. Actions can use outputs of other
|
|
154
154
|
as parts of their inputs establishing dependency. Action's state is serialized between each phase
|
155
155
|
and survives machine/executor restarts.
|
156
156
|
|
157
|
-
As lightly touched in the previous
|
158
|
-
Plan phase starts by triggering an action.
|
157
|
+
As lightly touched in the previous paragraphs there are 3 phases: `plan`, `run` and `finalize`.
|
158
|
+
Plan phase starts by triggering an action. `run` and `finalize` are only ran if you use
|
159
|
+
`plan_self` in `plan` phase.
|
159
160
|
|
160
161
|
#### Input and Output
|
161
162
|
|
@@ -315,7 +316,8 @@ an_action.plan(*args) # an_action is AnAction
|
|
315
316
|
```
|
316
317
|
|
317
318
|
`plan` method is inherited from Dynflow::Action and by default it plans itself if
|
318
|
-
`run` method is present using first argument as input.
|
319
|
+
`run` method is present using first argument as input. It also calls `finalize`
|
320
|
+
method if it is present.
|
319
321
|
|
320
322
|
```ruby
|
321
323
|
class AnAction < Dynflow::Action
|
@@ -409,9 +409,15 @@ module Dynflow
|
|
409
409
|
end
|
410
410
|
|
411
411
|
def self.steps_from_hash(step_ids, execution_plan_id, world)
|
412
|
+
steps = world.persistence.load_steps(execution_plan_id, world)
|
413
|
+
ids_to_steps = steps.inject({}) do |hash, step|
|
414
|
+
hash[step.id.to_i] = step
|
415
|
+
hash
|
416
|
+
end
|
417
|
+
# to make sure to we preserve the order of the steps
|
412
418
|
step_ids.inject({}) do |hash, step_id|
|
413
|
-
|
414
|
-
hash
|
419
|
+
hash[step_id.to_i] = ids_to_steps[step_id.to_i]
|
420
|
+
hash
|
415
421
|
end
|
416
422
|
end
|
417
423
|
|
@@ -113,7 +113,7 @@ module Dynflow
|
|
113
113
|
# @return [Action] in presentation mode, intended for retrieving: progress information,
|
114
114
|
# details, human outputs, etc.
|
115
115
|
def action(execution_plan)
|
116
|
-
world.persistence.load_action_for_presentation(execution_plan, action_id)
|
116
|
+
world.persistence.load_action_for_presentation(execution_plan, action_id, self)
|
117
117
|
end
|
118
118
|
|
119
119
|
def skippable?
|
data/lib/dynflow/persistence.rb
CHANGED
@@ -76,6 +76,12 @@ module Dynflow
|
|
76
76
|
ExecutionPlan::Steps::Abstract.from_hash(step_hash, execution_plan_id, world)
|
77
77
|
end
|
78
78
|
|
79
|
+
def load_steps(execution_plan_id, world)
|
80
|
+
adapter.load_steps(execution_plan_id).map do |step_hash|
|
81
|
+
ExecutionPlan::Steps::Abstract.from_hash(step_hash, execution_plan_id, world)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
79
85
|
def save_step(step)
|
80
86
|
adapter.save_step(step.execution_plan_id, step.id, step.to_hash)
|
81
87
|
end
|
@@ -113,6 +113,10 @@ module Dynflow
|
|
113
113
|
load :step, execution_plan_uuid: execution_plan_id, id: step_id
|
114
114
|
end
|
115
115
|
|
116
|
+
def load_steps(execution_plan_id)
|
117
|
+
load_records :step, execution_plan_uuid: execution_plan_id
|
118
|
+
end
|
119
|
+
|
116
120
|
def save_step(execution_plan_id, step_id, value)
|
117
121
|
save :step, { execution_plan_uuid: execution_plan_id, id: step_id }, value
|
118
122
|
end
|
@@ -139,8 +143,7 @@ module Dynflow
|
|
139
143
|
def pull_envelopes(receiver_id)
|
140
144
|
connector_feature!
|
141
145
|
db.transaction do
|
142
|
-
data_set = table(:envelope).where(receiver_id: receiver_id).
|
143
|
-
|
146
|
+
data_set = table(:envelope).where(receiver_id: receiver_id).all
|
144
147
|
envelopes = data_set.map { |record| load_data(record) }
|
145
148
|
|
146
149
|
table(:envelope).where(id: data_set.map { |d| d[:id] }).delete
|
@@ -246,7 +249,7 @@ module Dynflow
|
|
246
249
|
value
|
247
250
|
end
|
248
251
|
|
249
|
-
def
|
252
|
+
def load_record(what, condition)
|
250
253
|
table = table(what)
|
251
254
|
if (record = with_retry { table.first(Utils.symbolize_keys(condition)) } )
|
252
255
|
load_data(record)
|
@@ -255,6 +258,15 @@ module Dynflow
|
|
255
258
|
end
|
256
259
|
end
|
257
260
|
|
261
|
+
alias_method :load, :load_record
|
262
|
+
|
263
|
+
def load_records(what, condition)
|
264
|
+
table = table(what)
|
265
|
+
records = with_retry { table.filter(Utils.symbolize_keys(condition)).all }
|
266
|
+
records.map { |record| load_data(record) }
|
267
|
+
end
|
268
|
+
|
269
|
+
|
258
270
|
def load_data(record)
|
259
271
|
Utils.indifferent_hash(MultiJson.load(record[:data]))
|
260
272
|
end
|
data/lib/dynflow/version.rb
CHANGED
data/lib/dynflow/world.rb
CHANGED
@@ -13,8 +13,8 @@ module Dynflow
|
|
13
13
|
@id = SecureRandom.uuid
|
14
14
|
@clock = spawn_and_wait(Clock, 'clock')
|
15
15
|
config_for_world = Config::ForWorld.new(config, self)
|
16
|
-
config_for_world.validate
|
17
16
|
@logger_adapter = config_for_world.logger_adapter
|
17
|
+
config_for_world.validate
|
18
18
|
@transaction_adapter = config_for_world.transaction_adapter
|
19
19
|
@persistence = Persistence.new(self, config_for_world.persistence_adapter)
|
20
20
|
@coordinator = Coordinator.new(config_for_world.coordinator_adapter)
|
@@ -360,6 +360,9 @@ module Dynflow
|
|
360
360
|
end
|
361
361
|
end.compact
|
362
362
|
end
|
363
|
+
rescue Coordinator::LockError => e
|
364
|
+
logger.info "auto-executor lock already aquired: #{e.message}"
|
365
|
+
[]
|
363
366
|
end
|
364
367
|
|
365
368
|
def try_spawn_delayed_executor(config_for_world)
|
@@ -104,6 +104,9 @@ module Dynflow
|
|
104
104
|
client_world.auto_execute
|
105
105
|
expected_locks = ["lock auto-execute", "unlock auto-execute"]
|
106
106
|
client_world.coordinator.adapter.lock_log.must_equal(expected_locks)
|
107
|
+
lock = Coordinator::AutoExecuteLock.new(client_world)
|
108
|
+
client_world.coordinator.acquire(lock)
|
109
|
+
client_world.auto_execute.must_equal []
|
107
110
|
end
|
108
111
|
|
109
112
|
it "re-runs the plans that were planned but not executed" do
|
data/web/views/layout.erb
CHANGED
@@ -36,6 +36,11 @@
|
|
36
36
|
<ul class="nav navbar-nav">
|
37
37
|
<li><a href="<%= url '/' %>">Execution plans</a></li>
|
38
38
|
<li><a href="<%= url '/status' %>">Status</a></li>
|
39
|
+
<% if settings.respond_to?(:custom_navigation) && settings.custom_navigation %>
|
40
|
+
<% settings.custom_navigation.each do |description, uri| %>
|
41
|
+
<li><a href="<%= uri %>"><%= description %></a></li>
|
42
|
+
<% end %>
|
43
|
+
<% end %>
|
39
44
|
</ul>
|
40
45
|
<ul class="nav navbar-nav navbar-right">
|
41
46
|
</ul>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.16
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Necas
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-10-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|