libis-workflow 2.0.beta.11 → 2.0.beta.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a86fb4847f5b02c16e1e6b71433f3ccba54ee721
4
- data.tar.gz: a9c6c8c3a00b93216a6c08c00276b00f7a5886a8
3
+ metadata.gz: 3baa19f0fbc05d8254835124a68bf02dff63952d
4
+ data.tar.gz: 9a6f33b1e6de7ee1d699aaaca71e80a2194b1d9b
5
5
  SHA512:
6
- metadata.gz: 37071948f241e661356d909e46d431219a7c088abc7867ebc04b9eff3250f4b41c3d7278eb5a42f9878398f071ff92a7bb26d099ea704e1cb84355f37a3d99b9
7
- data.tar.gz: ef20686e433df64d613ef72bf09bd422b3d34943ee10d6b975789fab612bb98c6115724e241aff6256236019f469f43dcb4d5079c1e0b22cd62fe4df6bf17b61
6
+ metadata.gz: dd107fb0efd65099dda2c0215d93ad75fde65c0a2e3271f87ce505157ea1b1f321874d426f63a315214e3c09ba3ca3dc3d2f7d620edcdc02c16292912b38df41
7
+ data.tar.gz: 61199cfae002d01666ae76d76c2e5acdca3c837d99c59f57da0a972d9c21bdb011e59a89ebda3373f9b6387518cc0673f5d9282bf2516a72f7da5983cad36804
data/README.md CHANGED
@@ -42,12 +42,12 @@ provided. It contains all the basic logic required for proper configuration and
42
42
  implementation is provided in the class ::Libis::Workflow::Workflow for your convenience to be used as-is or to derive
43
43
  your own from.
44
44
 
45
- The workflow object will be able to execute the tasks in proper order on all the WorkItems supplied/collected. Each
46
- task can be implemented with code to run or simply contain a list of child tasks. When a workflow is executed a special
47
- run object is created that captures the configuration, logs and workitems generated while executing the tasks. Essential
48
- logic is provided in the module ::Libis::Workflow::Base::Run with a simple in-memory implementation in
49
- ::Libis::Workflow::Run. The run object's class name has to be provided to the workflow configuration so that the
50
- workflow can instantiate the correct object.
45
+ The Job class is responsible for instantiating a run-time workflow execution object - a Run - that captures the
46
+ configuration, logs and workitems generated while executing the tasks. Essential logic is provided in the module
47
+ ::Libis::Workflow::Base::Run with a simple in-memory implementation in ::Libis::Workflow::Run. The run object's class
48
+ name has to be provided to the job configuration so that the job can instantiate the correct object. The run object
49
+ will be able to execute the tasks in proper order on all the WorkItems supplied/collected. Each task can be implemented
50
+ with code to run or simply contain a list of child tasks.
51
51
 
52
52
  One tasks is predefined:
53
53
  ::Libis::Workflow::Tasks::Analyzer - analyzes the workflow run and summarizes the results. It is always included as the
@@ -67,22 +67,29 @@ You should start by including the following line in your source code:
67
67
  This will load all of the Libis Workflow framework into your environment, but including only the required parts is OK as
68
68
  well. This is shown in the examples below.
69
69
 
70
- ### Workflows
70
+ ### Workflows and Jobs
71
71
 
72
72
  An implementation of ::Libis::Workflow::Base::Workflow contains the definition of a workflow. Once instantiated, it can
73
- be run by calling the 'run' method. This will create an intance of an implementation of ::Libis::Workflow::Base::Run,
74
- configure it and call the 'run' method on it. The Workflow constructor takes no arguments, but is should be configured
75
- by calling the 'configure' method with the workflow configuration as an argument. The 'run' method takes an option Hash
76
- as argument.
73
+ be run by calling the 'execute' method on a job object created for that workflow. This will create an intance of an
74
+ implementation of ::Libis::Workflow::Base::Run, configure it and call the 'run' method on it. The Workflow constructor
75
+ takes no arguments, but is should be configured by calling the 'configure' method with the workflow configuration as an
76
+ argument. The job's 'execute' method takes an option Hash as argument with extra/overriding configuration values.
77
77
 
78
+ ### Job configuration
79
+ A job configuration is a Hash with:
80
+ * name: String to identify the workflow
81
+ * description: String with detailed textual information
82
+ * workflow: Object reference to a Workflow that contains the task configuration
83
+ * run_object: String with class name of the ::Libis::Workflow::Base::Run implementation to be created. An istance of
84
+ this class will be created for each run and serves as the root work item for that particular run.
85
+ * input: Hash with input parameter values for the workflow
86
+
78
87
  #### Workflow configuration
79
88
 
80
89
  A workflow configuration is a Hash with:
81
90
  * name: String to identify the workflow
82
91
  * description: String with detailed textual information
83
92
  * tasks: Array of task descriptions
84
- * run_object: String with class name of the ::Libis::Workflow::Base::Run implementation to be created. An istance of
85
- this class will be created for each run and serves as the root work item for that particular run.
86
93
  * input: Hash with input variable definitions
87
94
 
88
95
  ##### Task description
@@ -108,8 +115,8 @@ the chapter on 'Tasks' below for more information on tasks.
108
115
 
109
116
  ##### Input variable definition
110
117
 
111
- The input variables define parameters for the workflow. When a workflow is run, it can give values for any of these
112
- input variable and the workflow run will use the new values instead of the defaults.
118
+ The input variables define parameters for the workflow. When a job is executed, it can provide values for any of these
119
+ input variables and the workflow run will use the new values instead of the defaults.
113
120
 
114
121
  The key of the input Hash is the unique name of the variable. The value is another Hash with the parameter definition.
115
122
  See ::Libis::Tools::Parameter for the content of this Hash.
@@ -122,8 +129,8 @@ if absent.
122
129
 
123
130
  #### Run-time configuration
124
131
 
125
- The 'run' method takes an optional Hash as argument which will complement and override the options Hash described in the
126
- previous chapter.
132
+ The job's 'execute' method takes an optional Hash as argument which will complement and override the options Hash
133
+ described in the previous chapter.
127
134
 
128
135
  Once the workflow is configured and the root work item instantiated, the method will run each top-level task on the root
129
136
  work item in sequence until all tasks have completed successfully or a task has failed.
@@ -0,0 +1,85 @@
1
+ # encoding: utf-8
2
+
3
+ require 'libis/tools/parameter'
4
+
5
+ module Libis
6
+ module Workflow
7
+ module Base
8
+
9
+ # This is the base module for Jobs.
10
+ #
11
+ # This module lacks the implementation for the data attributes. It functions as an interface that describes the
12
+ # common functionality regardless of the storage implementation. These attributes require some implementation:
13
+ #
14
+ # - name: [String] the name of the Job. The name will be used to identify the job. Each time a job is executed,
15
+ # a Run will be created for the associated workflow. The Run will get a name that starts with the job name
16
+ # and ends with the date and time the Run was first started. As such this name attribute serves as an
17
+ # identifier and should be treated as such. If possible it should be unique.
18
+ # - description: [String] optional information about the job.
19
+ # - workflow: [Object] the workflow containing the tasks that need to run.
20
+ # - run_obj: [String] the full class name of the Run implementation object that should be created when the
21
+ # Job is executed.
22
+ # - input: [Hash] workflow input parameter values. Each input parameter of the workflow can be set by the entries
23
+ # in this Hash.
24
+ #
25
+ # A minimal in-memory implementation could be:
26
+ #
27
+ # class Job
28
+ # include ::Libis::Workflow::Base::Job
29
+ #
30
+ # attr_accessor :name, :description, :workflow, :run_object, :input
31
+ #
32
+ # def initialize
33
+ # @name = ''
34
+ # @description = ''
35
+ # @input = Hash.new
36
+ # @workflow = ::Libis::Workflow::Workflow.new
37
+ # @run_object = ::Libis::Workflow::Run.new
38
+ # end
39
+ #
40
+ # end
41
+ #
42
+ module Job
43
+
44
+ def run_name(timestamp = Time.now)
45
+ "#{self.name}-#{timestamp.strftime('%Y%m%d%H%M%S')}"
46
+ end
47
+
48
+ def configure(cfg = {})
49
+ self.name ||= ''
50
+ self.description ||= ''
51
+ self.input ||= {}
52
+
53
+ self.name = cfg[:name] if cfg.has_key?(:name)
54
+ self.description = cfg[:description] if cfg.has_key?(:description)
55
+ self.workflow = cfg[:workflow] if cfg.has_key?(:workflow)
56
+ self.run_object = cfg[:run_object] if cfg.has_key?(:run_object)
57
+ self.input.merge!(cfg[:input] || {})
58
+ end
59
+
60
+ # noinspection RubyResolve
61
+ # @param [Hash] opts optional extra conguration values for this particular run
62
+ def execute(opts = {})
63
+ run = self.create_run_object
64
+ raise RuntimeError.new "Could not create instance of run object '#{self.run_object}'" unless run
65
+
66
+ run.job = self
67
+ run.options = self.input.merge(opts)
68
+ run.save
69
+
70
+ run.run
71
+
72
+ run
73
+ end
74
+
75
+ protected
76
+
77
+ # noinspection RubyResolve
78
+ def create_run_object
79
+ self.run_object.constantize.new
80
+ end
81
+
82
+ end
83
+ end
84
+ end
85
+ end
@@ -14,7 +14,7 @@ module Libis
14
14
  # common functionality regardless of the storage implementation. These attributes require some implementation:
