1
0
Fork 0
mirror of https://github.com/xHyroM/lighteco.git synced 2024-11-25 08:11:04 +01:00

feat: mysql [wip]

This commit is contained in:
Jozef Steinhübl 2023-08-28 22:17:58 +02:00
parent 66bb95559c
commit 818ffe28cf
9 changed files with 262 additions and 20 deletions

View file

@ -12,6 +12,21 @@ public enum Dependency {
"org.xerial", "org.xerial",
"sqlite-jdbc", "sqlite-jdbc",
"3.28.0" "3.28.0"
),
MARIADB_DRIVER(
"org.mariadb.jdbc",
"mariadb-java-client",
"3.1.3"
),
MYSQL_DRIVER(
"mysql",
"mysql-connector-java",
"8.0.23"
),
POSTGRESQL_DRIVER(
"org.postgresql",
"postgresql",
"42.6.0"
); );
@Getter @Getter

View file

@ -11,6 +11,8 @@ public class DependencyRegistry {
private static final SetMultimap<StorageType, Dependency> STORAGE_DEPENDENCIES = ImmutableSetMultimap.<StorageType, Dependency>builder() private static final SetMultimap<StorageType, Dependency> STORAGE_DEPENDENCIES = ImmutableSetMultimap.<StorageType, Dependency>builder()
.putAll(StorageType.SQLITE, Dependency.SQLITE_DRIVER) .putAll(StorageType.SQLITE, Dependency.SQLITE_DRIVER)
.putAll(StorageType.H2, Dependency.H2_DRIVER) .putAll(StorageType.H2, Dependency.H2_DRIVER)
.putAll(StorageType.MYSQL, Dependency.MYSQL_DRIVER)
.putAll(StorageType.MARIADB, Dependency.MARIADB_DRIVER)
.build(); .build();
public Set<Dependency> resolveStorageDependencies(Set<StorageType> types) { public Set<Dependency> resolveStorageDependencies(Set<StorageType> types) {

View file

@ -7,6 +7,8 @@ import dev.xhyrom.lighteco.common.storage.provider.memory.MemoryStorageProvider;
import dev.xhyrom.lighteco.common.storage.provider.sql.SqlStorageProvider; import dev.xhyrom.lighteco.common.storage.provider.sql.SqlStorageProvider;
import dev.xhyrom.lighteco.common.storage.provider.sql.connection.file.H2ConnectionFactory; import dev.xhyrom.lighteco.common.storage.provider.sql.connection.file.H2ConnectionFactory;
import dev.xhyrom.lighteco.common.storage.provider.sql.connection.file.SqliteConnectionFactory; import dev.xhyrom.lighteco.common.storage.provider.sql.connection.file.SqliteConnectionFactory;
import dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari.MariaDBConnectionFactory;
import dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari.MySQLConnectionFactory;
import java.util.Set; import java.util.Set;
@ -45,6 +47,16 @@ public class StorageFactory {
this.plugin, this.plugin,
new SqliteConnectionFactory(this.plugin.getBootstrap().getDataDirectory().resolve("lighteco-sqlite.db")) new SqliteConnectionFactory(this.plugin.getBootstrap().getDataDirectory().resolve("lighteco-sqlite.db"))
); );
case "mysql":
return new SqlStorageProvider(
this.plugin,
new MySQLConnectionFactory(this.plugin.getConfig().storage.data)
);
case "mariadb":
return new SqlStorageProvider(
this.plugin,
new MariaDBConnectionFactory(this.plugin.getConfig().storage.data)
);
default: default:
throw new IllegalArgumentException("Unknown storage provider: " + provider); throw new IllegalArgumentException("Unknown storage provider: " + provider);
} }

View file

@ -25,7 +25,7 @@ public enum SqlStatements {
case SQLITE -> { case SQLITE -> {
return this.sqlite; return this.sqlite;
} }
case H2, MYSQL -> { case H2, MYSQL, MARIADB -> {
return this.mysql; return this.mysql;
} }
} }

