Class: Tap::Joins::Gate

Inherits:
Tap::Join show all
Defined in:
lib/tap/joins/gate.rb

Overview

:startdoc::join collects results

Similar to a synchronized merge, but collects all results regardless of where they come from. Gates enque themselves when called as a join, and won’t let results pass until they get run as a task.

% tap load a -- load b - inspect - gate 0,1 2
["a", "b"]

Gates are useful in conjunction with iteration where a single task may feed multiple results to a single join; in this case a sync merge doesn’t produce the desired behavior of collecting the results.

% tap load/yaml "[1, 2, 3]" -:i inspect -:.gate inspect
1
2
3
[1, 2, 3]

% tap load/yaml "[1, 2, 3]" -:i inspect -:.sync inspect
1
[1]
2
[2]
3
[3]

When a limit is specified, the gate will collect results up to the limit and then pass the results. Any leftover results are still passed at the end.

% tap load/yaml "[1, 2, 3]" -:i inspect - inspect - gate 1 2 --limit 2
1
2
[1, 2]
3
[3]

Instance Attribute Summary collapse

Attributes inherited from Tap::Join

#inputs, #outputs

Attributes inherited from App::Api

#app

Instance Method Summary collapse

Methods inherited from Tap::Join

#associations, build, #join, #to_spec

Methods inherited from App::Api

#associations, build, help, inherited, #inspect, parse, parse!, parser, #to_spec

Methods included from Signals

#sig, #signal, #signal?, #signals

Methods included from Signals::ModuleMethods

included

Constructor Details

#initialize(config = {}, app = Tap::App.current) ⇒ Gate

Returns a new instance of Gate.



49
50
51
52
# File 'lib/tap/joins/gate.rb', line 49

def initialize(config={}, app=Tap::App.current)
  super
  @results = nil
end

Instance Attribute Details

#resultsObject (readonly)

An array of results collected thusfar.



45
46
47
# File 'lib/tap/joins/gate.rb', line 45

def results
  @results
end

Instance Method Details

#call(result) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/tap/joins/gate.rb', line 54

def call(result)
  if @results
    # Results are set, so self is already enqued and collecting
    # results.  If the input is the collection, then it's time
    # to execute the results and reset.  Otherwise, just
    # collect the input and wait.
    
    if result == @results
      @results = nil
      super(result)
    else
      @results << result
      
      if limit && @results.length >= limit
        super(@results.dup)
        @results.clear
      end
    end
    
  else
    # No results are set, so this is a first call and self is
    # not enqued.  Setup the collection.
    
    @results = [result]
    app.enq(self, @results)
  end
  
  self
end