ソースを参照

Drupal-sessie 15 sep afgerond: open taken 47/48/54/56 uitgeschreven, cache- en pagermetingen naar CLAUDE.md

Ook meegecommit: de '— bezig'-marker die de parallelle sessie op het P2-1-restpunt
in de working tree had gezet (niet van mij, wel bewust behouden).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bob 8 時間 前
コミット
999a02a679
2 ファイル変更79 行追加3 行削除
  1. 33 2
      CLAUDE.md
  2. 46 1
      TASKS.md

+ 33 - 2
CLAUDE.md

@@ -3375,6 +3375,36 @@ ronde: een ongefilterde eerste pagina laadt prima. Gebruik als rookmelder een
 grens waar niets aan kan voldoen (`?datum_van=2030-01-01` → moet `0` items
 geven), en bij een lijst met een `nid`-filter een node die je kent.
 
+**Meet responstijden ZONDER cache-buster als je wilt weten wat een gebruiker
+merkt — met buster meet je structureel het slechtste geval.** Gemeten
+2026-09-15 op productie, dezelfde URL drie keer achter elkaar:
+`1,23 s (x-drupal-cache: MISS)` → `0,10 s (HIT)` → `0,11 s (HIT)`. Drupal's
+eigen page cache doet dus **12× zoveel** als alle micro-optimalisaties samen.
+Een poll van een minuut-per-meting liet de entry meerdere minuten staan met af
+en toe een terugval naar MISS. Praktisch: gebruik de cache-buster alleen om een
+*verse render* te forceren (na een code- of viewwijziging), en meet de
+gebruikerservaring met een vaste URL.
+- `cf-cache-status: DYNAMIC` + `cache-control: no-store, no-cache` betekent dat
+  **Cloudflare niets cachet**: elke gebruiker legt de volle weg naar de origin
+  af. Dat is de grootste openstaande winst (zie taak 54 in `TASKS.md`).
+- Wil je edge-caching aanzetten: dat moet in **Cloudflare** (een Cache Rule),
+  niet in Drupal. Een header uit Drupal is alleen een instructie, en `.json`
+  cachet Cloudflare sowieso niet op basis van extensie. Zet Edge TTL dan op
+  *"Ignore cache-control header and use this TTL"* — met *"use cache-control
+  if present, bypass if not"* bypasst hij alles, want de origin zegt `no-store`.
+- ⚠️ **Niet elk endpoint onder `/flutterdrup/views/` is user-onafhankelijk.**
+  `flutterflowmobiel_establishments` services_1 wordt in
+  `custom_views_query_alter()` gefilterd op de favorietenlijst van de ingelogde
+  gebruiker: dezelfde URL, een ander antwoord per gebruiker. Nooit edge-cachen.
+
+**De pagergrootte van `flutterflowmobiel1` mag ruim: 25 → 50 kost niets, 100
+wel.** Gemeten 2026-09-15 op services_5, 3 metingen per waarde: 25 items
+1,24 s · **50 items 1,25 s** · 100 items 1,42 s. Van 25 naar 50 halveert het
+aantal round trips bij infinite scroll voor 0,01 s. Staat sinds die datum op
+50. De zes overriding displays zetten alleen `defaults['filters']` en
+`defaults['filter_groups']` op FALSE — **de pager erven ze wél**, dus dit is
+één wijziging op de Master voor alle zeven.
+
 **Views is niet de performance-bottleneck — gemeten 2026-09-14, voordat je een
 custom-module-endpoint bouwt om Views te vervangen.** 3x per endpoint met
 cache-buster op productie: een **custom** Services-resource die twaalf
@@ -3626,8 +3656,9 @@ maakte dat er geen exposed datumfilter bestond.
   `LoginCall`'s response) vormen samen de sessie-cookie:
   `Cookie: <session_name>=<sessid>`. `token` is een los CSRF-token,
   alleen nodig bij schrijf-requests (POST/PUT/DELETE), nooit bij GET.
-- **Handmatig curl-testen tegen Drupal Services: voeg altijd HTTP Basic
-  Auth toe (`curl -u <user>:<pass> ...`), zowel op devbob als productie.**
+- **Handmatig curl-testen tegen Drupal Services: `curl -u <user>:<pass> ...`
+  is nodig op DEVBOB. Productie heeft die laag niet (meer) — gemeten
+  2026-09-15: zonder `-u` gewoon HTTP 200.**
   Bevestigd 2026-08-26: zonder deze `-u`-vlag krijg je geen JSON terug maar
   een kale challenge-/foutpagina die op het eerste gezicht als een
   Cloudflare-blokkade oogt (bevatte zelfs Cloudflare-JS-snippets) — bleek

+ 46 - 1
TASKS.md

