dynflow 1.9.3 → 2.0.0
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/.github/workflows/bats.yml +50 -0
- data/.github/workflows/release.yml +1 -1
- data/.github/workflows/ruby.yml +27 -46
- data/.gitignore +2 -0
- data/.rubocop.yml +3 -0
- data/Dockerfile +1 -1
- data/Gemfile +7 -8
- data/README.md +4 -4
- data/doc/pages/source/documentation/index.md +4 -4
- data/dynflow.gemspec +2 -3
- data/examples/example_helper.rb +1 -1
- data/examples/execution_plan_chaining.rb +56 -0
- data/examples/remote_executor.rb +5 -8
- data/lib/dynflow/action/format.rb +4 -33
- data/lib/dynflow/debug/telemetry/persistence.rb +1 -1
- data/lib/dynflow/delayed_executors/abstract_core.rb +1 -1
- data/lib/dynflow/delayed_plan.rb +6 -0
- data/lib/dynflow/director.rb +9 -1
- data/lib/dynflow/executors/sidekiq/core.rb +1 -1
- data/lib/dynflow/executors/sidekiq/redis_locking.rb +10 -3
- data/lib/dynflow/extensions/msgpack.rb +4 -0
- data/lib/dynflow/persistence.rb +14 -2
- data/lib/dynflow/persistence_adapters/abstract.rb +9 -1
- data/lib/dynflow/persistence_adapters/sequel.rb +91 -48
- data/lib/dynflow/persistence_adapters/sequel_migrations/025_create_execution_plan_dependencies.rb +22 -0
- data/lib/dynflow/rails/daemon.rb +16 -7
- data/lib/dynflow/testing.rb +1 -1
- data/lib/dynflow/version.rb +1 -1
- data/lib/dynflow/world.rb +34 -13
- data/lib/dynflow.rb +0 -1
- data/test/action_test.rb +3 -3
- data/test/bats/helpers/common.bash +67 -0
- data/test/bats/helpers/containers.bash +146 -0
- data/test/bats/setup_suite.bash +46 -0
- data/test/bats/sidekiq-orchestrator.bats +178 -0
- data/test/bats/teardown_suite.bash +16 -0
- data/test/concurrency_control_test.rb +0 -1
- data/test/daemon_test.rb +21 -2
- data/test/extensions_test.rb +3 -3
- data/test/future_execution_test.rb +150 -3
- data/test/persistence_test.rb +70 -3
- data/test/support/dummy_example.rb +4 -0
- data/test/test_helper.rb +19 -4
- data/web/views/show.erb +24 -0
- metadata +15 -17
- data/.github/install_dependencies.sh +0 -35
data/test/persistence_test.rb
CHANGED
|
@@ -342,7 +342,7 @@ module Dynflow
|
|
|
342
342
|
end
|
|
343
343
|
end
|
|
344
344
|
|
|
345
|
-
describe '#
|
|
345
|
+
describe '#find_ready_delayed_plans' do
|
|
346
346
|
it 'finds plans with start_before in past' do
|
|
347
347
|
start_time = Time.now.utc
|
|
348
348
|
prepare_and_save_plans
|
|
@@ -352,7 +352,7 @@ module Dynflow
|
|
|
352
352
|
adapter.save_delayed_plan('plan3', :execution_plan_uuid => 'plan3', :frozen => false, :start_at => format_time(start_time + 60))
|
|
353
353
|
adapter.save_delayed_plan('plan4', :execution_plan_uuid => 'plan4', :frozen => false, :start_at => format_time(start_time - 60),
|
|
354
354
|
:start_before => format_time(start_time - 60))
|
|
355
|
-
plans = adapter.
|
|
355
|
+
plans = adapter.find_ready_delayed_plans(start_time)
|
|
356
356
|
_(plans.length).must_equal 3
|
|
357
357
|
_(plans.map { |plan| plan[:execution_plan_uuid] }).must_equal %w(plan2 plan4 plan1)
|
|
358
358
|
end
|
|
@@ -366,10 +366,77 @@ module Dynflow
|
|
|
366
366
|
adapter.save_delayed_plan('plan2', :execution_plan_uuid => 'plan2', :frozen => true, :start_at => format_time(start_time + 60),
|
|
367
367
|
:start_before => format_time(start_time - 60))
|
|
368
368
|
|
|
369
|
-
plans = adapter.
|
|
369
|
+
plans = adapter.find_ready_delayed_plans(start_time)
|
|
370
370
|
_(plans.length).must_equal 1
|
|
371
371
|
_(plans.first[:execution_plan_uuid]).must_equal 'plan1'
|
|
372
372
|
end
|
|
373
|
+
|
|
374
|
+
it 'finds plans with null start_at' do
|
|
375
|
+
start_time = Time.now.utc
|
|
376
|
+
prepare_and_save_plans
|
|
377
|
+
|
|
378
|
+
adapter.save_delayed_plan('plan1', :execution_plan_uuid => 'plan1', :frozen => false)
|
|
379
|
+
|
|
380
|
+
plans = adapter.find_ready_delayed_plans(start_time)
|
|
381
|
+
_(plans.length).must_equal 1
|
|
382
|
+
_(plans.first[:execution_plan_uuid]).must_equal 'plan1'
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
it 'properly stored execution plan dependencies' do
|
|
386
|
+
prepare_and_save_plans
|
|
387
|
+
|
|
388
|
+
adapter.save_delayed_plan('plan1', :execution_plan_uuid => 'plan1', :frozen => false)
|
|
389
|
+
adapter.chain_execution_plan('plan2', 'plan1')
|
|
390
|
+
adapter.chain_execution_plan('plan3', 'plan1')
|
|
391
|
+
dependencies = adapter.find_execution_plan_dependencies('plan1')
|
|
392
|
+
_(dependencies.to_set).must_equal ['plan2', 'plan3'].to_set
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
it 'does not find blocked plans' do
|
|
396
|
+
start_time = Time.now.utc
|
|
397
|
+
prepare_and_save_plans
|
|
398
|
+
|
|
399
|
+
adapter.save_delayed_plan('plan1', :execution_plan_uuid => 'plan1', :frozen => false)
|
|
400
|
+
adapter.chain_execution_plan('plan2', 'plan1')
|
|
401
|
+
adapter.chain_execution_plan('plan3', 'plan1')
|
|
402
|
+
|
|
403
|
+
plans = adapter.find_ready_delayed_plans(start_time)
|
|
404
|
+
_(plans.length).must_equal 0
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
it 'finds plans which are no longer blocked' do
|
|
408
|
+
start_time = Time.now.utc
|
|
409
|
+
prepare_and_save_plans
|
|
410
|
+
|
|
411
|
+
adapter.save_delayed_plan('plan1', :execution_plan_uuid => 'plan1', :frozen => false)
|
|
412
|
+
adapter.chain_execution_plan('plan2', 'plan1')
|
|
413
|
+
|
|
414
|
+
plans = adapter.find_ready_delayed_plans(start_time)
|
|
415
|
+
_(plans.length).must_equal 1
|
|
416
|
+
_(plans.first[:execution_plan_uuid]).must_equal 'plan1'
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
it 'does not find plans which are no longer blocked but are frozen' do
|
|
420
|
+
start_time = Time.now.utc
|
|
421
|
+
prepare_and_save_plans
|
|
422
|
+
|
|
423
|
+
adapter.save_delayed_plan('plan1', :execution_plan_uuid => 'plan1', :frozen => true)
|
|
424
|
+
adapter.chain_execution_plan('plan2', 'plan1')
|
|
425
|
+
|
|
426
|
+
plans = adapter.find_ready_delayed_plans(start_time)
|
|
427
|
+
_(plans.length).must_equal 0
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
it 'does not find plans which are no longer blocked but their start_at is in the future' do
|
|
431
|
+
start_time = Time.now.utc
|
|
432
|
+
prepare_and_save_plans
|
|
433
|
+
|
|
434
|
+
adapter.save_delayed_plan('plan1', :execution_plan_uuid => 'plan1', :frozen => false, :start_at => start_time + 60)
|
|
435
|
+
adapter.chain_execution_plan('plan2', 'plan1') # plan2 is already stopped
|
|
436
|
+
|
|
437
|
+
plans = adapter.find_ready_delayed_plans(start_time)
|
|
438
|
+
_(plans.length).must_equal 0
|
|
439
|
+
end
|
|
373
440
|
end
|
|
374
441
|
|
|
375
442
|
describe '#delete_output_chunks' do
|
data/test/test_helper.rb
CHANGED
|
@@ -20,7 +20,9 @@ require 'support/rescue_example'
|
|
|
20
20
|
require 'support/dummy_example'
|
|
21
21
|
require 'support/test_execution_log'
|
|
22
22
|
|
|
23
|
-
Concurrent.
|
|
23
|
+
Concurrent.global_logger = lambda do |level, progname, message = nil, &block|
|
|
24
|
+
::Dynflow::Testing.logger_adapter.logger.add level, message, progname, &block
|
|
25
|
+
end
|
|
24
26
|
|
|
25
27
|
# To be able to stop a process in some step and perform assertions while paused
|
|
26
28
|
class TestPause
|
|
@@ -109,12 +111,19 @@ module WorldFactory
|
|
|
109
111
|
# This world survives though the whole run of the test suite: careful with it, it can
|
|
110
112
|
# introduce unnecessary test dependencies
|
|
111
113
|
def self.logger_adapter
|
|
112
|
-
|
|
114
|
+
::Dynflow::Testing.logger_adapter
|
|
113
115
|
end
|
|
114
116
|
|
|
115
117
|
def self.persistence_adapter
|
|
116
118
|
@persistence_adapter ||= begin
|
|
117
|
-
db_config = ENV
|
|
119
|
+
db_config = ENV.fetch('DB_CONN_STRING') do
|
|
120
|
+
case ENV['DB']
|
|
121
|
+
when 'postgresql'
|
|
122
|
+
"postgres://postgres@localhost/#{ENV.fetch('POSTGRES_DB', 'ci_test')}"
|
|
123
|
+
else
|
|
124
|
+
'sqlite:/'
|
|
125
|
+
end
|
|
126
|
+
end
|
|
118
127
|
puts "Using database configuration: #{db_config}"
|
|
119
128
|
Dynflow::PersistenceAdapters::Sequel.new(db_config)
|
|
120
129
|
end
|
|
@@ -127,7 +136,7 @@ module WorldFactory
|
|
|
127
136
|
def self.clean_coordinator_records
|
|
128
137
|
persistence_adapter = WorldFactory.persistence_adapter
|
|
129
138
|
persistence_adapter.find_coordinator_records({}).each do |w|
|
|
130
|
-
warn "Unexpected coordinator record: #{w}"
|
|
139
|
+
::Dynflow::Testing.logger_adapter.logger.warn "Unexpected coordinator record: #{w}"
|
|
131
140
|
persistence_adapter.delete_coordinator_record(w[:class], w[:id])
|
|
132
141
|
end
|
|
133
142
|
end
|
|
@@ -234,12 +243,18 @@ module TestHelpers
|
|
|
234
243
|
end
|
|
235
244
|
|
|
236
245
|
class MiniTest::Test
|
|
246
|
+
def logger
|
|
247
|
+
::Dynflow::Testing.logger_adapter.logger
|
|
248
|
+
end
|
|
249
|
+
|
|
237
250
|
def setup
|
|
251
|
+
logger.info(">>>>> #{location}")
|
|
238
252
|
WorldFactory.clean_coordinator_records
|
|
239
253
|
end
|
|
240
254
|
|
|
241
255
|
def teardown
|
|
242
256
|
WorldFactory.terminate_worlds
|
|
257
|
+
logger.info("<<<<< #{location}")
|
|
243
258
|
end
|
|
244
259
|
end
|
|
245
260
|
|
data/web/views/show.erb
CHANGED
|
@@ -43,6 +43,30 @@
|
|
|
43
43
|
<%= h(@plan.ended_at) %>
|
|
44
44
|
</p>
|
|
45
45
|
|
|
46
|
+
<% dependencies = @plan.world.persistence.find_execution_plan_dependencies(@plan.id) %>
|
|
47
|
+
<% if dependencies.any? %>
|
|
48
|
+
<p>
|
|
49
|
+
<b>Depends on execution plans:</b>
|
|
50
|
+
<ul>
|
|
51
|
+
<% dependencies.each do |dep_id| %>
|
|
52
|
+
<li><a href="<%= url("/#{dep_id}") %>"><%= h(dep_id) %></a></li>
|
|
53
|
+
<% end %>
|
|
54
|
+
</ul>
|
|
55
|
+
</p>
|
|
56
|
+
<% end %>
|
|
57
|
+
|
|
58
|
+
<% blocked_plans = @plan.world.persistence.find_blocked_execution_plans(@plan.id) %>
|
|
59
|
+
<% if blocked_plans.any? %>
|
|
60
|
+
<p>
|
|
61
|
+
<b>Blocks execution plans:</b>
|
|
62
|
+
<ul>
|
|
63
|
+
<% blocked_plans.each do |dep_id| %>
|
|
64
|
+
<li><a href="<%= url("/#{dep_id}") %>"><%= h(dep_id) %></a></li>
|
|
65
|
+
<% end %>
|
|
66
|
+
</ul>
|
|
67
|
+
</p>
|
|
68
|
+
<% end %>
|
|
69
|
+
|
|
46
70
|
<ul class="phases nav nav-tabs" id="myTab">
|
|
47
71
|
<li><a href="#plan">Plan</a></li>
|
|
48
72
|
<li class="active"><a href="#run">Run</a></li>
|
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:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ivan Necas
|
|
@@ -24,20 +24,6 @@ dependencies:
|
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: 0.7.0
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: apipie-params
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - ">="
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0'
|
|
34
|
-
type: :runtime
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - ">="
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0'
|
|
41
27
|
- !ruby/object:Gem::Dependency
|
|
42
28
|
name: concurrent-ruby
|
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -331,7 +317,7 @@ executables: []
|
|
|
331
317
|
extensions: []
|
|
332
318
|
extra_rdoc_files: []
|
|
333
319
|
files:
|
|
334
|
-
- ".github/
|
|
320
|
+
- ".github/workflows/bats.yml"
|
|
335
321
|
- ".github/workflows/release.yml"
|
|
336
322
|
- ".github/workflows/ruby.yml"
|
|
337
323
|
- ".gitignore"
|
|
@@ -480,6 +466,7 @@ files:
|
|
|
480
466
|
- examples/chunked_output_benchmark.rb
|
|
481
467
|
- examples/clock_benchmark.rb
|
|
482
468
|
- examples/example_helper.rb
|
|
469
|
+
- examples/execution_plan_chaining.rb
|
|
483
470
|
- examples/future_execution.rb
|
|
484
471
|
- examples/halt.rb
|
|
485
472
|
- examples/memory_limit_watcher.rb
|
|
@@ -621,6 +608,7 @@ files:
|
|
|
621
608
|
- lib/dynflow/persistence_adapters/sequel_migrations/022_store_flows_as_msgpack.rb
|
|
622
609
|
- lib/dynflow/persistence_adapters/sequel_migrations/023_sqlite_workarounds.rb
|
|
623
610
|
- lib/dynflow/persistence_adapters/sequel_migrations/024_store_execution_plan_data_as_msgpack.rb
|
|
611
|
+
- lib/dynflow/persistence_adapters/sequel_migrations/025_create_execution_plan_dependencies.rb
|
|
624
612
|
- lib/dynflow/persistence_adapters/sequel_migrations/msgpack_migration_helper.rb
|
|
625
613
|
- lib/dynflow/rails.rb
|
|
626
614
|
- lib/dynflow/rails/configuration.rb
|
|
@@ -676,6 +664,11 @@ files:
|
|
|
676
664
|
- test/action_test.rb
|
|
677
665
|
- test/activejob_adapter_test.rb
|
|
678
666
|
- test/batch_sub_tasks_test.rb
|
|
667
|
+
- test/bats/helpers/common.bash
|
|
668
|
+
- test/bats/helpers/containers.bash
|
|
669
|
+
- test/bats/setup_suite.bash
|
|
670
|
+
- test/bats/sidekiq-orchestrator.bats
|
|
671
|
+
- test/bats/teardown_suite.bash
|
|
679
672
|
- test/clock_test.rb
|
|
680
673
|
- test/concurrency_control_test.rb
|
|
681
674
|
- test/coordinator_test.rb
|
|
@@ -744,7 +737,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
744
737
|
requirements:
|
|
745
738
|
- - ">="
|
|
746
739
|
- !ruby/object:Gem::Version
|
|
747
|
-
version:
|
|
740
|
+
version: 3.0.0
|
|
748
741
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
749
742
|
requirements:
|
|
750
743
|
- - ">="
|
|
@@ -759,6 +752,11 @@ test_files:
|
|
|
759
752
|
- test/action_test.rb
|
|
760
753
|
- test/activejob_adapter_test.rb
|
|
761
754
|
- test/batch_sub_tasks_test.rb
|
|
755
|
+
- test/bats/helpers/common.bash
|
|
756
|
+
- test/bats/helpers/containers.bash
|
|
757
|
+
- test/bats/setup_suite.bash
|
|
758
|
+
- test/bats/sidekiq-orchestrator.bats
|
|
759
|
+
- test/bats/teardown_suite.bash
|
|
762
760
|
- test/clock_test.rb
|
|
763
761
|
- test/concurrency_control_test.rb
|
|
764
762
|
- test/coordinator_test.rb
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
|
|
3
|
-
set -x
|
|
4
|
-
|
|
5
|
-
echo "Setting the environment to use ${DB} database"
|
|
6
|
-
|
|
7
|
-
BUNDLE_CONFIG=.bundle/config
|
|
8
|
-
mkdir -p $(dirname $BUNDLE_CONFIG)
|
|
9
|
-
cat <<EOF > $BUNDLE_CONFIG
|
|
10
|
-
---
|
|
11
|
-
BUNDLE_WITHOUT: pry:mysql:postgresql:concurrent_ruby_ext
|
|
12
|
-
EOF
|
|
13
|
-
|
|
14
|
-
case $DB in
|
|
15
|
-
mysql)
|
|
16
|
-
sed -i 's/:mysql//'g $BUNDLE_CONFIG
|
|
17
|
-
;;
|
|
18
|
-
postgresql)
|
|
19
|
-
sed -i 's/:postgresql//'g $BUNDLE_CONFIG
|
|
20
|
-
;;
|
|
21
|
-
sqlite3)
|
|
22
|
-
# the tests are by default using sqlite3: do nothing
|
|
23
|
-
;;
|
|
24
|
-
*)
|
|
25
|
-
echo "Unsupported database ${DB}"
|
|
26
|
-
exit 1
|
|
27
|
-
;;
|
|
28
|
-
esac
|
|
29
|
-
|
|
30
|
-
if [ "$CONCURRENT_RUBY_EXT" = "true" ]; then
|
|
31
|
-
echo "Enabling concurrent-ruby-ext"
|
|
32
|
-
sed -i 's/:concurrent_ruby_ext//'g $BUNDLE_CONFIG
|
|
33
|
-
fi
|
|
34
|
-
gem update bundler
|
|
35
|
-
bundle install
|