main_loop 0.1.4.364822 → 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.
@@ -1,10 +1,49 @@
1
1
  require 'main_loop/handler'
2
2
 
3
+ # = MainLoop::ThreadHandler
4
+ #
5
+ # Управляет потоками через Thread.new.
6
+ #
7
+ # == Особенности потоков
8
+ #
9
+ # - Потоки не имеют status завершения (как процессы)
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
17
+ #
18
+ # == Сигналы для потока
19
+ #
20
+ # При {#term}:
21
+ # - Если не терминация: вызовы @runnable.on_term / @on_term
22
+ # - Если терминация: @thread.kill (FORCE)
23
+ #
24
+ # == Пример использования
25
+ #
26
+ # MainLoop::ThreadHandler.new dispatcher, 'worker', retry_count: 0, logger: logger do |thread|
27
+ # loop do
28
+ # sleep 1
29
+ # end
30
+ # end
31
+ #
32
+ # == См. также
33
+ # - {MainLoop::Handler} — базовый класс
34
+ # - {MainLoop::ProcessHandler} — обработчики процессов
35
+
3
36
  module MainLoop
4
37
  class ThreadHandler < MainLoop::Handler
5
-
6
38
  attr_reader :thread
7
39
 
40
+ # == Инициализация
41
+ #
42
+ # @param dispatcher [Dispatcher] ссылка на диспетчер
43
+ # @param name [String] имя обработчика
44
+ # @param runnable [Object] объект с методами run и on_term (опционально)
45
+ # @param retry_count [Integer, :unlimited] количество повторов
46
+ # @param logger [Logger] логгер
8
47
  def initialize(dispatcher, name, runnable: nil, **kwargs, &block)
9
48
  super
10
49
  @handler_type = 'Thread'
@@ -23,25 +62,35 @@ module MainLoop
23
62
  run
24
63
  end
25
64
 
65
+ # == Получить ID потока
66
+ #
67
+ # @return [String] object_id потока в виде строки
26
68
  def id
27
69
  @thread&.object_id.to_s
28
70
  end
29
71
 
72
+ # == Обработка завершения потока
73
+ #
74
+ # @param status [String] статус завершения (описание)
30
75
  def reap(status)
31
76
  logger.info "Thread[#{name}] exited: thread:#{@thread} Status:#{status}"
77
+ exit_reason = @thread[:exit_reason] if @thread
32
78
  @thread = nil
33
79
  @finished = true
34
80
 
35
81
  return if terminating?
36
- @success = false
37
82
 
83
+ @success = (exit_reason == :normal)
38
84
  handle_retry
39
85
  end
40
86
 
41
- def term
87
+ # == Терминация потока
88
+ #
89
+ # @param *_args (Unused)
90
+ def term(*_args)
42
91
  unless @thread
43
92
  @terminating_at ||= Time.now
44
- logger.debug "Thread[#{name}] alredy terminated. Skipped."
93
+ logger.debug "Thread[#{name}] already terminated. Skipped."
45
94
  return
46
95
  end
47
96
 
@@ -59,9 +108,12 @@ module MainLoop
59
108
  end
60
109
  end
61
110
 
62
- def kill
111
+ # == Принудительно завершить поток
112
+ #
113
+ # @param *_args (Unused)
114
+ def kill(*_args)
63
115
  unless @thread
64
- logger.debug "Thread[#{name}] alredy Killed. Skipped."
116
+ logger.debug "Thread[#{name}] already Killed. Skipped."
65
117
  return
66
118
  end
67
119
 
@@ -70,6 +122,9 @@ module MainLoop
70
122
  @thread.kill rescue nil
71
123
  end
72
124
 
125
+ # == Запустить поток
126
+ #
127
+ # Вызывает {#start_thread} с блоком или runnable.
73
128
  def run
74
129
  return if terminating?
75
130
 
@@ -80,20 +135,27 @@ module MainLoop
80
135
  end
81
136
  end
82
137
 
138
+ # == Create-thread блок (protected)
139
+ #
140
+ # Создает новый поток и настраивает обработку ошибок и завершения.
141
+ #
142
+ # @yield выполнить блок кода в потоке
143
+ # @return [Thread] созданный поток
83
144
  protected
84
145
 
85
146
  def start_thread
86
147
  @thread = Thread.new do
87
148
  yield(self)
149
+ Thread.current[:exit_reason] = :normal
88
150
  rescue StandardError => e
151
+ Thread.current[:exit_reason] = :exception
89
152
  logger.error "Thread[#{name}] crashed: #{e.message}"
90
153
  ensure
154
+ Thread.current[:exit_reason] ||= :killed
91
155
  publish("reap:#{id}:exited")
92
156
  end
93
157
  @finished = false
94
158
  logger.info "Thread[#{name}] created: thread:#{@thread}"
95
159
  end
96
-
97
-
98
160
  end
99
161
  end
data/lib/main_loop.rb CHANGED
@@ -1,10 +1,50 @@
1
+ # YARD-документация для main_loop
2
+ # Основной модуль библиотеки для управления субпроцессами и потоками
3
+
1
4
  require 'main_loop/bus'
2
5
  require 'main_loop/loop'
3
6
  require 'main_loop/dispatcher'
4
7
  require 'main_loop/process_handler'
5
8
  require 'main_loop/thread_handler'
6
9
 
7
-
10
+ # = MainLoop
11
+ #
12
+ # Главный модуль библиотеки для управления субпроцессами и потоками.
13
+ #
14
+ # Основные компоненты:
15
+ # - {MainLoop::Bus} — канал обмена событиями между компонентами
16
+ # - {MainLoop::Dispatcher} — координация обработчиков и управление жизненным циклом
17
+ # - {MainLoop::Loop} — главный цикл обработки событий и сигналов
18
+ # - {MainLoop::Handler} — абстрактный базовый класс для обработчиков
19
+ # - {MainLoop::ProcessHandler} — управление субпроцессами
20
+ # - {MainLoop::ThreadHandler} — управление потоками
21
+ #
22
+ # == Пример использования
23
+ #
24
+ # require 'main_loop'
25
+ # require 'logger'
26
+ #
27
+ # logger = Logger.new(STDOUT)
28
+ # logger.level = Logger::DEBUG
29
+ #
30
+ # bus = MainLoop::Bus.new
31
+ # dispatcher = MainLoop::Dispatcher.new(bus, timeout: 10, logger: logger)
32
+ # mainloop = MainLoop::Loop.new(bus, dispatcher, logger: logger)
33
+ #
34
+ # MainLoop::ProcessHandler.new dispatcher, 'worker', retry_count: 3, logger: logger do
35
+ # sleep 2
36
+ # exit! 0
37
+ # end
38
+ #
39
+ # mainloop.run
40
+ #
41
+ # == См. также
42
+ # - {MainLoop::Bus}
43
+ # - {MainLoop::Dispatcher}
44
+ # - {MainLoop::Loop}
45
+ # - {MainLoop::Handler}
46
+ # - {MainLoop::ProcessHandler}
47
+ # - {MainLoop::ThreadHandler}
8
48
 
9
49
  module MainLoop
10
50
 
@@ -13,4 +53,3 @@ module MainLoop
13
53
  end
14
54
 
15
55
  end
16
-
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.364822
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-03-30 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