This commit is contained in:
2025-10-27 16:28:03 +10:30
commit 15431b69b3
19 changed files with 771 additions and 0 deletions

155
db/build.gradle Normal file
View File

@@ -0,0 +1,155 @@
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
plugins {
id 'java'
id 'com.google.cloud.tools.jib' version '3.4.2'
id 'application'
}
application {
mainClass = 'com.example.DbSetup'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.postgresql:postgresql:42.7.3'
}
def containername = "mtg-search-db"
def dbName = "mtgsearch"
def dbUser = "dbuser"
def dbPass = "dbpass"
def psqlZipFile = new File("$rootDir\\AllPrintings.psql.zip")
def psqlFile = new File("$rootDir\\AllPrintings\\AllPrintings.psql")
jib {
from {
image = 'postgres:17' // base image
}
to {
image = "hub.docker.com/$containername:latest"
auth {
username = System.getenv("DOCKER_USER")?:""
password = System.getenv("DOCKER_PASS")?:""
}
}
container {
// Jib runs as rootless by default; PostgreSQL needs a few tweaks
entrypoint = ['docker-entrypoint.sh']
args = ['postgres']
environment = [
POSTGRES_USER: dbUser,
POSTGRES_PASSWORD: dbPass,
POSTGRES_DB: dbName
]
ports = ['5432']
}
}
// Custom Gradle task to run database setup logic
tasks.register('runDbSetup', JavaExec) {
dependsOn classes
mainClass.set('com.example.DbSetup')
classpath = sourceSets.main.runtimeClasspath
environment 'POSTGRES_USER', dbUser
environment 'POSTGRES_PASSWORD', dbPass
environment 'POSTGRES_DB', dbName
environment 'PSQL_FILE', psqlFile.canonicalPath
}
// Ensure setup runs before building the Docker image
tasks.named('jib') {
dependsOn('runDbSetup')
}
tasks.register('startPostgresContainer', Exec) {
commandLine 'docker', 'run', '-d',
'--name', "$containername",
'-e', "POSTGRES_USER=$dbUser",
'-e', "POSTGRES_PASSWORD=$dbPass",
'-e', "POSTGRES_DB=$dbName",
'-p', '5432:5432',
'postgres:17'
}
tasks.register('stopPostgresContainer', Exec) {
commandLine 'docker', 'rm', '-f', containername
}
// Hook the lifecycle
tasks.named('runDbSetup') {
dependsOn('startPostgresContainer')
finalizedBy('stopPostgresContainer')
}
tasks.register('getLatestMTGJson') {
outputs.files files("AllPrintings.psql.zip.sha256","AllPrintings.psql.zip")
outputs.upToDateWhen {
def url = new URL("https://mtgjson.com/api/v5/AllPrintings.psql.zip.sha256")
def urlHash = url.text // Groovy shortcut to read text from URL
def file = new File('AllPrintings.psql.zip.sha256')
if(file.exists()) {
def fileHash = file.text
def equal = urlHash == fileHash
if(!equal){
println("AllPrintings.psql.zip.sha256 out of date")
}
return equal
}
println("AllPrintings.psql.zip.sha256 not found")
return false
}
doLast {
def url = new URL("https://mtgjson.com/api/v5/AllPrintings.psql.zip")
println("Downloading $url to $psqlZipFile")
psqlZipFile.withOutputStream { out ->
out << url.openStream()
}
url = new URL("https://mtgjson.com/api/v5/AllPrintings.psql.zip.sha256")
def file = new File("AllPrintings.psql.zip.sha256")
println("Downloading $url to $file")
file.withOutputStream { out ->
out << url.openStream()
}
}
}
tasks.register("unzipAllPrintings"){
dependsOn("getLatestMTGJson")
doLast {
def destinationDir = new File("AllPrintings")
// Ensure the destination directory exists
destinationDir.mkdirs()
psqlZipFile.withInputStream { fis ->
new ZipInputStream(fis).with { zis ->
ZipEntry entry
while ((entry = zis.nextEntry) != null) {
def outputFile = new File(destinationDir, entry.name)
if (entry.isDirectory()) {
outputFile.mkdirs()
} else {
outputFile.parentFile.mkdirs() // Ensure parent directories exist
outputFile.withOutputStream { fos ->
fos << zis // Copy the entry's content
}
}
zis.closeEntry()
}
}
}
println "Successfully unzipped ${psqlZipFile.name} to ${destinationDir.absolutePath}"
}
}

2
db/docker/Dockerfile Normal file
View File

@@ -0,0 +1,2 @@
FROM postgres:17
COPY ./init.sql /docker-entrypoint-initdb.d/

View File

@@ -0,0 +1,67 @@
package com.example;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Objects;
import java.util.StringJoiner;
public class DbSetup {
public static void main(String[] args) throws Exception {
// ========================
//todo replace with better way to wait for container to be ready
Thread.sleep(5000);
// ========================
String dbuser = Objects.requireNonNullElse(System.getenv("POSTGRES_USER"),"dbuser");
String dbpass = Objects.requireNonNullElse(System.getenv("POSTGRES_PASSWORD"),"dbpass");
String dbname = Objects.requireNonNullElse(System.getenv("POSTGRES_DB"),"mtgsearch");
String psqlFilePath = Objects.requireNonNullElse(System.getenv("PSQL_FILE"),"AllPrintings/AllPrintings.psql");
String url = "jdbc:postgresql://localhost:5432/" + dbname;
//Load the MTGJson Allprintings PSQL File
File psqlFile = new File(psqlFilePath);
String[] commands = {"C:\\Program Files\\PostgreSQL\\17\\bin\\psql.exe","-U",dbuser,"-d",dbname,"-h","localhost","-p","5432","-f",psqlFile.getCanonicalPath()};
String[] envVars = { "PGPASSWORD="+dbpass };
Runtime rt = Runtime.getRuntime();
System.out.println(String.join(" ",commands));
Process proc = rt.exec(commands,envVars);
System.out.println("<OUTPUT>");
try (BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println("Output: " + line);
}
}
System.out.println("</OUTPUT>");
System.out.println("<ERROR>");
try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(proc.getErrorStream()))) {
String line;
while ((line = errorReader.readLine()) != null) {
System.err.println("Error: " + line);
}
}
System.out.println("</ERROR>");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
// try (Connection conn = DriverManager.getConnection(url, dbuser, dbpass);
// Statement stmt = conn.createStatement()) {
// stmt.execute("CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name TEXT)");
// stmt.execute("INSERT INTO users (name) VALUES ('Alice'), ('Bob')");
// System.out.println("✅ Database setup complete!");
// }
}
}