dynflow 0.8.3 → 0.8.4

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.
Files changed (44) hide show
  1. checksums.yaml +8 -8
  2. data/doc/pages/source/documentation/index.md +14 -14
  3. data/dynflow.gemspec +0 -1
  4. data/examples/future_execution.rb +7 -7
  5. data/lib/dynflow.rb +3 -3
  6. data/lib/dynflow/action.rb +7 -9
  7. data/lib/dynflow/action/with_sub_plans.rb +9 -3
  8. data/lib/dynflow/config.rb +2 -2
  9. data/lib/dynflow/coordinator.rb +3 -3
  10. data/lib/dynflow/delayed_executors.rb +9 -0
  11. data/lib/dynflow/{schedulers → delayed_executors}/abstract.rb +3 -3
  12. data/lib/dynflow/{schedulers → delayed_executors}/abstract_core.rb +7 -7
  13. data/lib/dynflow/{schedulers → delayed_executors}/polling.rb +6 -6
  14. data/lib/dynflow/{scheduled_plan.rb → delayed_plan.rb} +4 -4
  15. data/lib/dynflow/execution_plan.rb +10 -10
  16. data/lib/dynflow/execution_plan/output_reference.rb +2 -2
  17. data/lib/dynflow/execution_plan/steps/error.rb +1 -1
  18. data/lib/dynflow/execution_plan/steps/plan_step.rb +2 -2
  19. data/lib/dynflow/middleware.rb +1 -1
  20. data/lib/dynflow/middleware/stack.rb +1 -1
  21. data/lib/dynflow/middleware/world.rb +1 -1
  22. data/lib/dynflow/persistence.rb +10 -10
  23. data/lib/dynflow/persistence_adapters/abstract.rb +4 -4
  24. data/lib/dynflow/persistence_adapters/sequel.rb +17 -17
  25. data/lib/dynflow/persistence_adapters/sequel_migrations/008_rename_scheduled_plans_to_delayed_plans.rb +5 -0
  26. data/lib/dynflow/serializable.rb +1 -1
  27. data/lib/dynflow/serializer.rb +1 -1
  28. data/lib/dynflow/testing/assertions.rb +1 -1
  29. data/lib/dynflow/utils.rb +205 -0
  30. data/lib/dynflow/version.rb +1 -1
  31. data/lib/dynflow/web/console_helpers.rb +1 -1
  32. data/lib/dynflow/web/filtering_helpers.rb +3 -3
  33. data/lib/dynflow/world.rb +16 -16
  34. data/test/action_test.rb +4 -2
  35. data/test/future_execution_test.rb +32 -32
  36. data/test/middleware_test.rb +5 -5
  37. data/test/persistence_test.rb +3 -3
  38. data/test/support/dummy_example.rb +2 -2
  39. data/test/support/middleware_example.rb +5 -5
  40. data/test/test_helper.rb +1 -1
  41. data/test/testing_test.rb +1 -1
  42. data/web/views/show.erb +3 -3
  43. metadata +9 -21
  44. data/lib/dynflow/schedulers.rb +0 -9
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ODk3MTc2Nzc3ZDFmNTMwYTNiMDFjZmIyOWIxZjI5NTY4ZGRjNWE5MQ==
4
+ ZWZjMGI1OWM2ZWQ4N2JiNDM5MDVmMDA1NmJlODJiMmJmNzg1ZDRjOA==
5
5
  data.tar.gz: !binary |-
6
- ZGVhZTBhMGZkNWFkYzcxNWZjY2I2MDNlM2ZiNzFlMmJkNGRhZTQ4NQ==
6
+ ZWFhMTBiOWU0NTVjZTEyMGM5NDlhYTY1NDg0ZDVjYjg5MzJhZDFhMg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ODBjYjZmNWNmODU5ZWE4Y2JiYTBjNmE4OTYyNWExNjc0ZTg2OGMxZDI5NjEw
10
- ZDUyNWNiODgxNGE2NTBhYmU0ODdkM2QyNmU3ODdmMDRjZDY4Y2U0NDdjM2Y5
11
- OWRhMGViNWMyMjk0YmM2N2U2ZjE0ZDFkZmY0NjAwNDg3MDk5M2E=
9
+ ZDI4ZGVlNjQ5NGZkZGFhY2I3ZTlmZmJkNjRiZTMzODVkMDYzODAwNWNkYzU5
10
+ OTFjNGRiNWZjYzAwOTdjNDc5ZDcxMjk2MWNlMWVlNzdiYzhlNDVmMWExYTFl
11
+ MWZjYTAxZjMwODY1NTM2MWZiODliZjU2OTI3NGIyZThkNGU4YTI=
12
12
  data.tar.gz: !binary |-
