Forum: Ruby slave-1.2.1

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 Ara.T.Howard (Guest)
on 2007-04-28 00:43
(Received via mailing list)
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:

     slave = Slave::new{ AnyObject.new }

     slave.object                  #=> handle on drb object
     slave.uri                     #=> uri of the drb object
     slave.socket                  #=> unix domain socket path for drb
object
     slave.psname                  #=> title shown in ps/top

     object = slave.object

     value = object.any_method     #=> use the object normally

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

     * object : specify the slave object.  otherwise block value is
used.
     * socket_creation_attempts : specify how many attempts to create a
unix domain socket will be made
     * debug : turn on some logging to STDERR
     * psname : specify the name that will appear in 'top' ($0)
     * at_exit : specify a lambda to be called in the *parent* when the
child dies
     * dumped : specify that the slave object should *not* be
DRbUndumped (default is DRbUndumped)
     * threadsafe : wrap the slave object with ThreadSafe to implement
gross thread safety

URIS

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

HISTORY

   1.2.1:
     - jruby/ThreadSafe patches from skaar and ez.  using slave.rb with
jruby,
       how cool is that!?

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

       slave.shutdown

   ~ > 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
     samples/b.rb:22: undefined method `typo' for #<Server:0xb756ed18>
(NoMethodError)
       from ./lib/slave.rb:369:in `[]'
       from ./lib/slave.rb:369:in `initialize'
       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

     7971
     7972
     samples/c.rb:21: undefined local variable or method `fubar' for
main:Object (NameError)
       from ./lib/slave.rb:361:in `call'
       from ./lib/slave.rb:361:in `initialize'
       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"


   <========< samples/f.rb >========>

   ~ > cat samples/f.rb

     require 'slave'
     #
     # slaves created previously are visible to newly created slaves -
in this
     # example the child process of slave_a communicates directly with
the child
     # process of slave_a
     #
       slave_a = Slave.new{ Array.new }
       slave_b = Slave.new{ slave_a.object }

       a, b = slave_b.object, slave_a.object

       b << 42
       puts a #=> 42

   ~ > ruby samples/f.rb

     42


   <========< samples/g.rb >========>

   ~ > cat samples/g.rb

     require 'slave'
     #
     # Slave.object can used when you want to construct an object in
another
     # process.  in otherwords you want to fork a process and retrieve a
single
     # returned object from that process as opposed to setting up a
server.
     #
       this = Process.pid
       that = Slave.object{ Process.pid }

       p 'this' => this, 'that' => that

     #
     # any object can be returned and it can be returned asychronously
via a thread
     #
       thread = Slave.object(:async => true){ sleep 2 and [ Process.pid,
Time.now ] }
       this = [ Process.pid, Time.now ]
       that = thread.value

       p 'this' => this, 'that' => that

   ~ > ruby samples/g.rb

     {"that"=>7990, "this"=>7989}
     {"that"=>[7991, Fri, Apr 27 2007 16:38:30 -0600], "this"=>[7989,
Fri, Apr 27 2007 16:38:28 -0600]}


enjoy.

-a
Db524516a64318b0e937d41357c729eb?d=identicon&s=25 John Stoffel (johnstoffel)
on 2009-02-17 17:29
Ara.T.Howard wrote:
> 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.


Is this being maintained any more?  Should I be using some other module
for the same functionality in the future?  It's a nice tool to use, but
I'm going insane trying to debug issues and warnings with the code in my
Recursive Parallel directory descent tool.

Thanks,
John
This topic is locked and can not be replied to.