Created
May 3, 2014 21:17
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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