feat: media-send pacing na élke send (niet alleen tussen pagina's)
MEDIA_SEND_DELAY_MS pauzeert nu centraal in sendImageMessage ná elke media-send, zodat ook afbeeldingen naar verschillende ontvangers niet overlappen in de ene chromium-tab (staged-ghost race-risico). Per-pagina delay uit messageHandler verwijderd.
This commit is contained in:
parent
4360a0f46e
commit
7673239933
5 changed files with 83 additions and 20 deletions
66
AGENTS.md
66
AGENTS.md
|
|
@ -10,13 +10,18 @@ zag in de chat maar **één** bericht (ghost-sends: id geretourneerd, nooit echt
|
|||
- **`/chat/fetchMessages`-acks en de lokale message-store van wwebjs-api zijn een lokale
|
||||
registratie, géén bezorgbewijs.** Ze kunnen ack 1/2/3 tonen voor berichten die nooit
|
||||
aankwamen.
|
||||
- **Enige geldige bewijzen van levering:** (1) de **live `message_ack`-progressie** zoals
|
||||
die vlak ná verzending via de webhook binnenkomt; (2) de **zichtbare werkelijkheid op
|
||||
het apparaat** van de ontvanger/betrokkene.
|
||||
- **Ook de live `message_ack`-progressie is sinds 2026-09-26 géén bezorgbewijs meer:**
|
||||
de staged-ghost van dienst 5219 blz 2 kreeg via de webhook een `ack=2` afgegeven voor een
|
||||
bericht dat nooit getransmitteerd was (stond niet eens in de WhatsApp-app van de eigenaar).
|
||||
De bridge resolvet media-sends **optimistisch op lokale staging** en fabriceert daarna
|
||||
ack-events + delivery-info. Ack-tracking (stopt bij ack ≥ 2) kan deze klasse per ontwerp
|
||||
niet vangen.
|
||||
- **Enige geldige bewijzen van levering:** (1) de **zichtbare werkelijkheid op het
|
||||
apparaat** van de ontvanger/betrokkene; (2) `getInfo` (`message.getInfo()`): bij een
|
||||
staged-ghost blijft `read` leeg terwijl `delivery` gevuld kan zijn — het enige
|
||||
betrouwbare bridge-signaal is `read`/`readRemaining`.
|
||||
- **Trek NOOIT een leveringsconclusie uit een later gelezen fetchMessages-ack.** Claim geen
|
||||
"bezorgd/gelezen" op basis van de store — dat geeft verkeerde adviezen.
|
||||
- Dit is de reden dat ack-tracking bestaat: het hangt af van de live events, niet van de
|
||||
store.
|
||||
|
||||
## Waar draait de bot?
|
||||
|
||||
|
|
@ -176,13 +181,47 @@ 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**) pauzeert tussen de pagina's van één
|
||||
dienst (niet vóór de eerste). Doel: de wwebjs media-pipeline (één chromium-tab) per-verzending
|
||||
lucht geven en gelijktijdige storage/upload-conflicten verminderen. 0 = uitschakelen.
|
||||
- **Media-spreiding:** `MEDIA_SEND_DELAY_MS` (default **500**, nu **1500**) 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.)
|
||||
|
||||
Logregels: `[ack] track <id> (<bestand> → <chat>)`, `[ack] delivered ack=<n> <id>`, `[ack] pruned <n> stale entries`.
|
||||
|
||||
**Ack-semantiek (wwebjs 1.34.7):** ack 1 = verstuurd naar server (één grijs vinkje), ack 2 = bezorgd op apparaat (twee vinkjes), ack 3 = geopend/gelezen. Let op: eerdere notities die "één grijs vinkje (ack 2)" noemden, zaten er dus naast.
|
||||
**Ack-semantiek (wwebjs 1.34.7):** ack 1 = verstuurd naar server (één grijs vinkje), ack 2 = bezorgd op apparaat (twee vinkjes), ack 3 = geopend/gelezen. Let op: eerdere notities die "één grijs vinkje (ack 2)" noemden, zaten er dus naast. **Let op 2 (2026-09-26):** óók deze acks zijn geen leveringsbewijs — zie RCA hieronder.
|
||||
|
||||
### RCA 2026-09-26: staged-ghost = race-conditie, géén bestandprobleem
|
||||
|
||||
Casus: dienst 5219 (2 pagina's), 09:29 gevraagd in de groep, bot stuurt beide pagina's
|
||||
prive. App toont alleen blz 1; **blz 2 stond in het geheel niet in de WhatsApp-app van de
|
||||
eigenaar** (geen transmissie). Toch: bridge retourneerde success + message-ID (`3EB040AD…`),
|
||||
store toont het bericht, live `message_ack` gaf `ack=2`, `getInfo` toonde `delivery` gevuld
|
||||
maar `read` leeg. Geen enkele fout in de container-logs.
|
||||
|
||||
Mechanisme (bewezen uit fork-broncode + logs):
|
||||
- De send loopt via `WAWebSendMsgChatAction.addAndSendMsgToChat(chat, message)` →
|
||||
`[msgPromise, sendMsgResultPromise]`. De bridge zet `waitUntilMsgSent: true`
|
||||
(stock wwebjs-api, `clientController.js`), maar de promise resolve **ook optimistisch op
|
||||
lokale staging** — een echte serverbevestiging wordt nooit afgewacht. HTTP-success +
|
||||
message-ID betekenen dus **niet** "verzonden".
|
||||
- **Patroon (gebruiker, consistent met logs):** de ghost treedt alleen op bij **2+ media
|
||||
direct achter elkaar**, en dan altijd de **2e** van het paar; enkele sends falen nooit.
|
||||
- Verklaring: de bot wacht per pagina op het HTTP-signaal (staging), niet op echte
|
||||
transmissie → blz 2 wordt gestart terwijl blz 1's **echte** upload/transmissie nog in
|
||||
de lucht is. Twee echte media-transmissies overlappen in de ene chromium-tab → de 2e
|
||||
verliest (intermitterend) → staged-ghost.
|
||||
- Gevolgen: **`MEDIA_SEND_DELAY_MS` kan dit niet oplossen** (wacht op optimistisch
|
||||
signaal); **poppler/re-render maskeert het alleen** (nieuwe poging = nieuwe race-rol,
|
||||
soms gewonnen — wassen neus); **`sendMessageViaUi` lost het óók niet op** (wacht op
|
||||
dezelfde promises, alleen omzeilt het de media-editor); **ack-tracking kan het niet
|
||||
vangen** (stopt bij gefabriceerde ack ≥ 2).
|
||||
|
||||
Enige betrouwbare signalen: apparaat-waarheid; `getInfo` `read`/`readRemaining` (blijft
|
||||
leeg bij staged). Aanbevolen richting (nog niet geïmplementeerd): de fork moet ná
|
||||
`addAndSendMsgToChat` écht wachten op transmissiebevestiging — pas dan serialiseren
|
||||
multi-page sends vanzelf en is de race weg.
|
||||
|
||||
## Media bezorgtest (afbeeldingen die WhatsApp weigert)
|
||||
|
||||
|
|
@ -200,6 +239,15 @@ ack-tracking (zie hierboven), re-render via poppler en een verse bezorgtest.
|
|||
**Ack-telling:** ack 1 = één grijs vinkje (niet bezorgd), ack 2 = bezorgd op apparaat,
|
||||
ack 3 = geopend. (Eerdere notities "één grijs vinkje (ack 2)" zaten er dus naast.)
|
||||
|
||||
> **⚠️ 2026-09-26: onderscheid twee foutklassen.** De hierboven beschreven
|
||||
> bestand × ontvanger/offline-klasse (ack 1-hang, ontvanger offline of app weigert
|
||||
> render) is niet hetzelfde als de **staged-ghost-race** (zie RCA hierboven): daar is het
|
||||
> bestand nooit het probleem en **re-render (poppler) is een wassen neus** — het maskert
|
||||
> de race alleen. Check bij een "niet aangekomen bladzijde" eerst: was het de 2e pagina
|
||||
> van een paar binnen ~1s? Dan is het de race, geen bestand. Echte remedie is nog in
|
||||
> ontwerp (fork: wachten op transmissiebevestiging); voor nu: opnieuw versturen (eventuele
|
||||
> nieuwe poging) en apparaat als waarheid.
|
||||
|
||||
**Na elke omruiling van de dienstenmap: de volledige media-test doorlopen vóór ingebruikname.**
|
||||
|
||||
**Afbeeldingsformaat:** sinds `07b511e` leidt `sendImageMessage` de mimetype af uit de
|
||||
|
|
|
|||
Loading…
Reference in a new issue