Firebase Request Timeout Feature [duplicate] - firebase

I'm trying to create a cloud function for firebase that remove a user depending on the delay value and insert back the after the number of delay.
exports.delayqueue = functions.database.ref('/queues/{queueid}/members/{memberid}').onWrite(event => {
var members = event.data.ref.parent;
var user = event.data;
var queueid = members.parent;
var userid = event.params.memberid;
var delayfor = user.child('delay').val();
var name = user.child('name').val();
if(delayfor != 0){
members.child(event.params.memberid).remove();
join(userid,queueid,delayfor,name);
return;
}else{
return;
}
});
function join(userid,queueid,delayfor,name){
setTimeout(function(){
var ref = db.ref("queues/queueid/members/userid");
ref.set({
name: name,
timestamp: Date.now(),
delay : 0
});
}, delayfor*1000);
};
But it's not working can someone help?

You'll need to wrap your setTimeout in a Promise:
exports.delayqueue = functions.database.ref('/queues/{queueid}/members/{memberid}').onWrite(event => {
var members = event.data.ref.parent;
var user = event.data;
var queueid = members.parent;
var userid = event.params.memberid;
var delayfor = user.child('delay').val();
var name = user.child('name').val();
if (delayfor !== 0){
members.child(event.params.memberid).remove();
return join(userid,queueid,delayfor,name);
} else {
return;
}
});
function join(userid,queueid,delayfor,name){
return new Promise((resolve, reject) => {
setTimeout(function(){
var ref = db.ref("queues/queueid/members/userid");
ref.set({
name: name,
timestamp: Date.now(),
delay : 0
}).then(resolve, reject);
}, delayfor*1000);
});
};
Note that the time spent waiting for setTimeout is billed as function execution time and is also subject to the function timeout. If you're only delaying a few seconds, that might be okay, but if the delay is expected to be minutes this solution isn't going to be viable or cost-effective.

Related

Firestore update document on beforeunload

How can I update a document in Firestore on beforeunload?
function sleep() {
var start = new Date().getTime();
while (new Date().getTime() < start + 3000);
}
window.addEventListener("beforeunload", function(event) {
const ref = db.collection('users').doc(currentUser.uid);
ref.update({
profiles: true
}).then(function() {
console.log("Added!");
});
console.log("Blocking for 3 seconds...");
sleep();
console.log("Done!!");
});
Seems like ref.update() is never called? Any idea why that's the case?

Using Meteor.wrapAsync to wrap a callback inside a method

This Meteor code is giving the error:
Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.
I tried Meteor.bindEnvironment for no avail and want to try Meteor.wrapAsync. I could not figure it out from the docs. Could some one please help me with the syntax? thx
Meteor.methods({
'createTransaction':
function (nonceFromTheClient, Payment) {
let user = Meteor.user();
gateway.transaction.sale(
{
arg_object
},
function (err, success) {
if (!err) {
//do stuff here
}
}
);
}
});
Wrap in Meteor.wrapAsync
Meteor.methods({
'createTransaction':
function (nonceFromTheClient, Payment) {
this.unblock();
let user = Meteor.user();
var sale = Meteor.wrapAsync(gateway.transaction.sale);
var res = sale({arg_object});
future.return(res);
return future.wait();
}
});
Or try wrapping it in Fiber
var Fiber = Npm.require('fibers');
Meteor.methods({
'createTransaction': function (nonceFromTheClient, Payment) {
Fiber(function() {
let user = Meteor.user();
gateway.transaction.sale(
{
arg_object
},
function (err, success) {
if (!err) {
//do stuff here
}
}
);
}).run()
}
});
Update: Here's how I handle stripe with Async.runSync and Meteor.bindEnvironment
var stripe = require("stripe")(Meteor.settings.private.StripeKeys.secretKey);
Meteor.methods({
'stripeToken': function() {
this.unblock();
var future = new Future();
var encrypted = CryptoJS.AES.encrypt(Meteor.userId(), userIdEncryptionToken);
future.return(encrypted.toString());
return future.wait();
},
'stripePayment': function(token) {
var userId = Meteor.userId();
var totalPrice = 0;
//calculate total price from collection
totalPrice = Math.ceil(totalPrice * 100) / 100;
userEmail = Meteor.users.findOne({
'_id': userId
}).emails[0].address;
// Create a charge: this will charge the user's card
var now = new Date();
Async.runSync(function(done) {
var charge = stripe.charges.create({
amount: Math.ceil(totalPrice * 100), // Amount in cents // coverting dollars to cents
currency: "usd",
source: token,
receipt_email: userEmail,
description: "Charging"
}, Meteor.bindEnvironment(function(err, charge) {
if (err) {
//handle errors with a switch case for different errors
done();
} else {
//handle res, update order
}
}));
}); // Async.runSync
},
});

Firebase return multiple objects

