rflow 0.0.5 → 1.0.0a1
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-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +21 -0
- data/.yardopts +1 -0
- data/Gemfile +5 -1
- data/Guardfile +8 -0
- data/LICENSE +190 -0
- data/NOTES +26 -13
- data/README.md +448 -0
- data/Rakefile +5 -12
- data/bin/rflow +23 -20
- data/example/basic_config.rb +2 -2
- data/example/basic_extensions.rb +8 -8
- data/example/http_config.rb +1 -1
- data/example/http_extensions.rb +15 -15
- data/lib/rflow.rb +15 -387
- data/lib/rflow/component.rb +105 -50
- data/lib/rflow/component/port.rb +25 -24
- data/lib/rflow/components/raw.rb +4 -4
- data/lib/rflow/components/raw/extensions.rb +2 -2
- data/lib/rflow/configuration.rb +54 -36
- data/lib/rflow/configuration/component.rb +2 -3
- data/lib/rflow/configuration/connection.rb +9 -10
- data/lib/rflow/configuration/migrations/{20010101000001_create_settings.rb → 20010101000000_create_settings.rb} +2 -2
- data/lib/rflow/configuration/migrations/20010101000001_create_shards.rb +21 -0
- data/lib/rflow/configuration/migrations/20010101000002_create_components.rb +7 -2
- data/lib/rflow/configuration/migrations/20010101000003_create_ports.rb +3 -3
- data/lib/rflow/configuration/migrations/20010101000004_create_connections.rb +2 -2
- data/lib/rflow/configuration/port.rb +3 -4
- data/lib/rflow/configuration/ruby_dsl.rb +59 -35
- data/lib/rflow/configuration/setting.rb +8 -7
- data/lib/rflow/configuration/shard.rb +24 -0
- data/lib/rflow/configuration/uuid_keyed.rb +3 -3
- data/lib/rflow/connection.rb +21 -10
- data/lib/rflow/connections/zmq_connection.rb +45 -44
- data/lib/rflow/logger.rb +67 -0
- data/lib/rflow/master.rb +127 -0
- data/lib/rflow/message.rb +14 -14
- data/lib/rflow/pid_file.rb +84 -0
- data/lib/rflow/shard.rb +148 -0
- data/lib/rflow/version.rb +1 -1
- data/rflow.gemspec +22 -28
- data/schema/message.avsc +8 -8
- data/spec/fixtures/config_ints.rb +4 -4
- data/spec/fixtures/config_shards.rb +30 -0
- data/spec/fixtures/extensions_ints.rb +8 -8
- data/spec/rflow_component_port_spec.rb +58 -0
- data/spec/rflow_configuration_ruby_dsl_spec.rb +148 -0
- data/spec/rflow_configuration_spec.rb +4 -4
- data/spec/rflow_message_data_raw.rb +2 -2
- data/spec/rflow_message_data_spec.rb +6 -6
- data/spec/rflow_message_spec.rb +13 -13
- data/spec/rflow_spec.rb +294 -71
- data/spec/schema_spec.rb +2 -2
- data/spec/spec_helper.rb +6 -4
- data/temp.rb +21 -21
- metadata +56 -65
- data/.rvmrc +0 -1
- data/README +0 -0
data/lib/rflow/component.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
1
3
|
require 'rflow/message'
|
2
4
|
require 'rflow/component/port'
|
3
5
|
|
@@ -8,7 +10,7 @@ class RFlow
|
|
8
10
|
RFlow::Configuration.add_available_component(subclass)
|
9
11
|
end
|
10
12
|
|
11
|
-
|
13
|
+
|
12
14
|
# The Component class methods used in the creation of a component
|
13
15
|
class << self
|
14
16
|
def defined_input_ports
|
@@ -23,7 +25,7 @@ class RFlow
|
|
23
25
|
# Port defintions only have names
|
24
26
|
|
25
27
|
# TODO: consider class-based UUIDs to identify component types
|
26
|
-
|
28
|
+
|
27
29
|
# Define an input port with a given name
|
28
30
|
def input_port(port_name)
|
29
31
|
define_port(defined_input_ports, port_name)
|
@@ -41,89 +43,142 @@ class RFlow
|
|
41
43
|
|
42
44
|
# Create the port accessor method based on the port name
|
43
45
|
define_method port_name.to_s.to_sym do
|
44
|
-
port = ports.by_name[port_name.to_s]
|
46
|
+
port = ports.by_name[port_name.to_s]
|
45
47
|
return port if port
|
46
|
-
|
48
|
+
|
47
49
|
# If the port was not connected, return a port-like object
|
48
50
|
# that can respond/log but doesn't send any data. Note,
|
49
51
|
# it won't be available in the 'by_uuid' collection, as it
|
50
|
-
# doesn't have a configured
|
52
|
+
# doesn't have a configured uuid
|
51
53
|
RFlow.logger.debug "'#{self.name}##{port_name}' not connected, creating a disconnected port"
|
52
|
-
|
54
|
+
|
55
|
+
disconnected_port = DisconnectedPort.new(OpenStruct.new(:name => port_name, :uuid => 0))
|
53
56
|
ports << disconnected_port
|
54
57
|
disconnected_port
|
55
58
|
end
|
56
59
|
end
|
60
|
+
|
61
|
+
|
62
|
+
# Attempt to instantiate a component described by the config
|
63
|
+
# specification. This assumes that the specification of a
|
64
|
+
# component is a fully qualified Ruby class that has already
|
65
|
+
# been loaded. It will first attempt to find subclasses of
|
66
|
+
# RFlow::Component (in the available_components hash) and then
|
67
|
+
# attempt to constantize the specification into a different
|
68
|
+
# class. Future releases will support external (i.e. non-managed
|
69
|
+
# components), but the current stuff only supports Ruby classes
|
70
|
+
def build(config)
|
71
|
+
if config.managed?
|
72
|
+
RFlow.logger.debug "Instantiating component '#{config.name}' as '#{config.specification}' (#{config.uuid})"
|
73
|
+
begin
|
74
|
+
RFlow.logger.debug RFlow.configuration.available_components.inspect
|
75
|
+
instantiated_component = if RFlow.configuration.available_components.include? config.specification
|
76
|
+
RFlow.logger.debug "Component found in configuration.available_components['#{config.specification}']"
|
77
|
+
RFlow.configuration.available_components[config.specification].new(config)
|
78
|
+
else
|
79
|
+
RFlow.logger.debug "Component not found in configuration.available_components, constantizing component '#{config.specification}'"
|
80
|
+
config.specification.constantize.new(config)
|
81
|
+
end
|
82
|
+
rescue NameError => e
|
83
|
+
error_message = "Could not instantiate component '#{config.name}' as '#{config.specification}' (#{config.uuid}): the class '#{config.specification}' was not found"
|
84
|
+
RFlow.logger.error error_message
|
85
|
+
raise RuntimeError, error_message
|
86
|
+
rescue Exception => e
|
87
|
+
error_message = "Could not instantiate component '#{config.name}' as '#{config.specification}' (#{config.uuid}): #{e.class} #{e.message}"
|
88
|
+
RFlow.logger.error error_message
|
89
|
+
raise RuntimeError, error_message
|
90
|
+
end
|
91
|
+
else
|
92
|
+
error_message = "Non-managed components not yet implemented for component '#{config.name}' as '#{config.specification}' (#{config.uuid})"
|
93
|
+
RFlow.logger.error error_message
|
94
|
+
raise NotImplementedError, error_message
|
95
|
+
end
|
96
|
+
|
97
|
+
instantiated_component
|
98
|
+
end
|
57
99
|
end
|
58
100
|
|
59
|
-
attr_reader :
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
@instance_uuid = uuid
|
66
|
-
@name = name
|
101
|
+
attr_reader :config, :uuid, :name, :ports
|
102
|
+
|
103
|
+
def initialize(config)
|
104
|
+
@config = config
|
105
|
+
@uuid = config.uuid
|
106
|
+
@name = config.name
|
67
107
|
@ports = PortCollection.new
|
68
|
-
|
108
|
+
|
109
|
+
configure_ports!
|
110
|
+
configure_connections!
|
111
|
+
configure!(config.options)
|
69
112
|
end
|
70
113
|
|
71
|
-
|
114
|
+
|
72
115
|
# Returns a list of connected input ports. Each port will have
|
73
116
|
# one or more keys associated with a particular connection.
|
74
117
|
def input_ports
|
75
118
|
ports.by_type["RFlow::Component::InputPort"]
|
76
119
|
end
|
77
120
|
|
78
|
-
|
121
|
+
|
79
122
|
# Returns a list of connected output ports. Each port will have
|
80
123
|
# one or more keys associated with the particular connection.
|
81
124
|
def output_ports
|
82
125
|
ports.by_type["RFlow::Component::OutputPort"]
|
83
126
|
end
|
84
127
|
|
85
|
-
|
128
|
+
|
86
129
|
# Returns a list of disconnected output ports.
|
87
130
|
def disconnected_ports
|
88
131
|
ports.by_type["RFlow::Component::DisconnectedPort"]
|
89
132
|
end
|
90
|
-
|
91
133
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
134
|
+
|
135
|
+
def configure_ports!
|
136
|
+
# Send the port configuration to each component
|
137
|
+
config.input_ports.each do |input_port_config|
|
138
|
+
RFlow.logger.debug "Configuring component '#{name}' (#{uuid}) with input port '#{input_port_config.name}' (#{input_port_config.uuid})"
|
139
|
+
configure_input_port!(input_port_config)
|
97
140
|
end
|
98
|
-
|
141
|
+
|
142
|
+
config.output_ports.each do |output_port_config|
|
143
|
+
RFlow.logger.debug "Configuring component '#{name}' (#{uuid}) with output port '#{output_port_config.name}' (#{output_port_config.uuid})"
|
144
|
+
configure_output_port!(output_port_config)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
def configure_input_port!(port_config)
|
150
|
+
unless self.class.defined_input_ports.include? port_config.name
|
151
|
+
raise ArgumentError, "Input port '#{port_config.name}' not defined on component '#{self.class}'"
|
152
|
+
end
|
153
|
+
ports << InputPort.new(port_config)
|
99
154
|
end
|
100
155
|
|
101
|
-
|
102
|
-
def configure_output_port!(
|
103
|
-
unless self.class.defined_output_ports.include?
|
104
|
-
raise ArgumentError, "Output port '#{
|
156
|
+
|
157
|
+
def configure_output_port!(port_config)
|
158
|
+
unless self.class.defined_output_ports.include? port_config.name
|
159
|
+
raise ArgumentError, "Output port '#{port_config.name}' not defined on component '#{self.class}'"
|
105
160
|
end
|
106
|
-
ports << OutputPort.new(
|
161
|
+
ports << OutputPort.new(port_config)
|
107
162
|
end
|
108
163
|
|
109
164
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
when 'RFlow::Configuration::ZMQConnection'
|
117
|
-
connection = RFlow::Connections::ZMQConnection.new(connection_uuid, connection_name, connection_options)
|
118
|
-
else
|
119
|
-
raise ArgumentError, "Only ZMQConnections currently supported"
|
165
|
+
def configure_connections!
|
166
|
+
config.input_ports.each do |input_port_config|
|
167
|
+
input_port_config.input_connections.each do |input_connection_config|
|
168
|
+
RFlow.logger.debug "Configuring input port '#{input_port_config.name}' (#{input_port_config.uuid}) key '#{input_connection_config.input_port_key}' with #{input_connection_config.type.to_s} connection '#{input_connection_config.name}' (#{input_connection_config.uuid})"
|
169
|
+
ports.by_uuid[input_port_config.uuid].add_connection(input_connection_config.input_port_key, Connection.build(input_connection_config))
|
170
|
+
end
|
120
171
|
end
|
121
172
|
|
122
|
-
|
123
|
-
|
173
|
+
config.output_ports.each do |output_port_config|
|
174
|
+
output_port_config.output_connections.each do |output_connection_config|
|
175
|
+
RFlow.logger.debug "Configuring output port '#{output_port_config.name}' (#{output_port_config.uuid}) key '#{output_connection_config.output_port_key}' with #{output_connection_config.type.to_s} connection '#{output_connection_config.name}' (#{output_connection_config.uuid})"
|
176
|
+
ports.by_uuid[output_port_config.uuid].add_connection(output_connection_config.output_port_key, Connection.build(output_connection_config))
|
177
|
+
end
|
178
|
+
end
|
124
179
|
end
|
125
180
|
|
126
|
-
|
181
|
+
|
127
182
|
# Tell the component to establish it's ports' connections, i.e. make
|
128
183
|
# the connection. Uses the underlying connection object. Also
|
129
184
|
# establishes the callbacks for each of the input ports
|
@@ -141,26 +196,26 @@ class RFlow
|
|
141
196
|
end
|
142
197
|
end
|
143
198
|
end
|
144
|
-
|
199
|
+
|
145
200
|
output_ports.each do |output_port|
|
146
201
|
output_port.connect!
|
147
202
|
end
|
148
203
|
end
|
149
204
|
|
150
|
-
|
205
|
+
|
151
206
|
def to_s
|
152
|
-
string = "Component '#{name}' (#{
|
207
|
+
string = "Component '#{name}' (#{uuid})\n"
|
153
208
|
ports.each do |port|
|
154
209
|
port.keys.each do |port_key|
|
155
210
|
port[port_key].each do |connection|
|
156
|
-
string << "\t#{port.class.to_s} '#{port.name}' (#{port.
|
211
|
+
string << "\t#{port.class.to_s} '#{port.name}' (#{port.uuid}) key '#{port_key}' connection '#{connection.name}' (#{connection.uuid})\n"
|
157
212
|
end
|
158
213
|
end
|
159
214
|
end
|
160
215
|
string
|
161
216
|
end
|
162
217
|
|
163
|
-
|
218
|
+
|
164
219
|
# Method that should be overridden by a subclass to provide for
|
165
220
|
# component-specific configuration. The subclass should use the
|
166
221
|
# self.configuration attribute (@configuration) to store its
|
@@ -168,7 +223,7 @@ class RFlow
|
|
168
223
|
# parameter is from the RFlow configuration database and is (most
|
169
224
|
# likely) a hash. Don't assume that the keys are symbols
|
170
225
|
def configure!(deserialized_configuration); end
|
171
|
-
|
226
|
+
|
172
227
|
# Main component running method. Subclasses should implement if
|
173
228
|
# they want to set up any EventMachine stuffs (servers, clients,
|
174
229
|
# etc)
|
@@ -187,6 +242,6 @@ class RFlow
|
|
187
242
|
# before the global RFlow exit. Sublcasses should implement to
|
188
243
|
# cleanup any leftover state, e.g. flush file handles, etc
|
189
244
|
def cleanup!; end
|
190
|
-
|
245
|
+
|
191
246
|
end # class Component
|
192
247
|
end # class RFlow
|
data/lib/rflow/component/port.rb
CHANGED
@@ -10,7 +10,7 @@ class RFlow
|
|
10
10
|
connection.send_message(message)
|
11
11
|
end
|
12
12
|
end
|
13
|
-
end
|
13
|
+
end
|
14
14
|
|
15
15
|
# Collection class to make it easier to index by both names,
|
16
16
|
# UUIDs, and types.
|
@@ -25,7 +25,7 @@ class RFlow
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def <<(port)
|
28
|
-
by_uuid[port.
|
28
|
+
by_uuid[port.uuid.to_s] = port
|
29
29
|
by_name[port.name.to_s] = port
|
30
30
|
by_type[port.class.to_s] << port
|
31
31
|
ports << port
|
@@ -42,12 +42,14 @@ class RFlow
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
45
|
-
|
46
45
|
|
47
|
-
# Bare superclass for (potential) later methods. Currently empty
|
48
|
-
class Port; end
|
49
46
|
|
50
|
-
|
47
|
+
class Port
|
48
|
+
attr_reader :connected
|
49
|
+
def connected?; @connected; end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
51
53
|
# Allows for a list of connections to be assigned to each port/key
|
52
54
|
# combination. Note that binding an input port to an un-indexed
|
53
55
|
# output port will result in messages from all indexed connections
|
@@ -55,14 +57,16 @@ class RFlow
|
|
55
57
|
# result in the same message being sent to all indexed
|
56
58
|
# connections.
|
57
59
|
class HashPort < Port
|
58
|
-
attr_reader :
|
59
|
-
|
60
|
-
def initialize(
|
61
|
-
@
|
62
|
-
@
|
60
|
+
attr_reader :config, :name, :uuid, :connections_for
|
61
|
+
|
62
|
+
def initialize(config)
|
63
|
+
@config = config
|
64
|
+
@name = config.name
|
65
|
+
@uuid = config.uuid
|
63
66
|
@connections_for = Hash.new {|hash, key| hash[key] = Array.new.extend(ConnectionCollection)}
|
64
67
|
end
|
65
68
|
|
69
|
+
|
66
70
|
# Returns an extended Array of all the connections that should
|
67
71
|
# be sent/received on this port. Merges the nil-keyed port
|
68
72
|
# (i.e. any connections for a port without a key) to those
|
@@ -79,7 +83,7 @@ class RFlow
|
|
79
83
|
connections_for[key] << connection
|
80
84
|
end
|
81
85
|
|
82
|
-
|
86
|
+
|
83
87
|
# Return a list of connected keys
|
84
88
|
def keys
|
85
89
|
connections_for.keys
|
@@ -94,13 +98,13 @@ class RFlow
|
|
94
98
|
end
|
95
99
|
end
|
96
100
|
|
97
|
-
|
101
|
+
|
98
102
|
# Send a message to all connections on all keys for this port,
|
99
103
|
# but only once per connection.
|
100
104
|
def send_message(message)
|
101
105
|
all_connections.send_message(message)
|
102
106
|
end
|
103
|
-
|
107
|
+
|
104
108
|
|
105
109
|
# Should be overridden. Called when it is time to actually
|
106
110
|
# establish the connection
|
@@ -113,38 +117,35 @@ class RFlow
|
|
113
117
|
connections
|
114
118
|
end.flatten.uniq.extend(ConnectionCollection)
|
115
119
|
end
|
116
|
-
|
120
|
+
|
117
121
|
end
|
118
122
|
|
119
|
-
|
123
|
+
|
120
124
|
class InputPort < HashPort
|
121
125
|
def connect!
|
122
126
|
connections_for.each do |port_key, connections|
|
123
127
|
connections.each do |connection|
|
124
128
|
connection.connect_input!
|
129
|
+
@connected = true
|
125
130
|
end
|
126
131
|
end
|
127
132
|
end
|
128
133
|
end
|
129
134
|
|
130
|
-
|
135
|
+
|
131
136
|
class OutputPort < HashPort
|
132
137
|
def connect!
|
133
138
|
connections_for.each do |port_key, keyed_connections|
|
134
139
|
keyed_connections.each do |connection|
|
135
140
|
connection.connect_output!
|
141
|
+
@connected = true
|
136
142
|
end
|
137
143
|
end
|
138
144
|
end
|
139
145
|
end
|
140
146
|
|
147
|
+
|
141
148
|
class DisconnectedPort < HashPort; end
|
142
|
-
|
149
|
+
|
143
150
|
end
|
144
151
|
end
|
145
|
-
|
146
|
-
__END__
|
147
|
-
|
148
|
-
out[even] -> a
|
149
|
-
out[odd] -> b
|
150
|
-
out[nil] -> c
|
data/lib/rflow/components/raw.rb
CHANGED
@@ -3,14 +3,14 @@ require 'rflow/components/raw/extensions'
|
|
3
3
|
class RFlow
|
4
4
|
module Components
|
5
5
|
module Raw
|
6
|
-
|
6
|
+
|
7
7
|
# Load the schemas
|
8
8
|
SCHEMA_DIRECTORY = ::File.expand_path(::File.join(::File.dirname(__FILE__), '..', '..', '..', 'schema'))
|
9
|
-
|
9
|
+
|
10
10
|
SCHEMA_FILES = {
|
11
11
|
'raw.avsc' => 'RFlow::Message::Data::Raw',
|
12
12
|
}
|
13
|
-
|
13
|
+
|
14
14
|
SCHEMA_FILES.each do |file_name, data_type_name|
|
15
15
|
schema_string = ::File.read(::File.join(SCHEMA_DIRECTORY, file_name))
|
16
16
|
RFlow::Configuration.add_available_data_type data_type_name, 'avro', schema_string
|
@@ -20,7 +20,7 @@ class RFlow
|
|
20
20
|
RFlow::Configuration.add_available_data_extension('RFlow::Message::Data::Raw',
|
21
21
|
RFlow::Components::Raw::Extensions::RawExtension)
|
22
22
|
|
23
|
-
|
23
|
+
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
data/lib/rflow/configuration.rb
CHANGED
@@ -17,13 +17,13 @@ class RFlow
|
|
17
17
|
# An exception class
|
18
18
|
class ConfigurationInvalid < StandardError; end
|
19
19
|
|
20
|
-
|
20
|
+
|
21
21
|
# A class to hold DB config and connection information
|
22
22
|
class ConfigDB < ActiveRecord::Base
|
23
23
|
self.abstract_class = true
|
24
24
|
end
|
25
|
-
|
26
|
-
|
25
|
+
|
26
|
+
|
27
27
|
# A collection class for data extensions that supports a naive
|
28
28
|
# prefix-based 'inheritance' on lookup. When looking up a key
|
29
29
|
# with [] all existing keys will be examined to determine if the
|
@@ -55,10 +55,10 @@ class RFlow
|
|
55
55
|
def clear
|
56
56
|
@hash.clear
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
end
|
60
60
|
|
61
|
-
|
61
|
+
|
62
62
|
class << self
|
63
63
|
|
64
64
|
# A collection of data types (schemas) indexed by their name and
|
@@ -119,7 +119,7 @@ class RFlow
|
|
119
119
|
available_data_extensions.add data_type_name, data_extension
|
120
120
|
end
|
121
121
|
|
122
|
-
|
122
|
+
|
123
123
|
# Used when RFlow::Component is subclassed to add another
|
124
124
|
# available component to the list.
|
125
125
|
def self.add_available_component(component)
|
@@ -141,8 +141,8 @@ class RFlow
|
|
141
141
|
ConfigDB.establish_connection(:adapter => "sqlite3",
|
142
142
|
:database => config_database_path)
|
143
143
|
end
|
144
|
-
|
145
|
-
|
144
|
+
|
145
|
+
|
146
146
|
# Using default ActiveRecord migrations, attempt to migrate the
|
147
147
|
# database to the latest version.
|
148
148
|
def self.migrate_database
|
@@ -160,7 +160,7 @@ class RFlow
|
|
160
160
|
load config_file_path
|
161
161
|
end
|
162
162
|
|
163
|
-
|
163
|
+
|
164
164
|
# Connect to the configuration database, migrate it to the latest
|
165
165
|
# version, and process a config file if provided.
|
166
166
|
def self.initialize_database(config_database_path, config_file_path=nil)
|
@@ -172,7 +172,7 @@ class RFlow
|
|
172
172
|
:database => config_database_path)
|
173
173
|
|
174
174
|
migrate_database
|
175
|
-
|
175
|
+
|
176
176
|
expanded_config_file_path = File.expand_path config_file_path if config_file_path
|
177
177
|
|
178
178
|
working_dir = Dir.getwd
|
@@ -183,12 +183,14 @@ class RFlow
|
|
183
183
|
end
|
184
184
|
|
185
185
|
RFlow.logger.debug "Defaulting non-existing config values"
|
186
|
-
merge_defaults!
|
186
|
+
merge_defaults!
|
187
187
|
|
188
188
|
Dir.chdir working_dir
|
189
|
+
|
190
|
+
self.new(config_database_path)
|
189
191
|
end
|
190
192
|
|
191
|
-
|
193
|
+
|
192
194
|
# Make sure that the configuration has all the necessary values set.
|
193
195
|
def self.merge_defaults!
|
194
196
|
Setting::DEFAULTS.each do |name, default_value_or_proc|
|
@@ -202,8 +204,8 @@ class RFlow
|
|
202
204
|
end
|
203
205
|
end
|
204
206
|
end
|
205
|
-
|
206
|
-
|
207
|
+
|
208
|
+
|
207
209
|
attr_accessor :config_database_path
|
208
210
|
attr_accessor :cached_settings
|
209
211
|
attr_accessor :cached_components
|
@@ -211,19 +213,24 @@ class RFlow
|
|
211
213
|
attr_accessor :cached_connections
|
212
214
|
|
213
215
|
|
214
|
-
def initialize(config_database_path)
|
216
|
+
def initialize(config_database_path=nil)
|
215
217
|
@cached_settings = Hash.new
|
216
218
|
@cached_components = Hash.new
|
217
219
|
@cached_ports = []
|
218
220
|
@cached_connections = []
|
219
221
|
|
220
|
-
|
221
|
-
|
222
|
+
# If there is not a config DB path, assume that an AR
|
223
|
+
# conncection has already been established
|
224
|
+
if config_database_path
|
225
|
+
@config_database_path = config_database_path
|
226
|
+
self.class.establish_config_database_connection(config_database_path)
|
227
|
+
end
|
222
228
|
|
223
229
|
# Validate the connected database. TODO: make this more
|
224
230
|
# complete, i.e. validate the various columns
|
225
231
|
begin
|
226
232
|
Setting.first
|
233
|
+
Shard.first
|
227
234
|
Component.first
|
228
235
|
Port.first
|
229
236
|
Connection.first
|
@@ -234,44 +241,54 @@ class RFlow
|
|
234
241
|
end
|
235
242
|
end
|
236
243
|
|
237
|
-
|
244
|
+
|
238
245
|
def to_s
|
239
246
|
string = "Configuration:\n"
|
247
|
+
|
240
248
|
settings.each do |setting|
|
241
249
|
string << "Setting: '#{setting.name}' = '#{setting.value}'\n"
|
242
250
|
end
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
+
|
252
|
+
shards.each do |shard|
|
253
|
+
string << "Shard #{shard.name} (#{shard.uuid}), type #{shard.class.name}, count #{shard.count}\n"
|
254
|
+
shard.components.each do |component|
|
255
|
+
string << " Component '#{component.name}' as #{component.specification} (#{component.uuid})\n"
|
256
|
+
component.output_ports.each do |output_port|
|
257
|
+
output_port.output_connections.each do |output_connection|
|
258
|
+
input_port = output_connection.input_port
|
259
|
+
string << " OutputPort '#{output_port.name}' key '#{output_connection.output_port_key}' (#{output_port.uuid}) =>\n"
|
260
|
+
string << " Connection '#{output_connection.name}' as #{output_connection.type} (#{output_connection.uuid}) =>\n"
|
261
|
+
string << " InputPort '#{input_port.name}' key '#{output_connection.input_port_key}' (#{input_port.uuid}) Component '#{input_port.component.name}' (#{input_port.component.uuid})\n"
|
262
|
+
end
|
251
263
|
end
|
252
264
|
end
|
253
265
|
end
|
254
266
|
string
|
255
267
|
end
|
256
|
-
|
268
|
+
|
257
269
|
# Helper method to access settings with minimal syntax
|
258
270
|
def [](setting_name)
|
259
271
|
Setting.find_by_name(setting_name).value rescue nil
|
260
272
|
end
|
261
273
|
|
262
|
-
|
274
|
+
def settings
|
275
|
+
Setting.all
|
276
|
+
end
|
277
|
+
|
278
|
+
def shards
|
279
|
+
Shard.all
|
280
|
+
end
|
281
|
+
|
282
|
+
def shard(shard_uuid)
|
283
|
+
Shard.find_by_uuid shard_uuid
|
284
|
+
end
|
285
|
+
|
263
286
|
def components
|
264
287
|
Component.all
|
265
288
|
end
|
266
289
|
|
267
|
-
|
268
|
-
|
269
|
-
Component.find_by_uuid component_instance_uuid
|
270
|
-
end
|
271
|
-
|
272
|
-
|
273
|
-
def settings
|
274
|
-
Setting.all
|
290
|
+
def component(component_uuid)
|
291
|
+
Component.find_by_uuid component_uuid
|
275
292
|
end
|
276
293
|
|
277
294
|
def available_components
|
@@ -282,6 +299,7 @@ end
|
|
282
299
|
|
283
300
|
# Load the models
|
284
301
|
require 'rflow/configuration/setting'
|
302
|
+
require 'rflow/configuration/shard'
|
285
303
|
require 'rflow/configuration/component'
|
286
304
|
require 'rflow/configuration/port'
|
287
305
|
require 'rflow/configuration/connection'
|