nonnative 1.2.0 → 1.3.0

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
  SHA256:
3
- metadata.gz: 86688846c3dbab6791765d4e45791ee6512a2610acdbd244f98cc57e1e6d6b93
4
- data.tar.gz: a182c0f56776e8fd4b380ba68b70ae26faf459551d86a42e54bd5fb297f0cb8f
3
+ metadata.gz: 6f258779774baf11f2ae65c66b397f4f4fa0e1afd10972db59149080a3534616
4
+ data.tar.gz: ecd62fbcf9051813acda6b21dff301b4985d3ecb6ad3ef89cb3b810e917b297d
5
5
  SHA512:
6
- metadata.gz: 6aa499496170eaa5dd7e924a7390cd886b579092b0fe4177cfb401e8f2eb97dc0cd6f69f8a1741de16ef1718836c25fdb33d269cf9b6fa0792a0b189ceea1ab2
7
- data.tar.gz: b017ae7d02ed4289c7bbf9c4c408431aa51d80dfea80568cafe3eb68b982a980b39477876543dd4cac08c95770e23187c40eb837c2417ef188d77d551832391c
6
+ metadata.gz: 328717fae77a845b8009bdf265b072504b4ad0ec644fb29f5f6884460d8aff892f1f46b73b869010ceae536d3a590a778977a3e65cd86c5f2cc4a0f15fb5e670
7
+ data.tar.gz: 0dd2f19cf8773c08fe93cf911298e8441ae1465e4289eb2449a44887f8f1a594e50b31ffadb343fd0ebf6e67b0d9f16e29f0faa75406fa7c09e8c82d37fcc643
@@ -20,6 +20,5 @@ jobs:
20
20
  - vendor/bundle
21
21
  - run: make features
22
22
  - run: make analysis
23
- - run: make audit
24
23
  - store_artifacts:
25
24
  path: features/logs
@@ -7,3 +7,18 @@ Layout/LineLength:
7
7
 
8
8
  Style/Documentation:
9
9
  Enabled: false
10
+
11
+ Lint/RaiseException:
12
+ Enabled: true
13
+
14
+ Style/HashEachMethods:
15
+ Enabled: true
16
+
17
+ Style/HashTransformKeys:
18
+ Enabled: true
19
+
20
+ Style/HashTransformValues:
21
+ Enabled: true
22
+
23
+ Lint/StructNewOverride:
24
+ Enabled: true
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nonnative (1.2.0)
4
+ nonnative (1.3.0)
5
5
  cucumber
6
6
  rspec-expectations
7
7
  semantic_logger
@@ -10,14 +10,13 @@ GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
12
  ast (2.4.0)
13
- backports (3.16.1)
14
- benchmark-malloc (0.1.0)
15
- benchmark-perf (0.5.0)
16
- benchmark-trend (0.3.0)
13
+ backport (1.1.2)
14
+ backports (3.17.0)
15
+ benchmark (0.1.0)
16
+ benchmark-malloc (0.2.0)
17
+ benchmark-perf (0.6.0)
18
+ benchmark-trend (0.4.0)
17
19
  builder (3.2.4)
18
- bundler-audit (0.6.1)
19
- bundler (>= 1.2.0, < 3)
20
- thor (~> 0.18)
21
20
  concurrent-ruby (1.1.6)
22
21
  cucumber (3.1.2)
23
22
  builder (>= 2.1.2)
@@ -37,63 +36,86 @@ GEM
37
36
  cucumber-wire (0.0.1)
38
37
  diff-lcs (1.3)
39
38
  docile (1.3.2)
39
+ e2mmap (0.1.0)
40
40
  gherkin (5.1.0)
41
41
  jaro_winkler (1.5.4)
42
+ maruku (0.7.3)
43
+ mini_portile2 (2.4.0)
42
44
  multi_json (1.14.1)
43
45
  multi_test (0.1.2)
46
+ nokogiri (1.10.9)
47
+ mini_portile2 (~> 2.4.0)
44
48
  parallel (1.19.1)
45
- parser (2.7.0.2)
49
+ parser (2.7.0.5)
46
50
  ast (~> 2.4.0)
47
51
  rainbow (3.0.0)
48
52
  rake (13.0.1)
53
+ reverse_markdown (1.4.0)
54
+ nokogiri
49
55
  rexml (3.2.4)