15
15
  #
16
16
  # - start_date: [Time] the timestamp of the execution of the run
17
- # - workflow: [Object] a reference to the Workflow this Run belongs to
17
+ # - job: [Object] a reference to the Job this Run belongs to
18
18
  #
19
19
  # Note that ::Libis::Workflow::Base::WorkItem is a parent module and therefore requires implementation of the
20
20
  # attributes of that module too.
@@ -33,7 +33,7 @@ module Libis
33
33
  end
34
34
 
35
35
  def name
36
- self.workflow.run_name(self.start_date)
36
+ self.job.run_name(self.start_date)
37
37
  end
38
38
 
39
39
  def names
@@ -44,16 +44,18 @@ module Libis
44
44
  self.name
45
45
  end
46
46
 
47
+ def workflow
48
+ self.job.workflow
49
+ end
50
+
47
51
  # Execute the workflow.
48
- # @param [Hash] opts a list with parameter name and value tuples that specify the values for the workflow input
49
- # parameters.
50
- def run(opts = {})
52
+ def run
51
53
 
52
54
  self.start_date = Time.now
53
55
 
54
- self.options = workflow.prepare_input(self.options.merge(opts))
56
+ self.options = workflow.prepare_input(self.options)
55
57
 
56
- self.tasks = self.workflow.tasks(self)
58
+ self.tasks = workflow.tasks(self)
57
59
  configure_tasks self.options
58
60
 
59
61
  self.status = :STARTED
@@ -19,8 +19,6 @@ module Libis
19
19
  # - config: [Hash] detailed configuration for the workflow. The application assumes it behaves as a Hash and will
20
20
  # access it with [], merge! and delete methods. If your implementation decides to implement it with another
21
21
  # object, it should implement above methods. The config Hash requires the following keys:
22
- # - run_object: [String] the full class name of the Run implementation object that should be created when the
23
- # Workflow is executed.
24
22
  # - input: [Hash] all input parameter definitions where the key is the parameter name and the value is another
25
23
  # Hash with arguments for the parameter definition. It typically contains the following arguments:
26
24
  # - default: default value if no value specified when the workflow is executed
@@ -46,6 +44,9 @@ module Libis
46
44
  # ::Libis::Workflow::Task class will be instatiated. It will do nothing itself, but will execute the
47
45
  # subtasks on the item(s). In such case a 'name' is mandatory.
48
46
  #
47
+ # These values should be set by calling the #configure method which takes a Hash as argument with :name,
48
+ # :description, :input and :tasks keys.
49
+ #
49
50
  # A minimal in-memory implementation could be:
50
51
  #
51
52
  # class Workflow
@@ -55,7 +56,7 @@ module Libis
55
56
  #
56
57
  # def initialize
57
58
  # @name = ''
58
- # @descripition = ''
59
+ # @description = ''
59
60
  # @config = Hash.new
60
61
  # end
61
62
  #
@@ -105,44 +106,15 @@ module Libis
105
106
  {}
106
107
  end
107
108
 
