dynflow 1.8.2 → 1.8.4
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 +21 -9
- 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 +9 -1
- data/lib/dynflow/world.rb +20 -20
- 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
|
|
@@ -343,7 +344,7 @@ module Dynflow
|
|
343
344
|
clock.ask(:terminate!).wait(termination_timeout)
|
344
345
|
end
|
345
346
|
|
346
|
-
coordinator.delete_world(registered_world)
|
347
|
+
coordinator.delete_world(registered_world, true)
|
347
348
|
@terminated.resolve
|
348
349
|
true
|
349
350
|
rescue => e
|
@@ -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.configure_server { |c| c
|
28
|
+
@process_world = Sidekiq.configure_server { |c| c[: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
|