Getting TRIGGER_PAYLOAD_TOO_LARGE error on simple Firebase Cloud Function - node.js

I am getting this error when a cloud function is executed:
Error: TRIGGER_PAYLOAD_TOO_LARGE: This request would cause a function payload exceeding the maximum size allowed.
This is the cloud function causing the error:
exports.inyectSerie = functions.database.ref('forms/{pushId}').onCreate(event => {
if (!admin.apps.length) {
admin.initializeApp();
}
var form = event.val();
var formData = {
serie: form.serie
};
admin.database().ref('series/'+form.serie).set(formData);
});
How do I know this is the function causing the error? I removed all cloud functions from my firebase and it worked as expected. Then I put back this inyectSerie function and it gave me the error again.
This is my firebase structure, being "medidores" node the one with the most data, with 150k records (which doesn't sound like a lot to me):
+fallidas
+forms <-- This has only 20 records
+materiales
+medidores <-- This has 150,000+ records
+series
+users
If you notice, medidores node is never touched on the cloud function.
I searched for the error and only found this other question reporting it, but I think the cloud function causing the problem on that case did access all the records on the db.
The only thing that comes to my mind to be the problem on my case, is that functions.database loads the whole database no matter what.
UPDATE: Even after reducing my trigger to a bare minimum (thanks, James Poag), I am getting the same error.
exports.inyectSerie = functions.database.ref('forms/{pushId}').onCreate(event => {
return null;
});

Related

Serverless lambda - Function not executing completely

I'm using serverless with nodejs. I have lambda function which have around 6 API in it.
All APIs are working except one. But this non-working api is working fine in local serverless offline. After deployment in server, then it is behaving delayed.
Here is skeleton of what I did in api function
let rec_list = await db.sequelize.query(query).spread(rec_list => { return rec_list; }).catch((e)=>{
console.log("error");
throw e;
})
let rec_list2= rec_list .map((rec_list_sub) => {
//some assignment here
//let new_var = {}; // just assignment - no db operation
return new_var;
});
let resultArr = await Promise.all(rec_list2).then((result) => {
return result;
}).catch((e) => {
throw e;
});
let tem_list = await db.mymodel.bulkCreate(resultArr).then(function (li) {
selectedIds = li.map(({ id }) => {
return {
reqId: id,
description: 'sent',
status: 0
}
});
return li;
}).catch(function (err) {
throw err;
});
//send fcm push
//triggering push notification to user
fcm_send_msg("success", "body-message-here",["fdsfdsfdsf-device-id"]); //*--> Push notification is not triggered. When i hit any of api from this same lambda function, then previously called apis' push notification triggered.*
If I place push notification function call which is aysnc (tried with/without await) before bulkcreate call, then it is working but bulk create delayed.
Execution time for lambda function is 6 sec but it took 108ms only. Memory allocated 1024mb but 120mb only used.
I'm going to make a lot of assumptions, so if I am totally off base let me know and I will delete this answer. I assume your lambda is running in a VPC since it is accessing a database. And from your question I am understanding you to be saying that when the call "bulkCreate" happens before the call to "fcm_send_msg" then you are experiencing the issue, but when the call the "fcm_send_msg" happens before the call to "bulkCreate" then you get the notification, but the bulk create is still delayed.
I suspect you may have a permission issue. Lambda uses an ephemeral port range for calls, so you will want to be sure your security groups and NACLs allow the full ephemeral port range from which Lambda may originate the calls. See https://docs.aws.amazon.com/vpc/latest/userguide/vpc-network-acls.html#nacl-ephemeral-ports:
AWS Lambda functions use ports 1024-65535.
You can check the CloudWatch logs for the lambda (from monitoring) to see what it is doing, and if you see things in the logs that seem like something failed and it is retrying it could very well indicate that the calls are being blocked due to security groups or NACLs that don't allow the communication.

Firebase Function returning connection error

I am using firebase functions Database Triggers.
My Function :
exports.function_name = functions.database
.ref("/transact/{entry_type}/{id1}/{id2}/trigger_cross_entry_function")
.onCreate((data, context) => {
console.log("trigger_cross_entry_function value", data.val());
if (data.val() == true) {
console.log("Function Calling parent data");
return data.ref.parent.once('value').then(function(snapshot){
}, function(error) {
// The Promise was rejected.
console.error("THIS IS THE ERROR:"+error);
});
} else {
console.log("Function Returned");
return 0;
}
});
Whenever I want to trigger this function I put trigger_cross_entry_function into that partcular path from the Mobile App. Everything works fine and function is called as expected.
After sometime If I again try to do the same thing it gives me
Function execution took 16 ms, finished with status: 'connection error'
If I restart the function than it again works perfectly.
and If I trigger it continously than it has no issue.
But once I keep it idle and try to trigger it
again after sometime, it gives me this error.
And I am using Firebase Pay as you go Plan.
Also, as you can see I am returning all the promises correctly and function is being triggered everytime but It doesnt go into the function. it just exit with connection error.
What might be the cause for this ? I have a spent a day finding this.
Experiencing the same issue. Looks like Google changed the status of the service to down
https://status.firebase.google.com/incident/Functions/18046
https://status.firebase.google.com/
So most likely the Google side problem.

Firebase Bucket Download File taking a lot of time

I'm developing an app using Firebase as BaaS.
I'm having time problems when I'm uploading an image (with 90KB or less) and triggering a Cloud Function.
My trigger starts when upload ends:
exports.uploadControl = functions.storage.object().onFinalize((req, res) => {
uploadControl.handler(req, res);
return 0;
});
And, inside uploadControl, i have:
return mkdirp(tempLocalDir).then(() => {
console.log('1. mkDirp - OK!');
console.log('2. Download starts...');
return bucket.file(filePath).download();
}).then((content) => {
console.log('3. Download ends');
return 0;
});
This code works fine, but the problem is the time spent between step 2 and 3...
It takes 24 sec or more.
How to solve this? Is there any code problem? Or is there a Firebase setting to solve it?
Tks.
Two things wrong here:
The onFinalize() callback doesn't receive res and req objects like HTTP triggers do. It receives object metadata as the first argument. Read the documentation for details.
background triggers like this one must return a promise when all the work is complete. Otherwise Cloud Functions will shut down the work prematurely, as it has no idea when it's finished. If you want to kick off all that work from another function, it should be returning that promise.
-
exports.uploadControl = functions.storage.object().onFinalize(object => {
return uploadControl.handler(object);
});

Sporadic console message - Request failed with status code 429

I have this error or warning that seems to come up sporadically in the console. In the browser, the request will just hang a little and then eventually load, or eventually timeout. Other times the page will load normally.
Error
getWeather: Error: Request failed with status code 429
For brevity, this is part of my code that seems to produce the error
// get the weather from open weather map
let getWeather = new Promise(function(resolve, reject) {
getCity.then(
apiData => {
axios.all([
axios.get(apiData.weatherUrl),
axios.get(apiData.imageUrl)
])
.then(axios.spread((weatherRes, imageRes) => {
const weather = weatherRes.data;
apiData.weatherForcast = `It's ${weather.main.temp} degrees Celcius in ${weather.name}`;
const imageApiData = imageRes.data;
apiData.largeImageURL = imageApiData.hits[0]['largeImageURL'];
resolve(apiData);
}))
.catch(function (error) {
console.error("getWeather: "+error)
})
},
error => {
reject(error);
res.end("Could not query the get weather");
}
)
});
The error code is related to too many requests. What's causing this and how do I fix it? Perhaps you could dumb it down a little because I'm a bit new to Node. Thanks.
I hope this is not too late to answer your question, but I encountered the same issue when working on a project so perhaps this might still be of use to you.
The code 429 translates to a client error: Too Many Requests.
The API you are trying to call is probably limiting you to do an x amount of requests per hour and you have exceeded it. Check if you are calling the API multiple times, if that is the case you could try to call it just once and place all the data you need into an object or other sorts of data structure then you can just work with that data instead of calling the API.
Hope this helps!

Update value once write completes in Cloud Function

I'm trying to update one value after a write completes (in a Cloud Function) but it just wont work (I'm sure this is a stupidly simple problem). Code below:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const firebase = require('firebase');
admin.initializeApp(functions.config().firebase);
exports.createMessage = functions.https.onRequest((request, response) => {
const json = JSON.parse(request.query.json); // == "{'start':0, 'end':0}"
json.start = firebase.database.ServerValue.TIMESTAMP;
admin.database().ref('/messages/').push(json).then(snapshot => {
//Here is the problem. Whatever I try here it won't work to retrieve the value.
//So, how to I get the "start" value, which has been written to the DB (TIMESTAMP value)?
var startValue = snapshot.ref.child('start').val();
snapshot.ref.update({ end: (startValue + 85800000) }).then(snapshot2=>{
response.redirect(303, snapshot.ref);
});
});
});
Is the problem that I'm using admin.database()?
This code:
var startValue = snapshot.ref.child('start').val();
doesn't actually retrieve any values. Take a look at the docs for DataSnapshot. Reach into that snapshot directly with child() - you don't need the ref. Maybe this is what you meant?
var startValue = snapshot.child('start').val();
I'm not sure if there's a bug in Firebase or if I'm using it wrong, but if I try to call any method on the snapshot-reference I will only get an error saying: TypeError: snapshot.xxx is not a function where xxx is the function name i try to use (for example: child(...), forEach(...), etc).
However, the following seems to fix the issue with the snapshot:
admin.database().ref('/messages/').push(json).once('value').then(snapshot => {
instead of:
admin.database().ref('/messages/').push(json).then(snapshot => {
My uneducated guess is that the then-promise, for the push-function returns some faulty snapshot since the only thing that seems to work is snapshot.key.
Also, if I'm not mistaken, doesn't my solution make two reads now, instead of one? Since push will write and then (supposedly) read and return the written value and then I read it once more with once(value).
Does anyone has any further insights into this problem?

Resources