I have a node js controller
const calculateInitialStartTime = (
startDate,
frequency,
timeOfDay,
dayOfWeek,
dayOfMonth
) => {
let initialStart = new Date(startDate);
if (timeOfDay) {
const [hour, minute] = timeOfDay.split(":");
initialStart.setHours(hour);
initialStart.setMinutes(minute);
initialStart.setSeconds(0);
} else {
initialStart.setHours(7);
initialStart.setMinutes(0);
initialStart.setSeconds(0);
}
switch (frequency) {
case "weekly":
const day = initialStart.getDay();
const targetDay = dayOfWeek || 0;
const diff = (targetDay - day + 7) % 7;
initialStart.setDate(initialStart.getDate() + diff);
break;
case "monthly":
const monthDay = dayOfMonth || 1;
if (initialStart.getDate() > monthDay) {
initialStart.setMonth(initialStart.getMonth() + 1);
}
initialStart.setDate(monthDay);
break;
}
return initialStart;
};
const getCronExpression = (frequency, timeOfDay, dayOfWeek, dayOfMonth) => {
let cronTime = "0 7"; // Default to 7:00 AM
if (timeOfDay) {
const [hour, minute] = timeOfDay.split(":");
cronTime = `${minute} ${hour}`;
}
switch (frequency) {
case "hourly":
return "0 * * * *"; // Every hour at minute 0
case "daily":
return `${cronTime} * * *`; // Daily at specified time
case "weekly":
return `${cronTime} * * ${dayOfWeek || 0}`; // Weekly on specified day and time
case "monthly":
return `${cronTime} ${dayOfMonth || 1} * *`; // Monthly on specified day and time
default:
throw new BadRequestError("Invalid frequency");
}
};
const createThriftSave = async (req, res) => {
const { title, frequency, per, startDate, timeOfDay, dayOfWeek, dayOfMonth } =
req.body;
const { id, email, name } = req.user;
const startDateObj = new Date(startDate);
const initialStartTime = calculateInitialStartTime(
startDate,
frequency,
timeOfDay,
dayOfWeek,
dayOfMonth
);
const cronExpression = getCronExpression(
frequency,
timeOfDay,
dayOfWeek,
dayOfMonth
);
const interest = 0;
const thrift = await ThriftSave.create({
title,
amount: 0,
frequency,
startDate: startDateObj,
per,
interest,
user: id,
});
agenda.define(`thrift job - ${thrift._id}`, async (job, done) => {
try {
const { thriftId, userId } = job.attrs.data;
const thriftSave = await ThriftSave.findOne({ _id: thriftId });
const wallet = await Wallet.findOne({ user: userId });
if (thriftSave.status === "completed") {
await job.remove();
logger.info(`Job removed for completed thrift: ${thriftId}`);
return done();
}
if (!wallet) {
throw new BadRequestError("No Wallet found");
}
if (+wallet.amount < +thriftSave.per) {
await sendFailedWalletDebitEmail({
email,
title: `Thrift - ${thriftSave.title}`,
amount: thriftSave.per,
});
await Transactions.create({
user: id,
username: name,
amount: thriftSave.per,
title: `Thrift - ${thriftSave.title}`,
type: "debit",
status: "success",
});
throw new BadRequestError("Insufficient funds");
}
await Wallet.updateOne(
{ user: userId },
{ $inc: { amount: -thriftSave.per } }
);
await ThriftSave.updateOne(
{ _id: thriftId },
{ $inc: { amount: thriftSave.per } }
);
await Transactions.create({
user: id,
username: name,
amount: thriftSave.per,
title: `Thrift - ${thriftSave.title}`,
type: "debit",
status: "success",
});
done();
} catch (error) {
logger.error(`Error processing thrift job: ${error.message}`);
done(error);
}
});
// Schedule recurring jobs starting after the initial job
agenda.define(`recurringThrift job - ${thrift._id}`, async (job) => {
await agenda.every(cronExpression, `thrift job - ${thrift._id}`, {
thriftId: thrift._id,
userId: id,
});
job.remove(); // Remove the recurring job definition after scheduling the recurring job
});
await agenda.schedule(
initialStartTime,
`recurringThrift job - ${thrift._id}`
);
await sendThriftEmail({ email, title, per, frequency });
res.status(StatusCodes.OK).json({ thrift });
};
It is supposed to schedule a job at a startDate and time and then run the job subsequently by frequency chosen(daily, weekly, monthly), the job should be removed when a another controller is triggered to mark it as complete.. My problem is that the scheduled job never runs on the scheduled startDate and then subsequently(weekly, daily, monthly).
Is there a part of my code i am not getting right.
NB..This is hosted well on a paid render hosting so there are no downtimes between to eliminate the point of server might be asleep when job is supposed to run.