-
Notifications
You must be signed in to change notification settings - Fork 45
Implementation
The actual work of launching external processes and communicating with them is
performed by the so called drivers: modules implementing a specified set of
functions. Functions in the Porcelain
module delegate work to the currently
selected driver's implementations.
The basic functionality that provides a saner and more convenient API on top of
ports is implemented in the Porcelain.Driver.Basic
(or just Basic
)
driver.
Additional functionality that includes circumventing the "eof bug" and sending
signals to OS processes will be implemented in the Porcelain.Driver.Goon
(or
just Goon
) driver.
Suggestions of better names will be appreciated.
The following tasks are going to be performed by all drivers, so they should be implemented in a shared module.
-
splitting the shell-like invocation into program name and a list of arguments (
Porcelain.shplit
) (see this and this for reference) -
processing and validating given options (currently partly done in the
Porcelain
module) -
defining a set of Erlang port options shared accross all drivers
This section describes the details of the pure Elixir implementation of the Porcelain API.
It serves as a light shim on top of ports. The main responsibilities of the driver are:
- building the invocation of
Port.open
- implementing a receive loop to collect output from the program
The port is opened in stream mode to communicate directly with the external program.
The receive loop collects messages from the port and dispatches them to the caller according to the chosen output channel.
To implement the async API, the driver spawns additional processes as needed. The output received from the port connected to an external process is fed immediately to the target (where the target can be a file path, a file process, or a stream) or kept in memory until requested or discarded.
This section describes the details of interacting with the goon
middleman
from Elixir. See below for the description of goon
's implementation.
The main responsibilities of the driver are:
-
building the invocation of
Port.open
-
performing the handshake with
goon
to select the protocol for communications and perform any other required configuration (will most likely be implemented as a set of command-line flags and arguments to thegoon
program) -
implementing a receive loop to collect output from
goon
(reference) -
sending signals to the managed OS process
The port is opened in {:packet, 2}
mode. Then, the handshake is performed. In
case of failure, an error tuple is returned to the client. If the handshake
succeeded, the driver enters its receive loop and starts dispatching output to
the caller.
Sending signals is implemented by means of sending messages to the driver which will then forward them to the port program.
Implemented in Go, goon
will provide a lightweight solution for patching some
holes in the Erlang port functionality, namely:
- being able to interact with "eof-driven" programs
- being able to send signals to OS processes
It will be detected at run time by default, but the user should be able to
override the setting: to either never use goon
or to require goon
to be
present in $PATH
.
In terms of OS processes, the hierarchy when using the Goon driver will look as follows:
+-----------+
| Erlang VM |
+-----------+
||
\/
+------+
| Goon |
+------+
||
\/
+------------------+
| External program |
+------------------+
Arrows pointing down indicate the parent→child relationship between the OS processes.
The Go implementation will use packages from Go's stdlib to work with external processes in a portable way:
The program has to support the following command-line flags and arguments:
goon -proto <major>.<minor> -ack <string> -redir 1:2,2:1 <program> [<arg>...]
The options are as follows:
-
-proto
– protocol version number -
-ack
– arbitrary string, used during handshake -
-redir
– specify stdout (1) and stderr (2) redirection rules -
<program> [<arg>...]
– the invocation for external program
The actual implementation should conform to the Goex protocol specification.