How to reuse Redis connection using nodeJs childProcess - javascript

How could I reuse the redis connection in processes created using Childprocess.fork() in nodeJs ?
For example, I would have a redis-config.js file where I create an instance of RedisClient and connect to the redis server.
So after that I would have another file, test.js for example, and inside that file test, js I would access the instance of redis via import and then I could for example insert a key in redis. But this without creating another connection to the redis server.
For example
redis-conf.js
const Redis = require('redis');
const redisClient = Redis.createClient({name:'test-conecction'});
module.exports = {redisClient:Object.freeze(redisClient)}
main.js
const cp = require('node:child_process');
const {redisClient} = require('./redis');
redisClient.connect().then(()=>{ <<=== this is want i want, this does not work, i want to connect only once.
const c1 = cp.fork('./child.js');
const c2 = cp.fork('./child.js');
})
child.js
const {redisClient} = require('./redis');
redisClient.info().then((data)=>{ <<== when i try this, nodeJs tells that the client is disconnected
console.log(data);
})

IN resume. Its not possible. Because when nodeJs create a childPorcess evething is re-created and all resources are re-alocated.

Related

Export mysql2 connection to other files node js

I am trying to use one connection across all the files in a node and mysql2 project.
This is what I did ->
// db.js
const mysql = require('mysql2')
const connection = mysql.createConnection({dbinfo})
console.log(connection) // the connection is proper
module.exports = { connection }
//server.js
const { con } = require('./db')
console.log(con) //returns undefined
Similar thing works if I use the mysql package instead with mysql2

Use Node for send and receive pdf files

i'm using Express to create a backend server using NodeJs. One of the functionalities of the project is to send and receive PDF files. The other routes of the backend send and receive JSON files but i want to create a route for send and receive PDF files, what can i do? What i have until now:
const express = require('express')
const app = express()
const db = require('./config/db')
const consign = require('consign')
const consts = require('./util/constants')
//const routes = require('./config/routes')
consign()
.include('./src/config/middlewares.js')
.then('./src/api')
.then('./src/config/routes.js') // my routes file
.into(app)
app.db = db // database using knex
app.listen(consts.server_port,()=>{
//console.log('Backend executando...')
console.log(`Backend executing at port: ${consts.server_port}`)
})
app.get('/',(req,res)=>{
res.status(200).send('Primary endpoint')
})
/* basically at routes.js file i'm handling http routes that manages JSON objects such as this one below:
*/
At routes.js:
// intercept http routes and pass specific funtion for handling them
module.exports =app=>{
app.route('/products')// regular JSON objects
.post(app.src.api.itensVenda.saveItem)
.get(app.src.api.itensVenda.getItems)
.put(app.src.api.itensVenda.toggleItemVisibility)
app.route('/articles')
.get(app.src.api.articles.getArticle)
.post(app.src.api.articles.saveArticle)
// the route above is the one that i want to use for sending and receive PDF files
app.route('/info')// ordinary JSON objects
.post(app.src.api.info.saveInfo)
.get(app.src.api.info.getInfo)
}

Need help for my thesis project: electron, express & sqlite3