50
56
  rspec (3.9.0)
51
57
  rspec-core (~> 3.9.0)
52
58
  rspec-expectations (~> 3.9.0)
53
59
  rspec-mocks (~> 3.9.0)
54
- rspec-benchmark (0.5.1)
55
- benchmark-malloc (~> 0.1.0)
56
- benchmark-perf (~> 0.5.0)
57
- benchmark-trend (~> 0.3.0)
58
- rspec (>= 3.0.0, < 4.0.0)
60
+ rspec-benchmark (0.6.0)
61
+ benchmark-malloc (~> 0.2)
62
+ benchmark-perf (~> 0.6)
63
+ benchmark-trend (~> 0.4)
64
+ rspec (>= 3.0)
59
65
  rspec-core (3.9.1)
60
66
  rspec-support (~> 3.9.1)
61
- rspec-expectations (3.9.0)
67
+ rspec-expectations (3.9.1)
62
68
  diff-lcs (>= 1.2.0, < 2.0)
63
69
  rspec-support (~> 3.9.0)
64
70
  rspec-mocks (3.9.1)
65
71
  diff-lcs (>= 1.2.0, < 2.0)
66
72
  rspec-support (~> 3.9.0)
67
73
  rspec-support (3.9.2)
68
- rubocop (0.80.0)
74
+ rubocop (0.81.0)
69
75
  jaro_winkler (~> 1.5.1)
70
76
  parallel (~> 1.10)
71
77
  parser (>= 2.7.0.1)
72
78
  rainbow (>= 2.2.2, < 4.0)
73
79
  rexml
74
80
  ruby-progressbar (~> 1.7)
75
- unicode-display_width (>= 1.4.0, < 1.7)
81
+ unicode-display_width (>= 1.4.0, < 2.0)
76
82
  ruby-progressbar (1.10.1)
77
- semantic_logger (4.6.0)
83
+ semantic_logger (4.6.1)
78
84
  concurrent-ruby (~> 1.0)
79
- simplecov (0.18.2)
85
+ simplecov (0.18.5)
80
86
  docile (~> 1.1)
81
87
  simplecov-html (~> 0.11)
82
- simplecov-html (0.12.0)
83
- thor (0.20.3)
84
- unicode-display_width (1.6.1)
88
+ simplecov-html (0.12.2)
89
+ solargraph (0.38.6)
90
+ backport (~> 1.1)
91
+ benchmark
92
+ bundler (>= 1.17.2)
93
+ e2mmap
94
+ jaro_winkler (~> 1.5)
95
+ maruku (~> 0.7, >= 0.7.3)
96
+ nokogiri (~> 1.9, >= 1.9.1)
97
+ parser (~> 2.3)
98
+ reverse_markdown (~> 1.0, >= 1.0.5)
99
+ rubocop (~> 0.52)
100
+ thor (~> 1.0)
101
+ tilt (~> 2.0)
102
+ yard (~> 0.9)
103
+ thor (1.0.1)
104
+ tilt (2.0.10)
105
+ unicode-display_width (1.7.0)
106
+ yard (0.9.24)
85
107
 
86
108
  PLATFORMS
87
109
  ruby
88
110
 
89
111
  DEPENDENCIES
90
112
  bundler
91
- bundler-audit
92
113
  nonnative!
93
114
  rake
94
115
  rspec-benchmark
95
116
  rubocop
96
117
  simplecov
118
+ solargraph
97
119
 
98
120
  BUNDLED WITH
99
121
  2.1.4
data/Makefile CHANGED
@@ -12,10 +12,6 @@ features:
12
12
  analysis:
13
13
  bundle exec rubocop
14
14
 
15
- audit:
16
- bundle exec bundle-audit update
17
- bundle exec bundle-audit
18
-
19
15
  cleanup-analysis:
20
16
  bundle exec rubocop -a
21
17
 
data/README.md CHANGED
@@ -10,7 +10,7 @@ Well so do I. The issue is that most languages the cucumber implementation is no
10
10
 
11
11
  So why not test the way you want and build the microservice how you want. These kind of tests will make sure your application is tested properly by going end-to-end.
12
12
 
