libis-workflow 2.0.beta.19-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +36 -0
  4. data/.travis.yml +32 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +21 -0
  7. data/README.md +397 -0
  8. data/Rakefile +7 -0
  9. data/lib/libis/exceptions.rb +8 -0
  10. data/lib/libis/workflow/action.rb +24 -0
  11. data/lib/libis/workflow/base/dir_item.rb +15 -0
  12. data/lib/libis/workflow/base/file_item.rb +82 -0
  13. data/lib/libis/workflow/base/job.rb +85 -0
  14. data/lib/libis/workflow/base/logger.rb +30 -0
  15. data/lib/libis/workflow/base/logging.rb +76 -0
  16. data/lib/libis/workflow/base/run.rb +86 -0
  17. data/lib/libis/workflow/base/work_item.rb +176 -0
  18. data/lib/libis/workflow/base/workflow.rb +153 -0
  19. data/lib/libis/workflow/base.rb +7 -0
  20. data/lib/libis/workflow/config.rb +24 -0
  21. data/lib/libis/workflow/dir_item.rb +12 -0
  22. data/lib/libis/workflow/file_item.rb +17 -0
  23. data/lib/libis/workflow/job.rb +26 -0
  24. data/lib/libis/workflow/message_registry.rb +32 -0
  25. data/lib/libis/workflow/run.rb +26 -0
  26. data/lib/libis/workflow/status.rb +83 -0
  27. data/lib/libis/workflow/task.rb +287 -0
  28. data/lib/libis/workflow/task_group.rb +62 -0
  29. data/lib/libis/workflow/tasks/analyzer.rb +49 -0
  30. data/lib/libis/workflow/version.rb +7 -0
  31. data/lib/libis/workflow/work_item.rb +43 -0
  32. data/lib/libis/workflow/worker.rb +42 -0
  33. data/lib/libis/workflow/workflow.rb +22 -0
  34. data/lib/libis/workflow.rb +40 -0
  35. data/lib/libis-workflow.rb +2 -0
  36. data/libis-workflow.gemspec +38 -0
  37. data/spec/items/test_dir_item.rb +15 -0
  38. data/spec/items/test_file_item.rb +18 -0
  39. data/spec/items/test_run.rb +10 -0
  40. data/spec/items.rb +3 -0
  41. data/spec/spec_helper.rb +8 -0
  42. data/spec/task_spec.rb +16 -0
  43. data/spec/tasks/camelize_name.rb +13 -0
  44. data/spec/tasks/checksum_tester.rb +33 -0
  45. data/spec/tasks/collect_files.rb +48 -0
  46. data/spec/workflow_spec.rb +188 -0
  47. metadata +196 -0
