Start Nodejs server with Phoenix App

I have an (internal) API written in Node.js. I’m writing a Phoenix app that would consume that API (before I eventually port the node app to elixir too). Currently I have to start the node and phoenix servers separately (on different ports). I would like to automatically start the node server when the phoenix server is started (and similarly close it when it shuts down).

I was about to go with Foreman to start both of them together, but I’d like to see how would I do this in Elixir. I think the way to do this is to wrap the nodejs app in a new elixir app and add it as a dependency (and among the list of applications) in my phoenix app - but I’m not exactly sure how to do this (I have no experience with GenServers) or even if this is the right approach.

So what is the Elixir way of doing this?

I’d probably just wrap up a Porcelein connection to it inside a GenServer.

Porcelain seems like an interesting project, but I’m still not sure how to “wrap its connection inside a Genserver”. I think I’ll have to use the Porcelain.spawn/2 method?

Basically yep, just communicate back and forth with it via your GenServer and kill the spawned node when ‘terminate’ is called. :slight_smile:

So far, I’ve been able to start the Node.js server using Porcelain, but I can’t stop it. I’ve tried:

  • Porcelain.Process.stop(proc)
  • Porcelain.Process.signal(proc, 9)
  • Process.exit(proc.pid, :kill)

This is how I’m starting my node server:

proc =  Porcelain.spawn("node", ["#{__DIR__}/node_app/server.js"], [out: :stream])

What is the proper way to kill a node.js server? Closing stdin? Sending certain signals?

Do note, if you are using ‘exit’ or ‘signal’ in Porcelain then you need the addon process that actually sends those signals. The instructions of Porcelain talk about it, let me find it, here: https://github.com/alco/porcelain#configuring-the-goon-driver

Also you should add config :porcelain, :goon_warn_if_missing, true to your config so that it will yell at you if goon is missing since node probably requires it.

Do note also, goon is not needed if you can close node.js by closing the stdin pipe.

Hitting Ctrl-C works (which I think is equivalent to SIGINT?)

Yeah but that is a very ugly way to kill servers (as in unless things are handled ‘juuuust right’ it can cause things to not be cleaned up right). What about (if you are in bash/zsh) hitting “Ctrl+d” , that sounds a null line through stdin, which closes most properly programmed things unless they are designed to persist (in which case they usually have a communication pipe or so).

1 Like

No, Ctrl+D doesn’t stop it. :confused:

Your reply gave me an idea. After doing a bit more research on signals, I modified my Node.js app to listen for EOF on STDIN and exit when it gets that. Now calling Process.exit/2 works!

Parallel Question on StackOverflow

1 Like

Nice! Might be useful to release that as an npm library? :slight_smile:

I don’t think so. It’s only 3 LOC and also mentioned in the Node.js docs. :blush:

1 Like