Class: Eco::API::Session::Config::Workflow

Inherits:
Object
  • Object
show all
Extended by:
Common::ClassHierarchy
Defined in:
lib/eco/api/session/config/workflow.rb

Constant Summary collapse

WORKFLOW_MODEL =
[
  :options,
  {load: [{input: [:get, :filter]}, {people: [:get, :filter]}, :filter]},
  :usecases, :launch_jobs,
  {post_launch: [:usecases, :launch_jobs]},
  :report,
  :end,
  :close
]

Instance Attribute Summary collapse

Attributes included from Common::ClassHierarchy

#model

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Common::ClassHierarchy

model_attrs, parse_model

Methods included from Common::ClassHelpers

#class_resolver, #descendants, #descendants?, #inheritable_attrs, #inheritable_class_vars, #inherited, #instance_variable_name, #new_class, #resolve_class, #to_constant

Constructor Details

#initialize(name = nil, _parent: self, config:) ⇒ Workflow

Returns a new instance of Workflow.



43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/eco/api/session/config/workflow.rb', line 43

def initialize(name = nil, _parent: self, config:)
  @config   = config
  @name     = name

  @stages   = {}
  @_parent  = _parent

  @pending  = true
  # moments
  @on       = nil
  @before   = []
  @after    = []
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



41
42
43
# File 'lib/eco/api/session/config/workflow.rb', line 41

def config
  @config
end

Class Method Details

.modelObject



23
24
25
# File 'lib/eco/api/session/config/workflow.rb', line 23

def model
  super || {}
end

.stagesObject



19
20
21
# File 'lib/eco/api/session/config/workflow.rb', line 19

def stages
  model_attrs
end

.validate_stage(stage) ⇒ Object



27
28
29
# File 'lib/eco/api/session/config/workflow.rb', line 27

def validate_stage(stage)
  "Unknown Workflow stage '#{stage}'. Should be any of #{stages}" unless stages.include?(stage)
end

.workflow_class(key) ⇒ Object



31
32
33
34
35
36
37
# File 'lib/eco/api/session/config/workflow.rb', line 31

def workflow_class(key)
  class_name = to_constant(key.to_s)

  new_class(class_name, inherits: Eco::API::Session::Config::Workflow) do |klass|
    klass.model = model[key]
  end
end

Instance Method Details

#after(key = nil) {|stage_workflow, io| ... } ⇒ Eco::API::Session::Config::Workflow

Note:
  • it will not yield it immediately, but when the workflow reaches the target stage
  • in this case, you can define multiple callbacks

Used in configuration time add previous callbacks after the on callback of the (sub)stage key is actually run

Parameters:

  • key (Symbol, nil) (defaults to: nil)

    cases:

    • if key is not provided, it targets the current stage
    • if key is provided, it targets the specific sub-stage

Yields:

  • (stage_workflow, io)

    one of the things to do after the on callback of the (sub)stage key is actually run

Yield Parameters:

Yield Returns:

Returns:

Raises:

  • (ArgumentError)


183
184
185
186
187
188
189
190
191
# File 'lib/eco/api/session/config/workflow.rb', line 183

def after(key = nil, &block)
  raise ArgumentError, "A block should be given." unless block_given?
  if !key
    @after.push(block)
  else
    stage(key).after(&block)
  end
  self
end

#before(key = nil) {|stage_workflow, io| ... } ⇒ Eco::API::Session::Config::Workflow

Note:
  • it will not yield it immediately, but when the workflow reaches the target stage
  • in this case, you can define multiple callbacks

Used in configuration time add previous callbacks before the on callback of the (sub)stage key is actually run

Parameters:

  • key (Symbol, nil) (defaults to: nil)

    cases:

    • if key is not provided, it targets the current stage
    • if key is provided, it targets the specific sub-stage

Yields:

  • (stage_workflow, io)

    one of the things to do before the on callback of the (sub)stage key is actually run

Yield Parameters:

Yield Returns:

Returns:

Raises:

  • (ArgumentError)


161
162
163
164
165
166
167
168
169
# File 'lib/eco/api/session/config/workflow.rb', line 161

def before(key = nil, &block)
  raise ArgumentError, "A block should be given." unless block_given?
  if !key
    @before.push(block)
  else
    stage(key).before(&block)
  end
  self
end

#exit_handle(&block) ⇒ Object

Called on SystemExit exception



143
144
145
146
147
# File 'lib/eco/api/session/config/workflow.rb', line 143

def exit_handle(&block)
  return @exit_handle unless block
  @exit_handle = block
  self
end

#for(key = nil) {|stage_workflow| ... } ⇒ Eco::API::Session::Config::Workflow Also known as: with

Note:
  1. if a block is provided it will yield the target stage immediately
  2. a block is only required when key has not been specified.

Used in configuration time to configure the workflow of the target (sub)stage key

Parameters:

  • key (Symbol, nil) (defaults to: nil)

    cases:

    • if key is not provided, it targets the current stage
    • if key is provided, it targets the specific sub-stage

Yields:

  • (stage_workflow)

    further workflow configuration for the target stage key

Yield Parameters:

Returns:

  • (Eco::API::Session::Config::Workflow)
    1. if block is provided provided, it returns the current stage object (to ease chainig).
    2. if block is not provided, it returns the stage referred by key

Raises:

  • (ArgumentError)


98
99
100
101
102
103
104
105
# File 'lib/eco/api/session/config/workflow.rb', line 98