i'm currently working on my thesis project which consists of an educational desktop videogame for public and private schools in my city.
I also really like electron so i thought it would be a nice idea to make my app using it, however it's here when the problem starts. My university demands that all apps must use a relational database (SQL) and not non-relational db like MongoDB. Since the database i'll have it's relative small i chose SQLite.
For some reason i began to get a certain error:
C:\Users\Alejandro\Documents\Proyectos\express\node_modules\sqlite3\lib\binding\electron-v1.4-win32-ia32\node_sqlite3.node
After some research i found out that the reason was because electron executes on the client side and databases can only work on server side, to solve this issue i installed express on my app to execute a server in the background while electron executes the client (local client-server desktop app).
After some coding this was the result:
Main.js (Electron code changes)
const express = require('./resources/express')
const electron = require('electron')
// Module to control application life.
const app = electron.app
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow
const path = require('path')
const url = require('url')
// Keep a global reference of the window object, if you don't, the window will be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 800, height: 600})
// and load the index.html of the app.
mainWindow.loadURL('http://localhost:8080/')
// Emitted when the window is closed.
mainWindow.on('closed', function () {
console.log('app server is closing')
express.closeServer()
mainWindow = null
})
}
Express.js (Express code):
const http = require('http')
const express = require('express')
const dbmanager = require('./dbmanager.js')
app = express()
app.set('view engine', 'pug')
app.get('/',function(request, response){
console.log('server started :D')
response.end()
})
app.get('/checktable',function(request, response){
dbmanager.createTable()
response.redirect('/receive')
})
app.get('/receive',function(request, response){
dbmanager.selectAll(function(err,data){
data.forEach(function(row){
console.log(row.id + " " + row.name + "Edad: " + row.age)
})
response.render('index', { title: 'Usuario', message: data[0].name + " " + data[0].last })
response.end()
})
})
var server = http.createServer(app).listen(8080)
var serverManager = {}
serverManager.closeServer = function(){// This executes
console.log('This is executing')
console.log('Server should close now')
server.close()
}
module.exports = serverManager
dbmanager.js (SQLite queries)
var sqlite3 = require('sqlite3').verbose()
var db = new sqlite3.Database('memory')
var queryManager = {}
queryManager.createTable = function(){
db.run("CREATE TABLE IF NOT EXISTS students (id int, name TEXT,last TEXT, age int)")
}
queryManager.deleteTable = function(){
db.run('DROP TABLE students')
}
queryManager.insertStudent = function(student){
var stmt = db.prepare("INSERT INTO students VALUES (?,?,?,?)")
stmt.run(student.id,student.name,student.last,student.age)
stmt.finalize()
console.log('Insert Successful')
}
queryManager.selectAll = function(callback){
db.all('SELECT * FROM students', function(err,rows){
if(err)
{
throw err;
}
else
{
callback(null, rows);
}
})
}
module.exports= queryManager
Index.pug (view)
html
head
title= title
body
table#table
h1= message
Before trying to execute the entire app i tried only executing the server and it worked.
I modified the npm start line from "electron ." to "electron . && node ./resources/express.js" so i could execute both the client and the server.
At that moment i commented all the lines related to the dbmanager.js to test if the client and server were working.
Needing to close the server at the moment the app windows was close i created a function to close the server when window close funcion is called, but it doesn't.
That's the first problem. The second problem shows up when i undo the comment on the dbmanager lines, i get the same error as before:
'C:\Users\Alejandro\Documents\Proyectos\express\node_modules\sqlite3\lib\binding\electron-v1.4-win32-ia32\node_sqlite3.node'
Am i doing something wrong? Please i really need help.
You're spinning up an Express server on the same machine as your Electron app, if your server can access a local database then what makes you think your app can't? You don't need an Express server. To use the sqlite3 module in an Electron app you just have to rebuild it to target the specific Electron version using one of the documented approaches.

How to use socket.io browserify?

How do I use socket.io with browserify?
When socket.io is installed in a node app, it creates this url path for ths socket.io script:
/socket.io/socket.io.js
But what would be the real path of that file (relative to the node_modules dir) which needs to be passed to browserify?
Is it e.g.
socket.io-client/socket.io.js
or maybe
socket.io/lib/client.js
In the documentation of socket.io-client it says "Socket.IO is compatible with browserify." But they don't say how.
If you struggled to get it working with browserify as a window global use this code for the integration:
var io = require('socket.io-client');
window.io = io;
Here's a minimal client:
// client.js
var socket = require('socket.io-client')();
socket.on('message', ...);
Which you can Browserify:
browserify client.js > bundle.js
The path will be exactly the same since it's the server who serve the socket.io client library (and I guess you're not browserifying the server, are you?).
But I use a more convenient solution: check this out.
io = require 'socket.io-client'
class Network
constructor: (game, refresh_infos) ->
#sock = io()
#...
pending: (name, cb) ->
#name = name
#sock.emit 'pending', name: name
#sock.on 'new_game', (data) => cb data
Abrakadabra!
Import client and then assign it to variable with:
var client = require('socket.io/lib/client');
You can then call client.

Best way to store DB config in Node.Js / Express app