13
- YmU2NGFlOWU3YWY1NGRhMjc0MDA3Yjg4OTU2OTY1NzAyNjNjZTY1YzUzN2Fl
14
- MWIyNDlkYmM0ZDVkMjAxMTRmYjIwNDM3MjE2OTBkMGRmOGRiY2ExODY3YzQ2
15
- NDQzNzZhYmRiNWM4ZTUyYmU5YzcwYzk2ZWZjM2JmYmZmYTYyMGY=
13
+ OGEwM2M2YzViODM3Njc2NTExNTE0ZTY5YjA1NjNiNzJhMzIwNDBiZmQ2MmY0
14
+ NTg1MTBiYzViYjRjYmQ2MzU3YTFhZTdhOWQzZWIxMDYyZDM0NjM4YTZjYjc2
15
+ YTQyZTU1MWQ0MzcxYjMwNmYwYTM1NmUyOTc0YWQwZjQ1ZTU0OWM=
@@ -235,7 +235,7 @@ TriggerResult = Algebrick.type do
235
235
  PlaningFailed = type { fields! execution_plan_id: String, error: Exception }
236
236
  # Returned by #trigger when planning is successful but execution fails to start.
237
237
  ExecutionFailed = type { fields! execution_plan_id: String, error: Exception }
238
- # Returned by #schedule when scheduling succeeded.
238
+ # Returned by #delay when scheduling succeeded.
239
239
  Scheduled = type { fields! execution_plan_id: String }
240
240
  # Returned by #trigger when planning is successful, #future will resolve after
241
241
  # ExecutionPlan is executed.
@@ -273,19 +273,19 @@ end
273
273
  #### Scheduling
274
274
 
275
275
  Scheduling an action means setting it up to be triggered at set time in future.
276
- Any action can be scheduled by calling:
276
+ Any action can be delayed by calling:
277
277
 
278
278
  ```ruby
279
- world_instance.schedule(AnAction,
280
- { start_at: Time.now + 360, start_before: Time.now + 400 },
281
- *args)
279
+ world_instance.delay(AnAction,
280
+ { start_at: Time.now + 360, start_before: Time.now + 400 },
281
+ *args)
282
282
  ```
283
283
 
284
- This snippet of code would schedule `AnAction` with arguments `args` to be executed
284
+ This snippet of code would delay `AnAction` with arguments `args` to be executed
285
285
  in the time interval between `start_at` and `start_before`. Setting `start_before` to `nil`
286
- would schedule this action without the timeout limit.
286
+ would delay execution of this action without the timeout limit.
287
287
 
288
- When an action is scheduled, an execution plan object is created with state set
288
+ When an action is delayed, an execution plan object is created with state set
289
289
  to `scheduled`, but it doesn't run the the plan phase yet, the planning happens
290
290
  when the `start_at` time comes. If the planning doesn't happen in time
291
291
  (e.g. after `start_before`), the execution plan is marked as failed
@@ -293,12 +293,12 @@ when the `start_at` time comes. If the planning doesn't happen in time
293
293
 
294
294
  Since the `args` have to be saved, there must be a mechanism to safely serialize and deserialize them
295
295
  in order to make them survive being saved in a database. This is handled by a serializer.
296
- Different serializers can be set per action by overriding its `schedule` method.
296
+ Different serializers can be set per action by overriding its `delay` method.
297
297
 
298
- Planning of the scheduled plans is handled by `Scheduler`, an object which
299
- periodically checks for scheduled execution plans and plans them. Scheduled execution
300
- plans don't do anything by themselves, they just wait to be picked up and planned by a Scheduler.
301
- It means that if no scheduler is present, their planning will be delayed until a scheduler
298
+ Planning of the delayed plans is handled by `DelayedExecutor`, an object which
299
+ periodically checks for delayed execution plans and plans them. Scheduled execution
300
+ plans don't do anything by themselves, they just wait to be picked up and planned by a DelayedExecutor.
301
+ It means that if no DelayedExecutor is present, their planning will be delayed until a scheduler
302
302
  is spawned.
