dynflow 1.8.2 → 1.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (233) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -1
  3. data/.rubocop.yml +11 -5
  4. data/.rubocop_todo.yml +777 -345
  5. data/Gemfile +4 -3
  6. data/Rakefile +1 -0
  7. data/doc/pages/Gemfile +4 -3
  8. data/doc/pages/Rakefile +1 -0
  9. data/doc/pages/plugins/alert_block.rb +1 -0
  10. data/doc/pages/plugins/div_tag.rb +1 -0
  11. data/doc/pages/plugins/graphviz.rb +6 -6
  12. data/doc/pages/plugins/plantuml.rb +2 -3
  13. data/doc/pages/plugins/play.rb +1 -2
  14. data/doc/pages/plugins/tags.rb +2 -8
  15. data/doc/pages/plugins/toc.rb +1 -1
  16. data/dynflow.gemspec +11 -10
  17. data/examples/clock_benchmark.rb +1 -0
  18. data/examples/example_helper.rb +4 -3
  19. data/examples/future_execution.rb +0 -2
  20. data/examples/memory_limit_watcher.rb +8 -8
  21. data/examples/orchestrate.rb +9 -21
  22. data/examples/orchestrate_evented.rb +18 -33
  23. data/examples/remote_executor.rb +9 -11
  24. data/examples/singletons.rb +1 -0
  25. data/examples/sub_plan_concurrency_control.rb +0 -1
  26. data/examples/sub_plans.rb +1 -0
  27. data/examples/sub_plans_v2.rb +1 -0
  28. data/lib/dynflow/action/cancellable.rb +1 -0
  29. data/lib/dynflow/action/format.rb +1 -4
  30. data/lib/dynflow/action/missing.rb +4 -4
  31. data/lib/dynflow/action/polling.rb +2 -3
  32. data/lib/dynflow/action/progress.rb +1 -4
  33. data/lib/dynflow/action/rescue.rb +1 -2
  34. data/lib/dynflow/action/singleton.rb +1 -0
  35. data/lib/dynflow/action/suspended.rb +1 -0
  36. data/lib/dynflow/action/timeouts.rb +2 -1
  37. data/lib/dynflow/action/with_bulk_sub_plans.rb +1 -0
  38. data/lib/dynflow/action/with_polling_sub_plans.rb +1 -1
  39. data/lib/dynflow/action/with_sub_plans.rb +20 -19
  40. data/lib/dynflow/action.rb +37 -37
  41. data/lib/dynflow/active_job/queue_adapter.rb +2 -1
  42. data/lib/dynflow/actor.rb +2 -2
  43. data/lib/dynflow/actors/execution_plan_cleaner.rb +1 -0
  44. data/lib/dynflow/actors.rb +1 -0
  45. data/lib/dynflow/clock.rb +3 -4
  46. data/lib/dynflow/config.rb +6 -5
  47. data/lib/dynflow/connectors/abstract.rb +11 -10
  48. data/lib/dynflow/connectors/database.rb +2 -2
  49. data/lib/dynflow/connectors/direct.rb +2 -3
  50. data/lib/dynflow/connectors.rb +1 -0
  51. data/lib/dynflow/coordinator.rb +21 -9
  52. data/lib/dynflow/coordinator_adapters/abstract.rb +1 -0
  53. data/lib/dynflow/coordinator_adapters/sequel.rb +1 -0
  54. data/lib/dynflow/coordinator_adapters.rb +1 -2
  55. data/lib/dynflow/dead_letter_silencer.rb +1 -0
  56. data/lib/dynflow/debug/telemetry/persistence.rb +3 -2
  57. data/lib/dynflow/delayed_executors/abstract.rb +1 -2
  58. data/lib/dynflow/delayed_executors/abstract_core.rb +1 -1
  59. data/lib/dynflow/delayed_executors/polling.rb +1 -2
  60. data/lib/dynflow/delayed_executors.rb +1 -2
  61. data/lib/dynflow/delayed_plan.rb +6 -6
  62. data/lib/dynflow/director/execution_plan_manager.rb +1 -1
  63. data/lib/dynflow/director/flow_manager.rb +1 -0
  64. data/lib/dynflow/director/queue_hash.rb +2 -1
  65. data/lib/dynflow/director/running_steps_manager.rb +3 -2
  66. data/lib/dynflow/director/sequence_cursor.rb +1 -2
  67. data/lib/dynflow/director/sequential_manager.rb +1 -0
  68. data/lib/dynflow/director.rb +12 -11
  69. data/lib/dynflow/dispatcher/abstract.rb +1 -0
  70. data/lib/dynflow/dispatcher/client_dispatcher.rb +33 -33
  71. data/lib/dynflow/dispatcher/executor_dispatcher.rb +7 -6
  72. data/lib/dynflow/dispatcher.rb +8 -7
  73. data/lib/dynflow/errors.rb +1 -0
  74. data/lib/dynflow/execution_history.rb +2 -1
  75. data/lib/dynflow/execution_plan/dependency_graph.rb +1 -2
  76. data/lib/dynflow/execution_plan/hooks.rb +1 -1
  77. data/lib/dynflow/execution_plan/output_reference.rb +4 -4
  78. data/lib/dynflow/execution_plan/steps/abstract.rb +21 -20
  79. data/lib/dynflow/execution_plan/steps/abstract_flow_step.rb +1 -1
  80. data/lib/dynflow/execution_plan/steps/error.rb +10 -9
  81. data/lib/dynflow/execution_plan/steps/finalize_step.rb +1 -2
  82. data/lib/dynflow/execution_plan/steps/plan_step.rb +12 -11
  83. data/lib/dynflow/execution_plan/steps/run_step.rb +1 -1
  84. data/lib/dynflow/execution_plan/steps.rb +1 -2
  85. data/lib/dynflow/execution_plan.rb +46 -46
  86. data/lib/dynflow/executors/abstract/core.rb +4 -3
  87. data/lib/dynflow/executors/parallel/core.rb +3 -2
  88. data/lib/dynflow/executors/parallel/pool.rb +1 -4
  89. data/lib/dynflow/executors/parallel/worker.rb +1 -0
  90. data/lib/dynflow/executors/parallel.rb +3 -2
  91. data/lib/dynflow/executors/sidekiq/core.rb +2 -0
  92. data/lib/dynflow/executors/sidekiq/internal_job_base.rb +1 -0
  93. data/lib/dynflow/executors/sidekiq/orchestrator_jobs.rb +1 -0
  94. data/lib/dynflow/executors/sidekiq/redis_locking.rb +1 -0
  95. data/lib/dynflow/executors/sidekiq/serialization.rb +1 -0
  96. data/lib/dynflow/executors/sidekiq/worker_jobs.rb +1 -0
  97. data/lib/dynflow/executors.rb +1 -1
  98. data/lib/dynflow/extensions/msgpack.rb +5 -4
  99. data/lib/dynflow/extensions.rb +1 -0
  100. data/lib/dynflow/flows/abstract.rb +1 -1
  101. data/lib/dynflow/flows/abstract_composed.rb +1 -2
  102. data/lib/dynflow/flows/atom.rb +1 -2
  103. data/lib/dynflow/flows/concurrence.rb +1 -1
  104. data/lib/dynflow/flows/registry.rb +1 -0
  105. data/lib/dynflow/flows/sequence.rb +1 -1
  106. data/lib/dynflow/flows.rb +1 -2
  107. data/lib/dynflow/logger_adapters/abstract.rb +1 -1
  108. data/lib/dynflow/logger_adapters/delegator.rb +1 -1
  109. data/lib/dynflow/logger_adapters/formatters/abstract.rb +1 -0
  110. data/lib/dynflow/logger_adapters/formatters/exception.rb +1 -0
  111. data/lib/dynflow/logger_adapters/formatters.rb +1 -0
  112. data/lib/dynflow/logger_adapters/simple.rb +6 -5
  113. data/lib/dynflow/logger_adapters.rb +1 -0
  114. data/lib/dynflow/middleware/common/singleton.rb +1 -0
  115. data/lib/dynflow/middleware/common/transaction.rb +1 -0
  116. data/lib/dynflow/middleware/register.rb +1 -0
  117. data/lib/dynflow/middleware/resolver.rb +2 -3
  118. data/lib/dynflow/middleware/stack.rb +1 -0
  119. data/lib/dynflow/middleware/world.rb +1 -2
  120. data/lib/dynflow/middleware.rb +1 -0
  121. data/lib/dynflow/persistence.rb +4 -5
  122. data/lib/dynflow/persistence_adapters/abstract.rb +1 -1
  123. data/lib/dynflow/persistence_adapters/sequel.rb +14 -14
  124. data/lib/dynflow/persistence_adapters/sequel_migrations/001_initial.rb +2 -1
  125. data/lib/dynflow/persistence_adapters/sequel_migrations/002_incremental_progress.rb +1 -0
  126. data/lib/dynflow/persistence_adapters/sequel_migrations/003_parent_action.rb +1 -0
  127. data/lib/dynflow/persistence_adapters/sequel_migrations/004_coordinator_records.rb +1 -1
  128. data/lib/dynflow/persistence_adapters/sequel_migrations/005_envelopes.rb +1 -0
  129. data/lib/dynflow/persistence_adapters/sequel_migrations/006_fix_data_length.rb +1 -0
  130. data/lib/dynflow/persistence_adapters/sequel_migrations/007_future_execution.rb +1 -0
  131. data/lib/dynflow/persistence_adapters/sequel_migrations/008_rename_scheduled_plans_to_delayed_plans.rb +1 -0
  132. data/lib/dynflow/persistence_adapters/sequel_migrations/009_fix_mysql_data_length.rb +1 -1
  133. data/lib/dynflow/persistence_adapters/sequel_migrations/010_add_execution_plans_label.rb +1 -0
  134. data/lib/dynflow/persistence_adapters/sequel_migrations/011_placeholder.rb +1 -0
  135. data/lib/dynflow/persistence_adapters/sequel_migrations/012_add_delayed_plans_serialized_args.rb +1 -0
  136. data/lib/dynflow/persistence_adapters/sequel_migrations/013_add_action_columns.rb +1 -0
  137. data/lib/dynflow/persistence_adapters/sequel_migrations/014_add_step_columns.rb +1 -0
  138. data/lib/dynflow/persistence_adapters/sequel_migrations/015_add_execution_plan_columns.rb +1 -0
  139. data/lib/dynflow/persistence_adapters/sequel_migrations/016_add_step_queue.rb +1 -0
  140. data/lib/dynflow/persistence_adapters/sequel_migrations/017_add_delayed_plan_frozen.rb +1 -0
  141. data/lib/dynflow/persistence_adapters/sequel_migrations/018_add_uuid_column.rb +37 -30
  142. data/lib/dynflow/persistence_adapters/sequel_migrations/019_update_mysql_time_precision.rb +1 -0
  143. data/lib/dynflow/persistence_adapters/sequel_migrations/020_drop_duplicate_indices.rb +1 -0
  144. data/lib/dynflow/persistence_adapters/sequel_migrations/021_create_output_chunks.rb +4 -3
  145. data/lib/dynflow/persistence_adapters/sequel_migrations/023_sqlite_workarounds.rb +1 -0
  146. data/lib/dynflow/persistence_adapters.rb +1 -0
  147. data/lib/dynflow/rails/configuration.rb +1 -0
  148. data/lib/dynflow/rails/daemon.rb +1 -1
  149. data/lib/dynflow/rails.rb +3 -2
  150. data/lib/dynflow/round_robin.rb +2 -2
  151. data/lib/dynflow/semaphores/abstract.rb +1 -1
  152. data/lib/dynflow/semaphores/aggregating.rb +1 -2
  153. data/lib/dynflow/semaphores/dummy.rb +1 -1
  154. data/lib/dynflow/semaphores/stateful.rb +1 -1
  155. data/lib/dynflow/semaphores.rb +1 -0
  156. data/lib/dynflow/serializable.rb +1 -0
  157. data/lib/dynflow/serializer.rb +2 -2
  158. data/lib/dynflow/serializers/abstract.rb +1 -2
  159. data/lib/dynflow/serializers/noop.rb +1 -2
  160. data/lib/dynflow/serializers.rb +1 -2
  161. data/lib/dynflow/stateful.rb +1 -0
  162. data/lib/dynflow/telemetry.rb +11 -10
  163. data/lib/dynflow/telemetry_adapters/abstract.rb +1 -0
  164. data/lib/dynflow/telemetry_adapters/dummy.rb +1 -0
  165. data/lib/dynflow/telemetry_adapters/statsd.rb +2 -1
  166. data/lib/dynflow/testing/assertions.rb +7 -7
  167. data/lib/dynflow/testing/dummy_coordinator.rb +1 -0
  168. data/lib/dynflow/testing/dummy_execution_plan.rb +1 -0
  169. data/lib/dynflow/testing/dummy_executor.rb +1 -0
  170. data/lib/dynflow/testing/dummy_planned_action.rb +3 -1
  171. data/lib/dynflow/testing/dummy_step.rb +1 -0
  172. data/lib/dynflow/testing/dummy_world.rb +1 -0
  173. data/lib/dynflow/testing/factories.rb +42 -37
  174. data/lib/dynflow/testing/in_thread_executor.rb +1 -0
  175. data/lib/dynflow/testing/in_thread_world.rb +1 -0
  176. data/lib/dynflow/testing/managed_clock.rb +1 -1
  177. data/lib/dynflow/testing/mimic.rb +4 -4
  178. data/lib/dynflow/testing.rb +1 -0
  179. data/lib/dynflow/throttle_limiter.rb +1 -1
  180. data/lib/dynflow/transaction_adapters/abstract.rb +1 -0
  181. data/lib/dynflow/transaction_adapters/active_record.rb +1 -0
  182. data/lib/dynflow/transaction_adapters/none.rb +1 -0
  183. data/lib/dynflow/transaction_adapters.rb +1 -2
  184. data/lib/dynflow/utils/indifferent_hash.rb +7 -1
  185. data/lib/dynflow/utils/priority_queue.rb +1 -0
  186. data/lib/dynflow/utils.rb +1 -1
  187. data/lib/dynflow/version.rb +2 -1
  188. data/lib/dynflow/watchers/memory_consumption_watcher.rb +1 -1
  189. data/lib/dynflow/web/console.rb +1 -3
  190. data/lib/dynflow/web/console_helpers.rb +5 -4
  191. data/lib/dynflow/web/filtering_helpers.rb +1 -0
  192. data/lib/dynflow/web/world_helpers.rb +1 -0
  193. data/lib/dynflow/web.rb +3 -3
  194. data/lib/dynflow/web_console.rb +1 -0
  195. data/lib/dynflow/world/invalidation.rb +9 -1
  196. data/lib/dynflow/world.rb +20 -20
  197. data/lib/dynflow.rb +3 -6
  198. data/test/abnormal_states_recovery_test.rb +4 -8
  199. data/test/action_test.rb +10 -18
  200. data/test/activejob_adapter_test.rb +2 -2
  201. data/test/batch_sub_tasks_test.rb +1 -1
  202. data/test/clock_test.rb +2 -3
  203. data/test/concurrency_control_test.rb +6 -7
  204. data/test/coordinator_test.rb +1 -0
  205. data/test/daemon_test.rb +3 -2
  206. data/test/dead_letter_silencer_test.rb +2 -1
  207. data/test/dispatcher_test.rb +4 -5
  208. data/test/execution_plan_cleaner_test.rb +1 -0
  209. data/test/execution_plan_hooks_test.rb +1 -0
  210. data/test/execution_plan_test.rb +10 -32
  211. data/test/executor_test.rb +20 -37
  212. data/test/extensions_test.rb +1 -0
  213. data/test/flows_test.rb +2 -2
  214. data/test/future_execution_test.rb +2 -3
  215. data/test/memory_cosumption_watcher_test.rb +1 -0
  216. data/test/middleware_test.rb +4 -6
  217. data/test/persistence_test.rb +26 -26
  218. data/test/redis_locking_test.rb +1 -0
  219. data/test/rescue_test.rb +3 -11
  220. data/test/round_robin_test.rb +1 -0
  221. data/test/semaphores_test.rb +5 -7
  222. data/test/support/code_workflow_example.rb +11 -28
  223. data/test/support/dummy_example.rb +20 -19
  224. data/test/support/middleware_example.rb +2 -8
  225. data/test/support/rescue_example.rb +1 -14
  226. data/test/support/test_execution_log.rb +1 -2
  227. data/test/test_helper.rb +3 -7
  228. data/test/testing_test.rb +6 -8
  229. data/test/utils_test.rb +1 -0
  230. data/test/v2_sub_plans_test.rb +1 -0
  231. data/test/web_console_test.rb +4 -4
  232. data/test/world_test.rb +4 -3
  233. metadata +43 -43
