batch-kit 0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +165 -0
- data/lib/batch-kit.rb +9 -0
- data/lib/batch-kit/arguments.rb +57 -0
- data/lib/batch-kit/config.rb +517 -0
- data/lib/batch-kit/configurable.rb +68 -0
- data/lib/batch-kit/core_ext/enumerable.rb +97 -0
- data/lib/batch-kit/core_ext/file.rb +69 -0
- data/lib/batch-kit/core_ext/file_utils.rb +103 -0
- data/lib/batch-kit/core_ext/hash.rb +17 -0
- data/lib/batch-kit/core_ext/numeric.rb +17 -0
- data/lib/batch-kit/core_ext/string.rb +88 -0
- data/lib/batch-kit/database.rb +133 -0
- data/lib/batch-kit/database/java_util_log_handler.rb +65 -0
- data/lib/batch-kit/database/log4r_outputter.rb +57 -0
- data/lib/batch-kit/database/models.rb +548 -0
- data/lib/batch-kit/database/schema.rb +229 -0
- data/lib/batch-kit/encryption.rb +7 -0
- data/lib/batch-kit/encryption/java_encryption.rb +178 -0
- data/lib/batch-kit/encryption/ruby_encryption.rb +175 -0
- data/lib/batch-kit/events.rb +157 -0
- data/lib/batch-kit/framework/acts_as_job.rb +197 -0
- data/lib/batch-kit/framework/acts_as_sequence.rb +123 -0
- data/lib/batch-kit/framework/definable.rb +169 -0
- data/lib/batch-kit/framework/job.rb +121 -0
- data/lib/batch-kit/framework/job_definition.rb +105 -0
- data/lib/batch-kit/framework/job_run.rb +145 -0
- data/lib/batch-kit/framework/runnable.rb +235 -0
- data/lib/batch-kit/framework/sequence.rb +87 -0
- data/lib/batch-kit/framework/sequence_definition.rb +38 -0
- data/lib/batch-kit/framework/sequence_run.rb +48 -0
- data/lib/batch-kit/framework/task_definition.rb +89 -0
- data/lib/batch-kit/framework/task_run.rb +53 -0
- data/lib/batch-kit/helpers/date_time.rb +54 -0
- data/lib/batch-kit/helpers/email.rb +198 -0
- data/lib/batch-kit/helpers/html.rb +175 -0
- data/lib/batch-kit/helpers/process.rb +101 -0
- data/lib/batch-kit/helpers/zip.rb +30 -0
- data/lib/batch-kit/job.rb +11 -0
- data/lib/batch-kit/lockable.rb +138 -0
- data/lib/batch-kit/loggable.rb +78 -0
- data/lib/batch-kit/logging.rb +169 -0
- data/lib/batch-kit/logging/java_util_logger.rb +87 -0
- data/lib/batch-kit/logging/log4r_logger.rb +71 -0
- data/lib/batch-kit/logging/null_logger.rb +35 -0
- data/lib/batch-kit/logging/stdout_logger.rb +96 -0
- data/lib/batch-kit/resources.rb +191 -0
- data/lib/batch-kit/sequence.rb +7 -0
- metadata +122 -0
@@ -0,0 +1,157 @@
|
|
1
|
+
class BatchKit
|
2
|
+
|
3
|
+
# Manages batch event notifications and subscriptions, which provide a
|
4
|
+
# useful means of decoupling different components of the batch library.
|
5
|
+
#
|
6
|
+
# The problem we are looking to solve here is that we want our batch jobs,
|
7
|
+
# tasks etc to be able to notify interested parties when something happens
|
8
|
+
# (e.g. a task starts, a job fails, etc) without these event sources needing
|
9
|
+
# to know all the interested parties to notify. We therefore introduce an
|
10
|
+
# intermediary, which is the Events system.
|
11
|
+
#
|
12
|
+
# Interested parties register their interest in specific events or event
|
13
|
+
# classes by subscribing to the events of interest. Framework classes then
|
14
|
+
# notify the Event system when an event occurs, and the event system routes
|
15
|
+
# these notifications on to all registered subscribers.
|
16
|
+
#
|
17
|
+
# One of the problems we need to solve for is how subscribers can define the
|
18
|
+
# scope of their interest. Is it all events of a particular type, regardless
|
19
|
+
# of source? Or are we only interested in events from a specific source (e.g
|
20
|
+
# job or task)?
|
21
|
+
class Events
|
22
|
+
|
23
|
+
# Records subscription details
|
24
|
+
class Subscription
|
25
|
+
|
26
|
+
attr_reader :source, :event, :callback, :raise_on_error
|
27
|
+
|
28
|
+
|
29
|
+
def initialize(source, event, options, callback)
|
30
|
+
@source = source
|
31
|
+
@event = event
|
32
|
+
@raise_on_error = options.fetch(:raise_on_error, true)
|
33
|
+
@callback = callback
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def ===(obj)
|
38
|
+
@source.nil? || # Nil source means match any obj
|
39
|
+
(@source == obj) || # Source is obj
|
40
|
+
(@source === obj) || # obj is an instance of source class
|
41
|
+
(@source.instance_of?(Module) && obj.instance_of?(Class) &&
|
42
|
+
obj.include?(@source)) # Source is a module included by obj
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
class << self
|
50
|
+
|
51
|
+
# @param source [Object] The source of the event
|
52
|
+
# @param event [String] The name of the event
|
53
|
+
# @return [Boolean] whether there are any subscribers for the specified
|
54
|
+
# event.
|
55
|
+
def has_subscribers?(source, event)
|
56
|
+
subscribers.has_key?(event) && subscribers[event].size > 0 &&
|
57
|
+
subscribers[event].find{ |sub| sub === source }
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# Setup a subscription for a particular event. When a matching event
|
62
|
+
# occurs, the supplied block will be called with the published
|
63
|
+
# arguments.
|
64
|
+
#
|
65
|
+
# @param source [Object] The type of source object from which to
|
66
|
+
# listen for events.
|
67
|
+
# @param event [String] The name of the event to subscribe to.
|
68
|
+
# @param options [Hash] An options hash defining optional settings
|
69
|
+
# for the subscription.
|
70
|
+
# @option options [Fixnum] :position The position within the list to
|
71
|
+
# insert the subscriber. Default is to add to the end of the list.
|
72
|
+
# @param callback [Proc] A block to be invoked when the event occurs.
|
73
|
+
def subscribe(source, event, options = {}, &callback)
|
74
|
+
@log.trace "Adding subscriber for #{source} event '#{event}'" if @log
|
75
|
+
position = options.fetch(:position, -1)
|
76
|
+
if event.is_a?(Array)
|
77
|
+
event.each{ |e| subscribers[e].insert(position, Subscription.new(source, e, options, callback)) }
|
78
|
+
else
|
79
|
+
subscribers[event].insert(position, Subscription.new(source, event, options, callback))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# Remove a subscriber
|
85
|
+
#
|
86
|
+
# @param source [Object] The object that is the source of the event
|
87
|
+
# from which to unsubscribe.
|
88
|
+
# @param event [String] The name of the event to unsubscribe from.
|
89
|
+
def unsubscribe(source, event)
|
90
|
+
@log.trace "Removing subscriber(s) for #{source} event '#{event}'" if @log
|
91
|
+
subscribers[event].delete_if{ |sub| sub === source }
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
# Publishes an event to all registered subscribers.
|
96
|
+
#
|
97
|
+
# @param source [Object] The source from which the event has been
|
98
|
+
# generated.
|
99
|
+
# @param event [String] The name of the event that has occurred.
|
100
|
+
# @param payload [*Object] Arguments passed with the event.
|
101
|
+
def publish(source, event, *payload)
|
102
|
+
@log.trace "Publishing event '#{event}' for #{source}" if @log
|
103
|
+
res = true
|
104
|
+
count = 0
|
105
|
+
if subscribers.has_key?(event)
|
106
|
+
subscribers[event].each do |sub|
|
107
|
+
if sub === source
|
108
|
+
begin
|
109
|
+
r = sub.callback.call(source, *payload)
|
110
|
+
count += 1
|
111
|
+
res &&= r
|
112
|
+
rescue StandardError => ex
|
113
|
+
if sub.raise_on_error
|
114
|
+
raise
|
115
|
+
else
|
116
|
+
STDERR.puts "Exception in '#{event}' event listener for #{source}: #{ex}\n" +
|
117
|
+
" at: #{ex.backtrace[0...10].join("\n")}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
@log.debug "Notified #{count} listeners of '#{event}'" if @log
|
123
|
+
end
|
124
|
+
res
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
# Enable/disable event debugging
|
129
|
+
def debug=(dbg)
|
130
|
+
@log = dbg ? LogManager.logger('batch.events') : nil
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
# Dumps a list of events and their subscribers to the logger
|
135
|
+
def dump_subscribers(show_event = nil, log = @log)
|
136
|
+
if log
|
137
|
+
subscribers.each do |event, subs|
|
138
|
+
if show_event.nil? || show_event == event
|
139
|
+
log.info "Subscribers for event '#{event}':"
|
140
|
+
subs.each{ |sub| log.detail sub.inspect }
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def subscribers
|
150
|
+
@subscribers ||= Hash.new{ |h, k| h[k] = [] }
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
class BatchKit
|
2
|
+
|
3
|
+
# When included into a class, marks the class as a BatchKit job.
|
4
|
+
# The including class has the following class methods added, which act as a
|
5
|
+
# DSL for specifying the job properties and behaviour:
|
6
|
+
# - {ClassMethods#desc desc} A method for setting a description for a
|
7
|
+
# subsequent job or task
|
8
|
+
# - {ClassMethods#job job} Defines a job entry method
|
9
|
+
# - {ClassMethods#task task} Defines a task method
|
10
|
+
# - {ClassMethods#job_definition job_definition} Returns the Job::Definition
|
11
|
+
# object for the including class
|
12
|
+
# - {ClassMethods#on_success on_success} defines a callback to be called if
|
13
|
+
# the job completes successfully.
|
14
|
+
# - {ClassMethods#on_failure on_failure} defines a callback to be called if
|
15
|
+
# the job encounters an unhandled exception.
|
16
|
+
# - {ClassMethods#on_completion} defines a callback to be called when the
|
17
|
+
# job completes.
|
18
|
+
#
|
19
|
+
# Instances of the including class also get the following instance methods:
|
20
|
+
# - {#job} Returns the Job::Definition for the class
|
21
|
+
# - {#job_run} Returns the Job::Run associated with this object instance.
|
22
|
+
module ActsAsJob
|
23
|
+
|
24
|
+
# Define methods to be added to the class that includes this module.
|
25
|
+
module ClassMethods
|
26
|
+
|
27
|
+
# @return The Job::Definition object used to hold attributes of this
|
28
|
+
# job.
|
29
|
+
def job_definition
|
30
|
+
@__job__
|
31
|
+
end
|
32
|
+
alias_method :definition, :job_definition
|
33
|
+
|
34
|
+
|
35
|
+
# Captures a description for the following task or job definition.
|
36
|
+
#
|
37
|
+
# @param desc [String] The description to associate with the next
|
38
|
+
# task or job that is defined.
|
39
|
+
def desc(desc)
|
40
|
+
@__desc__ = desc
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# Defines the method that is used to run this job.
|
45
|
+
# This may be an existing method, in which case the name of the
|
46
|
+
# method must be passed as the first argument.
|
47
|
+
# Alternatively, a block may be supplied, which will be used to
|
48
|
+
# create the job method.
|
49
|
+
#
|
50
|
+
# @param job_method [Symbol] The name of an existing method that is
|
51
|
+
# to be the job entry point.
|
52
|
+
# @param job_opts [Hash] Options that affect the job definition.
|
53
|
+
# @option job_opts [Symbol] :method_name The name to be assigned to
|
54
|
+
# the job method created from the supplied block. Default is
|
55
|
+
# :execute.
|
56
|
+
# @option job_opts [String] :description A description for the job.
|
57
|
+
def job(job_method = nil, job_opts = @__desc__, &body)
|
58
|
+
# If called as an accessor, just return the @__job__
|
59
|
+
if job_method || job_opts || body
|
60
|
+
unless job_method.is_a?(Symbol)
|
61
|
+
job_opts = job_method
|
62
|
+
job_method = (job_opts && job_opts.is_a?(Hash) &&
|
63
|
+
job_opts[:method_name]) || :execute
|
64
|
+
end
|
65
|
+
|
66
|
+
job_desc = nil
|
67
|
+
if job_opts.is_a?(Hash)
|
68
|
+
job_desc = @__desc__
|
69
|
+
elsif job_opts.is_a?(String)
|
70
|
+
job_desc = job_opts
|
71
|
+
job_opts = {}
|
72
|
+
elsif job_opts.nil?
|
73
|
+
job_opts = {}
|
74
|
+
end
|
75
|
+
@__desc__ = nil
|
76
|
+
|
77
|
+
# Define job method if a body block was supplied
|
78
|
+
define_method(job_method, &body) if body
|
79
|
+
|
80
|
+
opts = job_opts.clone
|
81
|
+
opts[:description] = job_desc unless opts[:description]
|
82
|
+
opts[:method_name] = job_method
|
83
|
+
# The @__job__ instance variable is crated when this module is included
|
84
|
+
@__job__.set_from_options(opts)
|
85
|
+
end
|
86
|
+
@__job__
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
# Defines the method that is used to run a task.
|
91
|
+
# This may be an existing method, in which case the name of the
|
92
|
+
# method must be passed as the first argument.
|
93
|
+
# Alternatively, a block may be supplied, which will be used to
|
94
|
+
# create the task method.
|
95
|
+
#
|
96
|
+
# @param task_method [Symbol] The name for the method that is to be
|
97
|
+
# this task. May be the name of an existing method (in which case
|
98
|
+
# no block should be supplied), or the name to give to the method
|
99
|
+
# that will be created from the supplied block.
|
100
|
+
# @param task_opts [Hash] A hash containing options for the task
|
101
|
+
# being defined.
|
102
|
+
# @option task_opts [Symbol] :method_name The name for the method
|
103
|
+
# if no symbol was provided as the first argument.
|
104
|
+
# @option job_opts [String] :description A description for the task.
|
105
|
+
def task(task_method, task_opts = @__desc__, &body)
|
106
|
+
unless task_method.is_a?(Symbol)
|
107
|
+
task_opts = task_method
|
108
|
+
task_method = task_opts && task_opts[:method_name]
|
109
|
+
end
|
110
|
+
raise ArgumentError, "No method name specified for task" unless task_method
|
111
|
+
|
112
|
+
task_desc = nil
|
113
|
+
if task_opts.is_a?(Hash)
|
114
|
+
task_desc = @__desc__
|
115
|
+
elsif task_opts.is_a?(String)
|
116
|
+
task_desc = task_opts
|
117
|
+
task_opts = {}
|
118
|
+
elsif task_opts.nil?
|
119
|
+
task_opts = {}
|
120
|
+
end
|
121
|
+
@__desc__ = nil
|
122
|
+
|
123
|
+
# Define task method if a body block was supplied
|
124
|
+
define_method(task_method, &body) if body
|
125
|
+
|
126
|
+
opts = task_opts.clone
|
127
|
+
opts[:description] = task_desc unless opts[:description]
|
128
|
+
|
129
|
+
# Create a new TaskDefinition class for the task
|
130
|
+
task_defn = Task::Definition.new(self, task_method)
|
131
|
+
task_defn.set_from_options(opts)
|
132
|
+
task_defn
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
# Defines a handler to be invoked if the job encounters an unhandled
|
137
|
+
# exception.
|
138
|
+
def on_failure(mthd = nil, &blk)
|
139
|
+
Events.subscribe(self, 'job_run.failure'){ |jr, obj, ex| obj.send(mthd, ex) } if mthd
|
140
|
+
Events.subscribe(self, 'job_run.failure'){ |jr, obj, ex| obj.instance_exec(ex, &blk) } if blk
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
# Defines a handler to be invoked if the job ends successfully.
|
145
|
+
def on_success(mthd = nil, &blk)
|
146
|
+
Events.subscribe(self, 'job_run.success'){ |jr, obj| obj.send(mthd) } if mthd
|
147
|
+
Events.subscribe(self, 'job_run.success'){ |jr, obj| obj.instance_exec(&blk) } if blk
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
# Defines a handler to be invoked on completion of the job, whether
|
152
|
+
# the job completes successfully or fails. The handler may be specified
|
153
|
+
# as either a method name and/or via a block. Multiple calls to this
|
154
|
+
# method can be made to register multiple callbacks if desired.
|
155
|
+
#
|
156
|
+
# @param mthd [Symbol] The name of an existing method on the including
|
157
|
+
# class. This method will be called with the Job::Run object that
|
158
|
+
# represents the completing job run.
|
159
|
+
#
|
160
|
+
def on_completion(mthd = nil, &blk)
|
161
|
+
Events.subscribe(self, 'job_run.post-execute'){ |jr, obj, ok| obj.send(mthd, jr) } if mthd
|
162
|
+
Events.subscribe(self, 'job_run.post-execute'){ |jr, obj, ok| obj.instance_exec(jr, &blk) } if blk
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
# Hook used to extend the including class with class methods defined in
|
169
|
+
# the ActsAsJob::ClassMethods module.
|
170
|
+
#
|
171
|
+
# Creates a Job::Definition object to hold details of the job, and stores
|
172
|
+
# it away in a @__job__ class instance variable.
|
173
|
+
def self.included(base)
|
174
|
+
base.extend(ClassMethods)
|
175
|
+
caller.find{ |f| !(f =~ /batch-kit.framework/) } =~ /^((?:[a-zA-Z]:)?[^:]+)/
|
176
|
+
job_file = File.realpath($1)
|
177
|
+
job_defn = Job::Definition.new(base, job_file)
|
178
|
+
base.instance_variable_set :@__job__, job_defn
|
179
|
+
Events.publish(base, 'acts_as_job.included', job_defn)
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
# @return [Job::Definition] The JobDefinition for this job instance.
|
184
|
+
def job
|
185
|
+
self.class.job_definition
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
# @return [Job::Run] The JobRun for this job instance.
|
190
|
+
def job_run
|
191
|
+
@__job_run__
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
@@ -0,0 +1,123 @@
|
|
1
|
+
class BatchKit
|
2
|
+
|
3
|
+
# When included into a class, marks the class as a BatchKit sequence.
|
4
|
+
# The including class has the following class methods added, which act as a
|
5
|
+
# DSL for specifying the sequence properties and behaviour:
|
6
|
+
# - {ClassMethods#desc desc} A method for setting a description for a
|
7
|
+
# subsequent sequence
|
8
|
+
# - {ClassMethods#sequence sequence} Defines a sequence entry method
|
9
|
+
# - {ClassMethods#sequence_definition sequence_definition} Returns the
|
10
|
+
# Sequence::Definition object for the including class
|
11
|
+
# - {ClassMethods#on_success on_success} defines a callback to be called if
|
12
|
+
# the sequence completes successfully.
|
13
|
+
# - {ClassMethods#on_failure on_failure} defines a callback to be called if
|
14
|
+
# the sequence encounters an unhandled exception.
|
15
|
+
#
|
16
|
+
# Instances of the including class also get the following instance methods:
|
17
|
+
# - {#sequence} Returns the Sequence::Definition for the class
|
18
|
+
# - {#sequence_run} Returns the Sequence::Run associated with this object instance.
|
19
|
+
module ActsAsSequence
|
20
|
+
|
21
|
+
# Define methods to be added to the class that includes this module.
|
22
|
+
module ClassMethods
|
23
|
+
|
24
|
+
# @return The Sequence::Definition object used to hold attributes of this
|
25
|
+
# sequence.
|
26
|
+
def sequence_definition
|
27
|
+
@__sequence__
|
28
|
+
end
|
29
|
+
alias_method :definition, :sequence_definition
|
30
|
+
|
31
|
+
|
32
|
+
# Captures a description for the following sequence definition.
|
33
|
+
#
|
34
|
+
# @param desc [String] The description to associate with the next
|
35
|
+
# sequence, job, or task that is defined.
|
36
|
+
def desc(desc)
|
37
|
+
@__desc__ = desc
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
# Defines the method that is used to run this job.
|
42
|
+
# This may be an existing method, in which case the name of the
|
43
|
+
# method must be passed as the first argument.
|
44
|
+
# Alternatively, a block may be supplied, which will be used to
|
45
|
+
# create the job method.
|
46
|
+
#
|
47
|
+
# @param sequence_method [Symbol] The name of an existing method that is
|
48
|
+
# to be the sequence entry point.
|
49
|
+
# @param sequence_opts [Hash] Options that affect the sequence definition.
|
50
|
+
# @option sequence_opts [Symbol] :method_name The name to be assigned to
|
51
|
+
# the sequence method created from the supplied block. Default is
|
52
|
+
# :execute.
|
53
|
+
# @option sequence_opts [String] :description A description for the sequence.
|
54
|
+
def sequence(sequence_method = nil, sequence_opts = @__desc__, &body)
|
55
|
+
# If called as an accessor, just return the @__sequence__
|
56
|
+
if sequence_method || sequence_opts || body
|
57
|
+
unless sequence_method.is_a?(Symbol)
|
58
|
+
sequence_opts = sequence_method
|
59
|
+
sequence_method = (sequence_opts && sequence_opts.is_a?(Hash) &&
|
60
|
+
sequence_opts[:method_name]) || :execute
|
61
|
+
end
|
62
|
+
|
63
|
+
sequence_desc = nil
|
64
|
+
if sequence_opts.is_a?(Hash)
|
65
|
+
sequence_desc = @__desc__
|
66
|
+
elsif sequence_opts.is_a?(String)
|
67
|
+
sequence_desc = sequence_opts
|
68
|
+
sequence_opts = {}
|
69
|
+
elsif sequence_opts.nil?
|
70
|
+
sequence_opts = {}
|
71
|
+
end
|
72
|
+
@__desc__ = nil
|
73
|
+
|
74
|
+
# Define sequence method if a body block was supplied
|
75
|
+
define_method(sequence_method, &body) if body
|
76
|
+
|
77
|
+
opts = sequence_opts.clone
|
78
|
+
opts[:description] = sequence_desc unless opts[:description]
|
79
|
+
opts[:method_name] = sequence_method
|
80
|
+
# The @__sequence__ instance variable is crated when this module is included
|
81
|
+
@__sequence__.set_from_options(opts)
|
82
|
+
end
|
83
|
+
@__sequence__
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
# Hook used to extend the including class with class methods defined in
|
90
|
+
# the ActsAsSequence::ClassMethods module.
|
91
|
+
#
|
92
|
+
# Creates a Sequence::Definition object to hold details of the sequence,
|
93
|
+
# and stores it away in a @__sequence__ class instance variable.
|
94
|
+
def self.included(base)
|
95
|
+
base.extend(ClassMethods)
|
96
|
+
caller.find{ |f| !(f =~ /batch.framework/) } =~ /^((?:[a-zA-Z]:)?[^:]+)/
|
97
|
+
sequence_file = File.realpath($1)
|
98
|
+
sequence_defn = Sequence::Definition.new(base, sequence_file)
|
99
|
+
base.instance_variable_set :@__sequence__, sequence_defn
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
def parallel
|
104
|
+
# TODO: Implement running contents of block in parallel
|
105
|
+
yield
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
# @return [Sequence::Definition] The SequenceDefinition for this Sequence instance.
|
110
|
+
def sequence
|
111
|
+
self.class.sequence_definition
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
# @return [Sequence::Run] The SequenceRun for this Sequence instance.
|
116
|
+
def sequence_run
|
117
|
+
@__sequence_run__
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|