108
- def run_name(timestamp = Time.now)
109
- "#{self.workflow.name}-#{timestamp.strftime('%Y%m%d%H%M%S')}"
110
- end
111
-
112
- def perform(opts = {})
113
- self.run opts
114
- end
115
-
116
- def create_run_object
117
- self.config[:run_object].constantize.new
118
- end
119
-
120
- # @param [Hash] opts
121
- def run(opts = {})
122
-
123
- run_object = self.create_run_object
124
- raise RuntimeError.new "Could not create instance of run object '#{self.config[:run_object]}'" unless run_object
125
-
126
- run_object.workflow = self
127
- run_object.options = opts
128
- run_object.save
129
-
130
- run_object.run opts
131
-
132
- run_object
133
- end
134
-
135
109
  # @param [Hash] opts
136
110
  def prepare_input(opts)
137
111
  options = opts.dup
138
112
  self.input.each do |key, parameter|
139
- key
140
- # provided in opts
141
- options[key] = parameter[:default] unless options.has_key? key
113
+ options[key] = parameter[:default] unless options.has_key?(key)
142
114
  options[key] = parameter.parse(options[key])
143
115
  propagate_to = []
144
116
  propagate_to = parameter[:propagate_to] if parameter[:propagate_to].is_a? Array
145
- propagate_to = parameter[:propagate_to].split(/\s*,\s*/) if parameter[:propagate_to].is_a? String
117
+ propagate_to = parameter[:propagate_to].split(/[\s,;]+/) if parameter[:propagate_to].is_a? String
146
118
  propagate_to.each do |target|
147
119
  task_name, param_name = target.split('#')
148
120
  param_name ||= key
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ require 'libis/workflow/base/job'
4
+ require 'libis/workflow/workflow'
5
+ require 'libis/workflow/run'
6
+
7
+ module Libis
8
+ module Workflow
9
+
10
+ class Job
11
+ include ::Libis::Workflow::Base::Job
12
+
13
+ attr_accessor :name, :description, :workflow, :run_object, :input
14
+
15
+ def initialize
16
+ @name = ''
17
+ @description = ''
18
+ @input = Hash.new
19
+ @workflow = ::Libis::Workflow::Workflow.new
20
+ @run_object = ::Libis::Workflow::Run.new
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+ end
@@ -12,11 +12,11 @@ module Libis
12
12
  class Run < ::Libis::Workflow::WorkItem
13
13
  include ::Libis::Workflow::Base::Run
14
14
 
15
- attr_accessor :start_date, :workflow
15
+ attr_accessor :start_date, :job
16
16
 
17
17
  def initialize
18
18
  @start_date = Time.now
19
- @workflow = nil
19
+ @job = nil
20
20
  super
21
21
  end
22
22
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Libis
4
4
  module Workflow
5
- VERSION = '2.0.beta.11' unless const_defined? :VERSION # the guard is against a redefinition warning that happens on Travis
5
+ VERSION = '2.0.beta.12' unless const_defined? :VERSION # the guard is against a redefinition warning that happens on Travis
6
6
  end
7
7
  end
@@ -10,30 +10,30 @@ module Libis
10
10
  class Worker
11
11
  include Sidekiq::Worker
12
12
 
13
- def perform(workflow_config, options = {})
14
- workflow = self.class.configure(workflow_config, options)
13
+ def perform(job_config, options = {})
14
+ job = self.class.configure(job_config, options)
15
15
  options[:interactive] = false
16
- workflow.run options
16
+ job.execute options
17
17
  end
18
18
 
19
- def self.configure(workflow_config, options = {})
19
+ def self.configure(job_config, options = {})
20
20
  log_path = options.delete :log_path
21
21
  if log_path
22
22
  Config.logger = ::Logger.new(
23
- File.join(log_path, "#{workflow_config}.log"),
23
+ File.join(log_path, "#{job_config[:name]}.log"),
24
24
  (options.delete(:log_shift_age) || 'daily'),
25
25
  (options.delete(:log_shift_size) || 1024 ** 2)
26
26
  )
27
27
  Config.logger.formatter = ::Logger::Formatter.new
28
28
  Config.logger.level = ::Logger::DEBUG
29
29
  end
30
- get_workflow(workflow_config)
30
+ get_job(job_config)
31
31
  end
32
32
 
