Direkt zum Hauptinhalt

Architektur-Überblick

Diese Übersicht beschreibt dendie StandArchitektur dervon D-DOK-KomponentenDOK. Code-Stand: Version 0.0.8 (ReleaseBranch 0.0.7, in Entwicklung 0.0.8)master). Quelle: git.agrarforschung.at/ddok/ddok.

Architektur-Diagramm

flowchart LR
  subgraph Client["Browser-Client"]
    NG["Angular 21 SPA
(client/)"] PDFX["PDF-Volltext-Extraktion
im Browser (pdfparse)"] NG --- PDFX end subgraph Server["D-DOK Server (Node.js)js 22)"] API["Express 5 + InversifyAwilix (DI)
(TypeScript, server/)"] PDF["PDF-Parse Worker
(modules/pdfparse)"] end subgraph DBs[SQL["DatenbankenMySQL: eine gemeinsame Datenbank (lokal)D-DOK + D-ESS)"] MY[("MySQLddok_*-Tabellen
Projekte /Projekte, Publikationen
Metadaten"Volltext-Index (FULLTEXT)")] DESSDB[("D-ESS tbl_*-Tabellen
Kostenträger, Benutzer:innen")] end MO[("MongoDB 7.00, GridFS
PDF-Dateien +(Bucket Volltext"je Projekt)")] end subgraph DESS["D-ESS"] DESSDB[("MySQL
Kostentraeger / Benutzer:innen")] end subgraph Auth["Authentifizierung"] AD["Active Directory
 (LDAPS)"] KC["Keycloak OIDC
sso.agrarforschung.at"] end subgraph Web["BABÖffentliche BAB-Website (0.0.8)optionaler Publish)"] WEBMY[("MySQL
 WEB_DATABASE")] WEBMO[("MongoDB
 WEB_MONGO")] SITE["bab.gv.at Public-Frontend"] end NG -- "HTTPS / REST" --> API PDFX -- "pdfText im Upload" --> API API -- "Metadaten + Volltext" --> MY API -- "Lookup (gleiche Verbindung)" --> DESSDB API -- "PDF-Blob" --> MO API --. LookupOIDC -.-> DESSDBKC API -. optionalLDAPS .-> AD API -. optional .-> KC API -- "Sync (0.0.8)"Publish --> WEBMY API -- "Sync (0.0.8)"Publish --> WEBMO WEBMY --> SITE WEBMO --> SITE PDF --> MO classDef new fill:#e8f5e9,stroke:#388e3c class WEBMY,WEBMO,SITE,Web new

Komponenten im Überblick

KomponenteStackQuelle
Frontend (SPA)Angular 21 (seit 0.0.8, vorher· Angular 17)Material · Wijmo (@mescius) · Quill-EditorQuill (ngx-quill). Upgrade auf Angular 21 in 0.0.8 (zuvor Angular 20).client/
Backend-APINode.js 22 · Express 5 · InversifyAwilix / awilix-express (DI)Dependency Injection) · TypeScript · TypeORMserver/
PDF-ParserVolltext-ExtraktionWorkerLäuft fürim Volltext-ExtraktionBrowser aus(Bibliothek PDF-Dateienpdfparse, Git-Submodul modules/pdfparse); der extrahierte Text wird beim Upload an den Server mitgesendet – kein serverseitiger Parser-Worker.client/ (file-upload), modules/pdfparse/
Relationale DBMySQL 3306(Port 3306) · ddok_*-Tabellen: Projekte, Publikationen, Stammdaten + Volltext-Index (MySQL-FULLTEXT auf file_text) · TypeORM mit synchronize:trueGemeinsame MySQL-DB mit D-DOK eigene DBESS
Dokumenten-DBMongoDB 7.0 (Port 27017) · PDF-BinariesDateien +als GridFS, ein Bucket pro Projekt (PROJECT_<id>). Kein Volltext-Index – der liegt in MySQL.D-DOKLokale eigene DBMongoDB
D-ESS-AnbindungRead-only Lese-Zugriff auf die D-ESS-DatenbankTabellen für(tbl_*) Kostentraeger/über dieselbe MySQL-Verbindung: Kostenträger/KS/KT und+ Benutzer:innen-Stammdaten/BerechtigungsdatenDESS_LINK_ENABLED=DESS_LINK_ENABLED (Default true)
AuthentifizierungLokal · Active Directory (LDAPS)LDAPS, passport-ldapauth) · Keycloak OIDC (openid-client, Realm ddok auf sso.agrarforschung.at)KonfigurationAD_ENABLED / OIDC_ENABLED in server/config/config.js
Website-SyncPublish (NEU 0.0.8)optional)ZusaetzlicheManueller MySQL-Publish-Vorgang: undausgewählte MongoDB-VerbindungProjekte/Publikationen zursamt oeffentlichenDateien BAB-Websitewerden in Exportseparate ausgewählterWebsite-Datenbanken Publikationenkopiert (eigener Publish-Worker)WEB_DATABASE_* + WEB_MONGO_DATABASE_*