@@ -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
- .where(execution_plan_uuid: execution_plan.id).delete
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
- deserialized_execution_plan.send(attr).to_s,
55
- "invalid plan is supposed to still store #{attr}"
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
- deserialized_execution_plan.send(attr).to_f,
60
- "invalid plan is supposed to still store #{attr}"
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
- deserialized_execution_plan.execution_history.events,
64
- "invalid plan is supposed to still store execution history"
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
- .unique_filter plan.entry_action.class.name
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
- .unique_filter plan.entry_action.class.name
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
@@ -1,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # frozen_string_literal: true
3
+
3
4
  require_relative 'test_helper'
4
5
  require 'mocha/minitest'
5
6
 
@@ -11,11 +12,13 @@ require 'dynflow/executors/sidekiq/core'
11
12
 
12
13
  module RedisMocks
13
14
  def release_orchestrator_lock; end
15
+
14
16
  def wait_for_orchestrator_lock; end
17
+
15
18
  def reacquire_orchestrator_lock; end
16
19
  end
17
20
 
18
- ::Dynflow::Executors::Sidekiq::Core.send(:prepend, RedisMocks)
21
+ ::Dynflow::Executors::Sidekiq::Core.prepend RedisMocks
19
22
 
20
23
  module Dynflow
21
24
  module ExecutorTest
