class RingyDingy

RingyDingy registers a DRb service with a Rinda::RingServer and re-registers the service if communication with the Rinda::RingServer is ever lost.

Similarly, if the Rinda::RingServer should ever lose contact with the service the registration will be automatically dropped after a short timeout.

Example

my_service = MyService.new
rd = RingyDingy.new my_service, :MyService
rd.run
DRb.thread.join

Constants

BROADCAST_LIST

Lists of hosts to search for ring servers. By default includes the subnet broadcast address and localhost.

VERSION

The version of RingyDingy you are using

Attributes

check_every[RW]

Interval to check the RingServer for our registration information.

identifier[R]

RingyDingy service identifier. Use this to distinguish between RingyDingys registering the same service.

object[R]

The object being provided by RingyDingy

thread[R]

RingyDingy run loop thread.

Public Class Methods

find(service_name, broadcast_list = BROADCAST_LIST) click to toggle source

Finds the first live service matching service_name on any ring server. Ring servers are discovered via the broadcast_list.

# File lib/ringy_dingy.rb, line 61
def self.find service_name, broadcast_list = BROADCAST_LIST
  RingyDingy::Lookup.new(broadcast_list).find service_name
end
new(object, service = :RingyDingy, name = nil, lookup = BROADCAST_LIST) click to toggle source

Creates a new RingyDingy that registers object as service with optional identifier name.

The lookup is used to locate a Rinda::RingServer. It can be unspecified (to look for a ring server in the BROADCAST_LIST), an Array of host names or IP address strings, a Rinda::RingFinger or RingyDingy::Lookup using a specific broadcast list or a reference to a Rinda::TupleSpace.

# File lib/ringy_dingy.rb, line 74
def initialize object, service = :RingyDingy, name = nil,
               lookup = BROADCAST_LIST
  DRb.start_service unless DRb.primary_server

  @identifier = [Socket.gethostname.downcase, $PID, name].compact.join '_'
  @object = object
  @service = service || :RingyDingy

  @check_every = 15
  @renewer = Rinda::SimpleRenewer.new

  @ring_finger = nil
  @ring_server = nil

  case lookup
  when Array then
    @ring_finger = Rinda::RingFinger.new lookup
  when Rinda::RingFinger then
    @ring_finger = lookup
  when RingyDingy::Lookup then
    @ring_finger = lookup.ring_finger
  else
    @ring_server = lookup
  end

  @thread = nil
end

Public Instance Methods

register() click to toggle source

Registers this service with the primary Rinda::RingServer.

# File lib/ringy_dingy.rb, line 105
def register
  reference = DRb::DRbObject.new(@object)

  tuple = [:name, @service, reference, @identifier]

  ring_server.write tuple, @renewer

  nil
end
registered?() click to toggle source

Looks for a registration tuple in the primary Rinda::RingServer. If a RingServer can't be found or contacted, returns false.

# File lib/ringy_dingy.rb, line 119
def registered?
  registrations = ring_server.read_all [:name, @service, nil, @identifier]
  registrations.any? { |registration| registration[2] == @object }
rescue DRb::DRbConnError
  @ring_server = nil
  return false
end
ring_server() click to toggle source

Looks up the primary Rinde::RingServer.

# File lib/ringy_dingy.rb, line 131
def ring_server
  return @ring_server unless @ring_server.nil?
  @ring_server = @ring_finger.lookup_ring_any
end
run(wait = :none) click to toggle source

Starts a thread that checks for a registration tuple every check_every seconds.

If wait is :none (the default) run returns immediately. If wait is :first_register then run blocks until the service was successfully registered.

# File lib/ringy_dingy.rb, line 158
def run wait = :none
  mutex = Mutex.new
  service_registered = ConditionVariable.new

  @thread = Thread.start do
    loop do
      begin
        register unless registered?

        mutex.synchronize do
          service_registered.signal
        end if wait == :first_register
      rescue DRb::DRbConnError
        @ring_server = nil
      rescue RuntimeError => e
        raise unless e.message == 'RingNotFound'
      end
      sleep @check_every
    end
  end

  mutex.synchronize do
    service_registered.wait mutex
  end if wait == :first_register

  self
end
stop() click to toggle source

Stops checking for registration tuples.

# File lib/ringy_dingy.rb, line 189
def stop
  @thread.kill
  return nil
end