Deployment

D-DOK läuft in Produktion nicht als Container. Das im Repository vorhandene Dockerfile ist ausschließlich eine reproduzierbare Build-Umgebung für die CI – die Laufzeit ist ein klassischer Plesk-/Passenger-Node.js-Prozess.

AspektDetails
Laufzeit-HostPlesk-Server mit Phusion Passenger (LXC-Container). Geteilt mit D-ESS, Datenpool und Adressdatenbank (Co-Tenancy). Node 22 via nodenv.
App-PfadeLive: /var/www/vhosts/agrarforschung.at/ddok.agrarforschung.at
Staging: /var/www/vhosts/agrarforschung.at/staging-ddok.agrarforschung.at
SSOKeycloak-Realm ddok auf sso.agrarforschung.at

Build – npm run build

Führt drei Workspace-Builds nacheinander aus (package.json):

  • build:pdfparse – baut das PDF-Volltext-Modul (modules/pdfparse/).
  • build:client – Angular-Produktions-Build (client/).
  • build:server – bündelt den TypeScript-Server via esbuild (node esbuild.mjs) und erzeugt das Laufzeit-Lockfile (npm --prefix ./dist install --package-lock-only).

Resultat ist der Ordner dist/ – das eigentliche Deployment-Artefakt.

Rolle des Dockerfile

Multi-Stage-Build: Die builder-Stage führt npm ci + npm run build aus und erzeugt dist/; die finale Stage übernimmt nur dist/, exponiert Port 3000 und definiert CMD ["npm","run","start"]. In der CI wird dieses Image jedoch nicht als Runtime ausgerollt, sondern dient als hermetische Build-Box: Nach dem Build wird ein Wegwerf-Container erzeugt und dessen /usr/src/app (= dist/) per docker cp als CI-Artefakt herauskopiert.

CI/CD – .gitlab-ci.yml

Drei Stages, ausschließlich auf Branch master:

  1. build – Docker-Image bauen (Docker-in-Docker, BuildKit-Registry-Cache), nach Harbor pushen und dist/ als Artefakt extrahieren.
  2. deploy:staging (automatisch) – bestehendes Verzeichnis nach backup/ sichern (außer backup/log/config/config.js), dist/* per scp auf den Staging-Host kopieren, .npmrc schreiben, npm ci (nodenv Node 22), touch tmp/restart.txt → Passenger-Reload.
  3. deploy:live (manueller Trigger) – identischer Ablauf auf den Live-Host.

Das Deployment ist somit ein scp-basiertes Datei-Rollout des dist/-Ordners mit anschließendem Passenger-Restart – kein docker run und kein Image-Pull auf dem Zielhost.

DatenfluesseDatenflüsse

  1. Projekt-/Publikationsanlage: Benutzer:innen erstellen Projekte und Publikationen im Angular-Frontend; Datendie Metadaten werden über die Express-API in der MySQL-DBMySQL persistiert.
  2. PDF-Upload: HochgeladeneDer DateienBrowser werdenextrahiert beim Hochladen den PDF-Volltext (Bibliothek pdfparse). Die Datei wird als GridFS-Blob in MongoDB gespeichert;abgelegt, einder PDF-Parser-Workerextrahierte extrahiertText denin Volltextder MySQL-Spalte file_text (FULLTEXT-indiziert für die Suche.Suche).
  3. D-ESS-Lookup: Kostenstellen, KostentraegerKostenträger und Benutzer:innen-Stammdaten werden zur Laufzeit aus derden D-ESS-Tabellen (tbl_*) in derselben MySQL-Datenbank gelesen.gelesen (DESS_LINK_ENABLED).
  4. Website-ExportPublish (0.0.8)optional): FreigegebeneÜber einen manuellen Publish-Vorgang werden freigegebene Projekte/Publikationen werdensamt Dateien in die separateseparaten Website-DatenbankDatenbanken synchronisiert(WEB_*) kopiert und auf der oeffentlichenöffentlichen BAB-Website angezeigt.

Letzte Aktualisierung: 2026-06-10 · Pflege: Roland Neissl · Quelle: git.agrarforschung.at/ddok/ddok