@@ -71,9 +74,7 @@ module Dynflow
71
74
  end
72
75
 
73
76
  describe "execution plan state" do
74
-
75
77
  describe "after successful planning" do
76
-
77
78
  let :execution_plan do
78
79
  world.plan(Support::CodeWorkflowExample::IncomingIssues, issues_data)
79
80
  end
@@ -100,7 +101,6 @@ module Dynflow
100
101
  end
101
102
 
102
103
  describe "after error in planning" do
103
-
104
104
  class FailingAction < Dynflow::Action
105
105
  def plan
106
106
  raise "I failed"
@@ -114,7 +114,6 @@ module Dynflow
114
114
  it "is stopped" do
115
115
  _(execution_plan.state).must_equal :stopped
116
116
  end
117
-
118
117
  end
119
118
 
120
119
  describe "when being executed" do
@@ -166,7 +165,6 @@ module Dynflow
166
165
  end
167
166
 
168
167
  describe "execution of run flow" do
169
-
170
168
  before do
171
169
  TestExecutionLog.setup
172
170
  end
@@ -230,8 +228,8 @@ module Dynflow
230
228
  describe 'handling errors in setup' do
231
229
  let :execution_plan do
232
230
  world.plan(Support::DummyExample::Polling,
233
- external_task_id: '123',
234
- text: 'troll setup')
231
+ external_task_id: '123',
232
+ text: 'troll setup')
235
233
  end
