This commit is contained in:
romantarkin 2025-08-17 18:32:34 +05:00
parent 7590afb55c
commit 2f9cdadf01
4 changed files with 25 additions and 81 deletions

View File

@ -23,8 +23,9 @@ const PORT = process.env.PORT || 3000;
(async () => { (async () => {
try { try {
await sequelize.authenticate(); await sequelize.authenticate();
await sequelize.sync({ alter: true }); // Отключаем автоматическую синхронизацию, так как есть проблемы с ключами
console.log('Database connected and models synced'); // await sequelize.sync({ alter: true });
console.log('Database connected');
} catch (err) { } catch (err) {
console.error('Unable to connect to the database:', err); console.error('Unable to connect to the database:', err);
process.exit(1); process.exit(1);

View File

@ -55,7 +55,7 @@ export class DynamicConsumer {
try { try {
await this.consumer.subscribe({ await this.consumer.subscribe({
topic: topicName, topic: topicName,
fromBeginning: false fromBeginning: true
}); });
this.subscribedTopics.add(topicName); this.subscribedTopics.add(topicName);
console.log(`[DynamicConsumer] Subscribed to topic: ${topicName}`); console.log(`[DynamicConsumer] Subscribed to topic: ${topicName}`);
@ -88,7 +88,7 @@ export class DynamicConsumer {
await this.consumer.subscribe( await this.consumer.subscribe(
Array.from(this.subscribedTopics).map(topic => ({ Array.from(this.subscribedTopics).map(topic => ({
topic, topic,
fromBeginning: false fromBeginning: true
})) }))
); );
await this.startConsuming(); await this.startConsuming();
@ -215,17 +215,19 @@ async function processEmailTask(task, topic) {
return; return;
} }
try { // Создаем запись в DeliveryLog со статусом "sent" сразу (так как ENUM не поддерживает 'sending')
await new Promise((resolve) => setTimeout(resolve, 60_000)); console.log(`[DynamicConsumer] Creating DeliveryLog record for campaign ${task.campaignId}, subscriber ${task.subscriberId}`);
deliveryLog = await DeliveryLog.create({
campaign_id: task.campaignId,
subscriber_id: task.subscriberId,
status: 'sent',
sent_at: new Date(),
error_message: null
});
console.log(`[DynamicConsumer] DeliveryLog record created with ID: ${deliveryLog.id}`);
// Создаем запись в DeliveryLog со статусом "sending" try {
deliveryLog = await DeliveryLog.create({ console.log(`[DynamicConsumer] Getting SMTP server with ID: ${task.smtpServerId}`);
campaign_id: task.campaignId,
subscriber_id: task.subscriberId,
status: 'sent',
sent_at: new Date(),
error_message: null
});
// Получаем SMTP-сервер из БД // Получаем SMTP-сервер из БД
const smtp = await SmtpServer.findByPk(task.smtpServerId); const smtp = await SmtpServer.findByPk(task.smtpServerId);
@ -244,7 +246,9 @@ async function processEmailTask(task, topic) {
return; return;
} }
console.log(`[DynamicConsumer] Creating transporter for ${smtp.host}:${smtp.port}, secure: ${smtp.secure}`);
const transporter = nodemailer.createTransport({ const transporter = nodemailer.createTransport({
host: smtp.host,
host: smtp.host, host: smtp.host,
port: smtp.port, port: smtp.port,
secure: smtp.secure, secure: smtp.secure,
@ -253,6 +257,7 @@ async function processEmailTask(task, topic) {
pass: smtp.password, pass: smtp.password,
}, },
}); });
console.log(`[DynamicConsumer] Transporter created successfully`);
const mailOptions = { const mailOptions = {
from: smtp.from_email, from: smtp.from_email,

View File

@ -1,57 +0,0 @@
import { Kafka } from 'kafkajs';
import nodemailer from 'nodemailer';
import { SmtpServer } from '../models/index.js';
const kafka = new Kafka({
clientId: process.env.KAFKA_CLIENT_ID || 'mail-sender',
brokers: [process.env.KAFKA_BROKER || 'localhost:9092'],
});
const consumer = kafka.consumer({ groupId: process.env.KAFKA_GROUP_ID || 'mail-sender-group' });
export async function startMailSender() {
await consumer.connect();
console.log('[mailSender] Consumer connected');
await consumer.subscribe({ topic: /^mail-send-.+$/, fromBeginning: false });
console.log('[mailSender] Subscribed to topics: mail-send-*');
await consumer.run({
eachMessage: async ({ topic, partition, message }) => {
console.log(`[mailSender] Received message: topic=${topic}, partition=${partition}, offset=${message.offset}, value=${message.value.toString()}`);
// Можно раскомментировать для реальной отправки:
// const task = JSON.parse(message.value.toString());
// await processTask(task, topic);
},
});
console.log('[mailSender] Consumer is running and waiting for messages...');
}
// Реальная отправка через SMTP
async function processTask(task, topic) {
try {
// Получаем SMTP-сервер из БД
const smtp = await SmtpServer.findByPk(task.smtpServerId);
if (!smtp) {
console.error('SMTP server not found for id', task.smtpServerId);
return;
}
const transporter = nodemailer.createTransport({
host: smtp.host,
port: smtp.port,
secure: smtp.secure,
auth: {
user: smtp.username,
pass: smtp.password,
},
});
const mailOptions = {
from: smtp.from_email,
to: task.email,
subject: 'Test email',
text: 'This is a test email from mailSender',
html: '<b>This is a test email from mailSender</b>',
};
const info = await transporter.sendMail(mailOptions);
console.log('Email sent:', info.messageId, 'to', task.email);
} catch (err) {
console.error('Error sending email:', err, 'task:', task);
}
}

View File

@ -15,18 +15,12 @@ export async function processScheduledCampaigns() {
const campaigns = await Campaign.findAll({ const campaigns = await Campaign.findAll({
where: { where: {
status: 'scheduled', status: 'scheduled',
// Исключаем кампании, которые уже обрабатываются или отправлены scheduled_at: {
id: { [Op.lte]: new Date() // Только кампании, запланированные на текущее время или в прошлом
[Op.notIn]: sequelize.literal(`(
SELECT DISTINCT campaign_id
FROM delivery_logs
WHERE campaign_id = Campaign.id
)`)
} }
}, },
include: [ include: [
MailingGroup, MailingGroup,
SmtpServer,
{ {
model: EmailTemplateVersion, model: EmailTemplateVersion,
as: 'EmailTemplateVersion' as: 'EmailTemplateVersion'
@ -98,7 +92,8 @@ export async function processScheduledCampaigns() {
}); });
if (campaignLogs.length > 0) { if (campaignLogs.length > 0) {
console.log(`[queueFillerJob] Campaign ${campaign.id} already has delivery logs, skipping`); console.log(`[queueFillerJob] Campaign ${campaign.id} already has delivery logs, updating status to 'sent'`);
await campaign.update({ status: 'sent' });
continue; continue;
} }