| 1 | /**
|
|---|
| 2 | * Scheduler — release-planning (premium #3).
|
|---|
| 3 | *
|
|---|
| 4 | * Geplande posts hebben status 'scheduled' + publish_at (toekomst). Een lichte
|
|---|
| 5 | * timer zet ze op 'published' zodra publish_at bereikt is. Zo hoeven de publieke
|
|---|
| 6 | * queries (status='published') NIET aangepast te worden — een geplande post is
|
|---|
| 7 | * gewoon nog niet 'published' en dus nergens publiek zichtbaar tot het moment.
|
|---|
| 8 | */
|
|---|
| 9 |
|
|---|
| 10 | import db from '../config/database.js';
|
|---|
| 11 | import HtmlSanitizerService from './HtmlSanitizerService.js';
|
|---|
| 12 |
|
|---|
| 13 | export function flipScheduledPosts() {
|
|---|
| 14 | try {
|
|---|
| 15 | const due = db.prepare(`
|
|---|
| 16 | SELECT p.id, p.title, p.content, u.username
|
|---|
| 17 | FROM posts p JOIN users u ON u.id = p.author_id
|
|---|
| 18 | WHERE p.status = 'scheduled' AND p.publish_at IS NOT NULL AND p.publish_at <= CURRENT_TIMESTAMP
|
|---|
| 19 | `).all();
|
|---|
| 20 | if (!due.length) return 0;
|
|---|
| 21 | const upd = db.prepare(
|
|---|
| 22 | "UPDATE posts SET status = 'published', published_at = COALESCE(published_at, publish_at, CURRENT_TIMESTAMP) WHERE id = ?"
|
|---|
| 23 | );
|
|---|
| 24 | const fts = db.prepare('INSERT INTO posts_fts(content, title, author, post_id) VALUES (?, ?, ?, ?)');
|
|---|
| 25 | for (const p of due) {
|
|---|
| 26 | upd.run(p.id);
|
|---|
| 27 | try { fts.run(HtmlSanitizerService.toPlainText(p.content || ''), p.title || '', p.username || '', p.id); } catch { /* FTS niet-fataal */ }
|
|---|
| 28 | }
|
|---|
| 29 | return due.length;
|
|---|
| 30 | } catch { return 0; }
|
|---|
| 31 | }
|
|---|
| 32 |
|
|---|
| 33 | let _timer = null;
|
|---|
| 34 | export function startScheduler() {
|
|---|
| 35 | flipScheduledPosts(); // direct bij boot
|
|---|
| 36 | if (_timer) return;
|
|---|
| 37 | _timer = setInterval(flipScheduledPosts, 60 * 1000); // elke minuut
|
|---|
| 38 | if (_timer.unref) _timer.unref();
|
|---|
| 39 | }
|
|---|