This commit is contained in:
2026-04-17 13:57:48 +03:00
parent 031910e848
commit 5759a223d2
11 changed files with 466 additions and 87 deletions

View File

@@ -1,70 +1,80 @@
package su.xserver.iikocon;
import io.vertx.config.ConfigRetriever;
import io.vertx.config.ConfigRetrieverOptions;
import io.vertx.config.ConfigStoreOptions;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpServer;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.healthchecks.HealthChecks;
import io.vertx.ext.healthchecks.Status;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.handler.SessionHandler;
import io.vertx.ext.web.handler.StaticHandler;
import io.vertx.ext.web.sstore.LocalSessionStore;
import io.vertx.ext.web.sstore.SessionStore;
import io.vertx.ext.web.sstore.redis.RedisSessionStore;
import io.vertx.mysqlclient.MySQLConnectOptions;
import io.vertx.redis.client.Redis;
import io.vertx.redis.client.RedisAPI;
import io.vertx.redis.client.RedisOptions;
import io.vertx.sqlclient.Pool;
import io.vertx.sqlclient.PoolOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import su.xserver.iikocon.config.AppConfig;
import su.xserver.iikocon.service.DataBaseService;
import su.xserver.iikocon.service.HealthCheckService;
import su.xserver.iikocon.service.RedisService;
public class MainVerticle extends AbstractVerticle {
private static final Logger log = LoggerFactory.getLogger(MainVerticle.class);
private Pool dbPool;
private final Logger log = LoggerFactory.getLogger("[MainVerticle]");
private DataBaseService db;
private RedisService redis;
private HttpServer httpServer;
private AppConfig config;
private UserService userService;
@Override
public void start(Promise<Void> startPromise) {
// Конфигурация из переменных окружения
JsonObject config = new JsonObject()
.put("db_host", System.getenv().getOrDefault("DB_HOST", "localhost"))
.put("db_port", Integer.parseInt(System.getenv().getOrDefault("DB_PORT", "3306")))
.put("db_name", System.getenv().getOrDefault("DB_NAME", "admin_db"))
.put("db_user", System.getenv().getOrDefault("DB_USER", "admin_user"))
.put("db_password", System.getenv().getOrDefault("DB_PASSWORD", "admin_pass"))
.put("http_port", Integer.parseInt(System.getenv().getOrDefault("HTTP_PORT", "8080")));
log.info("Starting with config: {}", config.encodePrettily());
ConfigStoreOptions classpathStore = new ConfigStoreOptions()
.setType("file")
.setFormat("json")
.setConfig(new JsonObject().put("path", "config.json").put("hierarchical", true))
.setOptional(false);
// Подключение к MariaDB
MySQLConnectOptions connectOptions = new MySQLConnectOptions()
.setHost(config.getString("db_host"))
.setPort(config.getInteger("db_port"))
.setDatabase(config.getString("db_name"))
.setUser(config.getString("db_user"))
.setPassword(config.getString("db_password"));
ConfigRetrieverOptions options = new ConfigRetrieverOptions()
.addStore(classpathStore);
PoolOptions poolOptions = new PoolOptions().setMaxSize(5);
dbPool = Pool.pool(vertx, connectOptions, poolOptions);
ConfigRetriever retriever = ConfigRetriever.create(vertx, options);
// Инициализация сервисов
userService = new UserService(dbPool);
retriever.getConfig()
.onSuccess(cfg -> {
config = AppConfig.from(cfg);
// Инициализация БД (создание таблицы users)
userService.initDatabase()
.onSuccess(v -> log.info("Database initialized successfully"))
.onFailure(err -> {
log.error("Failed to initialize database", err);
startPromise.fail(err);
return;
});
db = new DataBaseService(vertx, config.database);
redis = new RedisService(vertx, config.redis);
// Инициализация сервисов
userService = new UserService(db.getPool());
// Инициализация БД (создание таблицы users)
userService.initDatabase()
.onSuccess(v -> log.info("Database initialized successfully"))
.onFailure(err -> {
log.error("Failed to initialize database", err);
startPromise.fail(err);
return;
});
Router router = initRouter();
startHttp(router, startPromise);
})
.onFailure(startPromise::fail);
}
private Router initRouter() {
// Настройка сессий (используем LocalSessionStore для простоты)
SessionStore sessionStore = LocalSessionStore.create(vertx);
@@ -95,27 +105,8 @@ public class MainVerticle extends AbstractVerticle {
});
// Health Checks
HealthChecks hc = HealthChecks.create(vertx);
hc.register("database", promise ->
dbPool.getConnection().onComplete(ar -> {
if (ar.succeeded()) {
ar.result().close();
promise.complete(Status.OK());
} else {
promise.fail(ar.cause());
}
})
);
router.get("/health").handler(rc ->
hc.checkStatus().onComplete(ar -> {
if (ar.succeeded()) {
rc.response().end(ar.result().toJson().encodePrettily());
} else {
rc.response().setStatusCode(503).end(ar.cause().getMessage());
}
})
);
HealthCheckService healthCheckService = new HealthCheckService(vertx, redis, db);
healthCheckService.registerHealthCheck(router);
// API маршруты
AuthHandler authHandler = new AuthHandler(userService);
@@ -169,26 +160,37 @@ public class MainVerticle extends AbstractVerticle {
.setCachingEnabled(false)
.setIndexPage("index.html"));
// Запуск HTTP сервера
int port = config.getInteger("http_port");
vertx.createHttpServer()
.requestHandler(router)
.listen(port).onComplete(http -> {
if (http.succeeded()) {
log.info("HTTP server started on port {}", port);
startPromise.complete();
} else {
log.error("Failed to start HTTP server", http.cause());
startPromise.fail(http.cause());
}
return router;
}
private void startHttp(Router router, Promise<Void> startPromise) {
// Запуск HTTP-сервера
httpServer = vertx.createHttpServer();
httpServer.requestHandler(router).listen(config.server.port, config.server.host)
.onSuccess(server -> {
log.info("HTTP server started on port {}", server.actualPort());
startPromise.complete();
})
.onFailure(throwable -> {
log.error(throwable.getMessage());
startPromise.fail(throwable);
});
}
@Override
public void stop(Promise<Void> stopPromise) {
if (dbPool != null) {
dbPool.close();
}
stopPromise.complete();
this.httpServer.close()
.onSuccess(server -> {
log.info("Stop HTTP server");
this.db.disconnect();
this.redis.disconnect();
this.vertx.close()
.onSuccess(vertx -> {
log.info("Stop Vert.x");
stopPromise.complete();
})
.onFailure(throwable -> log.info(throwable.getMessage()));
})
.onFailure(throwable -> log.info(throwable.getMessage()));
}
}