tap 0.11.1 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History +35 -1
- data/MIT-LICENSE +1 -1
- data/README +16 -15
- data/bin/tap +1 -1
- data/cmd/console.rb +4 -3
- data/cmd/manifest.rb +2 -2
- data/cmd/run.rb +12 -15
- data/doc/Class Reference +120 -117
- data/doc/Command Reference +27 -27
- data/doc/Syntax Reference +55 -111
- data/doc/Tutorial +69 -26
- data/lib/tap.rb +3 -8
- data/lib/tap/app.rb +122 -146
- data/lib/tap/constants.rb +2 -2
- data/lib/tap/env.rb +178 -252
- data/lib/tap/exe.rb +67 -30
- data/lib/tap/file_task.rb +224 -411
- data/lib/tap/generator/arguments.rb +13 -0
- data/lib/tap/generator/base.rb +112 -30
- data/lib/tap/generator/destroy.rb +36 -13
- data/lib/tap/generator/generate.rb +69 -48
- data/lib/tap/generator/generators/command/templates/command.erb +3 -3
- data/lib/tap/generator/generators/config/config_generator.rb +82 -10
- data/lib/tap/generator/generators/generator/generator_generator.rb +16 -6
- data/lib/tap/generator/generators/generator/templates/task.erb +2 -2
- data/lib/tap/generator/generators/generator/templates/test.erb +26 -0
- data/lib/tap/generator/generators/root/root_generator.rb +24 -13
- data/lib/tap/generator/generators/root/templates/Rakefile +4 -4
- data/lib/tap/generator/generators/root/templates/{tapfile → Rapfile} +6 -6
- data/lib/tap/generator/generators/root/templates/gemspec +0 -1
- data/lib/tap/generator/generators/task/task_generator.rb +3 -3
- data/lib/tap/generator/generators/task/templates/test.erb +1 -1
- data/lib/tap/generator/manifest.rb +7 -1
- data/lib/tap/generator/preview.rb +76 -0
- data/lib/tap/root.rb +222 -156
- data/lib/tap/spec.rb +41 -0
- data/lib/tap/support/aggregator.rb +25 -28
- data/lib/tap/support/audit.rb +278 -357
- data/lib/tap/support/constant.rb +2 -1
- data/lib/tap/support/constant_manifest.rb +28 -25
- data/lib/tap/support/dependency.rb +1 -1
- data/lib/tap/support/executable.rb +52 -183
- data/lib/tap/support/executable_queue.rb +50 -20
- data/lib/tap/support/gems.rb +1 -1
- data/lib/tap/support/intern.rb +0 -6
- data/lib/tap/support/join.rb +49 -83
- data/lib/tap/support/joins.rb +0 -3
- data/lib/tap/support/joins/switch.rb +13 -11
- data/lib/tap/support/joins/sync_merge.rb +25 -50
- data/lib/tap/support/manifest.rb +1 -0
- data/lib/tap/support/node.rb +140 -20
- data/lib/tap/support/parser.rb +56 -42
- data/lib/tap/support/schema.rb +183 -157
- data/lib/tap/support/templater.rb +9 -1
- data/lib/tap/support/versions.rb +39 -0
- data/lib/tap/task.rb +150 -177
- data/lib/tap/tasks/dump.rb +4 -4
- data/lib/tap/tasks/load.rb +29 -29
- data/lib/tap/test.rb +66 -53
- data/lib/tap/test/env_vars.rb +3 -3
- data/lib/tap/test/extensions.rb +11 -17
- data/lib/tap/test/file_test.rb +74 -132
- data/lib/tap/test/file_test_class.rb +4 -1
- data/lib/tap/test/regexp_escape.rb +2 -2
- data/lib/tap/test/script_test.rb +2 -2
- data/lib/tap/test/subset_test.rb +6 -6
- data/lib/tap/test/tap_test.rb +28 -154
- metadata +30 -51
- data/bin/rap +0 -118
- data/cgi/run.rb +0 -97
- data/lib/tap/declarations.rb +0 -229
- data/lib/tap/generator/generators/config/templates/doc.erb +0 -12
- data/lib/tap/generator/generators/config/templates/nodoc.erb +0 -8
- data/lib/tap/generator/generators/file_task/file_task_generator.rb +0 -27
- data/lib/tap/generator/generators/file_task/templates/file.txt +0 -11
- data/lib/tap/generator/generators/file_task/templates/result.yml +0 -6
- data/lib/tap/generator/generators/file_task/templates/task.erb +0 -33
- data/lib/tap/generator/generators/file_task/templates/test.erb +0 -29
- data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +0 -5
- data/lib/tap/patches/optparse/summarize.rb +0 -62
- data/lib/tap/support/assignments.rb +0 -173
- data/lib/tap/support/class_configuration.rb +0 -182
- data/lib/tap/support/combinator.rb +0 -125
- data/lib/tap/support/configurable.rb +0 -113
- data/lib/tap/support/configurable_class.rb +0 -271
- data/lib/tap/support/configuration.rb +0 -170
- data/lib/tap/support/gems/rake.rb +0 -111
- data/lib/tap/support/instance_configuration.rb +0 -173
- data/lib/tap/support/joins/fork.rb +0 -19
- data/lib/tap/support/joins/merge.rb +0 -22
- data/lib/tap/support/joins/sequence.rb +0 -21
- data/lib/tap/support/lazy_attributes.rb +0 -45
- data/lib/tap/support/lazydoc.rb +0 -386
- data/lib/tap/support/lazydoc/comment.rb +0 -503
- data/lib/tap/support/lazydoc/config.rb +0 -17
- data/lib/tap/support/lazydoc/definition.rb +0 -36
- data/lib/tap/support/lazydoc/document.rb +0 -152
- data/lib/tap/support/lazydoc/method.rb +0 -24
- data/lib/tap/support/tdoc.rb +0 -409
- data/lib/tap/support/tdoc/tdoc_html_generator.rb +0 -38
- data/lib/tap/support/tdoc/tdoc_html_template.rb +0 -42
- data/lib/tap/support/validation.rb +0 -479
- data/lib/tap/tasks/rake.rb +0 -57
data/lib/tap/support/constant.rb
CHANGED
@@ -21,7 +21,8 @@ module Tap
|
|
21
21
|
# const_name. When a constant is missing, constantize yields
|
22
22
|
# the current base and any non-existant constant names the block,
|
23
23
|
# if given, or raises a NameError. The block is expected
|
24
|
-
# to return the
|
24
|
+
# to return the desired constant; in the example 'Non::Existant'
|
25
|
+
# is effectively mapping to ConstName.
|
25
26
|
#
|
26
27
|
# module ConstName; end
|
27
28
|
#
|
@@ -4,18 +4,24 @@ require 'tap/support/constant'
|
|
4
4
|
module Tap
|
5
5
|
module Support
|
6
6
|
|
7
|
+
# :startdoc:::-
|
8
|
+
#
|
7
9
|
# ConstantManifest builds a manifest of Constant entries using Lazydoc.
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
10
|
+
#
|
11
|
+
# Lazydoc can quickly scan files for constant attributes, and thereby
|
12
|
+
# identify constants based upon a flag like the '::manifest' attribute used
|
13
|
+
# to identify task classes. ConstantManifest registers paths that will be
|
14
|
+
# scanned for a specific resource, and lazily builds the references to load
|
15
|
+
# them as necessary.
|
16
|
+
#
|
17
|
+
# :startdoc:::+
|
12
18
|
class ConstantManifest < Support::Manifest
|
13
19
|
|
14
|
-
# The attribute identifying
|
20
|
+
# The attribute identifying constants in a file
|
15
21
|
attr_reader :const_attr
|
16
22
|
|
17
|
-
#
|
18
|
-
# for
|
23
|
+
# An array of registered (root, [paths]) pairs
|
24
|
+
# that will be searched for const_attr
|
19
25
|
attr_reader :search_paths
|
20
26
|
|
21
27
|
# The current index of search_paths
|
@@ -24,7 +30,8 @@ module Tap
|
|
24
30
|
# The current index of paths
|
25
31
|
attr_reader :path_index
|
26
32
|
|
27
|
-
# Initializes a new ConstantManifest
|
33
|
+
# Initializes a new ConstantManifest that will identify constants
|
34
|
+
# using the specified constant attribute.
|
28
35
|
def initialize(const_attr)
|
29
36
|
@const_attr = const_attr
|
30
37
|
@search_paths = []
|
@@ -55,15 +62,15 @@ module Tap
|
|
55
62
|
# Sets search_path_index and path_index to zero and clears entries.
|
56
63
|
# Returns self.
|
57
64
|
def reset
|
58
|
-
|
65
|
+
@search_paths.each {|path| Lazydoc[path].resolved = false }
|
59
66
|
@entries.clear
|
60
67
|
@search_path_index = 0
|
61
68
|
@path_index = 0
|
62
69
|
super
|
63
70
|
end
|
64
71
|
|
65
|
-
# Yields each entry to the block. Unless built?, each
|
66
|
-
# iterates over search_paths to look for new entries.
|
72
|
+
# Yields each Constant entry to the block. Unless built?, each
|
73
|
+
# lazily iterates over search_paths to look for new entries.
|
67
74
|
def each
|
68
75
|
entries.each do |entry|
|
69
76
|
yield(entry)
|
@@ -93,25 +100,21 @@ module Tap
|
|
93
100
|
# objects for each. If the document has no default_const_name set,
|
94
101
|
# resolve will set the default_const_name based on the relative
|
95
102
|
# filepath from path_root to path.
|
96
|
-
def resolve(path_root, path)
|
103
|
+
def resolve(path_root, path) # :nodoc:
|
97
104
|
entries = []
|
98
|
-
|
105
|
+
document = nil
|
99
106
|
|
100
|
-
Lazydoc.scan(File.read(path), const_attr) do |const_name,
|
101
|
-
if
|
102
|
-
|
103
|
-
|
104
|
-
if lazydoc.default_const_name.empty?
|
105
|
-
relative_path = Root.relative_filepath(path_root, path).chomp(File.extname(path))
|
106
|
-
lazydoc.default_const_name = relative_path.camelize
|
107
|
-
end
|
107
|
+
Lazydoc::Document.scan(File.read(path), const_attr) do |const_name, key, value|
|
108
|
+
if document == nil
|
109
|
+
relative_path = Root.relative_filepath(path_root, path).chomp(File.extname(path))
|
110
|
+
document = Lazydoc.register_file(path, relative_path.camelize)
|
108
111
|
end
|
109
112
|
|
110
|
-
if const_name.empty?
|
111
|
-
|
112
|
-
|
113
|
+
const_name = document.default_const_name if const_name.empty?
|
114
|
+
comment = Lazydoc::Subject.new(nil, document)
|
115
|
+
comment.value = value
|
113
116
|
|
114
|
-
|
117
|
+
document[const_name][key] = comment
|
115
118
|
entries << Constant.new(const_name, path)
|
116
119
|
end
|
117
120
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'tap/support/audit'
|
2
|
+
require 'tap/support/joins'
|
2
3
|
|
3
4
|
module Tap
|
4
5
|
module Support
|
@@ -10,7 +11,7 @@ module Tap
|
|
10
11
|
attr_reader :app
|
11
12
|
|
12
13
|
# The method called during _execute
|
13
|
-
attr_reader :
|
14
|
+
attr_reader :method_name
|
14
15
|
|
15
16
|
# The block called when _execute completes
|
16
17
|
attr_reader :on_complete_block
|
@@ -18,143 +19,33 @@ module Tap
|
|
18
19
|
# An array of dependency indicies that will be resolved on _execute
|
19
20
|
attr_reader :dependencies
|
20
21
|
|
21
|
-
# The batch for self
|
22
|
-
attr_reader :batch
|
23
|
-
|
24
22
|
public
|
25
23
|
|
26
24
|
# Extends obj with Executable and sets up all required variables. The
|
27
25
|
# specified method will be called on _execute.
|
28
|
-
def self.initialize(obj, method_name, app=App.instance,
|
26
|
+
def self.initialize(obj, method_name, app=App.instance, dependencies=[], &on_complete_block)
|
29
27
|
obj.extend Executable
|
30
28
|
obj.instance_variable_set(:@app, app)
|
31
|
-
obj.instance_variable_set(:@
|
29
|
+
obj.instance_variable_set(:@method_name, method_name)
|
32
30
|
obj.instance_variable_set(:@on_complete_block, on_complete_block)
|
33
31
|
obj.instance_variable_set(:@dependencies, dependencies)
|
34
|
-
obj.instance_variable_set(:@batch, batch)
|
35
|
-
batch << obj
|
36
|
-
|
37
32
|
obj
|
38
33
|
end
|
39
34
|
|
40
|
-
#
|
41
|
-
#
|
42
|
-
# can raise an error for objects that don't support dup,
|
43
|
-
# notably Method objects generated by Object#_method).
|
44
|
-
def initialize_batch_obj
|
45
|
-
obj = self.dup
|
46
|
-
|
47
|
-
if obj.kind_of?(Executable)
|
48
|
-
batch << obj
|
49
|
-
obj
|
50
|
-
else
|
51
|
-
Executable.initialize(obj, _method_name, app, batch, dependencies, &on_complete_block)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Returns true if the batch size is greater than one
|
56
|
-
# (the one is assumed to be self).
|
57
|
-
def batched?
|
58
|
-
batch.length > 1
|
59
|
-
end
|
60
|
-
|
61
|
-
# Returns the index of self in batch.
|
62
|
-
def batch_index
|
63
|
-
batch.index(self)
|
64
|
-
end
|
65
|
-
|
66
|
-
# Merges the batches for self and the specified Executables,
|
67
|
-
# removing duplicates.
|
68
|
-
#
|
69
|
-
# class BatchExecutable
|
70
|
-
# include Tap::Support::Executable
|
71
|
-
# def initialize(batch=[])
|
72
|
-
# @batch = batch
|
73
|
-
# batch << self
|
74
|
-
# end
|
75
|
-
# end
|
76
|
-
#
|
77
|
-
# b1 = BatchExecutable.new
|
78
|
-
# b2 = BatchExecutable.new
|
79
|
-
# b3 = BatchExecutable.new
|
80
|
-
#
|
81
|
-
# b1.batch_with(b2, b3)
|
82
|
-
# b1.batch # => [b1, b2, b3]
|
83
|
-
# b3.batch # => [b1, b2, b3]
|
84
|
-
#
|
85
|
-
# Note that batch_with is not recursive (ie it does not
|
86
|
-
# merge the batches of each member in the batch):
|
87
|
-
#
|
88
|
-
# b4 = BatchExecutable.new
|
89
|
-
# b4.batch_with(b3)
|
90
|
-
#
|
91
|
-
# b4.batch # => [b4, b1, b2, b3]
|
92
|
-
# b3.batch # => [b4, b1, b2, b3]
|
93
|
-
# b2.batch # => [b1, b2, b3]
|
94
|
-
# b1.batch # => [b1, b2, b3]
|
95
|
-
#
|
96
|
-
# However it does affect all objects that share the same
|
97
|
-
# underlying batch:
|
98
|
-
#
|
99
|
-
# b5 = BatchExecutable.new(b1.batch)
|
100
|
-
# b6 = BatchExecutable.new
|
101
|
-
#
|
102
|
-
# b5.batch.object_id # => b1.batch.object_id
|
103
|
-
# b5.batch # => [b1, b2, b3, b5]
|
104
|
-
#
|
105
|
-
# b5.batch_with(b6)
|
106
|
-
#
|
107
|
-
# b5.batch # => [b1, b2, b3, b5, b6]
|
108
|
-
# b1.batch # => [b1, b2, b3, b5, b6]
|
109
|
-
#
|
110
|
-
# Returns self.
|
111
|
-
def batch_with(*executables)
|
112
|
-
batches = [batch] + executables.collect {|executable| executable.batch }
|
113
|
-
batches.uniq!
|
114
|
-
|
115
|
-
merged = []
|
116
|
-
batches.each do |batch|
|
117
|
-
merged.concat(batch)
|
118
|
-
batch.clear
|
119
|
-
end
|
120
|
-
|
121
|
-
merged.uniq!
|
122
|
-
batches.each {|batch| batch.concat(merged) }
|
123
|
-
self
|
124
|
-
end
|
125
|
-
|
126
|
-
# Enqueues each member of batch (and implicitly self) to app with the
|
127
|
-
# inputs. The number of inputs provided should match the number of
|
128
|
-
# inputs for the _method_name method.
|
35
|
+
# Enqueues self to app with the inputs. The number of inputs provided
|
36
|
+
# should match the number of inputs for the method_name method.
|
129
37
|
def enq(*inputs)
|
130
|
-
batch.each do |executable|
|
131
|
-
executable.unbatched_enq(*inputs)
|
132
|
-
end
|
133
|
-
self
|
134
|
-
end
|
135
|
-
|
136
|
-
# Like enq, but only enques self.
|
137
|
-
def unbatched_enq(*inputs)
|
138
38
|
app.queue.enq(self, inputs)
|
139
39
|
self
|
140
40
|
end
|
141
41
|
|
142
|
-
# Sets a block to receive the results of _execute
|
143
|
-
#
|
144
|
-
# is already set within the batch. Override the existing
|
42
|
+
# Sets a block to receive the results of _execute. Raises an error if
|
43
|
+
# an on_complete_block is already set. Override the existing
|
145
44
|
# on_complete_block by specifying override = true.
|
146
45
|
#
|
147
46
|
# Note: the block recieves an audited result and not the result
|
148
47
|
# itself (see Audit for more information).
|
149
48
|
def on_complete(override=false, &block) # :yields: _result
|
150
|
-
batch.each do |executable|
|
151
|
-
executable.unbatched_on_complete(override, &block)
|
152
|
-
end
|
153
|
-
self
|
154
|
-
end
|
155
|
-
|
156
|
-
# Like on_complete, but only sets the on_complete_block for self.
|
157
|
-
def unbatched_on_complete(override=false, &block) # :yields: _result
|
158
49
|
unless on_complete_block == nil || override
|
159
50
|
raise "on_complete_block already set: #{self}"
|
160
51
|
end
|
@@ -163,56 +54,54 @@ module Tap
|
|
163
54
|
end
|
164
55
|
|
165
56
|
# Sets a sequence workflow pattern for the tasks; each task
|
166
|
-
# enques the next task with it's results, starting with self.
|
167
|
-
# See Joins::Sequence.
|
57
|
+
# enques the next task with it's results, starting with self.
|
168
58
|
def sequence(*tasks, &block) # :yields: _result
|
169
|
-
|
59
|
+
options = tasks[-1].kind_of?(Hash) ? tasks.pop : {}
|
60
|
+
|
61
|
+
current_task = self
|
62
|
+
tasks.each do |next_task|
|
63
|
+
Join.new(options).join([current_task], [next_task], &block)
|
64
|
+
current_task = next_task
|
65
|
+
end
|
170
66
|
end
|
171
67
|
|
172
|
-
# Sets a fork workflow pattern for self; each target
|
173
|
-
#
|
68
|
+
# Sets a fork workflow pattern for self; each target will enque the
|
69
|
+
# results of self.
|
174
70
|
def fork(*targets, &block) # :yields: _result
|
175
|
-
|
71
|
+
options = targets[-1].kind_of?(Hash) ? targets.pop : {}
|
72
|
+
Join.new(options).join([self], targets, &block)
|
176
73
|
end
|
177
74
|
|
178
75
|
# Sets a simple merge workflow pattern for the source tasks. Each
|
179
76
|
# source enques self with it's result; no synchronization occurs,
|
180
|
-
# nor are results grouped before being enqued.
|
77
|
+
# nor are results grouped before being enqued.
|
181
78
|
def merge(*sources, &block) # :yields: _result
|
182
|
-
|
79
|
+
options = sources[-1].kind_of?(Hash) ? sources.pop : {}
|
80
|
+
Join.new(options).join(sources, [self], &block)
|
183
81
|
end
|
184
82
|
|
185
83
|
# Sets a synchronized merge workflow for the source tasks. Results
|
186
84
|
# from each source are collected and enqued as a single group to
|
187
85
|
# self. The collective results are not enqued until all sources
|
188
86
|
# have completed. See Joins::SyncMerge.
|
189
|
-
#
|
190
|
-
# Raises an error if a source returns twice before the target is enqued.
|
191
87
|
def sync_merge(*sources, &block) # :yields: _result
|
192
|
-
|
88
|
+
options = sources[-1].kind_of?(Hash) ? sources.pop : {}
|
89
|
+
Joins::SyncMerge.new(options).join(sources, [self], &block)
|
193
90
|
end
|
194
91
|
|
195
|
-
# Sets a switch workflow pattern for self.
|
196
|
-
#
|
197
|
-
#
|
198
|
-
#
|
199
|
-
#
|
92
|
+
# Sets a switch workflow pattern for self. On complete, switch yields
|
93
|
+
# the audited result to the block and the block should return the index
|
94
|
+
# of the target to enque with the results. No target will be enqued if
|
95
|
+
# the index is false or nil. An error is raised if no target can be
|
96
|
+
# found for the specified index. See Joins::Switch.
|
200
97
|
def switch(*targets, &block) # :yields: _result
|
201
|
-
|
98
|
+
options = targets[-1].kind_of?(Hash) ? targets.pop : {}
|
99
|
+
Joins::Switch.new(options).join([self], targets, &block)
|
202
100
|
end
|
203
101
|
|
204
|
-
# Adds the
|
205
|
-
#
|
206
|
-
# _execute, using resolve_dependencies.
|
102
|
+
# Adds the dependencies to self. Dependencies are resolved during
|
103
|
+
# _execute through resolve_dependencies.
|
207
104
|
def depends_on(*dependencies)
|
208
|
-
batch.each do |e|
|
209
|
-
e.unbatched_depends_on(*dependencies)
|
210
|
-
end
|
211
|
-
self
|
212
|
-
end
|
213
|
-
|
214
|
-
# Like depends_on, but only adds the dependency to self.
|
215
|
-
def unbatched_depends_on(*dependencies)
|
216
105
|
raise ArgumentError, "cannot depend on self" if dependencies.include?(self)
|
217
106
|
|
218
107
|
dependencies.each do |dependency|
|
@@ -236,53 +125,37 @@ module Tap
|
|
236
125
|
self
|
237
126
|
end
|
238
127
|
|
239
|
-
# Auditing method call. Resolves dependencies, executes
|
128
|
+
# Auditing method call. Resolves dependencies, executes method_name,
|
240
129
|
# and sends the audited result to the on_complete_block (if set).
|
241
130
|
#
|
242
|
-
#
|
243
|
-
# no inputs:: Creates a new, empty Audit. The first value of the audit
|
244
|
-
# will be the result of call.
|
245
|
-
# one input:: Forks the input if it is an audit, otherwise initializes
|
246
|
-
# a new audit using the input.
|
247
|
-
# multiple inputs:: Merges the inputs into a new Audit.
|
248
|
-
#
|
131
|
+
# Returns the audited result.
|
249
132
|
def _execute(*inputs)
|
250
133
|
resolve_dependencies
|
251
134
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
inputs = [audit._current]
|
258
|
-
audit._fork
|
135
|
+
previous = []
|
136
|
+
inputs.collect! do |input|
|
137
|
+
if input.kind_of?(Audit)
|
138
|
+
previous << input
|
139
|
+
input.value
|
259
140
|
else
|
260
|
-
Audit.new(
|
261
|
-
|
262
|
-
else
|
263
|
-
sources = []
|
264
|
-
inputs.collect! do |input|
|
265
|
-
if input.kind_of?(Audit)
|
266
|
-
sources << input._fork
|
267
|
-
input._current
|
268
|
-
else
|
269
|
-
sources << nil
|
270
|
-
input
|
271
|
-
end
|
141
|
+
previous << Audit.new(nil, input)
|
142
|
+
input
|
272
143
|
end
|
273
|
-
Audit.new(inputs, sources)
|
274
144
|
end
|
275
|
-
|
276
|
-
audit.
|
277
|
-
|
145
|
+
|
146
|
+
audit = Audit.new(self, send(method_name, *inputs), previous)
|
147
|
+
if complete_block = on_complete_block || app.on_complete_block
|
148
|
+
complete_block.call(audit)
|
149
|
+
else
|
150
|
+
app.aggregator.store(audit)
|
151
|
+
end
|
278
152
|
|
279
153
|
audit
|
280
154
|
end
|
281
155
|
|
282
|
-
# Calls _execute with the inputs and returns the
|
283
|
-
# Execute is not a batched method.
|
156
|
+
# Calls _execute with the inputs and returns the non-audited result.
|
284
157
|
def execute(*inputs)
|
285
|
-
_execute(*inputs).
|
158
|
+
_execute(*inputs).value
|
286
159
|
end
|
287
160
|
|
288
161
|
# Raises a TerminateError if app.state == State::TERMINATE.
|
@@ -294,10 +167,6 @@ module Tap
|
|
294
167
|
end
|
295
168
|
end
|
296
169
|
|
297
|
-
def inspect
|
298
|
-
"#<#{self.class.to_s}:#{object_id} _method: #{_method_name} batch_length: #{batch.length} app: #{app}>"
|
299
|
-
end
|
300
|
-
|
301
170
|
end
|
302
171
|
end
|
303
172
|
end
|
@@ -1,35 +1,39 @@
|
|
1
|
+
require 'tap/support/executable'
|
2
|
+
|
1
3
|
module Tap
|
2
4
|
module Support
|
3
5
|
|
4
|
-
# ExecutableQueue allows thread-safe enqueing and dequeing of
|
5
|
-
#
|
6
|
-
class ExecutableQueue
|
7
|
-
include MonitorMixin
|
6
|
+
# ExecutableQueue allows thread-safe enqueing and dequeing of Executable
|
7
|
+
# methods and inputs for execution.
|
8
|
+
class ExecutableQueue < Monitor
|
8
9
|
|
9
10
|
# Creates a new ExecutableQueue
|
10
11
|
def initialize
|
11
|
-
|
12
|
-
|
13
|
-
@queue = []
|
12
|
+
super
|
13
|
+
@rounds = [[]]
|
14
14
|
end
|
15
15
|
|
16
|
-
# Clears
|
16
|
+
# Clears self and returns an array of the enqueued methods and inputs,
|
17
|
+
# organized by round.
|
17
18
|
def clear
|
18
19
|
synchronize do
|
19
|
-
current =
|
20
|
-
self.queue = []
|
20
|
+
current, @rounds = @rounds, [[]]
|
21
21
|
current
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
# Returns the number of enqueued methods
|
26
26
|
def size
|
27
|
-
|
27
|
+
synchronize do
|
28
|
+
size = 0
|
29
|
+
@rounds.each {|round| size += round.length }
|
30
|
+
size
|
31
|
+
end
|
28
32
|
end
|
29
33
|
|
30
34
|
# True if no methods are enqueued
|
31
35
|
def empty?
|
32
|
-
|
36
|
+
synchronize { size == 0 }
|
33
37
|
end
|
34
38
|
|
35
39
|
# Enqueues the method and inputs. Raises an error if the
|
@@ -56,26 +60,52 @@ module Tap
|
|
56
60
|
synchronize { queue.shift }
|
57
61
|
end
|
58
62
|
|
59
|
-
|
63
|
+
# Enques an array of [method, inputs] entries as a round. Rounds are
|
64
|
+
# dequeued completely before the next round is dequeued.
|
65
|
+
def concat(round)
|
60
66
|
synchronize do
|
61
|
-
|
62
|
-
|
67
|
+
round.each do |method, inputs|
|
68
|
+
check_method(method)
|
63
69
|
end
|
70
|
+
|
71
|
+
@rounds << round.dup
|
64
72
|
end
|
65
73
|
end
|
66
74
|
|
67
|
-
# Converts self to an array.
|
68
|
-
|
69
|
-
|
75
|
+
# Converts self to an array. If flatten is specified, all rounds are
|
76
|
+
# concatenated into a single array.
|
77
|
+
def to_a(flatten=true)
|
78
|
+
synchronize do
|
79
|
+
if flatten
|
80
|
+
array = []
|
81
|
+
@rounds.each {|round| array.concat(round) }
|
82
|
+
array
|
83
|
+
else
|
84
|
+
@rounds.collect {|round| round.dup}
|
85
|
+
end
|
86
|
+
end
|
70
87
|
end
|
71
88
|
|
72
89
|
protected
|
73
90
|
|
74
|
-
|
91
|
+
# Returns the active round.
|
92
|
+
def queue # :nodoc:
|
93
|
+
while @rounds.length > 1
|
94
|
+
queue = @rounds[0]
|
95
|
+
|
96
|
+
if queue.empty?
|
97
|
+
@rounds.shift
|
98
|
+
else
|
99
|
+
return queue
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
@rounds[0]
|
104
|
+
end
|
75
105
|
|
76
106
|
# Checks if the input method is extended with Executable
|
77
107
|
def check_method(method) # :nodoc:
|
78
|
-
raise "not
|
108
|
+
raise "not executable: #{method.inspect}" unless method.kind_of?(Executable)
|
79
109
|
end
|
80
110
|
end
|
81
111
|
end
|