dynflow 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.travis.yml +3 -4
- data/Dockerfile +9 -0
- data/Gemfile +6 -0
- data/Rakefile +1 -0
- data/doc/pages/Gemfile +1 -0
- 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 +1 -0
- data/doc/pages/plugins/plantuml.rb +1 -0
- data/doc/pages/plugins/play.rb +1 -0
- data/doc/pages/plugins/tags.rb +1 -0
- data/doc/pages/plugins/toc.rb +1 -0
- data/docker-compose.yml +41 -0
- data/dynflow.gemspec +1 -0
- data/examples/clock_benchmark.rb +1 -0
- data/examples/example_helper.rb +19 -2
- data/examples/future_execution.rb +2 -1
- data/examples/memory_limit_watcher.rb +1 -0
- data/examples/orchestrate.rb +4 -5
- data/examples/orchestrate_evented.rb +3 -2
- data/examples/remote_executor.rb +68 -0
- data/examples/singletons.rb +4 -3
- data/examples/sub_plan_concurrency_control.rb +2 -1
- data/examples/sub_plans.rb +3 -2
- data/examples/termination.rb +1 -0
- data/lib/dynflow.rb +20 -0
- data/lib/dynflow/action.rb +28 -3
- data/lib/dynflow/action/cancellable.rb +1 -0
- data/lib/dynflow/action/format.rb +1 -0
- data/lib/dynflow/action/missing.rb +1 -0
- data/lib/dynflow/action/polling.rb +3 -1
- data/lib/dynflow/action/progress.rb +1 -0
- data/lib/dynflow/action/rescue.rb +1 -0
- data/lib/dynflow/action/singleton.rb +1 -0
- data/lib/dynflow/action/suspended.rb +9 -2
- data/lib/dynflow/action/timeouts.rb +2 -1
- data/lib/dynflow/action/with_bulk_sub_plans.rb +2 -1
- data/lib/dynflow/action/with_polling_sub_plans.rb +7 -5
- data/lib/dynflow/action/with_sub_plans.rb +1 -0
- data/lib/dynflow/active_job/queue_adapter.rb +1 -0
- data/lib/dynflow/actor.rb +13 -5
- data/lib/dynflow/actors.rb +1 -0
- data/lib/dynflow/actors/execution_plan_cleaner.rb +1 -0
- data/lib/dynflow/clock.rb +27 -47
- data/lib/dynflow/config.rb +11 -2
- data/lib/dynflow/connectors.rb +1 -0
- data/lib/dynflow/connectors/abstract.rb +1 -0
- data/lib/dynflow/connectors/database.rb +1 -0
- data/lib/dynflow/connectors/direct.rb +1 -0
- data/lib/dynflow/coordinator.rb +1 -0
- data/lib/dynflow/coordinator_adapters.rb +1 -0
- data/lib/dynflow/coordinator_adapters/abstract.rb +1 -0
- data/lib/dynflow/coordinator_adapters/sequel.rb +1 -0
- data/lib/dynflow/dead_letter_silencer.rb +2 -0
- data/lib/dynflow/debug/telemetry/persistence.rb +1 -0
- data/lib/dynflow/delayed_executors.rb +1 -0
- data/lib/dynflow/delayed_executors/abstract.rb +1 -0
- data/lib/dynflow/delayed_executors/abstract_core.rb +1 -0
- data/lib/dynflow/delayed_executors/polling.rb +1 -0
- data/lib/dynflow/delayed_plan.rb +1 -0
- data/lib/dynflow/director.rb +80 -15
- data/lib/dynflow/director/execution_plan_manager.rb +17 -3
- data/lib/dynflow/director/flow_manager.rb +1 -0
- data/lib/dynflow/director/{work_queue.rb → queue_hash.rb} +9 -8
- data/lib/dynflow/director/running_steps_manager.rb +55 -18
- data/lib/dynflow/director/sequence_cursor.rb +1 -0
- data/lib/dynflow/director/sequential_manager.rb +12 -2
- data/lib/dynflow/dispatcher.rb +4 -2
- data/lib/dynflow/dispatcher/abstract.rb +1 -0
- data/lib/dynflow/dispatcher/client_dispatcher.rb +6 -4
- data/lib/dynflow/dispatcher/executor_dispatcher.rb +13 -1
- data/lib/dynflow/errors.rb +1 -0
- data/lib/dynflow/execution_history.rb +1 -0
- data/lib/dynflow/execution_plan.rb +3 -2
- data/lib/dynflow/execution_plan/dependency_graph.rb +1 -0
- data/lib/dynflow/execution_plan/hooks.rb +1 -0
- data/lib/dynflow/execution_plan/output_reference.rb +2 -1
- data/lib/dynflow/execution_plan/steps.rb +1 -0
- data/lib/dynflow/execution_plan/steps/abstract.rb +10 -5
- data/lib/dynflow/execution_plan/steps/abstract_flow_step.rb +2 -0
- data/lib/dynflow/execution_plan/steps/error.rb +1 -0
- data/lib/dynflow/execution_plan/steps/finalize_step.rb +1 -0
- data/lib/dynflow/execution_plan/steps/plan_step.rb +1 -0
- data/lib/dynflow/execution_plan/steps/run_step.rb +1 -0
- data/lib/dynflow/executors.rb +1 -1
- data/lib/dynflow/executors/abstract/core.rb +132 -0
- data/lib/dynflow/executors/parallel.rb +24 -11
- data/lib/dynflow/executors/parallel/core.rb +10 -91
- data/lib/dynflow/executors/parallel/pool.rb +4 -2
- data/lib/dynflow/executors/parallel/worker.rb +2 -1
- data/lib/dynflow/executors/sidekiq/core.rb +121 -0
- data/lib/dynflow/executors/sidekiq/internal_job_base.rb +24 -0
- data/lib/dynflow/executors/sidekiq/orchestrator_jobs.rb +60 -0
- data/lib/dynflow/executors/sidekiq/redis_locking.rb +69 -0
- data/lib/dynflow/executors/sidekiq/serialization.rb +33 -0
- data/lib/dynflow/executors/sidekiq/worker_jobs.rb +42 -0
- data/lib/dynflow/flows.rb +1 -0
- data/lib/dynflow/flows/abstract.rb +1 -0
- data/lib/dynflow/flows/abstract_composed.rb +1 -0
- data/lib/dynflow/flows/atom.rb +1 -0
- data/lib/dynflow/flows/concurrence.rb +1 -0
- data/lib/dynflow/flows/sequence.rb +1 -0
- data/lib/dynflow/logger_adapters.rb +1 -0
- data/lib/dynflow/logger_adapters/abstract.rb +1 -0
- data/lib/dynflow/logger_adapters/delegator.rb +1 -0
- data/lib/dynflow/logger_adapters/formatters.rb +1 -0
- 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/simple.rb +1 -0
- data/lib/dynflow/middleware.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 +1 -0
- data/lib/dynflow/middleware/stack.rb +1 -0
- data/lib/dynflow/middleware/world.rb +1 -0
- data/lib/dynflow/persistence.rb +3 -2
- data/lib/dynflow/persistence_adapters.rb +1 -0
- data/lib/dynflow/persistence_adapters/abstract.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel.rb +10 -7
- data/lib/dynflow/persistence_adapters/sequel_migrations/001_initial.rb +1 -0
- 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 -0
- 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 -0
- 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 +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/019_update_mysql_time_precision.rb +48 -0
- data/lib/dynflow/rails.rb +1 -0
- data/lib/dynflow/rails/configuration.rb +6 -3
- data/lib/dynflow/rails/daemon.rb +1 -0
- data/lib/dynflow/round_robin.rb +1 -0
- data/lib/dynflow/semaphores.rb +1 -0
- data/lib/dynflow/semaphores/abstract.rb +1 -0
- data/lib/dynflow/semaphores/aggregating.rb +1 -0
- data/lib/dynflow/semaphores/dummy.rb +1 -0
- data/lib/dynflow/semaphores/stateful.rb +1 -0
- data/lib/dynflow/serializable.rb +13 -4
- data/lib/dynflow/serializer.rb +24 -0
- data/lib/dynflow/serializers.rb +1 -0
- data/lib/dynflow/serializers/abstract.rb +1 -0
- data/lib/dynflow/serializers/noop.rb +1 -0
- data/lib/dynflow/stateful.rb +1 -0
- data/lib/dynflow/telemetry.rb +1 -0
- 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 +1 -0
- data/lib/dynflow/testing.rb +1 -0
- data/lib/dynflow/testing/assertions.rb +6 -5
- data/lib/dynflow/testing/dummy_execution_plan.rb +1 -0
- data/lib/dynflow/testing/dummy_executor.rb +19 -2
- data/lib/dynflow/testing/dummy_planned_action.rb +1 -0
- data/lib/dynflow/testing/dummy_step.rb +3 -1
- data/lib/dynflow/testing/dummy_world.rb +9 -0
- data/lib/dynflow/testing/factories.rb +6 -1
- data/lib/dynflow/testing/in_thread_executor.rb +22 -3
- data/lib/dynflow/testing/in_thread_world.rb +9 -0
- data/lib/dynflow/testing/managed_clock.rb +1 -0
- data/lib/dynflow/testing/mimic.rb +1 -0
- data/lib/dynflow/throttle_limiter.rb +1 -0
- data/lib/dynflow/transaction_adapters.rb +1 -0
- 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/utils.rb +1 -0
- data/lib/dynflow/utils/indifferent_hash.rb +1 -0
- data/lib/dynflow/utils/priority_queue.rb +1 -0
- data/lib/dynflow/version.rb +2 -1
- data/lib/dynflow/watchers/memory_consumption_watcher.rb +1 -0
- data/lib/dynflow/web.rb +1 -0
- data/lib/dynflow/web/console.rb +1 -0
- data/lib/dynflow/web/console_helpers.rb +1 -0
- data/lib/dynflow/web/filtering_helpers.rb +1 -0
- data/lib/dynflow/web/world_helpers.rb +1 -0
- data/lib/dynflow/web_console.rb +1 -0
- data/lib/dynflow/world.rb +11 -1
- data/lib/dynflow/world/invalidation.rb +7 -1
- data/test/abnormal_states_recovery_test.rb +41 -40
- data/test/action_test.rb +160 -110
- data/test/activejob_adapter_test.rb +1 -0
- data/test/batch_sub_tasks_test.rb +12 -11
- data/test/clock_test.rb +2 -1
- data/test/concurrency_control_test.rb +20 -19
- data/test/coordinator_test.rb +20 -21
- data/test/daemon_test.rb +2 -1
- data/test/dead_letter_silencer_test.rb +9 -7
- data/test/dispatcher_test.rb +2 -1
- data/test/execution_plan_cleaner_test.rb +13 -12
- data/test/execution_plan_hooks_test.rb +3 -2
- data/test/execution_plan_test.rb +33 -32
- data/test/executor_test.rb +533 -489
- data/test/future_execution_test.rb +45 -44
- data/test/memory_cosumption_watcher_test.rb +5 -4
- data/test/middleware_test.rb +55 -54
- data/test/persistence_test.rb +56 -53
- data/test/rescue_test.rb +36 -35
- data/test/round_robin_test.rb +13 -12
- data/test/semaphores_test.rb +31 -30
- data/test/support/code_workflow_example.rb +1 -0
- data/test/support/dummy_example.rb +14 -1
- data/test/support/middleware_example.rb +2 -1
- data/test/support/rails/config/environment.rb +1 -0
- data/test/support/rescue_example.rb +1 -0
- data/test/support/test_execution_log.rb +1 -0
- data/test/test_helper.rb +18 -17
- data/test/testing_test.rb +45 -44
- data/test/utils_test.rb +18 -17
- data/test/web_console_test.rb +1 -0
- data/test/world_test.rb +7 -6
- metadata +13 -4
- data/lib/dynflow/executors/abstract.rb +0 -40
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require_relative 'test_helper'
|
2
3
|
|
3
4
|
module Dynflow
|
@@ -72,7 +73,7 @@ module Dynflow
|
|
72
73
|
plan = world.persistence.load_execution_plan(plan.id)
|
73
74
|
action = plan.entry_action
|
74
75
|
|
75
|
-
action.output[:batch_count].must_equal action.total_count / action.batch_size
|
76
|
+
_(action.output[:batch_count]).must_equal action.total_count / action.batch_size
|
76
77
|
end
|
77
78
|
|
78
79
|
it 'can resume tasks' do
|
@@ -82,17 +83,17 @@ module Dynflow
|
|
82
83
|
wait_for { future.resolved? }
|
83
84
|
plan = world.persistence.load_execution_plan(plan.id)
|
84
85
|
action = plan.entry_action
|
85
|
-
action.output[:batch_count].must_equal 1
|
86
|
-
future.value.state.must_equal :paused
|
86
|
+
_(action.output[:batch_count]).must_equal 1
|
87
|
+
_(future.value.state).must_equal :paused
|
87
88
|
|
88
89
|
FailureSimulator.wont_fail!
|
89
90
|
future = world.execute plan.id
|
90
91
|
wait_for { future.resolved? }
|
91
92
|
action = future.value.entry_action
|
92
|
-
future.value.state.must_equal :stopped
|
93
|
-
action.output[:batch_count].must_equal (action.total_count / action.batch_size) + 1
|
94
|
-
action.output[:total_count].must_equal action.total_count
|
95
|
-
action.output[:success_count].must_equal action.total_count
|
93
|
+
_(future.value.state).must_equal :stopped
|
94
|
+
_(action.output[:batch_count]).must_equal (action.total_count / action.batch_size) + 1
|
95
|
+
_(action.output[:total_count]).must_equal action.total_count
|
96
|
+
_(action.output[:success_count]).must_equal action.total_count
|
96
97
|
end
|
97
98
|
|
98
99
|
it 'is controlled only by total_count and output[:planned_count]' do
|
@@ -101,12 +102,12 @@ module Dynflow
|
|
101
102
|
wait_for { future.resolved? }
|
102
103
|
plan = world.persistence.load_execution_plan(plan.id)
|
103
104
|
action = plan.entry_action
|
104
|
-
action.send(:can_spawn_next_batch?).must_equal false
|
105
|
-
action.current_batch.must_be :empty?
|
105
|
+
_(action.send(:can_spawn_next_batch?)).must_equal false
|
106
|
+
_(action.current_batch).must_be :empty?
|
106
107
|
action.output[:pending_count] = 0
|
107
108
|
action.output[:success_count] = 5
|
108
|
-
action.send(:can_spawn_next_batch?).must_equal false
|
109
|
-
action.current_batch.must_be :empty?
|
109
|
+
_(action.send(:can_spawn_next_batch?)).must_equal false
|
110
|
+
_(action.current_batch).must_be :empty?
|
110
111
|
end
|
111
112
|
|
112
113
|
end
|
data/test/clock_test.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require_relative 'test_helper'
|
2
3
|
require 'logger'
|
3
4
|
|
@@ -8,7 +9,7 @@ describe clock_class do
|
|
8
9
|
let(:clock) { clock_class.spawn 'clock' }
|
9
10
|
|
10
11
|
it 'refuses who without #<< method' do
|
11
|
-
-> { clock.ping Object.new, 0.1, :pong }.must_raise TypeError
|
12
|
+
_(-> { clock.ping Object.new, 0.1, :pong }).must_raise TypeError
|
12
13
|
clock.ping [], 0.1, :pong
|
13
14
|
end
|
14
15
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require_relative 'test_helper'
|
2
3
|
|
3
4
|
module Dynflow
|
@@ -80,9 +81,9 @@ module Dynflow
|
|
80
81
|
end
|
81
82
|
|
82
83
|
def check_step(plan, total, finished)
|
83
|
-
world.throttle_limiter.observe(plan.id).length.must_equal (total - finished)
|
84
|
-
plan.sub_plans.select { |sub| planned? sub }.count.must_equal (total - finished)
|
85
|
-
plan.sub_plans.select { |sub| successful? sub }.count.must_equal finished
|
84
|
+
_(world.throttle_limiter.observe(plan.id).length).must_equal (total - finished)
|
85
|
+
_(plan.sub_plans.select { |sub| planned? sub }.count).must_equal (total - finished)
|
86
|
+
_(plan.sub_plans.select { |sub| successful? sub }.count).must_equal finished
|
86
87
|
end
|
87
88
|
|
88
89
|
def planned?(plan)
|
@@ -126,7 +127,7 @@ module Dynflow
|
|
126
127
|
future = world.execute plan.id
|
127
128
|
wait_for { future.resolved? }
|
128
129
|
plan.sub_plans.all? { |sub| successful? sub }
|
129
|
-
world.throttle_limiter.core.ask!(:running).must_equal [0]
|
130
|
+
_(world.throttle_limiter.core.ask!(:running)).must_equal [0]
|
130
131
|
end
|
131
132
|
|
132
133
|
it 'limits by concurrency level' do
|
@@ -135,7 +136,7 @@ module Dynflow
|
|
135
136
|
plan = world.plan(ParentAction, total, level)
|
136
137
|
future = world.execute plan.id
|
137
138
|
wait_for { future.resolved? }
|
138
|
-
world.throttle_limiter.core.ask!(:running).max.must_be :<=, level
|
139
|
+
_(world.throttle_limiter.core.ask!(:running).max).must_be :<=, level
|
139
140
|
end
|
140
141
|
|
141
142
|
it 'allows to cancel' do
|
@@ -147,8 +148,8 @@ module Dynflow
|
|
147
148
|
world.event(plan.id, plan.steps.values.last.id, ::Dynflow::Action::Cancellable::Cancel)
|
148
149
|
wait_for { triggered.resolved? }
|
149
150
|
plan = world.persistence.load_execution_plan(plan.id)
|
150
|
-
plan.entry_action.output[:failed_count].must_equal total
|
151
|
-
world.throttle_limiter.core.ask!(:running).max.must_be :<=, 0
|
151
|
+
_(plan.entry_action.output[:failed_count]).must_equal total
|
152
|
+
_(world.throttle_limiter.core.ask!(:running).max).must_be :<=, 0
|
152
153
|
end
|
153
154
|
end
|
154
155
|
|
@@ -165,21 +166,21 @@ module Dynflow
|
|
165
166
|
wait_for { plan.sub_plans_count == total }
|
166
167
|
wait_for { klok.progress; plan.sub_plans.all? { |sub| successful? sub } }
|
167
168
|
# 10 tasks over 10 seconds, one task at a time, 1 task every second
|
168
|
-
get_interval.call(plan).must_equal 1.0
|
169
|
+
_(get_interval.call(plan)).must_equal 1.0
|
169
170
|
|
170
171
|
plan = world.plan(ParentAction, total, 4, 10)
|
171
172
|
world.execute(plan.id)
|
172
173
|
wait_for { plan.sub_plans_count == total }
|
173
174
|
wait_for { klok.progress; plan.sub_plans.all? { |sub| successful? sub } }
|
174
175
|
# 10 tasks over 10 seconds, four tasks at a time, 1 task every 0.25 second
|
175
|
-
get_interval.call(plan).must_equal 0.25
|
176
|
+
_(get_interval.call(plan)).must_equal 0.25
|
176
177
|
|
177
178
|
plan = world.plan(ParentAction, total, nil, 10)
|
178
179
|
world.execute(plan.id)
|
179
180
|
wait_for { plan.sub_plans_count == total }
|
180
181
|
wait_for { klok.progress; plan.sub_plans.all? { |sub| successful? sub } }
|
181
182
|
# 1o tasks over 10 seconds, one task at a time (default), 1 task every second
|
182
|
-
get_interval.call(plan).must_equal 1.0
|
183
|
+
_(get_interval.call(plan)).must_equal 1.0
|
183
184
|
end
|
184
185
|
end
|
185
186
|
|
@@ -204,9 +205,9 @@ module Dynflow
|
|
204
205
|
check_step(plan, total, finished)
|
205
206
|
end
|
206
207
|
end_time = klok.current_time
|
207
|
-
(end_time - start_time).must_equal 4
|
208
|
-
world.throttle_limiter.observe(plan.id).must_equal []
|
209
|
-
world.throttle_limiter.core.ask!(:running).max.must_be :<=, level
|
208
|
+
_((end_time - start_time)).must_equal 4
|
209
|
+
_(world.throttle_limiter.observe(plan.id)).must_equal []
|
210
|
+
_(world.throttle_limiter.core.ask!(:running).max).must_be :<=, level
|
210
211
|
end
|
211
212
|
end
|
212
213
|
|
@@ -218,7 +219,7 @@ module Dynflow
|
|
218
219
|
plan = world.plan(ParentAction, total, level, time_span)
|
219
220
|
future = world.execute(plan.id)
|
220
221
|
wait_for { future.resolved? }
|
221
|
-
plan.sub_plans.all? { |sub| sub.result == :error }.must_equal true
|
222
|
+
_(plan.sub_plans.all? { |sub| sub.result == :error }).must_equal true
|
222
223
|
end
|
223
224
|
|
224
225
|
it 'cancels tasks which could not be started within the time window' do
|
@@ -230,14 +231,14 @@ module Dynflow
|
|
230
231
|
future = world.execute(plan.id)
|
231
232
|
wait_for { plan.sub_plans_count == total && plan.sub_plans.all? { |sub| sub.result == :pending } }
|
232
233
|
planned, running = plan.sub_plans.partition { |sub| planned? sub }
|
233
|
-
planned.count.must_equal total - level
|
234
|
-
running.count.must_equal level
|
235
|
-
world.throttle_limiter.observe(plan.id).length.must_equal (total - 1)
|
234
|
+
_(planned.count).must_equal total - level
|
235
|
+
_(running.count).must_equal level
|
236
|
+
_(world.throttle_limiter.observe(plan.id).length).must_equal (total - 1)
|
236
237
|
4.times { klok.progress }
|
237
238
|
wait_for { future.resolved? }
|
238
239
|
finished, stopped = plan.sub_plans.partition { |sub| successful? sub }
|
239
|
-
finished.count.must_equal level
|
240
|
-
stopped.count.must_equal (total - level)
|
240
|
+
_(finished.count).must_equal level
|
241
|
+
_(stopped.count).must_equal (total - level)
|
241
242
|
end
|
242
243
|
end
|
243
244
|
end
|
data/test/coordinator_test.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require_relative 'test_helper'
|
2
3
|
require 'fileutils'
|
3
4
|
|
@@ -11,13 +12,13 @@ module Dynflow
|
|
11
12
|
it 'unlocks the lock, when the block is passed' do
|
12
13
|
world.coordinator.acquire(Coordinator::AutoExecuteLock.new(world)) {}
|
13
14
|
expected_locks = ["lock auto-execute", "unlock auto-execute"]
|
14
|
-
world.coordinator.adapter.lock_log.must_equal(expected_locks)
|
15
|
+
_(world.coordinator.adapter.lock_log).must_equal(expected_locks)
|
15
16
|
end
|
16
17
|
|
17
18
|
it "doesn't unlock, when the block is not passed" do
|
18
19
|
world.coordinator.acquire(Coordinator::AutoExecuteLock.new(world))
|
19
20
|
expected_locks = ["lock auto-execute"]
|
20
|
-
world.coordinator.adapter.lock_log.must_equal(expected_locks)
|
21
|
+
_(world.coordinator.adapter.lock_log).must_equal(expected_locks)
|
21
22
|
end
|
22
23
|
|
23
24
|
it 'supports unlocking by owner' do
|
@@ -35,23 +36,23 @@ module Dynflow
|
|
35
36
|
it 'supports checking about locks' do
|
36
37
|
world.coordinator.acquire(Coordinator::AutoExecuteLock.new(world))
|
37
38
|
locks = world.coordinator.find_locks(Coordinator::AutoExecuteLock.unique_filter)
|
38
|
-
locks.map(&:world_id).must_equal([world.id])
|
39
|
+
_(locks.map(&:world_id)).must_equal([world.id])
|
39
40
|
end
|
40
41
|
|
41
42
|
it 'deserializes the data from the adapter when searching for locks' do
|
42
43
|
lock = Coordinator::AutoExecuteLock.new(world)
|
43
44
|
world.coordinator.acquire(lock)
|
44
45
|
found_locks = world.coordinator.find_locks(owner_id: lock.owner_id)
|
45
|
-
found_locks.size.must_equal 1
|
46
|
-
found_locks.first.data.must_equal lock.data
|
46
|
+
_(found_locks.size).must_equal 1
|
47
|
+
_(found_locks.first.data).must_equal lock.data
|
47
48
|
|
48
49
|
found_locks = world.coordinator.find_locks(class: lock.class.name, id: lock.id)
|
49
|
-
found_locks.size.must_equal 1
|
50
|
-
found_locks.first.data.must_equal lock.data
|
50
|
+
_(found_locks.size).must_equal 1
|
51
|
+
_(found_locks.first.data).must_equal lock.data
|
51
52
|
|
52
53
|
another_lock = Coordinator::AutoExecuteLock.new(another_world)
|
53
54
|
found_locks = world.coordinator.find_locks(owner_id: another_lock.owner_id)
|
54
|
-
found_locks.size.must_equal 0
|
55
|
+
_(found_locks.size).must_equal 0
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
@@ -76,15 +77,15 @@ module Dynflow
|
|
76
77
|
dummy_record = DummyRecord.new('dummy', 'Foo')
|
77
78
|
world.coordinator.create_record(dummy_record)
|
78
79
|
saved_dummy_record = world.coordinator.find_records(class: dummy_record.class.name).first
|
79
|
-
saved_dummy_record.must_equal dummy_record
|
80
|
+
_(saved_dummy_record).must_equal dummy_record
|
80
81
|
|
81
82
|
dummy_record.value = 'Bar'
|
82
83
|
world.coordinator.update_record(dummy_record)
|
83
84
|
saved_dummy_record = world.coordinator.find_records(class: dummy_record.class.name).first
|
84
|
-
saved_dummy_record.data.must_equal dummy_record.data
|
85
|
+
_(saved_dummy_record.data).must_equal dummy_record.data
|
85
86
|
|
86
87
|
world.coordinator.delete_record(dummy_record)
|
87
|
-
world.coordinator.find_records(class: dummy_record.class.name).must_equal []
|
88
|
+
_(world.coordinator.find_records(class: dummy_record.class.name)).must_equal []
|
88
89
|
end
|
89
90
|
end
|
90
91
|
|
@@ -94,14 +95,12 @@ module Dynflow
|
|
94
95
|
another_world.coordinator.acquire Coordinator::WorldInvalidationLock.new(another_world, another_world)
|
95
96
|
world.terminate.wait
|
96
97
|
expected_locks = ["lock auto-execute", "unlock auto-execute"]
|
97
|
-
world.coordinator.adapter.lock_log.must_equal(expected_locks)
|
98
|
+
_(world.coordinator.adapter.lock_log).must_equal(expected_locks)
|
98
99
|
end
|
99
100
|
|
100
101
|
it 'prevents new locks to be acquired by the world being terminated' do
|
101
102
|
world.terminate
|
102
|
-
->
|
103
|
-
world.coordinator.acquire(Coordinator::AutoExecuteLock.new(world))
|
104
|
-
end.must_raise(Errors::InactiveWorldError)
|
103
|
+
_(-> { world.coordinator.acquire(Coordinator::AutoExecuteLock.new(world)) }).must_raise(Errors::InactiveWorldError)
|
105
104
|
end
|
106
105
|
end
|
107
106
|
|
@@ -114,7 +113,7 @@ module Dynflow
|
|
114
113
|
adapter.create_record(record)
|
115
114
|
tester.pause
|
116
115
|
end
|
117
|
-
-> { another_adapter.create_record(record) }.must_raise(Coordinator::DuplicateRecordError)
|
116
|
+
_(-> { another_adapter.create_record(record) }).must_raise(Coordinator::DuplicateRecordError)
|
118
117
|
tester.finish
|
119
118
|
end
|
120
119
|
|
@@ -134,16 +133,16 @@ module Dynflow
|
|
134
133
|
lock = Coordinator::AutoExecuteLock.new(world)
|
135
134
|
adapter.create_record(lock)
|
136
135
|
found_records = adapter.find_records(owner_id: lock.owner_id)
|
137
|
-
found_records.size.must_equal 1
|
138
|
-
found_records.first.must_equal lock.data
|
136
|
+
_(found_records.size).must_equal 1
|
137
|
+
_(found_records.first).must_equal lock.data
|
139
138
|
|
140
139
|
found_records = adapter.find_records(class: lock.class.name, id: lock.id)
|
141
|
-
found_records.size.must_equal 1
|
142
|
-
found_records.first.must_equal lock.data
|
140
|
+
_(found_records.size).must_equal 1
|
141
|
+
_(found_records.first).must_equal lock.data
|
143
142
|
|
144
143
|
another_lock = Coordinator::AutoExecuteLock.new(another_world)
|
145
144
|
found_records = adapter.find_records(owner_id: another_lock.owner_id)
|
146
|
-
found_records.size.must_equal 0
|
145
|
+
_(found_records.size).must_equal 0
|
147
146
|
end
|
148
147
|
end
|
149
148
|
end
|
data/test/daemon_test.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require_relative 'test_helper'
|
2
3
|
require 'ostruct'
|
3
4
|
|
@@ -10,7 +11,7 @@ module Dynflow
|
|
10
11
|
let(:world) { WorldFactory.create_world }
|
11
12
|
|
12
13
|
it 'is started for each world' do
|
13
|
-
world.dead_letter_handler.actor_class
|
14
|
+
_(world.dead_letter_handler.actor_class)
|
14
15
|
.must_equal ::Dynflow::DeadLetterSilencer
|
15
16
|
end
|
16
17
|
|
@@ -26,19 +27,20 @@ module Dynflow
|
|
26
27
|
end
|
27
28
|
|
28
29
|
it 'matches any' do
|
29
|
-
DeadLetterSilencer::Matcher.new(any, any, any).match?(letter).must_equal true
|
30
|
+
_(DeadLetterSilencer::Matcher.new(any, any, any).match?(letter)).must_equal true
|
30
31
|
end
|
31
32
|
|
32
33
|
it 'matches comparing for equality' do
|
33
|
-
DeadLetterSilencer::Matcher.new(sender, msg, receiver)
|
34
|
-
|
35
|
-
DeadLetterSilencer::Matcher.new(any, :bad, any)
|
34
|
+
matcher = DeadLetterSilencer::Matcher.new(sender, msg, receiver)
|
35
|
+
_(matcher.match?(letter)).must_equal true
|
36
|
+
matcher = DeadLetterSilencer::Matcher.new(any, :bad, any)
|
37
|
+
_(matcher.match?(letter)).must_equal false
|
36
38
|
end
|
37
39
|
|
38
40
|
it 'matches by calling the proc' do
|
39
41
|
condition = proc { |actor_class| actor_class.is_a? Class }
|
40
|
-
DeadLetterSilencer::Matcher.new(condition, any, condition)
|
41
|
-
|
42
|
+
matcher = DeadLetterSilencer::Matcher.new(condition, any, condition)
|
43
|
+
_(matcher.match?(letter)).must_equal true
|
42
44
|
end
|
43
45
|
end
|
44
46
|
end
|
data/test/dispatcher_test.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require_relative 'test_helper'
|
2
3
|
|
3
4
|
module Dynflow
|
@@ -24,7 +25,7 @@ module Dynflow
|
|
24
25
|
|
25
26
|
describe 'event passing' do
|
26
27
|
it 'succeeds when expected' do
|
27
|
-
result = client_world.trigger(Support::DummyExample::
|
28
|
+
result = client_world.trigger(Support::DummyExample::DeprecatedEventedAction, :timeout => 3)
|
28
29
|
step = wait_for do
|
29
30
|
client_world.persistence.load_execution_plan(result.id).
|
30
31
|
steps_in_state(:suspended).first
|
@@ -1,5 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require_relative 'test_helper'
|
2
|
-
require 'mocha/
|
3
|
+
require 'mocha/minitest'
|
3
4
|
|
4
5
|
module Dynflow
|
5
6
|
module ExecutionPlanCleanerTest
|
@@ -28,16 +29,16 @@ module Dynflow
|
|
28
29
|
let(:clock) { Testing::ManagedClock.new }
|
29
30
|
|
30
31
|
it 'is disabled by default' do
|
31
|
-
default_world.execution_plan_cleaner
|
32
|
-
world.execution_plan_cleaner
|
33
|
-
|
32
|
+
assert_nil default_world.execution_plan_cleaner
|
33
|
+
_(world.execution_plan_cleaner)
|
34
|
+
.must_be_instance_of ::Dynflow::Actors::ExecutionPlanCleaner
|
34
35
|
end
|
35
36
|
|
36
37
|
it 'periodically looks for old execution plans' do
|
37
38
|
world.stub(:clock, clock) do
|
38
|
-
clock.pending_pings.count.must_equal 0
|
39
|
+
_(clock.pending_pings.count).must_equal 0
|
39
40
|
world.execution_plan_cleaner.core.ask!(:start)
|
40
|
-
clock.pending_pings.count.must_equal 1
|
41
|
+
_(clock.pending_pings.count).must_equal 1
|
41
42
|
world.persistence.expects(:find_old_execution_plans).returns([])
|
42
43
|
world.persistence.expects(:delete_execution_plans).with(:uuid => [])
|
43
44
|
clock.progress
|
@@ -48,7 +49,7 @@ module Dynflow
|
|
48
49
|
it 'cleans up old plans' do
|
49
50
|
world.stub(:clock, clock) do
|
50
51
|
world.execution_plan_cleaner.core.ask!(:start)
|
51
|
-
clock.pending_pings.count.must_equal 1
|
52
|
+
_(clock.pending_pings.count).must_equal 1
|
52
53
|
plans = (1..10).map { world.trigger SimpleAction }
|
53
54
|
.each { |plan| plan.finished.wait }
|
54
55
|
world.persistence.find_execution_plans(:uuid => plans.map(&:id))
|
@@ -57,8 +58,8 @@ module Dynflow
|
|
57
58
|
plan.save
|
58
59
|
end
|
59
60
|
world.execution_plan_cleaner.core.ask!(:clean!)
|
60
|
-
world.persistence.find_execution_plans(:uuid => plans.map(&:id))
|
61
|
-
|
61
|
+
plans = world.persistence.find_execution_plans(:uuid => plans.map(&:id))
|
62
|
+
_(plans.count).must_equal 0
|
62
63
|
end
|
63
64
|
end
|
64
65
|
|
@@ -66,12 +67,12 @@ module Dynflow
|
|
66
67
|
world.stub(:clock, clock) do
|
67
68
|
count = 10
|
68
69
|
world.execution_plan_cleaner.core.ask!(:start)
|
69
|
-
clock.pending_pings.count.must_equal 1
|
70
|
+
_(clock.pending_pings.count).must_equal 1
|
70
71
|
plans = (1..10).map { world.trigger SimpleAction }
|
71
72
|
.each { |plan| plan.finished.wait }
|
72
73
|
world.execution_plan_cleaner.core.ask!(:clean!)
|
73
|
-
world.persistence.find_execution_plans(:uuid => plans.map(&:id))
|
74
|
-
|
74
|
+
plans = world.persistence.find_execution_plans(:uuid => plans.map(&:id))
|
75
|
+
_(plans.count).must_equal count
|
75
76
|
end
|
76
77
|
end
|
77
78
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require_relative 'test_helper'
|
2
3
|
|
3
4
|
module Dynflow
|
@@ -137,7 +138,7 @@ module Dynflow
|
|
137
138
|
plan = world.plan(ActionOnStop)
|
138
139
|
plan = world.execute(plan.id).wait!.value
|
139
140
|
assert Flag.raised?
|
140
|
-
plan.result.must_equal :success
|
141
|
+
_(plan.result).must_equal :success
|
141
142
|
end
|
142
143
|
|
143
144
|
it 'inherits the hooks when subclassing' do
|
@@ -158,7 +159,7 @@ module Dynflow
|
|
158
159
|
refute Flag.raised?
|
159
160
|
plan = world.trigger(ComposedAction)
|
160
161
|
plan.finished.wait!
|
161
|
-
Flag.raised_count.must_equal 1
|
162
|
+
_(Flag.raised_count).must_equal 1
|
162
163
|
end
|
163
164
|
end
|
164
165
|
end
|