source: Klonkt/tools/ward-farm/offer-many.mjs@ 4425cc2

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

Het Offer IS de toestemming van de kandidaat (shaer-6wt)

Uitgezocht, en de fout was van mij. Ik gaf gisteren een "lead" af naar
handshake.js regel 600 -- de inkomende accept-tak die geen fanout doet. Die lead
was onjuist en ik trek hem terug.

Klonkt zegt het met zoveel woorden, en die regel had ik moeten lezen voordat ik
naar zijn code wees:

"The Offer carries the candidate's agreement -- a free ward then commits on

its own accept."

De afsluitende Accept van de kandidaat waar mijn daemon op wachtte, komt bij een
VRIJE ward nooit, en dat hoort ook niet. Dev deed precies wat het moest doen; de
daemon bleef wachten op iets dat het protocol niet stuurt. Dat verklaart ook @mee
meteen: haar Klonkt implementeert dit goed en committeerde op haar eigen ja.

De daemon telt nu echt. Partijen zijn de kandidaat, de ward zelf en de bestaande
guardians uit to; de kandidaat staat er meteen als ja in. Committen als
IEDEREEN ja heeft gezegd -- niet "commit bij mijn eigen ja", want dat werkt voor
de eerste guardian en is stilletjes fout voor de tweede. Wat nog ontbreekt wordt
gelogd, zodat een half afgemaakte handshake zichtbaar is in plaats van stil.

En de telling in offer-many: 202 is hier de NORMALE uitkomst, geen mislukking.
Het scherm zei "verstuurd 0" terwijl alles goed ging, en een verzonnen
mislukking is net zo verwarrend als een verzwegen fout.

RESULTAAT: 100 wards, beide kanten eens, over http met HTTP-signatures en zonder
TLS. Eerste meting van de caseload: 1414 poortrijen in 26 ms, maar de wards-queue
die de apps elke verversing ophalen is 222 KB.

  • Property mode set to 100644
File size: 4.0 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 || 'http://[::1]:3060').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 // De exacte waarde die isGuardianRelationship accepteert. Mijn eerste
64 // poging gebruikte een verzonnen URI en werd stil geweigerd.
65 relationship: 'shaer:Guardian',
66 },
67 };
68
69 try {
70 const uit = await AP.ingestOutboxActivity(site, { id: site.owner_id, username: slug }, activity);
71 // 202 is hier de NORMALE uitkomst: de handshake is aangenomen en loopt, de
72 // commit valt pas als de ward antwoordt. Ik telde hem als mislukt, en de
73 // eindregel zei daardoor "verstuurd 0" terwijl alles goed ging -- een
74 // verzonnen mislukking is net zo verwarrend als een verzwegen fout.
75 if (uit && uit.status >= 200 && uit.status < 300) gestuurd++;
76 else { mislukt++; console.warn(` ${naam}: ${uit && uit.status} ${uit && uit.error}`); }
77 } catch (e) {
78 mislukt++;
79 console.warn(` ${naam}: ${e.message}`);
80 }
81 // Een adempauze. Honderd handshakes tegelijk zegt meer over de bezorgwachtrij
82 // dan over het paneel, en dit script is er om het paneel te kunnen bekijken.
83 if (pauze) await new Promise((r) => setTimeout(r, pauze));
84}
85
86console.log(`[offer] verstuurd ${gestuurd}, overgeslagen ${overgeslagen}, mislukt ${mislukt}`);
87console.log('[offer] de commit valt pas als elke ward heeft geaccepteerd; kijk over een minuut met listWards.');
88process.exit(0);
Note: See TracBrowser for help on using the repository browser.