Skip to content

Instantly share code, notes, and snippets.

@robmckinnon
Last active March 19, 2024 11:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robmckinnon/10297a89c6dd0f21b2115a71458303c5 to your computer and use it in GitHub Desktop.
Save robmckinnon/10297a89c6dd0f21b2115a71458303c5 to your computer and use it in GitHub Desktop.
A GenServer implementation that starts a Node.js server process using Elixir ports.
defmodule NodeProcess.Server do
@moduledoc """
A GenServer implementation that starts a Node.js server process using Elixir ports.
"""
# Elixir automatically defines callbacks not overriden
use GenServer
@doc """
Called when application started via application.ex.
"""
def start_link(initial_value) do
GenServer.start_link(__MODULE__, initial_value, name: __MODULE__)
end
@doc """
Port spawns executable to run node server process via wrapper shell script.
An `enoent` error means FileName specified in {spawn_executable, FileName}
does not point out an existing file.
Docs for Port here: https://hexdocs.pm/elixir/Port.html
Docs for open_port options here: http://erlang.org/doc/man/erlang.html#open_port-2
"""
def init(:ok) do
{:ok, %{port: start_port()}}
end
@doc """
Close port when the genserver is about to exit.
"""
def terminate(_reason, %{port: port}) do
Port.close(port)
end
defp start_port do
js_file = "#{__DIR__}/../../../../../your-node-app/index.js"
# Elixir documentation recommends use of wrapper script
# to prevent zombie processes.
# See: https://hexdocs.pm/elixir/Port.html#module-zombie-processes
process_wrapper = "#{__DIR__}/../../wrapper.sh"
Port.open({:spawn_executable, process_wrapper}, [
{:args, ["node", js_file]}
])
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment