Slave-1.0.0

** PLEASE NOTE THAT THIS IS A DEVELOPMENTAL RELEASE **

SYNOPSIS

the Slave class forks a process and starts a drb server in the child
using
any object as the server. the process is detached so it is not
required
(nor possible) to wait on the child pid. a Heartbeat is set up
between the
parent and child processes so that the child will exit of the parent
exits
for any reason - preventing orphaned slaves from running
indefinitely. the
purpose of Slaves is to be able to easily set up a collection of
objects
communicating via drb protocols instead of having to use IPC.

typical usage:

 obj = AnyClass::new

 slave = Slave::new 'object' => obj

 p slave.object                  # handle on drb object
 p slave.uri                     # uri of the drb object
 p slave.socket                  # unix domain socket path for drb 

object
p slave.psname # title shown in ps/top

slaves may be configured via the environment, the Slave class, or via
the
ctor for object itself. attributes which may be configured include

 * socket_creation_attempts
 * pulse_rate
 * psname
 * debug
 * dumped

URIS

http://rubyforge.org/projects/codeforpeople/
http://codeforpeople.com/lib/ruby/slave

HISTORY

THIS RELEASE IS !! NOT !! BACKWARD COMPATIBLE. NOTE NEW CTOR SYNTAX.

1.0.0:

 - detach method also sets up at_exit handler.  extra protection 

from
zombies.

 - ezra zygmuntowicz asked for a feature whereby a parent could be 

notified
when a child exited. obviously such a mechanism should be both
async
and sync. to accomplish this the wait method was extended to
support a
callback with is either sync or async

     slave = Server.new{ Server.new }

     slave.wait and puts 'this is sync!'

     slave.wait(:non_block=>true){ 'this is async!' }

 - patch to getval from skaar<[email protected]>.  the impl dropped 

opts
delgating to the class method from the instance one.

SAMPLES

<========< samples/a.rb >========>

~ > cat samples/a.rb

 require 'slave'
 #
 # simple usage is simply to stand up a server object as a slave. 

you do not
# need to wait for the server, join it, etc. it will die when the
parent
# process dies - even under ‘kill -9’ conditions
#
class Server
def add_two n
n + 2
end
end

   slave = Slave.new :object => Server.new
   server = slave.object

   p server.add_two(40) #=> 42

~ > ruby samples/a.rb

 42

<========< samples/b.rb >========>

~ > cat samples/b.rb

 require 'slave'
 #
 # if certain operations need to take place in the child only a 

block can be
# used
#
class Server
def connect_to_db
“we only want to do this in the child process!”
@connection = :postgresql
end
attr :connection
end

   slave = Slave.new('object' => Server.new){|s| s.connect_to_db}

   server = slave.object

   p server.connection  #=> :postgresql
 #
 # errors in the child are detected and raised in the parent
 #
   slave = Slave.new('object' => Server.new){|s| s.typo} #=> raises 

an error!

~ > ruby samples/b.rb

 :postgresql
 ./lib/slave.rb:276:in `initialize': undefined method `typo' for 

#Server:0xb7573350 (NoMethodError)
from samples/b.rb:22:in `new’
from samples/b.rb:22

<========< samples/c.rb >========>

~ > cat samples/c.rb

 require 'slave'
 #
 # if no slave object is given the block itself is used to contruct 

it
#
class Server
def initialize
“this is run only in the child”
@pid = Process.pid
end
attr ‘pid’
end

   slave = Slave.new{ Server.new }
   server = slave.object

   p Process.pid
   p server.pid # not going to be the same as parents!
 #
 # errors are still detected though
 #
   slave = Slave.new{ fubar } # raises error in parent

~ > ruby samples/c.rb

 12244
 12245
 ./lib/slave.rb:276:in `initialize': undefined local variable or 

method fubar' for main:Object (NameError) from samples/c.rb:21:in new’
from samples/c.rb:21

<========< samples/d.rb >========>

~ > cat samples/d.rb

 require 'slave'
 #
 # at_exit hanlders are handled correctly in both child and parent
 #
   at_exit{ p 'parent' }
   slave = Slave.new{ at_exit{ p 'child' };  'the server is this 

string’ }
#
# this will print ‘child’, then ‘parent’
#

~ > ruby samples/d.rb

 "child"
 "parent"

<========< samples/e.rb >========>

~ > cat samples/e.rb

 require 'slave'
 #
 # slaves never outlive their parent.  if the parent exits, even 

under kill -9,
# the child will die.
#
slave = Slave.new{ at_exit{ p ‘child’ }; ‘the server is this
string’ }

   Process.kill brutal=9, the_parent_pid=Process.pid
 #
 # even though parent dies a nasty death the child will still print 

‘child’
#

~ > ruby samples/e.rb

 "child"

enjoy.

-a

Hi Ara-

On Oct 13, 2006, at 12:30 PM, [email protected] wrote:

  and sync.  to accomplish this the wait method was extended to  

support a
callback with is either sync or async

    slave = Server.new{ Server.new }

    slave.wait and puts 'this is sync!'

    slave.wait(:non_block=>true){ 'this is async!' }

Awesome thanks Ara!

# used

  server = slave.object

  p server.connection  #=> :postgresql
This part if killer too. Very nice to be able to run the block in

the child! I am getting a ton of use out of Slave. Thanks for the
killer library.

Cheers-
-Ezra

On Sat, 14 Oct 2006, Ezra Z. wrote:

Awesome thanks Ara!

no prob - it was a good idea

This part if killer too. Very nice to be able to run the block in the
child! I am getting a ton of use out of Slave. Thanks for the killer library.

great! test this one out though - i made quite few small changes, and
you
know how that goes!

let me know what you find…

have a good weekend.

-a