Changeset 7e474f7 in Klonkt
- Timestamp:
- 08/14/2026 03:12:04 AM (4 weeks ago)
- Branches:
- main
- Children:
- bfadc15
- Parents:
- 47f1183
- Files:
-
- 2 edited
-
src/services/MigrationService.js (modified) (4 diffs)
-
test/fep1580-migration.test.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/services/MigrationService.js
r47f1183 r7e474f7 36 36 import crypto from 'crypto'; 37 37 import db from '../config/database.js'; 38 import { AP_CONTEXT, actorId, pagedCollection } from './ap-core.js';38 import { AP_CONTEXT, actorId, pagedCollection, PAGINA_GROOTTE } from './ap-core.js'; 39 39 40 40 // ── Vertaaltabel ────────────────────────────────────────────────── … … 66 66 * de URIs van je fan-only posts opsomt is een lek, ook zonder de inhoud. 67 67 */ 68 export function migrationItems(slug, { alles = false } = {}) {68 export function migrationItems(slug, { alles = false, limit = null, offset = 0 } = {}) { 69 69 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. 70 75 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); 73 79 } catch { return []; } 74 80 } … … 151 157 const me = actorId(base, site.slug); 152 158 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 }) : []; 154 165 const items = rows.map((r) => ({ 155 166 type: 'Move', … … 159 170 })); 160 171 return pagedCollection(id, items, { 161 page, 172 page: nr, 173 totalItems: totaal, 174 alGesneden: true, 162 175 extra: { 163 176 attributedTo: me, -
test/fep1580-migration.test.js
r47f1183 r7e474f7 149 149 Mig.recordMigrated('ik', { origin: `${BRON}/notes/1`, target: `${IK}/notes/a`, sourceActor: BRON }); 150 150 Mig.recordMigrated('ik', { origin: `${BRON}/notes/2`, target: `${IK}/notes/b`, sourceActor: BRON }); 151 const coll = Mig.buildMigration('https://nieuw.example', s); 151 // De KALE collectie draagt alleen de telling en de wegwijzers. Bewust: dit is 152 // een publiek endpoint dat derden herhaaldelijk pollen, en alle rijen laden om 153 // er twintig te tonen is bij honderdduizend berichten een hefboom. Bovendien 154 // was een kale collectie MET items precies de valstrik waar onze eigen ingest 155 // in liep: hij zag items, sloeg `first` over en miste de helft. 156 const kaal = Mig.buildMigration('https://nieuw.example', s); 157 assert.equal(kaal.totalItems, 2, 'de telling staat er wel'); 158 assert.equal((kaal.orderedItems || []).length, 0, 'maar de rijen niet'); 159 assert.ok(kaal.first, 'wie ze wil volgt first'); 160 161 const coll = Mig.buildMigration('https://nieuw.example', s, { page: 1 }); 152 162 assert.equal(coll.totalItems, 2); 153 163 const items = coll.orderedItems || coll.items; 164 assert.equal(items.length, 2); 154 165 assert.equal(items[0].origin, `${BRON}/notes/2`, 'omgekeerd chronologisch op aanmaakmoment HIER'); 155 166 assert.equal(items[0].type, 'Move'); 156 167 assert.equal(items[0].target, `${IK}/notes/b`); 168 }); 169 170 test('de publieke vertaaltabel laadt niet alles om twintig te tonen', () => { 171 // Robins herinnering: honderd miljoen Klonkt-gebruikers. Dit endpoint is 172 // publiek en derden pollen het tot migrationComplete waar is, dus een query 173 // zonder LIMIT is hier geen inefficientie maar een hefboom. 174 const s = site(); 175 for (let i = 0; i < 45; i++) { 176 Mig.recordMigrated('ik', { origin: `${BRON}/notes/n${i}`, target: `${IK}/notes/n${i}` }); 177 } 178 const p1 = Mig.buildMigration('https://nieuw.example', s, { page: 1 }); 179 assert.equal(p1.totalItems, 45, 'de telling klopt over het geheel'); 180 assert.equal(p1.orderedItems.length, 20, 'maar er komt een PAGINA uit, geen bak van 45'); 181 assert.ok(p1.next, 'en er is een volgende'); 182 const p3 = Mig.buildMigration('https://nieuw.example', s, { page: 3 }); 183 assert.equal(p3.orderedItems.length, 5, 'de laatste pagina is de rest'); 184 assert.equal(p3.next, undefined, 'en die biedt geen volgende meer aan'); 185 // De pagina's overlappen niet en samen zijn ze het geheel. 186 const p2 = Mig.buildMigration('https://nieuw.example', s, { page: 2 }); 187 const alle = [...p1.orderedItems, ...p2.orderedItems, ...p3.orderedItems].map((x) => x.origin); 188 assert.equal(new Set(alle).size, 45, 'geen dubbele en niets kwijt'); 157 189 }); 158 190
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)