fix: stream newsletter progress to client

This commit is contained in:
Julian Krauser 2025-01-12 13:21:34 +01:00
parent e1f6b36336
commit 1c6c123142
2 changed files with 46 additions and 55 deletions

View file

@ -6,7 +6,10 @@ import NewsletterDatesFactory from "../../../factory/admin/club/newsletter/newsl
import NewsletterRecipientsService from "../../../service/club/newsletter/newsletterRecipientsService"; import NewsletterRecipientsService from "../../../service/club/newsletter/newsletterRecipientsService";
import NewsletterRecipientsFactory from "../../../factory/admin/club/newsletter/newsletterRecipients"; import NewsletterRecipientsFactory from "../../../factory/admin/club/newsletter/newsletterRecipients";
import { FileSystemHelper } from "../../../helpers/fileSystemHelper"; import { FileSystemHelper } from "../../../helpers/fileSystemHelper";
import { CreateNewsletterCommand, SynchronizeNewsletterCommand } from "../../../command/club/newsletter/newsletterCommand"; import {
CreateNewsletterCommand,
SynchronizeNewsletterCommand,
} from "../../../command/club/newsletter/newsletterCommand";
import NewsletterCommandHandler from "../../../command/club/newsletter/newsletterCommandHandler"; import NewsletterCommandHandler from "../../../command/club/newsletter/newsletterCommandHandler";
import { SynchronizeNewsletterDatesCommand } from "../../../command/club/newsletter/newsletterDatesCommand"; import { SynchronizeNewsletterDatesCommand } from "../../../command/club/newsletter/newsletterDatesCommand";
import NewsletterDatesCommandHandler from "../../../command/club/newsletter/newsletterDatesCommandHandler"; import NewsletterDatesCommandHandler from "../../../command/club/newsletter/newsletterDatesCommandHandler";
@ -188,15 +191,14 @@ export async function createNewsletter(req: Request, res: Response): Promise<any
export async function getNewsletterPrintoutProgressById(req: Request, res: Response): Promise<any> { export async function getNewsletterPrintoutProgressById(req: Request, res: Response): Promise<any> {
let newsletterId = parseInt(req.params.newsletterId); let newsletterId = parseInt(req.params.newsletterId);
res.setHeader("Content-Type", "text/event-stream"); res.writeHead(200, {
res.setHeader("Cache-Control", "no-cache"); "Content-Type": "text/plain",
res.setHeader("Connection", "keep-alive"); "Transfer-Encoding": "chunked",
});
res.flushHeaders();
const progressHandler = (data: NewsletterEventType) => { const progressHandler = (data: NewsletterEventType) => {
if (data.newsletterId == newsletterId && data.kind == "pdf") { if (data.newsletterId == newsletterId && data.kind == "pdf") {
res.write(JSON.stringify(data)); res.write(JSON.stringify(data) + "//");
} }
}; };
@ -287,15 +289,14 @@ export async function sendNewsletterById(req: Request, res: Response): Promise<a
export async function getNewsletterSendingProgressById(req: Request, res: Response): Promise<any> { export async function getNewsletterSendingProgressById(req: Request, res: Response): Promise<any> {
let newsletterId = parseInt(req.params.newsletterId); let newsletterId = parseInt(req.params.newsletterId);
res.setHeader("Content-Type", "text/event-stream"); res.writeHead(200, {
res.setHeader("Cache-Control", "no-cache"); "Content-Type": "text/plain",
res.setHeader("Connection", "keep-alive"); "Transfer-Encoding": "chunked",
});
res.flushHeaders();
const progressHandler = (data: NewsletterEventType) => { const progressHandler = (data: NewsletterEventType) => {
if (data.newsletterId == newsletterId && data.kind == "mail") { if (data.newsletterId == newsletterId && data.kind == "mail") {
res.write(JSON.stringify(data)); res.write(JSON.stringify(data) + "//");
} }
}; };

View file

@ -33,12 +33,21 @@ export abstract class NewsletterHelper {
private static formatJobEmit( private static formatJobEmit(
event: "progress" | "complete", event: "progress" | "complete",
kind: "pdf" | "mail", kind: "pdf" | "mail",
factor: "success" | "failed" | "info",
newsletterId: number, newsletterId: number,
total: number, total: number,
iteration: number, iteration: number,
msg: string msg: string
) { ) {
this.jobStatus.emit<NewsletterEventType>(event, { kind, newsletterId, total, iteration, msg, date: new Date() }); this.jobStatus.emit<NewsletterEventType>(event, {
kind,
newsletterId,
factor,
total,
iteration,
msg,
date: new Date(),
});
} }
public static buildData( public static buildData(
@ -169,18 +178,9 @@ export abstract class NewsletterHelper {
allowedForMail.includes(m.sendNewsletter?.type?.id) allowedForMail.includes(m.sendNewsletter?.type?.id)
); );
this.formatJobEmit("progress", "mail", newsletterId, mailRecipients.length, 0, "starting sending"); this.formatJobEmit("progress", "mail", "info", newsletterId, mailRecipients.length, 0, "starting sending");
for (const [index, rec] of mailRecipients.entries()) { for (const [index, rec] of mailRecipients.entries()) {
this.formatJobEmit(
"progress",
"mail",
newsletterId,
mailRecipients.length,
index,
`start sending to ${rec.sendNewsletter.email}`
);
let data = this.buildData(newsletter, dates, rec); let data = this.buildData(newsletter, dates, rec);
const { body } = await TemplateHelper.renderFileForModule({ const { body } = await TemplateHelper.renderFileForModule({
@ -195,9 +195,10 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"progress", "progress",
"mail", "mail",
"success",
newsletterId, newsletterId,
mailRecipients.length, mailRecipients.length,
index, index + 1,
`successfully sent to ${rec.sendNewsletter.email}` `successfully sent to ${rec.sendNewsletter.email}`
); );
}) })
@ -205,9 +206,10 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"progress", "progress",
"mail", "mail",
"failed",
newsletterId, newsletterId,
mailRecipients.length, mailRecipients.length,
index, index + 1,
`failed to send to ${rec.sendNewsletter.email}` `failed to send to ${rec.sendNewsletter.email}`
); );
}); });
@ -216,6 +218,7 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"complete", "complete",
"mail", "mail",
"info",
newsletterId, newsletterId,
mailRecipients.length, mailRecipients.length,
mailRecipients.length, mailRecipients.length,
@ -246,21 +249,12 @@ export abstract class NewsletterHelper {
(m) => !notAllowedForPdf.includes(m.sendNewsletter?.type?.id) || m.sendNewsletter == null (m) => !notAllowedForPdf.includes(m.sendNewsletter?.type?.id) || m.sendNewsletter == null
); );
this.formatJobEmit("progress", "pdf", newsletterId, pdfRecipients.length, 0, "starting sending"); this.formatJobEmit("progress", "pdf", "info", newsletterId, pdfRecipients.length + 1, 0, "starting sending");
for (const [index, rec] of [ for (const [index, rec] of [
...pdfRecipients, ...pdfRecipients,
{ id: 0, firstname: "Alle Mitglieder", lastname: CLUB_NAME } as member, { id: 0, firstname: "Alle Mitglieder", lastname: CLUB_NAME } as member,
].entries()) { ].entries()) {
this.formatJobEmit(
"progress",
"pdf",
newsletterId,
pdfRecipients.length,
index,
`start print for ${rec.lastname}, ${rec.firstname}`
);
let data = this.buildData(newsletter, dates, rec, printWithAdress.includes(rec.sendNewsletter?.type?.id)); let data = this.buildData(newsletter, dates, rec, printWithAdress.includes(rec.sendNewsletter?.type?.id));
await PdfExport.renderFile({ await PdfExport.renderFile({
@ -274,9 +268,10 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"progress", "progress",
"pdf", "pdf",
"success",
newsletterId, newsletterId,
pdfRecipients.length, pdfRecipients.length + 1,
index, index + 1,
`successfully printed for ${rec.lastname}, ${rec.firstname}` `successfully printed for ${rec.lastname}, ${rec.firstname}`
); );
}) })
@ -284,23 +279,15 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"progress", "progress",
"pdf", "pdf",
"failed",
newsletterId, newsletterId,
pdfRecipients.length, pdfRecipients.length + 1,
index, index + 1,
`failed print for ${rec.lastname}, ${rec.firstname}` `failed print for ${rec.lastname}, ${rec.firstname}`
); );
}); });
} }
this.formatJobEmit(
"progress",
"pdf",
newsletterId,
pdfRecipients.length,
pdfRecipients.length,
"starting pdf combine"
);
await PdfExport.sqashToSingleFile( await PdfExport.sqashToSingleFile(
`newsletter/${newsletter.id}_${newsletter.title.replace(" ", "")}`, `newsletter/${newsletter.id}_${newsletter.title.replace(" ", "")}`,
"allPdfsTogether", "allPdfsTogether",
@ -310,9 +297,10 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"progress", "progress",
"pdf", "pdf",
"success",
newsletterId, newsletterId,
pdfRecipients.length, pdfRecipients.length + 1,
pdfRecipients.length, pdfRecipients.length + 1,
"sucessfully combined pdf" "sucessfully combined pdf"
); );
}) })
@ -320,9 +308,10 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"progress", "progress",
"pdf", "pdf",
"failed",
newsletterId, newsletterId,
pdfRecipients.length, pdfRecipients.length + 1,
pdfRecipients.length, pdfRecipients.length + 1,
"failed combining pdf" "failed combining pdf"
); );
}); });
@ -330,9 +319,10 @@ export abstract class NewsletterHelper {
this.formatJobEmit( this.formatJobEmit(
"complete", "complete",
"pdf", "pdf",
"info",
newsletterId, newsletterId,
pdfRecipients.length, pdfRecipients.length + 1,
pdfRecipients.length, pdfRecipients.length + 1,
`completed printing process` `completed printing process`
); );
} }