main_loop

0

Описание

[MIRROR] Main Loop implementation to control subprocesses and threads

https://br.rnds.pro/ruby/main_loop

Языки

  • Ruby98,8%
  • Dockerfile1,2%
16 дней назад
16 дней назад
7 лет назад
7 лет назад
16 дней назад
7 лет назад
7 лет назад
16 дней назад
7 лет назад
16 дней назад
7 лет назад
6 дней назад
16 дней назад
README.md

MainLoop

Gem Version Gem YARD

Coverage Quality Outdated Vulnerabilities

MainLoop — Ruby-библиотека для управления субпроцессами и потоками с функциями:

  • автоматический сбор дочерних процессов (reaping)
  • корректное завершение (SIGTERM/SIGINT) процессов и потоков
  • автоматический перезапуск по количеству повторов
  • принудительное завершение по таймауту
  • обработка завершения процессов и потоков

MainLoop is a Ruby library for managing subprocesses and threads with features:

  • automatic child process reaping
  • graceful shutdown (SIGTERM/SIGINT) for processes and threads
  • automatic restart by retry count
  • timeout-based force termination
  • process/thread completion handling

Возможности / Features

  • Потоко-безопасный канал обмена событиями (IO.pipe) / Thread-safe event bus (IO.pipe)
  • Управление процессами через Kernel.fork / Process management via Kernel.fork
  • Управление потоками через Thread.new / Thread management via Thread.new
  • Обработка сигналов TERM/INT/CLD / SIGTERM/INT/CLD signal handling
  • Автоматический сбор завершенных процессов / Automatic child process reaping
  • Retry-логика для перезапуска / Retry logic for restarts
  • Принудительное завершение по таймауту / Timeout-based force termination

Начало работы / Getting started

gem install main_loop

При установке

MainLoop
через bundler добавьте следующую строку в
Gemfile
:


If you'd rather install

MainLoop
using bundler, add a line for it in your
Gemfile
:

gem 'main_loop'

Затем выполните / Then run:

bundle install # для установки гема / gem installation

Корневой модуль / Root module

MainLoop
- это корневой модуль, который подключает все компоненты:


MainLoop
is the root module that requires all components:

Субмодули / Submodules:

  • MainLoop::Bus
    — канал обмена событиями (IO.pipe)
  • MainLoop::Dispatcher
    — координация обработчиков и управление жизненным циклом
  • MainLoop::Loop
    — главный цикл обработки событий и сигналов
  • MainLoop::Handler
    — абстрактный базовый класс
  • MainLoop::ProcessHandler
    — управление субпроцессами
  • MainLoop::ThreadHandler
    — управление потоками

Архитектура / Architecture

Жизненный цикл обработчика / Handler lifecycle

Способы определения логики

Библиотека поддерживает два основных подхода для описания работы процессов и потоков:

1. Блок (inline block)

Передайте блок кода непосредственно в конструктор обработчика (

ProcessHandler
или
ThreadHandler
). В этом блоке размещается основная логика. При завершении (по сигналу, ошибке или таймауту) блок прерывается; вы можете определить дополнительные действия, используя переданный объект обработчика.

2. Объект с интерфейсом run / on_term

Передайте экземпляр класса, который реализует два обязательных метода:

  • run
    — содержит основную логику; для
    ProcessHandler
    метод не принимает аргументов, для
    ThreadHandler
    получает объект потока.
  • on_term
    — вызывается при необходимости завершить процесс/поток; для
    ProcessHandler
    принимает PID, для
    ThreadHandler
    — объект потока. В этом методе следует инициировать корректное завершение (например, послать сигнал процессу или установить флаг остановки для потока).

Оба подхода могут комбинироваться с параметрами (

retry_count
,
logger
и т.д.) и одинаково хорошо интегрируются с циклом
MainLoop::Loop
.

Выбор зависит от удобства: для простых сценариев подойдёт блок, для сложной логики управления завершением — объект с явными методами.

Использование / Usage

Базовая настройка / Basic setup

Обработка процессов / Process handling

Простейший пример / Simplest example

С блоком кода / With code block

С объектом runnable / With runnable object

Обработка потоков / Thread handling

Поток с блоком / Thread with block

Поток с блоком и колбэком завершения / Thread with block and termination callback

Поток с объектом runnable / Thread with runnable object

Запуск цикла / Start loop

Обработка завершения / Termination handling

Когда отправляется сигнал

TERM
или
INT
:

  1. trap
    перехватывает сигнал и отправляет
    bus.puts("sig:TERM")
  2. Loop
    получает событие из
    Bus
    и вызывает
    Dispatcher#term
  3. Dispatcher
    устанавливает
    @terminating_at = Time.now
  4. Все обработчики получают
    term
    :
    • ProcessHandler
      посылает
      Process.kill('TERM', pid)
    • ThreadHandler
      вызывает
      @on_term
      блок
  5. Если через
    timeout
    (по умолчанию 5 сек) процессы не завершились:
    • Dispatcher#tick
      проверяет
      need_force_kill?
    • Если
      true
      — посылает
      kill
      всем обработчикам
  6. Когда все обработчики завершаются (
    finished?
    ):
    • Dispatcher#try_exit!
      вызывает
      exit(@exit_code)

When sending

TERM
or
INT
signal:

  1. trap
    catches the signal and sends
    bus.puts("sig:TERM")
  2. Loop
    gets the event from
    Bus
    and calls
    Dispatcher#term
  3. Dispatcher
    sets
    @terminating_at = Time.now
  4. All handlers receive
    term
    :
    • ProcessHandler
      sends
      Process.kill('TERM', pid)
    • ThreadHandler
      calls
      @on_term
      block
  5. If processes don't terminate within
    timeout
    (default 5 seconds):
    • Dispatcher#tick
      checks
      need_force_kill?
    • If
      true
      — sends
      kill
      to all handlers
  6. When all handlers finish (
    finished?
    ):
    • Dispatcher#try_exit!
      calls
      exit(@exit_code)

Повторы (retry) / Retry

Публикация событий / Publishing events

Обработчики могут отправлять события в шину:


Handlers can publish events to the bus:

Особенности / Features

  • Потоко-безопасность:
    Bus
    и
    Dispatcher
    используют
    MonitorMixin
  • Таймауты:
    Timeouter
    используется для timeout в
    Bus#gets
    и
    Loop#start_loop_forever
  • Логирование: все классы принимают параметр
    logger:
    , по умолчанию
    Logger.new(nil)
  • Ошибки: используйте
    rescue StandardError
    (не пустой
    rescue
    )
  • Коды выхода:
    exit!(code)
    в процессах,
    exit(code)
    в основном потоке

  • Thread safety:
    Bus
    and
    Dispatcher
    use
    MonitorMixin
  • Timeouts:
    Timeouter
    is used for timeout in
    Bus#gets
    и
    Loop#start_loop_forever
  • Logging: all classes accept
    logger:
    parameter, default is
    Logger.new(nil)
  • Error handling: use
    rescue StandardError
    (not bare
    rescue
    )
  • Exit codes:
    exit!(code)
    in processes,
    exit(code)
    in main thread

Тестирование / Testing

Для запуска примеров из локальной копии репозитория (без установки гема) используйте опцию

-I
интерпретатора Ruby, указав путь к директории
lib
относительно текущей папки:

Версия / Version

Текущая версия / Current version:

0.1.4

Автор / Author

Юрий Самойленко / Yuri Samoylenko kinnalru@gmail.com

Лицензия / License

Библиотека доступна с открытым исходным кодом в соответствии с условиями лицензии MIT.


The gem is available as open source under the terms of the MIT License.