Firebase Function stops interval after 10 min - firebase

I have a timer function on firebase functions.
My code below
exports.timecontroller = functions.region('europe-west1').firestore.document("DigitalTargets/{digitalTargetID}").onCreate((snap, context) => {
const id = snap.id
const date = new Date(snap.data().endDate.toDate())
var countDownDate = date.getTime();
var myfunc = setInterval(async function () {
var now = new Date().getTime();
var timeleft = countDownDate - now;
db.collection('DigitalTargets').doc(snap.id).get().then(a => {
if (!a.data().isClaimed) {
console.log(timeleft)
if (timeleft < 0) {
db.collection("DigitalTargets").doc(id).update({ isActive: false })
clearInterval(myfunc);
}
}
else {
clearInterval(myfunc);
}
})
}, 1000);
return true;
})
My problem is, when i create a doc it starts the count. I can see on log screen. But after 10 min it stops working. no more logs shown. After expire time its not deactivating doc
What i need:
I placing targets on map and they have end time. I just want to set active false after timer finished.
is there any limitation on firebase functions? if theres ill check every 5 minutes with scheduled function.

From the docs:
The maximum value for timeoutSeconds is 540, or 9 minutes.
https://firebase.google.com/docs/functions/manage-functions
As mentioned, you could use a scheduled function:
exports.myCrontabFunction = functions.pubsub.schedule("every 5 minutes")
.timeZone("Europe/Berlin")
.onRun(async (context) => { ... } );

Sounds like you are using an Event Driven Function that starts when you create a doc.
As per this public documentation you can see that Even Driven Functions times out after 10 mins.
The alternative could be to have that event driven function to make an http request to another function with a higer time out of 60 minutes.

Related

Firebase Scheduled Functions with schedule time less than 1 minute

I'm developing a firebase scheduled function that updates my Firestore collection key-values based on some condition specified in the function. I want this scheduled function to be called every 5 seconds, but as I could understand from the firebase documents that the minimum granularity is 1 minute.
I'm thinking of using a setInterval() where each interval is of 5 seconds and executes the above-discussed function, but I'm not comfortable with such method, as I know this is not the correct way to do it and I may also end up incurring additional charges.
Any idea how to achieve this in a proper way? Thanks in advance.
The immediate and easiest solution I could think of was to use Javascript Interval Timers.
Please use the below given sample code if needed,
const intervalId = setInterval(() => {
// call your main function here
}, MAIN_FUNCTION_INTERVAL * 1000);
// Clear timers before next scheduled cycle i.e. after every 1 minute
await new Promise((resolve) => {
setTimeout(() => {
clearInterval(intervalId);
resolve();
}, (60 - MAIN_FUNCTION_INTERVAL) * 1000);
});
You need to call it multiple times in one schedule event.
const MAX_EXECUTE_TIME =3
const SLEEP_TIME = 18
exports.scheduledFunction = functions.pubsub.schedule('every 1 minutes').onRun((context) => {
for await (const executeTime of [...Array(MAX_EXECUTE_TIME)].map(
(_, i) => i
)) {
console.log("every 20 seconds");
await sleep(SLEEP_TIME);
}
});

I have a problem with autosaving data in VueJS, the autosave doesn't complete when I change the current note

so I have a problem this problem with my app. I'm not sure what is the right way to implement this autosaving feature. When you change the note's title or it's content, there is a debounce function that goes off in 2 seconds and if you change to the current note before the debounce update is complete it never updates. Let me know if I've done a poor job of explaining or if there is something that I need to clarify, Thanks!
Here's a video of what occurs: https://www.loom.com/share/ef5188eec3304b94b05960f403703429
And these are the important methods:
updateNoteTitle(e) {
this.noteData.title = e.target.innerText;
this.debouncedUpdate();
},
updateNoteContent(e) {
this.noteData.content = e;
this.debouncedUpdate();
},
debouncedUpdate: debounce(function () {
this.handleUpdateNote();
}, 2000),
async handleUpdateNote() {
this.state = "loading";
try {
await usersCollection
.doc(this.userId)
.collection("notes")
.doc(this.selectedNote.id)
.update(this.noteData)
.then(() => this.setStateToSaved());
} catch (error) {
this.state = "error";
this.error = error;
}
},
setStateToSaved() {
this.state = "saved";
},
Why running every two seconds ?
And an async wait is a really bad approach in a component.
To autosave the note I recommend that you add an eventListener on window closing or on changing the tab event, Like in the video provided (whatever event suits you best)
created () {
window.addEventListener('beforeunload', this.updateNote)
}
Where your updateNote function is not async.
But if you really want to save on each change.
You can make a computed property that looks like this:
note: {
get() {
return this.noteData.title;
},
set(value) {
this.noteData.title = value;
this.state= 'loading'
usersCollection.doc(this.userId)
.collection("notes")
.doc(this.selectedNote.id)
.update(this.noteData)
.then(() => this.setStateToSaved());
}
},
And the add v-model="note" to your input.
Imagine the user will type 10 characters a second That's 10 calls meaning 10 saves
EDIT:
Add a property called isSaved.
On Note change click if(isSaved === false) call your handleUpdateNote function.
updateNoteTitle(e) {
this.noteData.title = e.target.innerText;
this.isSaved = false;
this.debouncedUpdate();
}
and in your function setStateToSaved add this.isSaved = true ;
I don't know if your side bar is a different component or not.
If it is, and you are using $emit to handle the Note change, then use an event listener combined with the isSaved property.

Meteor Sub/pub with reactive vars break the DDP push?

