초기커밋

This commit is contained in:
2025-05-01 07:20:41 +09:00
commit 98bb2e3c5c
2747 changed files with 646947 additions and 0 deletions

View File

@@ -0,0 +1,53 @@

using ServerCore;
using ServerBase;
namespace ServerCommon;
public enum EchoSystemMethod
{
None = 0,
Get = 1,
Put = 2,
Delete = 3,
Post = 4
}
public static class EchoSystemHelper
{
public const int DoubleCalculateDigitsLong = 100;
public static void checkDeltaDouble(this CaliumEventRequest request)
{
request.m_calium_delta = checkDouble(request.m_calium_delta);
request.m_sapphire_delta = checkDouble(request.m_sapphire_delta);
}
public static HttpRequestMessage makeRequestMessage(EchoSystemMethod method, string urlPath)
{
var http_method = getMethod(method);
NullReferenceCheckHelper.throwIfNull(http_method);
var request = new HttpRequestMessage(http_method, urlPath);
return request;
}
private static double checkDouble(double delta)
{
var delta_long = (long)(delta * DoubleCalculateDigitsLong);
return delta_long / (double)DoubleCalculateDigitsLong;
}
private static HttpMethod? getMethod(EchoSystemMethod method)
{
return method switch
{
EchoSystemMethod.Get => new HttpMethod("GET"),
EchoSystemMethod.Put => new HttpMethod("PUT"),
EchoSystemMethod.Delete => new HttpMethod("DELETE"),
EchoSystemMethod.Post => new HttpMethod("POST"),
_ => null
};
}
}

View File

