Meteor: write to database on successful callback from server method - javascript

I want to write to database only on successful callback received from server when I invoke it from client.
Meteor.call('job', 'new', name, script, function(err,response) {
if(err) {
console.log(err);
alert('Error while processing your script. Please make sure syntax is correct.')
return;
}else{
taskid = response;
console.log(taskid);
FileSystem.update({ _id: this.params.fileId }, { $set: { content: content, taskid:taskid} }, function (e, t) {
if (e) {
//error
}
});
}
});
write now it says
Exception in delivering result of invoking 'job': TypeError: Cannot read property 'fileId' of undefined
I expected that it will only update the DB when the server call was successful. How can I make this happen?

Assuming this.params exists at all, you're likely losing your data context inside of these callback functions. What you want to do is define a variable before your Meteor.call() and set that variable to this.params.fileId. You can then use that variable inside of the callback function.
I've shown this in code below.
var fileId = this.params.fileId;
Meteor.call('job', 'new', name, script, function(err,response) {
if(err) {
console.log(err);
alert('Error while processing your script. Please make sure syntax is correct.')
return;
}else{
taskid = response;
console.log(taskid);
FileSystem.update({ _id: fileId }, { $set: { content: content, taskid:taskid} }, function (e, t) {
if (e) {
//error
}
});
}
});

Related

My Node Script Hangs after functions are finished

