Changeset d14bf1c in Klonkt for src/config/database.js
- Timestamp:
- 08/07/2026 09:14:32 AM (5 weeks ago)
- Branches:
- main
- Children:
- 44c9f3f
- Parents:
- f2a7181
- git-author:
- Robin <roboburr@…> (08/07/2026 09:14:20 AM)
- git-committer:
- roboburr <roboburr@…> (08/07/2026 09:14:32 AM)
- File:
-
- 1 edited
-
src/config/database.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/config/database.js
rf2a7181 rd14bf1c 771 771 ensureColumn('ap_followers', 'handle', 'TEXT'); // @user@host 772 772 ensureColumn('ap_followers', 'icon', 'TEXT'); // avatar URL 773 feedStateTriggers(); 774 } 775 776 /** 777 * Wat er met een tijdlijn gebeurd is, op één plek (shaer-n05). 778 * 779 * De inbox-lezing voegt vier bronnen samen. De vraag "is er iets veranderd" werd 780 * eerst beantwoord met MAX(rowid) over die vier -- een TOEVALLIGE eigenschap van 781 * de tabellen, geen feit dat ergens is opgeschreven. Dat gaf precies de gebreken 782 * die je van zo'n afleiding verwacht: bewerkingen en verwijderingen bewogen hem 783 * niet, en hij kon achteruit lopen. Dezelfde fout als reacties uitlezen uit 784 * ap_timeline.liked (shaer-9e9). 785 * 786 * Nu één rij per bericht per tijdlijn, met een oplopende `rev` en `kind`. Dat 787 * beantwoordt drie vragen die anders drie eigen oplossingen zouden krijgen: 788 * is er iets veranderd sinds N, wát is er veranderd, en is dit bericht bewerkt. 789 * 790 * Bijgehouden door TRIGGERS en niet door de aanroepende code, om dezelfde reden 791 * dat er geen gebeurtenis-emitter is: een trigger zit in de database, dus geen 792 * enkel codepad kan hem vergeten. De prijs is onzichtbare logica -- wie alleen de 793 * JavaScript leest ziet niet waarom deze tabel vult. Vandaar dat ze hier staan, 794 * bij de tabel, en niet verspreid. 795 * 796 * Let op de `UPDATE OF`-kolomlijsten: die zijn niet decoratief. Een like schrijft 797 * ap_timeline.liked en een 🔁 schrijft .boosted; zonder die afbakening zou je 798 * eigen like het bericht als BEWERKT merken en elke wachtende client wekken. 799 */ 800 function feedStateTriggers() { 801 try { 802 db.exec(` 803 CREATE TABLE IF NOT EXISTS ap_feed_state ( 804 slug TEXT NOT NULL, 805 object_uri TEXT NOT NULL, 806 rev INTEGER NOT NULL, 807 kind TEXT NOT NULL, -- new | updated | deleted 808 at DATETIME DEFAULT CURRENT_TIMESTAMP, 809 PRIMARY KEY (slug, object_uri) 810 ); 811 CREATE INDEX IF NOT EXISTS idx_ap_feed_state_rev ON ap_feed_state(slug, rev); 812 -- Eén doorlopende teller voor de hele instance. Bewust niet MAX(rev) uit de 813 -- tabel zelf: verdwijnt de hoogste rij, dan zou die teruglopen en denkt een 814 -- client dat er niets gebeurd is. 815 CREATE TABLE IF NOT EXISTS ap_feed_rev (n INTEGER NOT NULL); 816 `); 817 if (!db.prepare('SELECT COUNT(*) AS n FROM ap_feed_rev').get().n) { 818 db.prepare('INSERT INTO ap_feed_rev (n) VALUES (0)').run(); 819 } 820 // slug + object_uri verschillen per bron; de rest is voor alle vier gelijk. 821 const zet = (naam, gebeurtenis, tabel, slug, uri, kind, extra = '') => ` 822 DROP TRIGGER IF EXISTS ${naam}; 823 CREATE TRIGGER ${naam} AFTER ${gebeurtenis} ON ${tabel} BEGIN 824 UPDATE ap_feed_rev SET n = n + 1; 825 INSERT INTO ap_feed_state (slug, object_uri, rev, kind) 826 ${extra || `VALUES (${slug}, ${uri}, (SELECT n FROM ap_feed_rev), '${kind}')`} 827 ON CONFLICT(slug, object_uri) DO UPDATE 828 SET rev = excluded.rev, kind = excluded.kind, at = CURRENT_TIMESTAMP; 829 END;`; 830 const joinPosts = (uri, kind) => ` 831 SELECT s.slug, ${uri}, (SELECT n FROM ap_feed_rev), '${kind}' 832 FROM posts p JOIN sites s ON s.id = p.site_id`; 833 db.exec([ 834 zet('trg_feed_tl_ins', 'INSERT', 'ap_timeline', 'NEW.slug', 'NEW.id', 'new'), 835 zet('trg_feed_tl_upd', 'UPDATE OF content, media_json, nsfw, cw, url, poll_json, quote_json, embed_json', 'ap_timeline', 'NEW.slug', 'NEW.id', 'updated'), 836 zet('trg_feed_tl_del', 'DELETE', 'ap_timeline', 'OLD.slug', 'OLD.id', 'deleted'), 837 zet('trg_feed_mn_ins', 'INSERT', 'ap_mentions', 'NEW.slug', 'NEW.object_uri', 'new'), 838 zet('trg_feed_mn_upd', 'UPDATE OF content, media_json, quote_json, embed_json', 'ap_mentions', 'NEW.slug', 'NEW.object_uri', 'updated'), 839 zet('trg_feed_mn_del', 'DELETE', 'ap_mentions', 'OLD.slug', 'OLD.object_uri', 'deleted'), 840 zet('trg_feed_ob_ins', 'INSERT', 'ap_outbox', 'NEW.site_slug', 'NEW.id', 'new'), 841 zet('trg_feed_ob_upd', 'UPDATE OF content, attachments', 'ap_outbox', 'NEW.site_slug', 'NEW.id', 'updated'), 842 zet('trg_feed_ob_del', 'DELETE', 'ap_outbox', 'OLD.site_slug', 'OLD.id', 'deleted'), 843 // ap_interactions draagt geen slug: die hangt aan de POST. Vandaar de join, 844 // en vandaar dat deze drie niet in de gewone vorm passen. 845 zet('trg_feed_ia_ins', 'INSERT', 'ap_interactions', '', '', '', `${joinPosts('NEW.object_uri', 'new')} WHERE p.id = NEW.post_id`), 846 zet('trg_feed_ia_upd', 'UPDATE OF content, media_json, quote_json, embed_json', 'ap_interactions', '', '', '', `${joinPosts('NEW.object_uri', 'updated')} WHERE p.id = NEW.post_id`), 847 zet('trg_feed_ia_del', 'DELETE', 'ap_interactions', '', '', '', `${joinPosts('OLD.object_uri', 'deleted')} WHERE p.id = OLD.post_id`), 848 ].join('\n')); 849 } catch (e) { 850 // Niet fataal: zonder deze tabel valt het wachten terug op "altijd de tijd 851 // volmaken", en dat is traag maar niet stuk. 852 console.error('❌ feed-state triggers:', e.message); 853 } 773 854 } 774 855
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)