@@ -0,0 +1,219 @@
using System.Text;
using Newtonsoft.Json;
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
namespace ServerCommon;
public class EchoSystemRequester
{
private readonly HttpClient m_httpClient;
private readonly HttpClient? m_slackClient;
private const int DefaultTimeOutMs = 30_000;
private const string m_get_rollup_by_date_url_base = "/web/v3/rollup/ymd";
private const string m_get_rollup_by_epoch_url_base = "/web/v3/rollup/seq";
private const string m_post_calium_event_url = "/web/v3/circ_event";
private const string m_post_calium_event_time_url = "/web/v3/circ_event_time";
private const string m_get_acc_volume_url = "/web/v3/converter/acc_volume";
private readonly string m_server_name;
private readonly string m_ip_port;
public EchoSystemRequester(string baseAddress, string? serverName = null, string? ipPort = null, string? errorSlackAddress = null)
{
m_server_name = serverName ?? "None" ;
m_ip_port = ipPort ?? "None";
m_httpClient = new HttpClient
{
BaseAddress = new Uri(baseAddress),
Timeout = TimeSpan.FromMilliseconds(DefaultTimeOutMs)
};
if (!string.IsNullOrEmpty(errorSlackAddress))
{
m_slackClient = new HttpClient
{
BaseAddress = new Uri(errorSlackAddress),
Timeout = TimeSpan.FromMilliseconds(DefaultTimeOutMs)
};
}
}
public async Task<Result> checkWeb3Connection()
{
var res = await getConverterSyncData();
if (res.result.isFail() && res.response == null) return res.result;
return new Result();
}
public async Task<(Result result, CaliumRollUpResponse? response)> getDailyRollUpData(int epoch)
{
var result = new Result();
if (epoch <= 0)
{
var err_msg = $"fail to get daily roll up data !!! : epoch is zero - {epoch}";
result.setFail(ServerErrorCode.FailToSendEchoSystem, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
var url_path = $"{m_get_rollup_by_epoch_url_base}/{epoch}";
return await getDailyRollUpData(url_path);
}
public async Task<(Result result, CaliumRollUpResponse? response)> getDailyRollUpData(DateTime epochDate)
{
var url_path = $"{m_get_rollup_by_date_url_base}/{epochDate:yyyyMMdd}";
return await getDailyRollUpData(url_path);
}
public async Task<(Result result, ConverterSyncResponse? response)> getConverterSyncData()
{
var request = EchoSystemHelper.makeRequestMessage(EchoSystemMethod.Get, m_get_acc_volume_url);
Log.getLogger().debug($"EchoSystemRequester Request: url[{request.RequestUri}]");
var response = await sendHttpRequest<ConverterSyncResponse>(request);
return response;
}
public async Task<(Result result, CaliumEventResponse? response)> postCaliumEvent(CaliumEventRequest data)
{
var request = EchoSystemHelper.makeRequestMessage(EchoSystemMethod.Post, m_post_calium_event_time_url);
data.m_event_time = DateTimeHelper.Current.toStringWithUtcIso8601();
var body = JsonConvert.SerializeObject(data);
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
Log.getLogger().debug($"EchoSystemRequester Request: url[{request.RequestUri}] - content[{body}");
var response = await sendHttpRequest<CaliumEventResponse>(request);
return response;
}
private async Task sendEchoSystemSlackMessage(HttpRequestMessage request, string errMsg)
{
if (null == m_slackClient) return;
var title = getEchoSystemType(request.RequestUri!.ToString());
var slack_msg_builder = new EchoSystemSlackMessageBuilder(title, m_server_name, m_ip_port);
slack_msg_builder.appendValue("URI", $"{m_httpClient.BaseAddress}{request.RequestUri}");
if (null != request.Content)
{
slack_msg_builder.appendValue("Param", await request.Content.ReadAsStringAsync(), true);
}
slack_msg_builder.appendValue("ERROR", errMsg, true);
var req = EchoSystemHelper.makeRequestMessage(EchoSystemMethod.Post, "");
var content = slack_msg_builder.build();
req.Content = new StringContent(content);
try
{
Log.getLogger().debug($"EchoSystemRequester Slack Message Request: url[{m_slackClient.BaseAddress}] - content[{content}");
var res = await m_slackClient.SendAsync(req);
var res_content = await res.Content.ReadAsStringAsync();
Log.getLogger().debug($"EchoSystemRequester Slack Message Response: url[{m_slackClient.BaseAddress}] - content[{res_content}");
}
catch (Exception e)
{
var err_msg = $"EchoSystemRequester Slack Message Exception!!: {e}";
Log.getLogger().error(err_msg);
}
}
private static string getEchoSystemType(string uri)
{
return uri switch
{
m_get_rollup_by_epoch_url_base or m_get_rollup_by_date_url_base => "롤업 데이터 조회",
m_post_calium_event_url => "유통량 적재",
m_get_acc_volume_url => "롤업 동기화 조회",
_ => string.Empty
};
}
private async Task<(Result result, CaliumRollUpResponse? response)> getDailyRollUpData(string urlPath)
{
var request = EchoSystemHelper.makeRequestMessage(EchoSystemMethod.Get, urlPath);
Log.getLogger().debug($"EchoSystemRequester Request: url[{request.RequestUri}]");
var response = await sendHttpRequest<CaliumRollUpResponse>(request);
return response;
}
private async Task<(Result, TResponse?)> sendHttpRequest<TResponse>(HttpRequestMessage request) where TResponse : EchoSystemBaseResponse
{
var result = new Result();
try
{
var response = await m_httpClient.SendAsync(request, new CancellationToken());
if (response.IsSuccessStatusCode == false)
{
var err_msg = $"failed to get {nameof(TResponse)} data !!! : response error[{response.StatusCode}]";
result.setFail(ServerErrorCode.FailToGetEchoSystemHttpError, err_msg);
Log.getLogger().error(result.toBasicString());
await sendEchoSystemSlackMessage(request, err_msg);
return (result, null);
}
var content = await response.Content.ReadAsStringAsync();
Log.getLogger().debug($"EchoSystemRequester Response: url[{request.RequestUri}] - content[{content}]");
var msg = JsonConvert.DeserializeObject<TResponse>(content);
if (null == msg)
{
var err_msg = $"failed to get {nameof(TResponse)} data !!! - response message is null !!!";
result.setFail(ServerErrorCode.FailToGetEchoSystemMessageNull, err_msg);
Log.getLogger().error(result.toBasicString());
await sendEchoSystemSlackMessage(request, err_msg);
return (result, null);
}
var check_response = checkEchoSystemResponse<TResponse>(msg);
return (check_response, msg);
}
catch (Exception e)
{
var err_msg = $"failed to get EchoSystemRequester response !!! : exception - {e}";
result.setFail(ServerErrorCode.FailToGetEchoSystemException, err_msg);
Log.getLogger().error(result.toBasicString());
await sendEchoSystemSlackMessage(request, e.ToString());
return (result, null);
}
}
private Result checkEchoSystemResponse<T>(EchoSystemBaseResponse response)
{
var result = new Result();
if (false == response.m_success || !string.IsNullOrEmpty(response.m_code))
{
var err_msg = $"response is failed !!! : {nameof(T)} - {response.m_code ?? string.Empty}";
result.setFail(ServerErrorCode.GetFailEchoSystemResponse, err_msg);
Log.getLogger().error(result.toBasicString());
}
return result;
}
}

View File

@@ -0,0 +1,20 @@
using Newtonsoft.Json;
namespace ServerCommon;
public enum CaliumEventType
{
none = 0,
calium_get = 1,
extra_get = 2,
calium_burn = 3
}
public class CaliumEventRequest : CaliumEventData
{
// ?????
[JsonProperty("monitor_log_test")]
public bool m_monitor_log_test { get; set; }
}

View File

@@ -0,0 +1,21 @@
using Newtonsoft.Json;
namespace ServerCommon;
public class CaliumEventResponse : EchoSystemBaseResponse
{
[JsonProperty("data")]
public EchoEventData? m_data { get; set; } = new();
}
public class EchoEventData
{
// 등록 Id
[JsonProperty("_id")]
public string? m_id { get; set; }
// 등록 시간
[JsonProperty("create_time")]
public DateTime? m_create_time { get; set; }
}

View File

@@ -0,0 +1,107 @@
using Newtonsoft.Json;
namespace ServerCommon;
public class CaliumRollUpResponse : EchoSystemBaseResponse
{
[JsonProperty("data")]
public List<RollUpData>? m_list { get; set; } = new();
}
public class RollUpData
{
// Epoch 값
[JsonProperty("seq")] public int m_epoch { get; set; }
// 회차 적용 날짜 ( yyyyMMdd )
[JsonProperty("ymd")] public int m_date { get; set; }
// 교환소 총 발행량
[JsonProperty("calium_exchange_volume")] public double m_exchange_volume { get; set; }
// 컨버터 배정 수량
[JsonProperty("calium_convertor_volume")] public double m_convertor_volume { get; set; }
// 재원저장소 적재량 ( 교환소 )
[JsonProperty("calium_get_repository_volume")] public double m_exchange_repo_volume { get; set; }
// 재원저장소 적재량 ( 교환소 외 )
[JsonProperty("extra_get_repository_volume")] public double m_extra_exchange_repo_volume { get; set; }
// 적재량 합계
[JsonProperty("total_repository_volume")] public double m_total_repo_volume { get; set; }
// 차감 수량
[JsonProperty("repo_confirm_total_amount")] public double m_confirm_total_amount { get; set; }
// 재원저장소 적재량(누적)
[JsonProperty("stack_repository_count")] public double m_stack_repo_count { get; set; }
// 당일 발행량 합계
[JsonProperty("total_today_get_volume")] public double m_today_total_volume { get; set; }
// 타입별 당일 소각량 합계
[JsonProperty("total_today_calium_burn")]
public Dictionary<string, double> m_today_total_burn { get; set; } = new();
// 당일 소각량 합계
[JsonProperty("total_today_burn_volume")] public double m_today_total_burn_volume { get; set; }
// 당일 유통 공급량
[JsonProperty("total_today_circ_volume")] public double m_today_total_circ_volume { get; set; }
// 누적 발행량
[JsonProperty("stack_volume")] public double m_stack_volume { get; set; }
// 교환 가중치
[JsonProperty("swap_rate")] public double m_daily_inflation_rate { get; set; }
// 롤업 트랜젝션 상태
[JsonProperty("tx_state_info")] public RollUpState m_rollup_state { get; set; } = new();
// 생성일자
[JsonProperty("create_time")] public DateTime m_create_time { get; set; }
// 갱신일자
[JsonProperty("update_time")] public DateTime m_update_time { get; set; }
// Web2 롤업 여부 (최초 롤업)
[JsonProperty("is_web2_data")] public bool m_is_web2_data { get; set; }
// 지연확정 여부
[JsonProperty("is_delay_confirm")] public bool m_is_delay_confirm { get; set; }
// 전일자 롤업 필드 캐시
[JsonProperty("previous")] public PreviousRollUpData m_previous_roll_up { get; set; } = new();
// 컨버터 배정 누적 수량
[JsonProperty("stack_convertor_volume")] public double m_stack_converter_volume { get; set; }
// 기본 배정 물량
[JsonProperty("standard_alloc_amount")] public double m_standard_alloc_amount { get; set; }
// ObjectId
[JsonProperty("ccvid")] public string m_ccv_id { get; set; } = string.Empty;
// 컨버터 변환율
[JsonProperty("converter_pod_rate")] public double m_daily_converter_rate { get; set; }
}
public class RollUpState
{
// Pending 결과 : string.Empty - 전송대기 / pending - 결과 대기 / success - 성공
[JsonProperty("state")] public string m_state { get; set; } = string.Empty;
// 트랜젝션 id
[JsonProperty("hash")] public string m_hash { get; set; } = string.Empty;
}
public class PreviousRollUpData
{
[JsonProperty("total_today_circ_volume")] public double m_today_total_circ_volume { get; set; }
[JsonProperty("stack_volume")] public double m_stack_volume { get; set; }
[JsonProperty("swap_rate")] public double m_daily_inflation_rate { get; set; }
[JsonProperty("stack_convertor_volume")] public double m_stack_converter_volume { get; set; }
[JsonProperty("missing_volume")] public double m_missing_volume { get; set; }
}

View File

@@ -0,0 +1,26 @@
using Newtonsoft.Json;
namespace ServerCommon;
public class ConverterSyncResponse : EchoSystemBaseResponse
{
[JsonProperty("data")]
public ConverterSyncData? m_sync { get; set; } = new();
}
public class ConverterSyncData
{
// 현재까지 제공된 Epoch 값
[JsonProperty("seq")]
public int m_epoch { get; set; }
// 현재까지 제공된 회차 날짜 ( yyyyMMdd )
[JsonProperty("ymd")]
public int m_date { get; set; }
// 현재까지 제공된 칼리움 컨버터 총 누적 수량
[JsonProperty("acc_volume")]
public double m_stack_calium { get; set; }
}

View File

@@ -0,0 +1,16 @@
using Newtonsoft.Json;
namespace ServerCommon;
public class EchoSystemBaseResponse
{
[JsonProperty("success")]
public bool m_success { get; set; }
[JsonProperty("code")]
public string? m_code { get; set; }
[JsonProperty("message")]
public List<string>? m_messages { get; set; }
}

View File

@@ -0,0 +1,62 @@
using Newtonsoft.Json;
namespace ServerCommon;
public class EchoSystemSlackMessage
{
[JsonProperty("text")] public string Text { get; set; } = string.Empty;
}
public class EchoSystemSlackMessageBuilder
{
private EchoSystemSlackMessage m_message { get; set; } = new();
private string m_title { get; set; }
private string m_server_name { get; set; }
private string m_ip_port { get; set; }
private Dictionary<string, string> m_members { get; set; } = new();
public EchoSystemSlackMessageBuilder(string title, string serverName, string ipPort)
{
m_title = title;
m_server_name = serverName;
m_ip_port = ipPort;
}
public EchoSystemSlackMessageBuilder appendValue(string key, string value, bool useCodeBlock = false)
{
if (useCodeBlock)
{
value = $"```{value}```";
}
m_members.TryAdd(key, value);
return this;
}
public string build()
{
var txt = $">*Title*: {m_title}";
foreach (var member in m_members)
{
txt += $"\n>*{member.Key}*: {member.Value}";
}
if (!string.IsNullOrEmpty(m_server_name))
{
txt += $"\n>*Server*: {m_server_name}";
}
if (!string.IsNullOrEmpty(m_ip_port))
{
txt += $"\n>*IP/Port*: {m_ip_port}";
}
m_message = new EchoSystemSlackMessage { Text = txt };
var message = JsonConvert.SerializeObject(m_message);
return message;
}
}