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 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