Class: Nodule::Base
- Inherits:
-
Object
- Object
- Nodule::Base
- Defined in:
- lib/nodule/base.rb
Instance Attribute Summary collapse
-
#prefix ⇒ Object
Returns the value of attribute prefix.
-
#read_count ⇒ Object
readonly
Returns the value of attribute read_count.
-
#readers ⇒ Object
readonly
Returns the value of attribute readers.
-
#running ⇒ Object
readonly
Returns the value of attribute running.
-
#topology ⇒ Object
readonly
Returns the value of attribute topology.
Instance Method Summary collapse
-
#add_reader(action = nil) { ... } ⇒ Object
Add a reader action.
-
#add_readers(*args) ⇒ Object
Add reader arguments with add_reader.
-
#clear! ⇒ Object
Reset the read count to zero and clear any captured output.
- #done? ⇒ Boolean
-
#initialize(opts = {}) ⇒ Base
constructor
Create a new Nodule handler.
- #join_topology!(t, name = '') ⇒ Object
-
#output ⇒ Array<String>
Returns a copy of currently captured output.
-
#output! ⇒ Array<String>
Returns the captured output and clears the buffer (just like clear! but with a return value).
-
#output? ⇒ TrueClass, FalseClass
Returns whether or not any output has been captured.
-
#read_until(opts = {}) { ... } ⇒ Object
Wait in a sleep loop until a condition is true or the timeout is reached.
-
#require_read_count(count, max_sleep = 10) { ... } ⇒ Object
Wait in a sleep(0.1) loop for the number of reads on the handler to reach <count>.
- #run ⇒ Object
-
#run_readers(item, src = nil) ⇒ Object
Run all of the registered reader blocks.
- #stop ⇒ Object
- #stop! ⇒ Object
-
#verbose(*out) ⇒ Object
Verbose Nodule output.
- #wait(timeout = nil) ⇒ Object
-
#wait_with_backoff(timeout, sleeptime = 0.01) { ... } ⇒ Object
A dead-simple backoff loop.
Constructor Details
#initialize(opts = {}) ⇒ Base
Create a new Nodule handler. This is meant to be a bass class for higher-level Nodule types.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/nodule/base.rb', line 25 def initialize(opts={}) @read_count = 0 @readers ||= [] @output ||= [] @prefix = opts[:prefix] || '' @verbose = opts[:verbose] @done = false @topology = nil @capture_enabled = false add_readers(opts[:reader]) if opts[:reader] run if opts[:run] end |
Instance Attribute Details
#prefix ⇒ Object
Returns the value of attribute prefix.
12 13 14 |
# File 'lib/nodule/base.rb', line 12 def prefix @prefix end |
#read_count ⇒ Object (readonly)
Returns the value of attribute read_count.
11 12 13 |
# File 'lib/nodule/base.rb', line 11 def read_count @read_count end |
#readers ⇒ Object (readonly)
Returns the value of attribute readers.
11 12 13 |
# File 'lib/nodule/base.rb', line 11 def readers @readers end |
#running ⇒ Object (readonly)
Returns the value of attribute running.
11 12 13 |
# File 'lib/nodule/base.rb', line 11 def running @running end |
#topology ⇒ Object (readonly)
Returns the value of attribute topology.
11 12 13 |
# File 'lib/nodule/base.rb', line 11 def topology @topology end |
Instance Method Details
#add_reader(action = nil) { ... } ⇒ Object
Add a reader action. Can be a block which will be executed for each unit of input, :capture to capture all items emitted by the target to a list (accessible with .output), :ignore, or nil (which will be ignored).
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/nodule/base.rb', line 186 def add_reader(action=nil, &block) if block_given? @readers << block return unless action end if action.respond_to? :call @readers << action elsif action == :capture @capture_enabled = true @readers << proc { |item| @output.push(item) } elsif action == :drain @readers << proc { |_| } elsif action == :ignore # nothing to do here # if it's an unrecognized symbol, defer resolution against the containing topology elsif action.kind_of? Symbol @readers << proc do |item| raise "Topology is not set up!" unless @topology raise ":#{action} is not a valid topology symbol in #{@topology.to_hash.inspect}" unless @topology.has_key?(action) @topology[action].run_readers(item, self) end else raise ArgumentError.new "Invalid add_reader class: #{action.class}" end end |
#add_readers(*args) ⇒ Object
Add reader arguments with add_reader. Can be a single item or list.
217 218 219 220 221 |
# File 'lib/nodule/base.rb', line 217 def add_readers(*args) args.flatten.each do |reader| add_reader(reader) end end |
#clear! ⇒ Object
Reset the read count to zero and clear any captured output.
108 109 110 111 |
# File 'lib/nodule/base.rb', line 108 def clear! @read_count = 0 @output.clear end |
#done? ⇒ Boolean
66 67 68 |
# File 'lib/nodule/base.rb', line 66 def done? @done end |
#join_topology!(t, name = '') ⇒ Object
40 41 42 43 |
# File 'lib/nodule/base.rb', line 40 def join_topology!(t, name='') @topology = t @prefix = name if @prefix.nil? || @prefix.empty? end |
#output ⇒ Array<String>
Returns a copy of currently captured output. Line data is not chomped or anything of the sort. Will raise an exception if capture is not enabled.
88 89 90 91 |
# File 'lib/nodule/base.rb', line 88 def output raise "output is not captured unless you enable :capture" unless @capture_enabled @output.clone end |
#output! ⇒ Array<String>
Returns the captured output and clears the buffer (just like clear! but with a return value). Will raise an exception if capture is not enabled.
98 99 100 101 102 103 |
# File 'lib/nodule/base.rb', line 98 def output! raise "output is not captured unless you enable :capture" unless @capture_enabled out = @output.clone clear! out end |
#output? ⇒ TrueClass, FalseClass
Returns whether or not any output has been captured. Will raise an exception if capture is not enabled.
78 79 80 81 |
# File 'lib/nodule/base.rb', line 78 def output? raise "output is not captured unless you enable :capture" unless @capture_enabled @output.any? end |
#read_until(opts = {}) { ... } ⇒ Object
Wait in a sleep loop until a condition is true or the timeout is reached. On timeout an exception is raised. Has no impact on normal readers.
147 148 149 150 151 152 153 154 155 156 |
# File 'lib/nodule/base.rb', line 147 def read_until(opts = {}, &block) raise "No block given to read_until!" unless block_given? started = Time.now until block.call sleep (opts[:sleep_by] || 0.1) if Time.now - started >= (opts[:max_sleep] || 10.0) raise "Timeout!" end end end |
#require_read_count(count, max_sleep = 10) { ... } ⇒ Object
Wait in a sleep(0.1) loop for the number of reads on the handler to reach <count>. Returns when the number of reads is given. On timeout, if a block was provided, it’s called before return. Otherwise, an exception is raised. Has no impact on normal readers.
170 171 172 |
# File 'lib/nodule/base.rb', line 170 def require_read_count(count, max_sleep=10) read_until(:max_sleep => max_sleep) { @read_count == count } end |
#run ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/nodule/base.rb', line 45 def run @done = false unless @topology @toplogy = Nodule::Topology.new(:auto => self) end # automatically determine a prefix for console output based on the key name known to the topology if name = @topology.key(self) @prefix = "[#{name}]: " end end |
#run_readers(item, src = nil) ⇒ Object
Run all of the registered reader blocks. The block should expect a single argument that is an item of input. If the block has an arity of two, it will also be handed the nodule object provided to run_readers (if it was provided; no guarantee is made that it will be available). The arity-2 version is provided mostly as a clean way for Nodule::Console to add prefixes to output, but could be useful elsewhere.
232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/nodule/base.rb', line 232 def run_readers(item, src=nil) @read_count += 1 verbose "READ(#{@read_count}): #{item}" @readers.each do |reader| if reader.arity == 2 reader.call(item, src) else reader.call(item) end end end |
#stop ⇒ Object
58 59 60 |
# File 'lib/nodule/base.rb', line 58 def stop @done = true end |
#stop! ⇒ Object
62 63 64 |
# File 'lib/nodule/base.rb', line 62 def stop! @done = true end |
#verbose(*out) ⇒ Object
Verbose Nodule output.
248 249 250 251 252 253 254 255 256 |
# File 'lib/nodule/base.rb', line 248 def verbose(*out) if @verbose if @topology.respond_to? :[] and @topology[@verbose] @topology[@verbose].run_readers out.join(' ') else STDERR.print "#{out.join(' ')}\n" end end end |
#wait(timeout = nil) ⇒ Object
70 71 |
# File 'lib/nodule/base.rb', line 70 def wait(timeout=nil) end |
#wait_with_backoff(timeout, sleeptime = 0.01) { ... } ⇒ Object
A dead-simple backoff loop. Calls your block every @sleeptime seconds, increasing the sleep time by sleeptime every iteration, up to timeout, at which point false will be returned. If the block returns an non-false/nil value, it is returned.
122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/nodule/base.rb', line 122 def wait_with_backoff(timeout, sleeptime=0.01) raise "a block to execute on each iteration is required" unless block_given? started = Time.now loop do val = yield return val if val return false if Time.now - started > timeout sleep sleeptime if sleeptime < timeout / 4 sleeptime += sleeptime end end end |