Reputation: 255
I am building a website like a game. I want to update users' stats (gold, etc.) every 5 minutes for now. To do this I set up a cronjob running every 5 minutes, no problem. However, it seems like firebase functions might "hang" even though on their site, they go for about 5ms.
I just discovered if I "buy" just when the cronjob runs (the function runs) I see that the "gold" does not get updated probably, it gets set right back to when I started buying.
import * as functions from 'firebase-functions';
import * as admin from "firebase-admin";
import {UnitsDTO} from '../../ProjectXFrontend/src/ModelsDTO/Unit/unitsDTO';
import {CurrencyDTO} from '../../ProjectXFrontend/src/ModelsDTO/Currency/CurrencyDTO';
admin.initializeApp();
export const test = functions.https.onRequest((reques , respon) => {
admin.database().ref('/LastUpdated').set(
admin.database.ServerValue.TIMESTAMP
).then().catch()
return respon.send(reques.ip);
});
export const GetTime = functions.https.onRequest((request , response) => {
return response.send({data: new Date()})
});
export const CalculateBasics = functions.https.onRequest((request , res) => {
if (request.ip === '195.201.26.157') {
CalculateBreeder();
return res.send('ok');
} else {
res.statusCode = 400;
return res.send(new Error('Bad request'))
}
});
export const CalculateIncome = functions.https.onRequest((request , res) => {
if (request.ip === '195.201.26.157') {
CalculateIncomePrivate();
return res.send('ok');
} else {
res.statusCode = 400;
return res.send(new Error('Bad request'))
}
});
function CalculateIncomePrivate() {
admin.database().ref('/users').once('value').then( snap => {
snap.forEach( child => {
const user = child.key // uid
admin.database().ref('users/' + user).once('value').then(snapUser => {
const units = new UnitsDTO();
const currency = new CurrencyDTO();
if (snapUser.hasChild('Units')) { // in units
units.worker = snapUser.child('Units').child('worker').val()
}
if (snapUser.hasChild('currency/gold')) { // gold
currency.goldDto = snapUser.child('currency/gold').val();
}
// calculate news
currency.goldDto.amount += units.worker.amount * units.worker.currencyPerTick;
// set the Income
admin.database().ref('users/' + user + '/currency/gold').set(currency.goldDto).then().catch(error => {console.error(error)})
// update time
admin.database().ref('/status/LastIncome').set(
admin.database.ServerValue.TIMESTAMP
)
.then(() => {
// return res.send('ok');
})
.catch(error => {
// res.statusCode = 500;
// return res.send(error)
});
}).catch(error => {
// res.statusCode = 500;
// return res.send(error);
});
})
}).catch(error => {
// res.statusCode = 500;
// return res.send(error);
})
}
So, the expected result is of course that the function updates the user's income, which it does, however it seems like it "hangs" and that it doesn't quite update correctly, due to user "buying stuff" when the functions runs.
Upvotes: 0
Views: 61
Reputation: 10497
This is an async vs blocking problem.
CalculateIncomePrivate is async, so the code execution will move forward to the next line, returning
So change your function to
function CalculateIncomePrivate()
return admin.database...
And then called it like this:
exports.CalculateIncome....
return CalculateIncomePrivate().then(function(){
resp....
}).catch(function(error){
resp.status(500).send(error);
});
Make sure that any chained promise is returned.
This should help you with promises https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
And this with Firebase Functions Promises https://www.youtube.com/playlist?list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM
Upvotes: 1