Я использую gem paperclip с jruby, у меня проблема с памятью из-за способа, которым paperclip выполняет вызовы ОС при работе в среде Java. Внутренне он использует gem terrapin для выполнения вызовов, и при работе на JVM он не поддерживает предоставленный ProccessRunner или PosixRunner, поэтому, когда вызов выполняется стандартным способом (обратные ссылки), процесс rails раздвоены обычным способом. Проблема в том, что когда происходит разветвление, стек из родительского процесса должен быть скопирован в дочерний процесс, что является проблемой в этой среде, потому что jruby слишком требователен к памяти.
PosixRunner поддерживается, если установлен gem posix-spawn , но он не совместим с jruby. Поэтому я пытаюсь адаптировать PosixRunner для создания SpoonRunner, который использует гем spoon , который совместим с jruby и делает то же самое, что и posix-spawn.
Это хороший подход? Кто-то сделал это?
Проблема в том, что я не могу понять, как работать с файловыми дескрипторами, чтобы получить выходное значение выполняемой команды. Я был бы очень признателен за помощь с этим =)
Пожалуйста, проверьте комментарии к коду ниже:
module Terrapin
class CommandLine
class SpoonRunner
def self.available?
return @available unless @available.nil?
@available = spoon_gem_available?
end
def self.supported?
available?
end
def supported?
self.class.supported?
end
def call(command, env = {}, options = {})
pipe = MultiPipe.new
pid = spawn(env, command, options.merge(pipe.pipe_options))
pipe.read_and_then do
waitpid(pid)
end
pipe.output
end
private
def spawn(env, command, options)
# spoon gem example
# file_actions = Spoon::FileActions.new
# file_actions.close(1)
# the first argument is file_descriptor
# file_actions.open(1, "/tmp/ls.out", File::WRONLY | File::TRUNC | File::CREAT, 0600)
# spawn_attr = Spoon::SpawnAttributes.new
# pid = Spoon.posix_spawn('/usr/bin/env', file_actions, spawn_attr, %w(env ls -R))
puts "OPTIONS: #{options.inspect}"
# OPTIONS: #<IO:fd 27>
# why do I have to specify the file descriptor and the path, if the fd already exists
# does it mean it is already associated to a path ? Is there a way I can use a random
# one here and also an unique file name in order to keep things thread safe ?
# I guess maybe I have to use the fd passed in options here and write on this file
# that already exists, how can I do that ?
fd = ?
path = ?
flags = ?
file_actions = Spoon::FileActions.new
# do I have to close it first ?
file_actions.close(fd)
file_actions.open(fd, path, flags, 0600)
spawn_attr = Spoon::SpawnAttributes.new
pid = Spoon.posix_spawn(hash_to_path_env(env), file_actions, spawn_attr, [command])
end
def hash_to_path_env(hash)
# TODO
return ""
end
def waitpid(pid)
Process.waitpid(pid)
end
def self.spoon_gem_available?
require 'spoon'
true
rescue LoadError
false
end
private_class_method :spoon_gem_available?
end
end
end
Спасибо!