Import nicht an der JSON-Ablage scheitern lassen
Im Container lief der Import bis zum Ende der Auswertung und brach dann mit EACCES beim Schreiben der ersten JSON-Datei ab. Weil die Ablage vor dem Datenbankschreiben stand, wurde keine einzige Erklärung importiert. Reihenfolge umgedreht: Erst die Datenbank, danach die JSON-Dateien. Ein Fehler dabei wird einmal gemeldet und beendet nur die Ablage, nicht den Lauf. Neu ist --no-json, das sie ganz abschaltet. Getestet: Normalfall schreibt 120 Dateien, simulierter Schreibfehler meldet ihn und importiert vollständig weiter. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
d76ff12fbe
commit
ae752322f0
@ -153,7 +153,7 @@ Massenimporte gibt es zwei Wege:
|
|||||||
|
|
||||||
| Befehl | Zweck |
|
| Befehl | Zweck |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `npm run import-csv` | **Führender Weg:** DSE-Gesamtliste einlesen (`--dry-run`, `--prune`) |
|
| `npm run import-csv` | **Führender Weg:** DSE-Gesamtliste einlesen (`--dry-run`, `--prune`, `--no-json`) |
|
||||||
| `npm run check-completeness` | Berichtet fehlende Pflichtangaben (`--list`) |
|
| `npm run check-completeness` | Berichtet fehlende Pflichtangaben (`--list`) |
|
||||||
| `npm run compare-csv-pdf` | Gesamtliste gegen die alten Merkblatt-PDFs abgleichen (`--detail`) |
|
| `npm run compare-csv-pdf` | Gesamtliste gegen die alten Merkblatt-PDFs abgleichen (`--detail`) |
|
||||||
| `npm run import-policy -- data/policies/<datei>.json` | Einzelne Erklärung aus JSON importieren (`--update` überschreibt) |
|
| `npm run import-policy -- data/policies/<datei>.json` | Einzelne Erklärung aus JSON importieren (`--update` überschreibt) |
|
||||||
@ -184,6 +184,12 @@ Zwei Angaben stehen nicht in der Liste und werden ergänzt:
|
|||||||
Werte wie „entfällt“ in der Spalte Datenquelle gelten als leer – sonst würde die
|
Werte wie „entfällt“ in der Spalte Datenquelle gelten als leer – sonst würde die
|
||||||
Art.-14-Pflicht zu den Datenkategorien fälschlich ausgelöst.
|
Art.-14-Pflicht zu den Datenkategorien fälschlich ausgelöst.
|
||||||
|
|
||||||
|
Die Datenbank wird zuerst geschrieben, die JSON-Dateien danach. Sie dienen nur
|
||||||
|
der Nachvollziehbarkeit im Repository – schlägt das Schreiben fehl, etwa weil
|
||||||
|
das Verzeichnis im Container nicht beschreibbar ist, meldet der Lauf das und
|
||||||
|
der Import bleibt trotzdem vollständig. Mit `--no-json` lässt sich die Ablage
|
||||||
|
ganz abschalten; im Container ist das der Normalfall.
|
||||||
|
|
||||||
Der PDF-Import (`scripts/lib/pdf-policy.js`) bleibt für die alten Merkblätter
|
Der PDF-Import (`scripts/lib/pdf-policy.js`) bleibt für die alten Merkblätter
|
||||||
erhalten und dient als Gegenprobe.
|
erhalten und dient als Gegenprobe.
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,9 @@
|
|||||||
* Importiert die DSE-Gesamtliste des Amtes Leezen (Excel-Export, CSV).
|
* Importiert die DSE-Gesamtliste des Amtes Leezen (Excel-Export, CSV).
|
||||||
*
|
*
|
||||||
* node scripts/import-csv.js --dry-run nur prüfen und berichten
|
* node scripts/import-csv.js --dry-run nur prüfen und berichten
|
||||||
* node scripts/import-csv.js JSON schreiben und importieren
|
* node scripts/import-csv.js importieren und JSON ablegen
|
||||||
* node scripts/import-csv.js --prune zusätzlich verwaiste Datensätze löschen
|
* node scripts/import-csv.js --prune zusätzlich verwaiste Datensätze löschen
|
||||||
|
* node scripts/import-csv.js --no-json nur in die Datenbank (z. B. im Container)
|
||||||
*
|
*
|
||||||
* Die Liste ist führend für die Angaben je Verarbeitungstätigkeit. Die für alle
|
* Die Liste ist führend für die Angaben je Verarbeitungstätigkeit. Die für alle
|
||||||
* Erklärungen gleichen Bausteine kommen aus den zentralen Standardtexten und
|
* Erklärungen gleichen Bausteine kommen aus den zentralen Standardtexten und
|
||||||
@ -114,6 +115,7 @@ function addressBlock(value) {
|
|||||||
async function main() {
|
async function main() {
|
||||||
const dryRun = process.argv.includes("--dry-run")
|
const dryRun = process.argv.includes("--dry-run")
|
||||||
const prune = process.argv.includes("--prune")
|
const prune = process.argv.includes("--prune")
|
||||||
|
const ohneJson = process.argv.includes("--no-json")
|
||||||
|
|
||||||
if (!fs.existsSync(CSV)) {
|
if (!fs.existsSync(CSV)) {
|
||||||
console.error(`Liste nicht gefunden: ${CSV}`)
|
console.error(`Liste nicht gefunden: ${CSV}`)
|
||||||
@ -264,17 +266,26 @@ async function main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.mkdirSync(JSON_DIR, { recursive: true })
|
// Die JSON-Ablage ist nur zur Nachvollziehbarkeit im Repository gedacht.
|
||||||
|
// Im Container liegt sie im Volume und ist je nach Einhängung nicht
|
||||||
|
// beschreibbar – das darf den eigentlichen Import nicht verhindern.
|
||||||
|
let jsonZiel = ohneJson ? null : JSON_DIR
|
||||||
|
if (jsonZiel) {
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(jsonZiel, { recursive: true })
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`Hinweis: ${jsonZiel} nicht anlegbar (${error.code}) – JSON-Ablage wird übersprungen.`)
|
||||||
|
jsonZiel = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let neu = 0
|
let neu = 0
|
||||||
let aktualisiert = 0
|
let aktualisiert = 0
|
||||||
|
let geschrieben = 0
|
||||||
|
let jsonFehler = null
|
||||||
|
|
||||||
for (const { nummer, daten, overrides, bestehend } of aufbereitet) {
|
for (const { nummer, daten, overrides, bestehend } of aufbereitet) {
|
||||||
fs.writeFileSync(
|
// Datenbank zuerst: Sie ist der Zweck des Laufs.
|
||||||
path.join(JSON_DIR, `${daten.slug}.json`),
|
|
||||||
JSON.stringify({ _quelle: `DSE_Gesamtliste_Amt_Leezen.CSV · ${nummer}`, _abweichungen: overrides, ...daten }, null, 2),
|
|
||||||
"utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
if (bestehend) {
|
if (bestehend) {
|
||||||
await prisma.privacyPolicy.update({ where: { id: bestehend.id }, data: daten })
|
await prisma.privacyPolicy.update({ where: { id: bestehend.id }, data: daten })
|
||||||
aktualisiert++
|
aktualisiert++
|
||||||
@ -282,6 +293,21 @@ async function main() {
|
|||||||
await prisma.privacyPolicy.create({ data: daten })
|
await prisma.privacyPolicy.create({ data: daten })
|
||||||
neu++
|
neu++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!jsonZiel) continue
|
||||||
|
|
||||||
|
try {
|
||||||
|
fs.writeFileSync(
|
||||||
|
path.join(jsonZiel, `${daten.slug}.json`),
|
||||||
|
JSON.stringify({ _quelle: `DSE_Gesamtliste_Amt_Leezen.CSV · ${nummer}`, _abweichungen: overrides, ...daten }, null, 2),
|
||||||
|
"utf8"
|
||||||
|
)
|
||||||
|
geschrieben++
|
||||||
|
} catch (error) {
|
||||||
|
// Einmal melden, dann nicht weiter versuchen
|
||||||
|
jsonFehler = error
|
||||||
|
jsonZiel = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Neu angelegt: ${neu}`)
|
console.log(`Neu angelegt: ${neu}`)
|
||||||
@ -296,7 +322,18 @@ async function main() {
|
|||||||
console.log(`Unberührt: ${verwaist.length} (mit --prune entfernen)`)
|
console.log(`Unberührt: ${verwaist.length} (mit --prune entfernen)`)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`JSON-Dateien: data/policies/`)
|
if (ohneJson) {
|
||||||
|
console.log(`JSON-Ablage: übersprungen (--no-json)`)
|
||||||
|
} else if (jsonFehler) {
|
||||||
|
console.log(`JSON-Dateien: ${geschrieben} von ${aufbereitet.length} geschrieben`)
|
||||||
|
console.warn("")
|
||||||
|
console.warn(`WARNUNG: JSON-Ablage abgebrochen – ${jsonFehler.code} bei ${jsonFehler.path}`)
|
||||||
|
console.warn("Der Import in die Datenbank ist davon unberührt und vollständig.")
|
||||||
|
console.warn("Die JSON-Dateien dienen nur der Nachvollziehbarkeit im Repository;")
|
||||||
|
console.warn("im Container lassen sie sich mit --no-json ganz abschalten.")
|
||||||
|
} else {
|
||||||
|
console.log(`JSON-Dateien: ${geschrieben} in data/policies/`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user