Module: Lifeline

Defined in:
lib/lifeline.rb

Defined Under Namespace

Classes: LifelineRakeTask

Instance Method Summary collapse

Instance Method Details

#define_lifeline_tasks(namespace, &block) ⇒ Object

A method that defines 3 rake tasks for doing lifelines:

  • namespace:run runs the specified block

  • namespace:lifeline a lifeline for executing only a single copy of namespace:run at a time

  • namespace:terminate a task for terminating the lifelines

Parameters:

  • namespace (String, Symbol)

    the namespace to define the 3 tasks in

  • &block

    a block which defines the body of the namespace:run method

Raises:

  • (ArgumentError)

    if you do not pass in a block argument



129
130
131
# File 'lib/lifeline.rb', line 129

def define_lifeline_tasks(namespace, &block)
  LifelineRakeTask.new(namespace, &block)
end

#get_process_listObject



7
8
9
10
11
12
13
14
15
16
17
# File 'lib/lifeline.rb', line 7

def get_process_list
  processes = %x{ps ax -o pid,command}

  return nil if processes.nil?

  processes.split(/\n/).map do |p|
    if p =~ /^(\d+)\s(.+)$/
      {:pid => $1.to_i, :command => $2.strip}
    end
  end.compact
end

#lifelineObject

A method for executing a block of code only if there is no other process with the same command running. This is useful if you want to have a perpetually running daemon that only executes once at a time. It uses the process name returned by ps ax to see if there is a process with the same command name but a different PID already executing. If so, it terminates without running the block. NOTE: since it uses the command name returned from ps ax, it us up to to you to name the process containing this code with a distinctly unique name. If two separate Rails projects both have a rake lifeline task they WILL interfere with each other. I’d suggest prefixing with the project name (ie, doc_viewer:lifeline) to be sure

Parameters:

  • &block

    a block which is executed if there is not already a lifeline running.

Raises:

  • (ArgumentError)

    if you do not pass in a block argument



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/lifeline.rb', line 29

def lifeline
  if !block_given?
    raise ArgumentError, "You must pass in a block to be the body of the run rake task"
  end

  my_pid = $$
  processes = get_process_list

  if processes.nil? || processes.empty?
    raise "No processes being returned by get_process_list. Aborting!"
  end

  myself = processes.detect {|p| p[:pid] == my_pid}
  if myself.nil?
    raise "Unable to find self in process list. This is bizarre to say the least. Exiting"
  end

  # there isn't already another process running with the same command
  if !processes.any? {|p| p[:pid] != my_pid && p[:command] == myself[:command]}
    yield
  end
end