303
303
 
304
304
  #### Plan phase
@@ -1015,7 +1015,7 @@ client worlds: useful in production, see [develpment vs. production](#developmen
1015
1015
  client requests and other worlds
1016
1016
  1. **executor dispatcher** - responsible for getting requests from
1017
1017
  other worlds and sending the responses
1018
- 1. **scheduler** - responsible for planning and exectuion of scheduled tasks
1018
+ 1. **delayed executor** - responsible for planning and exectuion of scheduled tasks
1019
1019
 
1020
1020
  {% plantuml %}
1021
1021
 
@@ -18,7 +18,6 @@ Gem::Specification.new do |s|
18
18
 
19
19
  s.required_ruby_version = '>= 1.9.3'
20
20
 
21
- s.add_dependency "activesupport"
22
21
  s.add_dependency "multi_json"
23
22
  s.add_dependency "apipie-params"
24
23
  s.add_dependency "algebrick", '~> 0.7.0'
@@ -26,7 +26,7 @@ end
26
26
 
27
27
  class DelayedAction < Dynflow::Action
28
28
 
29
- def schedule(schedule_options, *args)
29
+ def delay(delay_options, *args)
30
30
  CustomPassedObjectSerializer.new(args)
31
31
  end
32
32
 
@@ -49,9 +49,9 @@ if $0 == __FILE__
49
49
 
50
50
  object = CustomPassedObject.new(1, 'CPS')
51
51
 
52
- past_plan = ExampleHelper.world.schedule(DelayedAction, { :start_at => past, :start_before => past }, object)
53
- near_future_plan = ExampleHelper.world.schedule(DelayedAction, { :start_at => near_future, :start_before => future }, object)
54
- future_plan = ExampleHelper.world.schedule(DelayedAction, { :start_at => future }, object)
52
+ past_plan = ExampleHelper.world.delay(DelayedAction, { :start_at => past, :start_before => past }, object)
53
+ near_future_plan = ExampleHelper.world.delay(DelayedAction, { :start_at => near_future, :start_before => future }, object)
54
+ future_plan = ExampleHelper.world.delay(DelayedAction, { :start_at => future }, object)
55
55
 
56
56
  puts <<-MSG.gsub(/^.*\|/, '')
57
57
  |
@@ -61,9 +61,9 @@ if $0 == __FILE__
61
61
  | This example shows the future execution functionality of Dynflow, which allows to plan actions to be executed at set time.
62
62
  |
63
63
  | Execution plans:
64
- | #{past_plan.id} is scheduled to execute before #{past} and should timeout on the first run of the scheduler.
65
- | #{near_future_plan.id} is scheduled to execute at #{near_future} and should run successfully.
66
- | #{future_plan.id} is scheduled to execute at #{future} and should run successfully.
64
+ | #{past_plan.id} is "delayed" to execute before #{past} and should timeout on the first run of the scheduler.
65
+ | #{near_future_plan.id} is delayed to execute at #{near_future} and should run successfully.
66
+ | #{future_plan.id} is delayed to execute at #{future} and should run successfully.
67
67
  |
68
68
  | Visit http://localhost:4567 to see their status.
69
69
  |
@@ -2,7 +2,6 @@ require 'apipie-params'
2
2
  require 'algebrick'
3
3
  require 'thread'
4
4
  require 'set'
5
- require 'active_support/core_ext/hash/indifferent_access'
6
5
  require 'base64'
7
6
  require 'concurrent'
8
7
  require 'concurrent-edge'
@@ -22,6 +21,7 @@ module Dynflow
22
21
  class Error < StandardError
23
22
  end
24
23
 
24
+ require 'dynflow/utils'
25
25
  require 'dynflow/round_robin'
26
26
  require 'dynflow/actor'
27
27
  require 'dynflow/errors'
@@ -36,7 +36,7 @@ module Dynflow
36
36
  require 'dynflow/flows'
37
37
  require 'dynflow/execution_history'
38
38
  require 'dynflow/execution_plan'
39
- require 'dynflow/scheduled_plan'
39
+ require 'dynflow/delayed_plan'
40
40
  require 'dynflow/action'
41
41
  require 'dynflow/executors'
42
42
  require 'dynflow/logger_adapters'
@@ -44,6 +44,6 @@ module Dynflow
44
44
  require 'dynflow/connectors'
45
45
  require 'dynflow/dispatcher'
46
46
  require 'dynflow/serializers'
47
- require 'dynflow/schedulers'
47
+ require 'dynflow/delayed_executors'
48
48
  require 'dynflow/config'
49
49
  end
@@ -1,5 +1,3 @@
1
- require 'active_support/inflector'
2
-
3
1
  module Dynflow
4
2
  class Action < Serializable
5
3
 
@@ -127,13 +125,13 @@ module Dynflow
127
125
  def input=(hash)
128
126
  Type! hash, Hash
129
127
  phase! Plan
130
- @input = hash.with_indifferent_access
128
+ @input = Utils.indifferent_hash(hash)
131
129
  end
132
130
 
133
131
  def output=(hash)
134
132
  Type! hash, Hash
135
133
  phase! Run
136
- @output = hash.with_indifferent_access
134
+ @output = Utlis.indifferent_hash(hash)
137
135
  end
138
136
 
139
137
  def output
@@ -282,10 +280,10 @@ module Dynflow
282
280
  recursion.(input)
283
281
  end
284
282
 
285
- def execute_schedule(schedule_options, *args)
283
+ def execute_delay(delay_options, *args)
286
284
  with_error_handling(true) do
287
- world.middleware.execute(:schedule, self, schedule_options, *args) do
288
- @serializer = schedule(schedule_options, *args).tap do |serializer|
285
+ world.middleware.execute(:delay, self, delay_options, *args) do
286
+ @serializer = delay(delay_options, *args).tap do |serializer|
289
287
  serializer.perform_serialization!
290
288
  end
291
289
  end
@@ -293,7 +291,7 @@ module Dynflow
293
291
  end
294
292
 
295
293
  def serializer
296
- raise "The action must be scheduled in order to access the serializer" if @serializer.nil?
294
+ raise "The action must be delayed in order to access the serializer" if @serializer.nil?
297
295
  @serializer
298
296
  end
299
297
 
@@ -313,7 +311,7 @@ module Dynflow
313
311
  @step.save
314
312
  end
315
313
 
316
- def schedule(schedule_options, *args)
314
+ def delay(delay_options, *args)
317
315
  Serializers::Noop.new(args)
318
316
  end
319
317
 
@@ -67,7 +67,8 @@ module Dynflow
67
67
  def wait_for_sub_plans(sub_plans)
68
68
  output.update(total_count: 0,
69
69
  failed_count: 0,
70
- success_count: 0)
70
+ success_count: 0,
71
+ pending_count: 0)
71
72
 
