dynflow 1.8.2 → 1.8.3
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/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
|