main_loop 0.1.4.367214 → 0.1.4.369901

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
  SHA256:
3
- metadata.gz: 850bb2f02f1bff7caf3ebca532839b4143a24810948b2ac29446d0321542911b
4
- data.tar.gz: 88f4324fb104706a0705260d6c82ca7f2f04e66af1a9ca2c88d63e3142bcbe62
3
+ metadata.gz: 6715ecb631f944f513d3ef4083ca568fe7f1e50fda1e007ff27a08f9d11da959
4
+ data.tar.gz: f639291ab878bec54c493e79abf9e5bd004ab670c44dea5db0fc2d892baf2070
5
5
  SHA512:
6
- metadata.gz: 2d2675f76bb8127405617c12f4fa39a5e6ae2f3507de8131b4f878a22dc9884ba46e2d50125729e2471bbaee9c2be2fbd164b047914738c5f2b7f13642b71197
7
- data.tar.gz: eaa4672e9905b147a25b8a376c871debc1841879e8f486d58f8928c14c7289ce19b3813b6ad7a8042f49a0eca88f5d190270e334b9799371b252468575a2a803
6
+ metadata.gz: ba62a2aa69a9774f8a6c851942689546ea6ab5a34297a60724c627fbb1427c5dde21d5f2435d6ade44afcec90de929c3066bd6f36439210bf0692af1becc83c5
7
+ data.tar.gz: a1892e24867d6be57ed7f00834f404635d92b907c46bcf1a5149559af84a5c05caa452cbdd0a41c2ca6e255bd8511c16160082fa0303a1ee9b12de344b12d104
data/lib/main_loop/bus.rb CHANGED
@@ -108,11 +108,11 @@ module MainLoop
108
108
 
109
109
  # == Блокирующее чтение события
110
110
  #
111
- # Блокирует до получения строки или таймаута.
111
+ # Блокирует до получения события или таймаута.
112
112
  # Использует {Timeouter.loop} для ограничения времени ожидания.
113
113
  #
114
114
  # @param timeout [Numeric] таймаут ожидания в секундах
115
- # @return [String|nil] прочитанная строка (без символа новой строки) или nil при таймауте
115
+ # @return [String|nil] прочитанное событие (без символа новой строки) или nil при таймауте
116
116
  def gets(timeout)
117
117
  Timeouter.loop(timeout) do |t|
118
118
  line = gets_nonblock if wait_for_event(t.left)
@@ -120,7 +120,7 @@ module MainLoop
120
120
  end
121
121
  end
122
122
 
123
- # == Неблокирующее чтение символа
123
+ # == Неблокирующее чтение строки
124
124
  #
125
125
  # Читает посимвольно до конца строки (EOL).
126
126
  # Буферизует символы и возвращает полную строку.
@@ -130,7 +130,7 @@ module MainLoop
130
130
 
131
131
  # == Отправить сигнал аварийного завершения
132
132
  #
133
- # Устанавливает 코드 выхода 3 и инициирует терминацию.
133
+ # Устанавливает код выхода 3 и инициирует терминацию.
134
134
  # Если уже терминация — ничего не делает.
135
135
  def crash
136
136
  @exit_code = 3
@@ -194,7 +194,7 @@ module MainLoop
194
194
  # == Логировать статус
195
195
  #
196
196
  # Логирует текущее состояние обработчиков (DEBUG уровень).
197
- # Формат: "Total:N Running:M Finihsed:K. TERM"
197
+ # Формат: "Total:N Running:M Finished:K. Success:[] TERM"
198
198
  #
199
199
  # :nocov:
200
200
  def log_status
@@ -202,7 +202,7 @@ module MainLoop
202
202
  running = handlers.count(&:running?)
203
203
  finihsed = handlers.count(&:finished?)
204
204
  term_text = terminating? ? 'TERM' : ''
205
- logger.debug("Total:#{total} Running:#{running} Finihsed:#{finihsed}. #{term_text}".strip)
205
+ logger.debug("Total:#{total} Running:#{running} Finished:#{finihsed} Success:#{handlers.map {|h| h.success?}.to_s}. #{term_text}".strip)
206
206
  end
207
207
  # :nocov:
208
208
  end
@@ -18,30 +18,6 @@ require 'logger'
18
18
  # - {#kill} — принудительное завершение
19
19
  # - {#reap(status)} — обработка завершения процесса/потока
20
20
  #
21
- # == Пример использования
22
- #
23
- # class MyHandler < MainLoop::Handler
24
- # def id
25
- # @process_id
26
- # end
27
- #
28
- # def term
29
- # Process.kill('TERM', @process_id)
30
- # end
31
- #
32
- # def run
33
- # @process_id = Process.fork { yield }
34
- # end
35
- #
36
- # def kill
37
- # Process.kill('KILL', @process_id)
38
- # end
39
- #
40
- # def reap(status)
41
- # # обработка завершения
42
- # end
43
- # end
44
- #
45
21
  # == См. также
