libis-workflow 2.0.beta.19-java

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 (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