Bronlaag-abstractie: meerdere bronnen naast Melvin #17

Closed
opened 2026-07-20 14:46:15 +02:00 by jelmer · 0 comments
Owner

Gemigreerd uit backlog/ naar issues op 2026-07-20 — oorspronkelijk TASK-14.
Labels in het oude bord: architectuur, bronnen.

Nu gaat server.py overal uit van de vorm van Melvin (NDW). Om ook Belgische
gewesten te kunnen ontsluiten moet daar eerst een bronlaag onder.

Doel: een intern meldingsmodel waar elke bron naartoe vertaalt, met per melding
minimaal: id, titel, geometrie, periode (start/eind), beperkingen, omleidingen,
fietsimpact, bron en (optioneel) deeplink.

Werk:

  • bron_melvin afsplitsen uit server.py zonder gedragsverandering; de
    Biesbosch-route blijft de regressietest.
  • Bronkeuze op route-bbox; routes over de grens bevragen meerdere bronnen en
    voegen samen.
  • Ophalen per tegel langs de route in plaats van een omvattende rechthoek.
    Gemeten op corridor Gent-Brugge: 8000+ zones voor de rechthoek tegen circa
    1100 voor tegels langs de route.
  • Gzip aanzetten (gemeten 3,3 MB naar 672 kB) en per tegel trimmen voor opslag.
    Let op de cgroup-limiet: hier ging het eerder mis met een SIGKILL.
  • Fietsimpact wordt bronspecifiek bepaald. Melvin houdt de bestaande heuristiek;
    bronnen die het zelf classificeren leveren het rechtstreeks aan.
  • Deeplink wordt optioneel: niet elke bron heeft er een. Geen kapotte knop tonen.

Bewust buiten scope: de UI-kant en de gewesten zelf, die volgen als aparte taken.

Definition of Done

Hoe het is opgelost

Afgerond (2026-07-20).

Indeling nu:
server.py HTTP, check-pijplijn, route-import, LLM, feedback, health
bron_melvin.py ophalen, vector-tiles, trimmen, fietsrelevantie
geo.py bronneutrale geometrie
net.py gedeelde HTTP-helpers

Een bron is een module met DEKKING (bbox) en fetch_situations(datum, route).
bronnen_voor() kiest op de bounding box van de hele route, niet op het
vertrekpunt, zodat een rit over de grens beide bronnen bevraagt. Het interne
model blijft de bestaande meldingsvorm, dus de frontend bleef ongemoeid en een
tweede bron wordt vooral een vertaalklus (TASK-15).

geo.py en net.py bestaan om een kringverwijzing te vermijden: een bronmodule
heeft geometrie en HTTP nodig maar mag server.py niet importeren.

Vangrail vooraf gebouwd. tests/regressie.py legt de volledige respons van
drie routes vast en speelt al het netwerkverkeer terug (hermetisch, want
Melvin-data verandert dagelijks). Onderschepping op urllib.request.urlopen,
niet op onze eigen functies — die verhuizen juist. Gevalideerd dat hij verschillen
betrapt vóór hij als bewijs werd gebruikt. Na de refactor: identiek op alle drie.
De test ving tijdens het werk ook vier gemiste verwijzingen (_http_json,
is_snelweg, UA, ThreadPoolExecutor).

Incident: 5 minuten 502 op productie. Beide deploypaden rsyncten alleen
server.py en static/, dus de nieuwe modules kwamen niet mee en de app startte
niet. Hersteld met deploy/handmatig.sh; daarna beide paden aangepast en er een
waarschuwing bij gezet. Uptime Kuma zag het correct (09:59 down, 10:00 weer up).

Les: de regressietest dekte de code, niet de levering. Een groene test zegt
niets over of het bestand ook op de server staat. Bij het toevoegen van een
module hoort de deploy-lijst in dezelfde commit.

Niet gedekt door de test: de buiten-bereik-waarschuwing komt nu uit
bronnen_voor() in plaats van een hardcoded NL-bbox; alle drie de testroutes
liggen in Nederland, dus dat pad is alleen met de hand nagelopen.