@@ -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
@@ -0,0 +1,30 @@
1
+ require 'libis/tools/logger'
2
+
3
+ module Libis
4
+ module Workflow
5
+ module Base
6
+ module Logger
7
+ include ::Libis::Tools::Logger
8
+
9
+ def message(severity, msg, *args)
10
+ item = self.workitem
11
+ item = args.shift if args.size > 0 and args[0].is_a?(WorkItem)
12
+
13
+ item.log_message(severity, to_msg(msg), *args) if item
14
+ end
15
+
16
+ def to_msg(msg)
17
+ case msg
18
+ when String
19
+ {text: msg}
20
+ when Integer
21
+ {id: msg}
22
+ else
23
+ {text: (msg.to_s rescue '')}
24
+ end.merge task: self.namepath
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,76 @@
1
+ module Libis
2
+ module Workflow
3
+ module Base
4
+ module Logging
5
+
6
+ # Helper function for the Tasks to add a log entry to the log_history.
7
+ #
8
+ # The supplied message structure is expected to contain the following fields:
9
+ # - :severity : ::Logger::Severity value
10
+ # - :id : optional message id
11
+ # - :text : message text
12
+ # - :task : list of tasks names (task hierarchy) that submits the message
13
+ #
14
+ # @param [Hash] message
15
+ def add_log(message = {})
16
+ msg = message_struct(message)
17
+ add_log_entry(msg)
18
+ self.save
19
+ end
20
+
21
+ def <=(message = {})
22
+ self.add_log(message)
23
+ end
24
+
25
+ # Add a structured message to the log history. The message text can be submitted as an integer or text. If an
26
+ # integer is submitted, it will be used to look up the text in the MessageRegistry. The message text will be
27
+ # passed to the % operator with the args parameter. If that failes (e.g. because the format string is not correct)
28
+ # the args value is appended to the message.
29
+ #
30
+ # @param [Symbol] severity
31
+ # @param [Hash] msg should contain message text as :id or :text and the hierarchical name of the task as :task
32
+ # @param [Array] args string format values
33
+ def log_message(severity, msg, *args)
34
+ # Prepare info from msg struct for use with string substitution
35
+ message_id, message_text = if msg[:id]
36
+ [msg[:id], MessageRegistry.instance.get_message(msg[:id])]
37
+ elsif msg[:text]
38
+ [0, msg[:text]]
39
+ else
40
+ [0, '']
41
+ end
42
+ task = msg[:task] || '*UNKNOWN*'
43
+ message_text = (message_text % args rescue "#{message_text} - #{args}")
44
+
45
+ self.add_log severity: severity, id: message_id.to_i, text: message_text, task: task
46
+ name = ''
47
+ begin
48
+ name = self.to_s
49
+ name = self.name
50
+ name = self.namepath
51
+ rescue
52
+ # do nothing
53
+ end
54
+ Config.logger.add(severity, message_text, ('%s - %s ' % [task, name]))
55
+ end
56
+
57
+ protected
58
+
59
+ SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY) unless const_defined? :SEV_LABEL
60
+
61
+ # create and return a proper message structure
62
+ # @param [Hash] opts
63
+ def message_struct(opts = {})
64
+ opts.reverse_merge!(severity: ::Logger::INFO, code: nil, text: '')
65
+ {
66
+ severity: SEV_LABEL[opts[:severity]],
67
+ task: opts[:task],
68
+ code: opts[:code],
69
+ message: opts[:text]
70
+ }.cleanup
71
+ end
72
+
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,86 @@
1
+ # encoding: utf-8
2
+
3
+ require 'fileutils'
4
+
5
+ require 'libis/workflow/base/work_item'
6
+
7
+ module Libis
8
+ module Workflow
9
+ module Base
10
+
11
+ # Base module for all workflow runs. It is created by an associated workflow when the workflow is executed.
12
+ #
13
+ # This module lacks the implementation for the data attributes. It functions as an interface that describes the
14
+ # common functionality regardless of the storage implementation. These attributes require some implementation:
15
+ #
16
+ # - start_date: [Time] the timestamp of the execution of the run
17
+ # - job: [Object] a reference to the Job this Run belongs to
18
+ #
19
+ # Note that ::Libis::Workflow::Base::WorkItem is a parent module and therefore requires implementation of the
20
+ # attributes of that module too.
21
+ #
22
+ # A simple in-memory implementation can be found in ::Libis::Workflow::Run
23
+ module Run
24
+ include ::Libis::Workflow::Base::WorkItem
25
+
26
+ attr_accessor :tasks, :action
27
+
28
+ def work_dir
29
+ # noinspection RubyResolve
30
+ dir = File.join(Config.workdir, self.name)
31
+ FileUtils.mkpath dir unless Dir.exist?(dir)
32
+ dir
33
+ end
34
+
35
+ def name
36
+ self.job.run_name(self.start_date)
37
+ end
38
+
39
+ def names
40
+ Array.new
41
+ end
42
+
43
+ def namepath
44
+ self.name
45
+ end
46
+
47
+ def workflow
48
+ self.job.workflow
49
+ end
50
+
51
+ # Execute the workflow.
52
+ #
53
+ # The action parameter defines how the execution of the tasks will behave:
54
+ # - With the default :run action each task will be executed regardsless how the task performed on the item
55
+ # previously.
56
+ # - When using the :retry action a task will not perform on an item if it was successful the last time. This
57
+ # allows you to retry a run when an temporary error (e.g. asynchronous wait or halt) occured.
58
+ #
59
+ # @param [Symbol] action the type of action to take during this run. :run or :retry
60
+ def run(action = :run)
61
+ self.action = action
62
+
63
+ self.start_date = Time.now
64
+
65
+ self.options = workflow.prepare_input(self.options)
66
+
67
+ self.tasks = workflow.tasks(self)
68
+ configure_tasks self.options
69
+
70
+
71
+ self.tasks.each do |task|
72
+ task.run self
73
+ end
74
+
75
+ end
76
+
77
+ protected
78
+
79
+ def configure_tasks(opts)
80
+ self.tasks.each { |task| task.apply_options opts }
81
+ end
82
+
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,176 @@
1
+ # encoding: utf-8
2
+
3
+ require 'backports/rails/hash'
4
+ require 'libis/tools/extend/hash'
5
+
6
+ require 'libis/workflow/config'
7
+ require 'libis/workflow/status'
8
+ require_relative 'logging'
9
+
10
+ module Libis
11
+ module Workflow
12
+ module Base
13
+
14
+ # Base module for all work items.
15
+ #
16
+ # This module lacks the implementation for the data attributes. It functions as an interface that describes the
17
+ # common functionality regardless of the storage implementation. These attributes require some implementation:
18
+ #
19
+ # - status: [Symbol] the status field. Each task sets the status of the items it works on. Before starting processing
20
+ # the status is set to "#{task_name}Started". After successfull processing it is set to "#{task_name}Done" and if
21
+ # the task failed, it is set to "#{task_name}Failed". The status field can be used to perform real-time
22
+ # monitoring, reporting and error-recovery or restart of the ingest.
23
+ # The initial value for this attribute is :START.
24
+ # - parent: [Object|nil] a link to a parent work item. Work items can be organized in any hierarchy you think is
25
+ # relevant for your workflow (e.g. directory[/directory...]/file/line or library/section/book/page). Of course
26
+ # hierarchies are not mandatory.
27
+ # - items: [Array] a list of child work items. see above.
28
+ # - options: [Hash] a set of options for the task chain on how to deal with this work item. This attribute can be
29
+ # used to fine-tune the behaviour of tasks for a particular work item.
30
+ # - properties: [Hash] a set of properties, typically collected during the workflow processing and used to store
31
+ # final or intermediate resulst of tasks. The ::Lias::Ingester::FileItem module uses this attribute to store the
32
+ # properties (e.g. size, checksum, ...) of the file it represents.
33
+ # - log_history: [Array] a list of all logging messages collected for this work item. Whenever a task logs a message
34
+ # it will automatically be registered for the work item that it is processing or for the work item that was
35
+ # supplied as the first argument.
36
+ # - status_log: [Array] a list of all status changes the work item went through.
37
+ # - summary: [Hash] collected statistics about the ingest for the work item and its children. This structure will
38
+ # be filled in by the included task ::Lias::Ingester::Tasks::Analyzer wich is appended to the workflow by default.
39
+ #
40
+ # The module is created so that it is possible to implement an ActiveRecord/Datamapper/... implementation easily.
41
+ # A simple in-memory implementation would require:
42
+ #
43
+ # attr_accessor :parent
44
+ # attr_accessor :items
45
+ # attr_accessor :options, :properties
46
+ # attr_accessor :log_history, :status_log
47
+ # attr_accessor :summary
48
+ #
49
+ # def initialize
50
+ # self.parent = nil
51
+ # self.items = []
52
+ # self.options = {}
53
+ # self.properties = {}
54
+ # self.log_history = []
55
+ # self.status_log = []
56
+ # self.summary = {}
57
+ # end
58
+ #
59
+ # protected
60
+ #
61
+ # ## Methods below should be adapted to match the implementation of the log arrays
62
+ #
63
+ # def add_log_entry(msg)
64
+ # self.log_history << msg.merge(c_at: ::Time.now)
65
+ # end
66
+ #
67
+ # def add_status_log(message, tasklist = nil)
68
+ # self.status_log << { c_at: ::Time.now, tasklist: tasklist, text: message }.cleanup
69
+ # end
70
+ #
71
+ #
72
+ module WorkItem
73
+ include Enumerable
74
+ include Libis::Workflow::Status
75
+ include Libis::Workflow::Base::Logging
76
+
77
+ # String representation of the identity of the work item.
78
+ #
79
+ # You may want to overwrite this method as it tries the :name property or whatever #inspect returns if that
80
+ # failes. Typically this should return the key value, file name or id number. If that's what your :name property
81
+ # contains, you're fine.
82
+ #
83
+ # @return [String] string identification for this work item.
84
+ def name
85
+ # noinspection RubyResolve
86
+ self.properties[:name] || self.inspect
87
+ end
88
+
89
+ def to_s;
90
+ self.name;
91
+ end
92
+
93
+ def names
94
+ (self.parent.names rescue Array.new).push(name).compact
95
+ end
96
+
97
+ def namepath;
98
+ self.names.join('/');
99
+ end
100
+
101
+ # File name safe version of the to_s output.
102
+ #
103
+ # The output should be safe to use as a file name to store work item
104
+ # data. Typical use is when extra file items are created by a task and need to be stored on disk. The default
105
+ # implementation URL-encodes (%xx) all characters except alphanumeric, '.' and '-'.
106
+ #
107
+ # @return [String] file name
108
+ def to_filename
109
+ self.to_s.gsub(/[^\w.-]/) { |s| '%%%02x' % s.ord }
110
+ end
111
+
112
+ # Iterates over the work item clients and invokes code on each of them.
113
+ def each
114
+ self.items.each { |item| yield item }
115
+ end
116
+
117
+ # Add a child work item
118
+ #
119
+ # @param [WorkItem] item to be added to the child list :items
120
+ def add_item(item)
121
+ return self unless item and item.is_a? Libis::Workflow::Base::WorkItem
122
+ self.items << item
123
+ item.parent = self
124
+ self.save!
125
+ item.save!
126
+ self
127
+ end
128
+
129
+ alias_method :<<, :add_item
130
+
131
+ def get_items
132
+ self.items.dup
133
+ end
134
+
135
+ def item_count
136
+ self.items.size
137
+ end
138
+
139
+ # Return item's parent
140
+ # @return [Libis::Workflow::Base::WorkItem]
141
+ def get_parent
142
+ self.parent
143
+ end
144
+
145
+ # go up the hierarchy and return the topmost work item
146
+ #
147
+ # @return [Libis::Workflow::Base::WorkItem]
148
+ def get_root
149
+ self.get_parent && self.get_parent.is_a?(Libis::Workflow::Base::WorkItem) && self.get_parent.get_root || self
150
+ end
151
+
152
+ # Get the top
153
+ #
154
+ # @return [Libis::Workflow::Base::Run]
155
+ def get_run
156
+ return self if self.is_a?(Libis::Workflow::Base::Run)
157
+ self.get_parent && self.get_parent.get_run || nil
158
+ end
159
+
160
+ # Dummy method. It is a placeholder for DB backed implementations. Wherever appropriate WorkItem#save will be
161
+ # called to save the current item's state. If state needs to persisted, you should override this method or make
162
+ # sure your persistence layer implements it in your class.
163
+ def save
164
+ end
165
+
166
+ # Dummy method. It is a placeholder for DB backed implementations. Wherever appropriate WorkItem#save will be
167
+ # called to save the current item's state. If state needs to persisted, you should override this method or make
168
+ # sure your persistence layer implements it in your class.
169
+ def save!
170
+ end
171
+
172
+ end
173
+
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,153 @@
1
+ # encoding: utf-8
2
+
3
+ require 'libis/tools/parameter'
4
+ require 'libis/workflow/task_group'
5
+
6
+ module Libis
7
+ module Workflow
8
+ module Base
9
+
10
+ # This is the base module for Workflows.
11
+ #
12
+ # This module lacks the implementation for the data attributes. It functions as an interface that describes the
13
+ # common functionality regardless of the storage implementation. These attributes require some implementation:
14
+ #
15
+ # - name: [String] the name of the Workflow. The name will be used to identify the workflow. Each time a workflow
16
+ # is executed, a Run will be created. The Run will get a name that starts with the workflow name and ends with
17
+ # the date and time the Run was started. As such this name attribute serves as an identifier and should be
18
+ # treated as such. If possible is should be unique.
19
+ # - description: [String] more information about the workflow.
20
+ # - config: [Hash] detailed configuration for the workflow. The application assumes it behaves as a Hash and will
21
+ # access it with [], merge! and delete methods. If your implementation decides to implement it with another
22
+ # object, it should implement above methods. The config Hash requires the following keys:
23
+ # - input: [Hash] all input parameter definitions where the key is the parameter name and the value is another
24
+ # Hash with arguments for the parameter definition. It typically contains the following arguments:
25
+ # - default: default value if no value specified when the workflow is executed
26
+ # - propagate_to: the task name (or path) and parameter name that any set value for this parameter will be
27
+ # propagated to. The syntax is <task name|task path>[#<parameter name>]. It the #<parameter name> part
28
+ # is not present, the same name as the input parameter is used. If you want to push the value to
29
+ # multiple task parameters, you can either supply an array of propagate paths or put them in a string
30
+ # separated by a ','.
31
+ # - tasks: [Array] task definitions that define the order in which the tasks should be executed for the workflow.
32
+ # A task definition is a Hash with the following values:
33
+ # - class: [String] the class name of the task including the module names
34
+ # - name: [String] optional if class is present. A friendly name for the task that will be used in the logs.
35
+ # - tasks: [Array] a list of subtask defintions for this task.
36
+ #
37
+ # Additionally the task definition Hash may specify values for any other parameter that the task knows of.
38
+ # All tasks have parameters 'quiet', 'recursive', 'retry_count' and 'retry_interval'. For more
39
+ # information about these see the documentation of the task class.
40
+ #
41
+ # A task definition does not require to have a 'class' entry. If not present the default
42
+ # ::Libis::Workflow::TaskGroup class will be instatiated. It will do nothing itself, but will execute the
43
+ # subtasks on the item(s). In such case a 'name' is mandatory.
44
+ #
45
+ # These values should be set by calling the #configure method which takes a Hash as argument with :name,
46
+ # :description, :input and :tasks keys.
47
+ #
48
+ # A minimal in-memory implementation could be:
49
+ #
50
+ # class Workflow
51
+ # include ::Libis::Workflow::Base::Workflow
52
+ #
53
+ # attr_accessor :name, :description, :config
54
+ #
55
+ # def initialize
56
+ # @name = ''
57
+ # @description = ''
58
+ # @config = Hash.new
59
+ # end
60
+ #
61
+ # end
62
+ #
63
+ module Workflow
64
+
65
+ module ClassMethods
66
+ def require_all
67
+ Config.require_all(File.join(File.dirname(__FILE__), '..', 'tasks'))
68
+ # noinspection RubyResolve
69
+ Config.require_all(Config.taskdir)
70
+ # noinspection RubyResolve
71
+ Config.require_all(Config.itemdir)
72
+ end
73
+ end
74
+
75
+ def self.included(base)
76
+
77
+ base.extend ClassMethods
78
+ end
79
+
80
+ def configure(cfg)
81
+ self.name = cfg.delete(:name) || self.class.name
82
+ self.description = cfg.delete(:description) || ''
83
+ self.config.merge! input: {}, tasks: []
84
+ self.config.merge! cfg
85
+
86
+ self.class.require_all
87
+
88
+ unless self.config[:tasks].last[:class] && self.config[:tasks].last[:class].split('::').last == 'Analyzer'
89
+ self.config[:tasks] << {class: '::Libis::Workflow::Tasks::Analyzer'}
90
+ end
91
+
92
+ self.config
93
+ end
94
+
95
+ def input
96
+ self.config[:input].inject({}) do |hash, input_def|
97
+ name = input_def.first.to_sym
98
+ default = input_def.last[:default]
99
+ parameter = ::Libis::Tools::Parameter.new name, default
100
+ input_def.last.each { |k, v| parameter[k.to_sym] = v }
101
+ hash[name] = parameter
102
+ hash
103
+ end
104
+ rescue
105
+ {}
106
+ end
107
+
108
+ # @param [Hash] options
109
+ def prepare_input(options)
110
+ result = {}
111
+ self.input.each do |key, parameter|
112
+ if options.has_key?(key)
113
+ value = parameter.parse(options[key])
114
+ elsif !parameter[:default].nil?
115
+ value = parameter[:default]
116
+ else
117
+ next
118
+ end
119
+ propagate_to = []
120
+ propagate_to = parameter[:propagate_to] if parameter[:propagate_to].is_a? Array
121
+ propagate_to = parameter[:propagate_to].split(/[\s,;]+/) if parameter[:propagate_to].is_a? String
122
+ result[key] = value if propagate_to.empty?
123
+ propagate_to.each do |target|
124
+ task_name, param_name = target.split('#')
125
+ param_name ||= key
126
+ result[task_name] ||= {}
127
+ result[task_name][param_name.to_sym] = value
128
+ end
129
+ end
130
+ result
131
+ end
132
+
133
+ def tasks(parent = nil)
134
+ self.config[:tasks].map do |cfg|
135
+ instantize_task(parent || self, cfg)
136
+ end
137
+ end
138
+
139
+ def instantize_task(parent, cfg)
140
+ task_class = Libis::Workflow::TaskGroup
141
+ task_class = cfg[:class].constantize if cfg[:class]
142
+ # noinspection RubyArgCount
143
+ task_instance = task_class.new(parent, cfg)
144
+ cfg[:tasks] && cfg[:tasks].map do |task_cfg|
145
+ task_instance << instantize_task(task_instance, task_cfg)
146
+ end
147
+ task_instance
148
+ end
149
+
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'base/logger'
2
+ require_relative 'base/logging'
3
+ require_relative 'base/work_item'
4
+ require_relative 'base/file_item'
5
+ require_relative 'base/dir_item'
6
+ require_relative 'base/run'
7
+ require_relative 'base/workflow'
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ require 'libis/tools/config'
4
+
5
+ module Libis
6
+ module Workflow
7
+
8
+ # noinspection RubyConstantNamingConvention
9
+ Config = ::Libis::Tools::Config
10
+
11
+ Config.define_singleton_method(:require_all) do |dir|
12
+ Dir.glob(File.join(dir, '*.rb')).each do |filename|
13
+ # noinspection RubyResolve
14
+ require filename
15
+ end
16
+ end
17
+
18
+ Config.require_all(File.join(File.dirname(__FILE__), 'tasks'))
19
+ Config[:workdir] = './work'
20
+ Config[:taskdir] = './tasks'
21
+ Config[:itemdir] = './items'
22
+
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+
3
+ require 'libis/workflow/file_item'
4
+
5
+ module Libis
6
+ module Workflow
7
+
8
+ class DirItem < ::Libis::Workflow::FileItem
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ require 'digest'
4
+
5
+ require 'libis/workflow/base/file_item'
6
+ require 'libis/workflow/work_item'
7
+
8
+ module Libis
9
+ module Workflow
10
+
11
+ # noinspection RubyResolve
12
+ class FileItem < ::Libis::Workflow::WorkItem
13
+ include ::Libis::Workflow::Base::FileItem
14
+
15
+ end
16
+ end
17
+ end