schedulaer complete
This commit is contained in:
parent
9795aa7cee
commit
da8ce3209a
85
src/schedulers/callScheduler.js
Normal file
85
src/schedulers/callScheduler.js
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
const cron = require('node-cron');
|
||||||
|
const moment = require('moment-timezone');
|
||||||
|
const axios = require('axios');
|
||||||
|
const { User } = require('../models');
|
||||||
|
|
||||||
|
const ongoingCalls = new Map(); // patientId -> { retryCount, lastAttemptTime }
|
||||||
|
|
||||||
|
// Utility to call Retell API
|
||||||
|
async function initiateCall(patient) {
|
||||||
|
const agentId = patient.genderVoiceCall === 'male'
|
||||||
|
? process.env.RETELL_MALE_AGENT_ID
|
||||||
|
: process.env.RETELL_FEMALE_AGENT_ID;
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
method: 'post',
|
||||||
|
url: 'https://api.retellai.com/v2/create-phone-call',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${process.env.RETELL_API_KEY}`,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
data: JSON.stringify({
|
||||||
|
from_number: process.env.RETELL_FROM_NUMBER,
|
||||||
|
to_number: patient.phoneNumber,
|
||||||
|
override_agent_id: agentId
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios(config);
|
||||||
|
console.log(`✅ Call initiated to ${patient.firstName}:`, response.data);
|
||||||
|
return true; // Call initiated successfully
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`❌ Call failed for ${patient.firstName}:`, err.response?.data || err.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cron job: runs every 1 minute
|
||||||
|
cron.schedule('* * * * *', async () => {
|
||||||
|
const nowUtc = moment.utc();
|
||||||
|
|
||||||
|
const patients = await User.findAll({ where: { role: 'patient' } });
|
||||||
|
|
||||||
|
for (const patient of patients) {
|
||||||
|
if (!patient.callTime || !patient.callFrequency || !patient.timeZone) continue;
|
||||||
|
|
||||||
|
const userNow = nowUtc.clone().tz(patient.timeZone);
|
||||||
|
const currentDay = userNow.format('dddd').toLowerCase();
|
||||||
|
|
||||||
|
if (!patient.callFrequency.includes(currentDay)) continue;
|
||||||
|
|
||||||
|
const [startStr, endStr] = patient.callTime.split('-');
|
||||||
|
const startTime = moment.tz(startStr, 'HH:mm', patient.timeZone);
|
||||||
|
const endTime = moment.tz(endStr, 'HH:mm', patient.timeZone);
|
||||||
|
|
||||||
|
if (!userNow.isBetween(startTime, endTime)) continue;
|
||||||
|
|
||||||
|
const callKey = patient.id.toString();
|
||||||
|
const retryInfo = ongoingCalls.get(callKey) || { retryCount: 0, lastAttemptTime: null };
|
||||||
|
|
||||||
|
const retryIntervalMs = {
|
||||||
|
'5m': 5 * 60 * 1000,
|
||||||
|
'10m': 10 * 60 * 1000,
|
||||||
|
'15m': 15 * 60 * 1000,
|
||||||
|
}[patient.retryInterval] || 5 * 60 * 1000;
|
||||||
|
|
||||||
|
const canRetry =
|
||||||
|
!retryInfo.lastAttemptTime ||
|
||||||
|
(Date.now() - retryInfo.lastAttemptTime > retryIntervalMs);
|
||||||
|
|
||||||
|
if (retryInfo.retryCount < patient.maxRetry && canRetry) {
|
||||||
|
const callSuccess = await initiateCall(patient);
|
||||||
|
ongoingCalls.set(callKey, {
|
||||||
|
retryCount: callSuccess ? patient.maxRetry : retryInfo.retryCount + 1,
|
||||||
|
lastAttemptTime: Date.now()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup if maxRetry reached or call was successful
|
||||||
|
if (ongoingCalls.get(callKey)?.retryCount >= patient.maxRetry) {
|
||||||
|
console.log(`📴 Call attempts completed for ${patient.firstName}`);
|
||||||
|
ongoingCalls.delete(callKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user