class Isomorfeus::Speednode::Runtime::VM
Attributes
responder[R]
Public Class Methods
exit_node(socket, socket_dir, socket_path, pid)
click to toggle source
# File lib/isomorfeus/speednode/runtime/vm.rb, line 65 def self.exit_node(socket, socket_dir, socket_path, pid) VMCommand.new(socket, "exit", [0]).execute socket.close File.unlink(socket_path) if File.exist?(socket_path) Dir.rmdir(socket_dir) if socket_dir && Dir.exist?(socket_dir) if Gem.win_platform? # SIGINT or SIGKILL are unreliable on Windows, try native taskkill first unless system("taskkill /f /t /pid #{pid} >NUL 2>NUL") Process.kill('KILL', pid) rescue nil end else Process.kill('KILL', pid) rescue nil end rescue nil end
finalize(socket, socket_dir, socket_path, pid)
click to toggle source
# File lib/isomorfeus/speednode/runtime/vm.rb, line 58 def self.finalize(socket, socket_dir, socket_path, pid) proc do Isomorfeus::Speednode::Runtime.responders[socket_path].kill if Isomorfeus::Speednode::Runtime.responders[socket_path] exit_node(socket, socket_dir, socket_path, pid) end end
new(options)
click to toggle source
# File lib/isomorfeus/speednode/runtime/vm.rb, line 46 def initialize(options) @mutex = Mutex.new @socket_path = nil @options = options @started = false @socket = nil end
Public Instance Methods
attach(context, func)
click to toggle source
# File lib/isomorfeus/speednode/runtime/vm.rb, line 98 def attach(context, func) create_responder(context) unless responder command("attach", {'context' => context, 'func' => func }) end
create(context, source, options)
click to toggle source
# File lib/isomorfeus/speednode/runtime/vm.rb, line 90 def create(context, source, options) command("create", {'context' => context, 'source' => source, 'options' => options}) end
createp(context, source, options)
click to toggle source
# File lib/isomorfeus/speednode/runtime/vm.rb, line 94 def createp(context, source, options) command("createp", {'context' => context, 'source' => source, 'options' => options}) end
delete_context(context)
click to toggle source
# File lib/isomorfeus/speednode/runtime/vm.rb, line 103 def delete_context(context) command("deleteContext", context) end
eval(context, source)
click to toggle source
# File lib/isomorfeus/speednode/runtime/vm.rb, line 82 def eval(context, source) command("eval", {'context' => context, 'source' => source}) end
exec(context, source)
click to toggle source
# File lib/isomorfeus/speednode/runtime/vm.rb, line 86 def exec(context, source) command("exec", {'context' => context, 'source' => source}) end
start()
click to toggle source
def context_options(context)
command('ctxo', {'context' => context })
end
# File lib/isomorfeus/speednode/runtime/vm.rb, line 111 def start @mutex.synchronize do start_without_synchronization end end
started?()
click to toggle source
# File lib/isomorfeus/speednode/runtime/vm.rb, line 54 def started? @started end
Private Instance Methods
command(cmd, *arguments)
click to toggle source
# File lib/isomorfeus/speednode/runtime/vm.rb, line 195 def command(cmd, *arguments) @mutex.synchronize do start_without_synchronization unless @started VMCommand.new(@socket, cmd, arguments).execute end end
create_responder(context)
click to toggle source
# File lib/isomorfeus/speednode/runtime/vm.rb, line 169 def create_responder(context) start unless @started run_block = Proc.new do |request| args = ::Oj.load(request.chop!, mode: :strict) req_context = args[0] method = args[1] method_args = args[2] begin result = Isomorfeus::Speednode::Runtime.attached_procs[req_context][method].call(*method_args) ::Oj.dump(['ok', result], mode: :strict) rescue Exception => err ::Oj.dump(['err', err.class.to_s, [err.message].concat(err.backtrace)], mode: :strict) end end responder_path = @socket_path + '_responder' @responder = Thread.new do if ExecJS.windows? Isomorfeus::Speednode::AttachPipe.new(responder_path, run_block).run else Isomorfeus::Speednode::AttachSocket.new(responder_path, run_block).run end end Isomorfeus::Speednode::Runtime.responders[@socket_path] = @responder_thread @responder.run end
start_without_synchronization()
click to toggle source
# File lib/isomorfeus/speednode/runtime/vm.rb, line 119 def start_without_synchronization return if @started if ExecJS.windows? @socket_dir = nil @socket_path = SecureRandom.uuid else @socket_dir = Dir.mktmpdir("isomorfeus-speednode-") @socket_path = File.join(@socket_dir, "socket") end @pid = Process.spawn({"SOCKET_PATH" => @socket_path}, @options[:binary], @options[:source_maps], @options[:runner_path]) retries = 20 if ExecJS.windows? timeout_or_connected = false begin retries -= 1 begin @socket = Win32::Pipe::Client.new(@socket_path, Win32::Pipe::ACCESS_DUPLEX) rescue sleep 0.1 raise "Unable to start nodejs process in time" if retries == 0 next end timeout_or_connected = true end until timeout_or_connected else while !File.exist?(@socket_path) sleep 0.1 retries -= 1 raise "Unable to start nodejs process in time" if retries == 0 end @socket = UNIXSocket.new(@socket_path) end @started = true at_exit do begin self.class.exit_node(@socket, @socket_dir, @socket_path, @pid) unless @socket.closed? rescue # do nothing end end ObjectSpace.define_finalizer(self, self.class.finalize(@socket, @socket_dir, @socket_path, @pid)) Kernel.at_exit { self.class.finalize(@socket, @socket_dir, @socket_path, @pid).call } end