Make async node script run forever - node.js

I searched a lot, but have not found the specific solution to my problem yet.
I have an async function that polls a database as node script that runs forever when using node 12, but in v14 the implementation changed and it closes immediately after running once.
(async function pollDatabase() {
const db = new Db();
return async.forever(async function (pollFn) {
const query = "SELECT * FROM templates WHERE data->>'isProcessed'='0' LIMIT 1;";
const templates = await db.query(query);
if (!templates || !templates.length) {
setTimeout(pollFn, 1000);
return;
}
await doSomethingWithTemplateAndReExecuteThisFunction(templates[0], pollFn);
});
})();
The weird thing is that for example an express server just stays running, but I have not figured out yet how that works. I was not planning to convert this background script to a server. Any thoughts on what would be the best way to make this run forever as some kind of background task? At the moment it is a docker container containing just this script.

I have solved it myself in the end. I don't know exactly why it happened with the switch to Node 14, but the combination of an outdated pg-promise and bluebird library seems to have been the culprit. I guess it probably has to do with the way Promises are now handled in Node 14.
Old versions:
pg-promise#3.2.6 and bluebird#2.10.2
New versions:
pg-promise#^10.9.4 with the native Promise implementation

Related

setTimeout() in node.js wont take effect inside listener

Im trying to setup a simple server to poke a database every 5 seconds and fetch data from it.
I've built a dummy function called "check_pairs" just to make sure that the setTimeout function is working, but it doesn't seems to make the timeout, it just prints without delays
any idea why is that? Im also importing the current imports and using node version v19.6.0
Thanks in advance :)
You don't wait for the setTimeout promise to resolve. Try this:
async function check_pair() {
while (true) {
console.log("Checking pairs");
await setTimeout(1000);
}
}

Managing multiple processes within a NodeJS application

Let's say I'd want to control (start/stop) several other NodeJS scripts from within one "main" NodeJS app. However, not necessarly NodeJS Scripts exclusively, but also simple bash scripts.
I'm looking into the following solution, using execa
// simplified
const managedProcesses = [];
async function Start (pkg) {
const runningProcess = await execa(pkg.run_command, {
cwd : pkg.path
});
return runningProcess;
}
async function Stop (pkg) {
// somehow stop the child process
return
}
const someProcess = await Start({
run_command : 'node app.js',
path : './path/to/my/script/'
});
// Keep Reference of process
managedProcesses.push(someProcess);
I first thought pm2 would be a viable solution, but I guess this would only fit for NodeJS-only scripts.
What Problems could I run into using the approach above ?
Should I consider moving forward with this idea ?
For node.js subprocesses there is the cluster module and I strongly recommend using this. For general subprocesses (e.g. bash scripts as you mentioned) you have to use child_process (-> execa). Communication between processes may then be accomplished via grpc. Your approach is fine, so you can consider moving forward with it.
I decided to go full with pm2 for the time being, as they have an excellent programmatic API - also (which I only just learned about) you can specify different interpreters to run your script. So not only node apps are possible but also bash, python, php and so on - which is exactly what I am looking for.

Run main process as child_process

