rflow 1.0.1 → 1.1.0
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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +3 -0
- data/Gemfile +2 -1
- data/Guardfile +1 -1
- data/README.md +9 -9
- data/Vagrantfile +9 -9
- data/bin/rflow +9 -9
- data/example/http_extensions.rb +7 -7
- data/lib/rflow.rb +24 -3
- data/lib/rflow/child_process.rb +2 -0
- data/lib/rflow/component.rb +2 -2
- data/lib/rflow/component/port.rb +51 -26
- data/lib/rflow/configuration.rb +4 -4
- data/lib/rflow/configuration/ruby_dsl.rb +4 -4
- data/lib/rflow/connection.rb +4 -4
- data/lib/rflow/connections/zmq_connection.rb +5 -7
- data/lib/rflow/daemon_process.rb +12 -2
- data/lib/rflow/logger.rb +1 -1
- data/lib/rflow/master.rb +2 -20
- data/lib/rflow/message.rb +28 -18
- data/lib/rflow/pid_file.rb +17 -5
- data/lib/rflow/shard.rb +6 -6
- data/lib/rflow/version.rb +1 -1
- data/rflow.gemspec +20 -20
- data/schema/message.avsc +6 -1
- data/spec/rflow/component/port_spec.rb +17 -17
- data/spec/rflow/components/clock_spec.rb +1 -1
- data/spec/rflow/configuration/ruby_dsl_spec.rb +47 -47
- data/spec/rflow/configuration_spec.rb +8 -8
- data/spec/rflow/forward_to_input_port_spec.rb +38 -9
- data/spec/rflow/forward_to_output_port_spec.rb +5 -4
- data/spec/rflow/logger_spec.rb +5 -5
- data/spec/rflow/message/data/raw_spec.rb +2 -2
- data/spec/rflow/message/data_spec.rb +8 -8
- data/spec/rflow/message_spec.rb +63 -29
- data/spec/rflow_spec.rb +18 -18
- metadata +14 -13
- data/NOTES +0 -187
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 325fd6dd2c2d5409dc692a641c36da3b2139f7e8
|
4
|
+
data.tar.gz: d71bb8ce7e17c7e86fc1e2de7f299e73efdaeb5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5a602dc11534aa9a48b81bfc5d2035103b048b67d96684587f84c03152f90b415a43f6e19050616cbdccd37cfbad3ddf67e5c45ecfb4690c2dd40cfaa1b5883
|
7
|
+
data.tar.gz: e7d78c206614c6df0824b4d87f50a1c48edb54468defc498f5fa2319b05c707a4a4ee440514a8a11058998202b76ab93885859a8a50b1dbe85bc33bc82a5c041
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.
|
1
|
+
ruby-2.3.0
|
data/.travis.yml
CHANGED
@@ -4,6 +4,8 @@ rvm:
|
|
4
4
|
- 1.9.3
|
5
5
|
- 2.0.0
|
6
6
|
- 2.1.0
|
7
|
+
- 2.2.0
|
8
|
+
- 2.3.0
|
7
9
|
|
8
10
|
before_install:
|
9
11
|
- sudo apt-get install libtool autoconf automake uuid-dev build-essential
|
@@ -12,6 +14,7 @@ before_install:
|
|
12
14
|
# - sudo add-apt-repository -y ppa:chris-lea/zeromq
|
13
15
|
# - sudo apt-get update
|
14
16
|
# - sudo apt-get install libzmq3 libzmq3-dev
|
17
|
+
- gem update bundler
|
15
18
|
|
16
19
|
script: bundle exec rspec spec
|
17
20
|
|
data/Gemfile
CHANGED
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -13,7 +13,7 @@ RFlow is a Ruby framework inspired by
|
|
13
13
|
|
14
14
|
In short, components communicate with each other by sending/receiving
|
15
15
|
messages via their output/input ports over connections. Ports are
|
16
|
-
|
16
|
+
'wired' together output->input with connections, and messages are
|
17
17
|
explicitly serialized before being sent over the connection. RFlow
|
18
18
|
supports generalized connection types and message serialization,
|
19
19
|
however only two are in current use, namely ZeroMQ connections and
|
@@ -58,7 +58,7 @@ work. (You will probably get errors saying arcane things like
|
|
58
58
|
|
59
59
|
* __Port__ - a named entity on each component that is responsible for
|
60
60
|
receiving data (and input port) or sending data (and output port).
|
61
|
-
Ports can be
|
61
|
+
Ports can be 'keyed' or 'indexed' to allow better multiplexing of
|
62
62
|
messages out/in a single port, as well as allow a single port to be
|
63
63
|
accessed by an array.
|
64
64
|
|
@@ -70,7 +70,7 @@ work. (You will probably get errors saying arcane things like
|
|
70
70
|
* __Message__ - a bit of serialized data that is sent out an output
|
71
71
|
port and received on an input port. Due to the serialization,
|
72
72
|
message types and schemas are explicitly defined. In a departure
|
73
|
-
from
|
73
|
+
from 'pure' FBP, RFlow supports sending multiple message types via a
|
74
74
|
single connection.
|
75
75
|
|
76
76
|
* __Workflow__ - the common name for the digraph created when the
|
@@ -126,7 +126,7 @@ end
|
|
126
126
|
component to clean up any external resources that it might have
|
127
127
|
outstanding, such as file handles or network sockets.
|
128
128
|
|
129
|
-
|
129
|
+
'Source' components will often do all of their work within the `run!`
|
130
130
|
method, and often gather message data from an external source, such as
|
131
131
|
file, database, or network socket. The following component generates a
|
132
132
|
set of integers between a configured start/finish, incrementing by a
|
@@ -158,7 +158,7 @@ class RFlow::Components::GenerateIntegerSequence < RFlow::Component
|
|
158
158
|
end
|
159
159
|
```
|
160
160
|
|
161
|
-
|
161
|
+
'Middle' components receive messages on input port(s), perform a bit
|
162
162
|
of computation, and then send a message out the output port(s). The
|
163
163
|
following component accepts a Ruby expression string via its config,
|
164
164
|
and then uses that as an expression to determine what port to send an
|
@@ -189,7 +189,7 @@ class RFlow::Components::RubyProcFilter < RFlow::Component
|
|
189
189
|
end
|
190
190
|
```
|
191
191
|
|
192
|
-
|
192
|
+
'Sink' components accept messages on an input port and do not have an
|
193
193
|
output port. They often operate on external sinks, such as writing
|
194
194
|
messages to a file, database, or network socket. The following
|
195
195
|
component writes the inspected message to a file (defined via the
|
@@ -220,10 +220,10 @@ end
|
|
220
220
|
|
221
221
|
RFlow messages are instances of
|
222
222
|
[`RFlow::Message`](lib/rflow/message.rb), which are ultimately
|
223
|
-
serialized via an Avro [schema](schema/message.
|
223
|
+
serialized via an Avro [schema](schema/message.avsc).
|
224
224
|
|
225
|
-
There are two parts of the message
|
226
|
-
embedded data object
|
225
|
+
There are two parts of the message 'envelope': a provenance and the
|
226
|
+
embedded data object 'payload'.
|
227
227
|
|
228
228
|
The `provenance` is a way for a component to annotate a message with a
|
229
229
|
bit of data that should (by convention) be carried through the
|
data/Vagrantfile
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
# -*- mode: ruby -*-
|
2
2
|
# vi: set ft=ruby :
|
3
|
-
VAGRANTFILE_API_VERSION =
|
3
|
+
VAGRANTFILE_API_VERSION = '2'
|
4
4
|
|
5
5
|
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
6
6
|
config.vm.define 'centos62' do |c|
|
7
|
-
c.vm.box =
|
7
|
+
c.vm.box = 'jstoneham/rflow-centos62'
|
8
8
|
end
|
9
9
|
config.vm.define 'centos64' do |c|
|
10
|
-
c.vm.box =
|
10
|
+
c.vm.box = 'box-cutter/centos64'
|
11
11
|
end
|
12
12
|
config.vm.define 'centos65' do |c|
|
13
|
-
c.vm.box =
|
13
|
+
c.vm.box = 'chef/centos-6.5'
|
14
14
|
end
|
15
15
|
|
16
16
|
config.vm.synced_folder '.', '/rflow'
|
@@ -21,28 +21,28 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
|
21
21
|
config.vm.synced_folder '../rflow-components-http', '/rflow-components-http'
|
22
22
|
|
23
23
|
# forward http for rflow testing
|
24
|
-
config.vm.network
|
24
|
+
config.vm.network 'forwarded_port', guest: 8000, host: 8000
|
25
25
|
|
26
26
|
# install RPM dependencies for rflow and zeromq
|
27
|
-
config.vm.provision
|
27
|
+
config.vm.provision 'shell', privileged: true, inline: <<-EOS
|
28
28
|
curl -O https://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
|
29
29
|
rpm -ivh epel-release-6-8.noarch.rpm
|
30
30
|
yum -y install libyaml-devel patch libffi-devel glibc-headers autoconf gcc-c++ glibc-devel readline-devel zlib-devel openssl-devel automake libtool bison git sqlite-devel rpm-build libuuid-devel vim
|
31
31
|
EOS
|
32
32
|
|
33
33
|
# build zeromq as vagrant user
|
34
|
-
config.vm.provision
|
34
|
+
config.vm.provision 'shell', privileged: false, inline: <<-EOS
|
35
35
|
curl -O http://download.zeromq.org/zeromq-3.2.4.tar.gz
|
36
36
|
rpmbuild -tb zeromq-3.2.4.tar.gz
|
37
37
|
EOS
|
38
38
|
|
39
39
|
# install zeromq
|
40
|
-
config.vm.provision
|
40
|
+
config.vm.provision 'shell', privileged: true, inline: <<-EOS
|
41
41
|
rpm -ivh ~vagrant/rpmbuild/RPMS/x86_64/zeromq-*
|
42
42
|
EOS
|
43
43
|
|
44
44
|
# set up RVM and bundler
|
45
|
-
config.vm.provision
|
45
|
+
config.vm.provision 'shell', privileged: false, inline: <<-EOS
|
46
46
|
rm -f .profile
|
47
47
|
curl -sSL https://get.rvm.io | bash -s stable
|
48
48
|
source .rvm/scripts/rvm
|
data/bin/rflow
CHANGED
@@ -16,41 +16,41 @@ option_parser = OptionParser.new do |opts|
|
|
16
16
|
Usage: #{File.basename $0} [options] (start|stop|status|load)
|
17
17
|
EOB
|
18
18
|
|
19
|
-
opts.on(
|
19
|
+
opts.on('-d', '--database DB', 'Config database (sqlite) path (GENERALLY REQUIRED)') do |db|
|
20
20
|
options[:config_database_path] = File.expand_path(db)
|
21
21
|
end
|
22
22
|
|
23
|
-
opts.on(
|
23
|
+
opts.on('-c', '--config CONFIG', 'Config file path (only valid for load)') do |config|
|
24
24
|
options[:config_file_path] = File.expand_path(config)
|
25
25
|
end
|
26
26
|
|
27
|
-
opts.on(
|
27
|
+
opts.on('-e', '--extensions FILE1[,FILE_N]', Array, 'Extension file paths (will load)') do |extensions|
|
28
28
|
options[:extensions_file_paths] += extensions.map {|extension| File.expand_path(extension)}
|
29
29
|
end
|
30
30
|
|
31
|
-
opts.on(
|
31
|
+
opts.on('-g', '--gems GEM1[,GEM_N]', Array, 'Extension gems (will require)') do |gems|
|
32
32
|
options[:gems] += gems
|
33
33
|
end
|
34
34
|
|
35
|
-
opts.on(
|
35
|
+
opts.on('-l', '--log LOGFILE', 'Initial startup log file (in addition to stdout)') do |log|
|
36
36
|
options[:startup_log_file_path] = File.expand_path(log)
|
37
37
|
end
|
38
38
|
|
39
|
-
opts.on(
|
39
|
+
opts.on('-v', '--verbose [LEVEL]', [:DEBUG, :INFO, :WARN], 'Control the startup log (and stdout) verbosity (DEBUG, INFO, WARN) defaults to INFO') do |level|
|
40
40
|
options[:startup_log_level] = level || :DEBUG
|
41
41
|
end
|
42
42
|
|
43
|
-
opts.on(
|
43
|
+
opts.on('-f', 'Run in the foreground') do |f|
|
44
44
|
options[:daemonize] = false
|
45
45
|
end
|
46
46
|
|
47
|
-
opts.on_tail(
|
47
|
+
opts.on_tail('--version', 'Show RFlow version and exit') do
|
48
48
|
require 'rflow/version'
|
49
49
|
puts RFlow::VERSION
|
50
50
|
exit 0
|
51
51
|
end
|
52
52
|
|
53
|
-
opts.on_tail(
|
53
|
+
opts.on_tail('-h', '--help', 'Show this message and exit') do
|
54
54
|
puts opts
|
55
55
|
exit 0
|
56
56
|
end
|
data/example/http_extensions.rb
CHANGED
@@ -98,10 +98,10 @@ class HTTPServer < RFlow::Component
|
|
98
98
|
# This is done by inspecting the provenance, specifically the
|
99
99
|
# context attribute that we stored originally
|
100
100
|
def process_message(input_port, input_port_key, connection, message)
|
101
|
-
RFlow.logger.debug
|
101
|
+
RFlow.logger.debug 'Received a message'
|
102
102
|
return unless message.data_type_name == 'HTTPResponse'
|
103
103
|
|
104
|
-
RFlow.logger.debug
|
104
|
+
RFlow.logger.debug 'Received a HTTPResponse message, determining if its mine'
|
105
105
|
my_events = message.provenance.find_all {|processing_event| processing_event.component_instance_uuid == instance_uuid}
|
106
106
|
RFlow.logger.debug "Found #{my_events.size} processing events from me"
|
107
107
|
|
@@ -122,7 +122,7 @@ class HTTPServer < RFlow::Component
|
|
122
122
|
attr_accessor :server, :client_ip, :client_port
|
123
123
|
|
124
124
|
def post_init
|
125
|
-
@client_port, @client_ip = Socket.unpack_sockaddr_in(get_peername) rescue [
|
125
|
+
@client_port, @client_ip = Socket.unpack_sockaddr_in(get_peername) rescue ['?', '?.?.?.?']
|
126
126
|
RFlow.logger.debug "Connection from #{@client_ip}:#{@client_port}"
|
127
127
|
super
|
128
128
|
no_environment_strings
|
@@ -154,9 +154,9 @@ class HTTPServer < RFlow::Component
|
|
154
154
|
|
155
155
|
# Default values
|
156
156
|
resp.status = 200
|
157
|
-
resp.content =
|
158
|
-
resp.headers[
|
159
|
-
resp.headers[
|
157
|
+
resp.content = ''
|
158
|
+
resp.headers['Content-Type'] = 'text/html; charset=UTF-8'
|
159
|
+
resp.headers['Server'] = 'Apache/2.2.3 (CentOS)'
|
160
160
|
|
161
161
|
if response_message
|
162
162
|
resp.status = response_message.data.status
|
@@ -170,7 +170,7 @@ class HTTPServer < RFlow::Component
|
|
170
170
|
# Called when a connection is torn down for whatever reason.
|
171
171
|
# Remove this connection from the server's list
|
172
172
|
def unbind
|
173
|
-
RFlow.logger.debug
|
173
|
+
RFlow.logger.debug 'Connection lost'
|
174
174
|
server.connections.delete(self.signature)
|
175
175
|
end
|
176
176
|
end
|
data/lib/rflow.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
3
|
require 'time'
|
4
4
|
require 'active_record'
|
5
5
|
require 'eventmachine'
|
@@ -38,7 +38,7 @@ class RFlow
|
|
38
38
|
def self.establish_configuration
|
39
39
|
@configuration = Configuration.new(@config_database_path)
|
40
40
|
unless configuration['rflow.application_directory_path']
|
41
|
-
raise ArgumentError,
|
41
|
+
raise ArgumentError, 'Empty configuration database! Use a view/controller (such as the RubyDSL) to create a configuration'
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
@@ -60,4 +60,25 @@ class RFlow
|
|
60
60
|
master.daemonize! if @daemonize
|
61
61
|
master.run! # blocks until EventMachine stops
|
62
62
|
end
|
63
|
+
|
64
|
+
# This ought to be in EM, but we'll put it here instead of monkey-patching
|
65
|
+
def self.next_tick_and_wait
|
66
|
+
mutex = Mutex.new
|
67
|
+
condition = ConditionVariable.new
|
68
|
+
|
69
|
+
mutex.synchronize do # while locked...
|
70
|
+
EM.next_tick do # schedule a job that will...
|
71
|
+
mutex.synchronize do # grab the lock
|
72
|
+
begin
|
73
|
+
yield # do its thing...
|
74
|
+
condition.signal # then wake us up when it's done...
|
75
|
+
rescue
|
76
|
+
condition.signal # even if the thing fails
|
77
|
+
raise
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
condition.wait(mutex) # drop the mutex to allow the job to run
|
82
|
+
end
|
83
|
+
end
|
63
84
|
end
|
data/lib/rflow/child_process.rb
CHANGED
data/lib/rflow/component.rb
CHANGED
@@ -91,11 +91,11 @@ class RFlow
|
|
91
91
|
|
92
92
|
# Returns a list of connected input ports. Each port will have
|
93
93
|
# one or more keys associated with a particular connection.
|
94
|
-
def input_ports; ports.by_type[
|
94
|
+
def input_ports; ports.by_type['RFlow::Component::InputPort']; end
|
95
95
|
|
96
96
|
# Returns a list of connected output ports. Each port will have
|
97
97
|
# one or more keys associated with the particular connection.
|
98
|
-
def output_ports; ports.by_type[
|
98
|
+
def output_ports; ports.by_type['RFlow::Component::OutputPort']; end
|
99
99
|
|
100
100
|
def configure_input_port!(port_name, options = {})
|
101
101
|
RFlow.logger.debug "Configuring component '#{name}' (#{uuid}) input port '#{port_name}' (#{options[:uuid]})"
|
data/lib/rflow/component/port.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class RFlow
|
2
2
|
class Component
|
3
3
|
# TODO: make this into a class to limit the amount of extensions
|
4
|
-
# that we have to do when operating on these
|
4
|
+
# that we have to do when operating on these 'Arrays', i.e. when
|
5
5
|
# adding two together
|
6
6
|
module ConnectionCollection
|
7
7
|
def send_message(message)
|
@@ -44,6 +44,30 @@ class RFlow
|
|
44
44
|
def connected?; connected; end
|
45
45
|
end
|
46
46
|
|
47
|
+
# Stateless class to help with a nicer API
|
48
|
+
class HashSubPort
|
49
|
+
def initialize(hash_port, key)
|
50
|
+
@hash_port = hash_port
|
51
|
+
@key = key
|
52
|
+
end
|
53
|
+
|
54
|
+
def send_message(message)
|
55
|
+
connections.each {|connection| connection.send_message(message) }
|
56
|
+
end
|
57
|
+
|
58
|
+
def connections
|
59
|
+
@hash_port.connections_for(@key)
|
60
|
+
end
|
61
|
+
|
62
|
+
def direct_connect(other_port)
|
63
|
+
@hash_port.direct_connect(@key, other_port)
|
64
|
+
end
|
65
|
+
|
66
|
+
def each
|
67
|
+
connections.each {|connection| yield connection }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
47
71
|
# Allows for a list of connections to be assigned to each port/key
|
48
72
|
# combination. Note that binding an input port to an un-indexed
|
49
73
|
# output port will result in messages from all indexed connections
|
@@ -53,41 +77,44 @@ class RFlow
|
|
53
77
|
class HashPort < Port
|
54
78
|
attr_accessor :name, :uuid
|
55
79
|
|
56
|
-
protected
|
57
|
-
attr_reader :connections_for
|
58
|
-
|
59
80
|
public
|
60
81
|
def initialize(component, args = {})
|
61
82
|
super(component)
|
62
83
|
self.uuid = args[:uuid]
|
63
84
|
self.name = args[:name]
|
64
|
-
@connections_for = Hash.new {|hash, key| hash[key] = []
|
85
|
+
@connections_for = Hash.new {|hash, key| hash[key] = []}
|
65
86
|
end
|
66
87
|
|
67
|
-
#
|
68
|
-
#
|
88
|
+
# Get the subport for a given key, which can be used to send messages
|
89
|
+
# or direct connection
|
90
|
+
def [](key)
|
91
|
+
HashSubPort.new(self, key)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Returns an Array of all the connections that should
|
95
|
+
# be sent/received on this subport. Merges the nil-keyed port
|
69
96
|
# (i.e. any connections for a port without a key) to those
|
70
97
|
# specific for the key, so should only be used to read a list of
|
71
98
|
# connections, not to add new ones. Use add_connection to add a
|
72
99
|
# new connection for a given key.
|
73
|
-
def
|
100
|
+
def connections_for(key)
|
74
101
|
case key
|
75
|
-
when nil; connections_for[nil]
|
76
|
-
else connections_for[key] + connections_for[nil]
|
77
|
-
end
|
102
|
+
when nil; @connections_for[nil]
|
103
|
+
else @connections_for[key] + @connections_for[nil]
|
104
|
+
end
|
78
105
|
end
|
79
106
|
|
80
107
|
# Adds a connection for a given key
|
81
108
|
def add_connection(key, connection)
|
82
109
|
RFlow.logger.debug "Attaching #{connection.class.name} connection '#{connection.name}' (#{connection.uuid}) to port '#{name}' (#{uuid}), key '#{connection.input_port_key}'"
|
83
|
-
connections_for[key] << connection
|
110
|
+
@connections_for[key] << connection
|
84
111
|
@all_connections = nil
|
85
112
|
end
|
86
113
|
|
87
114
|
# Removes a connection from a given key
|
88
115
|
def remove_connection(key, connection)
|
89
116
|
RFlow.logger.debug "Removing #{connection.class.name} connection '#{connection.name}' (#{connection.uuid}) from port '#{name}' (#{uuid}), key '#{connection.input_port_key}'"
|
90
|
-
connections_for[key].delete(connection)
|
117
|
+
@connections_for[key].delete(connection)
|
91
118
|
@all_connections = nil
|
92
119
|
end
|
93
120
|
|
@@ -105,41 +132,39 @@ class RFlow
|
|
105
132
|
end
|
106
133
|
end
|
107
134
|
|
108
|
-
def direct_connect(other_port)
|
135
|
+
def direct_connect(key = nil, other_port)
|
109
136
|
case other_port
|
110
|
-
when InputPort; add_connection
|
111
|
-
when OutputPort; add_connection
|
137
|
+
when InputPort; add_connection key, ForwardToInputPort.new(other_port)
|
138
|
+
when OutputPort; add_connection key, ForwardToOutputPort.new(other_port)
|
112
139
|
else raise ArgumentError, "Unknown port type #{other_port.class.name}"
|
113
140
|
end
|
114
141
|
end
|
115
142
|
|
116
143
|
# Return a list of connected keys
|
117
144
|
def keys
|
118
|
-
connections_for.keys
|
145
|
+
@connections_for.keys
|
119
146
|
end
|
120
147
|
|
121
|
-
# Enumerate through all the ConnectionCollections
|
122
|
-
# TODO: simplify with enumerators and procs
|
123
148
|
def each
|
124
|
-
connections_for.values.each {|connections| yield connections }
|
149
|
+
@connections_for.values.each {|connections| yield connections }
|
125
150
|
end
|
126
151
|
|
127
152
|
def send_message(message)
|
128
|
-
|
153
|
+
raise NotImplementedError, 'Raw ports do not know how to send messages'
|
129
154
|
end
|
130
155
|
|
131
156
|
# Should be overridden. Called when it is time to actually
|
132
157
|
# establish the connection
|
133
|
-
def connect!; raise NotImplementedError,
|
158
|
+
def connect!; raise NotImplementedError, 'Raw ports do not know which direction to connect'; end
|
134
159
|
|
135
160
|
def all_connections
|
136
|
-
@all_connections ||= connections_for.values.flatten.uniq.extend(ConnectionCollection)
|
161
|
+
@all_connections ||= @connections_for.values.flatten.uniq.extend(ConnectionCollection)
|
137
162
|
end
|
138
163
|
end
|
139
164
|
|
140
165
|
class InputPort < HashPort
|
141
166
|
def connect!
|
142
|
-
connections_for.each {|key, conns| conns.each {|c| c.connect_input! } }
|
167
|
+
@connections_for.each {|key, conns| conns.each {|c| c.connect_input! } }
|
143
168
|
@connected = true
|
144
169
|
end
|
145
170
|
|
@@ -149,7 +174,7 @@ class RFlow
|
|
149
174
|
end
|
150
175
|
|
151
176
|
def recv_callback=(callback)
|
152
|
-
connections_for.each do |key, connections|
|
177
|
+
@connections_for.each do |key, connections|
|
153
178
|
connections.each do |connection|
|
154
179
|
connection.recv_callback = Proc.new do |message|
|
155
180
|
callback.call self, key, connection, message
|
@@ -161,7 +186,7 @@ class RFlow
|
|
161
186
|
|
162
187
|
class OutputPort < HashPort
|
163
188
|
def connect!
|
164
|
-
connections_for.each {|key, conns| conns.each {|c| c.connect_output! } }
|
189
|
+
@connections_for.each {|key, conns| conns.each {|c| c.connect_output! } }
|
165
190
|
@connected = true
|
166
191
|
end
|
167
192
|
|