I'm calling three functions, after the completion of these functions I want my script to close on it's own but it just hangs.
I've tried making the functions async/promise based, closing the database after each 'mongodb' type function, and using process.exit() within a function as a callback to the last called function.
Connecting to the (local - not Atlas) Database:
MongoClient.connect(local, {useNewUrlParser: true, useUnifiedTopology: true}, function(err, db) {
if (err) {
console.log(err)
}
else {
console.log('Connected to MongoDB...')
//Read in data from jsonfiles and store each file's contents into the database : This is where the functions are being called... within a successful connect to the MongoDB
insertJSON(db, jsonfiles, 'requests', jsonfilesSource)
insertJSON(db, issuedfiles, 'issuedLicenses', isssuedfilesSource)
insertLicenses(db)
}
db.close()
})
Function 1:
function insertJSON(db, dirBuf,collection, sourceFolder) {
var database = db.db('license-server')
var collection = database.collection(collection)
fs.readdir(dirBuf, function(err, files) {
if (err) {
console.log(err.message)
}
else {
files.forEach(function(filename) {
var text = fs.readFileSync(sourceFolder + filename);
var filecontents = JSON.parse(text)
//collection.insertOne(filecontents)
collection.findOne({"DisplayTitle" : filecontents.DisplayTitle, "NodeInformation" : filecontents.NodeInformation, "Date": filecontents.Date})
.then(function(result) {
if(result) {
console.log(`An Item could already be in the database: A file is unique if its display title, nodeinformation, and date are different.
the items display title is ${result.DisplayTitle}`)
return
}
else {
collection.insertOne(filecontents)
console.log(`Added ${filecontents.DisplayTitle} to database`)
}
})
.catch(function(error) {
console.log(error)
})
})
}
})
}
Function 2:
function insertLicenses(db) {
// Set up GridFS to import .lic and .licx files into the database
var database = db.db('license-server')
var collection = database.collection('fs.files')
var bucket = new mongodb.GridFSBucket(database);
var dirBuf = Buffer.from('../license-server/private/licenses')
fs.readdir(dirBuf, function(err, files) {
if (err) {
console.log(err.message)
}
else {
files.forEach(function(filename) {
collection.findOne({"filename": filename}).
then(function(result) {
if(result) {
console.log(`The file ${filename} is already in the database`)
return
}
else {
fs.createReadStream('./private/licenses/' + filename).
pipe(bucket.openUploadStream(filename)).
on('error', function(error) {
assert.ifError(error)
}).
on('finish', function() {
console.log(`Uploaded ${filename}`)
})
}
})
})
}
})
// I tried calling db.close() here since this is the last function to be called. No luck.
}
I'm guessing it has something to do with the mongodb functions having their own way to close themselves but I couldn't seem to find what I was looking for in previous attempts to resolve this issue.
The expected result should be the script closing itself, the actual result is a handing script.
All of these database calls are asynchronous -- the result of this code running is to immediately call db.close and then do the work in insertJSON and insertLicenses. If you were to rewrite this to use async/await (and you'd need to update your other functions as well) the db.close call would close the db, and that would allow the script to exit:
await insertJSON(db, jsonfiles, 'requests', jsonfilesSource)
await insertJSON(db, issuedfiles, 'issuedLicenses', isssuedfilesSource)
await insertLicenses(db)
db.close()
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

How can I send messages to my queue and a post request?

I have a function that posts data to the database. It works fine but I would also like to use the same function to send a message to trigger another function.
I have tried to simultaneouslysend the message and make the post request but at this moment only the post request works
Here is what my code looks like
const params = {
"TableName": "sites",
"Item": {
userId: event.requestContext.identity.cognitoIdentityId,
siteId: siteIdFinal,
...data,
createdAt: Date.now()
}
};
const messageParams = {
MessageBody: 'Waddup fam',
QueueUrl: ' https://sqs.eu-west-1.amazonaws.com/106845550704/MyQueue'
};
try {
await dynamoDbLib.call("put", params);
sqs.sendMessage(messageParams, (err, data) => {
if (err) {
console.log("Error: "+err);
} else {
console.log("Success: "+data.MessageId);
}
});
return success(params.Item);
} catch (e) {
console.log(e);
return failure({ status: false });
}
I am not getting any error I am just getting returned back the data that has been posted. I thought i should receive the message Id of the message I sent but I am not getting that. When ever I look at the cloudwatch logs, the message isnt sent
Your async function returns params.Item before sendMessage executes a callback.
Use a promise to make sure that both methods finish properly
await sqs.sendMessage(messageParams).promise()
.then(function(data) {
console.log("Success: "+data.MessageId);
}).catch(function(err) {
console.log("Error: "+err);
});
More on aws-sdk and promises:
https://aws.amazon.com/blogs/developer/support-for-promises-in-the-sdk/

How to treat an error inside the try using only one catch?

I'm using try-catch to handle with the errors of my code.
Even reading and searching a lot, I'm still with some doubts.
In the piece of code bellow, I'd like to deal with any error that occurs inside the try block, but it captures an error only if it occurs in db.find line.
If the error occurs inside of db.find function, I mean, in the if or else code, this error is not captured by the catch.
routes.get('/app/:id', (req, res) => {
var downloadUrl = http://url;
try {
db.find({ _id: req.params.id }, function (err, subscriber) {
if (!subscriber.length) {
res.render('info', { url: consts.baseUrl, message: consts.USERNOTFOUND });
} else {
res.render("app", { downloadUrl: downloadUrl });
}
});
}
catch (e) {
logger.error(`${e.status || 500} - ${e.message} - /app`);
}
});
To capture an error in if else block (lets suppose that the var subscriber doesnt exists) I need to put another try catch like that:
routes.get('/app/:id', (req, res) => {
var downloadUrl = consts.baseUrl + 'downloadapk/' + req.params.id;
try {
db.find({ _id: req.params.id }, function (err, subscriber) {
try{
if (!suabscriber.length) {
res.render('info', { url: consts.baseUrl, message: consts.USERNOTFOUND });
} else {
res.render("app", { downloadUrl: downloadUrl });
}
}catch(e){
logger.error(`${e.status || 500} - ${e.message} - /app`);
}
});
}
catch (e) {
logger.error(`${e.status || 500} - ${e.message} - /app`);
}
});
I'm not sure that use try-catch inside another is the best solution.
So how can I treat any error inside the try using only one catch?

meteor methods functions return is not working

I am trying if my data is removed then show return "removed successfully"; but it's not working also not removing the data. If I am not used function then data is removed but not getting any return result form call back
Its working
Meteor.methods({
removeFAV: function(userID, product_id) {
Favorites.remove(
{ user_id: userID, product_id: product_id },
{ multi: true }
);
}
});
It's not working
Meteor.methods({
removeFAV: function(userID, product_id) {
Favorites.remove(
({ user_id: userID, product_id: product_id }, { multi: true }),
function(err) {
if (err) {
return err;
} else {
return "removed successfully";
}
}
);
}
});
The Meteor Mongo.Collection is not a native Mongo Collection but a wrapper that integrates native Mongo calls into the Meteor environment.
See: https://docs.meteor.com/api/collections.html#Mongo-Collection
The insert update and remove methods have a specific blocking behavior unless you provide a callback:
On the server, if you don’t provide a callback, then remove blocks until the database acknowledges the write and then returns the number of removed documents, or throws an exception if something went wrong.
If you do provide a callback, remove returns immediately. Once the remove completes, the callback is called with a single error argument in the case of failure, or a second argument indicating the number of removed documents if the remove was successful.
https://docs.meteor.com/api/collections.html#Mongo-Collection-remove
Since the blocking type call is automatically throwing en error, there is theoretically no need to explicitly handle the exception:
Meteor.methods({
removeFAV: function(userID, product_id) {
const removedDocs = Favorites.remove(
{ user_id: userID, product_id: product_id },
{ multi: true });
// remove returns the number of docs being removed
return `removed [${removedDocs}] document(s) successfully`
}
});
Such a method will return in the callback of Meteor.call either the thrown error as first parameter or the result as second.
However, it also makes sense to handle the exception and let the method fail silently:
Meteor.methods({
removeFAV: function(userID, product_id) {
let removedDocs = 0
try {
// remove returns the number of docs being removed
removedDocs = Favorites.remove(
{ user_id: userID, product_id: product_id },
{ multi: true });
} catch (e) {
// log error
myErrorLog.log(e)
} finally {
return `removed [${removedDocs}] document(s) successfully`
}
}
});
This will never return an error to the client but logs the error on the server.

Promise either never get called, or is rejected (Parse JS SDK)

I am trying to write a function that add or edit some fields on a User object.
The problem come when I try to save the user, if I use user.save, the Promise is rejected with error 206 UserCannotBeAlteredWithoutSessionError.
However, if I get the session id (and documentation about that is scarce), the promise never get resolve, nor rejected. The app seems to just jump to the callback.
My function:
function update(user, callback) {
let query = new Parse.Query(Parse.User);
query.equalTo("username", user.email);
query.find().then(
(users) => {
if(users.length === 0) {
callback('Non existent user');
} else {
let user = users[0];
// user.set('some', 'thing');
console.log('save');
user.save(/*{
sessionToken: user.getSessionToken()
}*/).then(
(test) => {
console.log('OK - ' + test);
callback();
}, (err) => {
console.log('ERR- ' + require('util').inspect(err));
// console.log(callback.toString());
callback(error.message);
}
);
}
},
(error) => {
callback(error.message);
}
);
}
Called with:
var async = require('async'),
baas = require('./baas.js');
async.waterfall([
(callback) => {
callback(null, {
email: 'user#test.com',
password: 'password'
});
},
(user, callback) => {
console.log('connect');
baas.connect(() => { //Initialize the connection to Parse, and declare use of masterKey
callback(null, user);
});
},
(user, callback) => {
console.log('update');
baas.update(user, (err) => {
callback(err);
});
}
], (err) => {
console.log('Error: ' + err);
});
The logs become:
Without session token:
connect
update
save
ERR- ParseError { code: 206, message: 'cannot modify user sA20iPbC1i' }
With session token:
connect
update
save
I do not understand how it is possible that the promise just callback without printing anything, nor why no error are raised anywhere.
Edit:
Following #user866762 advice, I tried to replace the query with Parse.User.logIn and use the resulting User object.
While this solution give me a sessionToken, the end result is the same, parse crash if I don t provide the session token, or give me a error if I do.
According to the Parse Dev guide:
...you are not able to invoke any of the save or delete methods unless the Parse.User was obtained using an authenticated method, like logIn or signUp.
You might also try becoming the user before saving, but I have my doubts that will work.
When you're "get[ting] the session id" my guess is that you're really breaking something. Either Parse is having a heart attack at you asking for the session token, or when you're passing it in save you're causing something there to explode.

Categories

Resources