User scheduled jobs - javascript

I would like to allow my users set a schedule when they would like a particular action to occur. I use a node server on azure. I am currently looking at node-schedule and would be making use of it. What I am contemplating is running a master schedule every hour that checks the database for user specified schedules and this schedule sets a new schedule based on the schedules from users. But I don't know if this is a good practice, plus I'm concerned about the server load.

You can use node's cron for that, and accommodate in different ways.
The pseudocode below gives a general idea.
var CronJob = require('cron').CronJob;
new CronJob('0 0 * * * *', function () { // every hour
// check schedules planned for the future, stored as ISODate
DB.getUserSchedule({jobdate:{$gte:Date.now()},
function(userSchedules) {
userSchedules.forEach(sched) {
// convert the date back to a string parsed by cron
var d=extractDayHourMin(sched)
var jobtime = d[4] +' '+d[3]+' '+d[2]+' '+d[1]+' '+d[0]
// setup a new job
var job=new CronJob(jobtime, function() {
performUserJob()
job.stop(); // fires only once
DB.removeUserSchedule(userSchedule);
})});
see https://github.com/ncb000gt/node-cron
However, this is possibly not the best solution : this does creates as much process as schedule, so yes, it would consume more resources than required. Instead of scheduling the schedulers, depending on the granularity of the possible calendar (hour, 1/2 hour, 1/4h), you could also query the db every hour (or 30 or 15mn) to retrieve every date that met, and trigger the appropriate function.

Search Quartz schedule.
My project using that to set the time to send email.

Related

How can set wait time in MySQL

Currently, I have a problem like this:
I add a new user to a table "users" with status set to "new". Then after 5 - 15 minutes the status is changed to "Em". It's dependent on how large the data is.
I would like to make a wait time in mySQL to get the status "Em".
how can I make a wait condition until it changes status, maybe in 5 minutes it has changed status already. how can I count those waits and get the status in every minute of waiting
You can guild me by Javascript it's okay.
Thank you so much
I am not entirely clear what your request is. But here I can provide you with some insight. If we need to trace the elapsed time since the creation of a new user and calculate how long it still needs for the new user to reach the em status, we can use a view. And if we want MySQL to update the status automatically when the time is right, we can use an event scheduler to check periodically.
-- Here is the view supposing it takes 600 seconds to reach em since creation
drop view if exists testview;
create view testview as select user_id,user_status,
concat(time_to_sec(now()) - time_to_sec(ts),' seconds have passed since adding the user.') as since_creation,
concat(time_to_sec(date_add(ts, interval + 600 second)) - time_to_sec(now()),' seconds more to reach em status.') as wait_time
from users
where user_status='new';
-- Here is the event scheduler which checks every 10 seconds
set global event_scheduler=on ;
delimiter //
drop event if exists periodic_check //
create event periodic_check on schedule every 10 second starts now() do
BEGIN
update users set user_status='em' where user_status='new'
and time_to_sec(date_add(ts, interval + 600 second)) - time_to_sec(now()) <=0;
END//

How to run a timer on server side

I would like to have a countdown timer always show a countdown for every new user. Basically, if I close the webpage, and reopen it, the timer should still be running. I'm thinking of using the JS variable code functions to define a new client's timezone together with an if statement comment and make it a repeat loop?
Basically, I would want to run a timer on the server side, not the client side.
Has anyone done this before?
Sounds something that you could try to solve with browsers localStorage. If your only requirement is to keep saved time available after you close tab/browser and come back to your page, this is a good fit for you.
Here's a small Codesandbox example code of how to conditionally check and save to localStorage and then start counter based on that value.
https://codesandbox.io/s/4xw97q02m0
EDIT: same code pasted to a post
function setCurrentTime(){
let localStore = window.localStorage.getItem("myTime") // Check if already exists
if(localStore) return localStore
const time = Date.now(); // get current time stamp
window.localStorage.setItem("myTime", time) // Save to localStorage
return time
}
function startCount(){
const time = setCurrentTime()
const elem = document.getElementById("app")
setInterval(() => {
elem.innerHTML = `seconds since time saved:
${Math.floor((Date.now() - time) / 1000)}
`
}, 1000)
}
startCount()
<div id="app"></div>

Continuously check whether or not a date has been expired

Here's our scenario:
We are using node w/ express for our web app and we need to create a background process that continuously checks the created date on multiple posts and when they expire. These expired dates are set by the user so the posts expire at different rates. When the date expires, our app should be triggering specific events.
We are considering using a "setInterval" but wasn't sure if this is the best long-term solution.
Is there a solution to have node continuously check whether or not a date has been expired? Upon expiring, the posts must trigger specific functions.
There are two ways to do this:
1) use moment lib like this:
var date = moment("2013-03-24")
var now = moment();
if (now > date) {
// date is past
} else {
// date is future
}
2) use node-schedule like this:
var schedule = require('node-schedule');
var futureDate = new Date(new Date().getTime() + 60 * 60 * 24 * 1000); // This is 24 hours from *now*
var j = schedule.scheduleJob(futureDate, function(){
console.log('Do your work here.');
});
Im not sure about your code but if u can catch the event when the users post, the easy way would be
setTimeout(whateverYouHaveTodo, expireTimeInMilliseconds);
each time an event is triggered.
And if you need to cancel the timeouts in the future, what i do personally is put the timeouts in a json object with the key as a unique id which you could identify the event specifically

How to execute a function only once in a day(&only if the app is opened)?

Let i have a function
function alert(){
alert("notification")
}
this function is a part of a mobile app, i want to show this alert(execute function) only once in a day only if user opens the app,
if user didn't open the app for so many days it shouldn't execute that function for that much days.
How to implement in javascript?
can anyone provide a common logic that can be used every where even in ios or ionic...etc ?
Select somewhere that you can store persistent data. That will depend on whatever APIs the app supplies.
Use new Date() to find out the current time.
Compare that to the stored time the function last executed fully. If it is less than a day, return immediately.
Otherwise, store the new time and let the rest of the function run.

Get only new "child added" after page load

I have on a website facebook style notification in top right corner. I show there up to 5 latest notifications. I do initial pulling with child_added and also after same firebaseRef child_added listening for new notifications.
Now I'd like to play a sound on new notification and a little number of new notifications.
The only thing I can't figure is how to distinguish when was a new notification and when was it already seen, a.k.a page reload? Is there any other approach than making some new property read?
I was looking around and found some old answers from 2012 with suggestions limitToLast(1) which doesn't help in my case.
EDIT:
https://stackoverflow.com/a/27693310/633154 This #Kato answers recommends to listen only to new notifications which time is more than current Firebase time Firebase.ServerValue.TIMESTAMP. This seems the way to go, but I am creating a new notification with REST API and myself setting timestamp as my server's UTC. So there may be some minor inconsistencies. Shouldn't be a big deal
EDIT 2:
With this query, I'm getting correctly up to 5 last notifications on page load and no new notifications are coming afterwards
notifRef.limitToLast(5).once("value", function(snapshot) {
snapshot.forEach(function(data) {
addNotifications(data.val());
});
});
In the above linked other SO thread #Kato's answer doesn't work, notifRef.orderBy is not a function.
I have tried multiple other versions according to doc
https://www.firebase.com/docs/web/guide/retrieving-data.html#section-queries
My structure is same
{
"messages": {
"$messageid": { // firebase generated key 'JqcEWLFJrl1eaed5naN'
"sender": "kato",
"message": "hello world"
"timestamp": 1433036536108 // Firebase.ServerValue.TIMESTAMP
}
}
}
Here is what i tried to do and errors I'm getting:
var queryRef = notifRef.orderByKey().startAt(Firebase.ServerValue.TIMESTAMP);
Error:Query: When ordering by key, the argument passed to startAt(), endAt(),or equalTo() must be a string.
var queryRef = notifRef.orderByChild('timestamp').startAt(Firebase.ServerValue.TIMESTAMP);
Error: Query: First argument passed to startAt(), endAt(), or equalTo() cannot be an object.
In the documentation I have not seen that to startAt anything but the element position is passed (integer) but not a firebase timestamp object, that's why such error.
Only below compiles, just having startAt without ordering, but it's not shooting any new notifications!
var queryRef = notifRef.startAt(Firebase.ServerValue.TIMESTAMP);
queryRef.on('child_added', function(snap) {
console.log(snap.val());
addNotifications(snap.val());
// TODO clean up if more than 5 notifications
});
Any idea where could be the problem? What is the correct way to listen only to newer notifications than current timestamp?
EDIT 3
Here is my final solution
notifRef.limitToLast(5).once("value", function(snapshot) {
var lastKey = null; // at least 1 key is always present
var count = 0; // because startAt is inclusive, we have to ignore first child_added
snapshot.forEach(function(data) {
addNotifications(data.val());
lastKey = data.key();
});
checkNotifications();
notifRef.orderByKey().startAt(lastKey).on('child_added', function(snap) {
if (count > 0) {
console.log(snap.val());
addNotifications(snap.val());
// TODO clean up if more than 5 notifications
checkNotifications();
}
count++;
});
});
I don't trust browser time, so had to go first by querying last 5 existing keys, and after that passing to startAt the last key I received. notifRef.orderByKey().startAt(lastKey) can't be outside notifRef.limitToLast(5).once("value" because according to doc, once is queried last so the lastKey js variable passed to startAt would be always null.
Also need to have the count variable, because startAt is taking inclusive, but because it was already there, I need to ignore the first one.
Also with this solution when there are more than 5 notifications, I query my backend with checkNotifications only once at the end when notifications are received with once query. Otherwise on child_added it would do up to 5 times on every page load.
If there is anything that could be optimized, please tell
One solution would be to have your local client listen for the last 5 latest notifications via ref.limitToLast(5).on('child_added', ...) and then only render them to the user if some timestamp field on each of those notifications is newer than your local timestamp on the machine.
When writing those notifications from other clients, you could include a timestamp field as specified via Firebase.ServerValue.TIMESTAMP, which will use the server's notion of the Unix timestamp. Readers of that data could then compare that timestamp to their local clock to make the aforementioned determination.

Categories