def for(key = nil, &block)
  raise ArgumentError, "With no 'key', a block should be given." unless key || block_given?
  self.tap do
    next yield(self)            unless key
    next stage(key).for(&block) if block_given?
    return stage(key)
  end
end

#name(with_path: false) ⇒ Object



57
58
59
60
# File 'lib/eco/api/session/config/workflow.rb', line 57

def name(with_path: false)
  return @name if !with_path || root?
  [@_parent.name(with_path: true), @name].compact.join('.')
end

#on(key = nil) {|stage_workflow, io| ... } ⇒ Eco::API::Session::Config::Workflow

Note:

if a block is provided it will not yield the target stage immediately, but when the workflow reaches the stage

Used in configuration time to define the behaviour the target (sub)stage key

Parameters:

  • key (Symbol, nil) (defaults to: nil)

    cases:

    • if key is not provided, it targets the current stage
    • if key is provided, it targets the specific sub-stage

Yields:

  • (stage_workflow, io)

    the behaviour of the target stage key when the workflow reaches it

Yield Parameters:

Yield Returns:

Returns:

Raises:

  • (ArgumentError)


118
119
120
121
122
123
124
125
126
# File 'lib/eco/api/session/config/workflow.rb', line 118

def on(key = nil, &block)
  raise ArgumentError, "A block should be given." unless block_given?
  if !key
    @on = block
  else
    stage(key).on(&block)
  end
  self
end

#pending?Boolean

Note:

it does not include sub-stages that run before

Has this stage run yet?

Returns:

  • (Boolean)

    true if it has run, false otherwise



65
66
67
# File 'lib/eco/api/session/config/workflow.rb', line 65

def pending?
  @pending
end

#rescue {|exception, io| ... } ⇒ Eco::API::Session::Config::Workflow Also known as: exception

When there is an Exception, you might have defined some callback to do something with it (i.e. register, email)

Yields:

  • (exception, io)

    the callback to do something with an Exception raised within this workflow stage

Yield Parameters:

Yield Returns:

Returns:



134
135
136
137
138
# File 'lib/eco/api/session/config/workflow.rb', line 134

def rescue(&block)
  return @rescue unless block
  @rescue = block
  self
end

#run(key = nil, io:) {|stage_workflow, io| ... } ⇒ Eco::API::Session::Config::Workflow

Note:

if a block is not provided:

  • it will run the before callbacks defined during the configuration time
  • it will run the workflow of any defined substage of the key stage
  • it will run the on callback defined during the configuration time
  • it will mark the stage as not pending?.
  • it will run the after callbacks defined during the configuration time
Note:

if a block is provided:

  • it will not run the workflow of the substages to key stage
  • it will not run the callback for on defined during the configuration time
  • it will rather yield the target stage after all the before callbacks have been run
  • aside of this, the rest will be the same as when the block is provided (see previous note)
Note:

[if the object returned by before, after and run callbacks is not an Eco::API::UseCases::BaseIO, the original io object will be returned instead.

Used in run time to execute the workflow of the (sub)stage key

Parameters:

  • key (Symbol, nil) (defaults to: nil)

    cases:

    • if key is not provided, it targets the current stage
    • if key is provided, it targets the specific sub-stage
  • io (Eco::API::UseCases::BaseIO)

    the input/output object

Yields:

  • (stage_workflow, io)

    if a block is provided, see note

Yield Parameters:

Yield Returns:

Returns:



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/eco/api/session/config/workflow.rb', line 216

def run(key = nil, io:, &block)
  raise "Missing BaseIO object" unless io.is_a?(Eco::API::UseCases::BaseIO)

  if key
    io = io_result(io: io) do
      stage(key).run(io: io, &block)
    end
  elsif pending?
    @before.each do |c|
      io = io_result(io: io) do
        io.evaluate(self, io, &c)
      end
    end

    unless skip?
      io.session.logger.debug("(Workflow: #{path}) running now")
      if block
        io = io_result(io: io) do
          io.evaluate(self, io, &block)
        end
      else
        existing_stages.each do |stg|
          io = io_result(io: io) do
            stg.run(io: io)
          end
        end

        unless ready?
          msg = "(Workflow: #{path}) 'on' callback is not defined, nor block given"
          io.session.logger.debug(msg)
        end
        io = io_result(io: io) do
          io.evaluate(self, io, &@on)
        end
      end
      @pending = false
    end

    @after.each do |c|
      io = io_result(io: io) do
        io.evaluate(self, io, &c)
      end
    end
  end
  io
rescue SystemExit => e
  io = io_result(io: io) do
    io.evaluate(e, io, &self.exit_handle)
  end
  exit e.status
rescue Interrupt => i
  raise
rescue Exception => e
  # raise unless self.rescue
  io = io_result(io: io) do
    io.evaluate(e, io, &self.rescue)
  end
  raise
ensure
  @pending = false
end

#skip!Object

Do not run this stage!



70
71
72
73
# File 'lib/eco/api/session/config/workflow.rb', line 70

def skip!
  @skip    = true
  @pending = false
end

#skip?Boolean

Has this stage been marked as to be skipped

Returns:

  • (Boolean)

    depends on this order:

    • true if skip! was called
    • false if the current stage is root? (the top stage of the hierarchy)
    • true if its parent task is to be skipped


80
81
82
83
84
# File 'lib/eco/api/session/config/workflow.rb', line 80

def skip?
  return @skip if instance_variable_defined?(:@skip)
  return false if root?
  @_parent.skip?
end