Files
caliverse_server/BrokerApiServer/Extensions/AppBuilderExtensions.cs
2025-11-28 16:54:56 +09:00

317 lines
9.9 KiB
C#

using System.Text;
using BrokerApiCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using ServerBase;
using ServerCore;
namespace BrokerApiServer;
public static class AppBuilderExtensions
{
public static void initGlobalNlog()
{
Log.initLog(nameof(ServerType.BrokerApi), "Developer"); // nlog 설정
Log.getLogger().info("NLog Init");
}
public static ServerConfigMetaverseBroker initBrokerServerConfig()
{
// 서버 설정
var server_config = new ServerConfigMetaverseBroker();
var server_config_path = "./Config/ServerConfig.json";
var full_path = Path.GetFullPath(server_config_path);
if (!File.Exists(full_path))
{
full_path = Path.GetFullPath(server_config_path, AppContext.BaseDirectory);
if (!File.Exists(full_path))
{
throw new ApplicationException("ServerConfig.json 파일을 찾을 수 없음");
}
}
server_config.setConfigFilePath(full_path);
var result = server_config.tryLoadConfig().GetAwaiter().GetResult();
Guard.Against.resultFail(result);
return server_config;
}
public static void addCoreServices(this IServiceCollection services,
ServerConfigMetaverseBroker serverConfig)
{
services.AddSingleton(serverConfig);
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey =
new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(serverConfig.MetaverseBroker?.JwtSecretKey ?? String.Empty))
};
});
services.AddScoped<UserAuthService>();
services.addExchangeServices();
// 메타데이터 관련 서비스 등록
services.AddSingleton<BrokerApiMetaLoader>();
services.AddScoped<BrokerMetaTableRef>(provider =>
{
var meta_loader = provider.GetRequiredService<BrokerApiMetaLoader>();
return new BrokerMetaTableRef(meta_loader.getMetaTable());
});
services.AddHostedService<MetaDataReloadScheduler>();
var jwt_option = new JwtOption
{
Secret = serverConfig.MetaverseBroker?.JwtSecretKey ?? String.Empty,
TokenValidityInMinutes = serverConfig.MetaverseBroker?.ExpireMinutes ?? 1
};
services.AddSingleton(jwt_option);
services.AddScoped<JwtGenerator>(provider => { return new JwtGenerator(jwt_option); });
services.AddScoped<JwtParser>(provider => { return new JwtParser(jwt_option); });
services.AddScoped<PlanetService>();
// 미들웨어 설정
services.AddScoped<ResultLoggingMiddleware>();
}
public static void addInfraServices(this IServiceCollection services, ServerConfigMetaverseBroker serverConfig)
{
// 코어 리파지토리 서비스 설정
services.AddScoped<SsoAccountRepo>();
services.AddScoped<PlanetInfoRepo>();
services.AddScoped<PlanetItemExchangeOrderRepo>();
services.AddScoped<PlanetItemExchangeOrderAmountTotalLimitRepo>();
services.AddScoped<PlanetItemExchangeOrderAmountUserLimitRepo>();
services.AddSingleton<DynamoDbClient>();
services.AddDbContext<SsoAccountDbContext>(options =>
{
var connection_string = serverConfig.SsoAccountDb;
options.UseMySql(connection_string, ServerVersion.AutoDetect(connection_string), mySqlOptions =>
{
mySqlOptions.EnableRetryOnFailure(
maxRetryCount: 10,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null
);
mySqlOptions.CommandTimeout(60);
mySqlOptions.MaxBatchSize(20);
});
});
services.AddDbContext<MetaverseBrokerDbContext>(options =>
{
var connection_string = serverConfig.MetaverseBroker?.MetaverseBrokerDb;
options.UseMySql(connection_string, ServerVersion.AutoDetect(connection_string), mySqlOptions =>
{
mySqlOptions.EnableRetryOnFailure(
maxRetryCount: 10,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null
);
mySqlOptions.CommandTimeout(60);
mySqlOptions.MaxBatchSize(20);
});
});
}
public static void brokerServerLogicInit(this IApplicationBuilder app)
{
var server_logic = app.ApplicationServices.GetRequiredService<IServerLogic>() as BrokerServerLogic;
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"BrokerServerLogic is null");
server_logic.onInit().Wait();
}
public static void metadataMangerInit(this IApplicationBuilder app, string? dataPath = null)
{
var meta_loader = app.ApplicationServices.GetRequiredService<BrokerApiMetaLoader>();
var result = meta_loader.load(dataPath);
if (result.isFail())
{
Log.getLogger().error($"MetaDataManager Init Failed => {result}");
throw new ApplicationException($"MetaDataManager Init Failed => {result}");
}
}
public static void validateRepoConnections(this IApplicationBuilder app)
{
// db 접속 유무 검사
using var scope = app.ApplicationServices.CreateScope();
var services = scope.ServiceProvider;
try
{
validateSsoAccountDb().Wait();
validateMetaverseBrokerDb().Wait();
// 마이그레이션은 코드에서 호출하지 말고, 별도의 migration script를 통해서 수행한다.
migrateMetaverseBrokerDbForDevelopment().Wait();
}
catch (Exception ex)
{
Log.getLogger().error($"[Check Tunneling] Repo Connections Validation Failed => {ex.Message}");
throw new ApplicationException($"Repo Connections Validation Failed => {ex.Message}");
}
return;
async Task validateSsoAccountDb()
{
try
{
var context = services.GetRequiredService<SsoAccountDbContext>();
if (await context.Database.CanConnectAsync())
{
Log.getLogger().info($"Sso Account DB Connection OK => {context.Database.GetConnectionString()}");
return;
}
Log.getLogger().error($"Sso Account DB Connection Failed => {context.Database.GetConnectionString()}");
}
catch (Exception ex)
{
Log.getLogger()
.error(
$"Sso Account DB Connection Failed => {ex.Message}");
}
// throw new ApplicationException($"Failed to connect Sso Account Db !!!");
}
async Task validateMetaverseBrokerDb()
{
try
{
var context = services.GetRequiredService<MetaverseBrokerDbContext>();
if (await context.Database.CanConnectAsync())
{
Log.getLogger()
.info($"Metaverse-Broker DB Connection OK => {context.Database.GetConnectionString()}");
var pending_migrations = await context.Database.GetPendingMigrationsAsync();
var migrations = pending_migrations as string[] ?? pending_migrations.ToArray();
if (migrations.Any())
{
Log.getLogger().error($"{context.Database.ToString()} 마이그레션이 필요함 !!!");
migrations.Select(x => x.ToString()).ToList().ForEach(x => Log.getLogger().warn(x));
}
return;
}
}
catch (Exception ex)
{
Log.getLogger()
.error($"Metaverse-Broker DB 접속 예외 발생 => {ex.Message}");
}
throw new ApplicationException($"Failed to connect Broker Db !!!");
}
async Task migrateMetaverseBrokerDbForDevelopment()
{
// if (!env.IsDevelopment())
// {
// return;
// }
var context = services.GetRequiredService<MetaverseBrokerDbContext>();
try
{
await context.Database.MigrateAsync();
}
catch (Exception ex)
{
Log.getLogger().error($"Metaverse-Broker DB Migrate 실패 => {ex.Message}");
}
}
}
public static void addDynamoDb(this IServiceCollection services)
{
services.AddSingleton<DynamoDbClient>(x =>
{
var dynamo_db_client = new DynamoDbClient();
return dynamo_db_client;
// var result = new Result();
// var config = x.GetRequiredService<ServerConfig>();
//
// (var error_code, var table_names) =
// ServerConfigHelper.getDynamoDbTableNamesWithServiceType(config.ServiceType);
// if (error_code.isFail())
// {
// var err_msg =
// $"Failed to DynamoDbClient.getDynamoDbTableNameWithServiceType() !!! : {config.toBasicString()}";
// result.setFail(error_code, err_msg);
// Log.getLogger().error(err_msg);
// Guard.Against.resultFail(result);
// }
//
// var dynamo_db_client = new DynamoDbClient();
// var dynamodb_url = config.Dynamodb;
// var region = config.AWS.Region;
// var access_key = config.AWS.AccessKey;
// var secret_key = config.AWS.SecretKey;
// var use_local_db = config.AWS.LocalDynamoDB;
// if (result.isFail())
// {
// Log.getLogger().error($"Failed to connectToDb !!! ");
// Guard.Against.resultFail(result);
// }
//
// dynamo_db_client.connectToDb(table_names, use_local_db, dynamodb_url, access_key, secret_key, region);
// return dynamo_db_client;
});
}
public static void useDynamoDb(this IApplicationBuilder app)
{
var result = new Result();
var config = app.ApplicationServices.GetRequiredService<ServerConfig>();
(var error_code, var table_names) =
ServerConfigHelper.getDynamoDbTableNamesWithServiceType(config.ServiceType);
if (error_code.isFail())
{
var err_msg =
$"Failed to DynamoDbClient.getDynamoDbTableNameWithServiceType() !!! : {config.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
Guard.Against.resultFail(result);
}
var dynamo_db_client = app.ApplicationServices.GetRequiredService<DynamoDbClient>();
var dynamodb_url = config.Dynamodb;
var region = config.AWS.Region;
var access_key = config.AWS.AccessKey;
var secret_key = config.AWS.SecretKey;
var use_local_db = config.AWS.LocalDynamoDB;
result = dynamo_db_client.connectToDb(table_names, use_local_db, dynamodb_url, access_key, secret_key, region);
if (result.isFail())
{
Log.getLogger().error($"Failed to connectToDb !!! ");
Guard.Against.resultFail(result);
}
var task = dynamo_db_client.createDBIfNotExists(false);
task.Wait();
if (false == task.Result)
{
var err_msg = $"Failed to create DB Table !!!";
result.setFail(ServerErrorCode.DynamoDbTableCreateFailed, err_msg);
Guard.Against.resultFail(result);
}
}
}