72
73
  planned, failed = sub_plans.partition(&:planned?)
73
74
 
@@ -75,6 +76,7 @@ module Dynflow
75
76
 
76
77
  output[:total_count] = sub_plan_ids.size
77
78
  output[:failed_count] = failed.size
79
+ output[:pending_count] = planned.size
78
80
 
79
81
  if planned.any?
80
82
  notify_on_finish(planned)
@@ -123,6 +125,7 @@ module Dynflow
123
125
  else
124
126
  output[:failed_count] += 1
125
127
  end
128
+ output[:pending_count] -= 1
126
129
  end
127
130
 
128
131
  def done?
@@ -144,7 +147,8 @@ module Dynflow
144
147
  def recalculate_counts
145
148
  output.update(total_count: 0,
146
149
  failed_count: 0,
147
- success_count: 0)
150
+ success_count: 0,
151
+ pending_count: 0)
148
152
  sub_plans.each do |sub_plan|
149
153
  output[:total_count] += 1
150
154
  if sub_plan.state == :stopped
@@ -153,12 +157,14 @@ module Dynflow
153
157
  else
154
158
  output[:success_count] += 1
155
159
  end
160
+ else
161
+ output[:pending_count] += 1
156
162
  end
157
163
  end
158
164
  end
159
165
 
160
166
  def counts_set?
161
- output[:total_count] && output[:success_count] && output[:failed_count]
167
+ output[:total_count] && output[:success_count] && output[:failed_count] && output[:pending_count]
162
168
  end
163
169
 
164
170
  def check_for_errors!