236
234
 
237
235
  it 'fails' do
@@ -310,8 +308,8 @@ module Dynflow
310
308
  describe 'plan with one action' do
311
309
  let :execution_plan do
312
310
  world.plan(Support::DummyExample::Polling,
313
- { external_task_id: '123',
314
- text: 'pause in progress 20%' })
311
+ { external_task_id: '123',
312
+ text: 'pause in progress 20%' })
315
313
  end
316
314
 
317
315
  it 'determines the progress of the execution plan in percents' do
@@ -325,8 +323,8 @@ module Dynflow
325
323
  describe 'plan with more action' do
326
324
  let :execution_plan do
327
325
  world.plan(Support::DummyExample::WeightedPolling,
328
- { external_task_id: '123',
329
- text: 'pause in progress 20%' })
326
+ { external_task_id: '123',
327
+ text: 'pause in progress 20%' })
330
328
  end
331
329
 
332
330
  it 'takes the steps weight in account' do
@@ -341,8 +339,8 @@ module Dynflow
341
339
  describe 'works when resumed after error' do
342
340
  let :execution_plan do
343
341
  world.plan(Support::DummyExample::Polling,
344
- { external_task_id: '123',
345
- text: 'troll progress' })
342
+ { external_task_id: '123',
343
+ text: 'troll progress' })
346
344
  end
