Changeset 7ccdced in Klonkt for test


Ignore:
Timestamp:
10/26/2026 01:46:00 PM (27 hours ago)
Author:
Robin <roboburr@…>
Branches:
main
Parents:
bfa3ba3
Message:

Een Delete van wat nog in de rij wacht: intern oplossen

Robins vraag (26-10): "Shouldn't a Delete on an undelivered Create resolve
internally for all unfederated ones?" Ja. bfa3ba3 zorgde er alleen voor dat de
Delete NA de wachtende Create aankwam -- maar de Create kwam dan nog steeds,
en wat gewist was bereikte zo alsnog een server die het nooit had gehad.

Nu haalt een Delete per inbox de wachtende Create en Update van datzelfde
object uit de rij (cancelUndelivered). Bewust alleen wat de inhoud draagt: een
Announce of Add van een gewist object is onschuldig, de ontvanger krijgt een
404 als hij het ophaalt.

Of de Delete zelf dan nog moet, hangt af van of er iets aangekomen KAN zijn.
Daarvoor de nieuwe kolom ap_delivery.tried: een rij die in de rij ging zonder
poging (de inbox wachtte al, of de server zat in zijn backoff) is nooit de deur
uit geweest; dan gaat er voor die inbox helemaal niets ('cancelled'). Is hij
wel geprobeerd, dan kan een time-out na verwerking hem hebben laten aankomen,
en gaat de Delete toch -- onschuldig als ze hem niet kenden. Rijen van voor de
kolom tellen als geprobeerd: dat is de veilige kant.

Daarbij twee directe verzenders die ik in bfa3ba3 had gemist, nu ook langs
deliverNowOrQueue: het bewerken van een antwoord (deliverOutboxUpdate -- een
Update vóór de wachtende Create wordt genegeerd, waarna de Create de oude tekst
brengt) en guardian-activiteiten (deliverToActor).

