Ignore:
Timestamp:
08/06/2026 09:46:01 AM (5 weeks ago)
Author:
Claude (agent) <aiclaude@…>
Branches:
main
Children:
5296349
Parents:
7842ca1
git-author:
Robin <roboburr@…> (08/06/2026 09:46:00 AM)
git-committer:
Claude (agent) <aiclaude@…> (08/06/2026 09:46:01 AM)
Message:

Weergave gelijkgetrokken: Krant en Cirkel lezen de tussentabel (shaer-9e9)

CORRECTIE: ik meldde fase 2 als klaar, en dat was te vroeg. De Krant TEKENDE
zijn like- en boostknoppen nog uit ap_timeline.liked/boosted (tl-item.ejs leest
p.liked en p.boosted), terwijl de toggle al uit getReaction besliste. Tekenen en
beslissen leunden dus op verschillende bronnen. Ze waren het eens zolang de
migratie ze gelijk hield -- synchronisatie, geen ontwerp.

getTimeline leidt liked/boosted nu af uit de tussentabel, met dezelfde
batch-query als de C2S-tijdlijn: één extra query per pagina, geen N+1. Bewust in
JS en niet als join, want de rijen komen met SELECT * en dan zouden twee
kolommen liked heten -- welke dan wint hangt van de driver af.

getCirkelPosts kon niet in JS: die filtert in de WHERE. Daar is het een LEFT JOIN
op ap_my_reactions geworden, met (rb.target_uri IS NOT NULL) AS boosted zodat de
view ongewijzigd blijft. De UNIQUE(site_slug, target_uri, kind) garandeert
hoogstens één match, dus de join kan geen rijen verdubbelen.

boostedCount telt nu de tussentabel, nog steeds met een join op ap_timeline zodat
de betekenis gelijk blijft: geboost EN in je tijdlijn.

Twee karakteriseringstests gingen hierdoor stuk, en dat is precies waarvoor ze er
staan: ze legden vast dat een kale kolomvlag een post de Cirkel in trok. Dat is
nu niet meer waar. Bewust bijgewerkt met de reden erbij, niet weggehaald.
upsertBoostedNote blijft verantwoordelijk voor de RIJ -- zonder die insert heeft
een boost van iemand die je niet volgt geen post om bij te horen.

Daarmee leest niets in de weergave nog uit de kolommen. Ze worden alleen nog
geschreven (vangnet) en gelezen door de migratie. Dat maakt de drop een losse,
terugdraaibare beslissing in plaats van een verweven.

Geen breaking change: additief en intern, dus kandidaat voor de volgende MINOR.

Suite 441/441.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/services/ActivityPubService.js

    r7842ca1 r25f2e64  
    31923192  return { ins: _insTl, list: _listTl, del: _delTl };
    31933193}
    3194 export function getTimeline(slug, limit, offset) { return tlStmts().list.all(slug, limit || 50, offset || 0); }
     3194/**
     3195 * De tijdlijn, met liked/boosted uit de TUSSENTABEL (shaer-9e9).
     3196 *
     3197 * De rijen komen met SELECT *, dus ap_timeline.liked en .boosted liften mee --
     3198 * en die zijn sinds fase 1 nog maar een afgeleide. De Krant tekende zijn
     3199 * knoppen daar wel op, terwijl de toggle al uit getReaction besliste: tekenen en
     3200 * beslissen leunden dus op verschillende bronnen. Ze waren het eens zolang de
     3201 * migratie ze gelijk hield, maar dat was synchronisatie en geen ontwerp.
     3202 *
     3203 * Bewust in JS en niet als join: met SELECT * zouden twee kolommen `liked`
     3204 * heten en hangt het van de driver af welke wint. Eén extra query per pagina
     3205 * (dezelfde batch die de C2S-tijdlijn gebruikt) is dat niet waard.
     3206 */
     3207export function getTimeline(slug, limit, offset) {
     3208  const rows = tlStmts().list.all(slug, limit || 50, offset || 0);
     3209  const reacties = getReactionsFor(slug, rows.map((r) => r.id));
     3210  for (const r of rows) {
     3211    const x = reacties.get(r.id);
     3212    r.liked = !!(x && x.liked);
     3213    r.boosted = !!(x && x.boosted);
     3214  }
     3215  return rows;
     3216}
    31953217
    31963218/**
     
    33843406    if (!_cirkelPosts) _cirkelPosts = db.prepare(`
    33853407      SELECT t.id, t.author_uri, t.author_name, t.author_handle, t.author_icon, t.author_url,
    3386              t.content, t.url, t.published, t.media_json, t.boosted, t.nsfw, t.cw
     3408             t.content, t.url, t.published, t.media_json, t.nsfw, t.cw,
     3409             (rb.target_uri IS NOT NULL) AS boosted
    33873410      FROM ap_timeline t
    33883411      LEFT JOIN ap_following f ON f.slug = t.slug AND f.actor_uri = t.author_uri
    3389       WHERE t.slug = ? AND (f.auto_boost = 1 OR t.boosted = 1)
     3412      -- Uit de tussentabel, niet uit t.boosted: die kolom is een afgeleide. De
     3413      -- UNIQUE(site_slug, target_uri, kind) garandeert hoogstens één match, dus
     3414      -- deze join kan geen rijen verdubbelen.
     3415      LEFT JOIN ap_my_reactions rb ON rb.site_slug = t.slug AND rb.target_uri = t.id AND rb.kind = 'boost'
     3416      WHERE t.slug = ? AND (f.auto_boost = 1 OR rb.target_uri IS NOT NULL)
    33903417      ORDER BY COALESCE(t.published, t.created_at) DESC, t.rowid DESC
    33913418      LIMIT ? OFFSET ?`);
     
    36373664}
    36383665export function boostedCount(slug) {
    3639   try { if (!_boostedCount) _boostedCount = db.prepare('SELECT COUNT(*) AS n FROM ap_timeline WHERE slug = ? AND boosted = 1'); return _boostedCount.get(slug).n; } catch { return 0; }
     3666  // Geboost EN in je tijdlijn, zoals voorheen: de tussentabel kan ook een boost
     3667  // bevatten van iets dat er (nog) niet in staat.
     3668  try {
     3669    if (!_boostedCount) _boostedCount = db.prepare(`SELECT COUNT(*) AS n FROM ap_my_reactions r
     3670      JOIN ap_timeline t ON t.slug = r.site_slug AND t.id = r.target_uri
     3671      WHERE r.site_slug = ? AND r.kind = 'boost'`);
     3672    return _boostedCount.get(slug).n;
     3673  } catch { return 0; }
    36403674}
    36413675
Note: See TracChangeset for help on using the changeset viewer.