Reputation: 13
I am working on medical reminder app, the user sets reminder to take medication at different frequency and time of the day, for example he can set time to 10 am 12 00 pm , 17;00pm. and i set my cron to send reminders at those specific times . My challenge is , i want to be able to pause the reminder by toggling. but i keep getting empty job when an instance of the scheduler has ran at a specific time. for example if it ran at 10 am, and i pause it after, i get no job found , and yet a gain the schedule still runs after . What am i doing wrong in my code.
const mongoose = require('mongoose');
const { toJSON, paginate } = require('./plugins');
const schedule = require('node-schedule');
const sendPushNotification = require('../lib/firebasePushNotification');
const DEFAULT_REMIND_BEFORE_MINUTES = 15; // Default remind before time in minutes
const reminderSchema = mongoose.Schema(
{
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Patient',
required: true
},
reminderType: {
type: String,
enum: ['Medication', 'Appointment', 'Test', 'Other'],
required: true,
default:'Medication'
},
title: {
type: String,
required: true
},
details: {
type: {
doseAmount: String,
frequency: {
type: String,
enum: ['once','daily','weekly','monthly','yearly']
},// daily, weekly,monthly
startDate: Date,
endDate: Date,
timesOfDay: [String] // Array to store the times of day for medication
},
required: function () {
return this.reminderType === 'Medication'; // Details are required only if the reminder type is 'Medication'
}
},
description: {
type: String
},
remindBefore: {
type: Number, // Value in minutes
default: DEFAULT_REMIND_BEFORE_MINUTES
},
date: {
type: Date,
},
paused: {
type: Boolean,
default: false
},
completed: {
type: Boolean,
default: false
},
jobIds: [{ type: String }] // Array to store job IDs
},
{
timestamps: true,
}
);
// add plugin that converts mongoose to json
reminderSchema.plugin(toJSON);
reminderSchema.plugin(paginate);
// Format time nicely
function formatTime(date) {
return date.toLocaleTimeString('en-US', {
hour: '2-digit',
minute: '2-digit',
});
}
// Schedule reminder
reminderSchema.pre('save', async function (next) {
console.log('scheduling...............')
const reminder = this;
const remindBefore = reminder.remindBefore || DEFAULT_REMIND_BEFORE_MINUTES;
// Helper function to schedule a single reminder
const scheduleReminder = async (reminderDate) => {
const jobDate = new Date(reminderDate.getTime() - remindBefore * 60000);
const jobId = reminder._id.toString();
// If the reminder is not paused, schedule the job
let job;
if (!reminder.paused) {
job = schedule.scheduleJob(jobId, jobDate, async function () {
const formattedTime = formatTime(new Date(reminderDate.getTime()));
const message = `Reminder: ${reminder.title} - ${reminder.reminderType}! Time: ${formattedTime}`;
console.log(message);
await sendPushNotification(reminder.userId, "Reminder", message, 'MEDICAL_REMINDER');
});
// Update the jobIds array
reminder.jobIds = [jobId];
} else {
// const allJobs = schedule.scheduledJobs;
const existingJob = schedule.scheduledJobs[jobId];
// console.log(allJobs)
existingJob.cancel();
}
};
// Schedule based on reminder type
if (reminder.reminderType === 'Medication') {
// Schedule medication reminders
// Calculate reminder times
const reminderTimes = [];
let currentDate = new Date(reminder.details.startDate);
const endDate = new Date(reminder.details.endDate) || currentDate; // default to start date when the end date is not provided
while (currentDate <= endDate) {
reminder.details.timesOfDay.forEach(timeOfDay => {
const timeParts = timeOfDay.split(':');
const jobDate = new Date(currentDate);
jobDate.setHours(parseInt(timeParts[0]));
jobDate.setMinutes(parseInt(timeParts[1]));
jobDate.setSeconds(0);
jobDate.setMilliseconds(0);
reminderTimes.push(jobDate);
});
switch (reminder.details.frequency) {
case 'once':
// For once, schedule a single reminder for each time of the day
reminderTimes.forEach(async (time) => {
await scheduleReminder(time);
});
break;
case 'daily':
// For daily, schedule reminders every day for each time of the day
let dailyDate = new Date(currentDate);
while (dailyDate <= endDate) {
reminderTimes.forEach(async (time) => {
await scheduleReminder(new Date(dailyDate.setHours(time.getHours(), time.getMinutes())));
});
dailyDate.setDate(dailyDate.getDate() + 1); // Move to the next day
}
break;
case 'weekly':
// For weekly, schedule reminders every week for each time of the day
let weeklyDate = new Date(currentDate);
while (weeklyDate <= endDate) {
reminderTimes.forEach(async (time) => {
await scheduleReminder(new Date(weeklyDate.setHours(time.getHours(), time.getMinutes())));
});
weeklyDate.setDate(weeklyDate.getDate() + 7); // Move to the next week
}
break;
case 'monthly':
// For monthly, schedule reminders every month for each time of the day
let monthlyDate = new Date(currentDate);
while (monthlyDate <= endDate) {
reminderTimes.forEach(async (time) => {
await scheduleReminder(new Date(monthlyDate.setHours(time.getHours(), time.getMinutes())));
});
monthlyDate.setMonth(monthlyDate.getMonth() + 1); // Move to the next month
}
break;
case 'yearly':
// For yearly, schedule reminders every year for each time of the day
let yearlyDate = new Date(currentDate);
while (yearlyDate <= endDate) {
reminderTimes.forEach(async (time) => {
await scheduleReminder(new Date(yearlyDate.setHours(time.getHours(), time.getMinutes())));
});
yearlyDate.setFullYear(yearlyDate.getFullYear() + 1); // Move to the next year
}
break;
default:
break;
}
currentDate.setDate(currentDate.getDate() + 1); // Move to the next day
}
} else {
// For non-medication reminders, schedule a single reminder
await scheduleReminder(reminder.date);
}
next();
});
/**
* @typedef Reminder
*/
const Reminder = mongoose.model('Reminder', reminderSchema);
module.exports = Reminder;
I tried checking for all jobs and finding that with specif id but it still failed
Upvotes: 0
Views: 36