Issue with Error handling on Firebase remove function - javascript

The promise that is returned by userRef.remove() is not giving any error, it always goes to then block even though if I change the non existing path dbRef.child('userssafasfsadf/' + userID); like so.
function deleteButtonClicked(e) {
e.stopPropagation();
var userID = e.target.getAttribute("userid");
const userRef = dbRef.child('users/' + userID);
userRef.remove()
.then(() => {
console.log('success!, show alert now');
})
.catch(err => {
console.log('errorcode', err.code);
});
}
Any help would be appreciated. Thanks.

It sounds like you're expecting the remove() function to generate an error if there was no data at the given location. It doesn't work that way, because the remove() is not transactional. Someone else could have removed the data a split second ahead of you, and that's OK. Database operations only return errors when a security rule is violated.

Related

Approach to selecting a document

I am using Couchbase in a node app. Every time I insert a document, I am using a random UUID.
It inserts fine and I could retrieve data based on this id.
But in reality, I actually want to search by a key called url in the document. To be able to get or update or delete a document.
I could possibly add the url as the id I suppose but that is not what I see in any database concepts. Ids are not urls
or any unique names. They are typically random numbers or incremental numbers.
How could I approach this so that I can use a random UUID as id but be able to search by url?
Cos lets say the id was 56475-asdf-7856, I am not going to know this value to search for right.
Whereas if the id was https://www.example.com I know about this url and searching for it would give me what I want.
Is it a good idea making the url the id.
This is in a node app using Couchbase.
databaseRouter.put('/update/:id', (req, res) => {
updateDocument(req)
.then(({ document, error }) => {
if (error) {
res.status(404).send(error);
}
res.json(document);
})
.catch(error => res.status(500).send(error));
});
export const updateDocument = async (req) => {
try {
const result = await collection.get(req.params.id); // Feels like id should be the way to do this, but doesn't make sense cos I won't know the id beforehand.
document.url = req.body.url || document.url;
await collection.replace(req.params.id, document);
return { document };
} catch (error) {
return { error };
}
};
I think it's okay to use URLs as IDs, especially if that's the primary way you're going to lookup documents, and you don't need to change the URL later. Yes, often times IDs are numbers or UUIDs, but there is no reason you have to be restricted to this.
However, another approach you can take is to use a SQL query (SQL++, technically, since this is a JSON database).
Something like:
SELECT d.*
FROM mybucket.myscope.mydocuments d
WHERE d.url = 'http://example.com/foo/baz/bar'
You'll also need an index with that, something like:
CREATE INDEX ix_url ON mybucket.myscope.mydocuments (url)
I'd recommend checking out the docs for writing a SQL++ query (sometimes still known as "N1QL") with Node.js: https://docs.couchbase.com/nodejs-sdk/current/howtos/n1ql-queries-with-sdk.html
Here's the first example in the docs:
async function queryPlaceholders() {
const query = `
SELECT airportname, city FROM \`travel-sample\`.inventory.airport
WHERE city=$1
`;
const options = { parameters: ['San Jose'] }
try {
let result = await cluster.query(query, options)
console.log("Result:", result)
return result
} catch (error) {
console.error('Query failed: ', error)
}
}

Code 9: Firebase Scheduled Export - 'The requested snapshot version is too old.'

I have encountered a new error that has recently occurred. As part of a scheduled backup function, I explore a copy go each datastore and save in a bucket for later use. The following syntax has worked well over the last year, however, I suspect due to load, has now stopped working.
async function getDataStore(collection) {
return admin.firestore().collection(collection).get()
.then(querySnapshot => {
if (querySnapshot.size == 0) {
console.log('No matching request for: ' + collection);
return []
} else {
const data = [];
//Query snapshot line throwing snapshot too old error.
querySnapshot.forEach(doc => {
let data_temp = doc.data();
data_temp.doc_id = doc.id;
data.push(data_temp);
});
return data;
}
});
}
This now throws a code 9, the requested snapshot version is too old. One way I can think of overcoming this, would be to batch the request into smaller 'chunks' and save. however, I wanted to see if there was something more efficient I may be missing. Fresh eyes are always helpful.
Thanks

Ban/kick command crashes on use

