main_loop 0.1.3.16874 → 0.1.4.364822
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/README.md +4 -5
- data/lib/main_loop/dispatcher.rb +2 -2
- data/lib/main_loop/handler.rb +2 -2
- data/lib/main_loop/loop.rb +8 -2
- data/lib/main_loop/process_handler.rb +30 -8
- data/lib/main_loop/thread_handler.rb +21 -6
- data/lib/main_loop/version.rb +1 -1
- metadata +34 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ec4bfd3358113dae75080b98525dcec837de50f484b9df20b6d19b0b93cfae12
|
|
4
|
+
data.tar.gz: 65e3173cd2c269a8c6ed8a1d2ca0a3ca9a94a7903c363901f3d82fe834f8e160
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a82577aaf2f8c3620a7bf45dd2baa08f1ec3e5da6d2ea9cc280ac7c7b78f974bfd0c5ae85eba516c4fec7d35fa7cb46207efbc9679b85b53d30f1bb5f555cdbc
|
|
7
|
+
data.tar.gz: 6c31a0c1f9e9c8294f45e3f15839379533ee5a7a2b40c021c25ff977977133ac1e77a6262d25148039fa675c313d6e403927f7259f33780e75fac6e7f5e667d6
|
data/README.md
CHANGED
|
@@ -4,11 +4,10 @@
|
|
|
4
4
|
[](https://rubygems.org/gems/main_loop/versions)
|
|
5
5
|
[](http://www.rubydoc.info/gems/main_loop)
|
|
6
6
|
|
|
7
|
-
[](https://lysander.x.rnds.pro/api/v1/badges/main_loop_vulnerable.html)
|
|
7
|
+
[](https://lysander.rnds.pro/api/v1/badges/main_loop_coverage.html)
|
|
8
|
+
[](https://lysander.rnds.pro/api/v1/badges/main_loop_quality.html)
|
|
9
|
+
[](https://lysander.rnds.pro/api/v1/badges/main_loop_outdated.html)
|
|
10
|
+
[](https://lysander.rnds.pro/api/v1/badges/main_loop_vulnerable.html)
|
|
12
11
|
|
|
13
12
|
MainLoop is a simple main application implementation to control subprocesses(children) and threads.
|
|
14
13
|
|
data/lib/main_loop/dispatcher.rb
CHANGED
|
@@ -26,10 +26,10 @@ module MainLoop
|
|
|
26
26
|
def reap_by_id(id, status)
|
|
27
27
|
synchronize do
|
|
28
28
|
if (handler = handlers.find {|h| h.id == id })
|
|
29
|
-
logger.info("Reap handler #{handler.name.inspect}. Status: #{status
|
|
29
|
+
logger.info("Reap handler #{handler.name.inspect}. Status: #{status&.inspect}")
|
|
30
30
|
handler.reap(status)
|
|
31
31
|
else
|
|
32
|
-
logger.debug("Reap unknown handler. Status: #{status
|
|
32
|
+
logger.debug("Reap unknown handler. Status: #{status&.inspect}. Skipped")
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
end
|
data/lib/main_loop/handler.rb
CHANGED
|
@@ -81,10 +81,10 @@ module MainLoop
|
|
|
81
81
|
def handle_retry
|
|
82
82
|
if @retry_count == :unlimited
|
|
83
83
|
logger.info "#{@handler_type}[#{name}] retry...."
|
|
84
|
-
self.run
|
|
84
|
+
self.run
|
|
85
85
|
elsif @retry_count && (@retry_count -= 1) >= 0
|
|
86
86
|
logger.info "#{@handler_type}[#{name}] retry...."
|
|
87
|
-
self.run
|
|
87
|
+
self.run
|
|
88
88
|
else
|
|
89
89
|
publish(:term)
|
|
90
90
|
end
|
data/lib/main_loop/loop.rb
CHANGED
|
@@ -28,6 +28,8 @@ module MainLoop
|
|
|
28
28
|
# :nocov:
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
# TODO поскольку wait всегда равен 5 секунд, то цикл работы 5 секунд, и потому
|
|
32
|
+
# timeout для Dispatcher нужно ставить больше 2 циклов, чтобы успели завершиться все потоки или процессы
|
|
31
33
|
def start_loop_forever(timeout = 0)
|
|
32
34
|
wait = [[(timeout / 2.5), 5].min, 5].max
|
|
33
35
|
Timeouter.loop(timeout) do
|
|
@@ -98,8 +100,12 @@ module MainLoop
|
|
|
98
100
|
results = []
|
|
99
101
|
|
|
100
102
|
@dispatcher.pids.each do |pid|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
begin
|
|
104
|
+
if (result = self.wait2(pid))
|
|
105
|
+
results << result
|
|
106
|
+
end
|
|
107
|
+
rescue Errno::ECHILD
|
|
108
|
+
results << [pid, nil]
|
|
103
109
|
end
|
|
104
110
|
end
|
|
105
111
|
|
|
@@ -5,13 +5,22 @@ module MainLoop
|
|
|
5
5
|
|
|
6
6
|
attr_reader :pid
|
|
7
7
|
|
|
8
|
-
def initialize(dispatcher, name, **kwargs, &block)
|
|
8
|
+
def initialize(dispatcher, name, runnable: nil, **kwargs, &block)
|
|
9
9
|
super
|
|
10
10
|
@handler_type = 'Process'
|
|
11
11
|
@pid = nil
|
|
12
12
|
dispatcher.add_handler(self)
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
if runnable
|
|
15
|
+
unless runnable.respond_to?(:run) && runnable.respond_to?(:on_term)
|
|
16
|
+
raise TypeError, "Runnable object must respond to :run and :on_term"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
@runnable = runnable
|
|
21
|
+
@block = block
|
|
22
|
+
|
|
23
|
+
run
|
|
15
24
|
end
|
|
16
25
|
|
|
17
26
|
def id
|
|
@@ -19,10 +28,15 @@ module MainLoop
|
|
|
19
28
|
end
|
|
20
29
|
|
|
21
30
|
def reap(status)
|
|
22
|
-
|
|
31
|
+
if status
|
|
32
|
+
logger.info "Process[#{name}] exited: Pid:#{@pid} Status: #{status.exitstatus.inspect} Termsig: #{status.termsig.inspect} Success: #{status.success?}"
|
|
33
|
+
@success = !!status.success?
|
|
34
|
+
else
|
|
35
|
+
logger.info "Process[#{name}] exited: Pid:#{@pid} with unknown status"
|
|
36
|
+
@success = true # TODO или false?
|
|
37
|
+
end
|
|
23
38
|
@pid = nil
|
|
24
39
|
@finished = true
|
|
25
|
-
@success = !!status.success?
|
|
26
40
|
|
|
27
41
|
return if terminating?
|
|
28
42
|
|
|
@@ -43,7 +57,10 @@ module MainLoop
|
|
|
43
57
|
else
|
|
44
58
|
@terminating_at ||= Time.now
|
|
45
59
|
logger.info "Process[#{name}] send terminate: Pid:#{@pid}"
|
|
60
|
+
|
|
61
|
+
@runnable&.on_term(@pid) rescue nil
|
|
46
62
|
@on_term&.call(@pid) rescue nil
|
|
63
|
+
|
|
47
64
|
::Process.kill('TERM', @pid) rescue nil
|
|
48
65
|
end
|
|
49
66
|
end
|
|
@@ -59,11 +76,14 @@ module MainLoop
|
|
|
59
76
|
::Process.kill('KILL', @pid) rescue nil
|
|
60
77
|
end
|
|
61
78
|
|
|
62
|
-
def run
|
|
79
|
+
def run
|
|
63
80
|
return if terminating?
|
|
64
81
|
|
|
65
|
-
@
|
|
66
|
-
|
|
82
|
+
if @runnable
|
|
83
|
+
start_fork { @runnable.run }
|
|
84
|
+
elsif @block
|
|
85
|
+
start_fork(&@block)
|
|
86
|
+
end
|
|
67
87
|
end
|
|
68
88
|
|
|
69
89
|
protected
|
|
@@ -71,6 +91,9 @@ module MainLoop
|
|
|
71
91
|
def start_fork
|
|
72
92
|
@pid = Kernel.fork do
|
|
73
93
|
yield
|
|
94
|
+
rescue StandardError => e
|
|
95
|
+
logger.error "Process[#{name}] crashed: #{e.message}"
|
|
96
|
+
exit!(1)
|
|
74
97
|
end
|
|
75
98
|
@finished = false
|
|
76
99
|
logger.info "Process[#{name}] created: Pid:#{@pid}"
|
|
@@ -79,4 +102,3 @@ module MainLoop
|
|
|
79
102
|
|
|
80
103
|
end
|
|
81
104
|
end
|
|
82
|
-
|
|
@@ -5,13 +5,22 @@ module MainLoop
|
|
|
5
5
|
|
|
6
6
|
attr_reader :thread
|
|
7
7
|
|
|
8
|
-
def initialize(dispatcher, name, **kwargs, &block)
|
|
8
|
+
def initialize(dispatcher, name, runnable: nil, **kwargs, &block)
|
|
9
9
|
super
|
|
10
10
|
@handler_type = 'Thread'
|
|
11
11
|
@thread = nil
|
|
12
12
|
dispatcher.add_handler(self)
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
if runnable
|
|
15
|
+
unless runnable.respond_to?(:run) && runnable.respond_to?(:on_term)
|
|
16
|
+
raise TypeError, "Runnable object must respond to :run and :on_term"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
@runnable = runnable
|
|
21
|
+
@block = block
|
|
22
|
+
|
|
23
|
+
run
|
|
15
24
|
end
|
|
16
25
|
|
|
17
26
|
def id
|
|
@@ -44,6 +53,8 @@ module MainLoop
|
|
|
44
53
|
@terminating_at ||= Time.now
|
|
45
54
|
@success = true
|
|
46
55
|
logger.info "Thread[#{name}] send terminate: thread:#{@thread}"
|
|
56
|
+
|
|
57
|
+
@runnable&.on_term(@thread) rescue nil
|
|
47
58
|
@on_term&.call(@thread) rescue nil
|
|
48
59
|
end
|
|
49
60
|
end
|
|
@@ -59,11 +70,14 @@ module MainLoop
|
|
|
59
70
|
@thread.kill rescue nil
|
|
60
71
|
end
|
|
61
72
|
|
|
62
|
-
def run
|
|
73
|
+
def run
|
|
63
74
|
return if terminating?
|
|
64
75
|
|
|
65
|
-
@
|
|
66
|
-
|
|
76
|
+
if @runnable
|
|
77
|
+
start_thread { @runnable.run(self) }
|
|
78
|
+
elsif @block
|
|
79
|
+
start_thread(&@block)
|
|
80
|
+
end
|
|
67
81
|
end
|
|
68
82
|
|
|
69
83
|
protected
|
|
@@ -71,6 +85,8 @@ module MainLoop
|
|
|
71
85
|
def start_thread
|
|
72
86
|
@thread = Thread.new do
|
|
73
87
|
yield(self)
|
|
88
|
+
rescue StandardError => e
|
|
89
|
+
logger.error "Thread[#{name}] crashed: #{e.message}"
|
|
74
90
|
ensure
|
|
75
91
|
publish("reap:#{id}:exited")
|
|
76
92
|
end
|
|
@@ -81,4 +97,3 @@ module MainLoop
|
|
|
81
97
|
|
|
82
98
|
end
|
|
83
99
|
end
|
|
84
|
-
|
data/lib/main_loop/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: main_loop
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.4.364822
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samoilenko Yuri
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-03-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -72,6 +72,20 @@ dependencies:
|
|
|
72
72
|
- - ">="
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
74
|
version: '0'
|
|
75
|
+
- !ruby/object:Gem::Dependency
|
|
76
|
+
name: rubycritic
|
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
type: :development
|
|
83
|
+
prerelease: false
|
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0'
|
|
75
89
|
- !ruby/object:Gem::Dependency
|
|
76
90
|
name: simplecov
|
|
77
91
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -100,6 +114,20 @@ dependencies:
|
|
|
100
114
|
- - ">="
|
|
101
115
|
- !ruby/object:Gem::Version
|
|
102
116
|
version: '0'
|
|
117
|
+
- !ruby/object:Gem::Dependency
|
|
118
|
+
name: simplecov-cobertura
|
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - ">="
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '0'
|
|
124
|
+
type: :development
|
|
125
|
+
prerelease: false
|
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - ">="
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '0'
|
|
103
131
|
- !ruby/object:Gem::Dependency
|
|
104
132
|
name: timeouter
|
|
105
133
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -135,7 +163,7 @@ homepage: https://github.com/RnD-Soft/main_loop
|
|
|
135
163
|
licenses:
|
|
136
164
|
- MIT
|
|
137
165
|
metadata: {}
|
|
138
|
-
post_install_message:
|
|
166
|
+
post_install_message:
|
|
139
167
|
rdoc_options: []
|
|
140
168
|
require_paths:
|
|
141
169
|
- lib
|
|
@@ -150,8 +178,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
150
178
|
- !ruby/object:Gem::Version
|
|
151
179
|
version: '0'
|
|
152
180
|
requirements: []
|
|
153
|
-
rubygems_version: 3.
|
|
154
|
-
signing_key:
|
|
181
|
+
rubygems_version: 3.2.33
|
|
182
|
+
signing_key:
|
|
155
183
|
specification_version: 4
|
|
156
184
|
summary: Main Loop implementation to control subprocesses and threads
|
|
157
185
|
test_files: []
|