class Schmooze::Base

Public Class Methods

new(root, env={}) click to toggle source
# File lib/schmooze/base.rb, line 43
def initialize(root, env={})
  @_schmooze_env = env
  @_schmooze_root = root
  @_schmooze_code = ProcessorGenerator.generate(self.class.instance_variable_get(:@_schmooze_imports) || [], self.class.instance_variable_get(:@_schmooze_methods) || [])
end

Protected Class Methods

dependencies(deps) click to toggle source
# File lib/schmooze/base.rb, line 10
def dependencies(deps)
  @_schmooze_imports ||= []
  deps.each do |identifier, package|
    @_schmooze_imports << {
      identifier: identifier,
      package: package
    }
  end
end
finalize(stdin, stdout, stderr, process_thread) click to toggle source
# File lib/schmooze/base.rb, line 32
def finalize(stdin, stdout, stderr, process_thread)
  proc do
    stdin.close
    stdout.close
    stderr.close
    Process.kill(0, process_thread.pid)
    process_thread.value
  end
end
method(name, code) click to toggle source
# File lib/schmooze/base.rb, line 20
def method(name, code)
  @_schmooze_methods ||= []
  @_schmooze_methods << {
    name: name,
    code: code
  }

  define_method(name) do |*args|
    call_js_method(name, args)
  end
end

Public Instance Methods

pid() click to toggle source
# File lib/schmooze/base.rb, line 49
def pid
  @_schmooze_process_thread && @_schmooze_process_thread.pid
end

Private Instance Methods

call_js_method(method, args) click to toggle source
# File lib/schmooze/base.rb, line 102
def call_js_method(method, args)
  ensure_process_is_spawned

  @_schmooze_stdin.puts JSON.dump([method, args])
  input = @_schmooze_stdout.gets
  raise Errno::EPIPE, "Can't read from stdout" if input.nil?

  status, message, error_class = JSON.parse(input)

  if status == 'ok'
    message
  else
    if error_class.nil?
      raise Schmooze::JavaScript::UnknownError, message
    else
      raise Schmooze::JavaScript.const_get(error_class, false), message
    end
  end
rescue Errno::EPIPE, IOError
  # TODO(bouk): restart or something? If this happens the process is completely broken
  raise ::StandardError, "Schmooze process failed:\n#{@_schmooze_stderr.read}"
end
ensure_packages_are_initiated(stdin, stdout, stderr, process_thread) click to toggle source
# File lib/schmooze/base.rb, line 72
def ensure_packages_are_initiated(stdin, stdout, stderr, process_thread)
  input = stdout.gets
  raise Schmooze::Error, "Failed to instantiate Schmooze process:\n#{stderr.read}" if input.nil?
  result = JSON.parse(input)
  unless result[0] == 'ok'
    stdin.close
    stdout.close
    stderr.close
    process_thread.join

    error_message = result[1]
    if /\AError: Cannot find module '(.*)'\z/ =~ error_message
      package_name = $1
      package_json_path = File.join(@_schmooze_root, 'package.json')
      begin
        package = JSON.parse(File.read(package_json_path))
        %w(dependencies devDependencies).each do |key|
          if package.has_key?(key) && package[key].has_key?(package_name)
            raise Schmooze::DependencyError, "Cannot find module '#{package_name}'. The module was found in '#{package_json_path}' however, please run 'npm install' from '#{@_schmooze_root}'"
          end
        end
      rescue Errno::ENOENT
      end
      raise Schmooze::DependencyError, "Cannot find module '#{package_name}'. You need to add it to '#{package_json_path}' and run 'npm install'"
    else
      raise Schmooze::Error, error_message
    end
  end
end
ensure_process_is_spawned() click to toggle source
# File lib/schmooze/base.rb, line 54
def ensure_process_is_spawned
  return if @_schmooze_process_thread
  spawn_process
end
spawn_process() click to toggle source
# File lib/schmooze/base.rb, line 59
def spawn_process
  process_data = Open3.popen3(
    @_schmooze_env,
    'node',
    '-e',
    @_schmooze_code,
    chdir: @_schmooze_root
  )
  ensure_packages_are_initiated(*process_data)
  ObjectSpace.define_finalizer(self, self.class.send(:finalize, *process_data))
  @_schmooze_stdin, @_schmooze_stdout, @_schmooze_stderr, @_schmooze_process_thread = process_data
end