33
- def get_workflow(workflow_config)
34
- workflow = ::Libis::Workflow::Workflow.new
35
- workflow.configure workflow_config
36
- workflow
33
+ def get_job(job_config)
34
+ job = ::Libis::Workflow::Job.new
35
+ job.configure job_config
36
+ job
37
37
  end
38
38
 
39
39
  end
@@ -1,12 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'backports/rails/string'
4
- require 'backports/rails/hash'
5
-
6
- require 'libis/workflow/config'
7
- require 'libis/workflow/task'
8
- require 'libis/workflow/tasks/analyzer'
9
-
10
3
  require 'libis/workflow/base/workflow'
11
4
 
12
5
  module Libis
@@ -19,7 +12,7 @@ module Libis
19
12
 
20
13
  def initialize
21
14
  @name = ''
22
- @descripition = ''
15
+ @description = ''
23
16
  @config = Hash.new
24
17
  end
25
18
 
@@ -12,6 +12,7 @@ module Libis
12
12
  autoload :FileItem, 'libis/workflow/base/file_item'
13
13
  autoload :DirItem, 'libis/workflow/base/dir_item'
14
14
  autoload :Logger, 'libis/workflow/base/logger'
15
+ autoload :Job, 'libis/workflow/base/job'
15
16
  autoload :Run, 'libis/workflow/base/run'
16
17
  autoload :Workflow, 'libis/workflow/base/workflow'
17
18
  end
@@ -21,6 +22,7 @@ module Libis
21
22
  autoload :DirItem, 'libis/workflow/dir_item'
22
23
 
23
24
  autoload :Workflow, 'libis/workflow/workflow'
25
+ autoload :Job, 'libis/workflow/job'
24
26
  autoload :Run, 'libis/workflow/run'
25
27
  autoload :Task, 'libis/workflow/task'
26
28
 
@@ -33,7 +33,6 @@ describe 'TestWorkflow' do
33
33
  ]
34
34
  }
35
35
  ],
36
- run_object: 'TestRun',
37
36
  input: {
38
37
  dirname: {default: '.', propagate_to: 'CollectFiles#location'},
39
38
  checksum_type: {default: 'SHA1', propagate_to: 'ChecksumTester'}
@@ -42,8 +41,20 @@ describe 'TestWorkflow' do
42
41
  workflow
43
42
  }
44
43
 
44
+ let(:job) {
45
+ job = ::Libis::Workflow::Job.new
46
+ job.configure(
47
+ name: 'TestJob',
48
+ description: 'Job for testing',
49
+ workflow: workflow,
50
+ run_object: 'TestRun',
51
+ input: {dirname: dirname, checksum_type: 'SHA256'},
52
+ )
53
+ job
54
+ }
55
+
45
56
  let!(:run) {
46
- workflow.run(dirname: dirname, checksum_type: 'SHA256')
57
+ job.execute
47
58
  }
48
59
 
49
60
  it 'should contain three tasks' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libis-workflow
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.beta.11
4
+ version: 2.0.beta.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kris Dekeyser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-22 00:00:00.000000000 Z
11
+ date: 2015-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -127,6 +127,7 @@ files:
127
127
  - lib/libis/workflow/base.rb
128
128
  - lib/libis/workflow/base/dir_item.rb
129
129
  - lib/libis/workflow/base/file_item.rb
130
+ - lib/libis/workflow/base/job.rb
130
131
  - lib/libis/workflow/base/logger.rb
131
132
  - lib/libis/workflow/base/run.rb
132
133
  - lib/libis/workflow/base/work_item.rb
@@ -134,6 +135,7 @@ files:
134
135
  - lib/libis/workflow/config.rb
135
136
  - lib/libis/workflow/dir_item.rb
136
137
  - lib/libis/workflow/file_item.rb
138
+ - lib/libis/workflow/job.rb
137
139
  - lib/libis/workflow/message_registry.rb
138
140
  - lib/libis/workflow/run.rb
139
141
  - lib/libis/workflow/task.rb
@@ -173,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
175
  version: 1.3.1
174
176
  requirements: []
175
177
  rubyforge_project:
176
- rubygems_version: 2.2.2
178
+ rubygems_version: 2.5.0
177
179
  signing_key:
178
180
  specification_version: 4
179
181
  summary: LIBIS Workflow framework.