Analyse: geo-update holt Neustart nach (Marker), Runner-Test für build-Injektion

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-01 11:04:50 +00:00
1 parent 714687fe3b
commit 466fcffa21
3 files changed
+85 -3

No files matched your search

+15 -3
View File
@@ -8,6 +8,7 @@ DIR="${ANALYTICS_DATA_DIR:-/srv/webklar-analytics}"
CONTAINER="${ANALYTICS_CONTAINER:-webklar-analytics}"
NEU="$DIR/geo.csv.new"
ZIEL="$DIR/geo.csv"
MARKER="$DIR/geo.restart-pending"
fehler() { echo "Fehler (geo-update): $*" >&2; rm -f "$NEU" "$NEU.gz"; exit 1; }
@@ -36,13 +37,24 @@ zeilen="$(wc -l < "$NEU" | tr -d ' ')"
[ "$zeilen" -gt 100000 ] || fehler "Neue Datei hat nur $zeilen Zeilen (erwartet > 100000). Bestehende geo.csv bleibt unverändert."
grep -Eq ',"?DE"?\r?$' "$NEU" || fehler "Neue Datei enthält kein 'DE'. Bestehende geo.csv bleibt unverändert."
neustart() {
docker restart "$CONTAINER" >/dev/null || fehler "Neustart von $CONTAINER fehlgeschlagen (geo.csv ist aber aktualisiert, nächster Lauf versucht den Neustart erneut)."
rm -f "$MARKER"
echo "$CONTAINER neu gestartet."
}
if [ -f "$ZIEL" ] && cmp -s "$NEU" "$ZIEL"; then
rm -f "$NEU"
echo "geo.csv ($geladen) unverändert, kein Neustart nötig."
if [ -f "$MARKER" ]; then
echo "geo.csv ($geladen) unverändert, aber ein früherer Neustart steht aus."
neustart
else
echo "geo.csv ($geladen) unverändert, kein Neustart nötig."
fi
exit 0
fi
mv -f "$NEU" "$ZIEL"
: > "$MARKER" # bleibt liegen, bis der Neustart gelungen ist
echo "geo.csv aktualisiert ($geladen, $zeilen Zeilen)."
docker restart "$CONTAINER" >/dev/null || fehler "Neustart von $CONTAINER fehlgeschlagen (geo.csv ist aber aktualisiert)."
echo "$CONTAINER neu gestartet."
neustart
+52
View File
@@ -0,0 +1,52 @@
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { mkdtempSync, mkdirSync, writeFileSync, existsSync, readFileSync, chmodSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { spawnSync } from 'node:child_process';
const SCRIPT = new URL('../scripts/geo-update.sh', import.meta.url).pathname;
// Fremde Programme (curl, docker) sind Attrappen im PATH; docker schlaegt fehl, solange DOCKER_FAIL=1 gesetzt ist.
function setup() {
const root = mkdtempSync(join(tmpdir(), 'geoupd-'));
const bin = join(root, 'bin');
const data = join(root, 'data');
mkdirSync(bin);
mkdirSync(data);
const csv = join(root, 'src.csv');
const rows = [];
for (let i = 0; i < 100100; i++) rows.push(`1.${i % 250}.${Math.floor(i / 250) % 250}.0,1.${i % 250}.${Math.floor(i / 250) % 250}.255,AU`);
rows.push('5.9.0.0,5.9.255.255,DE');
writeFileSync(csv, rows.join('\n') + '\n');
writeFileSync(join(bin, 'curl'), `#!/bin/sh\nwhile [ "$#" -gt 0 ]; do [ "$1" = "-o" ] && out="$2"; shift; done\ngzip -c "${csv}" > "$out"\n`);
writeFileSync(join(bin, 'docker'), `#!/bin/sh\necho "$@" >> "${root}/docker.log"\n[ "\${DOCKER_FAIL:-0}" = "1" ] && exit 1\nexit 0\n`);
chmodSync(join(bin, 'curl'), 0o755);
chmodSync(join(bin, 'docker'), 0o755);
const run = (fail) => spawnSync('sh', [SCRIPT], { env: { PATH: `${bin}:${process.env.PATH}`, ANALYTICS_DATA_DIR: data, DOCKER_FAIL: fail ? '1' : '0' }, encoding: 'utf8' });
const restarts = () => (existsSync(join(root, 'docker.log')) ? readFileSync(join(root, 'docker.log'), 'utf8').trim().split('\n').length : 0);
return { data, run, restarts, marker: join(data, 'geo.restart-pending') };
}
test('geo-update: Neustart schlägt fehl -> Marker; nächster Lauf startet trotz unveränderter Datei neu und entfernt ihn', () => {
const s = setup();
const first = s.run(true);
assert.notEqual(first.status, 0, first.stderr);
assert.ok(existsSync(join(s.data, 'geo.csv')), 'neue Datei ist schon an Ort und Stelle');
assert.ok(existsSync(s.marker), 'Marker liegt');
assert.equal(s.restarts(), 1);
const second = s.run(false);
assert.equal(second.status, 0, second.stderr);
assert.equal(s.restarts(), 2, 'Neustart nachgeholt');
assert.equal(existsSync(s.marker), false);
const third = s.run(false);
assert.equal(third.status, 0);
assert.equal(s.restarts(), 2, 'unverändert und ohne Marker: kein Neustart');
});
test('geo-update: erfolgreicher Neustart hinterlässt keinen Marker', () => {
const s = setup();
assert.equal(s.run(false).status, 0);
assert.equal(s.restarts(), 1);
assert.equal(existsSync(s.marker), false);
});