초기커밋
This commit is contained in:
26
BrokerApiCore/Meta/BrokerApiMetaDataManager.cs
Normal file
26
BrokerApiCore/Meta/BrokerApiMetaDataManager.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace BrokerCore.Meta;
|
||||
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
public class MetaDataReloadScheduler : BackgroundService
|
||||
{
|
||||
const int m_reload_interval_min = 1;
|
||||
private readonly BrokerApiMetaLoader m_broker_api_meta_data_loader;
|
||||
|
||||
public MetaDataReloadScheduler(BrokerApiMetaLoader brokerApiMetaDataLoader)
|
||||
{
|
||||
m_broker_api_meta_data_loader = brokerApiMetaDataLoader;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
using var timer = new PeriodicTimer(TimeSpan.FromMinutes(m_reload_interval_min));
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
// TODO: 버전 관리 이슈를 먼저 해결할 후에 사용할 것
|
||||
// m_broker_api_meta_data_loader.load();
|
||||
await timer.WaitForNextTickAsync(stoppingToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
260
BrokerApiCore/Meta/BrokerMetaDataManager.cs
Normal file
260
BrokerApiCore/Meta/BrokerMetaDataManager.cs
Normal file
@@ -0,0 +1,260 @@
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
public class BrokerMetaTable
|
||||
{
|
||||
public string Version { get; private set; }
|
||||
private readonly MetaTable m_meta_table = new MetaTable();
|
||||
|
||||
public ProductMetaTable ProductMetaTable => m_meta_table.ProductMetaTable;
|
||||
|
||||
// TODO: PlanetItemExchangePolicyMetaTable를 PlanetItemExchangePolicyTable로 이름 변경
|
||||
public PlanetItemExchangePolicyMetaTable PlanetItemExchangePolicyMetaTable => m_meta_table.PlanetItemExchangePolicyMetaTable;
|
||||
public SystemMailMetaTable SystemMailMetaTable => m_meta_table.SystemMailMetaTable;
|
||||
public ItemMetaTable ItemMetaTable => m_meta_table.ItemMetaTable;
|
||||
public TextStringMetaTable TextStringMetaTable => m_meta_table.TextStringMetaTable;
|
||||
|
||||
public BrokerMetaTable(MetaTable? source = null, string? versionName = null)
|
||||
{
|
||||
if (source != null)
|
||||
{
|
||||
m_meta_table = source;
|
||||
Version = versionName ?? Guid.NewGuid().ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class BrokerApiMetaLoader : IDisposable
|
||||
{
|
||||
readonly string m_input_path = "resource/meta";
|
||||
|
||||
// 스레드 세이프한 딕셔너리로 변경
|
||||
private readonly ConcurrentDictionary<string, BrokerMetaTable> m_meta_tables =
|
||||
new ConcurrentDictionary<string, BrokerMetaTable>();
|
||||
|
||||
// 더 세밀한 제어가 필요한 경우를 위한 ReaderWriterLockSlim 추가
|
||||
private readonly ReaderWriterLockSlim m_lock = new ReaderWriterLockSlim();
|
||||
|
||||
// 기본 메타테이블 캐싱
|
||||
private BrokerMetaTable m_default_meta_table;
|
||||
|
||||
public Result load(string? dataPath = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_lock.EnterWriteLock();
|
||||
|
||||
// 기본 메타 테이블 로드
|
||||
var (result, meta_table) = loadMetaData(dataPath);
|
||||
if (result.isFail() || meta_table == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (m_meta_tables.TryAdd(meta_table.Version, meta_table))
|
||||
{
|
||||
m_default_meta_table = meta_table;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_lock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
private (Result, BrokerMetaTable?) loadMetaData(string? dataPath = null, string? versionName = null)
|
||||
{
|
||||
var result = new Result();
|
||||
var input_path = dataPath ?? m_input_path;
|
||||
try
|
||||
{
|
||||
var full_path = Path.GetFullPath(input_path, Environment.CurrentDirectory);
|
||||
if (!Directory.Exists(full_path))
|
||||
{
|
||||
full_path = Path.GetFullPath(input_path, AppContext.BaseDirectory);
|
||||
if (!Directory.Exists(full_path))
|
||||
{
|
||||
result.setFail(ServerErrorCode.MetaDataLoadFailed, $"Meta data path not found: {input_path}");
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
|
||||
var meta_table = new MetaTable();
|
||||
meta_table.loadForBrokerApi(full_path);
|
||||
|
||||
var errors = new ValidatorErrorCollection();
|
||||
foreach (var data in meta_table.PlanetItemExchangePolicyMetaTable.PlanetItemExchangePolicyDataList)
|
||||
{
|
||||
validate(data, meta_table, errors);
|
||||
}
|
||||
if (errors.HasError)
|
||||
{
|
||||
errors.log();
|
||||
}
|
||||
|
||||
//TODO: ProductMetaTable, SystemMailMetaTable, ItemMetaTable 에 대한 검사도 필요하다.
|
||||
var broker_meta_table = new BrokerMetaTable(meta_table, versionName);
|
||||
return (result, broker_meta_table);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.setFail(ServerErrorCode.MetaDataLoadFailed, $"Meta data load failed => {ex.Message}");
|
||||
}
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
public BrokerMetaTable getMetaTable(string? versionName = null!)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_lock.EnterReadLock();
|
||||
|
||||
if (string.IsNullOrEmpty(versionName) || versionName == "default")
|
||||
{
|
||||
return m_default_meta_table;
|
||||
}
|
||||
|
||||
return m_meta_tables.GetValueOrDefault(versionName, m_default_meta_table);
|
||||
|
||||
// 요청된 버전이 없으면 기본 메타테이블 반환
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_lock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
private ValidatorErrorCollection validate(PlanetItemExchangePolicyMetaData planetItemExchange, MetaTable metaTable, ValidatorErrorCollection errors)
|
||||
{
|
||||
checkValidCaliverseItem(planetItemExchange);
|
||||
checkValidPlanetItem(planetItemExchange);
|
||||
return errors;
|
||||
|
||||
void checkValidPlanetItem(PlanetItemExchangePolicyMetaData data)
|
||||
{
|
||||
var planet_item_type = toEnum(data.PlanetItemType, PlanetItemType.None);
|
||||
switch (planet_item_type)
|
||||
{
|
||||
case PlanetItemType.Igm26Currency:
|
||||
{
|
||||
var currency_type = toEnum(data.PlanetItemId, PlanetCurrencyType.None);
|
||||
if (currency_type == PlanetCurrencyType.None)
|
||||
{
|
||||
addError(nameof(data.PlanetItemId),
|
||||
$"Planet 화폐 타입이 잘못되었습니다 => PlanetItemId:{data.PlanetItemId}");
|
||||
}
|
||||
|
||||
// if (data.PlanetItemAmount >= 0)
|
||||
// {
|
||||
// // 재화는 차감만 가능
|
||||
// addError(nameof(data.PlanetItemAmount),
|
||||
// $"Planet 화폐 수량은 양수 합니다 => PlanetItemAmount:{data.PlanetItemAmount}");
|
||||
// }
|
||||
|
||||
break;
|
||||
}
|
||||
case PlanetItemType.Igm26Quest:
|
||||
break;
|
||||
case PlanetItemType.None:
|
||||
default:
|
||||
addError(nameof(data.PlanetItemId),
|
||||
$"Planet 화폐 타입이 잘못되었습니다 => PlanetItemId:{data.PlanetItemId}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void checkValidCaliverseItem(PlanetItemExchangePolicyMetaData data)
|
||||
{
|
||||
var caliverse_item_type = toEnum(data.CaliverseItemType, CaliverseItemType.None);
|
||||
switch (caliverse_item_type)
|
||||
{
|
||||
case CaliverseItemType.Currency:
|
||||
{
|
||||
var currency_type = toEnum(data.CaliverseItemId, CurrencyType.None);
|
||||
if (currency_type == CurrencyType.None)
|
||||
{
|
||||
addError(nameof(data.CaliverseItemId),
|
||||
$"Caliverse 화폐 타입이 잘못되었습니다 => CaliverseItemId:{data.CaliverseItemId}");
|
||||
}
|
||||
|
||||
// if (data.CaliverseItemAmount >= 0)
|
||||
// {
|
||||
// // 재화는 차감만 가능
|
||||
// addError(nameof(data.CaliverseItemAmount),
|
||||
// $"Caliverse 화폐 수량은 음수여야 합니다 => CaliverseItemAmount:{data.CaliverseItemAmount}");
|
||||
// }
|
||||
|
||||
break;
|
||||
}
|
||||
case CaliverseItemType.CaliverseProduct:
|
||||
{
|
||||
var product_id = Convert.ToInt32(data.CaliverseItemId);
|
||||
if (metaTable.ProductMetaTable.ProductMetaDataListbyId.ContainsKey(product_id) == false)
|
||||
{
|
||||
addError(nameof(data.CaliverseItemId),
|
||||
$"CaliverseItemId이 존재하지 않습니다 => CaliverseItemId: {data.CaliverseItemId}");
|
||||
}
|
||||
|
||||
if (data.CaliverseItemAmount < 0)
|
||||
{
|
||||
addError(nameof(data.CaliverseItemAmount),
|
||||
$"Product 수량은 0보다 커야합니다 => CaliverseItemAmount:{data.CaliverseItemAmount}");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case CaliverseItemType.None:
|
||||
default:
|
||||
{
|
||||
addError(nameof(data.CaliverseItemType),
|
||||
$"Caliverse 아이템 타입이 잘못되었습니다 => CaliverseItemType:{data.CaliverseItemType}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addError(string variableName, string msg)
|
||||
{
|
||||
errors.add($"Invalid PlanetItemExchangePolicyMetaData Value: {variableName} - {msg}");
|
||||
}
|
||||
|
||||
TEnum toEnum<TEnum>(string enumTypeString, TEnum defaultValue) where TEnum : struct, Enum
|
||||
{
|
||||
var enum_type_string_result = enumTypeString.Replace("_", "");
|
||||
return Enum.TryParse<TEnum>(enum_type_string_result, ignoreCase: true, out var enum_type)
|
||||
? enum_type
|
||||
: defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
// 리소스 해제를 위한 Dispose 패턴 구현
|
||||
private bool m_disposed = false;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!m_disposed)
|
||||
{
|
||||
m_lock.Dispose();
|
||||
m_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 최신 메타테이블을 참조하는 클래스
|
||||
public class BrokerMetaTableRef
|
||||
{
|
||||
public BrokerMetaTable MetaTable => m_meta_table;
|
||||
private readonly BrokerMetaTable m_meta_table;
|
||||
|
||||
public BrokerMetaTableRef(BrokerMetaTable metaTable)
|
||||
{
|
||||
m_meta_table = metaTable;
|
||||
}
|
||||
}
|
||||
23
BrokerApiCore/Meta/PlanetItemExchangePolicy.cs
Normal file
23
BrokerApiCore/Meta/PlanetItemExchangePolicy.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
// namespace BrokerCore.Meta;
|
||||
//
|
||||
// public class PlanetItemExchangePolicy
|
||||
// {
|
||||
// // ID
|
||||
// // PlanetId
|
||||
// // CaliverseItemType
|
||||
// // CaliverseItemId
|
||||
// // CaliverseItemAmount
|
||||
// // PlanetItemType
|
||||
// // PlanetItemId
|
||||
// // PlanetItemAmount
|
||||
// // Description
|
||||
//
|
||||
// public string? Id { get; set; }
|
||||
// public string? PlanetId { get; set; }
|
||||
// public string? CaliverseItemType { get; set; }
|
||||
// public string? CaliverseItemId { get; set; }
|
||||
// public long CaliverseItemAmount { get; set; }
|
||||
// public string? PlanetItemType { get; set; }
|
||||
// public string? PlanetItemId { get; set; }
|
||||
// public long PlanetItemAmount { get; set; }
|
||||
// }
|
||||
Reference in New Issue
Block a user