Changeset 14f54a7 in Klonkt
- Timestamp:
- 07/04/2026 05:31:45 PM (2 months ago)
- Branches:
- main
- Children:
- 6ec0433
- Parents:
- 6dd1a3f
- Files:
-
- 5 edited
-
CHANGELOG.de.md (modified) (1 diff)
-
CHANGELOG.md (modified) (1 diff)
-
CHANGELOG.nl.md (modified) (1 diff)
-
src/routes/posts.js (modified) (1 diff)
-
src/services/ActivityPubService.js (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
CHANGELOG.de.md
r6dd1a3f r14f54a7 9 9 - **Boosts, die ihr Cover verloren hatten, bekommen es automatisch zurück.** 10 10 Beiträge, die du vor dem Cover-Fix geboostet hast, waren ohne Artwork 11 gespeichert; sie werden beim nächsten Neustart einmalig aufgefrischt. Einen 12 Beitrag erneut zu boosten aktualisiert jetzt ebenfalls die gespeicherte Kopie 13 (Cover, Inhalt) — ein veralteter Boost lässt sich also auch von Hand heilen. 11 gespeichert; sie werden beim nächsten Neustart einmalig aufgefrischt. Ist der 12 Heimserver eines Beitrags in dem Moment kurz nicht erreichbar, wird es bei den 13 nächsten Neustarts erneut versucht statt endgültig übersprungen. Einen Beitrag 14 erneut zu boosten aktualisiert jetzt ebenfalls die gespeicherte Kopie (Cover, 15 Inhalt) — aus dem Feed wie von der Interact-Seite. 14 16 15 17 ## [1.3.3] — 2026-07-03 -
CHANGELOG.md
r6dd1a3f r14f54a7 9 9 - **Boosts that lost their cover get it back automatically.** Posts you boosted 10 10 before the cover fix were cached without their artwork; they are refreshed 11 once on the next restart. Boosting a post again now also refreshes its cached 12 copy (cover, content), so a stale boost can always be healed by hand too. 11 once on the next restart. If a post's home server is briefly unreachable at 12 that moment, it is retried on the next restarts instead of being skipped for 13 good. Boosting a post again now also refreshes its cached copy (cover, 14 content) — from the feed as well as the interact page. 13 15 14 16 ## [1.3.3] — 2026-07-03 -
CHANGELOG.nl.md
r6dd1a3f r14f54a7 9 9 - **Boosts die hun cover kwijt waren krijgen 'm automatisch terug.** Posts die 10 10 je vóór de cover-fix boostte waren zonder artwork opgeslagen; die worden bij 11 de volgende herstart eenmalig ververst. Een post opnieuw boosten ververst nu 12 ook de opgeslagen kopie (cover, inhoud), dus een oude boost is altijd ook 13 handmatig te genezen. 11 de volgende herstart eenmalig ververst. Is de thuis-server van een post op dat 12 moment even onbereikbaar, dan wordt het bij volgende herstarts opnieuw 13 geprobeerd in plaats van voorgoed overgeslagen. Een post opnieuw boosten 14 ververst nu ook de opgeslagen kopie (cover, inhoud) — vanuit de feed én de 15 interact-pagina. 14 16 15 17 ## [1.3.3] — 2026-07-03 -
src/routes/posts.js
r6dd1a3f r14f54a7 867 867 on = !ActivityPubService.getTimelineReaction(site.slug, note).boosted; 868 868 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 } 870 880 } 871 881 if (req.get('X-Requested-With') === 'fetch') return res.json({ ok: true, on }); -
src/services/ActivityPubService.js
r6dd1a3f r14f54a7 1878 1878 // during a flux window, e.g. a fleet-wide update), and drops notes that are gone 1879 1879 // (404/410). Bump SELFHEAL_VERSION only on a release that warrants a re-sync. 1880 const SELFHEAL_VERSION = 6; // v6: re-fetch so boosted notes cached coverless (pre image-fallback in resolveRemoteNote) pick up their cover1880 const SELFHEAL_VERSION = 7; // v7: rerun v6 with retry-until-clean semantics (origins briefly offline no longer stay stale forever) 1881 1881 async function fetchNoteAP(url) { 1882 1882 try { … … 2052 2052 let rows = []; 2053 2053 try { rows = db.prepare('SELECT id, content, media_json, nsfw, cw, url FROM ap_timeline ORDER BY rowid DESC LIMIT 200').all(); } catch { /* no table */ } 2054 let healed = 0 ;2054 let healed = 0, failed = 0; 2055 2055 for (const r of rows) { 2056 2056 try { 2057 2057 const note = await fetchNoteAP(r.id); 2058 2058 if (note === 404) { db.prepare('DELETE FROM ap_timeline WHERE id = ?').run(r.id); healed++; continue; } 2059 if (!note || typeof note !== 'object') continue;2059 if (!note || typeof note !== 'object') { failed++; continue; } // origin unreachable right now 2060 2060 const html = HtmlSanitizerService.sanitize(note.content || ''); 2061 2061 const media = mediaFromNote(note); … … 2067 2067 healed++; 2068 2068 } 2069 } catch { /* per-note best-effort */ } 2070 } 2071 try { db.prepare('INSERT OR REPLACE INTO app_settings (key, value) VALUES (?, ?)').run('selfheal_version', String(SELFHEAL_VERSION)); } catch { /* ignore */ } 2072 if (rows.length) console.log(`[AP] self-heal v${SELFHEAL_VERSION}: ${healed}/${rows.length} timeline notes`); 2069 } catch { failed++; /* per-note best-effort */ } 2070 } 2071 // Only mark this version DONE after a clean pass. Some origins are briefly 2072 // offline exactly when we heal (phone-hosted instances!): skipping them and 2073 // consuming the version would leave those rows stale forever. Instead retry 2074 // on the next boots, giving up after a few attempts (permanently-dead 2075 // origins answer 404/410 and are deleted above, so they don't loop). 2076 const setSetting = (k, v) => { try { db.prepare('INSERT OR REPLACE INTO app_settings (key, value) VALUES (?, ?)').run(k, String(v)); } catch { /* ignore */ } }; 2077 let attempts = 0; 2078 try { const a = db.prepare('SELECT value FROM app_settings WHERE key = ?').get('selfheal_attempts'); attempts = a ? (parseInt(a.value, 10) || 0) : 0; } catch { /* ignore */ } 2079 if (failed === 0 || attempts >= 4) { 2080 setSetting('selfheal_version', SELFHEAL_VERSION); 2081 setSetting('selfheal_attempts', 0); 2082 } else { 2083 setSetting('selfheal_attempts', attempts + 1); 2084 } 2085 if (rows.length) console.log(`[AP] self-heal v${SELFHEAL_VERSION}: ${healed}/${rows.length} timeline notes${failed ? ` (${failed} unreachable — will retry next boot)` : ''}`); 2073 2086 } catch { /* never block boot */ } finally { _selfHealing = false; } 2074 2087 }
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)