- Timestamp:
- 09/04/2026 12:05:08 PM (4 days ago)
- Branches:
- main
- Children:
- 9946a68
- Parents:
- aa521c3
- Location:
- src
- Files:
-
- 4 edited
-
config/database.js (modified) (1 diff)
-
services/ArchiveExportService.js (modified) (3 diffs)
-
services/ap-cirkel.js (modified) (2 diffs)
-
services/ap-timeline.js (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/config/database.js
raa521c3 r8151340 21 21 db.pragma('busy_timeout = 5000'); // wait up to 5s for a lock instead of failing immediately 22 22 db.pragma('synchronous = NORMAL'); // safe with WAL (no torn writes); fewer fsyncs = faster writes 23 24 /** 25 * Tijdstempels in EEN spelling (shaer-a937). 26 * 27 * Deze database draagt twee vormen door elkaar: '2026-08-06 09:02:01' van 28 * CURRENT_TIMESTAMP en '2026-08-06T02:08:01.000Z' van toISOString(). SQLite 29 * vergelijkt ze als TEKST, en op positie 10 staat een 'T' (0x54) tegenover een 30 * spatie (0x20) -- dus binnen dezelfde dag wint de ISO-vorm altijd, hoe laat hij 31 * ook is. Een antwoord van 02:08 kwam zo boven een like van 09:02 te staan. 32 * 33 * `NU_ISO` is wat je SCHRIJFT, `isoSql()` is waarmee je VERGELIJKT of SORTEERT. 34 * De twee horen bij elkaar: het eerste zorgt dat er niets nieuws bijkomt, het 35 * tweede dat wat er al staat toch goed op volgorde komt. 36 * 37 * isoSql valt met COALESCE terug op de RAUWE waarde: strftime geeft NULL op iets 38 * dat het niet als tijd herkent, en zonder die terugval zou zo'n rij uit de 39 * sortering vallen -- of erger, als hij ook geSELECTeerd wordt (de cursor in de 40 * gesprekslezing) zou de client een lege stempel terugkrijgen en zijn plek 41 * kwijtraken. Waar zo'n onleesbare waarde dan LANDT is onbepaald: hij wordt als 42 * tekst vergeleken en 'geen datum' staat nu eenmaal boven '2026-...'. Dat is de 43 * juiste ruil -- data die je niet begrijpt bewaar je, je gooit hem niet weg. 44 * 45 * Ze staan HIER en niet in een dienst omdat ze over de opslag gaan: elke plek 46 * die sorteert importeert `db` toch al uit dit bestand. 47 */ 48 export const NU_ISO = "strftime('%Y-%m-%dT%H:%M:%SZ','now')"; 49 export const isoSql = (expr) => `COALESCE(strftime('%Y-%m-%dT%H:%M:%SZ', ${expr}), ${expr})`; 23 50 24 51 export function initializeDatabase() { -
src/services/ArchiveExportService.js
raa521c3 r8151340 18 18 import path from 'path'; 19 19 import crypto from 'crypto'; 20 import db from '../config/database.js';20 import db, { isoSql } from '../config/database.js'; 21 21 import { MEDIA_ROOT, resolveAudioPath } from '../config/paths.js'; 22 22 … … 494 494 // is de volgorde van twee posts op dezelfde seconde niet bepaald. 495 495 const posts = db.prepare(`SELECT * FROM posts WHERE site_id = ? 496 ORDER BY COALESCE(published_at, created_at)ASC, id ASC`).all(site.id);496 ORDER BY ${isoSql('COALESCE(published_at, created_at)')} ASC, id ASC`).all(site.id); 497 497 498 498 for (const post of posts) { … … 539 539 try { 540 540 replies = db.prepare(`SELECT * FROM ap_interactions WHERE post_id = ? AND kind = 'reply' 541 ORDER BY COALESCE(published, created_at)ASC, id ASC`).all(post.id);541 ORDER BY ${isoSql('COALESCE(published, created_at)')} ASC, id ASC`).all(post.id); 542 542 } catch { /* tabel kan ontbreken op een heel oude database */ } 543 543 if (replies.length) { -
src/services/ap-cirkel.js
raa521c3 r8151340 7 7 * een werktuig uit de dienstlaag: alleen db. 8 8 */ 9 import db from '../config/database.js';9 import db, { isoSql } from '../config/database.js'; 10 10 11 11 // ── Cirkel = posts from the accounts you auto-boost ("feature an artist") ── … … 29 29 LEFT JOIN ap_my_reactions rb ON rb.site_slug = t.slug AND rb.target_uri = t.id AND rb.kind = 'boost' 30 30 WHERE t.slug = ? AND (f.auto_boost = 1 OR rb.target_uri IS NOT NULL) 31 ORDER BY COALESCE(t.published, t.created_at)DESC, t.rowid DESC31 ORDER BY ${isoSql('COALESCE(t.published, t.created_at)')} DESC, t.rowid DESC 32 32 LIMIT ? OFFSET ?`); 33 33 return _cirkelPosts.all(slug, limit || 60, offset || 0); -
src/services/ap-timeline.js
raa521c3 r8151340 13 13 * wireTimeline, hetzelfde injectiepatroon als guardianship en ap-c2s. 14 14 */ 15 import db from '../config/database.js'; 15 import db, { isoSql } from '../config/database.js'; 16 17 // De helper woont sinds shaer-a937 in config/database.js: elke plek die 18 // sorteert had hem nodig, en twee kopieen van dezelfde regel lopen uit elkaar. 19 // Bovenaan, want de eerste statements hieronder gebruiken hem al. 20 const STEMPEL = isoSql; 16 21 17 22 // Het ene werktuig uit de dienstlaag. ActivityPubService vult het onderaan … … 26 31 if (!_insTl) { 27 32 _insTl = db.prepare('INSERT OR IGNORE INTO ap_timeline (id, slug, author_uri, author_name, author_handle, author_icon, author_url, content, url, published, media_json, nsfw, cw, created_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,CURRENT_TIMESTAMP)'); 28 _listTl = db.prepare( 'SELECT * FROM ap_timeline WHERE slug = ? ORDER BY COALESCE(published, created_at) DESC LIMIT ? OFFSET ?');33 _listTl = db.prepare(`SELECT * FROM ap_timeline WHERE slug = ? ORDER BY ${STEMPEL('COALESCE(published, created_at)')} DESC LIMIT ? OFFSET ?`); 29 34 _delTl = db.prepare('DELETE FROM ap_timeline WHERE id = ?'); 30 35 } … … 119 124 JOIN sites s ON s.id = p.site_id 120 125 WHERE s.slug = ? AND i.kind = 'reply' 121 ORDER BY COALESCE(i.published, i.created_at)DESC LIMIT ?`).all(slug, limit || 60);126 ORDER BY ${STEMPEL('COALESCE(i.published, i.created_at)')} DESC LIMIT ?`).all(slug, limit || 60); 122 127 } catch { return []; } 123 128 } … … 242 247 * een leeftijd die twee uur verschilde per vorm. 243 248 */ 244 const STEMPEL = (rauw) => `COALESCE(strftime('%Y-%m-%dT%H:%M:%SZ', ${rauw}), ${rauw})`;245 249 246 250 const CONVERSATION_UNION = ` … … 425 429 WHERE m.slug = ? 426 430 AND NOT EXISTS (SELECT 1 FROM ap_timeline t WHERE t.slug = m.slug AND t.id = m.object_uri) 427 ORDER BY COALESCE(m.published, m.created_at)DESC LIMIT ?`).all(slug, limit || 60);431 ORDER BY ${STEMPEL('COALESCE(m.published, m.created_at)')} DESC LIMIT ?`).all(slug, limit || 60); 428 432 } catch { return []; } 429 433 }
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)