13
- The way it works is it spawns the processes you configure and waits for it to start. Then you communicate with your microservice however you like (TCP, HTTP, gRPC, etc)
13
+ The way it works is it spawns processes or servers you configure and waits for it to start. Then you communicate with your microservice however you like (TCP, HTTP, gRPC, etc)
14
14
 
15
15
  ## Installation
16
16
 
@@ -40,6 +40,12 @@ Configure nonnative with the following:
40
40
 
41
41
  ### Ruby
42
42
 
43
+ We can start a process, server or both.
44
+
45
+ #### Processes
46
+
47
+ Setup it up programmatically:
48
+
43
49
  ```ruby
44
50
  require 'nonnative'
45
51
 
@@ -62,6 +68,8 @@ Nonnative.configure do |config|
62
68
  end
63
69
  ```
64
70
 
71
+ Setup it up through configuration:
72
+
65
73
  ### YAML
66
74
 
67
75
  ```yaml
@@ -87,3 +95,76 @@ require 'nonnative'
87
95
 
88
96
  Nonnative.load_configuration('configuration.yml')
89
97
  ```
98
+
99
+ #### Servers
100
+
101
+ Define your server:
102
+
103
+ ```ruby
104
+ module Nonnative
105
+ class EchoServer < Nonnative::Server
106
+ def perform_start
107
+ @socket_server = TCPServer.new('127.0.0.1', port)
108
+
109
+ loop do
110
+ client_socket = @socket_server.accept
111
+ client_socket.puts 'Hello World!'
112
+ client_socket.close
113
+ end
114
+ rescue StandardError
115
+ end
116
+
117
+ def perform_stop
118
+ @socket_server.close
119
+ end
120
+ end
121
+ end
122
+ ```
123
+
124
+ Setup it up programmatically:
125
+
126
+ ```ruby
127
+ require 'nonnative'
128
+
129
+ Nonnative.configure do |config|
130
+ config.strategy = :manual
131
+
132
+ config.server do |d|
133
+ d.klass = Nonnative::EchoServer
134
+ d.timeout = 1
135
+ d.port = 12_323
136
+ end
137
+
138
+ config.server do |d|
139
+ d.klass = Nonnative::EchoServer
140
+ d.timeout = 1
141
+ d.port = 12_324
142
+ end
143
+ end
144
+ ```
145
+
146
+ Setup it up through configuration:
147
+
148
+ ### YAML
149
+
150
+ ```yaml
151
+ version: 1.0
152
+ strategy: manual
153
+ servers:
154
+ -
155
+ klass: Nonnative::EchoServer
156
+ timeout: 1
157
+ port: 12323
158
+ -
159
+ klass: Nonnative::EchoServer
160
+ timeout: 1
161
+ port: 12324
162
+ ```
163
+
164
+ Then load the file with:
165
+
166
+ ```ruby
167
+ require 'nonnative'
168
+
169
+ Nonnative.load_configuration('configuration.yml')
170
+ ```
@@ -7,11 +7,14 @@ require 'yaml'
7
7
 
8
8
  require 'nonnative/version'
9
9
  require 'nonnative/error'
10
- require 'nonnative/configuration/object'
11
- require 'nonnative/configuration/process'
12
- require 'nonnative/process/system'
13
- require 'nonnative/process/pool'
14
- require 'nonnative/process/port'
10
+ require 'nonnative/timeout'
11
+ require 'nonnative/port'
12
+ require 'nonnative/configuration'
13
+ require 'nonnative/configuration_process'
14
+ require 'nonnative/configuration_server'
15
+ require 'nonnative/system'
16
+ require 'nonnative/pool'
17
+ require 'nonnative/server'
15
18
  require 'nonnative/logger'
16
19
 
17
20
  module Nonnative
@@ -21,11 +24,11 @@ module Nonnative
21
24
  end
22
25
 
23
26
  def load_configuration(path)
24
- @configuration ||= Nonnative::Configuration::Object.load_file(path) # rubocop:disable Naming/MemoizedInstanceVariableName
27
+ @configuration ||= Nonnative::Configuration.load_file(path) # rubocop:disable Naming/MemoizedInstanceVariableName
25
28
  end
26
29
 
27
30
  def configuration
28
- @configuration ||= Nonnative::Configuration::Object.new
31
+ @configuration ||= Nonnative::Configuration.new
29
32
  end
