How to run web server (Warp) in async/concurrent mode? - haskell

I'm using https://hackage.haskell.org/package/warp-3.3.24/docs/Network-Wai-Handler-Warp.html
I don't know much about haskell concurrency. Say I would like to run two servers on different ports:
So I do:
do
Warp.run 3000 waiApp
Warp.run 3002 waiApp
Then server is run on 3000 is working, but it never gets to the next line.
I tried:
do
forkIO $ Warp.run 3000 waiApp
forkIO $ Warp.run 3002 waiApp
But it doesn't seem to work, each of them just stop after forking.
How to make it work properly? Also I want to allow the code below to be executed aslo.
UPD:
So the current solution is just to add
forever (threadDelay 1000)
in the end of the main, I wonder if it is the correct way to do this.

So, we should not allow the main thread to terminate. Something like this should work:
do
a1 <- Async.async $ Warp.run 3000 waiApp
a2 - Async.async $ Warp.run 3002 waiApp
...
Async.waitAny [a1, a2]

Related

How to make a npm stop that terminates the correct forever

I am using forever in npm start to start the node.js app, and I would like to have a npm stop to terminate the task. How can I stop the right task? I really like to not use stop all
Normally you want to assing a uid and then stop the process based on assign name, for example:
1. Starting:
forever start --uid=myapp index.js
2. Stopping only myapp:
forever stop myapp

Node command isn't doing anything

On my linode server that I have SSH'd into, when I type
$ node server.js
$
Nothing happens!
Even if the only contents of sever.js is util.log("HELLO");
Nothing is printed! Why is this happening?

Node.js forever with environment variable

The command I run on my server to start my node app is:
sudo IS_PROD=1 node app.js
I have forever installed but can't seem to pass in the environment variable.
sudo IS_PROD=1 forever node app.js
Doesn't seem to do the trick. I have tried several varieties of this. How do I either execute this command successfully or permanently set the environment variable?
First of all you should skip the node thing in you command, it should not be there, you should not be able to execute that. forever automatically starts your script using nodejs. Instead you should do like this;
sudo IS_PROD=1 forever app.js
Probably you, instead of starting your server in foreground, will want to start your server as a daemon. eg.
sudo IS_PROD=1 forever start app.js
This will create a process in the background that will watch your node app and restart it when it exits. For more information see the readme.
Both of these methods preserves the environment variables, just like when you are just using node.
app.js:
console.log(process.env.IS_PROD);
Using node (v0.8.21)
$ node app.js
undefined
$ IS_PROD=1 node app.js
1
$ sudo IS_PROD=1 node app.js
1
Using forever (v0.10.0)
$ forever app.js
undefined
$ IS_PROD=1 forever app.js
1
$ sudo IS_PROD=1 forever app.js
1
Documentation:
process.env
An object containing the user environment. See environ(7).

Find the port bound by snap-server

Using snap-server's httpServe method, I can setPort 0 to instruct the server to connect on the next free port. Unfortunately, once I have started the http server, I can't find any way to determine which port it actually started on. As an example, my first try started on port 2679 - is there any way to determine that number?
I wrote this patch, included with snap-server 0.9 and above, using which you can write:
let hook dat = print $ socketPort $ head $ getStartupSockets dat
let config = setStartupHook hook $ setPort 0 mempty
httpServer config ...
Now hook will be called after the server is ready, and will print the port it started on.
The Config structure has a bunch of getters, no?
getPort :: Config m a -> Maybe Int
Returns the port to listen on (for http)

Forever.js starting and restarting multiple scripts

My web app has 3 main node.js components: website, feeds and jobs.
To start these I am using forever:
//forever.js
var forever = require('forever');
function start(name){
forever.start( ['coffee', name + '.coffee'], { /* log options */ } )
};
start('website');
start('feeds');
start('jobs');
What I first noticed is that if I run script it wont run it as a daemon. ( Which is most likely normal )
node forever.js
So what I did next was run the forever.js script with forever. I am not sure if this is correct, there is also a forever.startDaemon so not sure which one I should use.
forever start forever.js
This works but the problem is that I would like to restart all the processes when a new version of my app is published. I am using git's post-receive hook to run the forever.js the first time but if I do this on each post-recieve it will just spawn 3 processes each time.
So I guess I need a way to restart 3 processes if they are already running. I thought to do this with forever.list but the documentation only say:
forever.list (format, callback)
Returns a list of metadata objects about each process that is being run using
forever. This method is synchronous and will return the list of metadata as such.
Only processes which have invoked forever.startServer() will be available from
forever.list()
First of all I am not sure what format means and second it expects a callback but then it says its synchronous. Which is a little confusing and I am not sure how to use list.
In the end all I want to do is start/restart 3 node.js processes on git's post-receive hook.
I think the best way to do this is:
forever start website.js
forever start feeds.js
forever start jobs.js
and then in your git post-receive hook:
forever restart website.js
forever restart feeds.js
forever restart jobs.js
Wrapping these node processes inside a single process is not a good idea. I now personally use Supervisord with monit instead of forever (supervisord is more stable & powerful than forever IMHO).
I do it like this:
#!/bin/sh
# Make sure we're in the right place
DIR=$(cd $(dirname "$0"); pwd)
cd $DIR
echo "[ I am $USER and I changed PWD to $DIR ]"
forever restart --spinSleepTime=2000 api_daemon.js || (forever start --spinSleepTime=2000 api_daemon.js && forever list)
Works like a charm, I never get duplicate processes using ./run.sh
To read logs, I use
tail -f /path/to/.log
Yes, it's possible. You need to use npm run forever command to run a script.
Add this to your package.json
"scripts": {
"forever" : "forever start api/api-server.js && forever start www/www-server.js && forever start upload/upload-server.js && forever start static/static-server.js",
"test": "echo \"Error: no test specified\" && exit 1"
}
You can create package.json using npm init

Resources