Have a heroku app running on free tier that is working fine (it's a nodejs/express rest app).
Trying to add a clock process that fetches some content via https request and saves that content locally on the server.
It runs famously when I run locally (heroku local).
When I deploy to heroku, it doesn't run at all (the web app runs fine.)
I tried reducing the app to a simple case that only does a console.log() on the timer tick, but - nothing.
I also tried specifying the clock process as a worker in the Procfile - heroku doesn't see it (but heroku local does...).
My understanding is this is supposed to work ok in the free tier, but I'm having doubts.
Here's my (simple) Procfile:
web:npm start
clock:npm run start-clock
the scripts part of my package.json:
"scripts": {
"start": "node ./bin/www",
"start-clock": "node ./bin/clockproc.mjs"
},
and the simplified clockproc.mjs file (I'm using the node-cron package:
import cron from 'node-cron';
const TESTING = true;
const INTERVAL = TESTING? "*/15 * * * * *" : "0 10 * * *";
let task = cron.schedule(INTERVAL, async () => {
console.log("==> got a a tick...")
});
task.start();
Any clue why this isn't working?
Related
I use a web server (o2Switch) who use a Cpanel interface, my nodejs app is running with the setup node.js module.
My rest api use Nodejs with express and a database mongoDb atlas, my front is a Vuejs app, everythings works fine in production, but i have one cron with node-cron package:
// scripts/myscript.js
const cron = require('node-cron');
const script = cron.schedule('00 20 * * *', async () => {
console.log('PASSED')
},
{
scheduled: true,
timezone: "Europe/Paris"
}
);
script.start()
The script is import inside app.js:
// Scripts
require('./scripts/myscript')
My nodecron works fine in local and i don't have any trouble, but on production is not executed.
I do a lot of test:
It's 10:00(am) and i setup my cron on 05 10 * * *, this will work. But is never reexecuted the following day.
It's 10:00(am) and i setup 00 12 * * * this will never works.
I setup every minute * * * * * this works every minute.
What is seems, is my server is like standby after a couple of hours (i don't know if it's possible).
My vuejs app works fine at any time, the request works and do not have trouble.
Good day,
my very basic Nodejs app is deployed on a Google Cloud App Engine instance is not starting. The app works locally, deployment with app deploy runs without error - and on the app instance the app runs successfully when started manually through Cloud shell (with >npm start).
However, as soon as the Cloud Shell is closed my app is dead. What am I missing? How do I start-up the app to run permanently?
The app consists of
bot4.js file,
npm dependencies
app.yaml
package.json
app.yaml:
runtime: nodejs8
handlers:
- url: /
script: auto
package.json:
{
"name": "blexplorer",
"version": "1.0.0",
"description": "",
"main": "bot4.js",
"scripts": {
"start": "node bot4.js"
},
"author": "oystersauce",
"license": "ISC",
"dependencies": {
"discord.js": "^11.4.2",
"request": "^2.88.0"
}
}
Again, the app is running fine when started through the Cloud Shell but no longer, as soon as the Cloud Shell is closed. Also, it's a super simple discord-bot - hence there is no front-end whatsoever.
EDIT:
this is how I thought I started the app manually - but what I did here is starting the app within the cloud shell and not on the app instance:
here is how I deploy the app:
From GAE perspective the cloud shell is simply a shell on a "local" development machine which just happens to be hosted in the cloud. The instance running the cloud shell has no special relationship with GAE whatsoever.
What you're doing when running npm start is not actually starting the GAE instance, you're just starting a "local" execution of your service, just like when you'd be doing the same on your local machine.
With your configuration GAE should start your app automatically as soon a request for it is received. On an app with a frontend just clicking on the link you circled in the snapshot would get you on it. Since yours doesn't have a frontend it would probably be just started, but you'd have to rely on the dashboard info and/or your app's logs to confirm it is running.
I want a Nodejs application running on Heroku to run a task every 30 seconds. I use Heroku scheduler for another task but that's because it runs once a day and Scheduler seems fine for that, but to run at this interval it is not suitable.
So I have installed node-cron and setup a job that would run every 30 seconds, daily, between 11am and 6pm (I am basically calling an api and then updating a database), locally I can run this fine with node cron.js
cron.js
const cron = require('node-cron');
const task = require('./scripts/task');
cron.schedule('*/30 * 11-18 * * *', () => {
console.log('Running Function');
task.runFunction();
});
I'm not 100% sure how to run this on Heroku, from their docs they specify this kind of setup (configured in Procfile):
web: node web.js
worker: node worker.js
clock: node clock.js
Current Procfile
web: node server.js
Is it a case of changing my cron.js to clock.js ? and then having something in a worker.js file? (though unsure as to what).
You should probably change the clock.js to cron.js, or, as you say, rename cron.js to clock.js.
web: node web.js
worker: node worker.js
clock: node cron.js
Also, I'm not sure your cron.js is set up correctly. From the documentation on node-cron, it looks like you might need something that looks like this:
const CronJob = require('../lib/cron.js').CronJob;
console.log('Before job instantiation');`
const job = new CronJob('*/30 * 11-18 * * *', () => {
console.log('Running Function');
task.runFunction();
});
console.log('After job instantiation');
job.start();
You don't need this line worker: node worker.js if in your cron.js you don't tell him to do somethings with this worker. (I don't know what runFunctions() do). And you don't even need to add the first line if your application is just cron jobs.
So you can just have this Profile :
clock: cron.js
You can change clockto cron if you want. It doesn't mean: docs.
I've started a new app with create-react-app, and ejected from that. I made a small express server as follows:
const express = require('express');
const app = express();
if(process.env.NODE_ENV === 'production') {
app.use(express.static('build'));
}
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server started at: http://localhost:${port}/`);
});
In package.json I've added a line, "proxy": http://localhost:3000", as well as switching the commands:
"scripts": {
"run": "npm-run-all -p watch-css start-js",
"start": "node server.js",
},
run used to be start.
However now of course when I run npm start and go to localhost:3000, I get Cannot GET /. I need this server to receive and return local API calls I'll be making from my app, but I also want it to run a hot-reloading dev server just like the old npm start (now npm run) command did. How do I do this?
Some time ago I made a fork of the create-react-app repository adding webpack watch option because of this same reason. It might help you.
Just to add more info, I really invested time looking on how to get webpackdevserver to build the "bundle.js", and found that it is not possible because it loads the bundle into memory but doesn't persist it, so the file is never created. The only way available is the webpack watch option but, I don't understand why the create-react-app team can't add it to the repo, it's a really requested feature, and there are more forks than mine that solves this issue. So, you have three options:
Use the proxy server in package.json (if it works)
Make your own fork and add the watch option, or use an existing one
Don't use create-react-app
I'd like to start an app in two different ways depending on the environment.
In package.json:
"scripts": {
"start": "node start.js"
}
Then in the script check the environment variable and execute the correct command:
// start.js
var env = process.env.NODE_ENV;
if (env === 'development') {
//run './node_modules/.bin/nodemon main.js'
}
if (env === 'production') {
//run 'node main.js'
}
//do I need to exit?
process.exit(1);
Is exec, fork, or spawn ideal here? I need no communication between start.js and the main.js, and I want the least overhead. I want it to be as close to running the environment specific command directly. My inclination is fork because it will start a new process and the parent will terminate.
UPDATE: I am not interested in alternative solutions that use multiple npm commands. I specifically want to understand the pros/cons/resource use/performance implications of starting one node script from another using the various child_process methods.
I tend to do something like:
var env = process.env.NODE_ENV || 'development';
right in the main bootstrap application file (app.js, main.js, start.js or whatever you named it) because my usual use case is development work locally. So if nothing is set, it uses development, and if I have set an environment variable explicitly it uses that (usually only set for production, but could be anything including test etc).
Then for production, you would just need to set the NODE_ENV environment variable (which cloud services like Heroku make really simple to set up when deploying to the live environment too).
Another pattern you sometimes see is:
var env = process.env.NODE_ENV = process.env.NODE_ENV || 'development';
This is actually also updating the process.env.NODE_ENV assigned value, which means if you have other places also checking for the value of proces.env.NODE_ENV then you don't have to keep also using the "|| 'development'" check. It is not a pattern I tend to use, but you will see it in the wild.
Your npm scripts entry looks good, but there is nothing stopping you from defining others, calling out to shell scripts, setting env variables etc either.
If you are going to have one for production, I'd recommend making that explicit:
eg.In package.json:
"scripts": {
"start": "npm run dev"
"dev": "nodemon start.js",
"prd": "NODE_ENV=production node start.js"
}
That way, there is no confusion as you have to run either:
npm run dev
// same as npm start
or
npm run prd
Above, our dev environment is executed with nodemon, and our production environment with node as requested.
Update Based ON OP Feedback
which child_process method is best to start your main node app from. That was the main point of my question
What you are asking is atypical - however, there are of course options available:
If you wanted to background the node instance, then easy to control this from the command line via bash (&) etc.
However, if you really wish to do this, then in the past I have opted to use an NPM module - cluster.
npm install cluster
This allows you to spawn child instances from a master process - in your case just set the child instance count to 1.
var cluster = require('cluster')
, app = require('./main');
cluster(app)
.set('workers', 1)
// other configuration here
Finally, if you don't wish to use cluster, and really the question was more along the lines of "how to start another node.js application inside node then:
Use child_process.fork(). It is similar to spawn(), but is used to create entire new instances of V8. Therefore it is specially used for running new instances of Node.
var fork = require('child_process').fork;
var child = fork('./main');
There are further options, please see the documentation for details.
i think the approach not suitable.
in package.json
{
...
"scripts": {
"start": "NODE_ENV=production node ./app"
}
...
}
an then
npm start
UPDATE 1
If you are in windows machine just use it like this
set NODE_ENV=development&& nodemon server.js
If your machine is not a windows machine, use this
{
...
"scripts": {
"start": "NODE_ENV=development nodemon ./src/server/app.js"
}
...
}
The difference among spawn(), exec() and fork() of child_process as below
require('child_process').spawn() starts sending back data from the child process in a stream as soon as the child process starts executing. When you run this command, it send a system command that will run on its own process rather than executing code within your node process. In this no new V8 instance will be created and only one copy of the node module will be active on the processor. It is used when you want the child process to return large amount of data to Node.
require('child_process').fork() is a special instance of spawn thats runs a new instance of the V8 engine. Which actually means you are creating multiple workers running on the same Node code base for different task.
require('child_process').exec() returns a buffer from the child process. The default buffer size is 200k. It is asynchronous, but it waits for the child process to end and tries to return all the buffered data at once. If your return data from the child process is greater than 200k then you will get maxBuffer exceeded.
According to the source code of PM2
var exec = require('child_process').exec;
The child_process.exec is used to start node.js app. PM2 also has cluster mode, which culster.for() is used here. cluster.fork is implemented on top of child_process.fork.
if (cluster.isMaster) {
// Master:
// Let's fork as many workers as you have CPU cores
for (var i = 0; i < numCPUs; ++i) {
cluster.fork();
}
} else {
// Worker:
// Let's spawn a HTTP server
// (Workers can share any TCP connection.
// In this case its a HTTP server
...
}
IMO, the PM2 is one good option to start node.js app. It also can start node.js in development mode with PM2-dev. More details could be found here.
Source:
http://www.codingdefined.com/2014/08/difference-between-fork-spawn-and-exec.html
https://nodejs.org/api/cluster.html#cluster_cluster_fork_env