source: Klonkt/tools/ward-farm/offer-many.mjs@ 66d97b8

main
Last change on this file since 66d97b8 was 66d97b8, checked in by roboburr <roboburr@…>, 5 weeks ago

Een kudde ward-daemons, om de caseload te kunnen meten (shaer-6wt, vervolg)

Bart: "precies de jeugdzorgmedewerker." Dat was geen bijval maar een correctie op
mijn prioritering, en de bredere versie ervan is dat ALLES wat we bouwden --
wardlijst, poortenpanelen, hulpvragen -- ontworpen is voor iemand met twee
kinderen. Dit is de maat die ontbrak: honderd wards, een guardian.

tools/ward-farm/farm.mjs is honderd AP-actors met eigen sleutels die de
FEP-633c-handshake aannemen. Geen Klonkt: geen timelines, geen weergave, geen
C2S. Precies genoeg om aan de andere kant van de lijn te staan.

ECHT REMOTE, en dat is geen detail. Ze wonen op een ANDERE origin dan dev.
Hing je ze onder dev zelf, dan ziet Klonkt ze als lokaal -- het co-locatiepad
kijkt of de URI met PUBLIC_BASE_URL begint -- en meet je de kortsluitroute in
plaats van de federatie.

offer-many.mjs laat dev zich honderd keer aanbieden, via de OUTBOX en dus langs
dezelfde code als de knop in de PWA. Geen tweede pad naar hetzelfde besluit; dat
is de les van vandaag. Veilig om opnieuw te draaien: wie al gecommit is wordt
overgeslagen.

Het automatische ja in de daemon staat er met een waarschuwing bij: bij een echt
kind is juist dat het moment waarop iemand moet nadenken.

Draait nu op de VPS in ~aiclaude/ward-farm, poort 3060, 100 sleutels gemaakt.
Wat ontbreekt is de publieke hostname: /etc/caddy is root, en een subdomein
toevoegen op een doos die ook andermans sites draait doe ik niet ongevraagd.

  • Property mode set to 100644
File size: 3.6 KB
Line 
1/**
2 * Deze Klonkt biedt zich aan als guardian bij een reeks wards (FEP-633c 3.1).
3 *
4 * Bedoeld voor de caseload-test: honderd kinderen, een guardian. Draait tegen de
5 * database van de instance zelf, zoals de andere scripts hier -- geen OAuth, geen
6 * tweede weg. Wat het doet is precies wat de PWA-knop doet, honderd keer.
7 *
8 * DATABASE_PATH=... PUBLIC_BASE_URL=... node offer-many.mjs \
9 * --slug dev --base https://wards.klonkt.com --from 1 --to 100
10 *
11 * ECHTE FEDERATIE, geen kortsluiting: de wards wonen op een andere origin, dus
12 * elk aanbod gaat over de lijn en wordt daar ondertekend beantwoord. Dat is het
13 * hele punt -- een test die de co-locatieroute neemt meet iets anders dan wat er
14 * in productie gebeurt.
15 *
16 * VEILIG OM OPNIEUW TE DRAAIEN: een ward die al gecommit is wordt overgeslagen,
17 * en een aanbod dat al openstaat wordt niet nog eens gestuurd. Zonder dat maakt
18 * een tweede run honderd dubbele aanbiedingen bij mensen die al ja zeiden.
19 */
20
21const args = Object.fromEntries(
22 process.argv.slice(2).join(' ').split('--').filter(Boolean)
23 .map((s) => s.trim().split(/\s+/)).map(([k, ...v]) => [k, v.join(' ') || true]),
24);
25
26const slug = args.slug || 'dev';
27const farmBase = (args.base || 'https://wards.klonkt.com').replace(/\/+$/, '');
28const van = Number(args.from || 1);
29const tot = Number(args.to || 100);
30const pauze = Number(args.pauze || 150);
31
32const AP = await import('../../src/services/ActivityPubService.js');
33const Guardianship = await import('../../src/services/guardianship/index.js');
34const dbMod = await import('../../src/config/database.js');
35const db = dbMod.default;
36
37const site = db.prepare('SELECT * FROM sites WHERE slug = ?').get(slug);
38if (!site) { console.error(`geen site met slug "${slug}"`); process.exit(1); }
39
40const base = (process.env.PUBLIC_BASE_URL || '').replace(/\/+$/, '');
41const me = AP.actorId(base, site.slug);
42console.log(`[offer] ${me} biedt zich aan bij w${String(van).padStart(3, '0')}..w${String(tot).padStart(3, '0')} op ${farmBase}`);
43
44const alBekend = new Set(Guardianship.listWards(site.slug).map((w) => w.other_uri));
45let gestuurd = 0, overgeslagen = 0, mislukt = 0;
46
47for (let i = van; i <= tot; i++) {
48 const naam = `w${String(i).padStart(3, '0')}`;
49 const ward = `${farmBase}/u/${naam}`;
50 if (alBekend.has(ward)) { overgeslagen++; continue; }
51
52 // Precies de vorm die handleOutbox verwacht: een Offer van een
53 // Relationship{subject: ward, object: ik}. Door hem via de outbox te sturen
54 // loopt dit langs dezelfde code als de knop in de PWA -- er is geen tweede pad
55 // naar hetzelfde besluit, en dat is de les van vandaag.
56 const activity = {
57 type: 'Offer',
58 to: [ward],
59 object: {
60 type: 'Relationship',
61 subject: ward,
62 object: me,
63 relationship: 'https://shaer.klonkt.com/ns#guardian',
64 },
65 };
66
67 try {
68 const uit = await AP.ingestOutboxActivity(site, { id: site.owner_id, username: slug }, activity);
69 if (uit && (uit.status === 201 || uit.status === 200)) gestuurd++;
70 else { mislukt++; console.warn(` ${naam}: ${uit && uit.status} ${uit && uit.error}`); }
71 } catch (e) {
72 mislukt++;
73 console.warn(` ${naam}: ${e.message}`);
74 }
75 // Een adempauze. Honderd handshakes tegelijk zegt meer over de bezorgwachtrij
76 // dan over het paneel, en dit script is er om het paneel te kunnen bekijken.
77 if (pauze) await new Promise((r) => setTimeout(r, pauze));
78}
79
80console.log(`[offer] verstuurd ${gestuurd}, overgeslagen ${overgeslagen}, mislukt ${mislukt}`);
81console.log('[offer] de commit valt pas als elke ward heeft geaccepteerd; kijk over een minuut met listWards.');
82process.exit(0);
Note: See TracBrowser for help on using the repository browser.