347
345
 
348
346
  specify do
@@ -356,11 +354,9 @@ module Dynflow
356
354
  assert_equal :success, ep.run_steps.first.state
357
355
  end
358
356
  end
359
-
360
357
  end
361
358
 
362
359
  describe "action with empty flows" do
363
-
364
360
  let :execution_plan do
365
361
  world.plan(Support::CodeWorkflowExample::Dummy, { :text => "dummy" }).tap do |plan|
366
362
  assert_equal plan.run_flow.size, 0
@@ -379,11 +375,9 @@ module Dynflow
379
375
  world.execute(execution_plan.id)
380
376
  assert_raises(Dynflow::Error) { world.execute(execution_plan.id).value! }
381
377
  end
382
-
383
378
  end
384
379
 
385
380
  describe 'action with empty run flow but some finalize flow' do
386
-
387
381
  let :execution_plan do
388
382
  world.plan(Support::CodeWorkflowExample::DummyWithFinalize, { :text => "dummy" }).tap do |plan|
389
383
  assert_equal plan.run_flow.size, 0
@@ -395,7 +389,6 @@ module Dynflow
395
389
  _(result.result).must_equal :success
396
390
  _(result.state).must_equal :stopped
397
391
  end
398
-
399
392
  end
400
393
 
401
394
  describe 'running' do
@@ -417,7 +410,6 @@ module Dynflow
417
410
  EXECUTED_RUN_FLOW
418
411
  end
419
412
  end
420
-
421
413
  end
422
414
 
423
415
  describe "execution of finalize flow" do
@@ -438,10 +430,10 @@ module Dynflow
438
430
 
439
431
  it "runs all the steps in the finalize flow" do
440
432
  assert_finalized(Support::CodeWorkflowExample::IncomingIssues,
441
- { "issues" => [{ "author" => "Peter Smith", "text" => "Failing test" },
442
- { "author" => "John Doe", "text" => "Internal server error" }] })
433
+ { "issues" => [{ "author" => "Peter Smith", "text" => "Failing test" },
434
+ { "author" => "John Doe", "text" => "Internal server error" }] })
443
435
  assert_finalized(Support::CodeWorkflowExample::Triage,
444
- { "author" => "Peter Smith", "text" => "Failing test" })
436
+ { "author" => "Peter Smith", "text" => "Failing test" })
445
437
  end
446
438
  end
447
439
 
@@ -454,7 +446,6 @@ module Dynflow
454
446
  _(TestExecutionLog.finalize.size).must_equal 0
455
447
  end
456
448
  end
457
-
458
449
  end
459
450
 
460
451
  describe "re-execution of run flow after fix in run phase" do