So, I am making a public discord bot, but I am having trouble with one part of my script. My kick/ban commands are made to be done $ban #user It has to be done in a ping. Since this is public, I really want to fix this. I don't want one person to mess up and crash it to crash it for all servers. If someone does $ban user not in a ping, it crashes the bot. Here is my code:
client.on("message", (message) => {
if (message.content.startsWith("$kick")) {
if (!message.member.roles.find("name", "MODS"))
return;
// Easy way to get member object though mentions.
var member = message.mentions.members.first();
// Kick
member.kick().then((member) => {
// Successmessage
message.channel.send(":wave: " + member.displayName + " has been successfully kicked :point_right: ");
}).catch(() => {
// Failmessage
message.channel.send("Access Denied");
});
}
});
I don't want my bot to keep crashing to ruin the use for others, can anyone help out?
Your code crashed when you have no mention because you did not catch this use case.
Adding a simple catch, with a return for example, should work for you :
client.on("message", (message) => {
if (message.content.startsWith("$kick")) {
if(!message.member.roles.find("name", "MODS"))
return;
// Easy way to get member object though mentions.
var member= message.mentions.members.first();
// No mentions catch
if (member === undefined) return;
// Kick
member.kick().then((member) => {
// Successmessage
message.channel.send(":wave: " + member.displayName + " has been successfully kicked :point_right: ");
}).catch(() => {
// Failmessage
message.channel.send("Access Denied");
});
}
});
I think what is happening when you type $ban user (Which isn't a mention), and later when you assign var member = message.mentions.members.first(); it gives you null (Because no one was mentioned). Try to make sure that message.mentions.members isn't empty.
Cheers :)

Add Firebase Firestore DB listener from Node.js Cloud Function

My issue, cannot read the data from the write DB callback, check below for more details
I am using firestore with node.js cloud function, and I need to set DB listener to messages collection, below is the code of setting listener to the data and the data structure, and my issue that I cann please check the following data structure
Here is the second level and the added message
exports.sendNotificationDependsOnEvent = functions.firestore.document('events/{event}/messages/{message}')
.onCreate((snap, context) => {
const document = snap.val();
// I tried snap.val() and it's not worked
//and I tried snap.data (give me very long un related data)
//and I tried snap.data() and it throwing exception (data is not a function)
//and I tried snap.current.val (and no result for that)
const text = document.message;
console.log("Step 3 : get message text : " + text);
});
advise how can I read data from above data
Your problem most probably comes from the fact that snap does not exist. You may have an error in the way you build the reference.
As detailed in the doc (https://firebase.google.com/docs/firestore/query-data/get-data#get_a_document) it is recommended to check if the doc exist before trying to get its field values.
See this example (for node.js) from the doc referenced above:
var cityRef = db.collection('cities').doc('SF');
var getDoc = cityRef.get()
.then(doc => {
if (!doc.exists) {
console.log('No such document!');
} else {
console.log('Document data:', doc.data());
}
})
.catch(err => {
console.log('Error getting document', err);
});
Can you check, in your code, if snap really exist, as follow?
exports.sendNotificationDependsOnEvent = functions.firestore.document('events/{event}/messages/{message}')
.onCreate((snap, context) => {
if (!snap.exists) {
console.log('No such document!');
} else {
console.log('Document data:', snap.data());
}
});
The console will log in the Functions Log.

Best practices for waiting on the result of a function in Meteor?

I've got this function that involves uploading an image to Cloudinary, and then setting the component's state to be the resulting URL. Here's what it looks like:
loadFileFront: function(e) {
var imageFrontURL = window.webkitURL.createObjectURL(e.target.files[0]);
var imageFrontFile = e.target.files[0];
var returnedURL = '';
Cloudinary._upload_file(imageFrontFile, {}, function(err, res) {
if (err){
console.log(err);
return;
}
console.log(res.url);
});
this.setState({
imageFront: returnedURL,
imageFrontFile: imageFrontFile
})
},
(Ignore that top line with createObjectURL).
I've been doing a bunch of research into how best to structure this so that setState waits on the the upload to complete the the res.url to be returned, thus updating the state properly. When I console.log res.url, after a few seconds it shows up. However when I try to set returnedURL to res.url, there's no waiting and it just jumps ahead through the rest of the function.
What's the best way to wait on the result of the Cloudinary upload here? I've been reading about the async / await support in Meteor 1.3, but I've been having trouble figuring out how to configure this Cloudinary upload method in a Meteor method on the server. Any help is appreciated!
If I understand the problem correctly, then this should fix it. You want to do a fat arrow function on the callback so you can correctly pass (this), and won't have any issues calling this.setState. Also since the key and value of imageFrontFile are the same, you can use it as I typed it below. Hope that helps.
loadFileFront: function(e) {
var imageFrontURL = window.webkitURL.createObjectURL(e.target.files[0]);
var imageFrontFile = e.target.files[0];
var returnedURL = '';
Cloudinary._upload_file(imageFrontFile, {}, (err, res) => {
if (err){
console.log(err);
return;
}
this.setState({
imageFront: res.url,
imageFrontFile
});
});
},
I think you can do the job with future. (https://www.npmjs.com/package/future)
Here's an example : https://www.discovermeteor.com/patterns/5828399

Categories