I am using firebase and in below query extand() is a function that concatenate the objects. Can some one help me to remove $timeout from my query ?
currently i am waiting for my playerList to fill.
var getJoinedPlayers = function(gameId){
var deferred = $q.defer();
var playerList = {};
var usersRef = new Firebase(FBURL+'users');
var gameRef = new Firebase(self.firebaseURL);
var gamePlayersRef = gameRef.child(gameId).child("players");
gamePlayersRef.on("child_added", function(snap) {
usersRef.child(snap.key()).once("value", function(data) {
playerList[snap.key()] = extend({'playerId': snap.key()},data.val());
})
});
$timeout(function() {
if (playerList) {
deferred.resolve(playerList);
} else {
reason = {'message': "player Not found"};
deferred.reject(reason);
}
}, 1300);
return deferred.promise;
};
I would simplify this by replacing "child_added" with "value". This will return the list of players, which you could iterate over with regular JS.
Then call
usersRef.child(snap.key()).once("value", function(data)
for each of of the items in the result, and push each of these promises into an array
promiseArray.push(usersRef.child(snap.key()).once("value", function(data)...
then you could
$q.all(promiseArray).then(...
that will combine all promises into a single promise

Meteor app stuck at 100% CPU when client loads - how to fix?

My meteor app has been hitting 100% cpu on the server when I load certain pages of the app on the client. It causes the app to hang for other clients. How can I fix it?
I suspect that I can improve performance by publishing or subscribing more efficiently for those particular pages. I am not sure, however, if doing more calculations in the publish functions to reduce the fields being sent to the client helps or hurts. While the data size being sent decreases, the number of calculations before sending the data increases. Should I optimize for more calculations and less data or less calculations and more data? Specifically, what criteria do I use to decide?
My publish function:
Meteor.publish('userdata', function(id) {
if (!this.userId) return [];
var user = Meteor.users.findOne(this.userId);
if (!user) return [];
if (isStaff(this.userId)) user = Meteor.users.findOne(id);
var tasks;
var emails = [];
var network = user.users ? [user.users] : [];
var meals;
if (isStaff(this.userId) && this.userId === id) { //staff looking at own profile
tasks = Tasks.find({users: this.userId, status: "active"}, {sort: { taskName: 1 } });
emails = Emails.find({staffId: id});
meals = Meals.find({userId: this.userId});
}
else { //staff looking at other profiles
meals = Meals.find({userId: id});
var completedTasks = [];
if (user.userTaskStatus) {
completedTasks = user.userTaskStatus.map(function (thisTaskStatus) {
if (thisTaskStatus.status !== "incomplete") return thisTaskStatus.taskId;
});
}
var allUserTasks = Tasks.find({users: user._id});
var showTaskIds = [];
allUserTasks.forEach(function (thisTask) {
if (!thisTask.prereqs) showTaskIds.push(thisTask._id);
else {
var prereqs = thisTask.prereqs;
var pushTaskFlag = true;
for(var i=0; i<prereqs.length; i++)
if (completedTasks.indexOf(prereqs[i]) < 0) {
pushTaskFlag = false;
break;
}
if (pushTaskFlag) showTaskIds.push(thisTask._id);
}
});
tasks = Tasks.find({_id: {$in: showTaskIds}, visible: true, status: "active"}, {sort: { taskName: 1 } });
var network = user.users ? user.users.push(id) : [id];
if (isStaff(this.userId)) emails = Emails.find({userId: {$in: network}}, {sort: {date: -1}});
}
network.push(user._id);
var calls = Calls.find({$or: [{to:user.phone},{from:user.phone}] });
var callStaffIds = calls.map(function (thisCall) {
return thisCall.staff;
});
var callNoteIds = calls.map(function (thisCall) {
return thisCall.noteId;
});
var notes = Notes.find({
$or:[
{userId: this.userId},
{noteId: {$in: callNoteIds}}
]
});
var noteStaffIds = notes.map(function (thisNote) {
return thisNote.staff;
});
var allUserIds = network.concat(callStaffIds, noteStaffIds);
var groups = [];
if (user.groups) groups = user.groups;
return [
Meteor.users.find({_id: {$in: allUserIds}}, {fields: {services: 0}}),
tasks,
Groups.find({_id: {$in: groups}}, {sort: { groupName: 1 } }),
emails,
calls,
notes,
meals
];
});

How do I test to see if a doc exists based off of a date field?

I have a Template helper that attempting to return the current "Day" from the database. What's happening is that even though the current day or date exists in the database, for some reason my helper doesn't see that and creates another date.
client:
Template.days.helpers({
day: function() {
console.log("day called");
var now = new Date();
var month = now.getUTCMonth();
var day = now.getUTCDate();
var year = now.getUTCFullYear();
var bottomRangeDate = new Date(year, month, day);
var topRangeDate = new Date(year, month, day + 1);
// console.log('bottomRangeDate', bottomRangeDate);
// console.log('topRangeDate', topRangeDate);
var currentDay = Days.findOne({"date": {"$gte": bottomRangeDate, "$lt": topRangeDate }});
// console.log(currentDay);
if (currentDay !== undefined) {
// console.log("current day exists");
Session.set('currentDayId', currentDay._id);
return currentDay;
} else {
// console.log('current day is undefined');
Meteor.call('createDay', now, function(error, result) {
if(!error)
Session.set('currentDayId', result);
});
// console.log("current day does not exist");
}
}
});
server:
Meteor.methods({
createDay: function(date) {
console.log("date ", date);
var dayId = Days.insert({
date: date
});
return dayId;
}
});
So what I need to do is to see if today or "date" exists in the database, and if it does return it. If does not, I need to create it.
Edit
Here's a screen shot console after refreshing the browser and call find().fetch() on the collection.
Edit #2
I changed the code up a little to try and get it to work with moment:
Template.days.helpers({
day: function() {
var bottomRangeDate = moment().startOf('day').toDate();
var topRangeDate = moment().endOf('day').toDate();
var now = new Date();
console.log('bottomRangeDate: ', bottomRangeDate);
console.log('topRangeDate: ', topRangeDate);
var currentDay = Days.findOne({"date": {"$gte": bottomRangeDate, "$lt": topRangeDate }});
if (currentDay !== undefined) {
Session.set('currentDayId', currentDay._id);
return currentDay;
} else {
Meteor.call('createDay', now, function(error, result) {
if(!error) {
Session.set('currentDayId', result);
return Days.findOne({_id: result });
}
});
}
}
});
I'm still getting duplicates:

Resources