I am having troubles with getting child_process working with Atom Electron. First of all, I am using the pre-compiled binary app that you can download from Electron's website:
I am using the usual pre-compiled binary on Mac OS X.
In myapp.app/Contents/Resources I made a folder app as described.
I added a brief package.json inside it, setting index.js as main script.
Now, if I add to index.js the following snippet:
'use strict';
var electron = require('electron');
var app = electron.app;
const BrowserWindow = electron.BrowserWindow;
var mainWindow;
function createWindow () {
mainWindow = new BrowserWindow({width: 800, height: 600});
mainWindow.loadURL('file://' + __dirname + '/index.html');
mainWindow.webContents.openDevTools();
mainWindow.on('closed', function()
{
mainWindow = null;
});
}
app.on('ready', createWindow);
app.on('window-all-closed', function () {
if (process.platform !== 'darwin')
{
app.quit();
}
});
app.on('activate', function () {
if (mainWindow === null)
{
createWindow();
}
});
(that is basically the example code to get things working) everything works fine. I get the window and I can get it to do basically anything.
Now, for reasons related to updates, I am in need to slightly change this paradigm. What I would need is to be able to perform several tasks from index.js without any need to do any gui operation (it should be some sort of daemon) and then to start some child.js script as a child_process from index.js. child.js should be able to open windows and all the rest.
So here was my naive try. I just cut and pasted the example snippet above in child.js, then edited index.js into the following:
var child_process = require('child_process');
var my_child = child_process.fork(__dirname + '/child.js');
Quite minimal, right? Hoped it would work, but it didn't. When I double click on my pretty app, nothing happens. I bet I am doing something wrong in a trivial way, but I wouldn't be able to tell what.
Update 1 I moved this out of my package so that I could get console.logs. child.js dies with an error at require('electron'): it doesn't seem to be able to find it.
Update 2: I listed the environment variables in child.js and noticed a ATOM_SHELL_INTERNAL_RUN_AS_NODE = 1. I thought I should turn that to 0, but nothing changed.
In Electron child_process.fork() will spawn the child with the ATOM_SHELL_INTERNAL_RUN_AS_NODE environment variable set, which means that no Chromium features will be available in the child process (so no Electron built-in modules), all you'll get is the vanilla Node runtime plus a patched fs that can read inside ASAR files. If you look at the code for child_process.fork() you'll see there's no way to override the value of ATOM_SHELL_INTERNAL_RUN_AS_NODE. If you can, use child_process.spawn() instead, failing that I guess you could try opening an issue and asking if the Electron team will be open to modifying the current behavior.

Node program with oriento does not exit after select

From within node.js I use the oriento module to access a OrientDB. In principle everything works fine, the only thing is the program dos not exit as it should. Here is the example:
const oriento = require("oriento");
const server = oriento({});
const db = server.use(dbname);
db.select("#rid").from("codelists").limit(1).scalar().then(function (result) {
console.dir(result);
}).finally(function () {
db.close();
server.close();
console.info("finished");
});
The programm executes the select, then the "then" and finally the "finally" clauses. All fine. But it does not exit. There seems to be something hanging on the event loop. But what? And how can I get rid of it? The problem actually is worse then just "press Ctrl-C" or have a process.exit() when everything is done, because the code is supposed to run within a unit test, where I cannot call exit. Any suggestions?
The problem is solved in the current master version of oriento. https://github.com/codemix/oriento/issues/170
You can use process._getActiveRequests() and process._getActiveHandles() to see what's holding the app open. They are undocumented but commonly used in this scenario.

how to run knex migrations

I'm playing around with Ghost blogging platform https://github.com/TryGhost/Ghost/issues/769. It uses knex module for nodejs to interact with an sqlite3 database. The migrations to rollback look like this. I'm wondering if there's a way to run this from sqlite3 console, or how would I do it if I want to rollback migrations?
down = function () {
return when.all([
knex.schema.dropTableIfExists('posts_tags'),
knex.schema.dropTableIfExists('roles_users'),
knex.schema.dropTableIfExists('permissions_users'),
knex.schema.dropTableIfExists('permissions_roles'),
knex.schema.dropTableIfExists('users')
]).then(function () {
return when.all([
knex.schema.dropTableIfExists('roles'),
knex.schema.dropTableIfExists('settings'),
knex.schema.dropTableIfExists('permissions'),
knex.schema.dropTableIfExists('tags'),
knex.schema.dropTableIfExists('posts')
]);
});
};
exports.up = up;
exports.down = down;
exports.constraints = constraints;
There isn't currently a way to run this through the command line. We keep both the up and down migrations defined in case we need them in future, but there isn't a use for them at present.
The migration system in Ghost is also currently being rewritten before any actual migrations are done in version 0.4.

Resources