Skip to content

Commit

Permalink
retry by failed
Browse files Browse the repository at this point in the history
  • Loading branch information
White-Green committed Aug 8, 2023
1 parent 4fde394 commit 730bd6b
Showing 1 changed file with 37 additions and 14 deletions.
51 changes: 37 additions & 14 deletions lib/execjs/pcruntime/context_process_runtime.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@ def initialize(runtime, source = '', options = {})
super

# @type [JSRuntimeHandle]
@runtime = runtime.create_runtime_handle

# load initial source to Context
@runtime.evaluate(source.encode('UTF-8'))
@runtime = runtime.create_runtime_handle source.encode('UTF-8')
end

# implementation of ExecJS::Runtime::Context#eval
Expand Down Expand Up @@ -56,22 +53,39 @@ class JSRuntimeHandle
# @param [Array<String>] binary Launch command for the node(or similar JavaScript Runtime) binary,
# such as ['node'], ['deno', 'run'].
# @param [String] initial_source_path Path of .js Runtime loads at startup.
def initialize(binary, initial_source_path, semaphore)
def initialize(binary, initial_source_path, compile_source, semaphore)
@semaphore = semaphore
Dir::Tmpname.create 'execjs_pcruntime' do |path|
# Dir::Tmpname.create rescues Errno::EEXIST and retry block
# So, raise it if failed to create Process.
@runtime_pid = create_process(path, *binary, initial_source_path) || raise(Errno::EEXIST)
@socket_path = path
end
@binary = binary
@initial_source_path = initial_source_path
@compile_source = compile_source
@recreate_process_lock = Mutex.new
initialize_socket
evaluate(@compile_source)
ObjectSpace.define_finalizer(self, self.class.finalizer(@runtime_pid))
end

# Evaluate JavaScript source code and return the result.
# @param [String] source JavaScript source code
# @return [object]
def evaluate(source)
post_request(@socket_path, '/eval', 'text/javascript', source)
socket_path = @socket_path
post_request(socket_path, '/eval', 'text/javascript', source)
rescue RuntimeError => e
raise e
rescue ProgramError => e
raise e
rescue StandardError => e
warn e.full_message
retry if socket_path != @socket_path
@recreate_process_lock.synchronize do
if socket_path == @socket_path
err = self.class.kill_process(@runtime_pid)
warn err.full_message unless err.nil?
initialize_socket
post_request(@socket_path, '/eval', 'text/javascript', @compile_source)
end
end
retry
end

# Create a procedure to kill the Process that has specified pid.
Expand All @@ -97,6 +111,15 @@ def self.kill_process(pid)

private

def initialize_socket
Dir::Tmpname.create 'execjs_pcruntime' do |path|
# Dir::Tmpname.create rescues Errno::EEXIST and retry block
# So, raise it if failed to create Process.
@runtime_pid = create_process(path, *@binary, @initial_source_path) || raise(Errno::EEXIST)
@socket_path = path
end
end

# Attempt to execute the block several times, spacing out the attempts over a certain period.
# @param [Integer] times maximum number of attempts
# @yieldreturn [Boolean] true iff succeed execute
Expand Down Expand Up @@ -228,8 +251,8 @@ def deprecated?

# Launch JavaScript Runtime and return its handle.
# @return [JSRuntimeHandle]
def create_runtime_handle
JSRuntimeHandle.new(binary, @runner_path, @semaphore)
def create_runtime_handle(compile_source)
JSRuntimeHandle.new(binary, @runner_path, compile_source, @semaphore)
end

private
Expand Down

0 comments on commit 730bd6b

Please sign in to comment.