fredjean/simpler_workflow

View on GitHub
bin/swf

Summary

Maintainability
Test Coverage
#!/usr/bin/env ruby
# encoding: utf-8
# Mostly based on @ahoward's https://gist.github.com/3098500 with a few fixes and
# adjustments.

# setup
#
  require 'fileutils'

  pwd        = ENV['PWD']
  script     = File.expand_path(__FILE__).gsub(%r|\breleases/\d+\b|, 'current')
  rails_root = pwd.gsub(%r|\breleases/\d+\b|, 'current')

  Dir.chdir(rails_root)

  FileUtils.mkdir_p(File.join(rails_root, 'log', 'workflow'))
  FileUtils.touch(File.join(rails_root, 'log', 'workflow', 'pid'))

  quiet   = ARGV.delete('-q') || ARGV.delete('--quiet')
  mode    = ARGV.shift || 'run'

  pidfile = './log/workflow/pid'
  lockfile = File.open('./log/workflow/lock', "w")

  pid     = Integer(IO.read(pidfile).strip) rescue nil
  running = begin; Process.kill(0, pid); true; rescue Object; false; end

# go
#
  case mode
    when 'pid'
      puts(pid) if running

    when 'run'
      exit(42) unless lockfile.flock(File::LOCK_EX | File::LOCK_NB)

      exec "rake simpler_workflow:work"

    when 'start'
      exit(42) unless lockfile.flock(File::LOCK_EX | File::LOCK_NB)

      unless running
        FileUtils.rm_f(pidfile)

        pid = nil
        a, b = IO.pipe
        if fork
          b.close
          pid = Integer(a.read.strip)
          a.close
          puts(pid) unless quiet
          File.open(pidfile, "w") { |f| f.write(pid) }
          exit
        end
        exit!(0) if fork
        a.close
        b.puts(Process.pid)
        b.close

        {
          'stdin' => STDIN,
          'stdout' => STDOUT,
          'stderr' => STDERR,
        }.each do |basename, io|
          path = File.join("log/workflow/#{ basename }")
          begin
            open(path, 'a+'){|fd| io.reopen(fd)}
          rescue
            open(path, 'w+'){|fd| io.reopen(fd)}
          end
        end

        Process.setsid rescue nil
        File.umask(0) rescue nil

        exec "rake simpler_workflow:work"
      end

    when 'stop'
      if running
        begin
          Process.kill('QUIT', pid)
        rescue Errno::ESRCH
          nil
        end
      end

    when 'shutdown'
      if running
        alive = true

        %w( QUIT TERM ).each do |signal|
          begin
            Process.kill(signal, pid)
          rescue Errno::ESRCH
            nil
          end

          42.times do
            begin
              alive = Process.kill(0, pid)
              sleep(1 + rand) if alive
            rescue Errno::ESRCH
              alive = false
              break
            end
          end

          break unless alive
        end

        if alive
          begin
            Process.kill(-9, pid)
            sleep(rand)
          rescue Errno::ESRCH
            nil
          end
        end
      end

    when 'restart'
      exit! if fork
      exit! if fork
      system "#{ script } shutdown -q >/dev/null 2>&1"
      exec "#{ script } start -q >/dev/null 2>&1"

    when 'tail'
      exec "tail -F ./log/workflow/*"

    when 'pstree'
      exec "pstree #{ pid }" if running
  end

__END__