> Gemigreerd uit `backlog/` naar issues op 2026-07-20 — oorspronkelijk **TASK-14**. > Labels in het oude bord: `architectuur`, `bronnen`. Nu gaat `server.py` overal uit van de vorm van Melvin (NDW). Om ook Belgische gewesten te kunnen ontsluiten moet daar eerst een bronlaag onder. Doel: een intern meldingsmodel waar elke bron naartoe vertaalt, met per melding minimaal: id, titel, geometrie, periode (start/eind), beperkingen, omleidingen, fietsimpact, bron en (optioneel) deeplink. Werk: - `bron_melvin` afsplitsen uit `server.py` zonder gedragsverandering; de Biesbosch-route blijft de regressietest. - Bronkeuze op route-bbox; routes over de grens bevragen meerdere bronnen en voegen samen. - Ophalen per tegel langs de route in plaats van een omvattende rechthoek. Gemeten op corridor Gent-Brugge: 8000+ zones voor de rechthoek tegen circa 1100 voor tegels langs de route. - Gzip aanzetten (gemeten 3,3 MB naar 672 kB) en per tegel trimmen voor opslag. Let op de cgroup-limiet: hier ging het eerder mis met een SIGKILL. - Fietsimpact wordt bronspecifiek bepaald. Melvin houdt de bestaande heuristiek; bronnen die het zelf classificeren leveren het rechtstreeks aan. - Deeplink wordt optioneel: niet elke bron heeft er een. Geen kapotte knop tonen. Bewust buiten scope: de UI-kant en de gewesten zelf, die volgen als aparte taken. ## Definition of Done - [x] #1 Werkend op https://gpx.jelmer.org - [x] #2 Documentatie bijgewerkt ## Hoe het is opgelost Afgerond (2026-07-20). Indeling nu: server.py HTTP, check-pijplijn, route-import, LLM, feedback, health bron_melvin.py ophalen, vector-tiles, trimmen, fietsrelevantie geo.py bronneutrale geometrie net.py gedeelde HTTP-helpers Een bron is een module met DEKKING (bbox) en fetch_situations(datum, route). bronnen_voor() kiest op de bounding box van de hele route, niet op het vertrekpunt, zodat een rit over de grens beide bronnen bevraagt. Het interne model blijft de bestaande meldingsvorm, dus de frontend bleef ongemoeid en een tweede bron wordt vooral een vertaalklus (TASK-15). geo.py en net.py bestaan om een kringverwijzing te vermijden: een bronmodule heeft geometrie en HTTP nodig maar mag server.py niet importeren. **Vangrail vooraf gebouwd.** tests/regressie.py legt de volledige respons van drie routes vast en speelt al het netwerkverkeer terug (hermetisch, want Melvin-data verandert dagelijks). Onderschepping op urllib.request.urlopen, niet op onze eigen functies — die verhuizen juist. Gevalideerd dat hij verschillen betrapt vóór hij als bewijs werd gebruikt. Na de refactor: identiek op alle drie. De test ving tijdens het werk ook vier gemiste verwijzingen (_http_json, is_snelweg, UA, ThreadPoolExecutor). **Incident: 5 minuten 502 op productie.** Beide deploypaden rsyncten alleen server.py en static/, dus de nieuwe modules kwamen niet mee en de app startte niet. Hersteld met deploy/handmatig.sh; daarna beide paden aangepast en er een waarschuwing bij gezet. Uptime Kuma zag het correct (09:59 down, 10:00 weer up). Les: de regressietest dekte de code, niet de levering. Een groene test zegt niets over of het bestand ook op de server staat. Bij het toevoegen van een module hoort de deploy-lijst in dezelfde commit. Niet gedekt door de test: de buiten-bereik-waarschuwing komt nu uit bronnen_voor() in plaats van een hardcoded NL-bbox; alle drie de testroutes liggen in Nederland, dus dat pad is alleen met de hand nagelopen.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jelmer/gpx-afsluitingen#17
No description provided.