Scheduled job running twice (node-schedule)

39 views Asked by At

I'm new to web development and I've run into a problem I can't figure out. I've built a web app where users can create groups and each group has weekly video meetings. I wanted a function that would email users 24 hours before their next meeting, and then email them a survey after their meeting finished. The problem is that my function works fine in testing, but in production it's sending 2 reminder emails and 2 survey emails to each user.

const schedule = require('node-schedule')

const { sendMeetingReminder } = require('./meeting.email.helper')
const { findAllForEmails } = require('../controllers/groupControllers')
const { getNextRecurrenceDate } = require('./meetingRecurrenceDate')

const subjectReminder = 'Dein Gruppen-Meeting beginnt morgen!'
const subjectFeedback = 'Dein Feedback zum letzten Gruppentreffen bei Groupera'

const meetingScheduler = schedule.scheduleJob('0 0 * * *', async () => {
    let currentDate = new Date()

    try {
        const groupsAll = await findAllForEmails()

        const groups = groupsAll.filter((group) => {
            const nextMeeting = getNextRecurrenceDate(
                group.meetings[0],
                currentDate
            )

            const reminder24Hours = new Date(nextMeeting)
            reminder24Hours.setHours(reminder24Hours.getHours() - 24)

            return (
                reminder24Hours >= currentDate &&
                reminder24Hours.getTime() <
                    currentDate.getTime() + 23 * 60 * 60 * 1000
            )
        })


        groups.forEach((group) => {
            const nextMeeting = getNextRecurrenceDate(
                group.meetings[0],
                currentDate
            )

            const reminder24Hours = new Date(nextMeeting)
            reminder24Hours.setHours(reminder24Hours.getHours() - 24)

            const post1Hour = new Date(nextMeeting)
            post1Hour.setMinutes(
                post1Hour.getMinutes() + group.meetings[0].duration
            )

            const reminder = schedule.scheduleJob(reminder24Hours, async () => {
                if (process.env.NODE_ENV === 'development') {
                    console.log(`sending reminder to ${group.name}`)
                } else {
                    await sendMeetingReminder(
                        group.moderator.email,
                        group.moderator.alias,
                        group.name,
                        subjectReminder,
                        24
                    )
                    if (group.members.length >= 1)
                        group.members.forEach(async (member) => {
                            await sendMeetingReminder(
                                member.email,
                                member.alias,
                                group.name,
                                subjectReminder,
                                24
                            )
                        })
                }
                reminder.cancel()
            })

            const survey = schedule.scheduleJob(post1Hour, async () => {
                if (process.env.NODE_ENV === 'development') {
                    console.log(`sending feedback to ${group.name}`)
                } else {
                    await sendMeetingReminder(
                        group.moderator.email,
                        group.moderator.alias,
                        group.name,
                        subjectFeedback,
                        1
                    )
                    if (group.members.length >= 1)
                        group.members.forEach(async (member) => {
                            await sendMeetingReminder(
                                member.email,
                                member.alias,
                                group.name,
                                subjectFeedback,
                                1
                            )
                        })
                }
                survey.cancel()
            })
        })
    } catch (error) {
        console.error('Error fetching groups and meetings:', error)
    }
})

module.exports = { meetingScheduler }

My idea was that this function would run at midnight every day and look for groups whose next meeting was 24 hours later than any time between midnight and 23:00 of that particular day. For example, if Group 1 has a 60 minute meeting at 13:30 on Tuesday then my function running at 00:00 Monday morning will schedule a Group 1 reminder email for 13:30 on Monday and a survey email for 14:30 on Tuesday.

I tested this by changing the parent scheduler to run every 5 minutes, then look for groups who had meetings 24 hours later of any time over the next 5 minutes. It worked perfectly in these circumstances - it filtered the correct groups, sent the correct number of emails, then upon rerunning it filtered new groups and again sent the correct number of emails.

Can anyone tell me why it's sending 2 reminder emails and 2 survey emails in production? It's driving me crazy. Thanks in advance!

0

There are 0 answers