Honcho

Honcho is an in-application process1 supervisor for Crystal, inspired by erlang's supervisor module. Supervisors enable code to be aware of when things crash and automatically handle them in a variety of ways. For example:

The real power of supervisors is the ability to group and nest them into trees of management that give full control over the lifetimes of every process in the tree. Strategies, modes, and delays can all be applied individually to every process in the tree, including supervisors themselves!

This project is still somewhat early in development. It should be usable, but lacks proper testing and many features. Use at your own discretion.

Honcho is up-to-date as of Crystal 0.32.1 (released December 18th, 2019). Since this library relies on some internal behaviors, it is not guaranteed to work with future versions without an update to itself. However, as of version 0.1.0, Honcho's monkey-patching is simply a copy-paste of the ensure block of Fiber.run, so behavior should be predictable and even work in multi-threaded environments!

1 In accordance with erlang's parlance, process in this context refers to a program-level flow of execution. This may be actual OS processes, threads, fibers, or any other concurrent execution mechanism the language provides.

Notes

This project also monkey patches the Fiber class to allow supervisors to remotely kill off child fibers. This should be fairly safe, but could potentially cause issues. If you encounter anything abnormal, please file an issue so it can be addressed.

Usage

require "honcho"

sv = Honcho::Visor.new(strategy: Honcho::Strategy::ISOLATED)

puts "Starting ISOLATED strategy example. Press Ctrl+C to exit."

sv.start_supervised("permanent service", mode: Honcho::ProcessMode::PERMANENT, delay: 3.0) do
  puts "permanent service running. will never go down"
  i = 1
  loop do
    sleep(0.4)
    puts "permanent service iteration number: #{i}"
    i += 1
  end
end

sv.start_supervised("broken service", mode: Honcho::ProcessMode::PERMANENT) do
  sleep(1)
  puts "| broken service going down. will restart."
  raise "exit abnormally"
end

sv.start_supervised("one shot service", mode: Honcho::ProcessMode::ONE_SHOT) do
  sleep(5)
  puts "> one shot service going down. will not restart"
  raise "exit abnormally"
end

sv.run

Running this example will output:

Starting ISOLATED strategy example. Press Ctrl+C to exit.
permanent service running. will never go down
permanent service iteration number: 1
permanent service iteration number: 2
| broken service going down. will restart.
permanent service iteration number: 3
permanent service iteration number: 4
| broken service going down. will restart.
permanent service iteration number: 5
permanent service iteration number: 6
permanent service iteration number: 7
| broken service going down. will restart.
permanent service iteration number: 8
permanent service iteration number: 9
| broken service going down. will restart.
permanent service iteration number: 10
permanent service iteration number: 11
permanent service iteration number: 12
> one shot service going down. will not restart
| broken service going down. will restart.
permanent service iteration number: 13
permanent service iteration number: 14
| broken service going down. will restart.

For more examples, check out the samples directory.

Installation

dependencies:
  honcho:
    github: faultyserver/honcho

See Also

Earl is a library that implements Service objects for Crystal and provides much of the same functionality as Honcho, but does so by enforcing a structure on your application.

Earl is likely a better solution for your needs if you are: