Hello,
I developed a netlify function who
1 - get a simple string from mongodb
2 - make an external http request
3 - save the resulted data into the previus mongodb database
4 - return the result
My function works like a charm in local. But in production, on netlify, I get always a timeout error.
What can I do to solve it ?
I can’t use background function because I the result of the process directly.
David
@dbconception Is it a timeout on the execution of the function, or on the connection to MongoDB ?
Are you able to provide the error message that you see?
SamO
February 2, 2023, 5:32pm
3
Hi @dbconception can you confirm what your site name/slug is?
Hello Nathan, it’s a timeout of the function execution
Hello,
It’s curious-frangipane-4510b3
Hi @dbconception ,
Function timeout increase is a Pro and above feature. Let us know once you upgrade, so we can bump the time limit.
1 Like
Hello,
I upgrade to pro on the other account. Can you improve the timeout to 20 secondes please ?
David
SamO
February 15, 2023, 5:50pm
8
hi @dbconception , thanks so much for reaching back out! I gave you the bump on your function timeout.
taahir
February 20, 2023, 9:16am
9
Hi Sam0, I still have this error
gualter
February 20, 2023, 10:28am
10
hi @taahir
did you redeploy your site? You’ve got to do it to make this effective
taahir
February 20, 2023, 2:18pm
11
Hi Gualter,
I just redploy and still have a timeout after 20 secondes.
I don’t understand because as you can see on this screenshot my function end on 1 seconde on local env. But on netlify, it end after 20 secondes…
gualter
February 20, 2023, 3:14pm
12
There seems to be something else here. Given the huge difference, probably our environment cannot connect to your database instance. Can you add more logging to help us understand each step the function takes?
Feel free to share the function contents here if that helps!
taahir
February 20, 2023, 5:16pm
13
I added few logs.
Below my code.
import fetch from 'node-fetch';
import * as dotenv from 'dotenv' // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import
dotenv.config()
import { MongoClient, ObjectId } from "mongodb";
/**
*
* @param {*} event
* @returns true or { statusCode, body }
*/
const middleware = function (event) {
const { AUTH_BASIC } = process.env;
if(event.httpMethod !== "GET"){
return {
statusCode: 400
}
}
if("Basic " + AUTH_BASIC !== event.headers.authorization){
return {
statusCode: 401
}
}
return true;
}
const renewTokens = async function (refresh_token, client_secret, client_id) {
const urlSearchParam = new URLSearchParams({
refresh_token: refresh_token,
client_id: client_id,
client_secret: client_secret,
grant_type: 'refresh_token'
});
const options = {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: urlSearchParam.toString()
};
const resp = await fetch('https://oauth.qonto.com/oauth2/token', options)
if(!resp.ok){
console.error(resp.statusText);
console.error(await resp.json())
return null;
}
const qontoResponse = await resp.json();
return qontoResponse;
}
const getCurrentRefreshToken = async function(){
const { BDD_PWD, BDD_DOCUMENT_ID } = process.env;
const uri = "mongodb+srv://******:" + BDD_PWD + "@*********cdz.mongodb.net/?retryWrites=true&w=majority"
const client = new MongoClient(uri);
let document = null;
try {
const database = client.db('taahir_ms');
const collection = database.collection('qonto_coll');
// Query for a movie that has the title 'Back to the Future'
const query = { _id: new ObjectId(BDD_DOCUMENT_ID) };
document = await collection.findOne(query);
} finally {
// Ensures that the client will close when you finish/error
await client.close();
}
if(document && document.refresh_token)
return document.refresh_token;
else
return null;
}
const saveNewRefreshToken = async function(newRefreshToken){
const { BDD_PWD, BDD_DOCUMENT_ID } = process.env;
const uri = "mongodb+srv://******:" + BDD_PWD + "@*********mongodb.net/?retryWrites=true&w=majority"
const client = new MongoClient(uri);
try {
const database = client.db('taahir_ms');
const collection = database.collection('qonto_coll');
const filter = { _id: new ObjectId(BDD_DOCUMENT_ID)};
const updateDocument = {
$set: {
refresh_token: newRefreshToken
}
};
const result = await collection.updateOne(filter, updateDocument)
} finally {
// Ensures that the client will close when you finish/error
await client.close();
}
}
exports.handler = async function (event, context) {
let middlewareResult = middleware(event)
if (middlewareResult !== true) {
return middlewareResult
}
console.log("middleware ok");
const { CLIENT_SECRET, CLIENT_ID } = process.env;
const REFRESH_TOKEN = await getCurrentRefreshToken();
console.log("get current refresh token ok");
if(REFRESH_TOKEN === null){
console.error("can't retrieve the old refresh token")
}
const resp = await renewTokens(REFRESH_TOKEN, CLIENT_SECRET, CLIENT_ID);
console.log("renew token ok");
if(resp === null || !resp.access_token || !resp.refresh_token){
console.error("response incomplete or null")
return {
statusCode: 500,
body: "Failed"
}
}
const { access_token, refresh_token : new_refresh_token } = resp;
await saveNewRefreshToken(new_refresh_token);
console.log("save new token ok");
return {
statusCode: 200,
body: JSON.stringify({accessToken : access_token}),
};
};
gualter
February 20, 2023, 5:29pm
14
thanks. Maybe the issue is a missing environment variable? You’re using them but are you setting them on Netlify?
taahir
February 21, 2023, 7:59am
15
I add few logs to this function :
const getCurrentRefreshToken = async function(){
const { BDD_PWD, BDD_DOCUMENT_ID } = process.env;
const uri = "mongodb+srv://******:" + BDD_PWD + "@cluster0.gcezcdz.mongodb.net/?retryWrites=true&w=majority"
const client = new MongoClient(uri);
let document = null;
try {
const database = client.db('*****');
console.log("getCurrentRefreshToken > db ok")
const collection = database.collection('qonto_coll');
console.log("getCurrentRefreshToken > coll ok")
// Query for a movie that has the title 'Back to the Future'
const query = { _id: new ObjectId(BDD_DOCUMENT_ID) };
document = await collection.findOne(query);
console.log("findone ok", document)
} finally {
// Ensures that the client will close when you finish/error
await client.close();
console.log("getCurrentRefreshToken > client.clos() ok")
}
if(document && document.refresh_token)
return document.refresh_token;
else
return null;
}
And got this on function log :
It seems to be the collection.findOne who block.
After checking environement variables, BDD_PWD and BDD_DOCUMENT_ID are well set in netlify. Do you have an idea of why it block ?
taahir
February 23, 2023, 9:26am
16
Do you have another idea ?
gualter
February 23, 2023, 11:44am
17
not at this stage, can you try to add logs that output both query
and collection
:
try {
const database = client.db('*****');
console.log("getCurrentRefreshToken > db ok")
const collection = database.collection('qonto_coll');
console.log("getCurrentRefreshToken > coll ok")
// Query for a movie that has the title 'Back to the Future'
const query = { _id: new ObjectId(BDD_DOCUMENT_ID) };
console.log(`query: ${query}`)
console.log(`collection: ${collection}`)
document = await collection.findOne(query);
console.log("findone ok", document)
}
taahir
February 23, 2023, 2:37pm
18
I got this :
So I added JSON.serialize on your console.log
And now I got :
Did you try asking MongoDB why your query can be taking longer:
Hello, I have some problems with queries to the collection of users, there are more than 130 thousand documents in it, and when I want to get the data of the (findOne) user, it takes time, and therefore the bot gives with a slight delay, which I...
Reading time: 1 mins 🕑
Likes: 1 ❤
Unfortunately, without seeing your data structure and debugging this by testing your code, we cannot comment anything beyond this. All this is anyways out of our scope of support.