Skip to content
Turn any Ruby object into a daemon controlling an army of sponges. http://af83.github.io/sponges
Ruby Shell
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
examples
lib
spec
.gitignore
Gemfile
LICENSE
README.md
sponges.gemspec

README.md

sponges

When I build workers, I want them to be like an army of spongebobs, always stressed and eager to work. sponges helps you build this army of sponges, to control them, and, well, to kill them gracefully. Making them stressed and eager to work is your job. :)

Basically, sponges is a ruby supervisor that forks processes and controls their execution and termination. For example the following will start a supervision daemon and 8 processes of "a_worker".

ruby a_worker.rb start -d -s 8

If you kill the supervisor it will cleanly terminate the child processes.

Internally, sponges strongly relies on Unix signals.

Is it any good?

Yes.

Installation

Ruby 1.9.2 (or superior).

Install it with rubygems:

gem install sponges

With bundler, add it to your Gemfile:

gem "sponges"

Usage

In a file called example.rb:

# The worker class is the one you want to daemonize.
#
require 'sponges'

class Worker
  def run
    # Trap the HUP signal, set a boolean to true.
    trap(:HUP) {
      Sponges.logger.info "HUP signal trapped, clean stop."
      @hup = true
    }
    Sponges.logger.info Process.pid
    if @hup # is true, we need to shutdown this worker
      Sponges.logger.info "HUP signal trapped, shutdown..."
      exit 0 # everything's fine, we can exit
    else # this worker can continue its work
      sleep rand(20)
      run
    end
  end
end

Sponges.configure do |config|
  config.logger        = MyCustomLogger.new   # optionnal
  config.redis         = Redis.new            # optionnal
  config.size          = 3
  config.daemonize     = true
  config.after_fork do
    puts "Execute code when a child process is created"
  end
  config.on_chld do
    puts "Execute code when a child process is killed"
end

# Register a pool named "worker_name".
#
Sponges.start "worker_name" do
  Worker.new({some: args}).run
end

See the help message :

ruby example.rb

Start workers :

ruby example.rb start

Start workers and daemonize them:

ruby example.rb start -d

Start 8 instances of the worker and daemonize them:

ruby example.rb start -d -s 8 # By default, size equals cpu core's size.

Retart gracefully 4 instances of the worker, with a timeout of 3 seconds and daemonize them:

ruby example.rb restart -g -d -s 4 -t 3

Stop workers with a QUIT signal :

ruby example.rb stop

Stop workers with a KILL signal :

ruby example.rb kill

Stop workers with a HUP signal :

ruby example.rb stop -g -t 5

In this case, you will have to trap the HUP signal, and handle a clean stop from each workers. The point is to wait for a task to be done before quitting. A timeout can be specify with the -t option. When this timeout is hited, the process is killed.

Increment worker's pool size :

ruby example.rb increment # will add a worker to the pool.

Decrement worker's pool size :

ruby example.rb decrement # will remove a worker to the pool.

Show a list of workers and their children.

ruby example.rb list

Stores

sponges can store pids in memory or in redis. Memory is the default store. The list command is not available with the memory store.

To select the redis store, you need to add nest to your application's Gemfile, and do the following.

gem "sponges"
Sponges.configure do |config|
  config.store         = :redis
end

Acknowledgements

sponges would not have been the same without Jesse Storimer and his awesome book about Unix.

Copyright

MIT. See LICENSE for further details.

Something went wrong with that request. Please try again.