Phase4
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
-- Phase 4: Worlds & Backups
|
||||
|
||||
-- AlterEnum
|
||||
ALTER TYPE "GameServerStatus" ADD VALUE 'BACKING_UP';
|
||||
ALTER TYPE "GameServerStatus" ADD VALUE 'RESTORING';
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "BackupStatus" AS ENUM ('PENDING', 'RUNNING', 'AVAILABLE', 'FAILED', 'DELETED');
|
||||
CREATE TYPE "BackupType" AS ENUM ('MANUAL', 'SCHEDULED', 'PRE_RESTORE', 'PRE_WORLD_REPLACE');
|
||||
CREATE TYPE "BackupRestoreStatus" AS ENUM ('PENDING', 'RUNNING', 'COMPLETED', 'FAILED');
|
||||
CREATE TYPE "WorldUploadStatus" AS ENUM ('PENDING', 'UPLOADING', 'VALIDATING', 'READY', 'COMPLETED', 'FAILED');
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "game_servers" ADD COLUMN "activeWorldName" TEXT NOT NULL DEFAULT 'world';
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "server_backups" (
|
||||
"id" TEXT NOT NULL,
|
||||
"serverId" TEXT NOT NULL,
|
||||
"type" "BackupType" NOT NULL DEFAULT 'MANUAL',
|
||||
"status" "BackupStatus" NOT NULL DEFAULT 'PENDING',
|
||||
"s3Key" TEXT,
|
||||
"sizeBytes" BIGINT,
|
||||
"sha256" TEXT,
|
||||
"label" TEXT,
|
||||
"failureReason" TEXT,
|
||||
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"completedAt" TIMESTAMPTZ(3),
|
||||
"expiresAt" TIMESTAMPTZ(3),
|
||||
|
||||
CONSTRAINT "server_backups_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "backup_restores" (
|
||||
"id" TEXT NOT NULL,
|
||||
"serverId" TEXT NOT NULL,
|
||||
"backupId" TEXT NOT NULL,
|
||||
"safetyBackupId" TEXT,
|
||||
"status" "BackupRestoreStatus" NOT NULL DEFAULT 'PENDING',
|
||||
"failureReason" TEXT,
|
||||
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"completedAt" TIMESTAMPTZ(3),
|
||||
|
||||
CONSTRAINT "backup_restores_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "backup_schedules" (
|
||||
"id" TEXT NOT NULL,
|
||||
"serverId" TEXT NOT NULL,
|
||||
"enabled" BOOLEAN NOT NULL DEFAULT true,
|
||||
"intervalHours" INTEGER NOT NULL DEFAULT 24,
|
||||
"retentionCount" INTEGER NOT NULL DEFAULT 5,
|
||||
"nextRunAt" TIMESTAMPTZ(3),
|
||||
"lastRunAt" TIMESTAMPTZ(3),
|
||||
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMPTZ(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "backup_schedules_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "world_uploads" (
|
||||
"id" TEXT NOT NULL,
|
||||
"serverId" TEXT NOT NULL,
|
||||
"status" "WorldUploadStatus" NOT NULL DEFAULT 'PENDING',
|
||||
"s3Key" TEXT NOT NULL,
|
||||
"worldName" TEXT NOT NULL DEFAULT 'world',
|
||||
"sha256" TEXT,
|
||||
"sizeBytes" BIGINT,
|
||||
"failureReason" TEXT,
|
||||
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"completedAt" TIMESTAMPTZ(3),
|
||||
|
||||
CONSTRAINT "world_uploads_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "server_backups_serverId_idx" ON "server_backups"("serverId");
|
||||
CREATE INDEX "server_backups_status_idx" ON "server_backups"("status");
|
||||
CREATE INDEX "server_backups_createdAt_idx" ON "server_backups"("createdAt");
|
||||
|
||||
CREATE INDEX "backup_restores_serverId_idx" ON "backup_restores"("serverId");
|
||||
CREATE INDEX "backup_restores_backupId_idx" ON "backup_restores"("backupId");
|
||||
CREATE INDEX "backup_restores_status_idx" ON "backup_restores"("status");
|
||||
|
||||
CREATE UNIQUE INDEX "backup_schedules_serverId_key" ON "backup_schedules"("serverId");
|
||||
|
||||
CREATE INDEX "world_uploads_serverId_idx" ON "world_uploads"("serverId");
|
||||
CREATE INDEX "world_uploads_status_idx" ON "world_uploads"("status");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "server_backups" ADD CONSTRAINT "server_backups_serverId_fkey" FOREIGN KEY ("serverId") REFERENCES "game_servers"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "backup_restores" ADD CONSTRAINT "backup_restores_serverId_fkey" FOREIGN KEY ("serverId") REFERENCES "game_servers"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
ALTER TABLE "backup_restores" ADD CONSTRAINT "backup_restores_backupId_fkey" FOREIGN KEY ("backupId") REFERENCES "server_backups"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE "backup_restores" ADD CONSTRAINT "backup_restores_safetyBackupId_fkey" FOREIGN KEY ("safetyBackupId") REFERENCES "server_backups"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "backup_schedules" ADD CONSTRAINT "backup_schedules_serverId_fkey" FOREIGN KEY ("serverId") REFERENCES "game_servers"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "world_uploads" ADD CONSTRAINT "world_uploads_serverId_fkey" FOREIGN KEY ("serverId") REFERENCES "game_servers"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -37,6 +37,8 @@ enum GameServerStatus {
|
||||
STARTING
|
||||
RUNNING
|
||||
STOPPING
|
||||
BACKING_UP
|
||||
RESTORING
|
||||
ERROR
|
||||
DELETING
|
||||
DELETED
|
||||
@@ -63,6 +65,37 @@ enum JobStatus {
|
||||
CANCELLED
|
||||
}
|
||||
|
||||
enum BackupStatus {
|
||||
PENDING
|
||||
RUNNING
|
||||
AVAILABLE
|
||||
FAILED
|
||||
DELETED
|
||||
}
|
||||
|
||||
enum BackupType {
|
||||
MANUAL
|
||||
SCHEDULED
|
||||
PRE_RESTORE
|
||||
PRE_WORLD_REPLACE
|
||||
}
|
||||
|
||||
enum BackupRestoreStatus {
|
||||
PENDING
|
||||
RUNNING
|
||||
COMPLETED
|
||||
FAILED
|
||||
}
|
||||
|
||||
enum WorldUploadStatus {
|
||||
PENDING
|
||||
UPLOADING
|
||||
VALIDATING
|
||||
READY
|
||||
COMPLETED
|
||||
FAILED
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(uuid())
|
||||
email String @unique
|
||||
@@ -219,6 +252,7 @@ model GameServer {
|
||||
containerId String?
|
||||
dataPath String?
|
||||
ramMb Int @default(1024)
|
||||
activeWorldName String @default("world")
|
||||
createdAt DateTime @default(now()) @db.Timestamptz(3)
|
||||
updatedAt DateTime @updatedAt @db.Timestamptz(3)
|
||||
|
||||
@@ -227,6 +261,10 @@ model GameServer {
|
||||
node GameNode? @relation(fields: [nodeId], references: [id])
|
||||
stateTransitions GameServerStateTransition[]
|
||||
allocation GameServerAllocation?
|
||||
backups ServerBackup[]
|
||||
backupRestores BackupRestore[]
|
||||
backupSchedule BackupSchedule?
|
||||
worldUploads WorldUpload[]
|
||||
|
||||
@@index([userId])
|
||||
@@index([nodeId])
|
||||
@@ -385,3 +423,82 @@ model JobRecord {
|
||||
@@index([createdAt])
|
||||
@@map("job_records")
|
||||
}
|
||||
|
||||
model ServerBackup {
|
||||
id String @id @default(uuid())
|
||||
serverId String
|
||||
type BackupType @default(MANUAL)
|
||||
status BackupStatus @default(PENDING)
|
||||
s3Key String?
|
||||
sizeBytes BigInt?
|
||||
sha256 String?
|
||||
label String?
|
||||
failureReason String?
|
||||
createdAt DateTime @default(now()) @db.Timestamptz(3)
|
||||
completedAt DateTime? @db.Timestamptz(3)
|
||||
expiresAt DateTime? @db.Timestamptz(3)
|
||||
|
||||
server GameServer @relation(fields: [serverId], references: [id], onDelete: Cascade)
|
||||
restores BackupRestore[] @relation("RestoredFromBackup")
|
||||
safetyForRestores BackupRestore[] @relation("SafetyBackup")
|
||||
|
||||
@@index([serverId])
|
||||
@@index([status])
|
||||
@@index([createdAt])
|
||||
@@map("server_backups")
|
||||
}
|
||||
|
||||
model BackupRestore {
|
||||
id String @id @default(uuid())
|
||||
serverId String
|
||||
backupId String
|
||||
safetyBackupId String?
|
||||
status BackupRestoreStatus @default(PENDING)
|
||||
failureReason String?
|
||||
createdAt DateTime @default(now()) @db.Timestamptz(3)
|
||||
completedAt DateTime? @db.Timestamptz(3)
|
||||
|
||||
server GameServer @relation(fields: [serverId], references: [id], onDelete: Cascade)
|
||||
backup ServerBackup @relation("RestoredFromBackup", fields: [backupId], references: [id])
|
||||
safetyBackup ServerBackup? @relation("SafetyBackup", fields: [safetyBackupId], references: [id])
|
||||
|
||||
@@index([serverId])
|
||||
@@index([backupId])
|
||||
@@index([status])
|
||||
@@map("backup_restores")
|
||||
}
|
||||
|
||||
model BackupSchedule {
|
||||
id String @id @default(uuid())
|
||||
serverId String @unique
|
||||
enabled Boolean @default(true)
|
||||
intervalHours Int @default(24)
|
||||
retentionCount Int @default(5)
|
||||
nextRunAt DateTime? @db.Timestamptz(3)
|
||||
lastRunAt DateTime? @db.Timestamptz(3)
|
||||
createdAt DateTime @default(now()) @db.Timestamptz(3)
|
||||
updatedAt DateTime @updatedAt @db.Timestamptz(3)
|
||||
|
||||
server GameServer @relation(fields: [serverId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("backup_schedules")
|
||||
}
|
||||
|
||||
model WorldUpload {
|
||||
id String @id @default(uuid())
|
||||
serverId String
|
||||
status WorldUploadStatus @default(PENDING)
|
||||
s3Key String
|
||||
worldName String @default("world")
|
||||
sha256 String?
|
||||
sizeBytes BigInt?
|
||||
failureReason String?
|
||||
createdAt DateTime @default(now()) @db.Timestamptz(3)
|
||||
completedAt DateTime? @db.Timestamptz(3)
|
||||
|
||||
server GameServer @relation(fields: [serverId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([serverId])
|
||||
@@index([status])
|
||||
@@map("world_uploads")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user