46
22
  # - {MainLoop::ProcessHandler} — реализация для процессов
47
23
  # - {MainLoop::ThreadHandler} — реализация для потоков
@@ -92,7 +92,7 @@ module MainLoop
92
92
  def term(*_args)
93
93
  unless @pid
94
94
  @terminating_at ||= Time.now
95
- logger.debug "Process[#{name}] alredy terminated. Skipped."
95
+ logger.debug "Process[#{name}] already terminated. Skipped."
96
96
  return
97
97
  end
98
98
 
@@ -116,7 +116,7 @@ module MainLoop
116
116
  # @param *_args (Unused)
117
117
  def kill(*_args)
118
118
  unless @pid
119
- logger.debug "Process[#{name}] alredy Killed. Skipped."
119
+ logger.debug "Process[#{name}] already Killed. Skipped."
120
120
  return
121
121
  end
122
122
 
@@ -142,7 +142,7 @@ module MainLoop
142
142
  #
143
143
  # Создает дочерний процесс и настраивает обработку ошибок.
144
144
  #
145
- # @yield执行 блок кода в дочернем процессе
145
+ # @yield выполнить блок кода в дочернем процессе
146
146
  # @return [Integer] PID дочернего процесса
147
147
  protected
148
148
 
@@ -7,8 +7,13 @@ require 'main_loop/handler'
7
7
  # == Особенности потоков
8
8
  #
9
9
  # - Потоки не имеют status завершения (как процессы)
10
- # - Поэтому @success = false для всех завершений (кроме graceful term)
11
- # - Завершение потока публикуется в ensure блоке
10
+ # - Если завершение graceful term, то @success отражает, завершился ли он после вызова on_term (true) или после нашего kill
11
+ # - Внутри on_term поток может быть завершен так, как считает нужным разработчик метода, например
12
+ # @stopped = true
13
+ # @thread&.wakeup
14
+ # @thread&.kill unless @thread&.join(2)
15
+ # - Если поток завершился сам, то смотрим на Thread.current[:exit_reason]
16
+ # - Завершение потока публикуется в ensure блоке и обрабатывается в MainLoop#start_loop_forever
12
17
  #
13
18
  # == Сигналы для потока
14
19
  #
@@ -69,12 +74,13 @@ module MainLoop
69
74
  # @param status [String] статус завершения (описание)
70
75
  def reap(status)
71
76
  logger.info "Thread[#{name}] exited: thread:#{@thread} Status:#{status}"
77
+ exit_reason = @thread[:exit_reason] if @thread
72
78
  @thread = nil
73
79
  @finished = true
74
80
 
75
81
  return if terminating?
76
- @success = false
77
82
 
83
+ @success = (exit_reason == :normal)
78
84
  handle_retry
79
85
  end
80
86
 
@@ -84,7 +90,7 @@ module MainLoop
84
90
  def term(*_args)
85
91
  unless @thread
86
92
  @terminating_at ||= Time.now
87
- logger.debug "Thread[#{name}] alredy terminated. Skipped."
93
+ logger.debug "Thread[#{name}] already terminated. Skipped."
88
94
  return
89
95
  end
90
96
 
@@ -107,7 +113,7 @@ module MainLoop
107
113
  # @param *_args (Unused)
108
114
  def kill(*_args)
109
115
  unless @thread
110
- logger.debug "Thread[#{name}] alredy Killed. Skipped."
116
+ logger.debug "Thread[#{name}] already Killed. Skipped."
111
117
  return
112
118
  end
113
119
 
@@ -133,20 +139,23 @@ module MainLoop
133
139
  #
134
140
  # Создает новый поток и настраивает обработку ошибок и завершения.
135
141
  #
136
- # @yield执行 блок кода в потоке
142
+ # @yield выполнить блок кода в потоке
137
143
  # @return [Thread] созданный поток
138
144
  protected
139
145
 
140
146
  def start_thread
141
147
  @thread = Thread.new do
142
148
  yield(self)
149
+ Thread.current[:exit_reason] = :normal
143
150
  rescue StandardError => e
151
+ Thread.current[:exit_reason] = :exception
144
152
  logger.error "Thread[#{name}] crashed: #{e.message}"
145
153
  ensure
154
+ Thread.current[:exit_reason] ||= :killed
146
155
  publish("reap:#{id}:exited")
147
156
  end
148
157
  @finished = false
149
158
  logger.info "Thread[#{name}] created: thread:#{@thread}"
150
- end
159
+ end
151
160
  end
152
161
  end
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.367214
4
+ version: 0.1.4.369901
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samoilenko Yuri
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-09 00:00:00.000000000 Z
11
+ date: 2026-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler