atlas mongodb serverless and aws lambda connection issue - mongodb

I have got a serverless db on atlas (https://www.mongodb.com/serverless). I used the connection string recommended by ATLAS:
mongodb+srv://<username>:<password>#xyz.esxbh.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
however as soon as i try to create a record, i get the following error:
{"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"MongoParseError: Text record must only set `authSource` or `replicaSet`","reason":{"errorType":"MongoParseError","errorMessage":"Text record must only set `authSource` or `replicaSet`","name":"MongoParseError","stack":["MongoParseError: Text record must only set `authSource` or `replicaSet`","
I don't think that the connection string is correct, on the other hand the dns entry for the server does reply with 2 servers.
I tried dropping the '+srv' part, however in that case the save function from mongoose just hangs forever timing out the lambda function.
I could not find any similar problem on google.
The TXT entry record from the dns server shows:
"TXT "authSource=admin&loadBalanced=true"
How have you configured the serverless database to work?
The code that generates the error depends on mongoose and is as follows:
try {
const customer = new Customer(cust);
console.log('new cusotmer created');
const returnedCustomer = await customer.save();
console.log(returnedCustomer);
return serverResponse(200, returnedCustomer);
} catch(err){
console.log(err);
return errorHandler(500, err)
}
It seems that the connection to the database is fine:
try {
await dbTools.connectMongoose();
console.log('*** connected ***');
} catch(err){
console.log('error when connecting');
return errorHandler(500, err);
}
Now, looking at the source code, nothing really too complicated:
if (Object.keys(record).some(key => key !== 'authSource' && key !== 'replicaSet')) {
return callback(
new MongoParseError('Text record must only set `authSource` or `replicaSet`')
);
}
I am now really struggling to understand what's wrong as authSource seems to be present in the TXT record.

Upgrading mongoose to the latest version worked for me in Nodejs.
Remove "mongoose" from package.json.
Reinstall "npm i mongoose"
"mongoose version 6.0.5" should work.
Worked on 10-Sep-2021

For anyone still experiencing this in 2022, here is an answer from a MongoDB employee (at the bottom). It's a native Node.js driver issue (nothing to do with AWS lambda specifically), which will waterfall to all ODM implementations that implement the native driver.
https://www.mongodb.com/community/forums/t/atlas-serverless-and-dns-txt-record/117967/8
According to Zia Ullah's answer to this same question, this is fixed by Mongoose 6.0.5.

Related

mongo - dropping non existant collection throws 'ns not found'

I'm trying to drop a non existant collection and I get the following error:
MongoError: ns not found.
In a similar question, there is a link to the mongo code which shows that this is the expected behaviour:
MongoError: ns not found when try to drop collection
However, according to the mongo documentation, this method should return false if the collection does not exists:
https://docs.mongodb.com/manual/reference/method/db.collection.drop/#db.collection.drop
What am I missing?
Server version - 3.6.5, mongodb client (javascript) - 3.0.21
The commands I used:
await mongodb.collection('colname').drop()
and
mongodb.collection('colname').drop((err, res) => {
console.log('err: ' + err + ', res: ' + res) // doesn't get called
})
You link refers to the command interface of the mongo client. It uses javascript but is an application that has its own REPL. The documentaion is correct.
The command you are using is from the official mongodb node package. The behavior of these commands are different than those on the mongo client. The documentation concerning your usage is here: http://mongodb.github.io/node-mongodb-native/3.0/api/Collection.html#drop
BTW, the first parameter is an option object, the second would be the callback.
The callback you provide is only called on a successful mongodb query. When the collection does not exist (like in this case), the callback is not executed. But this function returns a promise, which can be used to handle any error:
mongodb.collection('colname').drop().then(function () {
// success
}).catch(function () {
// error handling
})

MongoDB Callback Error

I'm working on an application using Meteor and MongoDB where I'm attempting use nested callbacks to access a newly inserted document as seen below. However I keep getting an error where there is no matching document in the database even though I'm in the successful callback of the insert statement. I'm not sure as to why Mongo can't find the document I just inserted. I understand that the methods are asynchronous, but I assumed that the callback would allow me to access the newly inserted document once the find function returns. I attempted to place the find outside of the insert statement with its own callback and got the same error.
I've attached the error message as well. Any help on this matter would be greatly appreciated!
insertEntryForm.call(entryFormObj, (error, result) => {
if (error) {
console.log(error);
toastr['error'](error.reason);
}
else {
toastr['success']("Entry form created!");
EntryForms.find({_id: result}, function(err, res) {
console.log(res);
});
}
}
);
From the documentation and the examples provided by Inserting and updating - MongoDB the second argument for the insert callback is the object inserted and in your find you're looking for a document with result , it should be result._id , so this should work :
EntryForms.find({_id: result._id}, function(err, res) {
Turns out the issue had to do with the way in which I was publishing/subscribing to my object within Meteor. I registered my subscription in my router.js file and was then able to access my collection as expected. Chalk this one up to my small experience with Meteor.

Why doesn't my db.collection.insert work?

I am encountering a weird issue here...
After I seem to successfully insert some data into my db.collection I cant seem to get it to reflect using db.collection.find().fetch().
Find below the code I insert into my chrome console:
merchantReviews.insert({merchantScore: "5.5"}, function() {
console.log("Review value successfully inserted");
});
This yields:
"9sd5787kj7dsd98ycnd"
Review value successfully inserted
I think returned value "9sd5787kj7dsd98ycnd" is an indication of a successful db collection insert. Then when I run:
merchantReviews.find().fetch()
I get:
[]
Can anyone tell me what is going on here?
Looking forward to your help.
There are two possibilities here: either the insert fails on the server even though it passes on the client, or you haven't subscribed to your collection.
In case the insert fails on server (most likely due to insufficient permissions, if you have removed the insecure package but have not declared any collection.allow rules), the client code still returns the intended insert ID (in your case, "9sd5787kj7dsd98ycnd"). The callback is called once the server has confirmed that the insert has either failed or succeeded. If it has failed, the callback is called with a single error argument. To catch this, you can instead insert the document like this:
merchantReviews.insert({merchantScore: "5.5"}, function(error) {
if (error) {
console.error(error);
} else {
console.log("Review value successfully inserted");
}
});
If this still logs successful insert, then you haven't subscribed to the collection, and you have removed the autopublish package. You can read about Meteor publish-subscribe system here. Basically, you have to publish the collection in server-side code:
Meteor.publish('reviews', function () {
return merchantReviews.find();
});
And in server code (or your js console) you need to subscribe to the collection with Meteor.subscribe('reviews'). Now calling merchantReviews.find().fetch() should return all documents in the collection.

Cannot get my collection's data in meteor client side js in Meteor

I have written the following code in my client side js:
var resolutionsQ;
Template.body.onCreated(function bodyOnCreated() {
resolutionsQ = new Mongo.Collection("res");
});
Template.body.helpers({
resolutions: function() {
var res = resolutionsQ.find({});
console.log(res);
return resolutionsQ.find({});
}
});
Then in my project folder(in terminal), i wrote:
meteor mongo
After the mongo db console started, I worte:
db.res.insert({title: "hello #1", createdAt: new Date()});
This also worked.
When I wrote this, my frontend application showed everything as expected. Then I shut down my computer, and after sometime switched it on again and tried to run my meteor application. Now I see nothing, I get no error either in server console or browser's console. I don't know what went wrong then.
Please help.
You've created a client-side collection by defining the collection only in client code. A collection needs to be defined on both the server and the client in order to persist documents to the database.
The quick solution is to create a shared file like lib/collections/resolutions.js which will contain:
Resolutions = new Mongo.Collection("resolutions");
Using the new-style imports mechanism, you would create a file like imports/api/resolutions/resolutions.js which will contain:
import { Mongo } from 'meteor/mongo';
export const Todos = new TodosCollection('Todos');
See this section of the guide for more details.

Meteor.methods fails on the server side

My goal is to insert device token into db. The method succeeds on the client but fails on the server side. I have no idea why.
// lib/meteor_methods.js
Meteor.methods({
savePushTokens: function(myToken) {
console.log("Saving the token.")
Tokens.insert({token: myToken}, function(error, result) {
if (error) {
console.log(error);
}
else {
console.log(result);
}
});
console.log("Token is now saved!");
}
})
// client/push_notifications.js
...
function tokenSuccessHandler(result) {
console.log('token success result ' + result);
window.localStorage.setItem('deviceToken', result);
// API call to store token on your DB
Meteor.call('savePushTokens', result)
console.log(Tokens.find().fetch());
}
...
Please see the whole file: https://github.com/mvaisanen/SimplePushApp/blob/pushplugin/client/push_notifications.js
Xcode console output
2015-01-22 10:27:51.165 myapp[33366:5680153] token success result
077f2ea72eb6b2dfc381ce27f2eb12e2ee8ee68f7eeb90f7f2f10f1d99cd140e
2015-01-22 10:27:51.166 myapp[33366:5680153] Saving the token.
2015-01-22 10:27:51.166 myapp[33366:5680153] zp6vkrN5M4HtKF9NF
2015-01-22 10:27:51.166 myapp[33366:5680153] Token is now saved!
2015-01-22 10:27:51.166 myapp[33366:5680153] [{"token":"077f2ea72eb6b2dfc381ce27f2eb12e2ee8ee68f7eeb90f7f2f10f1d99cd140e","_id":"zp6vkrN5M4HtKF9NF"}]
Everything seems fine.
However, if I query database inside meteor shell, client or server, the result is empty collection. (> Tokens.find().fetch()
[]).
If I run the method on the server side, it actually never runs. See below.
// lib/meteor_methods.js
Meteor.methods({
savePushTokens: function(myToken) {
console.log("Saving the token.")
if (Meteor.isServer) {
Tokens.insert({token: myToken}, function(error, result) {
if (error) {
console.log(error);
}
else {
console.log(result);
}
});
console.log("Token is now saved!");
}
}
});
Xcode console output
2015-01-22 10:32:59.290 myapp[33375:5681416] token success result 077f2ea72eb6b2dfc381ce27f2eb12e2ee8ee68f7eeb90f7f2f10f1d99cd140e
2015-01-22 10:32:59.291 myapp[33375:5681416] Saving the token.
2015-01-22 10:32:59.291 myapp[33375:5681416] []
Any idea? The full repo is here https://github.com/mvaisanen/SimplePushApp/tree/pushplugin
UPDATE
I have autopublish and insecure installed.
I start the app with meteor run ios-device --mobile-server 192.168.1.6:3000.
I can manually insert data to db via meteor shell or meteor mongo.
I have also tried to check for tokens in meteor mongo:
$ meteor mongo
MongoDB shell version: 2.4.12
connecting to: 127.0.0.1:3001/meteor
meteor:PRIMARY> db.tokens.find();
meteor:PRIMARY>
But I get no tokens.
UPDATE 2
I haven't been able to fix the bug. Is there any simple (or complex) Meteor apps on github (or somewhere else) which have Apple push notifications and which I could clone and thus find the solutions.
Its quite likely that the token is saving but the way you're looking at it makes it appear as if its not, because it may not be visible at the places you're looking at the instant its being looked at.
Keep in mind that :
Meteor doesn't publish all data to the client unless autopublish is in to your project.
If you insert something on the server, it is not immediately available on the client, in the case that it is published to the client
The way that you look for the tokens is right after you call Meteor.call, it's not very likely the data would have been received on the client at this point.
I'm not sure whether this would make any difference, but you're using asynchronous javascript on the server. Meteor uses fibers and you don't have to do this.
It's helpful in that, if there is a problem meteor will throw an error. You can simply do this:
if (Meteor.isServer) {
Tokens.insert({token: myToken});
console.log("Token is now saved!");
}
To check whether the token has been inserted, the best way is to use the meteor mongo console while your app is running and check whether the tokens are in there, this is the actual mongo shell to the database so meteor's publish delay/lack of publish method is likely not to be an issue.
meteor mongo
>db.tokens.find();
(If your collection is called 'tokens', ie : var PushTokens = new Mongo.Collection("tokens").