From f1192279bf453f21e4f36e75657ebb6dde2609d4 Mon Sep 17 00:00:00 2001 From: P0nk Date: Fri, 24 Feb 2023 21:49:00 +0100 Subject: [PATCH] Add Flyway, run db migration in local PostgreSQL db First step in my plan to switch away from MySQL. --- config.yaml | 8 +++++ database/postgresql/create-admin-user.sql | 3 ++ pom.xml | 12 ++++++++ src/main/java/config/ServerConfig.java | 9 ++++++ src/main/java/database/PgDatabaseConfig.java | 30 +++++++++++++++++++ .../java/database/migration/FlywayRunner.java | 22 ++++++++++++++ src/main/java/net/server/Server.java | 21 +++++++++++++ .../db/migration/postgresql/V0__test.sql | 4 +++ src/main/resources/log4j2.xml | 2 ++ 9 files changed, 111 insertions(+) create mode 100644 database/postgresql/create-admin-user.sql create mode 100644 src/main/java/database/PgDatabaseConfig.java create mode 100644 src/main/java/database/migration/FlywayRunner.java create mode 100644 src/main/resources/db/migration/postgresql/V0__test.sql diff --git a/config.yaml b/config.yaml index 835fe88b93..8f84d933f3 100644 --- a/config.yaml +++ b/config.yaml @@ -165,6 +165,14 @@ server: DB_PASS: "snailshell" INIT_CONNECTION_POOL_TIMEOUT: 90 # Seconds + PG_DB_NAME: "cosmic" + PG_DB_HOST: "localhost" + PG_DB_SCHEMA: "cosmic" + PG_DB_ADMIN_USERNAME: "cosmic_admin" + PG_DB_ADMIN_PASSWORD: "redsnailshell" + PG_DB_USERNAME: "cosmic_server" + PG_DB_PASSWORD: "bluesnailshell" + #Login Configuration WORLDS: 1 #Initial number of worlds on the server. WLDLIST_SIZE: 21 #Max possible worlds on the server. diff --git a/database/postgresql/create-admin-user.sql b/database/postgresql/create-admin-user.sql new file mode 100644 index 0000000000..08eb0b59d5 --- /dev/null +++ b/database/postgresql/create-admin-user.sql @@ -0,0 +1,3 @@ +CREATE USER cosmic_admin WITH ENCRYPTED PASSWORD 'redsnailshell'; +GRANT ALL PRIVILEGES ON DATABASE cosmic TO cosmic_admin; +ALTER ROLE cosmic_admin WITH CREATEROLE; \ No newline at end of file diff --git a/pom.xml b/pom.xml index c5ac497114..be55b0e352 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,8 @@ 1.0 5.0.1 8.0.30 + 42.5.4 + 9.15.1 3.35.0 5.9.0 4.7.0 @@ -60,11 +62,21 @@ mysql-connector-java ${mysql-connector-java.version} + + org.postgresql + postgresql + ${postgresql.version} + org.jdbi jdbi3-core ${jdbi-version} + + org.flywaydb + flyway-core + ${flyway.version} + diff --git a/src/main/java/config/ServerConfig.java b/src/main/java/config/ServerConfig.java index 064599729a..8a07d5109e 100644 --- a/src/main/java/config/ServerConfig.java +++ b/src/main/java/config/ServerConfig.java @@ -12,6 +12,15 @@ public class ServerConfig { public String DB_PASS; public int INIT_CONNECTION_POOL_TIMEOUT; + // PostgreSQL database configuration + public String PG_DB_NAME; + public String PG_DB_HOST; + public String PG_DB_SCHEMA; + public String PG_DB_ADMIN_USERNAME; + public String PG_DB_ADMIN_PASSWORD; + public String PG_DB_USERNAME; + public String PG_DB_PASSWORD; + //Login Configuration public int WORLDS; public int WLDLIST_SIZE; diff --git a/src/main/java/database/PgDatabaseConfig.java b/src/main/java/database/PgDatabaseConfig.java new file mode 100644 index 0000000000..a290f23007 --- /dev/null +++ b/src/main/java/database/PgDatabaseConfig.java @@ -0,0 +1,30 @@ +package database; + +import java.time.Duration; + +public record PgDatabaseConfig( + String databaseName, String host, String schema, + String adminUsername, String adminPassword, + String username, String password, + Duration poolInitTimeout +) { + public PgDatabaseConfig { + verifyNotBlank(databaseName); + verifyNotBlank(host); + verifyNotBlank(schema); + verifyNotBlank(adminUsername); + verifyNotBlank(adminPassword); + verifyNotBlank(username); + verifyNotBlank(password); + } + + private void verifyNotBlank(String value) { + if (value == null || value.isBlank()) { + throw new IllegalArgumentException("Missing or blank value in PG database config"); + } + } + + public String getJdbcUrl() { + return "jdbc:postgresql://%s:5432/%s".formatted(host, databaseName); + } +} diff --git a/src/main/java/database/migration/FlywayRunner.java b/src/main/java/database/migration/FlywayRunner.java new file mode 100644 index 0000000000..960ffea00b --- /dev/null +++ b/src/main/java/database/migration/FlywayRunner.java @@ -0,0 +1,22 @@ +package database.migration; + +import database.PgDatabaseConfig; +import org.flywaydb.core.Flyway; +import org.flywaydb.core.api.FlywayException; + +public class FlywayRunner { + private final PgDatabaseConfig dbConfig; + + public FlywayRunner(PgDatabaseConfig dbConfig) { + this.dbConfig = dbConfig; + } + + public void migrate() throws FlywayException { + Flyway flyway = Flyway.configure() + .dataSource(dbConfig.getJdbcUrl(), dbConfig.adminUsername(), dbConfig.adminPassword()) + .schemas(dbConfig.schema()) + .createSchemas(true) + .load(); + flyway.migrate(); + } +} diff --git a/src/main/java/net/server/Server.java b/src/main/java/net/server/Server.java index 5b854bebcd..19e1490f11 100644 --- a/src/main/java/net/server/Server.java +++ b/src/main/java/net/server/Server.java @@ -31,11 +31,14 @@ import client.inventory.ItemFactory; import client.inventory.manipulator.CashIdGenerator; import client.newyear.NewYearCardRecord; import client.processor.npc.FredrickProcessor; +import config.ServerConfig; import config.YamlConfig; import constants.game.GameConstants; import constants.inventory.ItemConstants; import constants.net.OpcodeConstants; import constants.net.ServerConstants; +import database.PgDatabaseConfig; +import database.migration.FlywayRunner; import database.note.NoteDao; import net.ChannelDependencies; import net.PacketProcessor; @@ -840,6 +843,8 @@ public class Server { Runtime.getRuntime().addShutdownHook(new Thread(shutdown(false))); } + runDatabaseMigration(); + if (!DatabaseConnection.initializeConnectionPool()) { throw new IllegalStateException("Failed to initiate a connection to the database"); } @@ -922,6 +927,22 @@ public class Server { } } + private void runDatabaseMigration() { + PgDatabaseConfig pgDbConfig = readPgDbConfig(); + FlywayRunner flywayRunner = new FlywayRunner(pgDbConfig); + flywayRunner.migrate(); + } + + private PgDatabaseConfig readPgDbConfig() { + final ServerConfig serverConfig = YamlConfig.config.server; + return new PgDatabaseConfig( + serverConfig.PG_DB_NAME, serverConfig.PG_DB_HOST, serverConfig.PG_DB_SCHEMA, + serverConfig.PG_DB_ADMIN_USERNAME, serverConfig.PG_DB_ADMIN_PASSWORD, + serverConfig.PG_DB_USERNAME, serverConfig.PG_DB_PASSWORD, + Duration.ofSeconds(serverConfig.INIT_CONNECTION_POOL_TIMEOUT) + ); + } + private ChannelDependencies registerChannelDependencies() { NoteService noteService = new NoteService(new NoteDao()); FredrickProcessor fredrickProcessor = new FredrickProcessor(noteService); diff --git a/src/main/resources/db/migration/postgresql/V0__test.sql b/src/main/resources/db/migration/postgresql/V0__test.sql new file mode 100644 index 0000000000..e554e389ed --- /dev/null +++ b/src/main/resources/db/migration/postgresql/V0__test.sql @@ -0,0 +1,4 @@ +CREATE TABLE flyway_test( + id SERIAL PRIMARY KEY, + dummy TEXT +); \ No newline at end of file diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index 7bc44f142e..2eb24eaa3a 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -100,5 +100,7 @@ + + \ No newline at end of file