@@ -93,10 +93,10 @@ module Dynflow
93
93
  true
94
94
  end
95
95
 
96
- config_attr :scheduler, Schedulers::Abstract, NilClass do |world|
96
+ config_attr :delayed_executor, DelayedExecutors::Abstract, NilClass do |world|
97
97
  options = { :poll_interval => 15,
98
98
  :time_source => -> { Time.now.utc } }
99
- Schedulers::Polling.new(world, options)
99
+ DelayedExecutors::Polling.new(world, options)
100
100
  end
101
101
 
102
102
  config_attr :action_classes do
@@ -41,7 +41,7 @@ module Dynflow
41
41
 
42
42
  def initialize(*args)
43
43
  @data ||= {}
44
- @data = @data.merge(class: self.class.name).with_indifferent_access
44
+ @data = Utils.indifferent_hash(@data.merge(class: self.class.name))
45
45
  end
46
46
 
47
47
  def from_hash(hash)
@@ -157,10 +157,10 @@ module Dynflow
157
157
 
158
158
  end
159
159
 
160
- class SchedulerLock < LockByWorld
160
+ class DelayedExecutorLock < LockByWorld
161
161
  def initialize(world)
162
162
  super
163
- @data[:id] = "scheduler"
163
+ @data[:id] = "delayed-executor"
164
164
  end
165
165
  end
166
166
 
@@ -0,0 +1,9 @@
1
+ module Dynflow
2
+ module DelayedExecutors
3
+
4
+ require 'dynflow/delayed_executors/abstract'
5
+ require 'dynflow/delayed_executors/abstract_core'
6
+ require 'dynflow/delayed_executors/polling'
7
+
8
+ end
9
+ end
@@ -1,5 +1,5 @@
1
1
  module Dynflow
2
- module Schedulers
2
+ module DelayedExecutors
3
3
  class Abstract
4
4
 
5
5
  attr_reader :core
@@ -26,7 +26,7 @@ module Dynflow
26
26
 
27
27
  def spawn
28
28
  Concurrent.future.tap do |initialized|
29
- @core = core_class.spawn name: 'scheduler',
29
+ @core = core_class.spawn name: 'delayed-executor',
30
30
  args: [@world, @options],
31
31
  initialized: initialized
32
32
  end
@@ -34,4 +34,4 @@ module Dynflow
34
34
 
35
35
  end
36
36
  end
37
- end
37
+ end
@@ -1,5 +1,5 @@
1
1
  module Dynflow
2
- module Schedulers
2
+ module DelayedExecutors
3
3
  class AbstractCore < Actor
4
4
 
5
5
  include Algebrick::TypeCheck
@@ -19,7 +19,7 @@ module Dynflow
19
19
  @time_source = options.fetch(:time_source, -> { Time.now.utc })
20
20
  end
21
21
 
22
- def check_schedule
22
+ def check_delayed_plans
23
23
  raise NotImplementedError
24
24
  end
25
25
 
@@ -29,9 +29,9 @@ module Dynflow
29
29
  @time_source.call()
30
30
  end
31
31
 
32
- def scheduled_execution_plans(time)
32
+ def delayed_execution_plans(time)
33
33
  with_error_handling([]) do
34
- world.persistence.find_past_scheduled_plans(time)
34
+ world.persistence.find_past_delayed_plans(time)
35
35
  end
36
36
  end
37
37
 
@@ -42,9 +42,9 @@ module Dynflow
42
42
  error_retval
43
43
  end
44
44
 
45
- def process(scheduled_plans, check_time)
45
+ def process(delayed_plans, check_time)
46
46
  processed_plan_uuids = []
47
- scheduled_plans.each do |plan|
47
+ delayed_plans.each do |plan|
48
48
  with_error_handling do
49
49
  if !plan.start_before.nil? && plan.start_before < check_time
50
50
  @logger.debug "Failing plan #{plan.execution_plan_uuid}"
@@ -57,7 +57,7 @@ module Dynflow
57
57
  processed_plan_uuids << plan.execution_plan_uuid
58
58
  end
59
59
  end
60
- world.persistence.delete_scheduled_plans(:execution_plan_uuid => processed_plan_uuids) unless processed_plan_uuids.empty?
60
+ world.persistence.delete_delayed_plans(:execution_plan_uuid => processed_plan_uuids) unless processed_plan_uuids.empty?
61
61
  end