View file

@ -0,0 +1,46 @@
package dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari;
import com.zaxxer.hikari.HikariConfig;
import dev.xhyrom.lighteco.common.config.storage.StorageDataConfig;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
public abstract class DriverBasedHikariConnectionFactory extends HikariConnectionFactory {
protected DriverBasedHikariConnectionFactory(StorageDataConfig configuration) {
super(configuration);
}
protected abstract String driverClassName();
protected abstract String driverJdbcIdentifier();
@Override
protected void configureDatabase(HikariConfig config, String address, String port, String databaseName, String username, String password) {
config.setDriverClassName(driverClassName());
config.setJdbcUrl(String.format("jdbc:%s://%s:%s/%s", driverJdbcIdentifier(), address, port, databaseName));
config.setUsername(username);
config.setPassword(password);
}
@Override
protected void postInitialize() {
super.postInitialize();
deregisterDriver(driverClassName());
}
private static void deregisterDriver(String driverClassName) {
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
if (driver.getClass().getName().equals(driverClassName)) {
try {
DriverManager.deregisterDriver(driver);
} catch (SQLException ignored) {}
}
}
}
}

View file

@ -1,36 +1,104 @@
package dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari; package dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import dev.xhyrom.lighteco.common.config.storage.StorageDataConfig;
import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin; import dev.xhyrom.lighteco.common.plugin.LightEcoPlugin;
import dev.xhyrom.lighteco.common.storage.StorageType;
import dev.xhyrom.lighteco.common.storage.provider.sql.connection.ConnectionFactory; import dev.xhyrom.lighteco.common.storage.provider.sql.connection.ConnectionFactory;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
public class HikariConnectionFactory implements ConnectionFactory { public abstract class HikariConnectionFactory implements ConnectionFactory {
private final StorageDataConfig configuration;
private HikariDataSource hikari;
public HikariConnectionFactory(StorageDataConfig configuration) {
this.configuration = configuration;
}
protected abstract String defaultPort();
protected abstract void configureDatabase(HikariConfig config, String address, String port, String databaseName, String username, String password);
protected void overrideProperties(Map<String, Object> properties) {
// https://github.com/brettwooldridge/HikariCP/wiki/Rapid-Recovery
properties.putIfAbsent("socketTimeout", String.valueOf(TimeUnit.SECONDS.toMillis(30)));
}
protected void setProperties(HikariConfig config, Map<String, Object> properties) {
for (Map.Entry<String, Object> property : properties.entrySet()) {
config.addDataSourceProperty(property.getKey(), property.getValue());
}
}
/**
* Called after the Hikari pool has been initialised
*/
protected void postInitialize() {
@Override
public StorageType getImplementationName() {
return null;
} }
@Override @Override
public void init(LightEcoPlugin plugin) { public void init(LightEcoPlugin plugin) {
HikariConfig config = new HikariConfig();
// set pool name so the logging output can be linked back to us
config.setPoolName("lighteco-hikari");
// get the database info/credentials from the config file
String[] addressSplit = this.configuration.address.split(":");
String address = addressSplit[0];
String port = addressSplit.length > 1 ? addressSplit[1] : defaultPort();
// allow the implementation to configure the HikariConfig appropriately with these values
configureDatabase(config, address, port, this.configuration.database, this.configuration.username, this.configuration.password);
Map<String, Object> properties = new HashMap<>();
this.overrideProperties(properties);
this.setProperties(config, properties);
// configure the connection pool
// config.setMaximumPoolSize(1);
// config.setMinimumIdle(10);
// config.setMaxLifetime(1800000);
// config.setKeepaliveTime(0);
// config.setConnectionTimeout(5000);
// config.setInitializationFailTimeout(-1);
this.hikari = new HikariDataSource(config);
postInitialize();
} }
@Override @Override
public void shutdown() throws Exception { public void shutdown() {
if (this.hikari != null) {
this.hikari.close();
}
}
@Override
public Connection getConnection() throws SQLException {
if (this.hikari == null) {
throw new SQLException("Unable to get a connection from the pool. (hikari is null)");
}
Connection connection = this.hikari.getConnection();
if (connection == null) {
throw new SQLException("Unable to get a connection from the pool. (getConnection returned null)");
}
return connection;
} }
@Override @Override
public Function<String, String> getStatementProcessor() { public Function<String, String> getStatementProcessor() {
return null; return s -> s.replace('\'', '`');
}
@Override
public Connection getConnection() throws Exception {
return null;
} }
} }

