Skip to content

Commit

Permalink
Moved to DatabaseUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim203 committed Feb 11, 2024
1 parent 0975f48 commit 868ff81
Show file tree
Hide file tree
Showing 17 changed files with 157 additions and 379 deletions.
14 changes: 6 additions & 8 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ dependencies {
api(projects.api)
api(libs.base.api)
compileOnlyApi(projects.isolation)
api(libs.config.utils)

annotationProcessor(libs.config.utils.ap)
api(libs.config.utils)

annotationProcessor(libs.database.utils.ap)
api(libs.database.utils)
compileOnlyApi(libs.database.utils.sql)

api(libs.bundles.fastutil)
api(libs.java.websocket)
Expand All @@ -28,13 +33,6 @@ dependencies {
compileOnlyApi(libs.jakarta.jsonb)
annotationProcessor(libs.micronaut.serde.processor)

api(libs.micronaut.data.jdbc)
runtimeOnly(libs.micronaut.hikari)
annotationProcessor(libs.micronaut.data.processor)
compileOnlyApi(libs.jakarta.persistence)

runtimeOnly("com.h2database:h2")

testImplementation(libs.junit.jupiter)
testRuntimeOnly(libs.junit.platform.launcher)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import io.micronaut.context.ApplicationContext;
import io.micronaut.context.Qualifier;
import io.micronaut.core.type.Argument;
import io.micronaut.inject.qualifiers.Qualifiers;
import java.nio.file.Path;
import java.util.Map;
import java.util.UUID;
import org.geysermc.api.Geyser;
Expand All @@ -39,7 +41,10 @@
import org.geysermc.floodgate.api.inject.PlatformInjector;
import org.geysermc.floodgate.api.logger.FloodgateLogger;
import org.geysermc.floodgate.api.packet.PacketHandlers;
import org.geysermc.floodgate.core.config.ConfigLoader;
import org.geysermc.floodgate.core.config.FloodgateConfig;
import org.geysermc.floodgate.core.config.Properties;
import org.geysermc.floodgate.core.database.loader.DatabaseLoader;
import org.geysermc.floodgate.core.event.EventBus;
import org.geysermc.floodgate.core.event.lifecycle.PostEnableEvent;
import org.geysermc.floodgate.core.event.lifecycle.ShutdownEvent;
Expand Down Expand Up @@ -75,6 +80,12 @@ public void load() {
.eagerInitSingletons(true)
.build();
onContextCreated(context);

// load and register config and database related stuff
var dataDirectory = context.getBean(Path.class, Qualifiers.byName("dataDirectory"));
FloodgateConfig config = ConfigLoader.load(dataDirectory, isProxy(), context);
DatabaseLoader.load(config, manager, dataDirectory, context);

context.start();

injector = context.getBean(PlatformInjector.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,41 @@

import cloud.commandframework.Command;
import cloud.commandframework.CommandManager;
import cloud.commandframework.arguments.standard.StringArgument;
import cloud.commandframework.arguments.standard.UUIDArgument;
import cloud.commandframework.context.CommandContext;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import org.geysermc.api.Geyser;
import java.util.concurrent.ExecutionException;
import org.geysermc.floodgate.core.config.FloodgateConfig;
import org.geysermc.floodgate.core.connection.audience.UserAudience;
import org.geysermc.floodgate.core.link.CommonPlayerLink;
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
import org.geysermc.floodgate.core.util.Constants;
import org.geysermc.floodgate.core.util.Utils;

@Singleton
public class TestCommand implements FloodgateCommand {
@Inject CommonPlayerLink link;

@Override
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
return commandManager.commandBuilder("floodgate-test")
.senderType(UserAudience.class)
.senderType(UserAudience.ConsoleAudience.class)
.handler(this::execute)
.argument(StringArgument.of("xuid"))
.argument(UUIDArgument.of("uuid"))
.argument(StringArgument.of("name"))
.build();
}

@Override
public void execute(CommandContext<UserAudience> context) {
int players = Geyser.api().onlineConnectionsCount();
context.getSender().sendMessage(String.valueOf(players));
try {
link.addLink(context.get("uuid"), context.get("name"), Utils.getJavaUuid(context.get("xuid"))).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,76 +25,34 @@

package org.geysermc.floodgate.core.config;

import io.micronaut.context.annotation.BootstrapContextCompatible;
import io.micronaut.context.env.BootstrapPropertySourceLocator;
import io.micronaut.context.env.Environment;
import io.micronaut.context.env.PropertySource;
import io.micronaut.context.exceptions.ConfigurationException;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.inject.Singleton;
import java.lang.reflect.Proxy;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import org.geysermc.configutils.node.codec.strategy.object.ProxyEmbodimentStrategy;
import org.geysermc.floodgate.core.database.loader.DatabaseType;
import org.geysermc.floodgate.core.util.GlobalBeanCache;
import org.geysermc.floodgate.isolation.library.LibraryManager;

@Singleton
@BootstrapContextCompatible
public class ConfigAsProperties implements BootstrapPropertySourceLocator {
@Inject
@Named("dataDirectory")
Path dataDirectory;
public final class ConfigAsPropertySource {
private ConfigAsPropertySource() {}

@Inject FloodgateConfig config;

@Override
public Iterable<PropertySource> findPropertySources(Environment environment)
throws ConfigurationException {
loadDatabase();

var flat = flattern(Map.of("config", config));
flat.forEach((key, value) -> System.out.println(key + ": " + value));

return Collections.singleton(PropertySource.of(flat));
}

private void loadDatabase() {
LibraryManager manager = GlobalBeanCache.get("libraryManager");

var databaseConfig = config.database();
if (!databaseConfig.enabled()) {
return;
}

var type = DatabaseType.byId(databaseConfig.type());
if (type == null) {
throw new IllegalStateException(
"Unable to find database type that matches: " + databaseConfig.type()
);
}

type.libraries().forEach(manager::addLibrary);
manager.apply();
public static PropertySource toPropertySource(FloodgateConfig config) {
Objects.requireNonNull(config);
return PropertySource.of(flatten(Map.of("config", config)));
}

private Map<String, Object> flattern(Map<String, Object> map) {
return flattern0(Map.of("", map).get(""));
private static Map<String, Object> flatten(Map<String, Object> map) {
return flatten0(Map.of("", map).get(""));
}

@SuppressWarnings("unchecked")
private Map<String, Object> flattern0(Map<String, Object> map) {
private static Map<String, Object> flatten0(Map<String, Object> map) {
var result = new HashMap<String, Object>();
map.forEach((key, value) -> {
if (Proxy.isProxyClass(value.getClass())) {
value = new ProxyEmbodimentStrategy().disembody(value);
}
if (value instanceof Map<?,?>) {
flattern0((Map<String, Object>) value).forEach(
flatten0((Map<String, Object>) value).forEach(
(key1, value1) -> result.put(key + "." + key1, value1)
);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,49 +25,20 @@

package org.geysermc.floodgate.core.config;

import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.BootstrapContextCompatible;
import io.micronaut.context.annotation.Factory;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.inject.Singleton;
import io.micronaut.context.ApplicationContext;
import java.nio.file.Path;
import java.util.UUID;
import lombok.Getter;
import org.geysermc.configutils.ConfigUtilities;
import org.geysermc.configutils.file.codec.PathFileCodec;
import org.geysermc.configutils.updater.change.Changes;
import org.geysermc.floodgate.core.scope.ProxyOnly;
import org.geysermc.floodgate.core.scope.ServerOnly;
import org.geysermc.floodgate.core.util.GlobalBeanCache;

@Factory
@Getter
@BootstrapContextCompatible
public final class ConfigLoader {
private final Path dataDirectory;

@Inject
ConfigLoader(@Named("dataDirectory") Path dataDirectory) {
this.dataDirectory = dataDirectory;
}

@Bean
@ServerOnly
@Singleton
FloodgateConfig config() {
return GlobalBeanCache.cacheIfAbsent("config", () -> load(FloodgateConfig.class));
}

@Bean
@ProxyOnly
@Singleton
ProxyFloodgateConfig proxyConfig() {
return GlobalBeanCache.cacheIfAbsent("config", () -> load(ProxyFloodgateConfig.class));
}
private ConfigLoader() {}

@SuppressWarnings("unchecked")
private <T extends FloodgateConfig> T load(Class<? extends FloodgateConfig> configClass) {
public static <T extends FloodgateConfig> T load(Path dataDirectory, boolean isProxy, ApplicationContext context) {
var configClass = isProxy ? ProxyFloodgateConfig.class : FloodgateConfig.class;

// it would also be nice to have sections in versionBuilder so that you don't have to
// provide the path all the time

Expand All @@ -85,15 +56,24 @@ private <T extends FloodgateConfig> T load(Class<? extends FloodgateConfig> conf
.keyRenamed("playerLink.type", "database.type"))
.build())
.definePlaceholder("metrics.uuid", UUID::randomUUID)
.postInitializeCallbackArgument(this)
.postInitializeCallbackArgument(dataDirectory)
.build();

T config;
try {
return (T) utilities.executeOn(configClass);
config = (T) utilities.executeOn(configClass);
} catch (Throwable throwable) {
throw new RuntimeException(
"Failed to load the config! Try to delete the config file if this error persists",
throwable
);
}

// make sure the proxy and the normal config types are registered
context.registerSingleton(config);
context.registerSingleton(FloodgateConfig.class, config);
// make @Requires etc. work
context.getEnvironment().addPropertySource(ConfigAsPropertySource.toPropertySource(config));
return config;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@
* addition to the global configuration like {@link ProxyFloodgateConfig} for the proxies.
*/
@ConfigVersion(3)
public interface FloodgateConfig extends GenericPostInitializeCallback<ConfigLoader> {
public interface FloodgateConfig extends GenericPostInitializeCallback<Path> {
default boolean proxy() {
return this instanceof ProxyFloodgateConfig;
}

@Override
default CallbackResult postInitialize(ConfigLoader loader) {
Path keyPath = loader.getDataDirectory().resolve(keyFileName());
default CallbackResult postInitialize(Path dataDirectory) {
Path keyPath = dataDirectory.resolve(keyFileName());

// don't assume that the key always exists with the existence of a config
if (!Files.exists(keyPath)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@

package org.geysermc.floodgate.core.database;

import io.micronaut.context.annotation.Requires;
import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.query.builder.sql.Dialect;
import io.micronaut.data.repository.CrudRepository;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.geysermc.databaseutils.IRepository;
import org.geysermc.databaseutils.meta.Repository;
import org.geysermc.floodgate.core.database.entity.LinkRequest;

@JdbcRepository(dialect = Dialect.ANSI)
@Requires(property = "config.database.enabled", value = "true")
public interface PendingLinkRepository extends CrudRepository<LinkRequest, UUID> {
LinkRequest findByJavaUsername(String javaUsername);
@Repository
public interface PendingLinkRepository extends IRepository<LinkRequest> {
CompletableFuture<LinkRequest> findByJavaUsername(String javaUsername);

CompletableFuture<LinkRequest> insert(LinkRequest request);

CompletableFuture<Void> delete(LinkRequest request);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,32 +25,23 @@

package org.geysermc.floodgate.core.database;

import io.micronaut.context.annotation.Requires;
import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.query.builder.sql.Dialect;
import io.micronaut.data.repository.CrudRepository;
import jakarta.validation.constraints.NotNull;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.geysermc.databaseutils.IRepository;
import org.geysermc.databaseutils.meta.Repository;
import org.geysermc.floodgate.core.database.entity.LinkedPlayer;

@JdbcRepository(dialect = Dialect.ANSI)
@Requires(property = "config.database.enabled", value = "true")
public interface PlayerLinkRepository extends CrudRepository<LinkedPlayer, UUID> {
Optional<LinkedPlayer> findByBedrockId(@NotNull UUID bedrockId);
@Repository
public interface PlayerLinkRepository extends IRepository<LinkedPlayer> {

Optional<LinkedPlayer> findByJavaUniqueId(@NotNull UUID javaUniqueId);

Optional<LinkedPlayer> findByBedrockIdOrJavaUniqueId(
CompletableFuture<LinkedPlayer> findByBedrockIdOrJavaUniqueId(
UUID bedrockId,
UUID javaUniqueId
);

Boolean existsByBedrockId(@NotNull UUID bedrockId);

Boolean existsByJavaUniqueId(@NotNull UUID javaUniqueId);
CompletableFuture<Boolean> existsByBedrockIdOrJavaUniqueId(UUID bedrockId, UUID javaUniqueId);

Boolean existsByBedrockIdOrJavaUniqueId(UUID bedrockId, UUID javaUniqueId);
CompletableFuture<Void> deleteByBedrockIdOrJavaUniqueId(UUID bedrockId, UUID javaUniqueId);

void deleteByBedrockIdOrJavaUniqueId(UUID bedrockId, UUID javaUniqueId);
CompletableFuture<LinkedPlayer> insert(LinkedPlayer player);
}
Loading

0 comments on commit 868ff81

Please sign in to comment.