What would be the best way to store DB config (username, password) in an open source app that runs on node.js / Express? Two specific questions:
Shall I put it into a separate config.js file in /lib folder, for example, and never include it into the master repository that is publicly available on GitHub?
To inlcude the config, is it as simple as require('./config.js') from the file that needs it or is there a better way of doing it?
PS sorry if the questions seem a bit simple or not so well formulated, but I'm just starting :)
Here's how I do it:
Create a config.js which contains objects representing your configs:
var config = {
development: {
//url to be used in link generation
url: 'http://my.site.com',
//mongodb connection settings
database: {
host: '127.0.0.1',
port: '27017',
db: 'site_dev'
},
//server details
server: {
host: '127.0.0.1',
port: '3422'
}
},
production: {
//url to be used in link generation
url: 'http://my.site.com',
//mongodb connection settings
database: {
host: '127.0.0.1',
port: '27017',
db: 'site'
},
//server details
server: {
host: '127.0.0.1',
port: '3421'
}
}
};
module.exports = config;
Then in my index.js (or wherever really),
var env = process.env.NODE_ENV || 'development';
var config = require('./config')[env];
Then process with that object, e.g.
var server = express();
server.listen(config.server.port);
...
For running toy apps where I need to hide db credentials, I use the dotenv module.
Place your sensitive info in a .env file (which is .gitignored), place require('dotenv').config(); in your app; dotenv creates entries in process.env that you can refer to.
.env file:
DATABASE_PASSWORD=mypw
DATABASE_NAME=some_db
To refer to the values:
process.env.DATABASE_PASSWORD
Not sure whether this is the best practice, but personally I have a config.json file where I store my db connection information. Then I do the following:
// options.js
var fs = require('fs'),
configPath = './config.json';
var parsed = JSON.parse(fs.readFileSync(configPath, 'UTF-8'));
exports.storageConfig= parsed;
Then from a different file I do the following:
var options = require('./options');
var loginData = {
host: options.storageConfig.HOST,
user: options.storageConfig.user,
password: options.storageConfig.password
};
I do put in args. just like the port of so many node.js example.
you most likely forever, pm2, nodemon to run your app. so this variable is not check in as part of your source code. and they are globally available too.
process.env.PORT
process.env.DATABASE_USER
process.env.DATABASE_PASSWORD
PORT=3000 DATABASE_HOST=localhost DATABASE_USER=admin DATABASE_PASSWORD=mypassword node app.js
export PORT=3000
export DATABASE_HOST=localhost
export DATABASE_PORT=27017
export DATABASE_USER=admin
export DATABASE_PASSWORD=mypassword
node app.js
var server = app.listen(process.env.PORT, function() {
});
var mongoClient = new MongoClient(new Server(process.env.DATABASE_HOST, process.env.DATABASE_PORT));
To inlcude the config, is it as simple as require('./config.js') from the file that needs it or is there a better way of doing it?
This is the right way to store config files.
The best approach would be to write your entire application like an ordinary node.js module, and write a small start-up file that calls it. This idea also allow you to use different database drivers using dependency injection.
Good, but not perfect solution is the environment. It is shared among all application, so if you have certain data you want to be available to all of them, this is the best bet. But if you have a config for one particular app, not much so.
PS: And please, don't use JSON for this. It's the worst idea possible. :)
I found this a nice way to handle my config, considering different environments:
config.coffee
exports.setEnvironment = (env) ->
switch env
when "development"
exports.DEBUG_LOG = true
exports.DB_PORT = '27017'
# ...
when "testing"
exports.DEBUG_ERROR = true
exports.DEBUG_CLIENT = true
# ...
when "production"
exports.DEBUG_LOG = false
# ...
else console.log "environment #{env} not found"
server.coffee:
config = require('./config')
config.setEnvironment env
Using environment variables
You can use export to set environment variables in OSX and Linux. The following is an example of setting a value in the SESSION_SECRET key.
export SESSION_SECRET="keyboard cat"
In Windows, you can use set.
set SESSION_SECRET="keyboard cat"
You can also set environment variables each time you run them.
SESSION_SECRET="keyboard cat" node secret-env.js
Use process.env of node.js to access environmental variables within code.
var express = require('express')
var session = require('express-session')
var app = express()
app.use(session({secret: process.env.SESSION_SECRET}))
Request a argument from the command-line
The best way to protect confidential information is not to store it in a setup file.
If the command-line requests configuration information as an argument using the noopt package, the secret information does not need to exist as a file.
The following is an example of requesting a session key as an argument using the noopt package.
var nopt = require("nopt")
var longOpts = {
"sessionSecret": String,
}
var shortOpts = {
"s": ["--sessionSecret"],
}
var parsed = nopt(longOpts, shortOpts, process.argv, 2)
console.log("session secret is:", parsed.sessionSecret)
node secret-arg.js --sessionSecret "keyboard cat"
node secret-arg.js -s "keyboard cat"
Advantages : It is safer to expose confidential information than to hardcoding or having it as a configuration file.
Disadvantages : There is a hassle of increasing the amount of information to be entered each time the app is launched.
If you try to create and solve a script, the problem that the password still exists in the script remains.

Categories

Resources