Changeset 7e474f7 in Klonkt for src/services/MigrationService.js


Ignore:
Timestamp:
08/14/2026 03:12:04 AM (4 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
bfadc15
Parents:
47f1183
Message:

De publieke vertaaltabel laadde alles om er twintig te tonen

Robin, ter herinnering: honderd miljoen Klonkt-gebruikers. Terecht, en het
wees meteen een echte fout aan in wat ik vandaag bouwde.

migrationItems deed SELECT zonder LIMIT. buildMigration bouwde daar objecten
van en liet pagedCollection er twintig uit snijden. Bij een gebruiker met
honderdduizend berichten betekent dat: honderdduizend rijen uit de database,
honderdduizend objecten in geheugen, 99,98 procent daarvan direct de prullenbak
in. Per verzoek.

En het is geen intern verzoek. Dit endpoint is publiek EN FEP-1580 schrijft
derden voor het herhaaldelijk op te halen tot migrationComplete waar is. Een
ontbrekende LIMIT is daar geen inefficientie maar een hefboom.

Nu in SQL gepagineerd, met dezelfde alGesneden-aanpak die de outbox al had.

DE KALE COLLECTIE DRAAGT GEEN RIJEN MEER, alleen de telling en first/last. Dat
is niet alleen goedkoper maar ook veiliger: een kale collectie MET items was
precies de valstrik waar onze eigen ingest vanmorgen in liep. Hij zag items,
sloeg first over, vond geen next en dacht klaar te zijn bij 18 van de 35.

Changed files:
src/services/MigrationService.js

  • migrationItems kent limit en offset
  • buildMigration telt apart en haalt alleen de gevraagde pagina op

test/fep1580-migration.test.js

  • de kale collectie heeft een telling en geen rijen
  • 45 items geven pagina's van 20/20/5, zonder overlap en zonder verlies

remarks: de rate-limiter dekt /ap al, dus die kant zat goed. Wat NIET opgelost
is en bij deze schaal het echte plafond blijft: buildArchive bouwt de hele zip
in geheugen, inclusief elk audiobestand. Die grens van 512 MB is nog steeds een
beredeneerde gok en geen meting. Streamen staat als shaer-190t genoteerd; bij
honderd miljoen gebruikers is dat geen nice-to-have meer. Suite 1014 groen,
tegenproef gedaan.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/services/MigrationService.js

    r47f1183 r7e474f7  
    3636import crypto from 'crypto';
    3737import db from '../config/database.js';
    38 import { AP_CONTEXT, actorId, pagedCollection } from './ap-core.js';
     38import { AP_CONTEXT, actorId, pagedCollection, PAGINA_GROOTTE } from './ap-core.js';
    3939
    4040// ── Vertaaltabel ──────────────────────────────────────────────────
     
    6666 * de URIs van je fan-only posts opsomt is een lek, ook zonder de inhoud.
    6767 */
    68 export function migrationItems(slug, { alles = false } = {}) {
     68export function migrationItems(slug, { alles = false, limit = null, offset = 0 } = {}) {
    6969  try {
     70    // IN SQL pagineren, niet in geheugen. Dit is een PUBLIEK endpoint dat
     71    // derden volgens FEP-1580 juist herhaaldelijk ophalen tot migrationComplete
     72    // waar is. Alles laden om er twintig te tonen is dan geen inefficientie
     73    // maar een hefboom: bij honderdduizend berichten bouwt elke poll
     74    // honderdduizend objecten die meteen de prullenbak in gaan.
    7075    const sql = `SELECT origin, target, source_actor FROM ap_migration
    71                  WHERE slug = ?${alles ? '' : ' AND is_public = 1'} ORDER BY id DESC`;
    72     return db.prepare(sql).all(slug);
     76                 WHERE slug = ?${alles ? '' : ' AND is_public = 1'}
     77                 ORDER BY id DESC${limit ? ' LIMIT ? OFFSET ?' : ''}`;
     78    return limit ? db.prepare(sql).all(slug, limit, offset) : db.prepare(sql).all(slug);
    7379  } catch { return []; }
    7480}
     
    151157  const me = actorId(base, site.slug);
    152158  const id = `${me}/migration`;
    153   const rows = migrationItems(site.slug, { alles });
     159  const totaal = migrationCount(site.slug, { alles });
     160  // Zonder pagina: alleen de omslag met eerste/laatste en de telling. Zo hoeft
     161  // de kale collectie geen enkele rij aan te raken, en dat is precies wat een
     162  // consument als eerste opvraagt.
     163  const nr = page ? Math.max(1, Math.floor(Number(page)) || 1) : false;
     164  const rows = nr ? migrationItems(site.slug, { alles, limit: PAGINA_GROOTTE, offset: (nr - 1) * PAGINA_GROOTTE }) : [];
    154165  const items = rows.map((r) => ({
    155166    type: 'Move',
     
    159170  }));
    160171  return pagedCollection(id, items, {
    161     page,
     172    page: nr,
     173    totalItems: totaal,
     174    alGesneden: true,
    162175    extra: {
    163176      attributedTo: me,
Note: See TracChangeset for help on using the changeset viewer.