Changeset bfa3ba3 in Klonkt for src


Ignore:
Timestamp:
10/26/2026 01:35:31 PM (27 hours ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
7ccdced
Parents:
31288dc
Message:

Ook de directe verzenders langs de volgorde per inbox

Rest van shaer-xzab.3. Drie plekken verstuurden zelf met deliver() en zetten
pas bij een mislukking in de rij: een antwoord (deliverReply), het wissen
daarvan (deliverOutboxDelete) en een direct bericht (deliverDirectNote, ook de
hulpvraag en de zwaai). Zo kon de Delete van een antwoord aankomen vóór het
antwoord zelf als dat nog in de rij wachtte, en stond het antwoord daarna weer
op die server.

Nu één weg: deliverNowOrQueue in ap-transport, met dezelfde regel als
deliverWithRetry (wacht er voor die inbox al iets, of zit de server in zijn
backoff, dan achteraan), en hij zegt of het 'sent' of 'queued' werd, want
deliverReply en deliverDirectNote tellen wat er meteen aankwam.
deliverWithRetry is er nu een dunne laag over. guardianship/delivery.js krijgt
deliverNowOrQueue via wireDelivery in plaats van deliver en enqueueDelivery.

test/direct-sends-queue.test.js: vijf toetsen tegen een echte HTTP-server,
waaronder het hele scenario: antwoord lukt niet en wacht, de server is terug,
het antwoord wordt gewist -- de Delete wacht achter de Create en ze komen in
die volgorde aan. Vier mutaties apart gedraaid (elke plek terug naar zelf
versturen, en 'sent' dat niet telt), elk gevangen. Volledige suite 1376 groen.

Co-Authored-By: Claude Opus 5.5 <noreply@…>

Location:
src/services
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/services/ActivityPubService.js

    r31288dc rbfa3ba3  
    3434import {
    3535  safeFetch, getOrCreateKeys, deliver, fetchActor,
    36   enqueueDelivery, deliverWithRetry, processDeliveryQueue, startDeliveryWorker,
     36  enqueueDelivery, deliverWithRetry, deliverNowOrQueue, processDeliveryQueue, startDeliveryWorker,
    3737  anySigningSlug, verifyRequest, signedGetHeaders, signedGetJson, apGetJson,
    3838} from './ap-transport.js';
    3939export {
    4040  safeFetch, getOrCreateKeys, deliver, fetchActor,
    41   enqueueDelivery, deliverWithRetry, processDeliveryQueue, startDeliveryWorker,
     41  enqueueDelivery, deliverWithRetry, deliverNowOrQueue, processDeliveryQueue, startDeliveryWorker,
    4242  verifyRequest, signedGetHeaders, signedGetJson,
    4343};
    … …  
    24162416  let delivered = 0;
    24172417  for (const inbox of [...inboxes].filter(Boolean)) {
    2418     let ok = false;
    2419     try { const st = await deliver(inbox, create, keyId, keys.private_pem); ok = st >= 200 && st < 300; } catch { ok = false; }
    2420     if (ok) delivered++;
    2421     else enqueueDelivery(site.slug, inbox, create); // durable: retry a briefly-offline recipient (was silently dropped)
     2418    // Langs de volgorde per inbox (shaer-xzab.3); wat niet meteen kan, gaat
     2419    // in de rij en wordt later opnieuw geprobeerd.
     2420    if ((await deliverNowOrQueue(site.slug, inbox, create, keyId, keys.private_pem)) === 'sent') delivered++;
    24222421  }
    24232422  console.log('[AP] outreply', site.slug, '→', parent.actor_uri, 'delivered', delivered);
    … …  
    27892788    if (row.to_actor) { const a = await fetchActor(row.to_actor).catch(() => null); if (a) inboxes.add((a.endpoints && a.endpoints.sharedInbox) || a.inbox); }
    27902789    for (const f of fStmts().list.all(site.slug)) inboxes.add(f.shared_inbox || f.inbox);
    2791     for (const inbox of [...inboxes].filter(Boolean)) {
    2792       try { const st = await deliver(inbox, del, `${me}#main-key`, keys.private_pem); if (st >= 200 && st < 300) continue; } catch { /* queue below */ }
    2793       enqueueDelivery(site.slug, inbox, del); // durable: a failed comment-delete now retries (was silently dropped)
    2794     }
     2790    // Langs de volgorde per inbox (shaer-xzab.3): deze Delete mag niet vóór
     2791    // de Create van dezelfde reactie aankomen als die nog in de rij wacht --
     2792    // dan stond de reactie daarna weer op die server.
     2793    for (const inbox of [...inboxes].filter(Boolean)) await deliverNowOrQueue(site.slug, inbox, del, `${me}#main-key`, keys.private_pem);
    27952794  }
    27962795  db.prepare('DELETE FROM ap_outbox WHERE id = ?').run(outboxId);
    … …  
    41644163  actorId, fetchActor, localActor, deliverTo: deliverToActor, deriveHandle, escHtml, linkUrls, linkHashtags,
    41654164  getOutboxRow: (id) => iStmts().getO.get(id),
    4166   buildReplyNote, AP_CONTEXT, getOrCreateKeys, deliver, enqueueDelivery,
     4165  buildReplyNote, AP_CONTEXT, getOrCreateKeys, deliverNowOrQueue,
    41674166  // Rijke directe berichten: dezelfde sanitizer als deliverReply gebruikt, zodat
    41684167  // een antwoord uit Berichten door precies één poort gaat.
  • src/services/ap-transport.js

    r31288dc rbfa3ba3  
    278278  } catch { /* health tracking is non-fatal */ }
    279279}
    280 // Deliver now; queue for retry if it fails.
     280// Deliver now, or queue: zegt welke van de twee het werd ('sent' | 'queued'),
     281// voor de aanroepers die tellen wat er meteen aankwam.
    281282//
    282283// Niet meteen als er voor deze inbox al iets in de wachtrij staat (dan zou dit
    … …  
    284285// server net faalde en in zijn backoff zit (dan kost het alleen acht seconden
    285286// time-out om hetzelfde te horen). Dan achteraan in de rij.
     287//
     288// DE ENIGE WEG om iets direct te versturen dat bij een mislukking in de rij
     289// hoort (shaer-xzab.3). Drie plekken deden eerst zelf deliver() en pas bij een
     290// mislukking enqueueDelivery(), en gingen zo langs de volgorde per inbox.
     291export async function deliverNowOrQueue(slug, inbox, activity, keyId, privPem) {
     292  if (!inbox) return 'queued';
     293  try {
     294    const st = deliveryStmts();
     295    if (st.pendInbox.get(inbox) || st.hostWaits.get(inboxHost(inbox))) { enqueueDelivery(slug, inbox, activity); return 'queued'; }
     296  } catch { /* geen wachtrij te lezen: gewoon proberen */ }
     297  try { const st = await deliver(inbox, activity, keyId, privPem); if (st >= 200 && st < 300) { markFollowerDelivery(slug, inbox, true); return 'sent'; } } catch { /* queue below */ }
     298  enqueueDelivery(slug, inbox, activity);
     299  return 'queued';
     300}
     301// Deliver now; queue for retry if it fails.
    286302export async function deliverWithRetry(slug, inbox, activity, keyId, privPem) {
    287   if (!inbox) return;
    288   try {
    289     const st = deliveryStmts();
    290     if (st.pendInbox.get(inbox) || st.hostWaits.get(inboxHost(inbox))) { enqueueDelivery(slug, inbox, activity); return; }
    291   } catch { /* geen wachtrij te lezen: gewoon proberen */ }
    292   try { const st = await deliver(inbox, activity, keyId, privPem); if (st >= 200 && st < 300) { markFollowerDelivery(slug, inbox, true); return; } } catch { /* queue below */ }
    293   enqueueDelivery(slug, inbox, activity);
     303  await deliverNowOrQueue(slug, inbox, activity, keyId, privPem);
    294304}
    295305let _processingDeliv = false;
  • src/services/guardianship/delivery.js

    r31288dc rbfa3ba3  
    9393  if (!inReplyTo && helpMark && helpMark.noteUri) inReplyTo = helpMark.noteUri;
    9494  const { actorId, fetchActor, localActor, deliverTo, deriveHandle, escHtml, linkUrls, linkHashtags,
    95           getOutboxRow, buildReplyNote, AP_CONTEXT, getOrCreateKeys, deliver, enqueueDelivery } = deps;
     95          getOutboxRow, buildReplyNote, AP_CONTEXT, getOrCreateKeys, deliverNowOrQueue } = deps;
    9696  const base = (process.env.PUBLIC_BASE_URL || '').replace(/\/+$/, '');
    9797  const list = [...new Set((recipients || []).filter((u) => /^https?:\/\//i.test(String(u || ''))))].slice(0, 8);
    … …  
    207207  }
    208208  // Remote: one POST per inbox, so two guardians on the same server share it.
     209  // Langs de volgorde per inbox (shaer-xzab.3), zoals elke bezorging.
    209210  for (const inbox of [...new Set(resolved.filter((x) => !x.local).map((r) => r.inbox))]) {
    210     let ok = false;
    211     try { const st = await deliver(inbox, create, keyId, keys.private_pem); ok = st >= 200 && st < 300; } catch { ok = false; }
    212     if (ok) delivered++;
    213     else enqueueDelivery(site.slug, inbox, create);
     211    if ((await deliverNowOrQueue(site.slug, inbox, create, keyId, keys.private_pem)) === 'sent') delivered++;
    214212  }
    215213  console.log('[AP] direct note', site.slug, '→', resolved.length, 'recipient(s), delivered', delivered);
Note: See TracChangeset for help on using the changeset viewer.