rflow 1.2.0 → 1.3.0a1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b847e06bbad6d47e7cd74314add6f499c99c8bc9
4
- data.tar.gz: f707f01ec81e823d8c08711bf747f1a57b6a15a6
3
+ metadata.gz: 17406ab649fb487a35c56adf29bb50e51e192811
4
+ data.tar.gz: 8ccdc83a2b260d6431f0db4153dca3f1d93061be
5
5
  SHA512:
6
- metadata.gz: a5791ba65d956750314d374c00fb21bafcaa152a356331d41134929befaf9488f7519da287b796833430300f5f5aafb892465648ee54a6b8acdc3c1503181427
7
- data.tar.gz: bf9ebdb5eac95bd3307f86b54d23b872cd6365fd32db98daa962cd5c109f404c8bf3a9d3ebcc36d5b0c12fb7223b1c8d55b61e62678484fd12f5ca6292ac58e4
6
+ metadata.gz: d23c815a11716c0e12b7147f8a52f4e4019e5390327fb7810ad55479efdc0fd8a7c7de3b381cd60a5979ebd895c6c1184a8e3b56c95f9ebc06de03a8f9746808
7
+ data.tar.gz: 9d5ea8d7074d43ed5d0539d8e1e009984d79fcfa9c076ff008252ccecdd8922e7500217d0fc7e530e35c203780f3c33c62e4a6c4983a9ad732e64f7670f4e38c
@@ -1 +1 @@
1
- ruby-2.3.0
1
+ ruby-2.3.1
data/Gemfile CHANGED
@@ -3,7 +3,8 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :development do
6
- gem 'guard'
7
- gem 'guard-rspec'
8
- gem 'listen', '<3.1'
6
+ if Gem::Version.create(RUBY_VERSION) >= Gem::Version.create("2.2.5")
7
+ gem 'guard'
8
+ gem 'guard-rspec'
9
+ end
9
10
  end
@@ -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
- EM.next_tick do # schedule a job that will...
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...
@@ -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
- Log4r::NDC.push sprintf("%-#{RFlow.logger.context_width}s", @name)
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
@@ -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.find_or_create_by_name(:name => name, :value => value)
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
@@ -4,7 +4,7 @@ class CreateSettings < ActiveRecord::Migration
4
4
  t.string :name, :primary => true
5
5
  t.text :value
6
6
 
7
- t.timestamps
7
+ t.timestamps null: false
8
8
  end
9
9
  end
10
10
 
@@ -8,7 +8,7 @@ class CreateShards < ActiveRecord::Migration
8
8
  # STI
9
9
  t.string :type
10
10
 
11
- t.timestamps
11
+ t.timestamps null: false
12
12
  end
13
13
 
14
14
  add_index :shards, :uuid, :unique => true
@@ -10,7 +10,7 @@ class CreateComponents < ActiveRecord::Migration
10
10
  # UUID version of belongs_to :shard
11
11
  t.string :shard_uuid
12
12
 
13
- t.timestamps
13
+ t.timestamps null: false
14
14
  end
15
15
 
16
16
  add_index :components, :uuid, :unique => true
@@ -10,7 +10,7 @@ class CreatePorts < ActiveRecord::Migration
10
10
  # UUID version of belongs_to :component
11
11
  t.string :component_uuid
12
12
 
13
- t.timestamps
13
+ t.timestamps null: false
14
14
  end
15
15
 
16
16
  add_index :ports, :uuid, :unique => true
@@ -18,7 +18,7 @@ class CreateConnections < ActiveRecord::Migration
18
18
 
19
19
  t.text :options
20
20
 
21
- t.timestamps
21
+ t.timestamps null: false
22
22
  end
23
23
 
24
24
  add_index :connections, :uuid, :unique => true
@@ -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.find_or_initialize_by_name :name => spec[:output_port_name]
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.find_or_initialize_by_name :name => spec[:input_port_name]
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
@@ -8,8 +8,6 @@ class RFlow
8
8
 
9
9
  self.primary_key = 'name'
10
10
 
11
- attr_accessible :name, :value
12
-
13
11
  DEFAULTS = {
14
12
  'rflow.application_name' => 'rflow',
15
13
  'rflow.application_directory_path' => '.',
@@ -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
- Log4r::NDC.clear
96
- Log4r::NDC.push @name
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
@@ -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|
@@ -1,3 +1,3 @@
1
1
  class RFlow
2
- VERSION = '1.2.0'
2
+ VERSION = '1.3.0a1'
3
3
  end
@@ -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', '~> 3.2'
28
+ s.add_dependency 'activerecord', '~> 4.0'
29
29
 
30
- s.add_dependency 'avro', '~> 1.7'
31
- s.add_dependency 'em-zeromq', '~> 0.5.0'
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.8'
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.all.map(&:name)).to eq(['first', 'eighth'])
160
- expect(shards.second.components.all.map(&:name)).to eq(['second'])
161
- expect(shards.third.components.all.map(&:name)).to eq(['third', 'fourth'])
162
- expect(shards.fourth.components.all.map(&:name)).to eq(['fifth'])
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'])
@@ -7,6 +7,9 @@ require 'tmpdir'
7
7
 
8
8
  I18n.enforce_available_locales = true
9
9
 
10
+ ActiveRecord::Base.logger = Logger.new(STDOUT)
11
+ ActiveRecord::Base.logger.level = 4
12
+
10
13
  RSpec.configure do |config|
11
14
  config.before(:each) do
12
15
  @temp_directory_path = Dir.mktmpdir('rflow')
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.2.0
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-08-31 00:00:00.000000000 Z
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: '3.2'
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: '3.2'
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.7'
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.7'
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.0
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.0
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.8'
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.8'
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: '0'
281
+ version: 1.3.1
282
282
  requirements: []
283
283
  rubyforge_project:
284
- rubygems_version: 2.2.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