feat(auftraege): worker, Phasen und Live-Fortschritt per SSE
Aufträge laufen als pg-boss-Jobs im worker. Der Phasen-Runner der Engine kennt weder Proxmox noch Datenbank; eine Senke schreibt Phasen und Log in die DB und meldet per NOTIFY, die app streamt per SSE an Web und CLI (Last-Event-ID, Herzschlag, Polling-Fallback im Browser). VMIDs vergibt eine Advisory-Sperre je Server zusammen mit einer Reservierungstabelle; zehn parallele Reservierungen im Test bekommen zehn verschiedene IDs. Der Proxmox-Client hat einen Trockenmodus für den Dry-Run: Lesendes echt, Schreibendes nur aufgezeichnet. Live-Ansicht im Aufbau der CLI-Ausgabe. Im echten Betrieb aufgefallen: ssh2 und pg sind CommonJS und brauchen im worker Default-Importe. Closes #006 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,7 @@ model Benutzer {
|
||||
erstelltAm DateTime @default(now())
|
||||
geaendertAm DateTime @updatedAt
|
||||
protokoll Protokoll[]
|
||||
auftraege Auftrag[]
|
||||
}
|
||||
|
||||
/// Audit-Log. Nur anhängen – ein Trigger verweigert UPDATE und DELETE.
|
||||
@@ -99,6 +100,8 @@ model Server {
|
||||
geprueftAm DateTime?
|
||||
erstelltAm DateTime @default(now())
|
||||
geaendertAm DateTime @updatedAt
|
||||
auftraege Auftrag[]
|
||||
templates Template[]
|
||||
}
|
||||
|
||||
enum Herkunft {
|
||||
@@ -139,3 +142,138 @@ model Profil {
|
||||
geaendertVonId String?
|
||||
geaendertAm DateTime @updatedAt
|
||||
}
|
||||
|
||||
enum GastTyp {
|
||||
VM
|
||||
LXC
|
||||
}
|
||||
|
||||
enum AuftragsArt {
|
||||
AUSROLLEN
|
||||
TEMPLATE_BAUEN
|
||||
AUFRAEUMEN
|
||||
}
|
||||
|
||||
enum AuftragsStatus {
|
||||
WARTEND
|
||||
LAEUFT
|
||||
ERFOLGREICH
|
||||
FEHLGESCHLAGEN
|
||||
ABGEBROCHEN
|
||||
AUFGERAEUMT
|
||||
}
|
||||
|
||||
enum PhasenStatus {
|
||||
OFFEN
|
||||
LAEUFT
|
||||
ERLEDIGT
|
||||
FEHLER
|
||||
UEBERSPRUNGEN
|
||||
}
|
||||
|
||||
/// Ein Hintergrundjob: Ausrollen, Template bauen oder Aufräumen. Läuft im worker.
|
||||
model Auftrag {
|
||||
id String @id @default(cuid())
|
||||
/// Kurz und tippbar für CLI und URLs: „d-7f3k2“.
|
||||
kurzId String @unique
|
||||
art AuftragsArt
|
||||
status AuftragsStatus @default(WARTEND)
|
||||
serverId String
|
||||
server Server @relation(fields: [serverId], references: [id], onDelete: Restrict)
|
||||
knoten String?
|
||||
gastTyp GastTyp?
|
||||
vmid Int?
|
||||
name String?
|
||||
distributionId String?
|
||||
profile String[]
|
||||
/// Validierte Anfrage – Grundlage für „Wiederholen“.
|
||||
anfrage Json
|
||||
/// Plan zum Zeitpunkt des Starts (Phasen und geplante API-Aufrufe).
|
||||
plan Json?
|
||||
/// Kopfzeile wie in der CLI: „Server rz1 · Node pve01 · Debian 13 (Template 9013)“ – von der Engine gesetzt.
|
||||
kopf String?
|
||||
/// IP, SSH-Befehl, Dauer …
|
||||
ergebnis Json?
|
||||
/// Was ProxDeploy angelegt hat – Grundlage fürs Aufräumen.
|
||||
angelegt Json?
|
||||
/// { phase, ursache, hinweis }
|
||||
fehler Json?
|
||||
quelle Quelle
|
||||
erstelltVonId String
|
||||
erstelltVon Benutzer @relation(fields: [erstelltVonId], references: [id], onDelete: Restrict)
|
||||
wiederholtVonId String?
|
||||
/// Bei AUFRAEUMEN: der Auftrag, dessen Reste entfernt werden.
|
||||
bezugId String?
|
||||
abbrechen Boolean @default(false)
|
||||
erstelltAm DateTime @default(now())
|
||||
gestartetAm DateTime?
|
||||
beendetAm DateTime?
|
||||
phasen Phase[]
|
||||
log Logeintrag[]
|
||||
|
||||
@@index([serverId, erstelltAm])
|
||||
@@index([status])
|
||||
@@index([erstelltAm])
|
||||
}
|
||||
|
||||
model Phase {
|
||||
id String @id @default(cuid())
|
||||
auftragId String
|
||||
auftrag Auftrag @relation(fields: [auftragId], references: [id], onDelete: Cascade)
|
||||
reihenfolge Int
|
||||
schluessel String
|
||||
titel String
|
||||
status PhasenStatus @default(OFFEN)
|
||||
/// Der graue Detailtext hinter dem Phasennamen – in Web und CLI derselbe.
|
||||
detail String?
|
||||
ursache String?
|
||||
hinweis String?
|
||||
gestartetAm DateTime?
|
||||
beendetAm DateTime?
|
||||
|
||||
@@unique([auftragId, schluessel])
|
||||
@@index([auftragId, reihenfolge])
|
||||
}
|
||||
|
||||
model Logeintrag {
|
||||
/// Zugleich die Event-ID im SSE-Strom (Last-Event-ID).
|
||||
id BigInt @id @default(autoincrement())
|
||||
auftragId String
|
||||
auftrag Auftrag @relation(fields: [auftragId], references: [id], onDelete: Cascade)
|
||||
zeit DateTime @default(now())
|
||||
stufe String
|
||||
phase String?
|
||||
nachricht String
|
||||
daten Json?
|
||||
|
||||
@@index([auftragId, id])
|
||||
}
|
||||
|
||||
/// Vergebene VMIDs, solange ein Auftrag läuft – verhindert Doppelvergabe zwischen parallelen Aufträgen.
|
||||
model VmidReservierung {
|
||||
serverId String
|
||||
vmid Int
|
||||
auftragId String
|
||||
ablaufAm DateTime
|
||||
|
||||
@@id([serverId, vmid])
|
||||
@@index([auftragId])
|
||||
}
|
||||
|
||||
/// Von ProxDeploy gebaute Templates. Maßgeblich ist Proxmox (Tag proxdeploy-template); hier steht, woraus gebaut wurde.
|
||||
model Template {
|
||||
id String @id @default(cuid())
|
||||
serverId String
|
||||
server Server @relation(fields: [serverId], references: [id], onDelete: Cascade)
|
||||
knoten String
|
||||
vmid Int
|
||||
distributionId String
|
||||
storage String
|
||||
imageDatei String
|
||||
pruefsumme String
|
||||
gebautVonAuftragId String?
|
||||
gebautAm DateTime @default(now())
|
||||
|
||||
@@unique([serverId, vmid])
|
||||
@@index([serverId, distributionId])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user