feat: 플레이 감사 월별 수집과 원자적 배치 저장 연결

This commit is contained in:
2026-09-16 02:37:38 +00:00
parent 4de3175279
commit 35155e6b59
14 changed files with 594 additions and 12 deletions
+57
View File
@@ -1080,3 +1080,60 @@ model VoteComment {
@@index([voteId, createdAt])
@@map("vote_comment")
}
// 현재 기수 플레이 감사. gameplay 엔티티 삭제 뒤에도 당시 ID/이름을 유지한다.
model PlayAuditMonth {
id String @id
serverId String @map("server_id")
year Int
month Int
kind String
tick Int?
schemaVersion Int @default(1) @map("schema_version")
settlementsComplete Boolean @map("settlements_complete")
hash String
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
nations PlayAuditNation[]
cities PlayAuditCity[]
generals PlayAuditGeneral[]
@@unique([serverId, year, month, kind])
@@map("play_audit_month")
}
model PlayAuditNation {
sampleId String @map("sample_id")
nationId Int @map("nation_id")
data Json
sample PlayAuditMonth @relation(fields: [sampleId], references: [id], onDelete: Cascade)
@@id([sampleId, nationId])
@@map("play_audit_nation")
}
model PlayAuditCity {
sampleId String @map("sample_id")
cityId Int @map("city_id")
nationId Int @map("nation_id")
data Json
sample PlayAuditMonth @relation(fields: [sampleId], references: [id], onDelete: Cascade)
@@id([sampleId, cityId])
@@index([sampleId, nationId, cityId])
@@map("play_audit_city")
}
model PlayAuditGeneral {
sampleId String @map("sample_id")
generalId Int @map("general_id")
nationId Int @map("nation_id")
cityId Int @map("city_id")
npcState Int @map("npc_state")
data Json
sample PlayAuditMonth @relation(fields: [sampleId], references: [id], onDelete: Cascade)
@@id([sampleId, generalId])
@@index([sampleId, nationId, generalId])
@@index([sampleId, cityId, generalId])
@@map("play_audit_general")
}
@@ -0,0 +1,38 @@
CREATE TABLE "play_audit_month" (
"id" TEXT NOT NULL PRIMARY KEY,
"server_id" TEXT NOT NULL,
"year" INTEGER NOT NULL,
"month" INTEGER NOT NULL CHECK ("month" BETWEEN 1 AND 12),
"kind" TEXT NOT NULL CHECK ("kind" IN ('MONTH_END', 'FINAL')),
"tick" INTEGER,
"schema_version" INTEGER NOT NULL DEFAULT 1,
"settlements_complete" BOOLEAN NOT NULL,
"hash" TEXT NOT NULL,
"created_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE UNIQUE INDEX "play_audit_month_server_id_year_month_kind_key" ON "play_audit_month" ("server_id", "year", "month", "kind");
CREATE TABLE "play_audit_nation" (
"sample_id" TEXT NOT NULL REFERENCES "play_audit_month"("id") ON DELETE CASCADE ON UPDATE CASCADE,
"nation_id" INTEGER NOT NULL,
"data" JSONB NOT NULL,
PRIMARY KEY ("sample_id", "nation_id")
);
CREATE TABLE "play_audit_city" (
"sample_id" TEXT NOT NULL REFERENCES "play_audit_month"("id") ON DELETE CASCADE ON UPDATE CASCADE,
"city_id" INTEGER NOT NULL,
"nation_id" INTEGER NOT NULL,
"data" JSONB NOT NULL,
PRIMARY KEY ("sample_id", "city_id")
);
CREATE INDEX "play_audit_city_sample_id_nation_id_city_id_idx" ON "play_audit_city" ("sample_id", "nation_id", "city_id");
CREATE TABLE "play_audit_general" (
"sample_id" TEXT NOT NULL REFERENCES "play_audit_month"("id") ON DELETE CASCADE ON UPDATE CASCADE,
"general_id" INTEGER NOT NULL,
"nation_id" INTEGER NOT NULL,
"city_id" INTEGER NOT NULL,
"npc_state" INTEGER NOT NULL,
"data" JSONB NOT NULL,
PRIMARY KEY ("sample_id", "general_id")
);
CREATE INDEX "play_audit_general_sample_id_nation_id_general_id_idx" ON "play_audit_general" ("sample_id", "nation_id", "general_id");
CREATE INDEX "play_audit_general_sample_id_city_id_general_id_idx" ON "play_audit_general" ("sample_id", "city_id", "general_id");