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 +4 -4
- data/.circleci/config.yml +0 -1
- data/.rubocop.yml +15 -0
- data/Gemfile.lock +45 -23
- data/Makefile +0 -4
- data/README.md +82 -1
- data/lib/nonnative.rb +18 -12
- data/lib/nonnative/configuration.rb +67 -0
- data/lib/nonnative/configuration_process.rb +10 -0
- data/lib/nonnative/configuration_server.rb +9 -0
- data/lib/nonnative/pool.rb +57 -0
- data/lib/nonnative/port.rb +44 -0
- data/lib/nonnative/server.rb +29 -0
- data/lib/nonnative/system.rb +32 -0
- data/lib/nonnative/timeout.rb +21 -0
- data/lib/nonnative/version.rb +1 -1
- data/nonnative.gemspec +1 -1
- metadata +15 -12
- data/lib/nonnative/configuration/object.rb +0 -47
- data/lib/nonnative/configuration/process.rb +0 -12
- data/lib/nonnative/process/pool.rb +0 -51
- data/lib/nonnative/process/port.rb +0 -53
- data/lib/nonnative/process/system.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f258779774baf11f2ae65c66b397f4f4fa0e1afd10972db59149080a3534616
|
4
|
+
data.tar.gz: ecd62fbcf9051813acda6b21dff301b4985d3ecb6ad3ef89cb3b810e917b297d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 328717fae77a845b8009bdf265b072504b4ad0ec644fb29f5f6884460d8aff892f1f46b73b869010ceae536d3a590a778977a3e65cd86c5f2cc4a0f15fb5e670
|
7
|
+
data.tar.gz: 0dd2f19cf8773c08fe93cf911298e8441ae1465e4289eb2449a44887f8f1a594e50b31ffadb343fd0ebf6e67b0d9f16e29f0faa75406fa7c09e8c82d37fcc643
|
data/.circleci/config.yml
CHANGED
data/.rubocop.yml
CHANGED
@@ -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
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
nonnative (1.
|
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
|
-
|
14
|
-
|
15
|
-
benchmark
|
16
|
-
benchmark-
|
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.
|
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.
|
55
|
-
benchmark-malloc (~> 0.
|
56
|
-
benchmark-perf (~> 0.
|
57
|
-
benchmark-trend (~> 0.
|
58
|
-
rspec (>= 3.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.
|
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.
|
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, <
|
81
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
76
82
|
ruby-progressbar (1.10.1)
|
77
|
-
semantic_logger (4.6.
|
83
|
+
semantic_logger (4.6.1)
|
78
84
|
concurrent-ruby (~> 1.0)
|
79
|
-
simplecov (0.18.
|
85
|
+
simplecov (0.18.5)
|
80
86
|
docile (~> 1.1)
|
81
87
|
simplecov-html (~> 0.11)
|
82
|
-
simplecov-html (0.12.
|
83
|
-
|
84
|
-
|
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
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
|
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
|
+
```
|
data/lib/nonnative.rb
CHANGED
@@ -7,11 +7,14 @@ require 'yaml'
|
|
7
7
|
|
8
8
|
require 'nonnative/version'
|
9
9
|
require 'nonnative/error'
|
10
|
-
require 'nonnative/
|
11
|
-
require 'nonnative/
|
12
|
-
require 'nonnative/
|
13
|
-
require 'nonnative/
|
14
|
-
require 'nonnative/
|
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
|
27
|
+
@configuration ||= Nonnative::Configuration.load_file(path) # rubocop:disable Naming/MemoizedInstanceVariableName
|
25
28
|
end
|
26
29
|
|
27
30
|
def configuration
|
28
|
-
@configuration ||= Nonnative::Configuration
|
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
|
-
@
|
41
|
+
@pool ||= Nonnative::Pool.new(configuration)
|
39
42
|
|
40
|
-
@
|
41
|
-
logger.error('Process has started though did respond in time',
|
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
|
-
@
|
47
|
-
|
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,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
|
data/lib/nonnative/version.rb
CHANGED
data/nonnative.gemspec
CHANGED
@@ -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.
|
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
|
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:
|
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:
|
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:
|
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:
|
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:
|
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
|
162
|
-
- lib/nonnative/
|
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/
|
167
|
-
- lib/nonnative/
|
168
|
-
- lib/nonnative/
|
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,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
|