dynflow 1.8.1 → 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 +13 -14
- 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 +3 -1
- 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 +5 -4
- 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 +3 -6
- 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
data/lib/dynflow/world.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
# frozen_string_literal: true
|
3
|
+
|
3
4
|
require 'dynflow/world/invalidation'
|
4
5
|
|
5
6
|
module Dynflow
|
@@ -9,10 +10,10 @@ module Dynflow
|
|
9
10
|
include Invalidation
|
10
11
|
|
11
12
|
attr_reader :id, :config, :client_dispatcher, :executor_dispatcher, :executor, :connector,
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
:transaction_adapter, :logger_adapter, :coordinator,
|
14
|
+
:persistence, :action_classes, :subscription_index,
|
15
|
+
:middleware, :auto_rescue, :clock, :meta, :delayed_executor, :auto_validity_check, :validity_check_timeout, :throttle_limiter,
|
16
|
+
:termination_timeout, :terminated, :dead_letter_handler, :execution_plan_cleaner
|
16
17
|
|
17
18
|
def initialize(config)
|
18
19
|
@config = Config::ForWorld.new(config, self)
|
@@ -27,14 +28,14 @@ module Dynflow
|
|
27
28
|
@config.validate
|
28
29
|
@transaction_adapter = @config.transaction_adapter
|
29
30
|
@persistence = Persistence.new(self, @config.persistence_adapter,
|
30
|
-
|
31
|
-
|
31
|
+
:backup_deleted_plans => @config.backup_deleted_plans,
|
32
|
+
:backup_dir => @config.backup_dir)
|
32
33
|
@coordinator = Coordinator.new(@config.coordinator_adapter)
|
33
34
|
if @config.executor
|
34
35
|
@executor = Executors::Parallel.new(self,
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
executor_class: @config.executor,
|
37
|
+
heartbeat_interval: @config.executor_heartbeat_interval,
|
38
|
+
queues_options: @config.queues)
|
38
39
|
end
|
39
40
|
@action_classes = @config.action_classes
|
40
41
|
@auto_rescue = @config.auto_rescue
|
@@ -86,7 +87,7 @@ module Dynflow
|
|
86
87
|
end
|
87
88
|
|
88
89
|
def update_register
|
89
|
-
@meta
|
90
|
+
@meta ||= @config.meta
|
90
91
|
@meta['queues'] = @config.queues if @executor
|
91
92
|
@meta['delayed_executor'] = true if @delayed_executor
|
92
93
|
@meta['execution_plan_cleaner'] = true if @execution_plan_cleaner
|
@@ -278,7 +279,7 @@ module Dynflow
|
|
278
279
|
def auto_execute
|
279
280
|
coordinator.acquire(Coordinator::AutoExecuteLock.new(self)) do
|
280
281
|
planned_execution_plans =
|
281
|
-
|
282
|
+
self.persistence.find_execution_plans filters: { 'state' => %w(planned paused), 'result' => (ExecutionPlan.results - [:error]).map(&:to_s) }
|
282
283
|
planned_execution_plans.map do |ep|
|
283
284
|
if coordinator.find_locks(Dynflow::Coordinator::ExecutionLock.unique_filter(ep.id)).empty?
|
284
285
|
execute(ep.id)
|
@@ -297,7 +298,7 @@ module Dynflow
|
|
297
298
|
coordinator.acquire(lock_class.new(self)) if lock_class
|
298
299
|
object.spawn.wait
|
299
300
|
object
|
300
|
-
rescue Coordinator::LockError
|
301
|
+
rescue Coordinator::LockError
|
301
302
|
nil
|
302
303
|
end
|
303
304
|
|
@@ -361,12 +362,12 @@ module Dynflow
|
|
361
362
|
|
362
363
|
def calculate_subscription_index
|
363
364
|
@subscription_index =
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
365
|
+
action_classes.each_with_object(Hash.new { |h, k| h[k] = [] }) do |klass, index|
|
366
|
+
next unless klass.subscribe
|
367
|
+
Array(klass.subscribe).each do |subscribed_class|
|
368
|
+
index[Utils.constantize(subscribed_class.to_s)] << klass
|
369
|
+
end
|
370
|
+
end.tap { |o| o.freeze }
|
370
371
|
end
|
371
372
|
|
372
373
|
def run_before_termination_hooks
|
@@ -388,6 +389,5 @@ module Dynflow
|
|
388
389
|
initialized.wait
|
389
390
|
return actor
|
390
391
|
end
|
391
|
-
|
392
392
|
end
|
393
393
|
end
|
data/lib/dynflow.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'apipie-params'
|
3
4
|
require 'algebrick'
|
4
|
-
require 'thread'
|
5
5
|
require 'set'
|
6
6
|
require 'base64'
|
7
7
|
require 'concurrent'
|
@@ -25,7 +25,7 @@ module Dynflow
|
|
25
25
|
# @return [Dynflow::World, nil]
|
26
26
|
def process_world
|
27
27
|
return @process_world if defined? @process_world
|
28
|
-
@process_world = Sidekiq.options[:dynflow_world]
|
28
|
+
@process_world = Sidekiq.configure_server { |c| c.options[:dynflow_world] }
|
29
29
|
raise "process world is not set" unless @process_world
|
30
30
|
@process_world
|
31
31
|
end
|
@@ -79,10 +79,7 @@ module Dynflow
|
|
79
79
|
|
80
80
|
class Railtie < ::Rails::Railtie
|
81
81
|
config.before_initialize do
|
82
|
-
::ActiveJob::QueueAdapters.
|
83
|
-
:include,
|
84
|
-
Dynflow::ActiveJob::QueueAdapters
|
85
|
-
)
|
82
|
+
::ActiveJob::QueueAdapters.include Dynflow::ActiveJob::QueueAdapters
|
86
83
|
end
|
87
84
|
end
|
88
85
|
end
|
@@ -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
|