I try to use reactive vars to filter the published data, on a data list page, users can pickup 2 dates to show the data created during the dates; all works great until i got few computers to access this page at same time; the data changes would not push to every computers automatically- only the computer which makes the change has the new data listed. other computers have to refresh the page manually to see the new data or updated data.
if i remove the reactive vars in the sub/pub, all are good - if one computer changes the data, all computers get the new data immediately and automatically.
i even put the date filter to the helper - still same - no DDP push, same as in the sub/pub.
any ideas? any input are very appreciated.v
sub
Template.TestRV.onCreated(function () {
this.startDate = new ReactiveVar({});
this.endDate =new ReactiveVar({});
var sDate = new Date(new Date().setDate(new Date().getDate() - 30));
var eDate = new Date();
//show last 30 days data by default
this.startDate.set(sDate);
this.endDate.set(eDate);
this.autorun(() => {
this.subscribe('shipAllRV',this.startDate.get(),this.endDate.get());
});
//this.autorun(() => {
//this.subscribe('shipAll');
//});
});
Template.TestRV.helpers({
testListRV: function () {
let start = Template.instance().startDate.get();
let end = Template.instance().endDate.get();
return SHIP.find(
{createdAt: { $lte: end, $gte: start }},
{ sort: { createdAt: -1 } }
);
},
testList: function(){
return SHIP.find({},{ sort: { createdAt:-1} });
}
});
pub -SHIP is my collection
Meteor.publish('shipAll', function() {
return SHIP.find({});
});
Meteor.publish('shipAllRV', function(startDate,endDate) {
return SHIP.find({createdAt:{$lte:endDate,$gte:startDate}},{ sort: { createdAt: -1 } });
});
BTW,
1. i tried session variable is same;
2. if i don’t update the createdAt field in my SHIP.update method, it seems all good even the reactive vars in sub/pub
how can i do it correctly? i need the date filter and DDP push. thanks
Robin

Is it possible to implement an auto logout feature for inactivity?

I am trying to implement the auto logout feature after x mins of inactivity on flutter while using Firebase , authentication method being email.
I have searched online but whatever I've found is not for flutter.
Any help will be greatly appreciated thank you!
you can use interceptor for all api instance like this, but instead customize the onRequest method.
the idea is: save time information when hit api occurred. and then whenever another hit api occur, check duration between now and last saved time.
if the duration is longer than, let's say 5 minutes, then you can call method logout, else you can continue the request
here some snippet to make it clear:
Future<Dio> getApiClient() async {
_dio.interceptors.clear();
_dio.interceptors
.add(InterceptorsWrapper(onRequest: (RequestOptions options) {
// Do something before request is sent
var pref = await SharedPreferences.getInstance();
var timeNow = DateTime.now().millisecondsSinceEpoch;
var lastHitApi = pref.getInt(LAST_HIT_API);
var delay = timeNow - lastHitApi;
pref.setInt(LAST_HIT_API, timeNow);
if (delay > DELAY_MAX) {
// do logout here
}
return options;
},onResponse:(Response response) {
// Do something with response data
return response; // continue
}, onError: (DioError error) async {
// Do something with response error
}));
_dio.options.baseUrl = baseUrl;
return _dio;
}
Edit: i guess this one is more preferable
Set the timeout duration and call logout funtion
Timer(Duration(seconds: 5), () => logOut());

Is there a simple way to simulate lag with Meteor?

is there a way to simulate lag with Meteor? Perhaps something that would delay all calls by say, 300ms?
You can do it in publish using:
Meteor._sleepForMs(5000); // sleeps for 5 seconds
I guess I'm a bit late for the party, but here's a better solution:
There are basically two parts to this question. One is, how to delay Meteor WebSocket (SockJS) writes and one is how to delay HTTP traffic (connect). You'll need to add both of the following snippets to your server-side code in order to delay all traffic sent from the Meteor server.
WebSocket
The hard part was overwriting the WebSocket write to delay it with a setTimeout:
(function () {
// Set the delay you want
var timeout = 3000
// stream_server abstracts sockJS the DDP-Server talks to it.
var streamServer = Meteor.server.stream_server
// The connect event listener
var standardConnect = streamServer.server._events.connection
// Overwrite the default event-handler
streamServer.server._events.connection = function (socket) {
// Overwrite the writes to the socket
var write = socket.write
socket.write = function () {
var self = this
var args = arguments
// Add a delay
setTimeout(function () {
// Call the normal write methods with the arguments passed to this call
write.apply(self, args)
}, timeout)
}
// Call the normal handler after overwritting the socket.write function
standardConnect.apply(this, arguments)
}
})()
HTTP
With connect it's pretty straight forward:
// Add a simple connect handler, wich calls the next handler after a delay
WebApp.rawConnectHandlers.use(function (req, res, next) {
return setTimeout(next, timeout)
})
Not sure about all calls, but you can use Futures to add a lag on the server, that way you can see latency compensation in action.
In a meteor method for example, you can
Meteor.methods({
post: function(post) {
post.title = post.title + (this.isSimulation ? '(client)' : '(server)');
// wait for 5 seconds
if (! this.isSimulation) {
var Future = Npm.require('fibers/future');
var future = new Future();
Meteor.setTimeout(function() {
future.ret();
}, 5 * 1000); // 5 seconds
future.wait();
}
var postId = Posts.insert(post);
return postId;
}
});
This will show the post being inserted with (client) appended to the end, and then 5 seconds later will get the update from the server and post's title will end with (server)
If you want simulate the lag in the subscriptions you can do the next:
Meteor.publish('collection', function(params) {
Meteor._sleepForMs(2000); // Sleep for 2 seconds
return CollectionX.find(params.query,params.projection);
});

Resources