Mittwoch, 5. August 2009

Closures in Distributed Ruby

In this article I want to show how closures work with distributed ruby and what you have to do to make them work.
Here's a very simple server to start:
require 'drb'
 
class SimpleServer

 def initialize
   DRb.start_service('druby://localhost:9000', self)
 end
 
 def server_time
   Time.now
 end

end

SimpleServer.new
DRb.thread.join
In the constructor we start the drb service and register the server to localhost on port 9000. Then we have a very simple method, which just returns the time on the server, that we now want to call from our client. The last line prevents the programm to exit and keeps the server thread waiting for incoming requests.
require 'drb'

class SimpleClient 

 def initialize
   @remote = DRbObject.new(nil, 'druby://localhost:9000')
 end

 def time_on_server
   puts "Time on server #{@remote.server_time}"
 end

end

client = SimpleClient.new
client.time_on_server
In the client's constructor we get the remote object of the previous registered server. After that we can call the "time_on_server" method to print it on the client side.
Now let's add a method that uses a block parameter.
in the server:
  def time_on_client
    puts "Time on client #{yield}"
  end
and in the client:
  def client_time
    @remote.time_on_client { Time.now }
  end
Calling now "client_time" from the client, will raise a DRb::DRbServerNotFound error. The client fails to provide a drb proxy object for the server, which would need it to call the block on the client again. Blocks are bind to the environment, where they have been defined, in our case on the client.
All we have to do to make it work is starting also a drb service on the client side.
  def initialize
    DRb.start_service
    @remote = DRbObject.new(nil, 'druby://localhost:9000')
  end
So in Ruby we often have symetric roles, both sides need to act as client and server.

Keine Kommentare: