Gilbert Okullo
Gilbert Okullo

Reputation: 13

I want cancel node schedule by its name, when its set

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

Answers (0)

Related Questions