rflow 1.2.0 → 1.3.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-version +1 -1
- data/Gemfile +4 -3
- data/lib/rflow.rb +25 -1
- data/lib/rflow/child_process.rb +10 -12
- data/lib/rflow/configuration.rb +1 -1
- data/lib/rflow/configuration/migrations/20010101000000_create_settings.rb +1 -1
- data/lib/rflow/configuration/migrations/20010101000001_create_shards.rb +1 -1
- data/lib/rflow/configuration/migrations/20010101000002_create_components.rb +1 -1
- data/lib/rflow/configuration/migrations/20010101000003_create_ports.rb +1 -1
- data/lib/rflow/configuration/migrations/20010101000004_create_connections.rb +1 -1
- data/lib/rflow/configuration/ruby_dsl.rb +2 -2
- data/lib/rflow/configuration/setting.rb +0 -2
- data/lib/rflow/daemon_process.rb +13 -14
- data/lib/rflow/logger.rb +25 -0
- data/lib/rflow/version.rb +1 -1
- data/rflow.gemspec +5 -5
- data/spec/rflow/configuration/ruby_dsl_spec.rb +4 -4
- data/spec/spec_helper.rb +3 -0
- metadata +15 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17406ab649fb487a35c56adf29bb50e51e192811
|
4
|
+
data.tar.gz: 8ccdc83a2b260d6431f0db4153dca3f1d93061be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d23c815a11716c0e12b7147f8a52f4e4019e5390327fb7810ad55479efdc0fd8a7c7de3b381cd60a5979ebd895c6c1184a8e3b56c95f9ebc06de03a8f9746808
|
7
|
+
data.tar.gz: 9d5ea8d7074d43ed5d0539d8e1e009984d79fcfa9c076ff008252ccecdd8922e7500217d0fc7e530e35c203780f3c33c62e4a6c4983a9ad732e64f7670f4e38c
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.3.
|
1
|
+
ruby-2.3.1
|
data/Gemfile
CHANGED
data/lib/rflow.rb
CHANGED
@@ -61,13 +61,37 @@ class RFlow
|
|
61
61
|
master.run! # blocks until EventMachine stops
|
62
62
|
end
|
63
63
|
|
64
|
+
# Nice pretty wrapper method to help reduce direct dependencies on EM
|
65
|
+
def self.next_tick(pr = nil, &block)
|
66
|
+
EM.next_tick(pr, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.default_error_callback(error)
|
70
|
+
RFlow.logger.error "Unhandled error on worker thread: #{error.class}: #{error.message}, because: #{error.backtrace}"
|
71
|
+
end
|
72
|
+
|
73
|
+
# Wrapped version of EM.defer that also fixes logging, releases AR
|
74
|
+
# connections, and catches exceptions that would otherwise propagate to the
|
75
|
+
# main thread magically
|
76
|
+
def self.defer(op = nil, callback = nil, errback = nil, &blk)
|
77
|
+
context = RFlow.logger.clone_logging_context
|
78
|
+
EM.defer(nil, callback, errback || method(:default_error_callback)) do
|
79
|
+
begin
|
80
|
+
RFlow.logger.apply_logging_context context
|
81
|
+
(op || blk).call
|
82
|
+
ensure
|
83
|
+
ActiveRecord::Base.connection_pool.release_connection
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
64
88
|
# This ought to be in EM, but we'll put it here instead of monkey-patching
|
65
89
|
def self.next_tick_and_wait
|
66
90
|
mutex = Mutex.new
|
67
91
|
condition = ConditionVariable.new
|
68
92
|
|
69
93
|
mutex.synchronize do # while locked...
|
70
|
-
|
94
|
+
RFlow.next_tick do # schedule a job that will...
|
71
95
|
mutex.synchronize do # grab the lock
|
72
96
|
begin
|
73
97
|
yield # do its thing...
|
data/lib/rflow/child_process.rb
CHANGED
@@ -4,6 +4,8 @@ class RFlow
|
|
4
4
|
class ChildProcess
|
5
5
|
attr_reader :pid, :name
|
6
6
|
|
7
|
+
SIGINFO = 29
|
8
|
+
|
7
9
|
def initialize(name, role = name)
|
8
10
|
@name = name
|
9
11
|
@role = role
|
@@ -64,15 +66,7 @@ class RFlow
|
|
64
66
|
|
65
67
|
def register_logging_context
|
66
68
|
# arrange for child's name to appear in log messages
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
def clone_logging_context
|
71
|
-
Log4r::NDC.clone_stack
|
72
|
-
end
|
73
|
-
|
74
|
-
def apply_logging_context(context)
|
75
|
-
Log4r::NDC.inherit(context)
|
69
|
+
RFlow.logger.add_logging_context sprintf("%-#{RFlow.logger.context_width}s", @name)
|
76
70
|
end
|
77
71
|
|
78
72
|
def update_process_name
|
@@ -103,20 +97,24 @@ class RFlow
|
|
103
97
|
trap_signal 'SIGUSR2' do
|
104
98
|
RFlow.logger.toggle_log_level
|
105
99
|
end
|
100
|
+
|
101
|
+
trap_signal SIGINFO do
|
102
|
+
RFlow.logger.dump_threads
|
103
|
+
end
|
106
104
|
end
|
107
105
|
|
108
106
|
def unhandle_signals
|
109
|
-
['SIGTERM', 'SIGINT', 'SIGQUIT', 'SIGCHLD', 'SIGUSR1', 'SIGUSR2'].each do |signal|
|
107
|
+
['SIGTERM', 'SIGINT', 'SIGQUIT', 'SIGCHLD', 'SIGUSR1', 'SIGUSR2', SIGINFO].each do |signal|
|
110
108
|
Signal.trap signal, 'DEFAULT'
|
111
109
|
end
|
112
110
|
end
|
113
111
|
|
114
112
|
def trap_signal(signal)
|
115
113
|
# Log4r and traps don't mix, so we need to put it in another thread
|
116
|
-
context = clone_logging_context
|
114
|
+
context = RFlow.logger.clone_logging_context
|
117
115
|
Signal.trap signal do
|
118
116
|
Thread.new do
|
119
|
-
apply_logging_context context
|
117
|
+
RFlow.logger.apply_logging_context context
|
120
118
|
yield
|
121
119
|
end.join
|
122
120
|
end
|
data/lib/rflow/configuration.rb
CHANGED
@@ -159,7 +159,7 @@ class RFlow
|
|
159
159
|
def merge_defaults!
|
160
160
|
Setting::DEFAULTS.each do |name, default_value_or_proc|
|
161
161
|
value = default_value_or_proc.is_a?(Proc) ? default_value_or_proc.call() : default_value_or_proc
|
162
|
-
setting = Setting.
|
162
|
+
setting = Setting.find_or_create_by(:name => name, :value => value)
|
163
163
|
unless setting.valid?
|
164
164
|
raise RuntimeError, setting.errors.map {|_, msg| msg }.join(', ')
|
165
165
|
end
|
@@ -178,13 +178,13 @@ class RFlow
|
|
178
178
|
output_component = RFlow::Configuration::Component.find_by_name spec[:output_component_name]
|
179
179
|
raise RFlow::Configuration::Connection::ConnectionInvalid,
|
180
180
|
"Component '#{spec[:output_component_name]}' not found at #{spec[:config_line]}" unless output_component
|
181
|
-
output_port = output_component.output_ports.
|
181
|
+
output_port = output_component.output_ports.find_or_initialize_by :name => spec[:output_port_name]
|
182
182
|
output_port.save!
|
183
183
|
|
184
184
|
input_component = RFlow::Configuration::Component.find_by_name spec[:input_component_name]
|
185
185
|
raise RFlow::Configuration::Connection::ConnectionInvalid,
|
186
186
|
"Component '#{spec[:input_component_name]}' not found at #{spec[:config_line]}" unless input_component
|
187
|
-
input_port = input_component.input_ports.
|
187
|
+
input_port = input_component.input_ports.find_or_initialize_by :name => spec[:input_port_name]
|
188
188
|
input_port.save!
|
189
189
|
|
190
190
|
output_shards = output_component.shard.count
|
data/lib/rflow/daemon_process.rb
CHANGED
@@ -2,6 +2,8 @@ require 'rflow/pid_file'
|
|
2
2
|
|
3
3
|
class RFlow
|
4
4
|
class DaemonProcess
|
5
|
+
SIGINFO = 29
|
6
|
+
|
5
7
|
def initialize(name, role = name, options = {})
|
6
8
|
@name = name
|
7
9
|
@role = role
|
@@ -92,16 +94,8 @@ class RFlow
|
|
92
94
|
|
93
95
|
def register_logging_context
|
94
96
|
# arrange for process's name to appear in log messages
|
95
|
-
|
96
|
-
|
97
|
-
end
|
98
|
-
|
99
|
-
def clone_logging_context
|
100
|
-
Log4r::NDC.clone_stack
|
101
|
-
end
|
102
|
-
|
103
|
-
def apply_logging_context(context)
|
104
|
-
Log4r::NDC.inherit(context)
|
97
|
+
RFlow.logger.clear_logging_context
|
98
|
+
RFlow.logger.add_logging_context @name
|
105
99
|
end
|
106
100
|
|
107
101
|
def update_process_name
|
@@ -114,7 +108,7 @@ class RFlow
|
|
114
108
|
trap_signal(signal) do |return_code|
|
115
109
|
exit_status = if signal == 'SIGCHLD'
|
116
110
|
pid, status = Process.wait2
|
117
|
-
status.exitstatus
|
111
|
+
status.exitstatus || 0
|
118
112
|
else
|
119
113
|
0
|
120
114
|
end
|
@@ -132,10 +126,15 @@ class RFlow
|
|
132
126
|
RFlow.logger.toggle_log_level
|
133
127
|
signal_subprocesses 'SIGUSR2'
|
134
128
|
end
|
129
|
+
|
130
|
+
trap_signal SIGINFO do
|
131
|
+
RFlow.logger.dump_threads
|
132
|
+
# don't tell child processes to dump, too spammy
|
133
|
+
end
|
135
134
|
end
|
136
135
|
|
137
136
|
def unhandle_signals
|
138
|
-
['SIGTERM', 'SIGINT', 'SIGQUIT', 'SIGCHLD', 'SIGUSR1', 'SIGUSR2'].each do |signal|
|
137
|
+
['SIGTERM', 'SIGINT', 'SIGQUIT', 'SIGCHLD', 'SIGUSR1', 'SIGUSR2', SIGINFO].each do |signal|
|
139
138
|
Signal.trap signal, 'DEFAULT'
|
140
139
|
end
|
141
140
|
end
|
@@ -143,10 +142,10 @@ class RFlow
|
|
143
142
|
def trap_signal(signal)
|
144
143
|
# Log4r and traps don't mix, so we need to put it in another thread
|
145
144
|
return_code = $?
|
146
|
-
context = clone_logging_context
|
145
|
+
context = RFlow.logger.clone_logging_context
|
147
146
|
Signal.trap signal do
|
148
147
|
Thread.new do
|
149
|
-
apply_logging_context context
|
148
|
+
RFlow.logger.apply_logging_context context
|
150
149
|
yield return_code
|
151
150
|
end.join
|
152
151
|
end
|
data/lib/rflow/logger.rb
CHANGED
@@ -66,6 +66,31 @@ class RFlow
|
|
66
66
|
internal_logger.level = LNAMES.index new_log_level
|
67
67
|
end
|
68
68
|
|
69
|
+
def dump_threads
|
70
|
+
Thread.list.each do |t|
|
71
|
+
info "Thread #{t.inspect}:"
|
72
|
+
t.backtrace.each {|b| info " #{b}" }
|
73
|
+
info '---'
|
74
|
+
end
|
75
|
+
info 'Thread dump complete.'
|
76
|
+
end
|
77
|
+
|
78
|
+
def clone_logging_context
|
79
|
+
Log4r::NDC.clone_stack
|
80
|
+
end
|
81
|
+
|
82
|
+
def apply_logging_context(context)
|
83
|
+
Log4r::NDC.inherit(context)
|
84
|
+
end
|
85
|
+
|
86
|
+
def clear_logging_context
|
87
|
+
Log4r::NDC.clear
|
88
|
+
end
|
89
|
+
|
90
|
+
def add_logging_context(context)
|
91
|
+
Log4r::NDC.push context
|
92
|
+
end
|
93
|
+
|
69
94
|
private
|
70
95
|
def establish_internal_logger
|
71
96
|
@internal_logger = Log4r::Logger.new(log_name).tap do |logger|
|
data/lib/rflow/version.rb
CHANGED
data/rflow.gemspec
CHANGED
@@ -25,14 +25,14 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.add_dependency 'sys-filesystem', '~> 1.1'
|
26
26
|
|
27
27
|
s.add_dependency 'sqlite3', '~> 1.3'
|
28
|
-
s.add_dependency 'activerecord', '~>
|
28
|
+
s.add_dependency 'activerecord', '~> 4.0'
|
29
29
|
|
30
|
-
s.add_dependency 'avro', '~> 1.
|
31
|
-
s.add_dependency 'em-zeromq', '~> 0.5
|
30
|
+
s.add_dependency 'avro', '~> 1.8'
|
31
|
+
s.add_dependency 'em-zeromq', '~> 0.5'
|
32
32
|
|
33
|
-
s.add_development_dependency 'bundler', '~> 1'
|
33
|
+
s.add_development_dependency 'bundler', '~> 1.0'
|
34
34
|
s.add_development_dependency 'rspec', '~> 3.0'
|
35
35
|
s.add_development_dependency 'rspec-collection_matchers', '~> 1.0'
|
36
36
|
s.add_development_dependency 'rake', '>= 10.3'
|
37
|
-
s.add_development_dependency 'yard', '~> 0.
|
37
|
+
s.add_development_dependency 'yard', '~> 0.9'
|
38
38
|
end
|
@@ -156,10 +156,10 @@ class RFlow
|
|
156
156
|
Shard.all.tap do |shards|
|
157
157
|
expect(shards.map(&:name)).to eq(['DEFAULT', 's1', 's2', 's3', 's4', 's5'])
|
158
158
|
expect(shards.map(&:type)).to eq((['RFlow::Configuration::ProcessShard'] * 4) + (['RFlow::Configuration::ThreadShard'] * 2))
|
159
|
-
expect(shards.first.components.
|
160
|
-
expect(shards.second.components.
|
161
|
-
expect(shards.third.components.
|
162
|
-
expect(shards.fourth.components.
|
159
|
+
expect(shards.first.components.to_a.map(&:name)).to eq(['first', 'eighth'])
|
160
|
+
expect(shards.second.components.to_a.map(&:name)).to eq(['second'])
|
161
|
+
expect(shards.third.components.to_a.map(&:name)).to eq(['third', 'fourth'])
|
162
|
+
expect(shards.fourth.components.to_a.map(&:name)).to eq(['fifth'])
|
163
163
|
end
|
164
164
|
|
165
165
|
expect(Port.all.map(&:name)).to eq(['out', 'in', 'out', 'in', 'in2', 'out', 'in', 'in', 'in'])
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0a1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Stoneham
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-10-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: uuidtools
|
@@ -73,56 +73,56 @@ dependencies:
|
|
73
73
|
requirements:
|
74
74
|
- - "~>"
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: '
|
76
|
+
version: '4.0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
81
|
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: '
|
83
|
+
version: '4.0'
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
85
|
name: avro
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
88
|
- - "~>"
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: '1.
|
90
|
+
version: '1.8'
|
91
91
|
type: :runtime
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
95
|
- - "~>"
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version: '1.
|
97
|
+
version: '1.8'
|
98
98
|
- !ruby/object:Gem::Dependency
|
99
99
|
name: em-zeromq
|
100
100
|
requirement: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
102
|
- - "~>"
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version: 0.5
|
104
|
+
version: '0.5'
|
105
105
|
type: :runtime
|
106
106
|
prerelease: false
|
107
107
|
version_requirements: !ruby/object:Gem::Requirement
|
108
108
|
requirements:
|
109
109
|
- - "~>"
|
110
110
|
- !ruby/object:Gem::Version
|
111
|
-
version: 0.5
|
111
|
+
version: '0.5'
|
112
112
|
- !ruby/object:Gem::Dependency
|
113
113
|
name: bundler
|
114
114
|
requirement: !ruby/object:Gem::Requirement
|
115
115
|
requirements:
|
116
116
|
- - "~>"
|
117
117
|
- !ruby/object:Gem::Version
|
118
|
-
version: '1'
|
118
|
+
version: '1.0'
|
119
119
|
type: :development
|
120
120
|
prerelease: false
|
121
121
|
version_requirements: !ruby/object:Gem::Requirement
|
122
122
|
requirements:
|
123
123
|
- - "~>"
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version: '1'
|
125
|
+
version: '1.0'
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: rspec
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -171,14 +171,14 @@ dependencies:
|
|
171
171
|
requirements:
|
172
172
|
- - "~>"
|
173
173
|
- !ruby/object:Gem::Version
|
174
|
-
version: '0.
|
174
|
+
version: '0.9'
|
175
175
|
type: :development
|
176
176
|
prerelease: false
|
177
177
|
version_requirements: !ruby/object:Gem::Requirement
|
178
178
|
requirements:
|
179
179
|
- - "~>"
|
180
180
|
- !ruby/object:Gem::Version
|
181
|
-
version: '0.
|
181
|
+
version: '0.9'
|
182
182
|
description: A Ruby flow-based programming framework that utilizes ZeroMQ for component
|
183
183
|
connections and Avro for serialization
|
184
184
|
email:
|
@@ -276,12 +276,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
276
276
|
version: '1.9'
|
277
277
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
278
278
|
requirements:
|
279
|
-
- - "
|
279
|
+
- - ">"
|
280
280
|
- !ruby/object:Gem::Version
|
281
|
-
version:
|
281
|
+
version: 1.3.1
|
282
282
|
requirements: []
|
283
283
|
rubyforge_project:
|
284
|
-
rubygems_version: 2.
|
284
|
+
rubygems_version: 2.5.1
|
285
285
|
signing_key:
|
286
286
|
specification_version: 4
|
287
287
|
summary: A Ruby flow-based programming framework
|