Skip to content

Instantly share code, notes, and snippets.

@nat-n
Created May 3, 2014 21:17
Show Gist options
  • Save nat-n/399ca0530697982be2ca to your computer and use it in GitHub Desktop.
Save nat-n/399ca0530697982be2ca to your computer and use it in GitHub Desktop.
An experimental class wrapping druby to make it easy to spawn and control Distributed Ruby servers from within a ruby context. Thus allowing a ruby program to relatively painlessly spawn and control "worker" subprocesses.
#!/usr/bin/env ruby
require 'tempfile'
require 'drb/drb'
class DServer
attr_reader :active_server
attr_reader :service
attr_accessor :server_object_script
attr_accessor :server_uri
@@script_template = ["
require 'drb/drb'
require 'drb/acl'
", :server_object_script ,"
# Safety first!
# disable eval and co
$SAFE = 1
# only allow connections from 127.0.0.1
acl = ACL.new ['deny', 'all', 'allow', '127.0.0.1']
DRb.start_service('", :server_uri, "', FRONT_OBJECT, :tcp_acl => acl)
DRb.thread.join
"]
def initialize(server_object_script=nil, server_uri=nil)
@server_object_script = server_object_script
@server_uri = server_uri
end
# start the server by composing the script to a temp file and executing it
def start
unless @active_server
composed_server_script = @@script_template.map do |segment|
case segment
when Symbol
case segment
when :server_object_script then @server_object_script
when :server_uri then @server_uri
end
else
segment
end
end.join
script_file = Tempfile.new('drb-server-script')
script_file.write composed_server_script
script_file.close
@active_server = IO.popen "ruby #{script_file.path}"
# give popen a second to run before continuing
sleep 1
script_file.unlink
@service = DRbObject.new_with_uri @server_uri
DRb.start_service unless DRb.primary_server
end
self
end
# Check if this DServer is running
def active?
!!@active_server
end
# Don't forget to clean up your servers when you're done with them!
def kill
if @active_server
Process.kill 9, @active_server.pid
@active_server = nil
end
self
end
end
# -- # -- # -- # -- # -- EXAMPLE USAGE -- # -- # -- # -- # -- #
SERVER_URI = "druby://localhost:8788"
SERVICE_SCRIPT = "
class TimeServer
def get_current_time
return Time.now
end
end
FRONT_OBJECT = TimeServer.new
"
timeserver = DServer.new(SERVICE_SCRIPT, SERVER_URI).start
# it works if the time is printed
puts timeserver.service.get_current_time
timeserver.kill
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment