Skip to content

➕ Nieuwe berichten live in de open berichtenbox (_volgen) - #164

Draft
ericwout-overheid wants to merge 3 commits into
mainfrom
feat/keten-berichten-live-volgen
Draft

ericwout-overheid wants to merge 3 commits into
mainfrom
feat/keten-berichten-live-volgen

Conversation

@ericwout-overheid

@ericwout-overheid ericwout-overheid commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Helpt MinBZK/MijnOverheidZakelijk#939. Niet Closes: het issue sluit pas als beide kanten klaar zijn. Deze PR is de proeftuin-kant; het endpoint komt uit MinBZK/moza-poc-fbs-berichtenbox#336.

Was gestapeld op #163, die de naam van de afzender alsnog op main zette. #163 is gemerged; de basis van deze PR is nu main.

Wat de bezoeker merkt

Een bericht dat binnenkomt terwijl de berichtenbox openstaat, staat er binnen enkele seconden, zonder verversen en zonder ophaalronde langs de organisaties. In de netwerktab staan geen periodieke GET /api/v1/berichten meer.

Hoe

assets/javascript/berichtenbox-keten.js opent na een geslaagde ronde GET /api/v1/berichten/_volgen, met fetch en een reader. EventSource kan geen X-Ontvanger meesturen. De SSE-parser van _ophalen is leesSse geworden en wordt door beide gedeeld.

Gebeurtenis of status Wat de client doet
volgen-gestart Eén lijst-tik, via hetzelfde pad als pollTik. Liep er al een tik, dan volgt er nog één. Mislukt die tik, dan blijft de stroom open en volgt na 15 s een nieuwe poging; na drie op rij stopt het bijwerken met de bestaande mededeling.
bericht-bijgekomen naarBerichtenboxVorm en bovenaan de lijst. Ontdubbeld op berichtId. De bron maakt er een { nieuwBericht } van (bestaande weg).
hartslag De eerste maakt de verbinding "gezond": pas dan gaan de backoff-reeks, de mislukte verbindingen, de 409's en de herstelrem terug naar nul.
Onbekende event Negeren, met één console.warn per soort.
Melding die geen JSON is of niet te verwerken valt Overslaan met console.error; de verbinding blijft staan. Na 5 s een lijst-tik, die het bericht alsnog brengt of (zonder id) meldt.
45 s zonder leesbare gebeurtenis, ook tijdens het openen De waakhond breekt de verbinding af en de client verbindt opnieuw. Losse bytes en onleesbare frames tellen niet als teken van leven.
Stroom eindigt of breekt Opnieuw verbinden na 1, 2, 5, 10 en daarna 30 s, met ±20% spreiding.
sessie-verlopen herstelSessie, met dezelfde rem van twee rondes, en daarna opnieuw verbinden.
409 bij openen Eén keer herstelSessie. Komt er vóór een gezonde verbinding wéér een 409, dan blijvend terug naar navragen.
503, 429 Retry-After afwachten, hoogstens een minuut.
200 zonder text/event-stream Body sluiten (telt anders mee voor de vijf per ontvanger); telt als mislukte verbinding.
404, 405, 406 Blijvend terug naar periodiek navragen, tot een herlading. Geen melding.
3× op rij een verbinding die niet gezond wordt Tijdelijk terug naar navragen; na 5 minuten of bij pageshow de stroom opnieuw proberen, met de reeks tussenpozen waar die was. Geen melding.

Twee randgevallen:

  • Een bericht dat binnenkomt terwijl de lijst-tik onderweg is. Dat blijft staan (bijgekomenTijdensTik). Anders legt de oudere lijst zich eroverheen, ziet de bron het bericht "verdwijnen" en haalt die het weer weg.
  • Het 406-geval. De publieke FBS-omgeving (nog zonder _volgen) leest het pad als GET /berichten/{berichtId}. Met Accept: text/event-stream geeft die een 406, geen 404. Gemeten met curl. Zonder deze uitzondering zou de client daar pas na drie mislukte pogingen terugvallen.

Levenscyclus. pagehide sluit de stroom en pageshow verbindt opnieuw. Is er intussen een andere persona gekozen, dan stopt de pagina met volgen, want anders haalt die de post van iemand anders op. Een verborgen tabblad blijft verbonden. stopPollen() sluit de stroom ook.

Instelling. ?volgen=0 of setting:berichtenbox-volgen op 0 zet de stroom uit. ?poll= blijft werken voor de terugval.

Proxy. Niets veranderd. container/default.conf.template staat al ongebufferd met een proxy_read_timeout van 3600 s, en lokaal loopt /api/v1/ via server/keten-proxy.js, dat ook al een timeout van 3600 s heeft.

Correctie. De eerste commit veranderde server/proxy.js en beweerde dat die proxy elke stroom afkapte. Die proxy hoort bij de react-islands en staat niet in het pad van de berichtenbox; de wijziging is teruggedraaid.

Tests

Nieuw bestand tests/berichtenbox/keten-volgen.test.js, met 48 tests op een nagebootste ReadableStream:

  • de volgorde volgen-gestart → lijst-tik → bericht-bijgekomen, en daarna geen periodieke tikken;
  • ontdubbelen via lijst en stroom, een bericht dat binnenkomt terwijl de tik onderweg is, en tikNogEens;
  • meldingen die geen JSON zijn of niet te verwerken vallen: overgeslagen, de verbinding blijft staan;
  • de waakhond, ook tijdens het openen, en dat een hartslag de verbinding laat staan;
  • opnieuw verbinden na een afgebroken stroom (de lijst is daarna compleet) en na een stroom die netjes eindigt; de backoff, en dat die pas na een hartslag terug naar het begin gaat;
  • een stroom die telkens na de start wegvalt: die geeft op in plaats van eindeloos opnieuw te verbinden;
  • een lijst die hapert terwijl de stroom openstaat: de stroom blijft open, na 15 s een nieuwe poging, en het bijwerken houdt het een halve minuut vol;
  • het opnieuw aanbieden van de lijst na een verwerkingsfout;
  • sessie-verlopen → herstel, een 409 bij openen, een 409 die na een ronde terugkomt, en een 409 van de lijst terwijl de stroom openstaat;
  • terugval bij 404, 405 en 406, na drie mislukkingen en bij een 200 zonder stroom, steeds zonder melding;
  • 503 en 429 met Retry-After;
  • pagehide/pageshow, een verborgen tabblad (ook terug naar zichtbaar), een persona-wissel en stopPollen();
  • ?volgen=0 en de localStorage-instelling;
  • de herstelrem als de stroom telkens na de start sessie-verlopen meldt;
  • een overgeslagen bericht dat via een lijst-tik alsnog komt, en een bericht zonder id dat ook gemeld wordt als er tijdens de tik een bericht uit de stroom bijkwam;
  • de waakhond die niet op onleesbare frames reageert, Retry-After met een bovengrens, de tijdelijke terugval en zijn herkansing, en het sluiten van een body die we niet lezen;
  • het terugzetten van de tellers bij de eerste hartslag;
  • één test van stroom via ketenBron tot { nieuwBericht }, inclusief het grensvlak.

Nagelopen met mutaties, na elke reviewronde opnieuw: elke fix en elk kernpad weghalen laat minstens één test falen. Twee tests (pagehide en stopPollen()) slaagden eerst ook zonder dat de stroom dichtging, omdat de waakhond hem binnen hun wachttijd toch afbrak. Die kijken nu meteen.

Het harnas geeft op _volgen standaard een 404, zoals een keten zonder dat endpoint. Daarmee toetsen de bestaande polltests precies de terugval.

npm test: 516 geslaagd, 1 mislukt. Die ene is detail.test.js › "noemt de knop Terugzetten in inbox…". Die faalt op main al en hangt niet samen met deze PR.

Nog niet gedaan

Nog niet uitgeprobeerd tegen een keten die _volgen echt levert: lokaal de demo-stack van feature/939-nieuwe-berichten-live, of de preview van moza-poc-fbs-berichtenbox#336. De stappen uit de opdracht:

  1. Zet deze repo op die keten (BACKEND_KETEN).
  2. Open de berichtenbox van proeftuin-een en voer via het bedieningspaneel een bericht op. Dat hoort binnen enkele seconden te verschijnen, zonder periodieke lijstaanroepen in de netwerktab.
  3. Zet daarna de uitvraag even stil en weer aan. De berichtenbox verbindt opnieuw en de lijst is weer compleet.

Daarom is deze PR een draft.

🤖 Generated with Claude Code

…rugval

