dynflow 1.8.2 → 1.8.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -1
- data/.rubocop.yml +11 -5
- data/.rubocop_todo.yml +777 -345
- data/Gemfile +4 -3
- data/Rakefile +1 -0
- data/doc/pages/Gemfile +4 -3
- data/doc/pages/Rakefile +1 -0
- data/doc/pages/plugins/alert_block.rb +1 -0
- data/doc/pages/plugins/div_tag.rb +1 -0
- data/doc/pages/plugins/graphviz.rb +6 -6
- data/doc/pages/plugins/plantuml.rb +2 -3
- data/doc/pages/plugins/play.rb +1 -2
- data/doc/pages/plugins/tags.rb +2 -8
- data/doc/pages/plugins/toc.rb +1 -1
- data/dynflow.gemspec +11 -10
- data/examples/clock_benchmark.rb +1 -0
- data/examples/example_helper.rb +4 -3
- data/examples/future_execution.rb +0 -2
- data/examples/memory_limit_watcher.rb +8 -8
- data/examples/orchestrate.rb +9 -21
- data/examples/orchestrate_evented.rb +18 -33
- data/examples/remote_executor.rb +9 -11
- data/examples/singletons.rb +1 -0
- data/examples/sub_plan_concurrency_control.rb +0 -1
- data/examples/sub_plans.rb +1 -0
- data/examples/sub_plans_v2.rb +1 -0
- data/lib/dynflow/action/cancellable.rb +1 -0
- data/lib/dynflow/action/format.rb +1 -4
- data/lib/dynflow/action/missing.rb +4 -4
- data/lib/dynflow/action/polling.rb +2 -3
- data/lib/dynflow/action/progress.rb +1 -4
- data/lib/dynflow/action/rescue.rb +1 -2
- data/lib/dynflow/action/singleton.rb +1 -0
- data/lib/dynflow/action/suspended.rb +1 -0
- data/lib/dynflow/action/timeouts.rb +2 -1
- data/lib/dynflow/action/with_bulk_sub_plans.rb +1 -0
- data/lib/dynflow/action/with_polling_sub_plans.rb +1 -1
- data/lib/dynflow/action/with_sub_plans.rb +20 -19
- data/lib/dynflow/action.rb +37 -37
- data/lib/dynflow/active_job/queue_adapter.rb +2 -1
- data/lib/dynflow/actor.rb +2 -2
- data/lib/dynflow/actors/execution_plan_cleaner.rb +1 -0
- data/lib/dynflow/actors.rb +1 -0
- data/lib/dynflow/clock.rb +3 -4
- data/lib/dynflow/config.rb +6 -5
- data/lib/dynflow/connectors/abstract.rb +11 -10
- data/lib/dynflow/connectors/database.rb +2 -2
- data/lib/dynflow/connectors/direct.rb +2 -3
- data/lib/dynflow/connectors.rb +1 -0
- data/lib/dynflow/coordinator.rb +2 -6
- data/lib/dynflow/coordinator_adapters/abstract.rb +1 -0
- data/lib/dynflow/coordinator_adapters/sequel.rb +1 -0
- data/lib/dynflow/coordinator_adapters.rb +1 -2
- data/lib/dynflow/dead_letter_silencer.rb +1 -0
- data/lib/dynflow/debug/telemetry/persistence.rb +3 -2
- data/lib/dynflow/delayed_executors/abstract.rb +1 -2
- data/lib/dynflow/delayed_executors/abstract_core.rb +1 -1
- data/lib/dynflow/delayed_executors/polling.rb +1 -2
- data/lib/dynflow/delayed_executors.rb +1 -2
- data/lib/dynflow/delayed_plan.rb +6 -6
- data/lib/dynflow/director/execution_plan_manager.rb +1 -1
- data/lib/dynflow/director/flow_manager.rb +1 -0
- data/lib/dynflow/director/queue_hash.rb +2 -1
- data/lib/dynflow/director/running_steps_manager.rb +3 -2
- data/lib/dynflow/director/sequence_cursor.rb +1 -2
- data/lib/dynflow/director/sequential_manager.rb +1 -0
- data/lib/dynflow/director.rb +12 -11
- data/lib/dynflow/dispatcher/abstract.rb +1 -0
- data/lib/dynflow/dispatcher/client_dispatcher.rb +33 -33
- data/lib/dynflow/dispatcher/executor_dispatcher.rb +7 -6
- data/lib/dynflow/dispatcher.rb +8 -7
- data/lib/dynflow/errors.rb +1 -0
- data/lib/dynflow/execution_history.rb +2 -1
- data/lib/dynflow/execution_plan/dependency_graph.rb +1 -2
- data/lib/dynflow/execution_plan/hooks.rb +1 -1
- data/lib/dynflow/execution_plan/output_reference.rb +4 -4
- data/lib/dynflow/execution_plan/steps/abstract.rb +21 -20
- data/lib/dynflow/execution_plan/steps/abstract_flow_step.rb +1 -1
- data/lib/dynflow/execution_plan/steps/error.rb +10 -9
- data/lib/dynflow/execution_plan/steps/finalize_step.rb +1 -2
- data/lib/dynflow/execution_plan/steps/plan_step.rb +12 -11
- data/lib/dynflow/execution_plan/steps/run_step.rb +1 -1
- data/lib/dynflow/execution_plan/steps.rb +1 -2
- data/lib/dynflow/execution_plan.rb +46 -46
- data/lib/dynflow/executors/abstract/core.rb +4 -3
- data/lib/dynflow/executors/parallel/core.rb +3 -2
- data/lib/dynflow/executors/parallel/pool.rb +1 -4
- data/lib/dynflow/executors/parallel/worker.rb +1 -0
- data/lib/dynflow/executors/parallel.rb +3 -2
- data/lib/dynflow/executors/sidekiq/core.rb +2 -0
- data/lib/dynflow/executors/sidekiq/internal_job_base.rb +1 -0
- data/lib/dynflow/executors/sidekiq/orchestrator_jobs.rb +1 -0
- data/lib/dynflow/executors/sidekiq/redis_locking.rb +1 -0
- data/lib/dynflow/executors/sidekiq/serialization.rb +1 -0
- data/lib/dynflow/executors/sidekiq/worker_jobs.rb +1 -0
- data/lib/dynflow/executors.rb +1 -1
- data/lib/dynflow/extensions/msgpack.rb +5 -4
- data/lib/dynflow/extensions.rb +1 -0
- data/lib/dynflow/flows/abstract.rb +1 -1
- data/lib/dynflow/flows/abstract_composed.rb +1 -2
- data/lib/dynflow/flows/atom.rb +1 -2
- data/lib/dynflow/flows/concurrence.rb +1 -1
- data/lib/dynflow/flows/registry.rb +1 -0
- data/lib/dynflow/flows/sequence.rb +1 -1
- data/lib/dynflow/flows.rb +1 -2
- data/lib/dynflow/logger_adapters/abstract.rb +1 -1
- data/lib/dynflow/logger_adapters/delegator.rb +1 -1
- data/lib/dynflow/logger_adapters/formatters/abstract.rb +1 -0
- data/lib/dynflow/logger_adapters/formatters/exception.rb +1 -0
- data/lib/dynflow/logger_adapters/formatters.rb +1 -0
- data/lib/dynflow/logger_adapters/simple.rb +6 -5
- data/lib/dynflow/logger_adapters.rb +1 -0
- data/lib/dynflow/middleware/common/singleton.rb +1 -0
- data/lib/dynflow/middleware/common/transaction.rb +1 -0
- data/lib/dynflow/middleware/register.rb +1 -0
- data/lib/dynflow/middleware/resolver.rb +2 -3
- data/lib/dynflow/middleware/stack.rb +1 -0
- data/lib/dynflow/middleware/world.rb +1 -2
- data/lib/dynflow/middleware.rb +1 -0
- data/lib/dynflow/persistence.rb +4 -5
- data/lib/dynflow/persistence_adapters/abstract.rb +1 -1
- data/lib/dynflow/persistence_adapters/sequel.rb +14 -14
- data/lib/dynflow/persistence_adapters/sequel_migrations/001_initial.rb +2 -1
- data/lib/dynflow/persistence_adapters/sequel_migrations/002_incremental_progress.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/003_parent_action.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/004_coordinator_records.rb +1 -1
- data/lib/dynflow/persistence_adapters/sequel_migrations/005_envelopes.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/006_fix_data_length.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/007_future_execution.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/008_rename_scheduled_plans_to_delayed_plans.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/009_fix_mysql_data_length.rb +1 -1
- data/lib/dynflow/persistence_adapters/sequel_migrations/010_add_execution_plans_label.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/011_placeholder.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/012_add_delayed_plans_serialized_args.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/013_add_action_columns.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/014_add_step_columns.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/015_add_execution_plan_columns.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/016_add_step_queue.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/017_add_delayed_plan_frozen.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/018_add_uuid_column.rb +37 -30
- data/lib/dynflow/persistence_adapters/sequel_migrations/019_update_mysql_time_precision.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/020_drop_duplicate_indices.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/021_create_output_chunks.rb +4 -3
- data/lib/dynflow/persistence_adapters/sequel_migrations/023_sqlite_workarounds.rb +1 -0
- data/lib/dynflow/persistence_adapters.rb +1 -0
- data/lib/dynflow/rails/configuration.rb +1 -0
- data/lib/dynflow/rails/daemon.rb +1 -1
- data/lib/dynflow/rails.rb +3 -2
- data/lib/dynflow/round_robin.rb +2 -2
- data/lib/dynflow/semaphores/abstract.rb +1 -1
- data/lib/dynflow/semaphores/aggregating.rb +1 -2
- data/lib/dynflow/semaphores/dummy.rb +1 -1
- data/lib/dynflow/semaphores/stateful.rb +1 -1
- data/lib/dynflow/semaphores.rb +1 -0
- data/lib/dynflow/serializable.rb +1 -0
- data/lib/dynflow/serializer.rb +2 -2
- data/lib/dynflow/serializers/abstract.rb +1 -2
- data/lib/dynflow/serializers/noop.rb +1 -2
- data/lib/dynflow/serializers.rb +1 -2
- data/lib/dynflow/stateful.rb +1 -0
- data/lib/dynflow/telemetry.rb +11 -10
- data/lib/dynflow/telemetry_adapters/abstract.rb +1 -0
- data/lib/dynflow/telemetry_adapters/dummy.rb +1 -0
- data/lib/dynflow/telemetry_adapters/statsd.rb +2 -1
- data/lib/dynflow/testing/assertions.rb +7 -7
- data/lib/dynflow/testing/dummy_coordinator.rb +1 -0
- data/lib/dynflow/testing/dummy_execution_plan.rb +1 -0
- data/lib/dynflow/testing/dummy_executor.rb +1 -0
- data/lib/dynflow/testing/dummy_planned_action.rb +3 -1
- data/lib/dynflow/testing/dummy_step.rb +1 -0
- data/lib/dynflow/testing/dummy_world.rb +1 -0
- data/lib/dynflow/testing/factories.rb +42 -37
- data/lib/dynflow/testing/in_thread_executor.rb +1 -0
- data/lib/dynflow/testing/in_thread_world.rb +1 -0
- data/lib/dynflow/testing/managed_clock.rb +1 -1
- data/lib/dynflow/testing/mimic.rb +4 -4
- data/lib/dynflow/testing.rb +1 -0
- data/lib/dynflow/throttle_limiter.rb +1 -1
- data/lib/dynflow/transaction_adapters/abstract.rb +1 -0
- data/lib/dynflow/transaction_adapters/active_record.rb +1 -0
- data/lib/dynflow/transaction_adapters/none.rb +1 -0
- data/lib/dynflow/transaction_adapters.rb +1 -2
- data/lib/dynflow/utils/indifferent_hash.rb +7 -1
- data/lib/dynflow/utils/priority_queue.rb +1 -0
- data/lib/dynflow/utils.rb +1 -1
- data/lib/dynflow/version.rb +2 -1
- data/lib/dynflow/watchers/memory_consumption_watcher.rb +1 -1
- data/lib/dynflow/web/console.rb +1 -3
- data/lib/dynflow/web/console_helpers.rb +5 -4
- data/lib/dynflow/web/filtering_helpers.rb +1 -0
- data/lib/dynflow/web/world_helpers.rb +1 -0
- data/lib/dynflow/web.rb +3 -3
- data/lib/dynflow/web_console.rb +1 -0
- data/lib/dynflow/world/invalidation.rb +1 -0
- data/lib/dynflow/world.rb +19 -19
- data/lib/dynflow.rb +2 -5
- data/test/abnormal_states_recovery_test.rb +4 -8
- data/test/action_test.rb +10 -18
- data/test/activejob_adapter_test.rb +2 -2
- data/test/batch_sub_tasks_test.rb +1 -1
- data/test/clock_test.rb +2 -3
- data/test/concurrency_control_test.rb +6 -7
- data/test/coordinator_test.rb +1 -0
- data/test/daemon_test.rb +3 -2
- data/test/dead_letter_silencer_test.rb +2 -1
- data/test/dispatcher_test.rb +4 -5
- data/test/execution_plan_cleaner_test.rb +1 -0
- data/test/execution_plan_hooks_test.rb +1 -0
- data/test/execution_plan_test.rb +10 -32
- data/test/executor_test.rb +20 -37
- data/test/extensions_test.rb +1 -0
- data/test/flows_test.rb +2 -2
- data/test/future_execution_test.rb +2 -3
- data/test/memory_cosumption_watcher_test.rb +1 -0
- data/test/middleware_test.rb +4 -6
- data/test/persistence_test.rb +26 -26
- data/test/redis_locking_test.rb +1 -0
- data/test/rescue_test.rb +3 -11
- data/test/round_robin_test.rb +1 -0
- data/test/semaphores_test.rb +5 -7
- data/test/support/code_workflow_example.rb +11 -28
- data/test/support/dummy_example.rb +20 -19
- data/test/support/middleware_example.rb +2 -8
- data/test/support/rescue_example.rb +1 -14
- data/test/support/test_execution_log.rb +1 -2
- data/test/test_helper.rb +3 -7
- data/test/testing_test.rb +6 -8
- data/test/utils_test.rb +1 -0
- data/test/v2_sub_plans_test.rb +1 -0
- data/test/web_console_test.rb +4 -4
- data/test/world_test.rb +4 -3
- metadata +43 -43
@@ -1,13 +1,12 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
# frozen_string_literal: true
|
3
|
+
|
3
4
|
require_relative 'test_helper'
|
4
5
|
require 'ostruct'
|
5
6
|
|
6
7
|
module Dynflow
|
7
8
|
module ConsistencyCheckTest
|
8
|
-
|
9
9
|
describe "consistency check" do
|
10
|
-
|
11
10
|
include TestHelpers
|
12
11
|
|
13
12
|
def with_invalidation_while_executing(finish)
|
@@ -43,7 +42,6 @@ module Dynflow
|
|
43
42
|
let(:client_world_2) { create_world(false) }
|
44
43
|
|
45
44
|
describe "for plans assigned to invalid world" do
|
46
|
-
|
47
45
|
before do
|
48
46
|
# mention the executors to make sure they are initialized
|
49
47
|
[executor_world, executor_world_2]
|
@@ -187,7 +185,6 @@ module Dynflow
|
|
187
185
|
end
|
188
186
|
|
189
187
|
describe 'auto execute' do
|
190
|
-
|
191
188
|
before do
|
192
189
|
client_world.persistence.delete_execution_plans({})
|
193
190
|
end
|
@@ -273,10 +270,10 @@ module Dynflow
|
|
273
270
|
end
|
274
271
|
|
275
272
|
it 'by default, the auto_validity_check is enabled only for executor words' do
|
276
|
-
client_world_config = Config::ForWorld.new(Config.new.tap { |c| c.executor = false }, create_world
|
273
|
+
client_world_config = Config::ForWorld.new(Config.new.tap { |c| c.executor = false }, create_world)
|
277
274
|
_(client_world_config.auto_validity_check).must_equal false
|
278
275
|
|
279
|
-
executor_world_config = Config::ForWorld.new(Config.new.tap { |c| c.executor = Executors::Parallel::Core }, create_world
|
276
|
+
executor_world_config = Config::ForWorld.new(Config.new.tap { |c| c.executor = Executors::Parallel::Core }, create_world)
|
280
277
|
_(executor_world_config.auto_validity_check).must_equal true
|
281
278
|
end
|
282
279
|
|
@@ -304,7 +301,7 @@ module Dynflow
|
|
304
301
|
_(client_world.coordinator.find_worlds(false, id: [invalid_world.id, invalid_world_2.id]).size).must_equal 2
|
305
302
|
|
306
303
|
results = client_world.worlds_validity_check(true, :id => invalid_world.id)
|
307
|
-
_(results).must_equal(invalid_world.id =>
|
304
|
+
_(results).must_equal(invalid_world.id => :invalidated)
|
308
305
|
_(client_world.coordinator.find_worlds(false, id: [invalid_world.id, invalid_world_2.id]).size).must_equal 1
|
309
306
|
end
|
310
307
|
end
|
@@ -382,4 +379,3 @@ module Dynflow
|
|
382
379
|
end
|
383
380
|
end
|
384
381
|
end
|
385
|
-
|
data/test/action_test.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative 'test_helper'
|
3
4
|
require 'mocha/minitest'
|
4
5
|
|
5
6
|
module Dynflow
|
6
7
|
describe 'action' do
|
7
|
-
|
8
8
|
let(:world) { WorldFactory.create_world }
|
9
9
|
|
10
10
|
describe Action::Missing do
|
11
|
-
|
12
11
|
let :action_data do
|
13
12
|
{ class: 'RenamedAction',
|
14
13
|
id: 1,
|
@@ -32,7 +31,6 @@ module Dynflow
|
|
32
31
|
end
|
33
32
|
|
34
33
|
describe 'children' do
|
35
|
-
|
36
34
|
smart_action_class = Class.new(Dynflow::Action)
|
37
35
|
smarter_action_class = Class.new(smart_action_class)
|
38
36
|
|
@@ -50,7 +48,6 @@ module Dynflow
|
|
50
48
|
end
|
51
49
|
|
52
50
|
describe Action::Present do
|
53
|
-
|
54
51
|
let :execution_plan do
|
55
52
|
result = world.trigger(Support::CodeWorkflowExample::IncomingIssues, issues_data)
|
56
53
|
_(result).must_be :planned?
|
@@ -74,7 +71,6 @@ module Dynflow
|
|
74
71
|
end
|
75
72
|
|
76
73
|
describe 'serialization' do
|
77
|
-
|
78
74
|
include Testing
|
79
75
|
|
80
76
|
it 'fails when input is not serializable' do
|
@@ -196,10 +192,9 @@ module Dynflow
|
|
196
192
|
end
|
197
193
|
|
198
194
|
class TestPollingAction < Dynflow::Action
|
199
|
-
|
200
195
|
class Config
|
201
196
|
attr_accessor :external_service, :poll_max_retries,
|
202
|
-
|
197
|
+
:poll_intervals, :attempts_before_next_interval
|
203
198
|
|
204
199
|
def initialize
|
205
200
|
@external_service = ExternalService.new
|
@@ -383,7 +378,6 @@ module Dynflow
|
|
383
378
|
end
|
384
379
|
|
385
380
|
describe Action::WithSubPlans do
|
386
|
-
|
387
381
|
class FailureSimulator
|
388
382
|
class << self
|
389
383
|
attr_accessor :fail_in_child_plan, :fail_in_child_run
|
@@ -399,7 +393,6 @@ module Dynflow
|
|
399
393
|
end
|
400
394
|
|
401
395
|
class ParentAction < Dynflow::Action
|
402
|
-
|
403
396
|
include Dynflow::Action::WithSubPlans
|
404
397
|
|
405
398
|
def plan(*_)
|
@@ -413,7 +406,7 @@ module Dynflow
|
|
413
406
|
|
414
407
|
def resume(*args)
|
415
408
|
output[:custom_resume] = true
|
416
|
-
super
|
409
|
+
super(*args)
|
417
410
|
end
|
418
411
|
end
|
419
412
|
|
@@ -481,7 +474,6 @@ module Dynflow
|
|
481
474
|
def batch(from, size)
|
482
475
|
total_count.times.drop(from).take(size)
|
483
476
|
end
|
484
|
-
|
485
477
|
end
|
486
478
|
|
487
479
|
let(:execution_plan) { world.trigger(ParentAction, count: 2).finished.value }
|
@@ -506,7 +498,7 @@ module Dynflow
|
|
506
498
|
end
|
507
499
|
|
508
500
|
specify "it saves the information about number for sub plans in the output" do
|
509
|
-
_(execution_plan.entry_action.output).must_equal('total_count'
|
501
|
+
_(execution_plan.entry_action.output).must_equal('total_count' => 2,
|
510
502
|
'failed_count' => 0,
|
511
503
|
'success_count' => 2,
|
512
504
|
'pending_count' => 0)
|
@@ -514,7 +506,7 @@ module Dynflow
|
|
514
506
|
|
515
507
|
specify "when a sub plan fails, the caller action fails as well" do
|
516
508
|
FailureSimulator.fail_in_child_run = true
|
517
|
-
_(execution_plan.entry_action.output).must_equal('total_count'
|
509
|
+
_(execution_plan.entry_action.output).must_equal('total_count' => 2,
|
518
510
|
'failed_count' => 2,
|
519
511
|
'success_count' => 0,
|
520
512
|
'pending_count' => 0)
|
@@ -789,7 +781,7 @@ module Dynflow
|
|
789
781
|
plan = world.plan(SingletonAction)
|
790
782
|
_(plan.state).must_equal :planned
|
791
783
|
lock_filter = ::Dynflow::Coordinator::SingletonActionLock
|
792
|
-
|
784
|
+
.unique_filter plan.entry_action.class.name
|
793
785
|
_(world.coordinator.find_locks(lock_filter).count).must_equal 1
|
794
786
|
plan = world.execute(plan.id).wait!.value
|
795
787
|
_(plan.state).must_equal :stopped
|
@@ -801,7 +793,7 @@ module Dynflow
|
|
801
793
|
plan = world.plan(SingletonActionWithFinalize)
|
802
794
|
_(plan.state).must_equal :planned
|
803
795
|
lock_filter = ::Dynflow::Coordinator::SingletonActionLock
|
804
|
-
|
796
|
+
.unique_filter plan.entry_action.class.name
|
805
797
|
_(world.coordinator.find_locks(lock_filter).count).must_equal 1
|
806
798
|
plan = world.execute(plan.id).wait!.value
|
807
799
|
_(plan.state).must_equal :stopped
|
@@ -813,7 +805,7 @@ module Dynflow
|
|
813
805
|
plan = world.plan(SuspendedSingletonAction)
|
814
806
|
_(plan.state).must_equal :planned
|
815
807
|
lock_filter = ::Dynflow::Coordinator::SingletonActionLock
|
816
|
-
|
808
|
+
.unique_filter plan.entry_action.class.name
|
817
809
|
_(world.coordinator.find_locks(lock_filter).count).must_equal 1
|
818
810
|
future = world.execute(plan.id)
|
819
811
|
wait_for do
|
@@ -859,7 +851,7 @@ module Dynflow
|
|
859
851
|
|
860
852
|
# The lock was released when plan3 stopped
|
861
853
|
lock_filter = ::Dynflow::Coordinator::SingletonActionLock
|
862
|
-
|
854
|
+
.unique_filter plan3.entry_action.class.name
|
863
855
|
_(world.coordinator.find_locks(lock_filter)).must_be :empty?
|
864
856
|
end
|
865
857
|
|
@@ -868,7 +860,7 @@ module Dynflow
|
|
868
860
|
plan1 = world.plan(BadAction, true)
|
869
861
|
_(plan1.state).must_equal :planned
|
870
862
|
lock_filter = ::Dynflow::Coordinator::SingletonActionLock
|
871
|
-
|
863
|
+
.unique_filter plan1.entry_action.class.name
|
872
864
|
_(world.coordinator.find_locks(lock_filter).count).must_equal 0
|
873
865
|
plan2 = world.plan(BadAction, false)
|
874
866
|
_(plan2.state).must_equal :planned
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative 'test_helper'
|
3
4
|
require 'active_job'
|
4
5
|
require 'dynflow/active_job/queue_adapter'
|
@@ -21,7 +22,7 @@ module Dynflow
|
|
21
22
|
end
|
22
23
|
|
23
24
|
before(:all) do
|
24
|
-
::ActiveJob::QueueAdapters.
|
25
|
+
::ActiveJob::QueueAdapters.include ::Dynflow::ActiveJob::QueueAdapters
|
25
26
|
::ActiveJob::Base.queue_adapter = :dynflow
|
26
27
|
dynflow_mock = Minitest::Mock.new
|
27
28
|
dynflow_mock.expect(:world, world)
|
@@ -71,4 +72,3 @@ module Dynflow
|
|
71
72
|
end
|
72
73
|
end
|
73
74
|
end
|
74
|
-
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative 'test_helper'
|
3
4
|
|
4
5
|
module Dynflow
|
@@ -109,7 +110,6 @@ module Dynflow
|
|
109
110
|
_(action.send(:can_spawn_next_batch?)).must_equal false
|
110
111
|
_(action.current_batch).must_be :empty?
|
111
112
|
end
|
112
|
-
|
113
113
|
end
|
114
114
|
end
|
115
115
|
end
|
data/test/clock_test.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative 'test_helper'
|
3
4
|
require 'logger'
|
4
5
|
|
5
6
|
clock_class = Dynflow::Clock
|
6
7
|
|
7
8
|
describe clock_class do
|
8
|
-
|
9
9
|
let(:clock) { clock_class.spawn 'clock' }
|
10
10
|
|
11
11
|
it 'refuses who without #<< method' do
|
@@ -48,7 +48,6 @@ describe clock_class do
|
|
48
48
|
assert_equal (0...times).to_a, Array.new(times) { q.pop }.sort
|
49
49
|
end
|
50
50
|
end
|
51
|
-
threads.each
|
51
|
+
threads.each(&:join)
|
52
52
|
end
|
53
|
-
|
54
53
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative 'test_helper'
|
3
4
|
|
4
5
|
module Dynflow
|
@@ -81,8 +82,8 @@ module Dynflow
|
|
81
82
|
end
|
82
83
|
|
83
84
|
def check_step(plan, total, finished)
|
84
|
-
_(world.throttle_limiter.observe(plan.id).length).must_equal
|
85
|
-
_(plan.sub_plans.select { |sub| planned? sub }.count).must_equal
|
85
|
+
_(world.throttle_limiter.observe(plan.id).length).must_equal(total - finished)
|
86
|
+
_(plan.sub_plans.select { |sub| planned? sub }.count).must_equal(total - finished)
|
86
87
|
_(plan.sub_plans.select { |sub| successful? sub }.count).must_equal finished
|
87
88
|
end
|
88
89
|
|
@@ -95,14 +96,12 @@ module Dynflow
|
|
95
96
|
end
|
96
97
|
|
97
98
|
class LoggingThrottleLimiter < Dynflow::ThrottleLimiter
|
98
|
-
|
99
99
|
class LoggingCore < Dynflow::ThrottleLimiter::Core
|
100
|
-
|
101
100
|
attr_reader :running
|
102
101
|
|
103
102
|
def initialize(*args)
|
104
103
|
@running = [0]
|
105
|
-
super
|
104
|
+
super(*args)
|
106
105
|
end
|
107
106
|
|
108
107
|
def release(*args)
|
@@ -233,12 +232,12 @@ module Dynflow
|
|
233
232
|
planned, running = plan.sub_plans.partition { |sub| planned? sub }
|
234
233
|
_(planned.count).must_equal total - level
|
235
234
|
_(running.count).must_equal level
|
236
|
-
_(world.throttle_limiter.observe(plan.id).length).must_equal
|
235
|
+
_(world.throttle_limiter.observe(plan.id).length).must_equal(total - 1)
|
237
236
|
4.times { klok.progress }
|
238
237
|
wait_for { future.resolved? }
|
239
238
|
finished, stopped = plan.sub_plans.partition { |sub| successful? sub }
|
240
239
|
_(finished.count).must_equal level
|
241
|
-
_(stopped.count).must_equal
|
240
|
+
_(stopped.count).must_equal(total - level)
|
242
241
|
end
|
243
242
|
end
|
244
243
|
end
|
data/test/coordinator_test.rb
CHANGED
data/test/daemon_test.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'test_helper'
|
3
4
|
require 'active_support'
|
4
5
|
require 'mocha/minitest'
|
@@ -34,8 +35,8 @@ class DaemonTest < ActiveSupport::TestCase
|
|
34
35
|
@daemon.stubs(:sleep).returns(true) # don't pause the execution
|
35
36
|
@current_folder = File.expand_path('../support/rails/', __FILE__)
|
36
37
|
::ActiveRecord::Base.configurations = { 'development' => {} }
|
37
|
-
::Dynflow::Rails::Configuration.any_instance.stubs(:initialize_persistence)
|
38
|
-
|
38
|
+
::Dynflow::Rails::Configuration.any_instance.stubs(:initialize_persistence)
|
39
|
+
.returns(WorldFactory.persistence_adapter)
|
39
40
|
end
|
40
41
|
|
41
42
|
teardown do
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative 'test_helper'
|
3
4
|
require 'ostruct'
|
4
5
|
|
@@ -12,7 +13,7 @@ module Dynflow
|
|
12
13
|
|
13
14
|
it 'is started for each world' do
|
14
15
|
_(world.dead_letter_handler.actor_class)
|
15
|
-
|
16
|
+
.must_equal ::Dynflow::DeadLetterSilencer
|
16
17
|
end
|
17
18
|
|
18
19
|
describe ::Dynflow::DeadLetterSilencer::Matcher do
|
data/test/dispatcher_test.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative 'test_helper'
|
3
4
|
|
4
5
|
module Dynflow
|
5
6
|
module DispatcherTest
|
6
7
|
describe "dispatcher" do
|
7
|
-
|
8
8
|
include TestHelpers
|
9
9
|
|
10
10
|
let(:persistence_adapter) { WorldFactory.persistence_adapter }
|
@@ -27,8 +27,8 @@ module Dynflow
|
|
27
27
|
it 'succeeds when expected' do
|
28
28
|
result = client_world.trigger(Support::DummyExample::DeprecatedEventedAction, :timeout => 3)
|
29
29
|
step = wait_for do
|
30
|
-
client_world.persistence.load_execution_plan(result.id)
|
31
|
-
|
30
|
+
client_world.persistence.load_execution_plan(result.id)
|
31
|
+
.steps_in_state(:suspended).first
|
32
32
|
end
|
33
33
|
client_world.event(step.execution_plan_id, step.id, 'finish')
|
34
34
|
plan = result.finished.value
|
@@ -53,7 +53,7 @@ module Dynflow
|
|
53
53
|
it 'does not error on dispatching an optional event' do
|
54
54
|
request = client_world.event('123', 1, nil, optional: true)
|
55
55
|
request.wait(20)
|
56
|
-
assert_match
|
56
|
+
assert_match(/Could not find an executor for optional .*, discarding/, request.reason.message)
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
@@ -72,7 +72,6 @@ module Dynflow
|
|
72
72
|
assert_plan_reexecuted(plan)
|
73
73
|
end
|
74
74
|
end
|
75
|
-
|
76
75
|
end
|
77
76
|
|
78
77
|
def self.supports_ping_pong
|
data/test/execution_plan_test.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative 'test_helper'
|
3
4
|
|
4
5
|
module Dynflow
|
5
6
|
module ExecutionPlanTest
|
6
7
|
describe ExecutionPlan do
|
7
|
-
|
8
8
|
include PlanAssertions
|
9
9
|
|
10
10
|
let(:world) { WorldFactory.create_world }
|
@@ -15,7 +15,6 @@ module Dynflow
|
|
15
15
|
end
|
16
16
|
|
17
17
|
describe 'serialization' do
|
18
|
-
|
19
18
|
let :execution_plan do
|
20
19
|
world.plan(Support::CodeWorkflowExample::FastCommit, 'sha' => 'abc123')
|
21
20
|
end
|
@@ -25,7 +24,6 @@ module Dynflow
|
|
25
24
|
end
|
26
25
|
|
27
26
|
describe 'serialized execution plan' do
|
28
|
-
|
29
27
|
before { execution_plan.save }
|
30
28
|
after { world.persistence.delete_execution_plans(:uuid => execution_plan.id) }
|
31
29
|
|
@@ -46,26 +44,24 @@ module Dynflow
|
|
46
44
|
|
47
45
|
it 'handles issues with loading the data' do
|
48
46
|
world.persistence.adapter.send(:table, :step)
|
49
|
-
|
47
|
+
.where(execution_plan_uuid: execution_plan.id).delete
|
50
48
|
refute deserialized_execution_plan.valid?
|
51
49
|
assert_equal Dynflow::Errors::DataConsistencyError, deserialized_execution_plan.exception.class
|
52
50
|
[:label, :state, :started_at, :ended_at].each do |attr|
|
53
51
|
assert_equal execution_plan.send(attr).to_s,
|
54
|
-
|
55
|
-
|
52
|
+
deserialized_execution_plan.send(attr).to_s,
|
53
|
+
"invalid plan is supposed to still store #{attr}"
|
56
54
|
end
|
57
55
|
[:execution_time, :real_time].each do |attr|
|
58
56
|
assert_equal execution_plan.send(attr).to_f,
|
59
|
-
|
60
|
-
|
57
|
+
deserialized_execution_plan.send(attr).to_f,
|
58
|
+
"invalid plan is supposed to still store #{attr}"
|
61
59
|
end
|
62
60
|
assert_equal execution_plan.execution_history.events,
|
63
|
-
|
64
|
-
|
61
|
+
deserialized_execution_plan.execution_history.events,
|
62
|
+
"invalid plan is supposed to still store execution history"
|
65
63
|
end
|
66
|
-
|
67
64
|
end
|
68
|
-
|
69
65
|
end
|
70
66
|
|
71
67
|
describe '#label' do
|
@@ -83,24 +79,20 @@ module Dynflow
|
|
83
79
|
end
|
84
80
|
end
|
85
81
|
describe '#result' do
|
86
|
-
|
87
82
|
let :execution_plan do
|
88
83
|
world.plan(Support::CodeWorkflowExample::FastCommit, 'sha' => 'abc123')
|
89
84
|
end
|
90
85
|
|
91
86
|
describe 'for error in planning phase' do
|
92
|
-
|
93
87
|
before { execution_plan.steps[2].set_state :error, true }
|
94
88
|
|
95
89
|
it 'should be :error' do
|
96
90
|
_(execution_plan.result).must_equal :error
|
97
91
|
_(execution_plan.error?).must_equal true
|
98
92
|
end
|
99
|
-
|
100
93
|
end
|
101
94
|
|
102
95
|
describe 'for error in running phase' do
|
103
|
-
|
104
96
|
before do
|
105
97
|
step_id = execution_plan.run_flow.all_step_ids[2]
|
106
98
|
execution_plan.steps[step_id].set_state :error, true
|
@@ -109,11 +101,9 @@ module Dynflow
|
|
109
101
|
it 'should be :error' do
|
110
102
|
_(execution_plan.result).must_equal :error
|
111
103
|
end
|
112
|
-
|
113
104
|
end
|
114
105
|
|
115
106
|
describe 'for pending step in running phase' do
|
116
|
-
|
117
107
|
before do
|
118
108
|
step_id = execution_plan.run_flow.all_step_ids[2]
|
119
109
|
execution_plan.steps[step_id].set_state :pending, true
|
@@ -122,11 +112,9 @@ module Dynflow
|
|
122
112
|
it 'should be :pending' do
|
123
113
|
_(execution_plan.result).must_equal :pending
|
124
114
|
end
|
125
|
-
|
126
115
|
end
|
127
116
|
|
128
117
|
describe 'for all steps successful or skipped' do
|
129
|
-
|
130
118
|
before do
|
131
119
|
execution_plan.run_flow.all_step_ids.each_with_index do |step_id, index|
|
132
120
|
step = execution_plan.steps[step_id]
|
@@ -137,9 +125,7 @@ module Dynflow
|
|
137
125
|
it 'should be :warning' do
|
138
126
|
_(execution_plan.result).must_equal :warning
|
139
127
|
end
|
140
|
-
|
141
128
|
end
|
142
|
-
|
143
129
|
end
|
144
130
|
|
145
131
|
describe 'sub plans' do
|
@@ -171,11 +157,9 @@ module Dynflow
|
|
171
157
|
NotifyAssignee
|
172
158
|
PLAN_STEPS
|
173
159
|
end
|
174
|
-
|
175
160
|
end
|
176
161
|
|
177
162
|
describe 'persisted action' do
|
178
|
-
|
179
163
|
let :execution_plan do
|
180
164
|
world.plan(Support::CodeWorkflowExample::IncomingIssues, issues_data)
|
181
165
|
end
|
@@ -206,7 +190,6 @@ module Dynflow
|
|
206
190
|
end
|
207
191
|
|
208
192
|
describe 'planning algorithm' do
|
209
|
-
|
210
193
|
describe 'single dependencies' do
|
211
194
|
let :execution_plan do
|
212
195
|
world.plan(Support::CodeWorkflowExample::IncomingIssues, issues_data)
|
@@ -225,7 +208,6 @@ module Dynflow
|
|
225
208
|
18: NotifyAssignee(pending) {"triage"=>Step(13).output}
|
226
209
|
RUN_FLOW
|
227
210
|
end
|
228
|
-
|
229
211
|
end
|
230
212
|
|
231
213
|
describe 'error in planning phase' do
|
@@ -286,7 +268,6 @@ module Dynflow
|
|
286
268
|
end
|
287
269
|
|
288
270
|
describe 'finalize flow' do
|
289
|
-
|
290
271
|
let :execution_plan do
|
291
272
|
world.plan(Support::CodeWorkflowExample::IncomingIssues, issues_data)
|
292
273
|
end
|
@@ -301,7 +282,6 @@ module Dynflow
|
|
301
282
|
20: IncomingIssues(pending) {\"issues\"=>[{\"author\"=>\"Peter Smith\", \"text\"=>\"Failing test\"}, {\"author\"=>\"John Doe\", \"text\"=>\"Internal server error\"}]}
|
302
283
|
RUN_FLOW
|
303
284
|
end
|
304
|
-
|
305
285
|
end
|
306
286
|
end
|
307
287
|
|
@@ -355,7 +335,6 @@ module Dynflow
|
|
355
335
|
end
|
356
336
|
|
357
337
|
describe ExecutionPlan::Steps::Error do
|
358
|
-
|
359
338
|
it "doesn't fail when deserializing with missing class" do
|
360
339
|
error = ExecutionPlan::Steps::Error.new_from_hash(exception_class: "RenamedError",
|
361
340
|
message: "This errror is not longer here",
|
@@ -364,7 +343,6 @@ module Dynflow
|
|
364
343
|
_(error.exception_class.to_s).must_equal "Dynflow::Errors::UnknownError[RenamedError]"
|
365
344
|
_(error.exception.inspect).must_equal "Dynflow::Errors::UnknownError[RenamedError]: This errror is not longer here"
|
366
345
|
end
|
367
|
-
|
368
346
|
end
|
369
347
|
|
370
348
|
describe 'with singleton actions' do
|
@@ -382,7 +360,7 @@ module Dynflow
|
|
382
360
|
plan = world.plan(SingletonAction)
|
383
361
|
_(plan.state).must_equal :planned
|
384
362
|
lock_filter = ::Dynflow::Coordinator::SingletonActionLock
|
385
|
-
|
363
|
+
.unique_filter plan.entry_action.class.name
|
386
364
|
_(world.coordinator.find_locks(lock_filter).count).must_equal 1
|
387
365
|
plan = world.execute(plan.id).wait!.value
|
388
366
|
_(plan.state).must_equal :stopped
|
@@ -394,7 +372,7 @@ module Dynflow
|
|
394
372
|
plan = world.plan(SingletonAction, :fail => true)
|
395
373
|
_(plan.state).must_equal :planned
|
396
374
|
lock_filter = ::Dynflow::Coordinator::SingletonActionLock
|
397
|
-
|
375
|
+
.unique_filter plan.entry_action.class.name
|
398
376
|
_(world.coordinator.find_locks(lock_filter).count).must_equal 1
|
399
377
|
plan = world.execute(plan.id).wait!.value
|
400
378
|
_(plan.state).must_equal :paused
|