@@ -493,13 +484,11 @@ module Dynflow
493
484
  13: Triage(success) {\"author\"=>\"John Doe\", \"text\"=>\"ok\"} --> {\"classification\"=>{\"assignee\"=>\"John Doe\", \"severity\"=>\"medium\"}}
494
485
  16: UpdateIssue(success) {\"author\"=>\"John Doe\", \"text\"=>\"trolling\", \"assignee\"=>\"John Doe\", \"severity\"=>\"medium\"} --> {}
495
486
  18: NotifyAssignee(success) {\"triage\"=>{\"classification\"=>{\"assignee\"=>\"John Doe\", \"severity\"=>\"medium\"}}} --> {}
496
- EXECUTED_RUN_FLOW
487
+ EXECUTED_RUN_FLOW
497
488
  end
498
-
499
489
  end
500
490
 
501
491
  describe "re-execution of run flow after fix in finalize phase" do
502
-
503
492
  after do
504
493
  TestExecutionLog.teardown
505
494
  end
@@ -532,13 +521,11 @@ module Dynflow
532
521
  14: Triage(success) {\"author\"=>\"John Doe\", \"text\"=>\"ok\"} --> {\"classification\"=>{\"assignee\"=>\"John Doe\", \"severity\"=>\"medium\"}}
533
522
  19: NotifyAssignee(success) {\"triage\"=>{\"classification\"=>{\"assignee\"=>\"John Doe\", \"severity\"=>\"medium\"}}} --> {}
534
523
  20: IncomingIssues(success) {\"issues\"=>[{\"author\"=>\"Peter Smith\", \"text\"=>\"Failing test\"}, {\"author\"=>\"John Doe\", \"text\"=>\"trolling in finalize\"}]} --> {}
535
- EXECUTED_RUN_FLOW
524
+ EXECUTED_RUN_FLOW
536
525
  end
537
-
538
526
  end
539
527
 
540
528
  describe "re-execution of run flow after skipping" do
541
-
542
529
  after do
543
530
  TestExecutionLog.teardown
544
531
  end
@@ -571,7 +558,7 @@ module Dynflow
571
558
  13: Triage(skipped) {\"author\"=>\"John Doe\", \"text\"=>\"trolling\"} --> {}
572
559
  16: UpdateIssue(skipped) {\"author\"=>\"John Doe\", \"text\"=>\"trolling\", \"assignee\"=>Step(13).output[:classification][:assignee], \"severity\"=>Step(13).output[:classification][:severity]} --> {}
573
560
  18: NotifyAssignee(skipped) {\"triage\"=>Step(13).output} --> {}
574
- EXECUTED_RUN_FLOW
561
+ EXECUTED_RUN_FLOW
575
562
 
576
563
  assert_finalize_flow <<-FINALIZE_FLOW, resumed_execution_plan
577
564
  Dynflow::Flows::Sequence
@@ -580,8 +567,7 @@ module Dynflow
580
567
  14: Triage(skipped) {\"author\"=>\"John Doe\", \"text\"=>\"trolling\"} --> {}
581
568
  19: NotifyAssignee(skipped) {\"triage\"=>Step(13).output} --> {}
582
569
  20: IncomingIssues(success) {\"issues\"=>[{\"author\"=>\"Peter Smith\", \"text\"=>\"Failing test\"}, {\"author\"=>\"John Doe\", \"text\"=>\"trolling\"}]} --> {}
583
- FINALIZE_FLOW
584
-
570
+ FINALIZE_FLOW
585
571
  end
586
572
  end
587
573
 
@@ -617,7 +603,6 @@ module Dynflow
617
603
  end
618
604
 
619
605
  describe 'what_is_next with errors' do
620
-
621
606
  it "doesn't return next steps if requirements failed" do
622
607
  assert_next_steps([4, 13])
623
608
  assert_next_steps([], 4, false)
@@ -631,7 +616,6 @@ module Dynflow
631
616
  assert manager.done?
632
617
  end
633
618
  end
634
-
635
619
  end
636
620
 
637
621
  describe 'Pool::JobStorage' do
@@ -673,7 +657,6 @@ module Dynflow
673
657
  assert_nil storage.pop
674
658
  end
675
659
  end
676
-
677
660
  end
678
661
 
679
662
  describe 'termination' do
@@ -682,7 +665,7 @@ module Dynflow
682
665
  it 'waits for currently running actions' do
683
666
  $slow_actions_done = 0
684
667
  running = world.trigger(Support::DummyExample::Slow, 1)
685
- suspended = world.trigger(Support::DummyExample::DeprecatedEventedAction, :timeout => 3 )
668
+ suspended = world.trigger(Support::DummyExample::DeprecatedEventedAction, :timeout => 3)
686
669
  sleep 0.2
687
670
  world.terminate.wait
688
671
  _($slow_actions_done).must_equal 1
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative 'test_helper'
3
4
  require 'active_support/time'
4
5
 
data/test/flows_test.rb CHANGED
@@ -1,10 +1,10 @@
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 'flow' do
7
-
8
8
  class TestRegistry < Flows::Registry
9
9
  class << self
10
10
  def reset!
@@ -22,7 +22,7 @@ module Dynflow
22
22
  TestRegistry.register!(TestRegistry, 'TS')
23
23
  TestRegistry.register!(Integer, 'I')
24
24
  map = TestRegistry.instance_variable_get("@serialization_map")
25
- _(map).must_equal({'TS' => TestRegistry, 'I' => Integer})
25
+ _(map).must_equal({ 'TS' => TestRegistry, 'I' => Integer })
26
26
  end
27
27
 
28
28
  it "prevents overwriting values" do
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative 'test_helper'
3
4
 
4
5
  module Dynflow
@@ -9,7 +10,6 @@ module Dynflow
9
10
  include Dynflow::Testing::Factories
10
11
 
11
12
  describe 'action scheduling' do
12
-
13
13
  before do
14
14
  @start_at = Time.now.utc + 180
15
15
  world.persistence.delete_delayed_plans({})
@@ -98,10 +98,9 @@ module Dynflow
98
98
  delayed_plan.timeout
99
99
  _(execution_plan.state).must_equal :stopped
100
100
  _(execution_plan.result).must_equal :error
101
- _(execution_plan.errors.first.message).must_match /could not be started before set time/
101
+ _(execution_plan.errors.first.message).must_match(/could not be started before set time/)
102
102
  _(history_names.call(execution_plan)).must_equal %W(delay timeout)
103
103
  end
104
-
105
104
  end
106
105
 
107
106
  describe 'polling delayed executor' do
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative 'test_helper'
3
4
  require 'fileutils'
4
5
  require 'dynflow/watchers/memory_consumption_watcher'
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative 'test_helper'
3
4
 
4
5
  module Dynflow
5
6
  module MiddlewareTest
6
-
7
7
  describe 'Middleware' do
8
8
  let(:world) { WorldFactory.create_world }
9
9
  let(:log) { Support::MiddlewareExample::LogMiddleware.log }
@@ -77,8 +77,7 @@ module Dynflow
77
77
  let(:world_with_middleware) do
78
78
  WorldFactory.create_world.tap do |world|
79
79
  world.middleware.use(Support::MiddlewareExample::AnotherLogRunMiddleware,
80
- after: Support::MiddlewareExample::LogRunMiddleware)
81
-
80
+ after: Support::MiddlewareExample::LogRunMiddleware)
82
81
  end
83
82
  end
84
83
 
@@ -112,7 +111,7 @@ module Dynflow
112
111
  it "allows access the running action" do
113
112
  world = WorldFactory.create_world
114
113
  world.middleware.use(Support::MiddlewareExample::ObservingMiddleware,
115
- replace: Support::MiddlewareExample::LogRunMiddleware)
114
+ replace: Support::MiddlewareExample::LogRunMiddleware)
116
115
  world.trigger(Support::MiddlewareExample::Action, message: 'hello').finished.wait
117
116
  _(log).must_equal %w[input#message:hello
118
117
  run
@@ -122,7 +121,7 @@ module Dynflow
122
121
  it "allows modification of the running action when delaying execution" do
123
122
  world = WorldFactory.create_world
124
123
  world.middleware.use(Support::MiddlewareExample::AnotherObservingMiddleware,
125
- replace: Support::MiddlewareExample::LogRunMiddleware)
124
+ replace: Support::MiddlewareExample::LogRunMiddleware)
126
125
  delay = world.delay(Support::MiddlewareExample::Action, { :start_at => Time.now - 60 })
127
126
  plan = world.persistence.load_delayed_plan delay.execution_plan_id
128
127
  plan.plan
@@ -183,7 +182,6 @@ module Dynflow
183
182
  _(presenter_without_middleware.input['text']).must_equal('Lord Voldemort is comming')
184
183
  end
185
184
  end
186
-
187
185
  end
188
186
  end
189
187
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative 'test_helper'
3
4
  require 'tmpdir'
4
5
  require 'ostruct'
@@ -6,7 +7,6 @@ require 'ostruct'
6
7
  module Dynflow
7
8
  module PersistenceTest
8
9
  describe 'persistence adapters' do
9
-
10
10
  let :execution_plans_data do
11
11
  [{ id: 'plan1', :label => 'test1', root_plan_step_id: 1, class: 'Dynflow::ExecutionPlan', state: 'paused' },
12
12
  { id: 'plan2', :label => 'test2', root_plan_step_id: 1, class: 'Dynflow::ExecutionPlan', state: 'stopped' },
@@ -20,8 +20,8 @@ module Dynflow
20
20
  caller_execution_plan_id: nil,
21
21
  caller_action_id: nil,
22
22
  class: 'Dynflow::Action',
23
- input: {key: 'value'},
24
- output: {something: 'else'},
23
+ input: { key: 'value' },
24
+ output: { something: 'else' },
25
25
  plan_step_id: 1,
26
26
  run_step_id: 2,
27
27
  finalize_step_id: 3
@@ -150,9 +150,9 @@ module Dynflow
150
150
  _(loaded_plans).must_be_empty
151
151
 
152
152
  adapter.save_delayed_plan('plan1',
153
- :execution_plan_uuid => 'plan1',
154
- :start_at => format_time(Time.now + 60),
155
- :start_before => format_time(Time.now - 60))
153
+ :execution_plan_uuid => 'plan1',
154
+ :start_at => format_time(Time.now + 60),
155
+ :start_before => format_time(Time.now - 60))
156
156
  loaded_plans = adapter.find_execution_plans(filters: { label: ['test1'], :delayed => true })
157
157
  _(loaded_plans.map { |h| h[:id] }).must_equal ['plan1']
158
158
  end
@@ -169,29 +169,29 @@ module Dynflow
169
169
  prepare_and_save_plans
170
170
  if adapter.ordering_by.include?('state')
171
171
  loaded_plans = adapter.find_execution_plan_statuses(filters: { label: ['test1'] })
172
- _(loaded_plans).must_equal({ 'plan1' => { state: 'paused', result: nil} })
172
+ _(loaded_plans).must_equal({ 'plan1' => { state: 'paused', result: nil } })
173
173
 
174
174
  loaded_plans = adapter.find_execution_plan_statuses(filters: { state: ['paused'] })
175
- _(loaded_plans).must_equal({"plan1"=>{:state=>"paused", :result=>nil},
176
- "plan3"=>{:state=>"paused", :result=>nil},
177
- "plan4"=>{:state=>"paused", :result=>nil}})
175
+ _(loaded_plans).must_equal({ "plan1" => { :state => "paused", :result => nil },
176
+ "plan3" => { :state => "paused", :result => nil },
177
+ "plan4" => { :state => "paused", :result => nil } })
178
178
 
179
179
  loaded_plans = adapter.find_execution_plan_statuses(filters: { state: ['stopped'] })
180
- _(loaded_plans).must_equal({"plan2"=>{:state=>"stopped", :result=>nil}})
180
+ _(loaded_plans).must_equal({ "plan2" => { :state => "stopped", :result => nil } })
181
181
 
182
182
  loaded_plans = adapter.find_execution_plan_statuses(filters: { state: [] })
183
183
  _(loaded_plans).must_equal({})
184
184
 
185
185
  loaded_plans = adapter.find_execution_plan_statuses(filters: { state: ['stopped', 'paused'] })
186
- _(loaded_plans).must_equal({"plan1"=>{:state=>"paused", :result=>nil},
187
- "plan2"=>{:state=>"stopped", :result=>nil},
188
- "plan3"=>{:state=>"paused", :result=>nil}, "plan4"=>{:state=>"paused", :result=>nil}})
186
+ _(loaded_plans).must_equal({ "plan1" => { :state => "paused", :result => nil },
187
+ "plan2" => { :state => "stopped", :result => nil },
188
+ "plan3" => { :state => "paused", :result => nil }, "plan4" => { :state => "paused", :result => nil } })
189
189
 
190
190
  loaded_plans = adapter.find_execution_plan_statuses(filters: { 'state' => ['stopped', 'paused'] })
191
- _(loaded_plans).must_equal({"plan1"=>{:state=>"paused", :result=>nil},
192
- "plan2"=>{:state=>"stopped", :result=>nil},
193
- "plan3"=>{:state=>"paused", :result=>nil},
194
- "plan4"=>{:state=>"paused", :result=>nil}})
191
+ _(loaded_plans).must_equal({ "plan1" => { :state => "paused", :result => nil },
192
+ "plan2" => { :state => "stopped", :result => nil },
193
+ "plan3" => { :state => "paused", :result => nil },
194
+ "plan4" => { :state => "paused", :result => nil } })
195
195
 
196
196
  loaded_plans = adapter.find_execution_plan_statuses(filters: { label: ['test1'], :delayed => true })
197
197
  _(loaded_plans).must_equal({})
@@ -229,9 +229,9 @@ module Dynflow
229
229
  _(loaded_plans).must_equal 0
230
230
 
231
231
  adapter.save_delayed_plan('plan1',
232
- :execution_plan_uuid => 'plan1',
233
- :start_at => format_time(Time.now + 60),
234
- :start_before => format_time(Time.now - 60))
232
+ :execution_plan_uuid => 'plan1',
233
+ :start_at => format_time(Time.now + 60),
234
+ :start_before => format_time(Time.now - 60))
235
235
  loaded_plans = adapter.find_execution_plan_counts(filters: { label: ['test1'], :delayed => true })
236
236
  _(loaded_plans).must_equal 1
237
237
  end
@@ -276,14 +276,14 @@ module Dynflow
276
276
  it 'creates backup dir and produce backup including steps and actions' do
277
277
  prepare_plans_with_steps
278
278
  Dir.mktmpdir do |backup_dir|
279
- _(adapter.delete_execution_plans({'uuid' => 'plan1'}, 100, backup_dir)).must_equal 1
279
+ _(adapter.delete_execution_plans({ 'uuid' => 'plan1' }, 100, backup_dir)).must_equal 1
280
280
  plans = CSV.read(backup_dir + "/execution_plans.csv", :headers => true)
281
281
  assert_equal 1, plans.count
282
282
  assert_equal 'plan1', plans.first.to_hash['uuid']
283
283
  actions = CSV.read(backup_dir + "/actions.csv", :headers => true)
284
284
  assert_equal 1, actions.count
285
285
  assert_equal 'plan1', actions.first.to_hash['execution_plan_uuid']
286
- steps = CSV.read(backup_dir +"/steps.csv", :headers => true)
286
+ steps = CSV.read(backup_dir + "/steps.csv", :headers => true)
287
287
  assert_equal 1, steps.count
288
288
  assert_equal 'plan1', steps.first.to_hash['execution_plan_uuid']
289
289
  end
@@ -376,7 +376,7 @@ module Dynflow
376
376
  it 'deletes output chunks' do
377
377
  prepare_plans_with_actions
378
378
 
379
- adapter.save_output_chunks('plan1', 1, [{chunk: "Hello", timestamp: Time.now}, {chunk: "Bye", timestamp: Time.now}])
379
+ adapter.save_output_chunks('plan1', 1, [{ chunk: "Hello", timestamp: Time.now }, { chunk: "Bye", timestamp: Time.now }])
380
380
  chunks = adapter.load_output_chunks('plan1', 1)
381
381
  _(chunks.length).must_equal 2
382
382
  deleted = adapter.delete_output_chunks('plan1', 1)
@@ -451,7 +451,7 @@ module Dynflow
451
451
  envelopes = [client_envelope, executor_envelope]
452
452
 
453
453
  envelopes.each { |e| adapter.push_envelope(e) }
454
- adapter.insert_coordinator_record({"class"=>"Dynflow::Coordinator::ExecutorWorld",
454
+ adapter.insert_coordinator_record({ "class" => "Dynflow::Coordinator::ExecutorWorld",
455
455
  "id" => executor_world_id, "meta" => {}, "active" => true })
456
456
 
457
457
  assert_equal 1, adapter.prune_undeliverable_envelopes
@@ -526,7 +526,7 @@ module Dynflow
526
526
 
527
527
  value = 'a' * 1000
528
528
 
529
- adata = action_data.merge({:output => { :key => value }})
529
+ adata = action_data.merge({ :output => { :key => value } })
530
530
  plan_record = adapter.send(:prepare_record, :execution_plan, plan.merge(:uuid => plan[:id]))
531
531
  action_record = adapter.send(:prepare_record, :action, adata.dup)
532
532