fix: persist weekly brief delivery claims and accepted messages

This commit is contained in:
2026-09-06 14:32:56 +03:00
parent d3a52caf2b
commit 99a7f2f571
6 changed files with 213 additions and 10 deletions
+18 -4
View File
@@ -1,10 +1,11 @@
import { briefWeekKey } from './brief-outbox.mjs';
import { splitBriefText } from './brief-content.mjs';
/** Delivery accounting shared by scheduled and administrator-triggered briefs. */
export function createBriefSender({ store, buildBrief, text, html, telegramConfigured, sendTelegram, emailConfigured, sendEmail, warn = console.warn }) {
export function createBriefSender({ store, buildBrief, text, html, telegramConfigured, sendTelegram, emailConfigured, sendEmail, outbox, clock = () => new Date(), warn = console.warn }) {
return async function sendBrief(tenderGetir) {
const tenders = await tenderGetir();
const r = { kullanici:0, gonderilen:0, bos:0, hata:0, kapali:0, kanalsiz:0,
const r = { kullanici:0, gonderilen:0, bos:0, hata:0, kapali:0, kanalsiz:0, atlanan:0, bekleyen:0,
kanallar:{ telegram:{denenen:0,kabul:0,hata:0}, email:{denenen:0,kabul:0,hata:0} } };
for (const user of store.listUsers()) {
r.kullanici++;
@@ -18,28 +19,41 @@ export function createBriefSender({ store, buildBrief, text, html, telegramConfi
const telegram = store.getData(user.email, 'telegram');
if (telegramConfigured() && telegram?.chatId) {
for (const part of splitBriefText(text(brief))) channels.push({
payload:{channel:'telegram',chatId:telegram.chatId,text:part},
name:'telegram', send:() => sendTelegram(telegram.chatId, part, { parseMode:null }),
valid:receipt => receipt === true,
});
}
if (emailConfigured()) channels.push({
payload:{channel:'email',to:user.email,subject:`İhaleist — Haftalık Brief (${brief.hafta})`,html:html(brief),text:text(brief)},
name:'email', send:() => sendEmail({ to:user.email, subject:`İhaleist — Haftalık Brief (${brief.hafta})`, html:html(brief), text:text(brief) }),
valid:receipt => typeof receipt?.id === 'string' && Boolean(receipt.id.trim()),
});
if (!channels.length) r.kanalsiz++;
if (!channels.length) { r.kanalsiz++; continue; }
const batch = outbox?.prepare(briefWeekKey(clock()),user.email,channels.map(channel=>channel.payload));
if (batch?.changed) { r.bekleyen++; r.hata++; continue; }
const failedChannels = new Set();
for (const channel of channels) {
for (const [position,channel] of channels.entries()) {
if (failedChannels.has(channel.name)) continue;
// An earlier channel can await the network while the user disables briefs.
if (store.getData(user.email, 'brief')?.kapali) { r.kapali++; break; }
const claim = outbox?.claim(batch.id,position,clock().getTime());
if (claim?.state === 'accepted') { r.atlanan++; continue; }
if (claim && claim.state !== 'sending') {
r.bekleyen++; failedChannels.add(channel.name);
if (claim.state === 'uncertain') failed=true;
continue;
}
const counts = r.kanallar[channel.name];
counts.denenen++;
try {
const receipt = await channel.send();
if (!channel.valid(receipt)) throw new Error('Sağlayıcı gönderimi doğrulamadı.');
if (claim) outbox.accept(claim,receipt === true ? 'telegram-accepted' : receipt.id);
counts.kabul++;
accepted = true;
} catch (error) {
if (claim) outbox.hold(claim,error);
counts.hata++;
failedChannels.add(channel.name);
failed = true;