2026-04-08 14:18:07 +02:00
# Workflow: Automatischer Dateieingang — SFTP → OCI Object Storage → DB
2026-04-08 08:37:58 +02:00
2026-04-08 14:18:07 +02:00
**Stand:** 2026-04-08
2026-04-08 08:37:58 +02:00
---
## Beteiligte Systeme
| System | Rolle |
|---|---|
| **SFTP-Server ** | Quelle — externer Lieferant legt ZIP-Dateien ab |
2026-04-08 14:18:07 +02:00
| **Dateieingang Service ** | Middleware (Quarkus) — holt ZIP, entpackt, lädt Dateien + Marker in OCI hoch |
2026-04-08 08:37:58 +02:00
| **OCI Object Storage ** | Zwischenspeicher — Eingangsordner, Zielordner nach Verarbeitung |
| **Oracle DB / APEX ** | Verarbeitung — liest Dateien aus OCI, importiert Daten |
2026-04-21 14:51:50 +02:00
Details zum Dateieingang Service: `quarkus-automaton/docs/Architecture.md`
2026-04-08 14:18:07 +02:00
Details zur DB-Verarbeitung: `database/docs/plan_pck_net_storage.md`
2026-04-08 08:37:58 +02:00
---
## Ablauf
```
┌─────────────────────────────────────────────────────────────────┐
│ APEX Automation (stündlich) │
2026-04-21 14:51:50 +02:00
│ → pck_auto_import.p_run_ba_korrespondenz_dateieingang_automation │
2026-04-08 08:37:58 +02:00
│ │
2026-04-21 14:51:50 +02:00
│ 1. p_process_incoming_ba_data aufrufen │
│ → OCI-Batches mit Marker verarbeiten (Fallback: ORDS-Aufruf │
│ im letzten Quarkus-Lauf fehlgeschlagen) │
2026-04-08 08:37:58 +02:00
│ │
2026-04-08 14:18:07 +02:00
│ 2. Dateieingang Service aufrufen (fire & forget) │
2026-04-21 15:13:57 +02:00
│ HTTP POST /api/process-incoming-ba-korrespondenz |
| (Header: X-Api-Key) │
2026-04-08 08:37:58 +02:00
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
2026-04-08 14:18:07 +02:00
│ Dateieingang Service (Quarkus, läuft im Hintergrund) │
2026-04-08 08:37:58 +02:00
│ │
2026-04-08 14:18:07 +02:00
│ 3a. Neue *.zip-Dateien vom SFTP-Server auflisten │
│ 3b. ZIP herunterladen und entpacken │
2026-04-08 08:37:58 +02:00
│ 3c. Alle Dateien in OCI eingang/<zip-name>/ hochladen │
│ (Unterordner aus der ZIP werden beibehalten) │
2026-04-08 14:18:07 +02:00
│ → Fehler stoppt Verarbeitung dieser ZIP │
2026-05-04 10:18:36 +02:00
│ 3d. ZIP auf SFTP löschen │
2026-04-22 14:04:46 +02:00
│ → bei ungültiger ZIP: .error (manuelle Prüfung nötig) │
2026-05-04 10:18:36 +02:00
│ → bei Infrastrukturfehlern: kein Löschen, Retry │
2026-04-22 14:04:46 +02:00
│ 3e. Marker eingang/<zip-name>/_READY_FOR_DB_PROCESSING_ │
2026-05-04 10:18:36 +02:00
│ hochladen — ERST NACH dem SFTP-Delete (siehe unten) │
│ 3f. Lokale Arbeitsdateien löschen │
│ │
│ Nach allen ZIPs (einmalig): │
│ 3g. ORDS-Endpunkt aufrufen │
│ (pck_auto_import.p_process_incoming_ba_data) │
2026-04-08 08:37:58 +02:00
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
2026-04-21 14:51:50 +02:00
│ Oracle DB (via ORDS-Endpunkt) │
2026-04-08 08:37:58 +02:00
│ │
│ 4. Unterordner in eingang/ auflisten │
│ 5. Für jeden Unterordner mit Marker: │
│ Für jede Datei (außer Marker) einzeln: │
│ a. Daten importieren (noch kein Commit) │
│ → log_object_ref = eingang/<zip-name>/datei.csv │
│ b. Datei in Zielordner verschieben │
│ c. Commit │
│ d. Fehler → Rollback, ERROR in lg_app_log, nächste Datei │
│ 6. Keine Dateien mehr im Unterordner (außer Marker)? │
│ → Marker löschen (Batch abgeschlossen) │
└─────────────────────────────────────────────────────────────────┘
```
---
## OCI Ordnerstruktur
```
bucket/
eingang/
export_2026-04-07/ ← Unterordner = ZIP-Name
datei1.csv
datei2.csv
unterordner/
datei3.csv
_READY_FOR_DB_PROCESSING_ ← Marker: Batch vollständig
<zielordner>/
export_2026-04-07/ ← gleiche Struktur nach Verarbeitung
datei1.csv
...
```
Der Marker bleibt solange erhalten bis **alle ** Dateien des Unterordners
2026-04-21 14:51:50 +02:00
verarbeitet wurden. Fehlgeschlagene Dateien bleiben im Ordner.
Wenn ein Import-Lauf alle Dateien im Ordner einmal versucht hat zu importieren, und min. eine Datei übrig geblieben ist, für die der automatische Import also nicht funktioniert hat, dann wird für jede dieser Dateien eine Wiedervorlage für die Sachbearbeiter erstellt und eine Marker Datei für die Sachbearbeiter wird im Ordner abgelegt.
Daran können die Sachbearbeiter erkennen, dass der Ordner nicht mehr automatisch importiert wird, sondern sie manuell tätig werden müssen.
2026-04-08 08:37:58 +02:00
---
## Fehlerfall-Verhalten
2026-04-22 14:04:46 +02:00
**Service: ZIP ist beschädigt oder ungültig**
- SFTP: ZIP → `.error` (manuelle Prüfung nötig)
- OCI: kein Upload, kein Marker
- DB: wird nicht aufgerufen
2026-04-08 08:37:58 +02:00
2026-04-22 14:04:46 +02:00
**Service: SFTP-Download fehlgeschlagen**
- SFTP: ZIP bleibt unverändert, wird beim nächsten Stundenlauf erneut versucht
- OCI: kein Upload, kein Marker
- DB: wird nicht aufgerufen
**Service: OCI-Upload (Dateien) fehlgeschlagen**
- SFTP: ZIP bleibt unverändert, wird beim nächsten Stundenlauf erneut versucht
- OCI: teilweise hochgeladene Dateien bleiben liegen (kein Marker → DB ignoriert den Ordner); beim Retry werden sie überschrieben (OCI PUT ist idempotent)
- DB: wird nicht aufgerufen
2026-05-04 10:18:36 +02:00
**Service: SFTP-Delete fehlgeschlagen**
2026-04-22 14:04:46 +02:00
- SFTP: ZIP bleibt unverändert, wird beim nächsten Stundenlauf erneut versucht
2026-05-04 10:18:36 +02:00
- OCI: Dateien hochgeladen, noch kein Marker (Marker kommt erst nach dem Delete)
- DB: wird nicht aufgerufen
2026-04-22 14:04:46 +02:00
- beim nächsten Stundenlauf werden die Dateien aber nicht importiert, da APEX Automation ohne Marker nichts findet
2026-05-04 10:18:36 +02:00
- d.h. erst nachdem die ZIP Datei erneut abgearbeitet und komplett in OCI hochgeladen wurde (diesmal mit erfolgreichem Delete auf SFTP & Marker in OCI) werden die Dateien abgearbeitet
2026-04-22 14:04:46 +02:00
**Service: OCI-Marker-Upload fehlgeschlagen**
2026-05-04 10:18:36 +02:00
- SFTP: ZIP ist bereits gelöscht — Quarkus greift sie nie wieder auf
2026-04-22 14:04:46 +02:00
- OCI: Dateien vollständig hochgeladen, Marker fehlt → DB-Verarbeitung wird nicht ausgelöst
- DB wird die Dateien wegen dem fehlendem Marker nie automatisiert abarbeiten, aber man sieht das recht einfach über den OCI Dateibrowser in Apex
- DB: wird nicht aufgerufen
- **Manueller Fix:** Marker-Datei `eingang/<zip-name>/_READY_FOR_DB_PROCESSING_` in OCI von Hand anlegen (leere Datei) — APEX Automation verarbeitet den Batch dann beim nächsten Stundenlauf
**Service: ORDS-Aufruf fehlgeschlagen**
2026-05-04 10:18:36 +02:00
- SFTP: ZIP ist bereits gelöscht — Quarkus greift sie nie wieder auf
2026-04-22 14:04:46 +02:00
- OCI: Dateien + Marker vollständig hochgeladen
2026-05-04 10:18:36 +02:00
- DB: APEX Automation findet den Marker beim nächsten Stundenlauf und verarbeitet ihn (Schritt 1) — kein Doppelimport, da Quarkus die gelöschte ZIP nicht erneut verarbeitet
2026-04-08 08:37:58 +02:00
**DB: Verarbeitung einer einzelnen Datei schlägt fehl**
2026-04-22 14:04:46 +02:00
- OCI `eingang/` : Datei bleibt in `eingang/<zip-name>/` (Rollback)
- OCI `zielordner/` : keine Änderung
- DB: Rollback, ERROR in `lg_app_log` mit `log_object_ref = eingang/<zip-name>/datei.csv` , nächste Dateien im Batch werden weiterverarbeitet
2026-04-21 14:51:50 +02:00
**DB: Batch-Abschluss (nach dem Datei-Loop)**
2026-04-22 14:04:46 +02:00
- Alle Dateien erfolgreich: `eingang/<zip-name>/` ist leer, Marker wird gelöscht
- Noch Dateien übrig: Marker wird gelöscht, SB-Marker (`_BITTE_PRÜFEN_` ) wird angelegt → Sachbearbeiter müssen manuell eingreifen
2026-04-08 08:37:58 +02:00
**DB: p_move_object schlägt nach erfolgreichem Import fehl**
2026-04-22 14:04:46 +02:00
- OCI `eingang/` : Datei bleibt in `eingang/<zip-name>/` (Rollback des gesamten Imports)
- OCI `zielordner/` : keine Änderung
- DB: Marker wird am Ende des Loops trotzdem gelöscht; falls noch Dateien übrig → SB-Marker
---
2026-05-04 10:18:36 +02:00
## Design-Entscheidung: Marker wird nach dem SFTP-Delete gesetzt
2026-04-22 14:04:46 +02:00
2026-05-04 10:18:36 +02:00
Der OCI-Marker `_READY_FOR_DB_PROCESSING_` wird bewusst **nach ** dem SFTP-Delete
2026-04-22 14:04:46 +02:00
hochgeladen — nicht davor. Das erzeugt eine harte Invariante:
2026-05-04 10:18:36 +02:00
> **Marker in OCI vorhanden ↔ ZIP auf SFTP bereits gelöscht**
2026-04-22 14:04:46 +02:00
### Warum ist das wichtig?
APEX Automation ruft `p_process_incoming_ba_data` in jedem Stundenlauf einmal direkt auf
2026-05-04 10:18:36 +02:00
(Schritt 1, Fallback), und Quarkus ruft dieselbe Funktion via ORDS auf (Schritt 3g, schneller Pfad).
2026-04-22 14:04:46 +02:00
Ohne die Invariante könnte folgender Race entstehen:
2026-05-04 10:18:36 +02:00
1. Quarkus lädt Dateien + Marker hoch, schlägt dann beim SFTP-Delete fehl
2026-04-22 14:04:46 +02:00
2. APEX Schritt 1 findet den Marker → importiert Daten
3. Quarkus wiederholt den Lauf, ruft ORDS auf → zweiter Import derselben Daten
Mit der Invariante ist dieser Fall ausgeschlossen: APEX Schritt 1 findet nur dann einen Marker,
2026-05-04 10:18:36 +02:00
wenn die ZIP auf dem SFTP bereits gelöscht ist. Ist sie das, greift Quarkus sie im Retry
2026-04-22 14:04:46 +02:00
nicht mehr an — `listZipFiles()` gibt nur `.zip` -Dateien zurück.
### Einzig verbleibender manueller Fehlerfall
2026-05-04 10:18:36 +02:00
Schlägt der Marker-Upload fehl (nach erfolgreichem SFTP-Delete), ist der Zustand eindeutig
erkennbar: ZIP auf SFTP gelöscht, Dateien in OCI ohne Marker. Manueller Fix: Marker-Datei
2026-04-22 14:04:46 +02:00
in OCI von Hand anlegen. Dieser Fall erfordert keine DB-seitige Idempotenz, da Quarkus
2026-05-04 10:18:36 +02:00
die gelöschte ZIP nicht erneut verarbeitet und ORDS nicht aufruft.
2026-04-21 14:51:50 +02:00
---
## Warum ruft die APEX Automation p_process_incoming_ba_data auf, obwohl Quarkus das auch tut?
`p_process_incoming_ba_data` wird in jedem Stundenlauf **zweimal ** aufgerufen:
1. Direkt durch `p_run_ba_korrespondenz_dateieingang_automation` (Schritt 1)
2. Indirekt — von Quarkus via ORDS, nachdem der Upload abgeschlossen ist (Schritt 3f)
Der direkte Aufruf in Schritt 1 ist ein **Fallback ** : Wenn der ORDS-Aufruf in einem vorherigen Quarkus-Lauf fehlgeschlagen ist, liegt der Marker bereits in OCI, aber `p_process_incoming_ba_data` wurde nie aufgerufen. Ohne Schritt 1 würde dieser Batch erst beim nächsten Quarkus-Lauf verarbeitet — und nur dann, wenn Quarkus beim nächsten Mal auch wieder erfolgreich bis zum ORDS-Aufruf kommt. Mit Schritt 1 ist die DB-Verarbeitung unabhängig davon, ob Quarkus den ORDS-Aufruf erfolgreich abgeschlossen hat.
Das heißt: Quarkus ist der **schnelle Pfad ** (Upload + sofortiger DB-Trigger), die APEX Automation ist die **Absicherung ** (findet Marker, die noch nicht verarbeitet wurden).
2026-04-08 08:37:58 +02:00
---
## Warum kein Fehlerordner, keine Status-Tabelle?
Der Zustand steckt im Dateisystem:
- Unterordner mit Marker = Batch bereit oder teilweise verarbeitet
2026-04-08 14:18:07 +02:00
- Unterordner ohne Marker = unvollständiger Upload, wird ignoriert
2026-04-08 08:37:58 +02:00
- Datei im Zielordner = erfolgreich verarbeitet
- Datei noch in `eingang/<zip-name>/` = noch ausstehend oder fehlgeschlagen
2026-04-08 14:18:07 +02:00
- ZIP auf SFTP mit `.error` = persistenter Fehler, manuelle Prüfung nötig
2026-04-08 08:37:58 +02:00
Fehlerdetails stehen in `lg_app_log` . Über `log_object_ref` ist jede Datei
eindeutig einer ZIP zugeordnet. Kein Verhalten wird aus dem Log abgeleitet —
es dient ausschließlich dem Audit-Trail.
---
## Zeitplan
2026-04-08 14:18:07 +02:00
APEX Automation läuft **1x pro Stunde ** . Der Dateieingang Service wird dabei per
HTTP POST aufgerufen und läuft zeitlich versetzt nach dem Automation-Start.