dynflow 1.8.2 → 1.8.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -1
- data/.rubocop.yml +11 -5
- data/.rubocop_todo.yml +777 -345
- data/Gemfile +4 -3
- data/Rakefile +1 -0
- data/doc/pages/Gemfile +4 -3
- data/doc/pages/Rakefile +1 -0
- data/doc/pages/plugins/alert_block.rb +1 -0
- data/doc/pages/plugins/div_tag.rb +1 -0
- data/doc/pages/plugins/graphviz.rb +6 -6
- data/doc/pages/plugins/plantuml.rb +2 -3
- data/doc/pages/plugins/play.rb +1 -2
- data/doc/pages/plugins/tags.rb +2 -8
- data/doc/pages/plugins/toc.rb +1 -1
- data/dynflow.gemspec +11 -10
- data/examples/clock_benchmark.rb +1 -0
- data/examples/example_helper.rb +4 -3
- data/examples/future_execution.rb +0 -2
- data/examples/memory_limit_watcher.rb +8 -8
- data/examples/orchestrate.rb +9 -21
- data/examples/orchestrate_evented.rb +18 -33
- data/examples/remote_executor.rb +9 -11
- data/examples/singletons.rb +1 -0
- data/examples/sub_plan_concurrency_control.rb +0 -1
- data/examples/sub_plans.rb +1 -0
- data/examples/sub_plans_v2.rb +1 -0
- data/lib/dynflow/action/cancellable.rb +1 -0
- data/lib/dynflow/action/format.rb +1 -4
- data/lib/dynflow/action/missing.rb +4 -4
- data/lib/dynflow/action/polling.rb +2 -3
- data/lib/dynflow/action/progress.rb +1 -4
- data/lib/dynflow/action/rescue.rb +1 -2
- data/lib/dynflow/action/singleton.rb +1 -0
- data/lib/dynflow/action/suspended.rb +1 -0
- data/lib/dynflow/action/timeouts.rb +2 -1
- data/lib/dynflow/action/with_bulk_sub_plans.rb +1 -0
- data/lib/dynflow/action/with_polling_sub_plans.rb +1 -1
- data/lib/dynflow/action/with_sub_plans.rb +20 -19
- data/lib/dynflow/action.rb +37 -37
- data/lib/dynflow/active_job/queue_adapter.rb +2 -1
- data/lib/dynflow/actor.rb +2 -2
- data/lib/dynflow/actors/execution_plan_cleaner.rb +1 -0
- data/lib/dynflow/actors.rb +1 -0
- data/lib/dynflow/clock.rb +3 -4
- data/lib/dynflow/config.rb +6 -5
- data/lib/dynflow/connectors/abstract.rb +11 -10
- data/lib/dynflow/connectors/database.rb +2 -2
- data/lib/dynflow/connectors/direct.rb +2 -3
- data/lib/dynflow/connectors.rb +1 -0
- data/lib/dynflow/coordinator.rb +21 -9
- data/lib/dynflow/coordinator_adapters/abstract.rb +1 -0
- data/lib/dynflow/coordinator_adapters/sequel.rb +1 -0
- data/lib/dynflow/coordinator_adapters.rb +1 -2
- data/lib/dynflow/dead_letter_silencer.rb +1 -0
- data/lib/dynflow/debug/telemetry/persistence.rb +3 -2
- data/lib/dynflow/delayed_executors/abstract.rb +1 -2
- data/lib/dynflow/delayed_executors/abstract_core.rb +1 -1
- data/lib/dynflow/delayed_executors/polling.rb +1 -2
- data/lib/dynflow/delayed_executors.rb +1 -2
- data/lib/dynflow/delayed_plan.rb +6 -6
- data/lib/dynflow/director/execution_plan_manager.rb +1 -1
- data/lib/dynflow/director/flow_manager.rb +1 -0
- data/lib/dynflow/director/queue_hash.rb +2 -1
- data/lib/dynflow/director/running_steps_manager.rb +3 -2
- data/lib/dynflow/director/sequence_cursor.rb +1 -2
- data/lib/dynflow/director/sequential_manager.rb +1 -0
- data/lib/dynflow/director.rb +12 -11
- data/lib/dynflow/dispatcher/abstract.rb +1 -0
- data/lib/dynflow/dispatcher/client_dispatcher.rb +33 -33
- data/lib/dynflow/dispatcher/executor_dispatcher.rb +7 -6
- data/lib/dynflow/dispatcher.rb +8 -7
- data/lib/dynflow/errors.rb +1 -0
- data/lib/dynflow/execution_history.rb +2 -1
- data/lib/dynflow/execution_plan/dependency_graph.rb +1 -2
- data/lib/dynflow/execution_plan/hooks.rb +1 -1
- data/lib/dynflow/execution_plan/output_reference.rb +4 -4
- data/lib/dynflow/execution_plan/steps/abstract.rb +21 -20
- data/lib/dynflow/execution_plan/steps/abstract_flow_step.rb +1 -1
- data/lib/dynflow/execution_plan/steps/error.rb +10 -9
- data/lib/dynflow/execution_plan/steps/finalize_step.rb +1 -2
- data/lib/dynflow/execution_plan/steps/plan_step.rb +12 -11
- data/lib/dynflow/execution_plan/steps/run_step.rb +1 -1
- data/lib/dynflow/execution_plan/steps.rb +1 -2
- data/lib/dynflow/execution_plan.rb +46 -46
- data/lib/dynflow/executors/abstract/core.rb +4 -3
- data/lib/dynflow/executors/parallel/core.rb +3 -2
- data/lib/dynflow/executors/parallel/pool.rb +1 -4
- data/lib/dynflow/executors/parallel/worker.rb +1 -0
- data/lib/dynflow/executors/parallel.rb +3 -2
- data/lib/dynflow/executors/sidekiq/core.rb +2 -0
- data/lib/dynflow/executors/sidekiq/internal_job_base.rb +1 -0
- data/lib/dynflow/executors/sidekiq/orchestrator_jobs.rb +1 -0
- data/lib/dynflow/executors/sidekiq/redis_locking.rb +1 -0
- data/lib/dynflow/executors/sidekiq/serialization.rb +1 -0
- data/lib/dynflow/executors/sidekiq/worker_jobs.rb +1 -0
- data/lib/dynflow/executors.rb +1 -1
- data/lib/dynflow/extensions/msgpack.rb +5 -4
- data/lib/dynflow/extensions.rb +1 -0
- data/lib/dynflow/flows/abstract.rb +1 -1
- data/lib/dynflow/flows/abstract_composed.rb +1 -2
- data/lib/dynflow/flows/atom.rb +1 -2
- data/lib/dynflow/flows/concurrence.rb +1 -1
- data/lib/dynflow/flows/registry.rb +1 -0
- data/lib/dynflow/flows/sequence.rb +1 -1
- data/lib/dynflow/flows.rb +1 -2
- data/lib/dynflow/logger_adapters/abstract.rb +1 -1
- data/lib/dynflow/logger_adapters/delegator.rb +1 -1
- data/lib/dynflow/logger_adapters/formatters/abstract.rb +1 -0
- data/lib/dynflow/logger_adapters/formatters/exception.rb +1 -0
- data/lib/dynflow/logger_adapters/formatters.rb +1 -0
- data/lib/dynflow/logger_adapters/simple.rb +6 -5
- data/lib/dynflow/logger_adapters.rb +1 -0
- data/lib/dynflow/middleware/common/singleton.rb +1 -0
- data/lib/dynflow/middleware/common/transaction.rb +1 -0
- data/lib/dynflow/middleware/register.rb +1 -0
- data/lib/dynflow/middleware/resolver.rb +2 -3
- data/lib/dynflow/middleware/stack.rb +1 -0
- data/lib/dynflow/middleware/world.rb +1 -2
- data/lib/dynflow/middleware.rb +1 -0
- data/lib/dynflow/persistence.rb +4 -5
- data/lib/dynflow/persistence_adapters/abstract.rb +1 -1
- data/lib/dynflow/persistence_adapters/sequel.rb +14 -14
- data/lib/dynflow/persistence_adapters/sequel_migrations/001_initial.rb +2 -1
- data/lib/dynflow/persistence_adapters/sequel_migrations/002_incremental_progress.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/003_parent_action.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/004_coordinator_records.rb +1 -1
- data/lib/dynflow/persistence_adapters/sequel_migrations/005_envelopes.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/006_fix_data_length.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/007_future_execution.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/008_rename_scheduled_plans_to_delayed_plans.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/009_fix_mysql_data_length.rb +1 -1
- data/lib/dynflow/persistence_adapters/sequel_migrations/010_add_execution_plans_label.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/011_placeholder.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/012_add_delayed_plans_serialized_args.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/013_add_action_columns.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/014_add_step_columns.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/015_add_execution_plan_columns.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/016_add_step_queue.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/017_add_delayed_plan_frozen.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/018_add_uuid_column.rb +37 -30
- data/lib/dynflow/persistence_adapters/sequel_migrations/019_update_mysql_time_precision.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/020_drop_duplicate_indices.rb +1 -0
- data/lib/dynflow/persistence_adapters/sequel_migrations/021_create_output_chunks.rb +4 -3
- data/lib/dynflow/persistence_adapters/sequel_migrations/023_sqlite_workarounds.rb +1 -0
- data/lib/dynflow/persistence_adapters.rb +1 -0
- data/lib/dynflow/rails/configuration.rb +1 -0
- data/lib/dynflow/rails/daemon.rb +1 -1
- data/lib/dynflow/rails.rb +3 -2
- data/lib/dynflow/round_robin.rb +2 -2
- data/lib/dynflow/semaphores/abstract.rb +1 -1
- data/lib/dynflow/semaphores/aggregating.rb +1 -2
- data/lib/dynflow/semaphores/dummy.rb +1 -1
- data/lib/dynflow/semaphores/stateful.rb +1 -1
- data/lib/dynflow/semaphores.rb +1 -0
- data/lib/dynflow/serializable.rb +1 -0
- data/lib/dynflow/serializer.rb +2 -2
- data/lib/dynflow/serializers/abstract.rb +1 -2
- data/lib/dynflow/serializers/noop.rb +1 -2
- data/lib/dynflow/serializers.rb +1 -2
- data/lib/dynflow/stateful.rb +1 -0
- data/lib/dynflow/telemetry.rb +11 -10
- data/lib/dynflow/telemetry_adapters/abstract.rb +1 -0
- data/lib/dynflow/telemetry_adapters/dummy.rb +1 -0
- data/lib/dynflow/telemetry_adapters/statsd.rb +2 -1
- data/lib/dynflow/testing/assertions.rb +7 -7
- data/lib/dynflow/testing/dummy_coordinator.rb +1 -0
- data/lib/dynflow/testing/dummy_execution_plan.rb +1 -0
- data/lib/dynflow/testing/dummy_executor.rb +1 -0
- data/lib/dynflow/testing/dummy_planned_action.rb +3 -1
- data/lib/dynflow/testing/dummy_step.rb +1 -0
- data/lib/dynflow/testing/dummy_world.rb +1 -0
- data/lib/dynflow/testing/factories.rb +42 -37
- data/lib/dynflow/testing/in_thread_executor.rb +1 -0
- data/lib/dynflow/testing/in_thread_world.rb +1 -0
- data/lib/dynflow/testing/managed_clock.rb +1 -1
- data/lib/dynflow/testing/mimic.rb +4 -4
- data/lib/dynflow/testing.rb +1 -0
- data/lib/dynflow/throttle_limiter.rb +1 -1
- data/lib/dynflow/transaction_adapters/abstract.rb +1 -0
- data/lib/dynflow/transaction_adapters/active_record.rb +1 -0
- data/lib/dynflow/transaction_adapters/none.rb +1 -0
- data/lib/dynflow/transaction_adapters.rb +1 -2
- data/lib/dynflow/utils/indifferent_hash.rb +7 -1
- data/lib/dynflow/utils/priority_queue.rb +1 -0
- data/lib/dynflow/utils.rb +1 -1
- data/lib/dynflow/version.rb +2 -1
- data/lib/dynflow/watchers/memory_consumption_watcher.rb +1 -1
- data/lib/dynflow/web/console.rb +1 -3
- data/lib/dynflow/web/console_helpers.rb +5 -4
- data/lib/dynflow/web/filtering_helpers.rb +1 -0
- data/lib/dynflow/web/world_helpers.rb +1 -0
- data/lib/dynflow/web.rb +3 -3
- data/lib/dynflow/web_console.rb +1 -0
- data/lib/dynflow/world/invalidation.rb +9 -1
- data/lib/dynflow/world.rb +20 -20
- data/lib/dynflow.rb +3 -6
- data/test/abnormal_states_recovery_test.rb +4 -8
- data/test/action_test.rb +10 -18
- data/test/activejob_adapter_test.rb +2 -2
- data/test/batch_sub_tasks_test.rb +1 -1
- data/test/clock_test.rb +2 -3
- data/test/concurrency_control_test.rb +6 -7
- data/test/coordinator_test.rb +1 -0
- data/test/daemon_test.rb +3 -2
- data/test/dead_letter_silencer_test.rb +2 -1
- data/test/dispatcher_test.rb +4 -5
- data/test/execution_plan_cleaner_test.rb +1 -0
- data/test/execution_plan_hooks_test.rb +1 -0
- data/test/execution_plan_test.rb +10 -32
- data/test/executor_test.rb +20 -37
- data/test/extensions_test.rb +1 -0
- data/test/flows_test.rb +2 -2
- data/test/future_execution_test.rb +2 -3
- data/test/memory_cosumption_watcher_test.rb +1 -0
- data/test/middleware_test.rb +4 -6
- data/test/persistence_test.rb +26 -26
- data/test/redis_locking_test.rb +1 -0
- data/test/rescue_test.rb +3 -11
- data/test/round_robin_test.rb +1 -0
- data/test/semaphores_test.rb +5 -7
- data/test/support/code_workflow_example.rb +11 -28
- data/test/support/dummy_example.rb +20 -19
- data/test/support/middleware_example.rb +2 -8
- data/test/support/rescue_example.rb +1 -14
- data/test/support/test_execution_log.rb +1 -2
- data/test/test_helper.rb +3 -7
- data/test/testing_test.rb +6 -8
- data/test/utils_test.rb +1 -0
- data/test/v2_sub_plans_test.rb +1 -0
- data/test/web_console_test.rb +4 -4
- data/test/world_test.rb +4 -3
- metadata +43 -43
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
module Debug
|
4
5
|
module Telemetry
|
@@ -32,7 +33,7 @@ module Dynflow
|
|
32
33
|
|
33
34
|
methods.each do |name|
|
34
35
|
define_method(name) do |*args|
|
35
|
-
Dynflow::Telemetry.measure(:dynflow_persistence, :method => name, :world => @world.id) { super
|
36
|
+
Dynflow::Telemetry.measure(:dynflow_persistence, :method => name, :world => @world.id) { super(*args) }
|
36
37
|
end
|
37
38
|
end
|
38
39
|
end
|
@@ -40,4 +41,4 @@ module Dynflow
|
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
43
|
-
::Dynflow::Persistence.
|
44
|
+
::Dynflow::Persistence.prepend ::Dynflow::Debug::Persistence
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
module DelayedExecutors
|
4
5
|
class Abstract
|
5
|
-
|
6
6
|
attr_reader :core
|
7
7
|
|
8
8
|
def initialize(world, options = {})
|
@@ -39,7 +39,6 @@ module Dynflow
|
|
39
39
|
def core_class
|
40
40
|
raise NotImplementedError
|
41
41
|
end
|
42
|
-
|
43
42
|
end
|
44
43
|
end
|
45
44
|
end
|
data/lib/dynflow/delayed_plan.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
class DelayedPlan < Serializable
|
4
|
-
|
5
5
|
include Algebrick::TypeCheck
|
6
6
|
|
7
7
|
attr_reader :execution_plan_uuid, :start_before
|
@@ -72,11 +72,11 @@ module Dynflow
|
|
72
72
|
def self.new_from_hash(world, hash, *args)
|
73
73
|
serializer = Utils.constantize(hash[:args_serializer]).new(nil, hash[:serialized_args])
|
74
74
|
self.new(world,
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
75
|
+
hash[:execution_plan_uuid],
|
76
|
+
string_to_time(hash[:start_at]),
|
77
|
+
string_to_time(hash[:start_before]),
|
78
|
+
serializer,
|
79
|
+
hash[:frozen] || false)
|
80
80
|
rescue NameError => e
|
81
81
|
error(e.message)
|
82
82
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
class Director
|
4
5
|
class QueueHash
|
@@ -7,7 +8,7 @@ module Dynflow
|
|
7
8
|
def initialize(key_type = Object, value_type = Object)
|
8
9
|
@key_type = key_type
|
9
10
|
@value_type = value_type
|
10
|
-
@stash
|
11
|
+
@stash = Hash.new { |hash, key| hash[key] = [] }
|
11
12
|
end
|
12
13
|
|
13
14
|
def push(key, value)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
class Director
|
4
5
|
# Handles the events generated while running actions, makes sure
|
@@ -50,13 +51,13 @@ module Dynflow
|
|
50
51
|
while (work = @work_items.shift(step.id))
|
51
52
|
@world.logger.debug "step #{step.execution_plan_id}:#{step.id} dropping event #{work.request_id}/#{work.event}"
|
52
53
|
finish_event_result(work) do |f|
|
53
|
-
f.reject
|
54
|
+
f.reject(UnprocessableEvent.new("Message dropped").tap { |e| e.set_backtrace(caller) })
|
54
55
|
end
|
55
56
|
end
|
56
57
|
while (event = @events.shift(step.id))
|
57
58
|
@world.logger.debug "step #{step.execution_plan_id}:#{step.id} dropping event #{event.request_id}/#{event}"
|
58
59
|
if event.result
|
59
|
-
event.result.reject
|
60
|
+
event.result.reject(UnprocessableEvent.new("Message dropped").tap { |e| e.set_backtrace(caller) })
|
60
61
|
end
|
61
62
|
end
|
62
63
|
unless @work_items.empty?(step.id) && @events.empty?(step.id)
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
class Director
|
4
5
|
class SequenceCursor
|
5
|
-
|
6
6
|
def initialize(flow_manager, sequence, parent_cursor = nil)
|
7
7
|
@flow_manager = flow_manager
|
8
8
|
@sequence = sequence
|
@@ -86,7 +86,6 @@ module Dynflow
|
|
86
86
|
@todo << @flow_manager.execution_plan.steps[flow.step_id]
|
87
87
|
end
|
88
88
|
end
|
89
|
-
|
90
89
|
end
|
91
90
|
end
|
92
91
|
end
|
data/lib/dynflow/director.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
# Director is responsible for telling what to do next when:
|
4
5
|
# * new execution starts
|
@@ -75,9 +76,9 @@ module Dynflow
|
|
75
76
|
|
76
77
|
def self.new_from_hash(hash, *_args)
|
77
78
|
self.new(hash[:execution_plan_id],
|
78
|
-
|
79
|
-
|
80
|
-
|
79
|
+
Serializable.from_hash(hash[:step], hash[:execution_plan_id], Dynflow.process_world),
|
80
|
+
hash[:queue],
|
81
|
+
hash[:sender_orchestrator_id])
|
81
82
|
end
|
82
83
|
end
|
83
84
|
|
@@ -100,11 +101,11 @@ module Dynflow
|
|
100
101
|
|
101
102
|
def self.new_from_hash(hash, *_args)
|
102
103
|
self.new(hash[:request_id],
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
104
|
+
hash[:execution_plan_id],
|
105
|
+
Serializable.from_hash(hash[:step], hash[:execution_plan_id], Dynflow.process_world),
|
106
|
+
Dynflow.serializer.load(hash[:event]),
|
107
|
+
hash[:queue],
|
108
|
+
hash[:sender_orchestrator_id])
|
108
109
|
end
|
109
110
|
end
|
110
111
|
|
@@ -301,16 +302,16 @@ module Dynflow
|
|
301
302
|
|
302
303
|
if @execution_plan_managers[execution_plan_id]
|
303
304
|
raise Dynflow::Error,
|
304
|
-
|
305
|
+
"cannot execute execution_plan_id:#{execution_plan_id} it's already running"
|
305
306
|
end
|
306
307
|
|
307
308
|
if execution_plan.state == :stopped
|
308
309
|
raise Dynflow::Error,
|
309
|
-
|
310
|
+
"cannot execute execution_plan_id:#{execution_plan_id} it's stopped"
|
310
311
|
end
|
311
312
|
|
312
313
|
@execution_plan_managers[execution_plan_id] =
|
313
|
-
|
314
|
+
ExecutionPlanManager.new(@world, execution_plan, finished)
|
314
315
|
rescue Dynflow::Error => e
|
315
316
|
finished.reject e
|
316
317
|
nil
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
module Dispatcher
|
4
5
|
class ClientDispatcher < Abstract
|
5
|
-
|
6
6
|
TrackedRequest = Algebrick.type do
|
7
7
|
fields! id: String, request: Request,
|
8
8
|
accepted: Concurrent::Promises::ResolvableFuture, finished: Concurrent::Promises::ResolvableFuture
|
@@ -134,16 +134,16 @@ module Dynflow
|
|
134
134
|
def dispatch_request(request, client_world_id, request_id)
|
135
135
|
ignore_unknown = false
|
136
136
|
executor_id = match request,
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
137
|
+
(on ~Execution | ~Planning do |execution|
|
138
|
+
AnyExecutor
|
139
|
+
end),
|
140
|
+
(on ~Event do |event|
|
141
|
+
ignore_unknown = event.optional
|
142
|
+
find_executor(event.execution_plan_id)
|
143
|
+
end),
|
144
|
+
(on Ping.(~any, ~any) | Status.(~any, ~any) do |receiver_id, _|
|
145
|
+
receiver_id
|
146
|
+
end)
|
147
147
|
envelope = Envelope[request_id, client_world_id, executor_id, request]
|
148
148
|
if Dispatcher::UnknownWorld === envelope.receiver_id
|
149
149
|
raise Dynflow::Error, "Could not find an executor for #{envelope}" unless ignore_unknown
|
@@ -161,22 +161,22 @@ module Dynflow
|
|
161
161
|
def dispatch_response(envelope)
|
162
162
|
return unless @tracked_requests.key?(envelope.request_id)
|
163
163
|
match envelope.message,
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
164
|
+
(on ~Accepted do
|
165
|
+
@tracked_requests[envelope.request_id].accept!
|
166
|
+
end),
|
167
|
+
(on ~Failed do |msg|
|
168
|
+
resolve_tracked_request(envelope.request_id, Dynflow::Error.new(msg.error))
|
169
|
+
end),
|
170
|
+
(on Done do
|
171
|
+
resolve_tracked_request(envelope.request_id)
|
172
|
+
end),
|
173
|
+
(on Pong do
|
174
|
+
add_ping_cache_record(envelope.sender_id)
|
175
|
+
resolve_tracked_request(envelope.request_id)
|
176
|
+
end),
|
177
|
+
(on ExecutionStatus.(~any) do |steps|
|
178
|
+
@tracked_requests.delete(envelope.request_id).success! steps
|
179
|
+
end)
|
180
180
|
end
|
181
181
|
|
182
182
|
# Records when was the world with provided id last seen using a PingCache
|
@@ -233,12 +233,12 @@ module Dynflow
|
|
233
233
|
else
|
234
234
|
tracked_request = @tracked_requests[id]
|
235
235
|
resolve_to = match tracked_request.request,
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
236
|
+
(on Execution.(execution_plan_id: ~any) do |uuid|
|
237
|
+
@world.persistence.load_execution_plan(uuid)
|
238
|
+
end),
|
239
|
+
(on Event | Ping do
|
240
|
+
true
|
241
|
+
end)
|
242
242
|
@tracked_requests.delete(id).success! resolve_to
|
243
243
|
end
|
244
244
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
module Dispatcher
|
4
5
|
class ExecutorDispatcher < Abstract
|
@@ -9,10 +10,10 @@ module Dynflow
|
|
9
10
|
|
10
11
|
def handle_request(envelope)
|
11
12
|
match(envelope.message,
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
on(Planning) { perform_planning(envelope, envelope.message) },
|
14
|
+
on(Execution) { perform_execution(envelope, envelope.message) },
|
15
|
+
on(Event) { perform_event(envelope, envelope.message) },
|
16
|
+
on(Status) { get_execution_status(envelope, envelope.message) })
|
16
17
|
end
|
17
18
|
|
18
19
|
protected
|
@@ -61,13 +62,13 @@ module Dynflow
|
|
61
62
|
end
|
62
63
|
if event_request.time.nil? || event_request.time < Time.now
|
63
64
|
@world.executor.event(envelope.request_id, event_request.execution_plan_id, event_request.step_id, event_request.event, future,
|
64
|
-
|
65
|
+
optional: event_request.optional)
|
65
66
|
else
|
66
67
|
@world.clock.ping(
|
67
68
|
@world.executor,
|
68
69
|
event_request.time,
|
69
70
|
Director::Event[envelope.request_id, event_request.execution_plan_id, event_request.step_id, event_request.event, Concurrent::Promises.resolvable_future,
|
70
|
-
|
71
|
+
event_request.optional],
|
71
72
|
:delayed_event
|
72
73
|
)
|
73
74
|
# resolves the future right away - currently we do not wait for the clock ping
|
data/lib/dynflow/dispatcher.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
module Dispatcher
|
4
5
|
Request = Algebrick.type do
|
@@ -33,10 +34,10 @@ module Dynflow
|
|
33
34
|
|
34
35
|
Response = Algebrick.type do
|
35
36
|
variants Accepted = atom,
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
Failed = type { fields! error: String },
|
38
|
+
Done = atom,
|
39
|
+
Pong = atom,
|
40
|
+
ExecutionStatus = type { fields! execution_status: Hash }
|
40
41
|
end
|
41
42
|
|
42
43
|
Envelope = Algebrick.type do
|
@@ -49,9 +50,9 @@ module Dynflow
|
|
49
50
|
module Envelope
|
50
51
|
def build_response_envelope(response_message, sender)
|
51
52
|
Envelope[self.request_id,
|
52
|
-
|
53
|
-
|
54
|
-
|
53
|
+
sender.id,
|
54
|
+
self.sender_id,
|
55
|
+
response_message]
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
data/lib/dynflow/errors.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
class ExecutionHistory
|
4
5
|
include Algebrick::TypeCheck
|
@@ -35,7 +36,7 @@ module Dynflow
|
|
35
36
|
end
|
36
37
|
|
37
38
|
def inspect
|
38
|
-
"ExecutionHistory: #{
|
39
|
+
"ExecutionHistory: #{@events.inspect}"
|
39
40
|
end
|
40
41
|
|
41
42
|
def self.new_from_hash(value)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
class ExecutionPlan::DependencyGraph
|
4
|
-
|
5
5
|
def initialize
|
6
6
|
@graph = Hash.new { |h, k| h[k] = Set.new }
|
7
7
|
end
|
@@ -25,6 +25,5 @@ module Dynflow
|
|
25
25
|
def unresolved?
|
26
26
|
@graph.any? { |step_id, required_step_ids| required_step_ids.any? }
|
27
27
|
end
|
28
|
-
|
29
28
|
end
|
30
29
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
class ExecutionPlan::OutputReference < Serializable
|
4
5
|
include Algebrick::TypeCheck
|
@@ -77,10 +78,9 @@ module Dynflow
|
|
77
78
|
def self.new_from_hash(hash)
|
78
79
|
check_class_matching hash
|
79
80
|
new(hash.fetch(:execution_plan_id),
|
80
|
-
|
81
|
-
|
82
|
-
|
81
|
+
hash.fetch(:step_id),
|
82
|
+
hash.fetch(:action_id),
|
83
|
+
hash.fetch(:subkeys))
|
83
84
|
end
|
84
|
-
|
85
85
|
end
|
86
86
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
module ExecutionPlan::Steps
|
4
5
|
class Abstract < Serializable
|
@@ -6,7 +7,7 @@ module Dynflow
|
|
6
7
|
include Stateful
|
7
8
|
|
8
9
|
attr_reader :execution_plan_id, :id, :state, :action_class, :action_id, :world, :started_at,
|
9
|
-
|
10
|
+
:ended_at, :execution_time, :real_time, :queue, :delayed_events
|
10
11
|
attr_accessor :error
|
11
12
|
|
12
13
|
# rubocop:disable Metrics/ParameterLists
|
@@ -37,7 +38,7 @@ module Dynflow
|
|
37
38
|
@progress_done = Type! progress_done, Numeric, NilClass
|
38
39
|
@progress_weight = Type! progress_weight, Numeric, NilClass
|
39
40
|
|
40
|
-
@queue
|
41
|
+
@queue = Type! queue, Symbol, NilClass
|
41
42
|
|
42
43
|
self.state = state.to_sym
|
43
44
|
|
@@ -144,25 +145,25 @@ module Dynflow
|
|
144
145
|
def self.new_from_hash(hash, execution_plan_id, world)
|
145
146
|
check_class_matching hash
|
146
147
|
new(execution_plan_id,
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
148
|
+
hash[:id],
|
149
|
+
hash[:state],
|
150
|
+
Action.constantize(hash[:action_class]),
|
151
|
+
hash[:action_id],
|
152
|
+
hash_to_error(hash[:error]),
|
153
|
+
world,
|
154
|
+
string_to_time(hash[:started_at]),
|
155
|
+
string_to_time(hash[:ended_at]),
|
156
|
+
hash[:execution_time].to_f,
|
157
|
+
hash[:real_time].to_f,
|
158
|
+
hash[:progress_done].to_f,
|
159
|
+
hash[:progress_weight].to_f,
|
160
|
+
(hash[:queue] && hash[:queue].to_sym))
|
160
161
|
end
|
161
162
|
|
162
163
|
private
|
163
164
|
|
164
165
|
def with_meta_calculation(action, &block)
|
165
|
-
start
|
166
|
+
start = Time.now.utc
|
166
167
|
@started_at ||= start
|
167
168
|
block.call
|
168
169
|
ensure
|
@@ -186,12 +187,12 @@ module Dynflow
|
|
186
187
|
Dynflow::Telemetry.with_instance do |t|
|
187
188
|
if [:success, :skipped].include?(state)
|
188
189
|
t.observe_histogram(:dynflow_step_real_time,
|
189
|
-
|
190
|
-
|
190
|
+
real_time * 1000,
|
191
|
+
:action => action_class.to_s, :phase => phase.to_s_humanized)
|
191
192
|
end
|
192
193
|
t.observe_histogram(:dynflow_step_execution_time,
|
193
|
-
|
194
|
-
|
194
|
+
current_execution_time * 1000,
|
195
|
+
:action => action_class.to_s, :phase => phase.to_s_humanized)
|
195
196
|
end
|
196
197
|
end
|
197
198
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
module ExecutionPlan::Steps
|
4
5
|
class AbstractFlowStep < Abstract
|
5
|
-
|
6
6
|
# Method called when initializing the step to customize the behavior based on the
|
7
7
|
# action definition during the planning phase
|
8
8
|
def update_from_action(action)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
module ExecutionPlan::Steps
|
4
5
|
class Error < Serializable
|
@@ -11,12 +12,12 @@ module Dynflow
|
|
11
12
|
case args.size
|
12
13
|
when 1
|
13
14
|
match obj = args.first,
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
(on String do
|
16
|
+
super(StandardError, obj, caller, nil)
|
17
|
+
end),
|
18
|
+
(on Exception do
|
19
|
+
super(obj.class, obj.message, obj.backtrace, obj)
|
20
|
+
end)
|
20
21
|
when 3, 4
|
21
22
|
super(*args.values_at(0..3))
|
22
23
|
else
|
@@ -49,9 +50,9 @@ module Dynflow
|
|
49
50
|
|
50
51
|
def to_s
|
51
52
|
format '%s (%s)\n%s',
|
52
|
-
|
53
|
-
|
54
|
-
|
53
|
+
(@exception || self).message,
|
54
|
+
(@exception ? @exception.class : exception_class),
|
55
|
+
(@exception || self).backtrace
|
55
56
|
end
|
56
57
|
|
57
58
|
def exception
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Dynflow
|
3
4
|
module ExecutionPlan::Steps
|
4
5
|
class FinalizeStep < AbstractFlowStep
|
5
|
-
|
6
6
|
def self.state_transitions
|
7
7
|
@state_transitions ||= {
|
8
8
|
pending: [:running, :skipped], # :skipped when its run_step is skipped
|
@@ -27,7 +27,6 @@ module Dynflow
|
|
27
27
|
self.state = :skipped
|
28
28
|
self.save
|
29
29
|
end
|
30
|
-
|
31
30
|
end
|
32
31
|
end
|
33
32
|
end
|