dynflow 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/dynflow/semaphores.rb
CHANGED
data/lib/dynflow/serializable.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'date'
|
1
3
|
module Dynflow
|
2
4
|
class Serializable
|
5
|
+
TIME_FORMAT = '%Y-%m-%d %H:%M:%S.%L'
|
6
|
+
LEGACY_TIME_FORMAT = '%Y-%m-%d %H:%M:%S'
|
7
|
+
|
3
8
|
def self.from_hash(hash, *args)
|
4
9
|
check_class_key_present hash
|
5
10
|
constantize(hash[:class]).new_from_hash(hash, *args)
|
@@ -58,15 +63,19 @@ module Dynflow
|
|
58
63
|
def self.string_to_time(string)
|
59
64
|
return if string.nil?
|
60
65
|
return string if string.is_a?(Time)
|
61
|
-
|
62
|
-
|
63
|
-
|
66
|
+
time = begin
|
67
|
+
DateTime.strptime(string, TIME_FORMAT)
|
68
|
+
rescue ArgumentError => _
|
69
|
+
DateTime.strptime(string, LEGACY_TIME_FORMAT)
|
70
|
+
end
|
71
|
+
|
72
|
+
time.to_time.utc
|
64
73
|
end
|
65
74
|
|
66
75
|
def time_to_str(time)
|
67
76
|
return if time.nil?
|
68
77
|
Type! time, Time
|
69
|
-
time.utc.strftime
|
78
|
+
time.utc.strftime(TIME_FORMAT)
|
70
79
|
end
|
71
80
|
|
72
81
|
def self.hash_to_error(hash)
|
data/lib/dynflow/serializer.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'algebrick/serializer'
|
2
3
|
|
3
4
|
module Dynflow
|
@@ -10,6 +11,24 @@ module Dynflow
|
|
10
11
|
ARBITRARY_TYPE_KEY = :class
|
11
12
|
MARSHAL_KEY = :marshaled
|
12
13
|
|
14
|
+
def load(data, options = {})
|
15
|
+
case data
|
16
|
+
when ::Array
|
17
|
+
data.collect { |v| load(v) }
|
18
|
+
else
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def dump(object, options = {})
|
24
|
+
case object
|
25
|
+
when ::Array
|
26
|
+
object.collect { |v| dump(v) }
|
27
|
+
else
|
28
|
+
super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
13
32
|
protected
|
14
33
|
|
15
34
|
def parse_other(other, options = {})
|
@@ -19,6 +38,9 @@ module Dynflow
|
|
19
38
|
end
|
20
39
|
|
21
40
|
if (type_name = other[ARBITRARY_TYPE_KEY] || other[ARBITRARY_TYPE_KEY.to_s])
|
41
|
+
if type_name == 'Time' && ( time_str = other['value'] )
|
42
|
+
return Serializable.send(:string_to_time, time_str)
|
43
|
+
end
|
22
44
|
type = Utils.constantize(type_name) rescue nil
|
23
45
|
if type && type.respond_to?(:from_hash)
|
24
46
|
return type.from_hash other
|
@@ -35,6 +57,8 @@ module Dynflow
|
|
35
57
|
object.to_h
|
36
58
|
when object.respond_to?(:to_hash)
|
37
59
|
object.to_hash
|
60
|
+
when object.is_a?(Time) && !options[:marshaled_time]
|
61
|
+
{ ARBITRARY_TYPE_KEY => 'Time', 'value' => object.utc.strftime(Serializable::TIME_FORMAT) }
|
38
62
|
else
|
39
63
|
{ ARBITRARY_TYPE_KEY => object.class.to_s,
|
40
64
|
MARSHAL_KEY => Base64.strict_encode64(Marshal.dump(object)) }
|
data/lib/dynflow/serializers.rb
CHANGED
data/lib/dynflow/stateful.rb
CHANGED
data/lib/dynflow/telemetry.rb
CHANGED
data/lib/dynflow/testing.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Dynflow
|
2
3
|
module Testing
|
3
4
|
module Assertions
|
@@ -48,8 +49,8 @@ module Dynflow
|
|
48
49
|
def assert_run_phase(action, input = nil, &block)
|
49
50
|
Match! action.phase, Action::Plan
|
50
51
|
Match! action.state, :success
|
51
|
-
action.execution_plan.planned_run_steps.must_include action
|
52
|
-
action.input.must_equal Utils.stringify_keys(input) if input
|
52
|
+
_(action.execution_plan.planned_run_steps).must_include action
|
53
|
+
_(action.input).must_equal Utils.stringify_keys(input) if input
|
53
54
|
block.call action.input if block
|
54
55
|
end
|
55
56
|
|
@@ -57,21 +58,21 @@ module Dynflow
|
|
57
58
|
def refute_run_phase(action)
|
58
59
|
Match! action.phase, Action::Plan
|
59
60
|
Match! action.state, :success
|
60
|
-
action.execution_plan.planned_run_steps.wont_include action
|
61
|
+
_(action.execution_plan.planned_run_steps).wont_include action
|
61
62
|
end
|
62
63
|
|
63
64
|
# assert that +action+ has finalize-phase planned
|
64
65
|
def assert_finalize_phase(action)
|
65
66
|
Match! action.phase, Action::Plan
|
66
67
|
Match! action.state, :success
|
67
|
-
action.execution_plan.planned_finalize_steps.must_include action
|
68
|
+
_(action.execution_plan.planned_finalize_steps).must_include action
|
68
69
|
end
|
69
70
|
|
70
71
|
# refute that +action+ has finalize-phase planned
|
71
72
|
def refute_finalize_phase(action)
|
72
73
|
Match! action.phase, Action::Plan
|
73
74
|
Match! action.state, :success
|
74
|
-
action.execution_plan.planned_finalize_steps.wont_include action
|
75
|
+
_(action.execution_plan.planned_finalize_steps).wont_include action
|
75
76
|
end
|
76
77
|
|
77
78
|
end
|
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Dynflow
|
2
3
|
module Testing
|
3
4
|
class DummyExecutor
|
4
|
-
attr_reader :world
|
5
|
+
attr_reader :world, :events_to_process
|
5
6
|
|
6
7
|
def initialize(world)
|
7
8
|
@world = world
|
@@ -12,6 +13,22 @@ module Dynflow
|
|
12
13
|
@events_to_process << [execution_plan_id, step_id, event, future]
|
13
14
|
end
|
14
15
|
|
16
|
+
def delayed_event(director_event)
|
17
|
+
@events_to_process << [director_event.execution_plan_id, director_event.step_id, director_event.event, director_event.result]
|
18
|
+
end
|
19
|
+
|
20
|
+
def plan_events(delayed_events)
|
21
|
+
delayed_events.each do |event|
|
22
|
+
world.plan_event(event.execution_plan_id, event.step_id, event.event, event.time)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def execute(action, event = nil)
|
27
|
+
action.execute event
|
28
|
+
plan_events(action.delayed_events.dup)
|
29
|
+
action.delayed_events.clear
|
30
|
+
end
|
31
|
+
|
15
32
|
# returns true if some event was processed.
|
16
33
|
def progress
|
17
34
|
events = @events_to_process.dup
|
@@ -21,7 +38,7 @@ module Dynflow
|
|
21
38
|
if event && world.action.state != :suspended
|
22
39
|
return false
|
23
40
|
end
|
24
|
-
world.action
|
41
|
+
execute(world.action, event)
|
25
42
|
end
|
26
43
|
end
|
27
44
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Dynflow
|
2
3
|
module Testing
|
3
4
|
class DummyWorld
|
@@ -34,6 +35,14 @@ module Dynflow
|
|
34
35
|
executor.event execution_plan_id, step_id, event, future
|
35
36
|
end
|
36
37
|
|
38
|
+
def plan_event(execution_plan_id, step_id, event, time, accepted = Concurrent::Promises.resolvable_future)
|
39
|
+
if time.nil? || time < Time.now
|
40
|
+
event(execution_plan_id, step_id, event, accepted)
|
41
|
+
else
|
42
|
+
clock.ping(executor, time, Director::Event[SecureRandom.uuid, execution_plan_id, step_id, event, accepted], :delayed_event)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
37
46
|
def persistence
|
38
47
|
nil
|
39
48
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Dynflow
|
2
3
|
module Testing
|
3
4
|
module Factories
|
@@ -47,6 +48,10 @@ module Dynflow
|
|
47
48
|
plan_action create_action(action_class), *args, &block
|
48
49
|
end
|
49
50
|
|
51
|
+
def plan_events(world, delayed_events)
|
52
|
+
delayed_events.each { |event| world.plan_event(event.execution_plan_id, event.step_id, event.event, event.time) }
|
53
|
+
end
|
54
|
+
|
50
55
|
# @return [Action::RunPhase]
|
51
56
|
def run_action(plan_action, event = nil, &stubbing)
|
52
57
|
Match! plan_action.phase, Action::Plan, Action::Run
|
@@ -70,7 +75,7 @@ module Dynflow
|
|
70
75
|
run_action.world.action ||= run_action
|
71
76
|
run_action.world.clock.clear
|
72
77
|
stubbing.call run_action if stubbing
|
73
|
-
run_action.execute event
|
78
|
+
run_action.world.executor.execute(run_action, event)
|
74
79
|
raise run_action.error if run_action.error
|
75
80
|
run_action
|
76
81
|
end
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Dynflow
|
2
3
|
module Testing
|
3
|
-
class InThreadExecutor
|
4
|
+
class InThreadExecutor
|
4
5
|
def initialize(world)
|
5
6
|
@world = world
|
6
7
|
@director = Director.new(@world)
|
@@ -20,25 +21,43 @@ module Dynflow
|
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
24
|
+
def plan_events(delayed_events)
|
25
|
+
delayed_events.each do |event|
|
26
|
+
@world.plan_event(event.execution_plan_id, event.step_id, event.event, event.time)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
23
30
|
def handle_work(work_item)
|
24
31
|
work_item.execute
|
32
|
+
step = work_item.step if work_item.is_a?(Director::StepWorkItem)
|
33
|
+
plan_events(step && step.delayed_events) if step && step.delayed_events
|
25
34
|
@director.work_finished(work_item)
|
26
35
|
end
|
27
36
|
|
28
37
|
def event(execution_plan_id, step_id, event, future = Concurrent::Promises.resolvable_future)
|
29
|
-
event = (Director::Event[execution_plan_id, step_id, event, future])
|
38
|
+
event = (Director::Event[SecureRandom.uuid, execution_plan_id, step_id, event, future])
|
30
39
|
@director.handle_event(event).each do |work_item|
|
31
40
|
@work_items << work_item
|
32
41
|
end
|
33
42
|
future
|
34
43
|
end
|
35
44
|
|
45
|
+
def delayed_event(director_event)
|
46
|
+
@director.handle_event(director_event).each do |work_item|
|
47
|
+
@work_items << work_item
|
48
|
+
end
|
49
|
+
director_event.result
|
50
|
+
end
|
51
|
+
|
36
52
|
def clock_tick
|
37
53
|
@world.clock.progress_all([:periodic_check_inbox])
|
38
54
|
end
|
39
55
|
|
40
56
|
def feed_queue(work_items)
|
41
|
-
work_items.each
|
57
|
+
work_items.each do |work_item|
|
58
|
+
work_item.world = @world
|
59
|
+
@work_items.push(work_item)
|
60
|
+
end
|
42
61
|
end
|
43
62
|
|
44
63
|
def terminate(future = Concurrent::Promises.resolvable_future)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Dynflow
|
2
3
|
module Testing
|
3
4
|
class InThreadWorld < Dynflow::World
|
@@ -60,6 +61,14 @@ module Dynflow
|
|
60
61
|
def event(execution_plan_id, step_id, event, done = Concurrent::Promises.resolvable_future)
|
61
62
|
@executor.event(execution_plan_id, step_id, event, done)
|
62
63
|
end
|
64
|
+
|
65
|
+
def plan_event(execution_plan_id, step_id, event, time, done = Concurrent::Promises.resolvable_future)
|
66
|
+
if time.nil? || time < Time.now
|
67
|
+
event(execution_plan_id, step_id, event, done)
|
68
|
+
else
|
69
|
+
clock.ping(executor, time, Director::Event[SecureRandom.uuid, execution_plan_id, step_id, event, done], :delayed_event)
|
70
|
+
end
|
71
|
+
end
|
63
72
|
end
|
64
73
|
end
|
65
74
|
end
|
data/lib/dynflow/utils.rb
CHANGED