62
62
 
63
63
  end
@@ -1,9 +1,9 @@
1
1
  module Dynflow
2
- module Schedulers
2
+ module DelayedExecutors
3
3
  class Polling < Abstract
4
4
 
5
5
  def core_class
6
- Dynflow::Schedulers::PollingCore
6
+ Dynflow::DelayedExecutors::PollingCore
7
7
  end
8
8
 
9
9
  end
@@ -17,15 +17,15 @@ module Dynflow
17
17
  end
18
18
 
19
19
  def start
20
- check_schedule
20
+ check_delayed_plans
21
21
  end
22
22
 
23
- def check_schedule
23
+ def check_delayed_plans
24
24
  check_time = time
25
- plans = scheduled_execution_plans(check_time)
25
+ plans = delayed_execution_plans(check_time)
26
26
  process plans, check_time
27
27
 
28
- world.clock.ping(self, poll_interval, :check_schedule)
28
+ world.clock.ping(self, poll_interval, :check_delayed_plans)
29
29
  end
30
30
  end
31
31
  end
@@ -1,5 +1,5 @@
1
1
  module Dynflow
2
- class ScheduledPlan < Serializable
2
+ class DelayedPlan < Serializable
3
3
 
4
4
  include Algebrick::TypeCheck
5
5
 
@@ -37,8 +37,8 @@ module Dynflow
37
37
  end
38
38
 
39
39
  def cancel
40
- error("Scheduled task cancelled", "Scheduled task cancelled")
41
- @world.persistence.delete_scheduled_plans(:execution_plan_uuid => execution_plan.id)
40
+ error("Delayed task cancelled", "Delayed task cancelled")
41
+ @world.persistence.delete_delayed_plans(:execution_plan_uuid => execution_plan.id)
42
42
  return true
43
43
  end
44
44
 
@@ -56,7 +56,7 @@ module Dynflow
56
56
 
57
57
  # @api private
58
58
  def self.new_from_hash(world, hash, *args)
59
- serializer = hash[:args_serializer].constantize.new(nil, hash[:serialized_args])
59
+ serializer = Utils.constantize(hash[:args_serializer]).new(nil, hash[:serialized_args])
60
60
  self.new(world,
61
61
  hash[:execution_plan_uuid],
62
62
  string_to_time(hash[:start_at]),
@@ -152,23 +152,23 @@ module Dynflow
152
152
  @last_step_id += 1
153
153
  end
154
154
 
155
- def schedule(action_class, schedule_options, *args)
155
+ def delay(action_class, delay_options, *args)
156
156
  save
157
157
  @root_plan_step = add_scheduling_step(action_class)
158
- execution_history.add("schedule", @world.id)
159
- serializer = root_plan_step.schedule(schedule_options, args)
160
- scheduled_plan = ScheduledPlan.new(@world,
158
+ execution_history.add("delay", @world.id)
159
+ serializer = root_plan_step.delay(delay_options, args)
160
+ delayed_plan = DelayedPlan.new(@world,
161
161
  id,
162
- schedule_options[:start_at],
163
- schedule_options.fetch(:start_before, nil),
162
+ delay_options[:start_at],
163
+ delay_options.fetch(:start_before, nil),
164
164
  serializer)
165
- persistence.save_scheduled_plan(scheduled_plan)
165
+ persistence.save_delayed_plan(delayed_plan)
166
166
  ensure
167
167
  update_state(error? ? :stopped : :scheduled)
168
168
  end
169
169
 
170
- def schedule_record
171
- @schedule_record ||= persistence.load_scheduled_plan(id)
170
+ def delay_record
171
+ @delay_record ||= persistence.load_delayed_plan(id)
172
172
  end
173
173
 
174
174
  def prepare(action_class, options = {})
@@ -208,7 +208,7 @@ module Dynflow
208
208
  # array with the future value of the cancel result)
209
209
  def cancel
210
210
  if state == :scheduled
211
- [Concurrent.future.tap { |f| f.success schedule_record.cancel }]
211
+ [Concurrent.future.tap { |f| f.success delay_record.cancel }]
212
212
  else
213
213
  steps_to_cancel.map do |step|
214
214
  world.event(id, step.id, ::Dynflow::Action::Cancellable::Cancel)