rflow 1.0.0a1 → 1.0.0a2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|