30
33
 
31
34
  def configure
@@ -35,16 +38,18 @@ module Nonnative
35
38
  end
36
39
 
37
40
  def start
38
- @process_pool ||= Nonnative::Process::Pool.new(configuration)
41
+ @pool ||= Nonnative::Pool.new(configuration)
39
42
 
40
- @process_pool.start do |pid, result|
41
- logger.error('Process has started though did respond in time', pid: pid) unless result
43
+ @pool.start do |id, result|
44
+ logger.error('Process has started though did respond in time', id: id) unless result
42
45
  end
43
46
  end
44
47
 
45
48
  def stop
46
- @process_pool.stop do |pid, result|
47
- logger.error('Process has stopped though did respond in time', pid: pid) unless result
49
+ return if @pool.nil?
50
+
51
+ @pool.stop do |id, result|
52
+ logger.error('Process has stopped though did respond in time', id: id) unless result
48
53
  end
49
54
  end
50
55
 
@@ -52,6 +57,7 @@ module Nonnative
52
57
  @logger = nil
53
58
  @configuration = nil
54
59
  @process_pool = nil
60
+ @pool = nil
55
61
  end
56
62
  end
57
63
  end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class Configuration
5
+ class << self
6
+ def load_file(path)
7
+ file = YAML.load_file(path)
8
+
9
+ new.tap do |c|
10
+ c.strategy = file['strategy']
11
+
12
+ processes(file, c)
13
+ servers(file, c)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def processes(file, config)
20
+ processes = file['processes'] || []
21
+ processes.each do |fd|
22
+ config.process do |d|
23
+ d.command = fd['command']
24
+ d.timeout = fd['timeout']
25
+ d.port = fd['port']
26
+ d.file = fd['file']
27
+ end
28
+ end
29
+ end
30
+
31
+ def servers(file, config)
32
+ servers = file['servers'] || []
33
+ servers.each do |fd|
34
+ config.server do |s|
35
+ s.klass = Object.const_get(fd['klass'])
36
+ s.timeout = fd['timeout']
37
+ s.port = fd['port']
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ def initialize
44
+ self.strategy = :before
45
+ self.processes = []
46
+ self.servers = []
47
+ end
48
+
49
+ attr_accessor :strategy
50
+ attr_accessor :processes
51
+ attr_accessor :servers
52
+
53
+ def process
54
+ process = Nonnative::ConfigurationProcess.new
55
+ yield process
56
+
57
+ processes << process
58
+ end
59
+
60
+ def server
61
+ server = Nonnative::ConfigurationServer.new
62
+ yield server
63
+
64
+ servers << server
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class ConfigurationProcess
5
+ attr_accessor :command
6
+ attr_accessor :timeout
7
+ attr_accessor :port
8
+ attr_accessor :file
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class ConfigurationServer
5
+ attr_accessor :klass
6
+ attr_accessor :timeout
7
+ attr_accessor :port
8
+ end
9
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class Pool
5
+ def initialize(configuration)
6
+ @configuration = configuration
7
+ end
8
+
9
+ def start(&block)
10
+ all = processes + servers
11
+ process_all(all, :start, :open?, &block)
12
+ end
13
+
14
+ def stop(&block)
15
+ all = processes + servers
16
+ process_all(all, :stop, :closed?, &block)
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :configuration
22
+
23
+ def processes
24
+ @processes ||= configuration.processes.map do |d|
25
+ [Nonnative::System.new(d), Nonnative::Port.new(d)]
26
+ end
27
+ end
28
+
29
+ def servers
30
+ @servers ||= configuration.servers.map do |d|
31
+ [d.klass.new(d.port), Nonnative::Port.new(d)]
32
+ end
33
+ end
34
+
35
+ def process_all(all, pr_method, po_method, &block)
36
+ prs = []
37
+ ths = []
38
+
39
+ all.each do |pr, po|
40
+ prs << pr.send(pr_method)
41
+ ths << Thread.new { po.send(po_method) }
42
+ end
43
+
44
+ ThreadsWait.all_waits(*ths)
45
+
46
+ pos = ths.map(&:value)
47
+
48
+ yield_results(prs, pos, &block)
49
+ end
50
+
51
+ def yield_results(prs, pos)
52
+ prs.zip(pos).each do |id, result|
53
+ yield id, result
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class Port
5
+ def initialize(process)
6
+ @process = process
7
+ @timeout = Nonnative::Timeout.new(process.timeout)
8
+ end
9
+
10
+ def open?
11
+ timeout.perform do
12
+ open_socket
13
+ true
14
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
15
+ sleep_interval
16
+ retry
17
+ end
18
+ end
19
+
20
+ def closed?
21
+ timeout.perform do
22
+ open_socket
23
+ raise Nonnative::Error
24
+ rescue Nonnative::Error
25
+ sleep_interval
26
+ retry
27
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ECONNRESET
28
+ true
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :process, :timeout
35
+
36
+ def open_socket
37
+ TCPSocket.new('127.0.0.1', process.port).close
38
+ end
39
+
40
+ def sleep_interval
41
+ sleep 0.01
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class Server < Thread
5
+ def initialize(port)
6
+ @port = port
7
+ self.abort_on_exception = true
8
+
9
+ super do
10
+ perform_start
11
+ end
12
+ end
13
+
14
+ def start
15
+ object_id
16
+ end
17
+
18
+ def stop
19
+ perform_stop
20
+ object_id
21
+ end
22
+
23
+ attr_reader :port
24
+
25
+ def perform_start; end
26
+
27
+ def perform_stop; end
28
+ end
29
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class System
5
+ def initialize(process)
6
+ @process = process
7
+ @started = false
8
+ end
9
+
10
+ def start
11
+ unless started
12
+ @pid = spawn(process.command, %i[out err] => [process.file, 'a'])
13
+ @started = true
14
+ end
15
+
16
+ pid
17
+ end
18
+
19
+ def stop
20
+ raise Nonnative::Error, "Can't stop a process that has not started" unless started
21
+
22
+ ::Process.kill('SIGINT', pid)
23
+ @started = false
24
+
25
+ pid
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :process, :pid, :started
31
+ end
32
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class Timeout
5
+ def initialize(time)
6
+ @time = time
7
+ end
8
+
9
+ def perform
10
+ ::Timeout.timeout(time) do
11
+ yield
12
+ end
13
+ rescue ::Timeout::Error
14
+ false
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :time
20
+ end
21
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nonnative
4
- VERSION = '1.2.0'
4
+ VERSION = '1.3.0'
5
5
  end
