perf: opstart-fetches /auth/me en /me/data parallel i.p.v. serieel (v0.4.31-beta)
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 37s

- Beide verzoeken hangen alleen af van dezelfde sessie-cookie, niet van
  elkaars antwoord - ze werden tot nu toe na elkaar aangeroepen
  (hydrateFromServer() startte pas na een voltooide /auth/me), wat een
  hele round-trip extra kost bij elke opstart voor staf/thuisgebruikers.
- app.js vraagt ze nu tegelijk op via Promise.allSettled; hydrateFromServer()
  krijgt het /me/data-resultaat optioneel meegegeven i.p.v. het zelf
  (opnieuw) op te halen. Voor een leerling/ouder wordt dat resultaat
  genegeerd (zij krijgen sowieso geen whiteboard-data) - nooit verspild
  werk, soms ongebruikt, wat de server niet meer kost dan de bestaande
  losse aanroep die er toch al was.
- De twee andere hydrateFromServer()-aanroepen (na inloggen, na een
  save-conflict) geven bewust niets mee en halen gewoon vers op, zoals
  voorheen - alleen de allereerste opstart kan dit parallelliseren.
- Geverifieerd met de volledige testsuite (112/112) en drie losse
  boot-scenario's in de sandbox (gast/staf/leerling): in alle drie komen
  /auth/me en /me/data binnen ~1ms van elkaar aan (voorheen serieel), en
  blijft het bestaande gedrag (gast blijft gast, staf krijgt het bord,
  leerling krijgt de afgeschermde weergave) exact hetzelfde.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014EPxzBVRXZZnBPvSAaPAbJ
This commit is contained in:
Ramon 2026-07-19 13:43:32 +02:00
parent 4e4aeb4b6d
commit c183c8f931
3 changed files with 20 additions and 7 deletions

View file

@ -1 +1 @@
0.4.30-beta
0.4.31-beta

View file

@ -85,10 +85,17 @@ updateEmptyHint();
(async function(){
updateBoardsUI();
try{
const me = await api("/auth/me");
currentUser = me.user;
/* /auth/me en /me/data hangen allebei alleen af van dezelfde sessie-cookie,
niet van elkaars antwoord - serieel wachten (eerst wie-ben-ik, dan pas
mijn-data ophalen) kost een hele round-trip voor niets. Parallel
opvragen en het tweede antwoord meegeven aan hydrateFromServer()
(die het gewoon negeert voor een leerling/ouder, zie daar) scheelt die
round-trip in het veelvoorkomende geval (staf/thuisgebruiker). */
const [meResult, dataResult] = await Promise.allSettled([api("/auth/me"), api("/me/data")]);
if(meResult.status !== "fulfilled") throw meResult.reason;
currentUser = meResult.value.user;
updateUserUI();
await hydrateFromServer();
await hydrateFromServer(dataResult.status === "fulfilled" ? dataResult.value : null);
}catch(e){
resetToGuest();
}

View file

@ -2,7 +2,7 @@
"use strict";
/* version shown until /api/version resolves (or if the fetch fails, e.g. offline).
Kept in sync by hand with the VERSION file at the repo root on every release. */
const VERSION = "0.4.30-beta";
const VERSION = "0.4.31-beta";
(function(){
const tag = document.getElementById("verTag");
tag.textContent = "v"+VERSION;
@ -887,7 +887,13 @@ function persistWords(){
function generalExtraFromData(data){
return (data && data.generalExtra) ? data.generalExtra : {nl:[], en:[]};
}
async function hydrateFromServer(){
/* prefetchedData: alleen gebruikt door de opstart-boot in app.js, die /me/data
al parallel met /auth/me heeft opgehaald (zie daar) i.p.v. serieel te
wachten - een leerling/ouder gebruikt het resultaat toch niet (zie de twee
vroege returns hieronder), dus dat verzoek is nooit verspild werk, alleen
soms ongebruikt. Elke andere aanroep (na inloggen, na een save-conflict)
geeft niets mee en haalt gewoon vers op, zoals voorheen. */
async function hydrateFromServer(prefetchedData){
/* schoolleerlingen hebben geen eigen borden - zij zien enkel wat de
leerkracht heeft toegewezen (zie pupil.js), nooit het whiteboard.
Thuiskinderen (leerling zonder school, ouderportaal) vallen hier expres
@ -911,7 +917,7 @@ async function hydrateFromServer(){
}
stopPupilView();
stopParentView();
const res = await api("/me/data");
const res = prefetchedData || await api("/me/data");
const d = res.data || {};
DATA_REV = typeof res.rev === "number" ? res.rev : 0;
THEMES = themesFromData(d);