diff --git a/.env.example b/.env.example index 0de1d7e..21102fb 100644 --- a/.env.example +++ b/.env.example @@ -25,7 +25,6 @@ MAX_REQUESTS_PER_DAY=5 ACK_STUCK_TIMEOUT_MS=300000 # 5 min zonder ack 2 = stuck ACK_PRUNED_AFTER_MS=1800000 # 30 min: stale trackings opruimen (loop stopt dan) ACK_CHECK_INTERVAL_MS=30000 # checkinterval (alleen actief als er iets pending is) -MEDIA_SEND_DELAY_MS=500 # wacht ná élke media-send (media-pipeline is één tab; voorkomt overlappende sends) # Admin notifications ADMIN_NUMBER=31612345678@c.us diff --git a/AGENTS.md b/AGENTS.md index 0d07324..22f5e9f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -181,13 +181,11 @@ Sommige mediabestand-verzendingen keren `success` + message-ID terug maar worden - **Pruning** na `ACK_PRUNED_AFTER_MS` (30 min); de check-loop is **activity-driven** (draait alleen bij openstaande tracking, geen polling in rust). - Vereiste aan de bridge: `message_ack` staat sinds 2026-09-24 in wwebjs-api `.env` **niet** meer in `DISABLED_CALLBACKS`; container is daarvoor herstart. - Env-vars: `ACK_STUCK_TIMEOUT_MS` (default 300000), `ACK_PRUNED_AFTER_MS` (default 1800000), `ACK_CHECK_INTERVAL_MS` (default 30000). -- **Media-spreiding:** `MEDIA_SEND_DELAY_MS` (default **500**; praktijktest op 500) - pauzeert **na élke media-send** (in `sendImageMessage`), niet alleen tussen pagina's van - één dienst. De - wwebjs-media-pipeline is EEN chromium-tab; opeenvolgende media-sends — óók naar - verschillende ontvangers — overlappen anders en veroorzaken de staged-ghost-race. - 0 = uitschakelen. (Tijdelijke mitigatie; permanente fix = fork: send óf écht verzenden - óf zichtbaar falen, zie RCA.) +- **Media-pacing zit bridge-breed** (wwebjs-api, niet de bot): de bridge serialiseert + media-sends en wacht `MEDIA_SEND_DELAY_MS` (bridge-.env) tussen twee sends — de + wwebjs-media-pipeline is EEN chromium-tab; opeenvolgende media-sends (van wélke client + ook: dienst-bot, EBS, rss-forward) overlappen anders → staged-ghost-race. De bot zelf + pauzeert niet meer. Logregels: `[ack] track ( → )`, `[ack] delivered ack= `, `[ack] pruned stale entries`. diff --git a/README.md b/README.md index 876c568..47da18d 100644 --- a/README.md +++ b/README.md @@ -190,7 +190,10 @@ sessie — zie AGENTS.md). De bot detecteert dit via `message_ack`-events en waa | `ACK_STUCK_TIMEOUT_MS` | Leeftijd zonder ack 2 = stuck | `300000` (5 min) | | `ACK_PRUNED_AFTER_MS` | Stale tracking opruimen | `1800000` (30 min) | | `ACK_CHECK_INTERVAL_MS` | Checkinterval (alleen actief bij pending) | `30000` | -| `MEDIA_SEND_DELAY_MS` | Wacht ná élke media-send (media-pipeline is één tab; voorkomt overlappende sends naar elk doel) | `500` | + +> **Media-pacing:** zit bridge-breed (wwebjs-api), niet in de bot — zie AGENTS.md. De bot +> pauzeert niet tussen media-sends; de bridge serialiseert ze met `MEDIA_SEND_DELAY_MS` +> (bridge `.env`). Opvallende logregels: `[ack] track …`, `[ack] delivered ack=…`, `[ack] pruned …`. diff --git a/src/messageHandler.js b/src/messageHandler.js index 74affee..e458fea 100644 --- a/src/messageHandler.js +++ b/src/messageHandler.js @@ -68,8 +68,8 @@ async function handleWebhook(payload) { return } - // Pacing gebeurt nu centraal in sendImageMessage (na élke media-send), zodat óók - // afbeeldingen naar verschillende ontvangers niet overlappen in de ene chromium-tab. + // Media-pacing voor opeenvolgende sends gebeurt bridge-breed (wwebjs-api + // serialiseert + throttle de media-sends; MEDIA_SEND_DELAY_MS in bridge-.env). const pngPaths = getPngFilePaths(dienst) if (!pngPaths || pngPaths.length === 0) { await sendTextMessage(author, `Geen pagina's gevonden voor dienst ${dienstnummer}.`) diff --git a/src/whatsappApi.js b/src/whatsappApi.js index b797eb7..1d8e71a 100644 --- a/src/whatsappApi.js +++ b/src/whatsappApi.js @@ -19,19 +19,6 @@ 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 @@ -69,10 +56,6 @@ 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') @@ -88,14 +71,6 @@ async function sendImageMessageInner(chatId, filePath, filename) { }) const messageId = response.data?.message?._data?.id?.id registerSend(messageId, chatId, filename) - // 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. - const mediaSendDelayMs = parseInt(process.env.MEDIA_SEND_DELAY_MS, 10) || 500 - if (mediaSendDelayMs > 0) { - await sleep(mediaSendDelayMs) - } return response.data }, `sendImageMessage ${filename} to ${chatId}`) }