I have firebase cloud schedule function. It works fine for the first two periods, but then it stops. my function codes are below. I am not experienced in javascript. Is there any mistake in my codes?
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(functions.config().firebase); const database = admin.database(); // kapandığı zamandan 30 dk sonra devreye gir. exports.soloTurnuvaTetikleyici = functions.pubsub.schedule("every 360 minutes").onRun((context) => { const peryot = 360; turnuvaGuncelle(peryot, "solo"); return null; }); function turnuvaGuncelle(peryot, oyunTipi) { const kapaliKalmaZamani = Math.floor(Math.random() * 60) + 90; // min 90 dk max 150 dk const kapanistanSonraBekle = 30; // wait after finish const now = new Date().getTime(); const acilisZamani = new Date(now + kapaliKalmaZamani * 60000).getTime(); // open date const kapanisZamani = new Date(now + (peryot - kapanistanSonraBekle) * 60000).getTime(); // close date const tarihler = { acilis: acilisZamani, kapanis: kapanisZamani, }; const diller = ["ar", "bj", "bn", "ca", "cs", "dz", "fr", "hr", "hu", "tr", "ch"]; const ligler = ["1lig", "2lig", "3lig", "4lig", "5lig", "6lig", "7lig", "8lig", "9lig"]; const ref = database.ref("/turnuvalar/"); const updates = {}; diller.forEach((dil) => { ligler.forEach((lig) => { updates[dil + "/" + lig + "/" + oyunTipi + "/info/"] = tarihler; updates[dil + "/" + lig + "/" + oyunTipi + "/matchmaking/"] = null; }); }); ref.update(updates); }
I am attaching the logs. 12:07:04.314 AM -> worked fine
6:07:03,658 AM -> worked fine
12:07:04.314 PM -> not calling
current date now -> 5:14:38.060 PM
it’s supposed to run every 6 hours but it doesn’t work. what do you think is the reason?
Advertisement
Answer
You are not at all taking into account the asynchronous character of the Firebase method you call in your Cloud Function. I don’t know if this is the exact cause of your problem but it will create problems one day or the other, in a way that is difficult to debug because it will appear in a erratic manner, as explained below.
As you will see in the three videos about “JavaScript Promises” from the official Firebase video series you MUST return a Promise or a value in a background triggered Cloud Function when all the asynchronous operations are complete. This indicates to the platform that it was completed, and it avoids the Cloud Function is terminated before the asynchronous operations are done.
In your case, you don’t wait that the asynchronous turnuvaGuncelle()
function is complete before doing return null;
. This indicates to the Cloud Function platform that it can terminate and clean up your function without waiting for the asynchronous turnuvaGuncelle()
function to be complete.
This may cause some erratic behaviour because, it happens sometimes that your Cloud Function is terminated before the asynchronous update operation is complete, but some other times, the Cloud Function platform does not terminate the Function immediately and the asynchronous operation can be completed.
You need to adapt your code as follows (we use async/await
):
// kapandığı zamandan 30 dk sonra devreye gir. exports.soloTurnuvaTetikleyici = functions.pubsub.schedule("every 360 minutes").onRun(async (context) => { const peryot = 360; await turnuvaGuncelle(peryot, "solo"); return null; }); async function turnuvaGuncelle(peryot, oyunTipi) { const kapaliKalmaZamani = Math.floor(Math.random() * 60) + 90; // min 90 dk max 150 dk const kapanistanSonraBekle = 30; // wait after finish const now = new Date().getTime(); const acilisZamani = new Date(now + kapaliKalmaZamani * 60000).getTime(); // open date const kapanisZamani = new Date(now + (peryot - kapanistanSonraBekle) * 60000).getTime(); // close date const tarihler = { acilis: acilisZamani, kapanis: kapanisZamani, }; const diller = ["ar", "bj", "bn", "ca", "cs", "dz", "fr", "hr", "hu", "tr", "ch"]; const ligler = ["1lig", "2lig", "3lig", "4lig", "5lig", "6lig", "7lig", "8lig", "9lig"]; const ref = database.ref("/turnuvalar/"); const updates = {}; diller.forEach((dil) => { ligler.forEach((lig) => { updates[dil + "/" + lig + "/" + oyunTipi + "/info/"] = tarihler; updates[dil + "/" + lig + "/" + oyunTipi + "/matchmaking/"] = null; }); }); await ref.update(updates); }