test/direct-sends-queue.test.js, nu negen toetsen: het gewiste antwoord dat
wachtte komt nooit aan (en de Delete gaat wel, want het was geprobeerd), een
nooit geprobeerd en gewist antwoord laat niets vertrekken, alleen Create en
Update van dat object en die inbox, en de bewerking en de guardian-activiteit
wachten. Acht mutaties apart gedraaid, elk gevangen; één (ook andere soorten
weghalen) eerst niet, waarop de bedoelde grens in de toets is vastgelegd.
Volledige suite 1380 groen.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • test/direct-sends-queue.test.js

    rbfa3ba3 r7ccdced  
    5656const stil = (f) => async () => { const l = console.log, w = console.warn; console.log = () => {}; console.warn = () => {}; try { await f(); } finally { console.log = l; console.warn = w; } };
    5757
    58 test('een gewist antwoord komt niet aan vóór het antwoord zelf', stil(async () => {
     58test('een gewist antwoord dat nog wachtte, komt nooit meer aan', stil(async () => {
     59  // Robins vraag (26-10): een Delete van een Create die nog in de rij staat,
     60  // hoort intern opgelost te worden. Eerst zorgde de volgorde per inbox er
     61  // alleen voor dat de Delete NA de Create kwam -- maar de Create kwam dan nog.
    5962  leeg();
    6063  status = 503;                                            // de server van de volger hapert
    … …  
    6669  ontvangen.length = 0;
    6770  await AP.deliverOutboxDelete(site, r.id);
    68   assert.deepEqual(ontvangen, [], 'de Delete gaat niet voor');
    69   assert.deepEqual(typen(), ['Create', 'Delete'], 'hij wacht achter de Create');
     71  await AP.processDeliveryQueue();
     72  assert.ok(!ontvangen.some((o) => o.type === 'Create'), 'het gewiste antwoord gaat niet meer de deur uit');
     73  // Hij is wel één keer geprobeerd (de 503), en dan KAN hij aangekomen zijn:
     74  // dan gaat de Delete toch, voor de zekerheid.
     75  assert.deepEqual(ontvangen.map((o) => o.type), ['Delete']);
     76  assert.deepEqual(rij(), []);
     77}));
    7078
    71   await AP.processDeliveryQueue();
    72   await AP.processDeliveryQueue();
    73   assert.deepEqual(ontvangen.map((o) => o.type), ['Create', 'Delete'], 'en zo komen ze aan');
     79test('nooit geprobeerd en gewist: er gaat helemaal niets heen', stil(async () => {
     80  leeg();
     81  // De server zit in zijn backoff, dus het antwoord gaat meteen de rij in,
     82  // zonder poging; daarna wordt het gewist.
     83  AP.enqueueDelivery('me', `http://${host}/ander-pad`, { type: 'Create', id: 'https://klonkt.test/iets' });
     84  db.prepare("UPDATE ap_delivery SET next_at = datetime('now', '+30 minutes')").run();
     85  const r = await AP.deliverReply(site, { postId: '', postSlug: null, parent, text: 'nooit verstuurd' });
     86  assert.equal(rij().filter((x) => x.inbox === inbox).length, 1, 'het antwoord wacht, ongeprobeerd');
     87  await AP.deliverOutboxDelete(site, r.id);
     88  assert.deepEqual(rij().filter((x) => x.inbox === inbox), [], 'Create weg, en geen Delete erachteraan');
     89  assert.deepEqual(ontvangen, []);
     90  assert.equal(rij().length, 1, 'wat er voor een andere inbox wachtte, blijft');
     91}));
     92
     93test('alleen de Create en Update van DAT object, en alleen voor die inbox', () => {
     94  leeg();
     95  const obj = 'https://klonkt.test/ap/notes/x';
     96  AP.enqueueDelivery('me', inbox, { type: 'Create', id: `${obj}#create`, object: { id: obj } }, { tried: false });
     97  AP.enqueueDelivery('me', inbox, { type: 'Update', id: `${obj}#update`, object: { id: obj } }, { tried: false });
     98  AP.enqueueDelivery('me', inbox, { type: 'Create', id: 'y#create', object: { id: 'https://klonkt.test/ap/notes/y' } }, { tried: false });
     99  AP.enqueueDelivery('me', `http://${host}/elders`, { type: 'Create', id: `${obj}#create`, object: { id: obj } }, { tried: false });
     100  // Bewust ALLEEN wat de inhoud draagt. Een Announce of Add van een gewist
     101  // object is onschuldig: de ontvanger haalt het op en krijgt een 404.
     102  AP.enqueueDelivery('me', inbox, { type: 'Announce', id: `${obj}#boost`, object: obj }, { tried: false });
     103  const r = AP.cancelUndelivered(inbox, obj);
     104  assert.deepEqual(r, { cancelled: 2, mayHaveArrived: false });
     105  assert.deepEqual(rij().map((x) => [x.inbox.endsWith('/inbox') ? 'deze' : 'andere', JSON.parse(x.body).type, String(JSON.parse(x.body).object.id || JSON.parse(x.body).object).slice(-1)]),
     106    [['deze', 'Create', 'y'], ['andere', 'Create', 'x'], ['deze', 'Announce', 'x']]);
     107});
     108
     109test('een bewerking gaat niet voorbij het antwoord dat nog wacht', stil(async () => {
     110  leeg();
     111  status = 503;
     112  const r = await AP.deliverReply(site, { postId: '', postSlug: null, parent, text: 'origineel' });
     113  status = 202; ontvangen.length = 0;
     114  await AP.deliverOutboxUpdate(site, r.id, 'bewerkt');
     115  assert.deepEqual(ontvangen, [], 'de Update gaat niet voor: dan negeert de ander hem, en brengt de Create daarna de oude tekst');
     116  assert.deepEqual(typen(), ['Create', 'Update']);
     117}));
     118
     119test('een guardian-activiteit gaat niet voorbij wat er voor die inbox wacht', stil(async () => {
     120  leeg();
     121  const omaInbox = `http://${host}/users/oma/inbox`;
     122  AP.enqueueDelivery('me', omaInbox, { type: 'Create', id: 'https://klonkt.test/eerder' });
     123  await AP.deliverToActor(site, `http://${host}/users/oma`, { type: 'Offer', id: 'https://klonkt.test/offer/1' });
     124  assert.deepEqual(ontvangen, []);
     125  assert.equal(rij().filter((x) => x.inbox === omaInbox).length, 2);
    74126}));
    75127
Note: See TracChangeset for help on using the changeset viewer.