@@ -322,7 +322,7 @@ gemeten; er is nóg één knoop door te hakken, zie het restpunt onderaan.**
 - `homeCopy` staat als vangnet klaar (Bob's verzoek vóór het Home-werk).
   **Opruimen mag zodra je tevreden bent — dat is een taak voor Bob.**
 
-⚠️ **RESTPUNT, en het is er één voor jou — keuze nodig (prio 1).** Op de
+⚠️ **RESTPUNT — Bob koos optie 2 (2026-09-15). Eigenaar: Claude — bezig.** Op de
 telefoon-emulator getest met een profile-build: de chips wisselen, App State
 wisselt, de parameters gaan goed mee... **maar de lijst herlaadt niet vanzelf.**
 Trek je de lijst omlaag (pull-to-refresh), dan staat het weekendresultaat er
@@ -894,6 +894,51 @@ De oorzaak is het klassieke Views-patroon "een veld met meerdere waarden krijgt
 een eigen rij" — kijk op node `214439` welk veld 14 waarden heeft en zet
 *Multiple field settings → Display all values in the same row* aan.
 
+### 🌐 Voor Bob — open na de Drupal-sessie van 2026-09-15
+
+*Afgerond die sessie en daarom hier niet meer uitgeschreven: taak 29 + 39
+(HTML-entiteiten, 1981 records / 0 entiteiten), taak 31 (dubbele rijen),
+taak 21/33 (datumfilter, zie het blok hieronder), taak 43 + 46
+(debug-logging achter `_custom_flutterflow_debug()`), taak 45 (alle 14
+API-calls van `/en/` naar `/nl/`), taak 50 (pager 25 → 50), taak 52
+(`dblog_row_limit` stond al goed) en taak 53 (`services_2` uitgezet).*
+
+**Taak 47 · Theater Landgraaf mist zijn gemeente/plaats.** Horecagelegenheid
+nid **70155** heeft geen `field_hor_municipality_town`. Gevolg: de events daar
+(nid 221721, 221722, 221723 — adres "Kerkberg 4") hebben een lege `plaats` en
+zijn dus **niet vindbaar via `townid`**; ze komen in geen enkele stadstab. Het
+zijn er 3 van de 1200 gemeten events (0,2%), dus het is één node, geen
+structureel probleem. ⚠️ `custom_node_presave()` kopieert de plaats naar het
+event **op het moment dat het event wordt opgeslagen** — de zaak repareren is
+dus niet genoeg, die drie events moeten daarna opnieuw opgeslagen worden.
+
+**Taak 48 · FlutterFlow-commit op `main`.** Staat sinds 14 sep open (Claude's
+klik op de commit-knop in het Version Control-paneel komt niet aan) en er zijn
+op 15 sep opnieuw drie API-calls gewijzigd.
+
+**Taak 54 · Cloudflare Cache Rule voor de publieke endpoints.** De winst is
+gemeten: dezelfde URL zonder cache-buster geeft **1,23 s (MISS) → 0,10 s
+(HIT)**, maar `cf-cache-status` staat op `DYNAMIC`, dus Cloudflare cachet niets
+en elke gebruiker legt de volle weg naar de origin af. Bob doet dit puur in
+Cloudflare (geen Drupal-header). De twee instellingen die het bepalen:
+- **Expression**: `http.request.method eq "GET"` **en** `not http.cookie
+  contains "SESS"` **en** een expliciete lijst van paden.
+- **Edge TTL**: "Ignore cache-control header and use this TTL" → **300 s**.
+  De optie "Use cache-control header if present, bypass cache if not" werkt
+  hier **niet**, want de origin stuurt `no-store, no-cache`.
+⚠️ `flutterflowmobiel_establishments.json` hoort **niet** in die lijst: die
+display filtert in `custom_views_query_alter()` op de favorietenlijst van de
+ingelogde gebruiker, dus dezelfde URL geeft per gebruiker een ander antwoord.
+Idem voor `/flutterdrup/favorieten*`, `/mijn_*`, `/accountdelete`, `/user/*`.
+
+**Taak 56 · De opruim-cron zegt 30 dagen maar doet 360.** In
+`custom_cronapi()` staat *"after 30 days"*, in
+`custom_delete_expired_events_callback()` staat `$date->modify('- 360 days')`.
+Met 16.065 events in de voorraad is dat geen detail. Er zit bovendien een
+`range(0, 500)` op: max 500 verwijderingen per cronrun, wat bij de huidige
+importsnelheid mogelijk niet meer volstaat. Besluit welke van de twee klopt,
+maak description en code gelijk, en hernoem `$date_after_30`.
+
 ### Voor Bob — drie Drupal-taken, uitgeschreven
 
 **Taak 19 (P1-42b) · view `flutterflowmobiel_establishment_events` — de