@@ -29,9 +29,9 @@ Gem::Specification.new do |spec|
29
29
  spec.add_dependency 'semantic_logger'
30
30
 
31
31
  spec.add_development_dependency 'bundler'
32
- spec.add_development_dependency 'bundler-audit'
33
32
  spec.add_development_dependency 'rake'
34
33
  spec.add_development_dependency 'rspec-benchmark'
35
34
  spec.add_development_dependency 'rubocop'
36
35
  spec.add_development_dependency 'simplecov'
36
+ spec.add_development_dependency 'solargraph'
37
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nonnative
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Falkowski
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-02-24 00:00:00.000000000 Z
11
+ date: 2020-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cucumber
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: bundler-audit
70
+ name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rake
84
+ name: rspec-benchmark
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: rspec-benchmark
98
+ name: rubocop
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
@@ -109,7 +109,7 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: rubocop
112
+ name: simplecov
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - ">="
@@ -123,7 +123,7 @@ dependencies:
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: simplecov
126
+ name: solargraph
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - ">="
@@ -158,15 +158,18 @@ files:
158
158
  - bin/setup
159
159
  - lib/nonnative.rb
160
160
  - lib/nonnative/before.rb
161
- - lib/nonnative/configuration/object.rb
162
- - lib/nonnative/configuration/process.rb
161
+ - lib/nonnative/configuration.rb
162
+ - lib/nonnative/configuration_process.rb
163
+ - lib/nonnative/configuration_server.rb
163
164
  - lib/nonnative/error.rb
164
165
  - lib/nonnative/logger.rb
165
166
  - lib/nonnative/manual.rb
166
- - lib/nonnative/process/pool.rb
167
- - lib/nonnative/process/port.rb
168
- - lib/nonnative/process/system.rb
167
+ - lib/nonnative/pool.rb
168
+ - lib/nonnative/port.rb
169
+ - lib/nonnative/server.rb
169
170
  - lib/nonnative/startup.rb
