Changeset 279ca0b in Klonkt for scripts/backfill-reactions.mjs


Ignore:
Timestamp:
08/06/2026 12:42:50 PM (5 weeks ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
32a4ffb
Parents:
bedd7a6
git-author:
Robin <roboburr@…> (08/06/2026 12:42:40 PM)
git-committer:
roboburr <roboburr@…> (08/06/2026 12:42:50 PM)
Message:

De derde reactiebron ook naar ap_my_reactions (shaer-ipb)

ap_interactions.acted_like/acted_boost -- wat JIJ deed met een reactie onder je
eigen post -- was de derde bron van 'heb ik hierop gereageerd'. shaer-9e9 trok de
andere twee samen en liet deze staan omdat hij op het interactie-rij-id
gesleuteld was en de tussentabel op de object-URI.

De betekeniskeuze die de bead eerst wilde beantwoorden: dezelfde note, geliket
als comment en als post, wordt EEN feit. Er gaat immers ook maar een Like de
fediverse in; twee knoppen die los van elkaar aan konden staan voor hetzelfde
object was eerder een bug dan een feature. Mechanisch blijkt dat al veilig:
markLiked en markBoosted zijn kale UPDATEs op ap_timeline die nul rijen raken als
de URI daar niet staat, en upsertBoostedNote draait alleen met opts.note mee.

Volgorde zoals bij shaer-9e9, en om dezelfde reden -- een leespad dat naar de
tussentabel wijst terwijl de rijen nog in de kolommen staan laat reacties STIL
verdwijnen:

schrijven fedi-react roept setReaction aan; acted_* loopt nog als afgeleide

mee, hetzelfde vangnet dat ap_timeline.liked na shaer-9e9 is. Ook de
toggle leest nu uit de tussentabel: las de knop de ene bron en de
richting de andere, dan stuurt een divergentie een Undo voor iets dat
nooit verstuurd is.

migreren REACTIONS_MIGRATION_VERSION 1 -> 2, derde stap erbij. Een bump laat

alle stappen opnieuw lopen; ze zijn alle drie idempotent. Rijen
zonder object_uri vallen af, en dat verliest per constructie niets:
fedi-react eist een object_uri voordat acted_* gezet kan worden.

lezen getInteractions doet een batch-lookup langs dezelfde sleutel als de

schrijfkant, dus geen N+1 in een drukke thread.

Het backfill-script zou anders vals alarm slaan: een reactie op een COMMENT hoort
geen tijdlijnrij te hebben, dus die telt niet meer als wees. Er is een controle
bij voor acted_* zonder tegenhanger.

Gemeten op een kopie van dev: scheefActed 1 -> 0, tussentabel 19 -> 20, wees
onveranderd. Suite 472/472. Gecontroleerd dat de tests bijten: laat het leespad
weer uit de kolom lezen en vier van de zes vallen om.

De karakteriseringstest zette de versievlag hard op 1 en zou bij elke bump
omvallen zonder dat er iets stuk is; die toetst nu het gedrag (ouder = opnieuw,
gelijk of hoger = overslaan) in plaats van het getal.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • scripts/backfill-reactions.mjs

    rbedd7a6 r279ca0b  
    2525//                 niet-gereageerd -- en klikt iemand opnieuw, met een tweede
    2626//                 Like de fediverse in als gevolg.
     27//   UIT REACTIES  De derde bron (shaer-ipb): ap_interactions.acted_like/_boost,
     28//                 wat jij deed met een reactie ONDER je eigen post. Zelfde
     29//                 gevolg als hierboven, alleen op een ander oppervlak.
    2730//
    2831// Wat het NIET kan: bij AANVULLEN de oorspronkelijke reactiedatum herstellen.
     
    4548       AND NOT EXISTS (SELECT 1 FROM ap_my_reactions r
    4649                        WHERE r.site_slug = t.slug AND r.target_uri = t.id)`).get().n,
     50  // Een reactie op een COMMENT hoort geen tijdlijnrij te hebben, dus die telt
     51  // hier niet als wees -- anders slaat de controle hieronder alarm op precies
     52  // wat stap 3 net goed heeft gezet.
    4753  wees: db.prepare(`
    4854    SELECT COUNT(*) AS n FROM ap_my_reactions r
    4955     WHERE NOT EXISTS (SELECT 1 FROM ap_timeline t
    50                         WHERE t.slug = r.site_slug AND t.id = r.target_uri)`).get().n,
     56                        WHERE t.slug = r.site_slug AND t.id = r.target_uri)
     57       AND NOT EXISTS (SELECT 1 FROM ap_interactions i WHERE i.object_uri = r.target_uri)`).get().n,
     58  scheefActed: db.prepare(`
     59    SELECT COUNT(*) AS n FROM ap_interactions i
     60     JOIN posts p ON p.id = i.post_id
     61     JOIN sites s ON s.id = p.site_id
     62     WHERE (i.acted_like = 1 OR i.acted_boost = 1) AND IFNULL(i.object_uri, '') <> ''
     63       AND NOT EXISTS (SELECT 1 FROM ap_my_reactions r
     64                        WHERE r.site_slug = s.slug AND r.target_uri = i.object_uri)`).get().n,
    5165});
    5266
     
    6074}
    6175if (dryRun) {
    62   console.log(`\n--dry-run: zou ${uit.hersleuteld} rij(en) hersleutelen en ${uit.aangevuld} aanvullen. Niets geschreven.`);
     76  console.log(`\n--dry-run: zou ${uit.hersleuteld} rij(en) hersleutelen, ${uit.aangevuld} aanvullen`
     77    + ` en ${uit.reacties} uit reacties overnemen. Niets geschreven.`);
    6378  process.exit(0);
    6479}
    6580
    6681const na = meet();
    67 console.log('hersleuteld:', uit.hersleuteld, ' aangevuld:', uit.aangevuld);
     82console.log('hersleuteld:', uit.hersleuteld, ' aangevuld:', uit.aangevuld, ' uit reacties:', uit.reacties);
    6883console.log('achteraf   :', JSON.stringify(na));
    6984
     
    7590if (na.scheef !== 0) {
    7691  console.error(`\nFOUT: nog ${na.scheef} rij(en) met een vlag zonder tegenhanger.`);
     92  process.exit(1);
     93}
     94if (na.scheefActed !== 0) {
     95  console.error(`\nFOUT: nog ${na.scheefActed} reactie(s) onder je eigen posts met acted_* zonder tegenhanger.`);
    7796  process.exit(1);
    7897}
Note: See TracChangeset for help on using the changeset viewer.