fix(livia): eigenes Zeitlimit für die Zefix-CSV

Im Produktionslauf fiel Zefix mit «This operation was aborted» aus, während
beide Newsquellen sauber lieferten. Ursache ist die Dateigrösse: 10,5 MB,
unkomprimiert, weil der Server kein gzip anbietet. Von einem Schweizer
Anschluss dauert der Abruf 1,7 Sekunden, aus dem Rechenzentrum der Anwendung
mehr als die fünfzehn, die für die Newsquellen reichlich bemessen sind.

Die CSV bekommt deshalb dreissig Sekunden, die HTML-Abrufe behalten fünfzehn.
Beides läuft parallel, der Ausfall einer Quelle bleibt folgenlos für die
anderen — nur war es bisher immer dieselbe, die ausfiel.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin SutterandClaude Opus 5 committed 2026-08-30 18:16:12 +02:00
1 parent f58d841e7d
commit 31a098f219
1 file changed
+14 -4
+14 -4
View File
@@ -47,14 +47,24 @@ const MAX_ARTICLES = 24
const FETCH_CONCURRENCY = 8
const FETCH_TIMEOUT_MS = 15_000
/**
* Eigenes Zeitlimit für die Zefix-CSV.
*
* Die Datei ist 10,5 MB gross und wird unkomprimiert ausgeliefert — der Server
* bietet kein gzip an. Von einem Schweizer Anschluss dauert der Abruf keine
* zwei Sekunden, aus dem Rechenzentrum der Anwendung aber mehr als fünfzehn,
* und genau daran ist die Quelle im ersten Produktionslauf gescheitert.
*/
const CSV_TIMEOUT_MS = 30_000
const UA = 'Mozilla/5.0 (compatible; PropertyMatch-LiviaResearch/1.0; +https://property-match-virid.vercel.app)'
async function getText(url: string, extraHeaders: Record<string, string> = {}): Promise<string> {
async function getText(url: string, timeoutMs: number = FETCH_TIMEOUT_MS): Promise<string> {
const ctrl = new AbortController()
const timer = setTimeout(() => ctrl.abort(), FETCH_TIMEOUT_MS)
const timer = setTimeout(() => ctrl.abort(), timeoutMs)
try {
const res = await fetch(url, {
headers: { 'User-Agent': UA, 'Accept-Language': 'de-CH,de;q=0.9', ...extraHeaders },
headers: { 'User-Agent': UA, 'Accept-Language': 'de-CH,de;q=0.9' },
redirect: 'follow',
signal: ctrl.signal,
})
@@ -257,7 +267,7 @@ export async function fetchGreaterZurichResearch(): Promise<ResearchItem[]> {
* Sache, die Livia nie tun darf.
*/
export async function fetchZefixResearch(): Promise<ResearchItem[]> {
const csv = await getText(SOURCES.ZEFIX.url)
const csv = await getText(SOURCES.ZEFIX.url, CSV_TIMEOUT_MS)
const lines = csv.split(/\r?\n/)
if (lines.length < 2) throw new Error('CSV enthält keine Daten')