Schedule poll/notify and the digest as systemd timers
news-cycle.timer runs poll then notify every 15 minutes; news-digest.timer runs the briefing at 08:45 daily. Both enabled and verified: a manual cycle fetched 1047 items, embedded 95 new ones and clustered them in 74s. Units are installed as COPIES rather than symlinks. The previous service's units were symlinked into docs/projects/news/deploy/, and when that repo was renamed to news_triage they became dangling and the timer failed every ten minutes, unnoticed, until this rebuild found it. Copying costs a re-copy after editing; symlinking cost days of silent failure. Deliberate details: the poll ExecStart is `-` prefixed so a failed fetch does not skip notify; RandomizedDelaySec spreads polling off the quarter hour rather than hitting 56 sources at once; the digest is Persistent so a machine that was off at 08:45 still sends rather than skipping the day.
This commit is contained in:
1 parent
327d6a69ae
commit
83bc36aa79
5 files changed
+90
-4
No files matched your search
+39
-4
@@ -127,12 +127,47 @@ sudo systemctl disable --now news-update.timer
|
||||
| `POST /api/feedback/.../bogus` | `{"error":"bad signature"}` | reaches the app, unauthenticated, and rejects a forgery |
|
||||
| `POST /api/feedback/.../<valid HMAC>` | `{"ok":true}` and a row in `feedback` | **the loop that never once worked in v0.2** |
|
||||
|
||||
## 3. Scheduling
|
||||
## 3. Scheduling — APPLIED 2026-09-08
|
||||
|
||||
Two systemd timers, units in this directory:
|
||||
|
||||
| unit | cadence | does |
|
||||
|---|---|---|
|
||||
| `news-cycle.timer` | every 15 min | `poll` then `notify` |
|
||||
| `news-digest.timer` | daily 08:45 | `digest` |
|
||||
|
||||
```sh
|
||||
sudo cp deploy/news-*.service deploy/news-*.timer /etc/systemd/system/
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now news-cycle.timer news-digest.timer
|
||||
```
|
||||
*/15 * * * * podman exec news-backend python -m news.cli poll
|
||||
*/20 * * * * podman exec news-backend python -m news.cli notify
|
||||
45 8 * * * podman exec news-backend python -m news.cli digest
|
||||
|
||||
**Copy the units, do not symlink them.** The previous service's units were
|
||||
symlinks into `docs/projects/news/deploy/`, and when that repo was renamed to
|
||||
`news_triage` they became dangling and the timer failed every ten minutes,
|
||||
unnoticed, for days. The cost of copying is remembering to re-copy after editing
|
||||
a unit here; the cost of symlinking is a silent failure the next time a
|
||||
directory moves.
|
||||
|
||||
Design notes:
|
||||
|
||||
- `news-cycle.service` has two `ExecStart` lines and the first is prefixed `-`,
|
||||
so a failed fetch does not skip `notify` -- there may still be ripe clusters
|
||||
from an earlier cycle worth sending.
|
||||
- `RandomizedDelaySec=90` on the cycle: feeds get polled by everyone on the
|
||||
quarter hour, and this both spreads that load and avoids hitting all 56
|
||||
sources at the same instant.
|
||||
- `Persistent=true` on the digest, so a machine that was off at 08:45 still
|
||||
sends the briefing on the next boot rather than silently skipping a day.
|
||||
- `TimeoutStartSec=20min` on the cycle: a cold start embeds the whole backlog at
|
||||
~11 items/sec. Steady state is far quicker -- a real incremental cycle
|
||||
measured 74s for 95 new items.
|
||||
|
||||
Reading the logs is noisier than it should be, because podman writes its own
|
||||
container-exec events into the same unit journal:
|
||||
|
||||
```sh
|
||||
journalctl -u news-cycle -o cat | grep -vE '^[0-9]{4}-[0-9]{2}-[0-9]{2} .* container '
|
||||
```
|
||||
|
||||
## 4. Verifying it actually works
|
||||
|
||||
Reference in new issue
Block a user