Changeset e667d26 in Klonkt
- Timestamp:
- 08/09/2026 07:28:31 AM (4 weeks ago)
- Branches:
- main
- Children:
- c832064
- Parents:
- 82c3356
- git-author:
- Robin <roboburr@…> (08/09/2026 07:28:29 AM)
- git-committer:
- roboburr <roboburr@…> (08/09/2026 07:28:31 AM)
- Files:
-
- 5 edited
-
src/assets/js/guardian.js (modified) (5 diffs)
-
src/routes/guardian.js (modified) (1 diff)
-
src/services/guardianship/help.js (modified) (2 diffs)
-
src/services/guardianship/queues.js (modified) (1 diff)
-
test/guardian-help-state.test.js (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/assets/js/guardian.js
r82c3356 re667d26 108 108 */ 109 109 function helpState(h) { 110 var st = h.state || { open: true, pickedUpBy: [], handled: null, ageMs: null };110 var st = h.state || { open: true, pickedUpBy: [], handled: null, oldestPickupAt: null }; 111 111 var box = el('div', 'g-help-state'); 112 112 … … 133 133 // Oud, maar niet weg. Dit is het verschil tussen 'er is iemand mee bezig' en 134 134 // 'er was ooit iemand mee bezig'. 135 if (st.ageMs != null && st.ageMs > 3600000) { 136 box.appendChild(el('div', 'g-help-age small', ago(st.ageMs))); 135 // De leeftijd wordt HIER uitgerekend, niet op de server: een verschil met 136 // `now` in het antwoord maakt dat antwoord elke milliseconde anders, en dan 137 // kan de ETag nooit gelijk zijn. 138 var oud = st.oldestPickupAt ? (Date.now() - Date.parse(st.oldestPickupAt)) : null; 139 if (oud != null && !isNaN(oud) && oud > 3600000) { 140 box.appendChild(el('div', 'g-help-age small', ago(oud))); 137 141 } 138 142 … … 894 898 } 895 899 900 901 // De scrollpositie overleeft een verversing (Barts melding, 9-8). renderAll 902 // bouwt lijsten opnieuw op; staat de pagina daarbij even korter, dan springt 903 // de browser omhoog en ben je kwijt waar je was. Meten en terugzetten is 904 // genoeg -- en het is het verschil tussen een scherm dat bijwerkt en een 905 // scherm dat onder je handen wegschuift. 906 function metBehoudVanScroll(fn) { 907 var y = window.scrollY || document.documentElement.scrollTop || 0; 908 fn(); 909 if (y) window.scrollTo(0, y); 910 } 911 896 912 function renderAll() { renderHelp(); renderPending(); renderWards(); } 897 913 … … 963 979 return fetch('/guardian/api/state?site=' + encodeURIComponent(S.site)) 964 980 .then(function (r) { return r.json(); }) 965 .then(function (s) { if (s && !s.error) { S = s; T = s.strings || T; renderAll(); } })981 .then(function (s) { if (s && !s.error) { S = s; T = s.strings || T; metBehoudVanScroll(renderAll); } }) 966 982 .then(loadFeed).then(loadFollowReqs); 967 983 } … … 978 994 // opnieuw getekend. 979 995 var pollBezig = false; 996 var laatsteState = null; // de vorige body, om onnodig hertekenen te herkennen 997 980 998 function longPoll() { 981 999 if (pollBezig || document.hidden) return; 982 1000 pollBezig = true; 1001 var t0 = Date.now(); 983 1002 fetch('/guardian/api/state?wait=25&site=' + encodeURIComponent(S.site)) 984 1003 .then(function (r) { 985 1004 pollBezig = false; 986 1005 if (r.status === 304) return null; // stilte 987 return r.json().then(function (s) { 988 if (s && !s.error) { S = s; T = s.strings || T; renderAll(); } 1006 return r.text().then(function (tekst) { 1007 // ZELFDE INHOUD, NIET HERTEKENEN. De 304 zou dit al moeten afvangen, 1008 // maar een enkel veld dat per verzoek verandert (er stond een levende 1009 // klok in) maakt elke ETag anders, en dan tekent het paneel zichzelf 1010 // stuk terwijl je scrollt. Dit is de tweede grendel, aan de kant die 1011 // de gebruiker merkt. 1012 if (tekst === laatsteState) return null; 1013 laatsteState = tekst; 1014 var s; try { s = JSON.parse(tekst); } catch (e) { return null; } 1015 if (s && !s.error) { S = s; T = s.strings || T; metBehoudVanScroll(renderAll); } 989 1016 return loadFeed().then(loadFollowReqs); 990 1017 }); 991 1018 }) 992 .then(function () { setTimeout(longPoll, 200); }) 1019 .then(function () { 1020 // EEN LANGE POLL DIE METEEN TERUGKEERT MAG GEEN LUS WORDEN. Wachtte de 1021 // server niet (een fout, een tussenliggende proxy, iets wat we nog niet 1022 // weten), dan houden we zelf de rem erop. Anders vervangt een defect de 1023 // ene tik van 45 seconden door duizend per minuut. 1024 var snel = Date.now() - t0 < 2000; 1025 setTimeout(longPoll, snel ? 3000 : 200); 1026 }) 993 1027 .catch(function () { 994 1028 // Netwerk weg of server herstart: niet meteen opnieuw beuken. -
src/routes/guardian.js
r82c3356 re667d26 99 99 // niet is, is de gevaarlijke fout -- niet andersom. 100 100 state: Guardianship.help.withWardship( 101 helpStaat.get(h.object_uri) || { open: true, pickedUpBy: [], handled: null, ageMs: null },101 helpStaat.get(h.object_uri) || { open: true, pickedUpBy: [], handled: null, oldestPickupAt: null }, 102 102 mijnWards.has(h.actor_uri), 103 103 ), -
src/services/guardianship/help.js
r82c3356 re667d26 52 52 * zijn zonder database of scherm. 53 53 * 54 * `ageMs` is de leeftijd van de OUDSTE oppik. Daar tekent het scherm mee dat een 55 * signaal oud wordt -- niets verdwijnt, maar je ziet wel dat er misschien niets 56 * meer gebeurt. 54 * `oldestPickupAt` is het TIJDSTIP van de oudste oppik, niet de leeftijd. Daar 55 * tekent het scherm mee dat een signaal oud wordt -- niets verdwijnt, maar je 56 * ziet wel dat er misschien niets meer gebeurt. 57 * 58 * EEN TIJDSTIP, GEEN LEEFTIJD, en dat is geen smaak. Hier stond `ageMs`, een 59 * verschil met `now`, en dus veranderde dit antwoord elke milliseconde. Zodra 60 * het paneel een ETag kreeg (9-8) kon die daardoor nooit meer gelijk zijn: de 61 * 304 kwam nooit, de lange poll keerde meteen terug, en de browser kwam in een 62 * lus van ongeveer een seconde waarin de scrollpositie werd vermalen. Een 63 * levende klok in een antwoord maakt dat antwoord onvergelijkbaar met zichzelf. 64 * 65 * De leeftijd is een weergavedetail en wordt in de client uitgerekend. 57 66 */ 58 67 export function helpStatus(rows, now = Date.now()) { … … 67 76 handled: done ? { uri: done.guardian_uri, handle: done.guardian_handle || null, at: done.created_at } : null, 68 77 // Alleen betekenisvol zolang er niets is afgesloten. 69 ageMs: (!done && oudste) ? Math.max(0, now - oudste) : null,78 oldestPickupAt: (!done && oudste) ? new Date(oudste).toISOString() : null, 70 79 // Waar het scherm op afgaat. Bij twijfel OPEN: een lege lijst, een rij die we 71 80 // niet kunnen lezen, wat dan ook -- alles wat geen expliciete afsluiting is, -
src/services/guardianship/queues.js
r82c3356 re667d26 226 226 // niet is, is de gevaarlijke fout -- niet andersom. 227 227 state: help.withWardship( 228 staat.get(r.object_uri) || { open: true, pickedUpBy: [], handled: null, ageMs: null },228 staat.get(r.object_uri) || { open: true, pickedUpBy: [], handled: null, oldestPickupAt: null }, 229 229 mijn.has(r.actor_uri), 230 230 ), -
test/guardian-help-state.test.js
r82c3356 re667d26 63 63 const s = help.helpStatus(rijen, Date.parse('2026-08-07T10:00:00.000Z')); 64 64 assert.equal(s.open, true); 65 assert.equal(s.ageMs, 2 * 24 * 3600 * 1000, 'twee dagen oud, en dat hoort te zien te zijn'); 65 // Een TIJDSTIP, geen leeftijd: een verschil met `now` maakt het antwoord elke 66 // milliseconde anders, en dan kan de ETag van het paneel nooit gelijk zijn -- 67 // dat leverde een lus op waarin de browser zichzelf bleef verversen. 68 assert.equal(s.oldestPickupAt, '2026-08-05T10:00:00.000Z'); 66 69 }); 67 70 … … 71 74 assert.equal(s.open, false); 72 75 assert.equal(s.handled.handle, '@opa@opa.test'); 73 assert.equal(s. ageMs, null, 'de leeftijdvan een oppik zegt niets meer als het klaar is');76 assert.equal(s.oldestPickupAt, null, 'het tijdstip van een oppik zegt niets meer als het klaar is'); 74 77 }); 75 78 … … 146 149 assert.deepEqual(help.withWardship(basis, true), basis); 147 150 }); 151 152 test('het antwoord verandert NIET als je het twee keer opvraagt', () => { 153 // De fout die Barts browser in een lus bracht (9-8): hier stond ageMs, een 154 // verschil met `now`. Daardoor was elk antwoord anders, kon de ETag van het 155 // paneel nooit gelijk zijn, kwam de 304 nooit, en keerde de lange poll meteen 156 // terug -- inclusief een hertekening die de scrollpositie vermaalde. 157 // 158 // Een levende klok in een antwoord maakt dat antwoord onvergelijkbaar met 159 // zichzelf. Deze toets bewaakt precies dat. 160 const rijen = [{ kind: 'pickup', guardian_uri: OMA, created_at: '2026-08-05T10:00:00.000Z' }]; 161 const a = JSON.stringify(help.helpStatus(rijen, Date.parse('2026-08-05T12:00:00.000Z'))); 162 const b = JSON.stringify(help.helpStatus(rijen, Date.parse('2026-08-05T12:00:00.500Z'))); 163 assert.equal(a, b, 'een halve seconde later is hetzelfde antwoord'); 164 });
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)