From 79ff8790b986c61ca47d17795f0273650f101a97 Mon Sep 17 00:00:00 2001 From: Eddy de Vink Date: Sat, 26 Sep 2026 22:28:52 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20serialiseer=20alle=20media-sends=20in=20?= =?UTF-8?q?=C3=A9=C3=A9n=20keten=20+=20pacing=20ertussen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gelijktijdige webhook-requests (afbeeldingen naar verschillende ontvangers) konden overlappen in de ene chromium-tab. nu loopt élke media-send door een seriële keten en eindigt met MEDIA_SEND_DELAY_MS, zodat de tab tussen twee sends rust krijgt. Smoke-test: 3 gelijktijdige sends -> gaps ~delay. --- src/whatsappApi.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/whatsappApi.js b/src/whatsappApi.js index e5b0534..b797eb7 100644 --- a/src/whatsappApi.js +++ b/src/whatsappApi.js @@ -19,6 +19,19 @@ async function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)) } +// Media-send seriële keten: de wwebjs-media-pipeline is EÉN chromium-tab. Zonder +// serialisatie overlappen opeenvolgende media-sends — pagina's van één dienst óf +// afbeeldingen naar verschillende ontvangers bij gelijktijdige webhook-requests. +// Daarom loopt élke media-send door deze ene keten en eindigt elke send met +// MEDIA_SEND_DELAY_MS, zodat de tab tussen twee sends rust krijgt. +let mediaSendChain = Promise.resolve() + +function enqueueSend(run) { + const job = mediaSendChain.then(run, run) + mediaSendChain = job.catch(() => {}) // keten levend houden, ook als een send faalt + return job +} + function isRetryableError(error) { if (error.response) { const status = error.response.status @@ -56,6 +69,10 @@ async function sendTextMessage(chatId, text) { } async function sendImageMessage(chatId, filePath, filename) { + return enqueueSend(() => sendImageMessageInner(chatId, filePath, filename)) +} + +async function sendImageMessageInner(chatId, filePath, filename) { return withRetry(async () => { const fileBuffer = fs.readFileSync(filePath) const base64Data = fileBuffer.toString('base64') @@ -71,7 +88,7 @@ async function sendImageMessage(chatId, filePath, filename) { }) const messageId = response.data?.message?._data?.id?.id registerSend(messageId, chatId, filename) - // Pacing na élke media-send: de wwebjs-media-pipeline is EEN chromium-tab. Twee + // Pacing ná élke media-send: de wwebjs-media-pipeline is EEN chromium-tab. Twee // opeenvolgende media-sends (pagina's van één dienst óf afbeeldingen naar // verschillende ontvangers) mogen niet overlappen — dat veroorzaakt de staged- // ghost-race (2e send verliest). Wacht dus altijd MEDIA_SEND_DELAY_MS ná een send.