Staat de berichtenbox open en komt er een bericht binnen, dan meldt het
stelsel dat nu zelf (`GET /api/v1/berichten/_volgen`, MinBZK/moza-poc-fbs-
berichtenbox#336). De berichtenbox hoeft niet meer elke vijftien seconden de
lijst op te vragen.

De stroom begint met `volgen-gestart`. Dan haalt de berichtenbox één keer de
lijst op, langs hetzelfde pad als een polltik. Daarna komt elk bericht als
`bericht-bijgekomen`, met de naam van de afzender erbij. Het gaat als
gewijzigde lijst naar de bron, die er een binnenkomer van maakt. Ontdubbelen
gebeurt op `berichtId`, want een bericht op het grensvlak kan in allebei
zitten. Een bericht dat binnenkomt terwijl die lijst nog onderweg is, blijft
staan; anders legt de lijst zich eroverheen en verdwijnt het weer.

Een waakhond breekt de verbinding af na 45 seconden zonder hartslag, want na
een slaapstand merkt de browser het niet. Opnieuw verbinden gebeurt na 1, 2,
5, 10 en daarna 30 seconden, met spreiding; `volgen-gestart` zet die reeks
terug. Na `sessie-verlopen` en bij een 409 draait het bestaande herstel. Een
503 wacht `Retry-After` af.

Kent de keten `_volgen` niet (404, 405, of 406 zoals de publieke omgeving
nu antwoordt), of komen drie verbindingen op rij niet tot stand, dan valt de
berichtenbox stil terug op het periodiek navragen. Geen melding: de lijst
werkt gewoon, alleen verschijnen nieuwe berichten wat later.

`pagehide` sluit de stroom en `pageshow` verbindt opnieuw, behalve als er
intussen een andere persona gekozen is. Een verborgen tabblad blijft
verbonden. `?volgen=0` of `setting:berichtenbox-volgen` op 0 zet de stroom
uit, voor een demonstratie van allebei.

De SSE-parser van `_ophalen` is nu `leesSse` en wordt door beide gedeeld.

De dev-proxy `server/proxy.js` kapte elke stroom af: zijn `proxyTimeout` van
15 seconden is korter dan de hartslag van 20. Voor `text/event-stream` staan
de timeouts nu uit, en die antwoorden worden niet meer in het geheugen
verzameld.

Helpt MinBZK/MijnOverheidZakelijk#939

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

🚀 Preview Deployment

Your changes have been deployed to a preview environment:

proef: https://proef-pr164-pm-5sj.rig.prd1.gn2.quattro.rijksapps.nl

📱 Scan to open on mobile
 ▄▄▄▄▄ █▀▀ ██▄  ▀▀▀▄▀█▀ ██ ▄▄▄▄▄ 
 █   █ █▄▀██▀▀█▄█▄ ▀██ ███ █   █ 
 █▄▄▄█ █ ▄ █ █▄ ▄█▀▀█ █▄▄█ █▄▄▄█ 
▄▄▄▄▄▄▄█ █ ▀▄▀▄█▄▀▄█ ▀▄█▄█▄▄▄▄▄▄▄
 ▄█ ▀▀▄ █▀█  ▀▄▄▄▀▀█  ██ █ ▄▄▀▄▄▀
▄▄▄ ▄█▄ █▀▀   ▄█▄▄▄ ▀  ▀█ ▄▀█▄█▀ 
▄█▀▀█▄▄▄█▀▄ █▀ ██▄█▀▀▄ █▀▀ ▄▀ ▀▀ 
 ▄ ▀▀▀▄ ▀▀▄ █▄▄▀▄▀▀█▀ █ ▀██▄  █ █
▄▄  █ ▄██ ▀█  ▀█  ▄█   ▀█▄▄▀▄▀▀█▄
█▀ ▀██▄█ █ ▄ █ ▀  █▀▄▀ ▀▀▄ █▀ █▄▄
▄█  ▄▀▄▄▀▀ ▀██▀█▀▀▀█▄ ▀█▄█▀██▄▀▄▀
▄ █▄▀█▄▄▄█ ███▀▀▄▄▄▄▄ ██▀▀ ▄█ █▀ 
▄█▄█▄▄▄█▀ █▀ ███▄▄█   ▀  ▄▄▄  ██▀
 ▄▄▄▄▄ █▄▄██ ▀▀██  █ ▀██ █▄█ ▄▄ █
 █   █ █▀▀ ▄█▄▄█  █▄▄ ▀█▄    ▄███
 █▄▄▄█ █▀█ ▀█ ██▀ ▄▀ ▀▄█ ▀▀▄▄███▄
▄▄▄▄▄▄▄█▄██▄▄█▄▄▄██▄█▄▄█▄▄█▄█▄█▄█

This deployment will be automatically cleaned up when the PR is closed.

Uit de review van #164.

Een verbinding telt pas als gezond na haar eerste hartslag, en niet al bij
`volgen-gestart`. Pas dan gaat de reeks tussenpozen terug naar het begin.
Zette `volgen-gestart` hem terug, dan verbond een stroom die telkens net na de
start wegvalt elke seconde opnieuw, haalde elke keer de lijst op, en gaf nooit
op. Zo'n stroom telt nu mee voor de terugval op navragen.

Mislukt de lijst terwijl de stroom openstaat, dan blijft de stroom open en
probeert de berichtenbox het na vijftien seconden opnieuw. Eerst brak hij de
gezonde stroom af en verbond hij opnieuw, en de nieuwe `volgen-gestart` haalde
de lijst meteen weer op: drie mislukkingen in drie seconden, en het bijwerken
hield op. Nu houdt hij het een halve minuut vol, net als het navragen.

Een melding die geen JSON is of niet te verwerken valt, wordt overgeslagen met
een `console.error`. Eerst nam die fout de verbinding mee, onder de noemer
"verbinding viel weg", met hetzelfde gevolg als hierboven.

Een 409 bij het openen draait één keer een nieuwe ronde. Komt er daarna weer
een 409, dan ligt het niet aan de sessie en valt de berichtenbox terug op
navragen, in plaats van na twee rondes op te houden met een mededeling terwijl
de lijst gewoon werkt. Een 429 wacht net als een 503 `Retry-After` af, en een
200 zonder `text/event-stream` telt als mislukte verbinding.

Teruggedraaid: de wijziging in `server/proxy.js`. Die proxy hoort bij de
react-islands; de berichtenbox gaat lokaal via `server/keten-proxy.js`, dat al
een timeout van 3600 s heeft. De bewering in de vorige commit dat de
berichtenbox er last van had, klopte niet.

Tests voor elk van deze paden, en voor `tikNogEens`, het opnieuw aanbieden na
een verwerkingsfout, een 409 van de lijst terwijl de stroom openstaat en de
waakhond tijdens het openen. De tests voor `pagehide` en `stopPollen()`
slaagden ook zonder dat de stroom dichtging, omdat de waakhond hem binnen hun
wachttijd toch afbrak; die kijken nu meteen. Verouderde commentaren die alleen
over pollen spraken, zijn bijgewerkt.

Helpt MinBZK/MijnOverheidZakelijk#939

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… blijvend

Uit de tweede review van #164.

De herstelrem werkte niet over de stroom. Een geslaagde lijst-tik zette hem
terug, en over de stroom komt die tik meteen na een herstelronde, als de
sessie net gevuld is. Een sessie die korter leeft dan één cyclus draaide zo
om de paar seconden een ronde langs alle organisaties, zonder einde. Over de
stroom zet nu de eerste hartslag de rem terug, samen met de andere tellers.

Een bericht uit de stroom dat we moesten overslaan, bleef weg tot de volgende
`volgen-gestart`, en die kan een uur op zich laten wachten. Nu volgt na vijf
seconden een lijst-tik, die het alsnog brengt of, zonder id, meldt.

Een bericht zonder id werd niet gemeld als er tijdens de tik een bericht uit
de stroom bijkwam: de telling liep ná het samenvoegen. Ook niet als het de
enige wijziging was, want de vergelijking met de vorige lijst kwam eerst. Nu
wordt het gemeld zodra het aantal verandert.

De waakhond herstart op een gebeurtenis die we konden lezen, niet op elk
binnenkomend blok. Een stroom met alleen onleesbare frames bleef anders een
uur open en telde nooit als mislukt.

Drie mislukte verbindingen binnen een paar seconden — een wifi-wissel — zetten
de pagina voorgoed op navragen. Die terugval is nu tijdelijk: na vijf minuten,
of bij `pageshow`, probeert de berichtenbox de stroom opnieuw. Blijvend is hij
alleen bij een keten zonder `_volgen` en bij een 409 die na een ronde
terugkomt. De terugval staat in de console als waarschuwing, niet als info.

Verder: `Retry-After` wacht hoogstens een minuut, de body van een 200 zonder
stroom wordt gesloten (elke open verbinding telt mee voor de vijf per
ontvanger), en een onbekende soort melding komt één keer in de console.

Tests voor elk punt, eerst rood; ook voor het terugzetten van de tellers bij
de eerste hartslag, en één test die een bericht van de stroom tot een
binnenkomer in de bron volgt. Elke fix weghalen laat een test vallen.

Helpt MinBZK/MijnOverheidZakelijk#939

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
pr164 — 1cfc0f6b Deployed Sep 22, 2026 by ericwout-overheid via deploy-preview #548
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant