rflow 1.0.0a1 → 1.0.0a2
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/.gitignore +2 -0
- data/.rspec +1 -0
- data/Gemfile +0 -1
- data/NOTES +0 -13
- data/README.md +6 -1
- data/bin/rflow +2 -9
- data/example/basic_config.rb +1 -33
- data/example/basic_extensions.rb +0 -98
- data/example/http_config.rb +2 -3
- data/example/http_extensions.rb +6 -63
- data/lib/rflow.rb +31 -39
- data/lib/rflow/child_process.rb +112 -0
- data/lib/rflow/component.rb +77 -148
- data/lib/rflow/component/port.rb +38 -41
- data/lib/rflow/components.rb +4 -8
- data/lib/rflow/components/clock.rb +49 -0
- data/lib/rflow/components/integer.rb +39 -0
- data/lib/rflow/components/raw.rb +10 -6
- data/lib/rflow/components/replicate.rb +20 -0
- data/lib/rflow/components/ruby_proc_filter.rb +27 -0
- data/lib/rflow/configuration.rb +105 -184
- data/lib/rflow/configuration/component.rb +1 -4
- data/lib/rflow/configuration/connection.rb +11 -16
- data/lib/rflow/configuration/port.rb +3 -5
- data/lib/rflow/configuration/ruby_dsl.rb +105 -119
- data/lib/rflow/configuration/setting.rb +19 -25
- data/lib/rflow/configuration/shard.rb +1 -3
- data/lib/rflow/connection.rb +47 -10
- data/lib/rflow/connections.rb +0 -1
- data/lib/rflow/connections/zmq_connection.rb +34 -38
- data/lib/rflow/daemon_process.rb +155 -0
- data/lib/rflow/logger.rb +41 -25
- data/lib/rflow/master.rb +23 -105
- data/lib/rflow/message.rb +78 -108
- data/lib/rflow/pid_file.rb +37 -37
- data/lib/rflow/shard.rb +33 -100
- data/lib/rflow/version.rb +2 -2
- data/rflow.gemspec +2 -2
- data/schema/tick.avsc +10 -0
- data/spec/fixtures/config_ints.rb +4 -40
- data/spec/fixtures/config_shards.rb +1 -2
- data/spec/fixtures/extensions_ints.rb +0 -98
- data/spec/rflow/component/port_spec.rb +61 -0
- data/spec/rflow/components/clock_spec.rb +72 -0
- data/spec/rflow/configuration/ruby_dsl_spec.rb +150 -0
- data/spec/rflow/configuration_spec.rb +54 -0
- data/spec/rflow/forward_to_input_port_spec.rb +48 -0
- data/spec/rflow/forward_to_output_port_spec.rb +40 -0
- data/spec/rflow/logger_spec.rb +48 -0
- data/spec/rflow/message/data/raw_spec.rb +29 -0
- data/spec/rflow/message/data_spec.rb +58 -0
- data/spec/rflow/message_spec.rb +154 -0
- data/spec/rflow_spec.rb +94 -124
- data/spec/spec_helper.rb +8 -12
- metadata +46 -22
- data/lib/rflow/components/raw/extensions.rb +0 -18
- data/lib/rflow/port.rb +0 -4
- data/lib/rflow/util.rb +0 -19
- data/spec/rflow_component_port_spec.rb +0 -58
- data/spec/rflow_configuration_ruby_dsl_spec.rb +0 -148
- data/spec/rflow_configuration_spec.rb +0 -73
- data/spec/rflow_message_data_raw.rb +0 -26
- data/spec/rflow_message_data_spec.rb +0 -60
- data/spec/rflow_message_spec.rb +0 -182
- data/spec/schema_spec.rb +0 -28
- data/temp.rb +0 -295
@@ -3,13 +3,10 @@ require 'rflow/configuration/uuid_keyed'
|
|
3
3
|
|
4
4
|
class RFlow
|
5
5
|
class Configuration
|
6
|
-
class Component <
|
6
|
+
class Component < ConfigurationItem
|
7
7
|
include UUIDKeyed
|
8
8
|
include ActiveModel::Validations
|
9
9
|
|
10
|
-
class ComponentInvalid < StandardError; end
|
11
|
-
class ComponentNotFound < StandardError; end
|
12
|
-
|
13
10
|
serialize :options, Hash
|
14
11
|
|
15
12
|
belongs_to :shard, :primary_key => 'uuid', :foreign_key => 'shard_uuid'
|
@@ -3,7 +3,7 @@ require 'rflow/configuration/uuid_keyed'
|
|
3
3
|
|
4
4
|
class RFlow
|
5
5
|
class Configuration
|
6
|
-
class Connection <
|
6
|
+
class Connection < ConfigurationItem
|
7
7
|
class ConnectionInvalid < StandardError; end
|
8
8
|
|
9
9
|
include UUIDKeyed
|
@@ -19,10 +19,9 @@ class RFlow
|
|
19
19
|
validates_uniqueness_of :uuid
|
20
20
|
validates_presence_of :output_port_uuid, :input_port_uuid
|
21
21
|
|
22
|
-
validate :all_required_options_present
|
22
|
+
validate :all_required_options_present?
|
23
23
|
|
24
|
-
|
25
|
-
def all_required_options_present
|
24
|
+
def all_required_options_present?
|
26
25
|
self.class.required_options.each do |option_name|
|
27
26
|
unless self.options.include? option_name.to_s
|
28
27
|
errors.add(:options, "must include #{option_name} for #{self.class.to_s}")
|
@@ -30,49 +29,41 @@ class RFlow
|
|
30
29
|
end
|
31
30
|
end
|
32
31
|
|
33
|
-
|
34
32
|
def merge_default_options!
|
35
33
|
self.options ||= {}
|
36
|
-
self.class.default_options.each do |
|
37
|
-
self.options[
|
34
|
+
self.class.default_options.each do |name, default_value_or_proc|
|
35
|
+
self.options[name.to_s] ||= default_value_or_proc.is_a?(Proc) ? default_value_or_proc.call(self) : default_value_or_proc
|
38
36
|
end
|
39
37
|
end
|
40
38
|
|
41
|
-
|
42
39
|
# Should return a list of require option names which will be
|
43
40
|
# used in validations. To be overridden.
|
44
41
|
def self.required_options; []; end
|
45
42
|
|
46
|
-
|
47
43
|
# Should return a hash of default options, where the keys are
|
48
44
|
# the option names and the values are either default option
|
49
45
|
# values or Procs that take a single connection argument. This
|
50
46
|
# allow defaults to use other parameters in the connection to
|
51
47
|
# construct the appropriate default value.
|
52
48
|
def self.default_options; {}; end
|
53
|
-
|
54
49
|
end
|
55
50
|
|
56
|
-
|
57
51
|
# STI Subclass for ZMQ connections and their required options
|
58
52
|
class ZMQConnection < Connection
|
59
|
-
|
60
53
|
def self.default_options
|
61
54
|
{
|
62
55
|
'output_socket_type' => 'PUSH',
|
63
|
-
'output_address'
|
56
|
+
'output_address' => lambda{|conn| "ipc://rflow.#{conn.uuid}"},
|
64
57
|
'output_responsibility' => 'connect',
|
65
58
|
'input_socket_type' => 'PULL',
|
66
|
-
'input_address'
|
59
|
+
'input_address' => lambda{|conn| "ipc://rflow.#{conn.uuid}"},
|
67
60
|
'input_responsibility' => 'bind',
|
68
61
|
}
|
69
62
|
end
|
70
63
|
end
|
71
64
|
|
72
|
-
|
73
65
|
# STI Subclass for AMQP connections and their required options
|
74
66
|
class AMQPConnection < Connection
|
75
|
-
|
76
67
|
def self.default_options
|
77
68
|
{
|
78
69
|
'host' => 'localhost',
|
@@ -91,7 +82,11 @@ class RFlow
|
|
91
82
|
'queue_nowait' => true,
|
92
83
|
}
|
93
84
|
end
|
85
|
+
end
|
94
86
|
|
87
|
+
# for testing purposes
|
88
|
+
class NullConfiguration
|
89
|
+
attr_accessor :name, :uuid, :options
|
95
90
|
end
|
96
91
|
end
|
97
92
|
end
|
@@ -3,12 +3,10 @@ require 'rflow/configuration/uuid_keyed'
|
|
3
3
|
|
4
4
|
class RFlow
|
5
5
|
class Configuration
|
6
|
-
class Port <
|
6
|
+
class Port < ConfigurationItem
|
7
7
|
include UUIDKeyed
|
8
8
|
include ActiveModel::Validations
|
9
9
|
|
10
|
-
class PortInvalid < StandardError; end
|
11
|
-
|
12
10
|
belongs_to :component, :primary_key => 'uuid', :foreign_key => 'component_uuid'
|
13
11
|
|
14
12
|
# TODO: Make some sort of component/port validation work here
|
@@ -16,12 +14,12 @@ class RFlow
|
|
16
14
|
end
|
17
15
|
|
18
16
|
# STI-based classes
|
19
|
-
class InputPort < Port
|
17
|
+
class InputPort < Port
|
20
18
|
has_many :input_connections, :class_name => 'RFlow::Configuration::Connection', :primary_key => 'uuid', :foreign_key => 'input_port_uuid'
|
21
19
|
has_many :connections, :class_name => 'RFlow::Configuration::Connection', :primary_key => 'uuid', :foreign_key => 'input_port_uuid'
|
22
20
|
end
|
23
21
|
|
24
|
-
class OutputPort < Port
|
22
|
+
class OutputPort < Port
|
25
23
|
has_many :output_connections, :class_name => 'RFlow::Configuration::Connection', :primary_key => 'uuid', :foreign_key => 'output_port_uuid'
|
26
24
|
has_many :connections, :class_name => 'RFlow::Configuration::Connection', :primary_key => 'uuid', :foreign_key => 'output_port_uuid'
|
27
25
|
end
|
@@ -2,57 +2,53 @@ require 'rflow/configuration'
|
|
2
2
|
|
3
3
|
class RFlow
|
4
4
|
class Configuration
|
5
|
-
|
6
5
|
# Ruby DSL config file controller.
|
7
6
|
# TODO: more docs and examples
|
8
7
|
class RubyDSL
|
9
|
-
|
8
|
+
private
|
9
|
+
attr_accessor :setting_specs, :shard_specs, :connection_specs, :default_shard
|
10
10
|
|
11
|
+
public
|
11
12
|
def initialize
|
13
|
+
@default_shard = {:name => "DEFAULT", :type => :process, :count => 1, :components => []}
|
14
|
+
@current_shard = default_shard
|
15
|
+
|
12
16
|
@setting_specs = []
|
13
|
-
@shard_specs = [
|
17
|
+
@shard_specs = [default_shard]
|
14
18
|
@connection_specs = []
|
15
|
-
|
16
|
-
@current_shard = @shard_specs.first
|
17
|
-
end
|
18
|
-
|
19
|
-
# Helper function to extract the line of the config that
|
20
|
-
# specified the operation. Useful in printing helpful error messages
|
21
|
-
def get_config_line(call_history)
|
22
|
-
call_history.first.split(':in').first
|
23
19
|
end
|
24
20
|
|
25
21
|
# DSL method to specify a name/value pair. RFlow core uses the
|
26
22
|
# 'rflow.' prefix on all of its settings. Custom settings
|
27
23
|
# should use a custom (unique) prefix
|
28
|
-
def setting(
|
29
|
-
setting_specs << {:name =>
|
24
|
+
def setting(name, value)
|
25
|
+
setting_specs << {:name => name.to_s, :value => value.to_s, :config_line => get_config_line(caller)}
|
30
26
|
end
|
31
27
|
|
32
28
|
# DSL method to specify a shard block for either a process or thread
|
33
|
-
def shard(
|
34
|
-
raise ArgumentError, "Cannot use DEFAULT as a shard name" if
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
@current_shard = {:name =>
|
44
|
-
|
29
|
+
def shard(name, options = {})
|
30
|
+
raise ArgumentError, "Cannot use DEFAULT as a shard name" if name == 'DEFAULT'
|
31
|
+
raise ArgumentError, "Cannot nest shards" if @current_shard != default_shard
|
32
|
+
|
33
|
+
type = if options[:thread] || options[:type] == :thread; :thread
|
34
|
+
else :process
|
35
|
+
end
|
36
|
+
|
37
|
+
count = options[type] || options[:count] || 1
|
38
|
+
|
39
|
+
@current_shard = {:name => name, :type => type, :count => count, :components => [], :config_line => get_config_line(caller)}
|
40
|
+
shard_specs << @current_shard
|
45
41
|
yield self
|
46
|
-
@current_shard =
|
42
|
+
@current_shard = default_shard
|
47
43
|
end
|
48
44
|
|
49
45
|
# DSL method to specify a component. Expects a name,
|
50
46
|
# specification, and set of component specific options, that
|
51
47
|
# must be marshallable into the database (i.e. should all be strings)
|
52
|
-
def component(
|
48
|
+
def component(name, specification, options = {})
|
53
49
|
@current_shard[:components] << {
|
54
|
-
:name =>
|
55
|
-
:specification =>
|
50
|
+
:name => name,
|
51
|
+
:specification => specification.to_s, :options => options,
|
56
52
|
:config_line => get_config_line(caller)
|
57
53
|
}
|
58
54
|
end
|
@@ -67,9 +63,8 @@ class RFlow
|
|
67
63
|
# progamming syntax, i.e.
|
68
64
|
# connect 'componentA#arrayport[2]' => 'componentB#in[1]'
|
69
65
|
# Uses the model to assign random UUIDs
|
70
|
-
def connect(
|
71
|
-
|
72
|
-
connection_hash.each do |output_string, input_string|
|
66
|
+
def connect(hash)
|
67
|
+
hash.each do |output_string, input_string|
|
73
68
|
output_component_name, output_port_name, output_port_key = parse_connection_string(output_string)
|
74
69
|
input_component_name, input_port_name, input_port_key = parse_connection_string(input_string)
|
75
70
|
|
@@ -81,21 +76,18 @@ class RFlow
|
|
81
76
|
:input_component_name => input_component_name,
|
82
77
|
:input_port_name => input_port_name, :input_port_key => input_port_key,
|
83
78
|
:input_string => input_string,
|
84
|
-
:config_line =>
|
79
|
+
:config_line => get_config_line(caller)
|
85
80
|
}
|
86
81
|
end
|
87
82
|
end
|
88
83
|
|
89
|
-
#
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
# component_name, port_name, port_key
|
95
|
-
[matched[1], matched[2], (matched[3] || nil)]
|
84
|
+
# Method called within the config file itself
|
85
|
+
def self.configure
|
86
|
+
config_file = self.new
|
87
|
+
yield config_file
|
88
|
+
config_file.process
|
96
89
|
end
|
97
90
|
|
98
|
-
|
99
91
|
# Method to process the 'DSL' objects into the config database
|
100
92
|
# via ActiveRecord
|
101
93
|
def process
|
@@ -104,37 +96,54 @@ class RFlow
|
|
104
96
|
process_connection_specs
|
105
97
|
end
|
106
98
|
|
99
|
+
private
|
100
|
+
# Helper function to extract the line of the config that
|
101
|
+
# specified the operation. Useful in printing helpful error messages
|
102
|
+
def get_config_line(call_history)
|
103
|
+
call_history.first.split(':in').first
|
104
|
+
end
|
105
|
+
|
106
|
+
# Splits the connection string into component/port parts
|
107
|
+
COMPONENT_PORT_STRING_REGEX = /^(\w+)#(\w+)(?:\[([^\]]+)\])?$/
|
108
|
+
|
109
|
+
def parse_connection_string(string)
|
110
|
+
matched = COMPONENT_PORT_STRING_REGEX.match(string)
|
111
|
+
raise ArgumentError, "Invalid component/port string specification: #{string}" unless matched
|
112
|
+
component_name, port_name, port_key = matched.captures
|
113
|
+
[component_name, port_name, port_key]
|
114
|
+
end
|
107
115
|
|
108
116
|
# Iterates through each setting specified in the DSL and
|
109
117
|
# creates rows in the database corresponding to the setting
|
110
118
|
def process_setting_specs
|
111
|
-
setting_specs.each do |
|
112
|
-
RFlow.logger.debug "Found config file setting '#{
|
113
|
-
RFlow::Configuration::Setting.create! :name =>
|
119
|
+
setting_specs.each do |spec|
|
120
|
+
RFlow.logger.debug "Found config file setting '#{spec[:name]}' = (#{Dir.getwd}) '#{spec[:value]}'"
|
121
|
+
RFlow::Configuration::Setting.create! :name => spec[:name], :value => spec[:value]
|
114
122
|
end
|
115
123
|
end
|
116
124
|
|
117
|
-
|
118
125
|
# Iterates through each shard specified in the DSL and creates
|
119
126
|
# rows in the database corresponding to the shard and included
|
120
127
|
# components
|
121
128
|
def process_shard_specs
|
122
|
-
|
123
|
-
RFlow.logger.debug "Found #{
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
129
|
+
shard_specs.each do |spec|
|
130
|
+
RFlow.logger.debug "Found #{spec[:type]} shard '#{spec[:name]}', creating"
|
131
|
+
|
132
|
+
if spec[:components].empty?
|
133
|
+
RFlow.logger.warn "Skipping shard '#{spec[:name]}' because it has no components"
|
134
|
+
next
|
135
|
+
end
|
136
|
+
|
137
|
+
clazz = case spec[:type]
|
138
|
+
when :process; RFlow::Configuration::ProcessShard
|
139
|
+
when :thread; RFlow::Configuration::ThreadShard
|
140
|
+
else raise RFlow::Configuration::Shard::ShardInvalid, "Invalid shard: #{spec.inspect}"
|
141
|
+
end
|
142
|
+
|
143
|
+
shard = clazz.create! :name => spec[:name], :count => spec[:count]
|
144
|
+
|
145
|
+
spec[:components].each do |component_spec|
|
146
|
+
RFlow.logger.debug "Shard '#{spec[:name]}' found component '#{component_spec[:name]}', creating"
|
138
147
|
RFlow::Configuration::Component.create!(:shard => shard,
|
139
148
|
:name => component_spec[:name],
|
140
149
|
:specification => component_spec[:specification],
|
@@ -143,65 +152,42 @@ class RFlow
|
|
143
152
|
end
|
144
153
|
end
|
145
154
|
|
146
|
-
|
147
|
-
# Iterates through each component specified in the DSL and uses
|
148
|
-
# 'process_connection' to insert all the parts of the connection
|
149
|
-
# into the database
|
150
|
-
def process_connection_specs
|
151
|
-
connection_specs.each do |connection_spec|
|
152
|
-
process_connection_spec(connection_spec)
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
# For the given connection, break up each input/output
|
155
|
+
# For each given connection, break up each input/output
|
157
156
|
# component/port specification, ensure that the component
|
158
157
|
# already exists in the database (by name). Also, only supports
|
159
158
|
# ZeroMQ ipc sockets
|
160
|
-
def
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
error_message = "#{e.class}: #{e.message} at config '#{connection_spec[:config_line]}'"
|
192
|
-
RFlow.logger.debug "Exception #{e.class} - " + error_message
|
193
|
-
RFlow.logger.error error_message
|
194
|
-
raise RFlow::Configuration::Connection::ConnectionInvalid, error_message
|
195
|
-
end
|
196
|
-
|
197
|
-
|
198
|
-
# Method called within the config file itself
|
199
|
-
def self.configure
|
200
|
-
config_file = self.new
|
201
|
-
yield config_file
|
202
|
-
config_file.process
|
159
|
+
def process_connection_specs
|
160
|
+
connection_specs.each do |spec|
|
161
|
+
begin
|
162
|
+
RFlow.logger.debug "Found connection from '#{spec[:output_string]}' to '#{spec[:input_string]}', creating"
|
163
|
+
|
164
|
+
# an input port can be associated with multiple outputs, but
|
165
|
+
# an output port can only be associated with one input
|
166
|
+
output_component = RFlow::Configuration::Component.find_by_name spec[:output_component_name]
|
167
|
+
raise RFlow::Configuration::Connection::ConnectionInvalid,
|
168
|
+
"Component '#{spec[:output_component_name]}' not found at #{spec[:config_line]}" unless output_component
|
169
|
+
output_port = output_component.output_ports.find_or_initialize_by_name :name => spec[:output_port_name]
|
170
|
+
output_port.save!
|
171
|
+
|
172
|
+
input_component = RFlow::Configuration::Component.find_by_name spec[:input_component_name]
|
173
|
+
raise RFlow::Configuration::Connection::ConnectionInvalid,
|
174
|
+
"Component '#{spec[:input_component_name]}' not found at #{spec[:config_line]}" unless input_component
|
175
|
+
input_port = input_component.input_ports.find_or_initialize_by_name :name => spec[:input_port_name]
|
176
|
+
input_port.save!
|
177
|
+
|
178
|
+
RFlow::Configuration::ZMQConnection.create!(:name => spec[:name],
|
179
|
+
:output_port_key => spec[:output_port_key],
|
180
|
+
:input_port_key => spec[:input_port_key],
|
181
|
+
:output_port => output_port,
|
182
|
+
:input_port => input_port)
|
183
|
+
rescue Exception => e
|
184
|
+
# TODO: Figure out why an ArgumentError doesn't put the
|
185
|
+
# offending message into e.message, even though it is printed
|
186
|
+
# out if not caught
|
187
|
+
raise RFlow::Configuration::Connection::ConnectionInvalid, "#{e.class}: #{e.message} at config '#{spec[:config_line]}'"
|
188
|
+
end
|
189
|
+
end
|
203
190
|
end
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
end # class RFlow
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -3,9 +3,7 @@ require 'rflow/configuration/uuid_keyed'
|
|
3
3
|
|
4
4
|
class RFlow
|
5
5
|
class Configuration
|
6
|
-
class Setting <
|
7
|
-
class SettingInvalid < StandardError; end
|
8
|
-
|
6
|
+
class Setting < ConfigurationItem
|
9
7
|
include ActiveModel::Validations
|
10
8
|
|
11
9
|
self.primary_key = 'name'
|
@@ -13,33 +11,30 @@ class RFlow
|
|
13
11
|
attr_accessible :name, :value
|
14
12
|
|
15
13
|
DEFAULTS = {
|
16
|
-
'rflow.application_name'
|
17
|
-
|
14
|
+
'rflow.application_name' => 'rflow',
|
18
15
|
'rflow.application_directory_path' => '.',
|
19
|
-
'rflow.pid_directory_path' => 'run', #
|
20
|
-
'rflow.log_directory_path' => 'log', #
|
21
|
-
|
16
|
+
'rflow.pid_directory_path' => 'run', # relative to rflow.application_directory_path
|
17
|
+
'rflow.log_directory_path' => 'log', # relative to rflow.application_directory_path
|
22
18
|
'rflow.log_file_path' => lambda {File.join(Setting['rflow.log_directory_path'], Setting['rflow.application_name'] + '.log')},
|
23
19
|
'rflow.pid_file_path' => lambda {File.join(Setting['rflow.pid_directory_path'], Setting['rflow.application_name'] + '.pid')},
|
24
|
-
|
25
20
|
'rflow.log_level' => 'INFO',
|
26
21
|
}
|
27
22
|
|
28
23
|
DIRECTORY_PATHS = [
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
FILE_PATHS = [
|
34
|
-
'rflow.log_file_path',
|
35
|
-
'rflow.pid_file_path',
|
36
|
-
]
|
24
|
+
'rflow.application_directory_path',
|
25
|
+
'rflow.pid_directory_path',
|
26
|
+
'rflow.log_directory_path',
|
27
|
+
]
|
37
28
|
|
29
|
+
FILE_PATHS = [
|
30
|
+
'rflow.log_file_path',
|
31
|
+
'rflow.pid_file_path',
|
32
|
+
]
|
38
33
|
|
39
34
|
# TODO: fix these validations, as they run without the
|
40
|
-
#application directory path context for subdirectories
|
41
|
-
#validate :valid_directory_path
|
42
|
-
#validate :valid_writable_path
|
35
|
+
# application directory path context for subdirectories
|
36
|
+
#validate :valid_directory_path?, :if => :directory_path?
|
37
|
+
#validate :valid_writable_path?, :if => :directory_path?
|
43
38
|
|
44
39
|
# TODO: Think about making this a regex check to pull in other,
|
45
40
|
# externally-defined settings
|
@@ -47,22 +42,21 @@ class RFlow
|
|
47
42
|
DIRECTORY_PATHS.include? self.name
|
48
43
|
end
|
49
44
|
|
50
|
-
def valid_directory_path
|
45
|
+
def valid_directory_path?
|
51
46
|
unless File.directory? self.value
|
52
47
|
errors.add :value, "setting '#{self.name}' is not a directory ('#{File.expand_path self.value}')"
|
53
48
|
end
|
54
49
|
end
|
55
50
|
|
56
|
-
def valid_writable_path
|
51
|
+
def valid_writable_path?
|
57
52
|
unless File.writable? self.value
|
58
53
|
errors.add :value, "setting '#{self.name}' is not writable ('#{File.expand_path self.value}')"
|
59
54
|
end
|
60
55
|
end
|
61
56
|
|
62
|
-
def self.[](
|
63
|
-
Setting.find(
|
57
|
+
def self.[](name)
|
58
|
+
Setting.find(name).value rescue nil
|
64
59
|
end
|
65
|
-
|
66
60
|
end
|
67
61
|
end
|
68
62
|
end
|