class Async::Container::Notify::Pipe

Implements a process readiness protocol using an inherited pipe file descriptor.

Constants

NOTIFY_PIPE

The environment variable key which contains the pipe file descriptor.

Public Class Methods

new(io) click to toggle source

Initialize the notification client. @parameter io [IO] An IO instance used for sending messages.

# File lib/async/container/notify/pipe.rb, line 48
def initialize(io)
        @io = io
end
open!(environment = ENV) click to toggle source

Open a notification client attached to the current {NOTIFY_PIPE} if possible.

# File lib/async/container/notify/pipe.rb, line 36
def self.open!(environment = ENV)
        if descriptor = environment.delete(NOTIFY_PIPE)
                self.new(::IO.for_fd(descriptor.to_i))
        end
rescue Errno::EBADF => error
        Console.logger.error(self) {error}
        
        return nil
end

Public Instance Methods

before_spawn(arguments, options) click to toggle source

Inserts or duplicates the environment given an argument array. Sets or clears it in a way that is suitable for {::Process.spawn}.

# File lib/async/container/notify/pipe.rb, line 54
def before_spawn(arguments, options)
        environment = environment_for(arguments)
        
        # Use `notify_pipe` option if specified:
        if notify_pipe = options.delete(:notify_pipe)
                options[notify_pipe] = @io
                environment[NOTIFY_PIPE] = notify_pipe.to_s
        
        # Use stdout if it's not redirected:
        # This can cause issues if the user expects stdout to be connected to a terminal.
        # elsif !options.key?(:out)
        #  options[:out] = @io
        #  environment[NOTIFY_PIPE] = "1"
        
        # Use fileno 3 if it's available:
        elsif !options.key?(3)
                options[3] = @io
                environment[NOTIFY_PIPE] = "3"
        
        # Otherwise, give up!
        else
                raise ArgumentError, "Please specify valid file descriptor for notify_pipe!"
        end
end
send(**message) click to toggle source

Formats the message using JSON and sends it to the parent controller. This is suitable for use with {Channel}.

# File lib/async/container/notify/pipe.rb, line 81
def send(**message)
        data = ::JSON.dump(message)
        
        @io.puts(data)
        @io.flush
end

Private Instance Methods

environment_for(arguments) click to toggle source
# File lib/async/container/notify/pipe.rb, line 90
def environment_for(arguments)
        # Insert or duplicate the environment hash which is the first argument:
        if arguments.first.is_a?(Hash)
                environment = arguments[0] = arguments.first.dup
        else
                arguments.unshift(environment = Hash.new)
        end
        
        return environment
end