Files
swp-01-ingest/NOTES.md
T
irrlichtandClaude Sonnet 5 8a1ab8a146 Poll-Takt von 15 Minuten auf 2 Stunden senken
Reduziert den Traffic gegen die Quellen. slot_von() rundet jetzt generisch
auf TAKT-Grenzen statt fest auf 15-Minuten-Slots, die Stillstands-Schwelle
in quellen_stillstand steigt von 6h auf 24h, damit der Watchdog nicht schon
nach drei verpassten Slots anschlaegt. GDELT-Vergleich aus den Kommentaren
entfernt, da die Slots nicht mehr mit dessen 15-Minuten-Paketen zusammenfallen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013vHZCwcCJnz4LKNgvT4bxv
2026-09-04 20:34:22 +02:00

4.7 KiB

Wurzelwerk — Ingest

Stufe 0 und 1 der Pipeline: Quellenregister und Roh-Erfassung. Keine Kodierung — was hier landet, soll sich beliebig oft neu kodieren lassen.

Dateien

Datei Zweck
sources.toml Quellenregister, einzige Wahrheit ueber die Quellen
schema.sql Postgres-Schema (quellen, raw_items, codings, poll_laeufe)
poller.py Poller, zwei Senken: Postgres und gzip-JSONL
Containerfile Image fuer den Produktivbetrieb
wurzelwerk-ingest.container, wurzelwerk.network Quadlet-Units, rootless
ingest.env.example Vorlage fuer die Zugangsdaten

Deploy mit Postgres + Podman/Quadlet (rootless)

# 1. Schema einspielen
psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f schema.sql

# 2. Image bauen
podman build -t localhost/wurzelwerk-ingest:latest .

# 3. Konfiguration ablegen
mkdir -p ~/.config/wurzelwerk
cp ingest.env.example ~/.config/wurzelwerk/ingest.env
cp sources.toml       ~/.config/wurzelwerk/sources.toml
chmod 600 ~/.config/wurzelwerk/ingest.env
$EDITOR ~/.config/wurzelwerk/ingest.env

# 4. Quadlet installieren
mkdir -p ~/.config/containers/systemd
cp wurzelwerk-ingest.container wurzelwerk.network ~/.config/containers/systemd/
systemctl --user daemon-reload
systemctl --user start wurzelwerk-ingest
journalctl --user -u wurzelwerk-ingest -f

# Damit der Dienst ohne offene Sitzung weiterlaeuft:
loginctl enable-linger "$USER"

sources.toml ist eingehaengt, nicht ins Image gebacken: eine neue Quelle ist ein systemctl --user restart wurzelwerk-ingest, kein Neubau.

Schatten-Ingest auf einem Zweitgeraet

Ohne Postgres, ohne Container:

python3 poller.py --sink jsonl:/pfad/zu/deinem/ablageordner

Legt <dir>/YYYYMMDD/YYYYMMDDHHMMSS.jsonl.gz an, dedupliziert ueber eine SQLite daneben. Als systemd --user-Unit mit Restart=always einrichten.

Der Sinn ist nicht Redundanz um ihrer selbst willen: RSS-Feeds haben kein Archiv. Steht der Produktiv-Poller einen Tag still, ist dieser Tag unwiederbringlich weg. Kodierungen lassen sich wiederholen, Rohdaten nie.

Betrieb

# Lizenzstatus im Register gegen die aktuelle robots.txt pruefen
python3 poller.py --check-robots        # Exit != 0 bei Abweichung

# ein einzelner Durchlauf
python3 poller.py --sink "$DATABASE_URL" --once

--check-robots gehoert in einen woechentlichen Cron. Ein Verlag, der seine robots.txt aendert, aendert damit seinen Nutzungsvorbehalt — und das ist der Punkt, an dem eine Quelle stillgelegt werden muss.

Aendert sich etwas, wird sources.toml angepasst, nie der Code. Eine gesperrte Quelle bleibt im Register stehen (aktiv = false), damit nachvollziehbar bleibt, warum sie fehlt. Der Poller verweigert den Start, wenn eine als gesperrt gefuehrte Quelle aktiv geschaltet ist.

Waechter

-- aktive Quellen, die seit ueber sechs Stunden nichts Neues liefern
select * from quellen_stillstand;

-- Fehler der letzten Stunde
select quelle, http_status, fehler, begonnen_am from poll_laeufe
where fehler is not null and begonnen_am > now() - interval '1 hour';

Arbeitsvorrat fuer Yantra

select * from unkodiert('qwen3-14b-q4/prompt-1') limit 500;

Liefert alle Items, die diese Kodierer-Version noch nicht gesehen hat. Eine neue Prompt-Version ist damit automatisch ein vollstaendiger Recode-Auftrag ueber die gesamte Historie, ohne dass ein Feed erneut abgerufen wird.

Verhalten

  • 2-Stunden-Takt, an den Slotgrenzen ausgerichtet (+30 s Versatz), um unnoetigen Traffic bei den Quellen zu vermeiden.
  • Bedingter GET ueber ETag/Last-Modified, im Register gespeichert. Im Test antworteten 4 von 12 Quellen im zweiten Durchlauf mit 304.
  • Dedup ueber unique (quelle, item_key); item_key ist guid, ersatzweise Link, ersatzweise ein Titel-Hash.
  • Fehlertoleranz: eine kaputte Quelle beendet den Durchlauf nicht, der Fehler landet in poll_laeufe.
  • Kein Volltext-Abruf. Nur der Feed selbst wird geholt. Titel und Teaser reichen als Kodierungsinput, und damit stellt sich die TDM-Frage nach § 44b UrhG gar nicht erst.

Gemessen (2026-09-04)

Erster Lauf ueber 12 aktive Quellen: 820 Items gesehen, 810 neu, gesamter Durchlauf unter 3 s. Zweiter Lauf unmittelbar danach: 1 neues Item.

Das Trigramm-Clustering findet quellenuebergreifende Dubletten sofort:

zeit    | handelsblatt | 1.00 | Bekennerschreiben: Erneut Sabotage am Stromnetz
spiegel | derstandard  | 0.92 | Niederlage fuer Donald Trump - Gericht in Missouri

Offen

  • Telegram-Fetcher (Telethon/MTProto). Register ist vorbereitet, Eintraege stehen auf aktiv = false. Die Bot-API kann fremde Kanaele nicht lesen.
  • Ersatz-URL fuer den BR24-Feed (aktuell 404).
  • Quellenpool von 12 auf ~40 erweitern; Regionalzeitungen ueber SearXNG suchen.