View file

@ -0,0 +1,32 @@
package dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari;
import dev.xhyrom.lighteco.common.config.storage.StorageDataConfig;
import dev.xhyrom.lighteco.common.storage.StorageType;
import java.util.Map;
public class MariaDBConnectionFactory extends DriverBasedHikariConnectionFactory {
public MariaDBConnectionFactory(StorageDataConfig configuration) {
super(configuration);
}
@Override
public StorageType getImplementationName() {
return StorageType.MARIADB;
}
@Override
protected String defaultPort() {
return "3306";
}
@Override
protected String driverClassName() {
return "org.mariadb.jdbc.Driver";
}
@Override
protected String driverJdbcIdentifier() {
return "mariadb";
}
}

View file

@ -0,0 +1,54 @@
package dev.xhyrom.lighteco.common.storage.provider.sql.connection.hikari;
import dev.xhyrom.lighteco.common.config.storage.StorageDataConfig;
import dev.xhyrom.lighteco.common.storage.StorageType;
import java.util.Map;
public class MySQLConnectionFactory extends DriverBasedHikariConnectionFactory {
public MySQLConnectionFactory(StorageDataConfig configuration) {
super(configuration);
}
@Override
public StorageType getImplementationName() {
return StorageType.MYSQL;
}
@Override
protected String defaultPort() {
return "3306";
}
@Override
protected String driverClassName() {
return "com.mysql.cj.jdbc.Driver";
}
@Override
protected String driverJdbcIdentifier() {
return "mysql";
}
@Override
protected void overrideProperties(Map<String, Object> properties) {
// https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration
properties.putIfAbsent("cachePrepStmts", "true");
properties.putIfAbsent("prepStmtCacheSize", "250");
properties.putIfAbsent("prepStmtCacheSqlLimit", "2048");
properties.putIfAbsent("useServerPrepStmts", "true");
properties.putIfAbsent("useLocalSessionState", "true");
properties.putIfAbsent("rewriteBatchedStatements", "true");
properties.putIfAbsent("cacheResultSetMetadata", "true");
properties.putIfAbsent("cacheServerConfiguration", "true");
properties.putIfAbsent("elideSetAutoCommits", "true");
properties.putIfAbsent("maintainTimeStats", "false");
properties.putIfAbsent("alwaysSendSetIsolation", "false");
properties.putIfAbsent("cacheCallableStmts", "true");
// https://stackoverflow.com/a/54256150
// It's not super important which timezone we pick, because we don't use time-based
// data types in any of our schemas/queries.
properties.putIfAbsent("serverTimezone", "UTC");
}
}

View file

@ -0,0 +1,13 @@
CREATE TABLE IF NOT EXISTS `{prefix}_users` (
`uuid` VARCHAR(36) NOT NULL,
`currency_identifier` VARCHAR(255) NOT NULL,
`balance` DECIMAL(10, 2) NOT NULL,
PRIMARY KEY (`uuid`, `currency_identifier`)
);
CREATE TABLE IF NOT EXISTS `{prefix}_{context}_users` (
`uuid` VARCHAR(36) NOT NULL,
`currency_identifier` VARCHAR(255) NOT NULL,
`balance` DECIMAL(10, 2) NOT NULL,
PRIMARY KEY (`uuid`, `currency_identifier`)
);