In my (express.js based) loopback app I want to schedule a task to run every 1 second. It should count every open ticket, and if they already open for a certain time, then an email should be sent. Below is a simplified code.
The problem, that 'scheduleJob' is logged, as expected, but the number of tickets is not. I think it is a context problem. How should I log the number of the found ticket? How should I communicate back from count 's callback to the schedule 's callback?
var schedule = require('node-schedule');
module.exports = function(app) {
var Ticket = app.models['Ticket']
var j = schedule.scheduleJob('* * * * * *', function(){
console.log('scheduleJob')
Ticket.count(function(err, count){
if (err) {console.log(err)}
console.log(count)
})
});
};
Do not count all the open ticket like that - It costs a lots of resources.
You should keep the number of ticket in your node.js and increase/decrease it. If you have multiple processes interacting with the database, makes one of them your master and make it handle this task.
About your problem, it seems that the library node-schedule do not support asynchronous calls.
Algorithm
At your program start, look up at the ticket in your database and retrieve the next timestamp when you should send an email.
Example, you want to send an email if a ticket is open for 1 hour, and your database have :
ticket 1 / 10 min
ticket 2 / 40 min
So your next mail should be sent in 20 min (60 min - 40 min).
use setTimeout() to wake up your node in 20 min. When you wake up, send the mail, and look at your database again for the next mail to send.
Recalcul your setTimeout if there is a new Ticket inserted in your database or If one get removed/updated.
Related
I'm trying to send an email to the user periodically(daily, weekly, monthly) based on their preference from my nodejs application using node-cron. Here, user can edit/change their mail preference(weekly, daily..etc). so when they do, the cron expression gets updated to match their preference from the backend.
However, the previous preference still getting triggered, I believe that we have to destroy the previous job. how to do it?
Is this the right approach for my problem? or Do I need to store their preferences in database and triggered the mails manually based on the date?
This is how you should do it with node-cron :
const cron = require('node-cron');
const task = cron.schedule('* * * * *', () => {
console.log('stopped task');
}, {
scheduled: true
});
task.start();
task.stop();
task.getStatus(); // get you the status, so for every user check it and then restart it.
task.destroy(); // it will kill the job
It doesn't give any ID, but you can check the processID and store it anywhere.
You can check here for documentation.
I have a simple component to verify user's email. It consists of "Send Email" (that sends email with code) button, text input to enter sent code and "Verify" button that sends code to back for verification. Berification code expires in 5 minutes. And if I resend email new code expires in 5 minutes after resend.
I'm using OnPush change detection strategy so everything is handled with async pipes. The observable wrapping "Send Email" request is passed to template as async pipe. I want to have an other observable that will emit something (e.g. true) when 5 minutes passed. Yes, I can use delay operator in the way like the following
expired$ = sendObservable$.pipe(delay(5 * 60 * 1000), mapTo(true))
But. What if user decide to resend email? How can I restart these 5 minutes from the beginging?
And yes, I understand that all of that is somewhat strange. Maybe there's totaly different way to handle expiration of code using observables and async pipes?
debounceTime delays values emitted by the source Observable, but drops
previous pending delayed emissions if a new value arrives on the
source Observable. This operator keeps track of the most recent value
from the source Observable, and emits that only when dueTime enough
time has passed without any other value appearing on the source
Observable. If a new value appears before dueTime silence occurs, the
previous value will be dropped and will not be emitted on the output
So, simply:
expired$ = sendObservable$.pipe(debounceTime(5 * 60 * 1000))
i want to display when a user last seen online by time like whatsapp
using xmpp and angular
i made an xmpp request and i get user last seen by second and i want to convert it to time
what i got :
user last seen 903 seconds ago
what i want :
user last seen at 11:30 pm
Last Activity Response by Server¶
<iq from='juliet#capulet.com'
id='last1'
to='romeo#montague.net/orchard'
type='result'>
<query xmlns='jabber:iq:last' seconds='903'>Heading Home</query>
</iq>
If you take the seconds value you received from server to a variable, you can do it like below.
const timeInSeconds = getValueFromServer();
const lastLoggedInTime = new Date(Date.now() - timeInSeconds * 1000);
In your html template, you can use lastLoggedInTime variable to show the date.
I am creating a function on my server which is supposed to trigger daily, but not only does it not trigger as expected it triggers every time the server is reset (which it did not do yesterday). The data only needs updated once a day and rapidapi is pay per api call after 100 calls a day, so I'm really trying to get this scheduled job working.
I've only tried node-schedule on my server, which has a dependency of CRON (which is why scheduleJob is using the CRON format). Originally the function triggered as fast as my computer could refresh the server, so I know the scheduleJob is stopping the API call from being constant.
schedule.scheduleJob('* * */23 * *', function () {
console.log('Daily API call initiated.');
unirest.get("https://unogs-unogs-v1.p.rapidapi.com/aaapi.cgi?q=get:exp:US&t=ns&st=adv&p=1")
.header("X-RapidAPI-Host", "unogs-unogs-v1.p.rapidapi.com")
.header("X-RapidAPI-Key", `${keys.RICHARD_UNOGS_KEY}`)
.end(function (result) {
console.log(result.status, result.headers);
//console.log(result.body) to see all data
let data = JSON.stringify(result.body)
fs.writeFile('./movieData.json', data)
});
})
Is there a better way to write this function or achieve the desired results? I only need it triggering once per day, but my computer isn't on 24/7. Since I'm still developing the app, I don't think hosting the server on Heroku or another platform is time-efficient, but I'm more than willing to try it if it'll solve my issue.
The main goal is to tell my server to run it once a day, but to check if it was run in the last 24 hours. If it hasn't been run, run it.
ANSWERED BY jakemingolla: My CRON expression was incorrectly formatted for my intended use. * * */23 * * has the function triggering on every 23rd day (today is the 24th, +1 for index value) with no limitation or other value. That's why my function was calling constantly today. I changed my CRON expression to 15 9 * * * to trigger my API call every morning at 0915 hours.
I'm not sure your CRON format is correct based on https://crontab.guru. Based on * * */23 * *, that would correspond to "“At every minute on every 23rd day-of-month", which does not sound like what you want.
For example, the CRON string 0 0 * * * * is every day at midnight. I would update that CRON string to see if it helps alleviate the problem.
I need to write a php function for sending a Telegram notification after 4 hours.
With the application i'm posting data into a SQL db, after I pressed the Submit button, i need that a php function starts and after 2 days sends to my Telegram channel a notification, with some of the data that i've posted into the db record.
For the posting part and Telegram part i'm ok, i've already linked the website to the channel and normal notifications from php work fine, but i need some advice on the "reminder" part.
I was thinking about some date() function and post the value in to the record, make another var with the date + 2days e make some for or while cycle but i don't think that this can works. Some advice?
I'm new to php, maybe i dont know some function that could help me?
Add to your table a column and name it notification_send and give it a default value of 0
Create a crontab that calls a php file for example:
*/60 * * * * php -f /etc/www/my_notification.php : calls the file every 60 mintues
In this file create a query that selects all the data with the notification_send = 0 then check if the current_date - date column of each row => 2 days :
If so : update the notification_send value to 1 and send your notification
As I commented, your approach is right. As you asked something more, though, I chose to write an answer.
As you asked, when you send a Telegram notification you have to send a reminder notification after 2 days (48h). If I'm right it's an e-mail.
First of all, as you said, you have to create a column to warn when the remember should be send.
Also, to know if the reminder has been sent or not you have to create another column. It could be a flag (true/false) or a datetime column (null = not sent, filled = sent).
Besides that, a cronjob or schedule have to call a PHP script. I'll show to you an example of a PHP script.
I'll call the table as reminder and the column sendIn and isSent.
//select only the reminder that has the sendIn lesser than now and that not has been sent
$statement = $pdo->query("SELECT * FROM reminder WHERE sendIn <= NOW() AND isSent is null");
//prepared statement to update the reminder sent
$updateStatement = $pdo->query("UPDATE reminder SET isSent = NOW() WHERE id = :id");
foreach($statement as $reminder)
{
/**
script to send the reminder
**/
//update the reminder
$updateStatement->execute(array(':id' , $reminder['id']));
}
To create a cronjob, you could take a look here:
https://askubuntu.com/questions/2368/how-do-i-set-up-a-cron-job
You don't need to delete the cron, just let it run periodically and send all your reminders.