171
+ - lib/nonnative/system.rb
172
+ - lib/nonnative/timeout.rb
170
173
  - lib/nonnative/version.rb
171
174
  - nonnative.gemspec
172
175
  homepage: https://github.com/alexfalkowski/nonnative
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nonnative
4
- module Configuration
5
- class Object
6
- class << self
7
- def load_file(path)
8
- file = YAML.load_file(path)
9
-
10
- new.tap do |c|
11
- c.strategy = file['strategy']
12
-
13
- processes(file, c)
14
- end
15
- end
16
-
17
- private
18
-
19
- def processes(file, config)
20
- file['processes'].each do |fd|
21
- config.process do |d|
22
- d.command = fd['command']
23
- d.timeout = fd['timeout']
24
- d.port = fd['port']
25
- d.file = fd['file']
26
- end
27
- end
28
- end
29
- end
30
-
31
- def initialize
32
- self.strategy = :before
33
- self.processes = []
34
- end
35
-
36
- attr_accessor :strategy
37
- attr_accessor :processes
38
-
39
- def process
40
- process = Nonnative::Configuration::Process.new
41
- yield process
42
-
43
- processes << process
44
- end
45
- end
46
- end
47
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nonnative
4
- module Configuration
5
- class Process
6
- attr_accessor :command
7
- attr_accessor :timeout
8
- attr_accessor :port
9
- attr_accessor :file
10
- end
11
- end
12
- end
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nonnative
4
- module Process
5
- class Pool
6
- def initialize(configuration)
7
- @configuration = configuration
8
- end
9
-
10
- def start(&block)
11
- process_all(:start, :open?, &block)
12
- end
13
-
14
- def stop(&block)
15
- process_all(:stop, :closed?, &block)
16
- end
17
-
18
- private
19
-
20
- attr_reader :configuration
21
-
22
- def processes
23
- @processes ||= configuration.processes.map do |d|
24
- [Nonnative::Process::System.new(d), Nonnative::Process::Port.new(d)]
25
- end
26
- end
27
-
28
- def process_all(pr_method, po_method, &block)
29
- prs = []
30
- ths = []
31
-
32
- processes.each do |pr, po|
33
- prs << pr.send(pr_method)
34
- ths << Thread.new { po.send(po_method) }
35
- end
36
-
37
- ThreadsWait.all_waits(*ths)
38
-
39
- pos = ths.map(&:value)
40
-
41
- yield_results(prs, pos, &block)
42
- end
43
-
44
- def yield_results(prs, pos)
45
- prs.zip(pos).each do |pid, result|
46
- yield pid, result
47
- end
48
- end
49
- end
50
- end
51
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nonnative
4
- module Process
5
- class Port
6
- def initialize(process)
7
- @process = process
8
- end
9
-
10
- def open?
11
- timeout do
12
- open_socket
13
- true
14
- rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
15
- sleep_interval
16
- retry
17
- end
18
- end
19
-
20
- def closed?
21
- timeout do
22
- open_socket
23
- raise Nonnative::Error
24
- rescue Nonnative::Error
25
- sleep_interval
26
- retry
27
- rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ECONNRESET
28
- true
29
- end
30
- end
31
-
32
- private
33
-
34
- attr_reader :process
35
-
36
- def timeout
37
- Timeout.timeout(process.timeout) do
38
- yield
39
- end
40
- rescue Timeout::Error
41
- false
42
- end
43
-
44
- def open_socket
45
- TCPSocket.new('127.0.0.1', process.port).close
46
- end
47
-
48
- def sleep_interval
49
- sleep 0.01
50
- end
51
- end
52
- end
53
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nonnative
4
- module Process
5
- class System
6
- def initialize(process)
7
- @process = process
8
- @started = false
9
- end
10
-
11
- def start
12
- unless started
13
- @pid = spawn(process.command, %i[out err] => [process.file, 'a'])
14
- @started = true
15
- end
16
-
17
- pid
18
- end
19
-
20
- def stop
21
- raise Nonnative::Error, "Can't stop a process that has not started" unless started
22
-
23
- ::Process.kill('SIGINT', pid)
24
- @started = false
25
-
26
- pid
27
- end
28
-
29
- private
30
-
31
- attr_reader :process, :pid, :started
32
- end
33
- end
34
- end