Changeset 14f54a7 in Klonkt for src/routes


Ignore:
Timestamp:
07/04/2026 05:31:45 PM (2 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
6ec0433
Parents:
6dd1a3f
Message:

fix(ap): self-heal retries until a clean pass; feed re-boost also refreshes

Scale fix (think 1M instances, not this one row): the previous remedies
still had two gaps that only showed up per-user.

  • selfHealTimeline consumed its version even when some origins were unreachable at that exact moment - phone-hosted instances are offline routinely, so their notes stayed stale forever with no retry. The version is now only persisted after a CLEAN pass (0 unreachable); otherwise it retries on the next boots and gives up after 5 attempts (dead origins answer 404/410 and are pruned, so no infinite loop). SELFHEAL_VERSION 6 -> 7 so already-healed instances rerun with the new semantics.
  • The /news feed boost only did markBoosted, so "boost again to heal a stale copy" silently worked from the interact page but not the feed. Boosting from the feed now also re-resolves the note (fire-and-forget) and refreshes the cached row via upsertBoostedNote.

Retry state machine verified in isolation (offline-then-reachable ->
heals; permanently dead -> gives up after 5 passes, then skips). Suite
45/45.

  • src/services/ActivityPubService.js - clean-pass gating + attempts counter (app_settings, no schema change); SELFHEAL_VERSION 7
  • src/routes/posts.js - /news/boost refreshes the cached row on boost
  • CHANGELOG(.nl/.de).md - extended the Unreleased bullet (3 languages)

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/routes/posts.js

    r6dd1a3f r14f54a7  
    867867    on = !ActivityPubService.getTimelineReaction(site.slug, note).boosted;
    868868    try { await ActivityPubService.sendInteraction(site, on ? 'boost' : 'unboost', note, (req.body.author || '').toString()); } catch (e) { /* ignore */ }
    869     if (on) ActivityPubService.markBoosted(site.slug, note); else ActivityPubService.unmarkBoosted(site.slug, note);
     869    if (on) {
     870      ActivityPubService.markBoosted(site.slug, note); // instant UI state
     871      // Fire-and-forget: re-resolve the note so the cached row is refreshed
     872      // (cover/content) — boosting again heals a stale copy from EVERY boost
     873      // path, not just the interact page.
     874      ActivityPubService.resolveRemoteNote(note)
     875        .then((n) => { if (n) ActivityPubService.upsertBoostedNote(site.slug, n); })
     876        .catch(() => { /* best-effort */ });
     877    } else {
     878      ActivityPubService.unmarkBoosted(site.slug, note);
     879    }
    870880  }
    871881  if (req.get('X-Requested-With') === 'fetch') return res.json({ ok: true, on });
Note: See TracChangeset for help on using the changeset viewer.