mongodb connections and sessions not working as intended - javascript

for context I am fairly new to mongodb transactions, i was initially working with a standalone database but am using atlas now so that i can test my transactions without affecting my main database.
here is how i used to connect to the atlas database :
export var client = mongoose
.connect(CONNECTION_URL, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() =>
app.listen(PORT, () => console.log(`SERVER RUNNING ON PORT: ${PORT}`))
)
.catch(() => console.log("launch error, probably ip address on mongo db"));
however i keep getting a
TypeError: client.startSession is not a function
error so i changed my client to be like this :
export var client = await MongoClient.connect(CONNECTION_URL, { useNewUrlParser: true, useUnifiedTopology: true })
app.listen(PORT, () => console.log(`SERVER RUNNING ON PORT: ${PORT}`));
which is incorrect in a sense but it seems to get my session to start, however it fails all my model queries (the error is : usermodels.findOne() buffering timed out after 10000ms) and it only works as intended when i use my client to get a collection instead of using the model directly
const Collection = client.db("myFirstDatabase").collection("usermodels");
and then running
const user = await Collection.find({});
instead of
const user = await User.find({}); (where User is just the model i import)
I cant seem to understand why I am unable to use my models as i used to and have to call the collections each time I attempt to run a query on my DB, why isn't possible to run queries with models and collections at the same time ?
I tried going through the official and unofficial documentation about connections/sessions/transactions/queries and its been days since I've been reading but I feel like am on the wrong track or that I am missing something obvious, any help or pointers would be appreciated, I tried looking into previous SO questions but most of them are either unanswered or missing crucial context !

Related

Mongoose.connect() fails when database is specified in connection string

I'm running a local MongoDB server and am trying to connect to it from a node.js server using the Mongoose library.
I'm using SCRAM-SHA-1 as the authentication mechanism
I'm able to connect to it with the admin account when I don't specify a database to connect to, using a connection string such as:
mongodb://{username}:{password}#{address}:{port}?authMechanism=SCRAM-SHA-256
But when I try to specify which database to connect to, using a connection string such as:
mongodb://{username}:{password}#{address}:{port}/database123?authMechanism=SCRAM-SHA-256
the authentication fails.
For reference, my code looks like:
const mongoose = require('mongoose');
let conn_string = `mongodb://mongo_uname:mongo_pass#192.168.1.1:3000/database123?authMechanism=SCRAM-SHA-256`
mongoose
.connect(database_uri, {
useUnifiedTopology: true
})
.then(() => console.log('MongoDB database Connected...'))
.catch((err) => console.log(err))
Is there a different way to specify which database to connect to with mongoose, or is there something I can do differently when constructing the connection string to make it work?
Cheers.
Make sure that the database user you are using is configured to read and write to the database uou are trying to connect to.
import mongoose from "mongoose";
const mongoDB = "mongodb://localhost:27017/twlight";
mongoose.Promise = global.Promise;
mongoose.connect(mongoDB, { useNewUrlParser: true })
.then(() => {
console.log("Database is connected");
},
(err) => {
console.log("There is problem while connecting database " + err);
});
Please try
Note: twilight is database name
If you are using Mongoose v6+, you should NOT specify useUnifiedTopology.
That is deprecated and if you include it, Mongoose will throw the error. Try to include the connection string only:
mongoose.connect(database_uri)
My error ended up being in the configuration of the database user I was trying to connect with, they weren't even set up to read or write to the database I was attempting to connect to.

Does setInterval in node.js start running when computer falls asleep?

I'm trying to fetch an API in node.js server and updated the stored data by using setInterval in JavaScript in every 3 hours. The code is like this: (I'm using mongoDB as database)
mongoose.connect(
constants.db,
{
useNewUrlParser: true,
useUnifiedTopology: true,
reconnectTries: 30000,
},
() => {
app.listen(5000, () => {
console.log("server is running");
const time = 10800000; // for 3 hours
setInterval(dataFetch, time);
dataFetch();
});
}
);
The problem is that I want to use heroku free web-hosting plan and as you know, in this case, heroku make the server sleep after 1 hour until it receives a request and I want to make sure that in case of server sleep, this code do the job well.
Please guide me to handle this case of situation. Thank you :)

Error Continue wait issue on Cube.js backend

I'm having some trouble connecting to the cube.js backend on AWS serverless and executing the /cubejs-api/v1/load request in the frontend dashboard. I keep getting {"error":"Continue wait"} instead of a result returned.
I am following the react-dashboard guide for authentication but deployed using the backend cube.js serverless AWS template.
This is what my main cube.js file looks like.:
const AWSHandlers = require('#cubejs-backend/serverless-aws');
const PostgresDriver = require('#cubejs-backend/postgres-driver');
const fs = require("fs");
const jwt = require("jsonwebtoken");
const jwkToPem = require("jwk-to-pem");
const jwks = JSON.parse(fs.readFileSync("jwks.json"));
const _ = require("lodash");
module.exports = new AWSHandlers({
checkAuth: async (req, auth) => {
const decoded = jwt.decode(auth, { complete: true });
const jwk = _.find(jwks.keys, x => x.kid === decoded.header.kid);
const pem = jwkToPem(jwk);
req.authInfo = jwt.verify(auth, pem);
},
externalDbType: 'postgres',
externalDriverFactory: () => new PostgresDriver({
host: process.env.CUBEJS_EXT_DB_HOST,
database: process.env.CUBEJS_EXT_DB_NAME,
port: process.env.CUBEJS_EXT_DB_PORT,
user: process.env.CUBEJS_EXT_DB_USER,
password: process.env.CUBEJS_EXT_DB_PASS,
})
});
I didn't have the redis URL set correctly initially and fixed the connection to redis after adding redis:// extension before the url to the serverless.yml file to fix that so I know it's not redis connection issue. I'm assuming there's some other problem.
The cubejs process function has no logs at all. I have setup a NAT gateway and subnets according to the guide on the deployment site so that i have 1 subnet for each zone just for the lambda and they have been added to the new NAT gateway that was created and to the 2 functions so they have internet access.
What could be the issue? Did I configure something wrong or do I need to make changes to something?
#cubejs-backend/serverless uses internet connection to access messaging API as well as Redis inside VPC for managing queue and cache.
Such continuous Continue wait messages usually mean that there's a problem with internet connection or with Redis connection. If it's Redis you'll usually see timeouts after 5 minutes or so in both cubejs and cubejsProcess functions. If it's internet connection you will never see any logs of query processing in cubejsProcess function.

Express Server routing issue

I'm trying to add a new route to fetch a user by id but my error handling is not working correctly. Here is the code for that route.
const express = require('express');
require('./db/mongoose');
const User = require('./models/user');
const Task = require('./models/task');
const app = express();
const port = process.env.PORT || 3000;
app.use(express.json());
// ***removed code for brevity
// Route for fetching user by id
app.get('/users/:id', (req, res) => {
//console.log(req.params.id);
const _id = req.params.id;
User.findById(_id)
.then(user => {
//console.log(user)
if (!user) {
return res.status(404).send();
}
res.send(user);
})
.catch(e => {
res.status(500).send();
});
});
So if I test the route on Postman and I enter the correct user id from the database I get that user sent back, which is the the correct response. But if I enter an incorrect user id I get the 500 error code response instead of the 404 error code. The if (!user) statement is getting skipped and I can't figure out why. Any thoughts as to what I am missing?
Running this thru my own personal mongoose/express-using project, I get the following error:
UnhandledPromiseRejectionWarning: CastError: Cast to ObjectId failed for value "12345" at path "_id" for model "User"
That basically means Mongoose is expecting its own specific object type, an "ObjectId". This is a bit of a pain, since normally if you're using .findOne({_id:something), you can just use a string. If we do:
User.findById(mongoose.Types.ObjectId(_id))
it should work. Note that if you use an invalid id (like I obviously did here, it'll still error out. For that reason, I'd use the standard NodeJS format for callbacky stuff:
.then((err,result)=>{
//other stuff
});
In general, the .catch() block should only happen if obviously Mongoose and your router can't handle it.
EDIT: Also, for others info, Mongoose.model.findById is a built-in convenience method, and should basically do exactly what it says on the tin.

mongoose connection can´t handle errors

I am building my first test API rest with Mongo and Node
I am opening a connection to the database, and it works right... but I can´t handle the error case. Despite i write a wrong URI, it makes a successful connection. Tried with promises, callbacks, and events, but nothing works:
For example:
const mongoose=require('mongoose');
mongoose.Promise = global.Promise;
const express=require('express');
const bodyParser=require('body-parser');
const portApp=1300;
const app=express();
app.listen(portApp,'localhost',()=>{
console.log(`server works fine at ${portApp}`);
mongoose.connect('mongodb://localhost:27017/RIGHTdbname')
.then((res)=>
{
console.log(`successful connection to BBDD`);
//console.log(res);
})
.catch((error)=>{
console.log("error"+error.message);
});
});
That´s ok, it throws "successful connection to BBDD"... the problem is, when I write a wrong database name, it throws the same!
I tried to with callback too. like suggested here:
mongoose.connect('mongodb://localhost:27017/WRONGdbname',function(err){
if(err)
{
throw err;
}
});
And tried to use these events (taken from here, and which I actually don´t understand, only used the .on() jquery method in the past, for event delegation tasks), but it does´t work either, because always the "connected" event fires, even if database name is wrong, again.
// When successfully connected
mongoose.connection.on('connected', function () {
console.log('Mongoose default connection opened);
});
// If the connection throws an error
mongoose.connection.on('error',function (err) {
console.log('Mongoose default connection error: ' + err);
});
Can someone explain me what I´´m doing wrong? Thanks
The "database" in the Mongo connection string is used for authentication, and is only relevant if you pass the username and password in the URL using the mongodb://user:pass#host:port/database syntax.
From the reference
/database Optional. The name of the database to authenticate if the connection string includes authentication credentials in the form of username:password#. If /database is not specified and the connection string includes credentials, the driver will authenticate to the admin database.

Categories