Compare commits

..

6 Commits

Author SHA1 Message Date
44e87f1334 잡 기반 구현 2025-12-07 05:29:06 +09:00
61d43ef61e 메인 루프 구조 2025-12-07 04:40:54 +09:00
3261e85b33 간단한 루프 추가 2025-12-07 04:30:11 +09:00
ed36f4e747 싱글톤 클래스 추가 2025-12-07 04:14:03 +09:00
5e673375d4 예외 발생시 에러코드 출력 가능하도록 수정 2025-12-07 04:13:40 +09:00
8458995132 테스트 코드 제거 2025-12-07 03:52:48 +09:00
4 changed files with 159 additions and 67 deletions

61
WarhoundConsole/Job.cs Normal file
View File

@@ -0,0 +1,61 @@
namespace WarhoundConsole
{
public abstract class Job
{
private readonly TimeSpan interval;
private Task task;
private DateTime lastExecutedTime;
public Job(TimeSpan interval)
{
if (interval <= TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(interval));
}
this.interval = interval;
this.task = Task.CompletedTask;
this.lastExecutedTime = DateTime.MinValue;
}
public bool TryExecute()
{
try
{
var now = DateTime.Now;
if (now - this.lastExecutedTime < this.interval)
{
return false;
}
if (!this.task.IsCompleted)
{
// 이 경우 로그를 출력하도록 하고, 타이밍을 조절해야한다.
//Console.WriteLine($"Job skipped at {DateTime.Now}");
return false;
}
this.lastExecutedTime = now;
this.task = Task.Run(async () =>
{
await this.Execute();
});
}
catch (Exception e)
{
Console.WriteLine(e);
}
return true;
}
protected abstract Task Execute();
public void Wait()
{
this.task?.Wait();
}
}
}

View File

@@ -1,13 +1,11 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System.Diagnostics;
namespace WarhoundConsole
{
public class Program
{
public static void Main(string[] args)
public static int Main(string[] args)
{
try
{
@@ -16,37 +14,53 @@ namespace WarhoundConsole
catch (Exception e)
{
Console.WriteLine(e);
return -1;
}
return 0;
}
private static void MainInternal(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseUrls("http://localhost:80");
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
Singleton.I.Initialize(new());
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.MapControllers();
app.UseExceptionHandler(ExceptionHandler);
app.Run();
var jobs = new List<Job>();
var sw = Stopwatch.StartNew();
while (!Singleton.I.ExitRequested)
{
try
{
sw.Restart();
foreach (var job in jobs)
{
_ = job.TryExecute();
}
sw.Stop();
const int targetFrameTimeMs = 10;
if (sw.Elapsed.Milliseconds < targetFrameTimeMs)
{
Thread.Sleep(targetFrameTimeMs - sw.Elapsed.Milliseconds);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
foreach (var job in jobs)
{
job.Wait();
}
Shutdown();
}
private static void ExceptionHandler(IApplicationBuilder applicationBuilder)
private static void Shutdown()
{
applicationBuilder.Run(async context =>
{
var exceptionHandlerFeature = context.Features.Get<IExceptionHandlerFeature>();
if (exceptionHandlerFeature != null)
{
var exception = exceptionHandlerFeature.Error;
// Do something here
}
});
// DO SOMETHING
}
}
}

View File

@@ -0,0 +1,57 @@
namespace WarhoundConsole
{
public sealed class Singleton
{
public sealed class InitializeParams
{
// FILL SOMETHING
}
public static Singleton I => i ??= new();
private static Singleton? i = null;
private bool isInitialized;
public bool ExitRequested { get; private set; }
private Singleton()
{
this.isInitialized = false;
this.ExitRequested = false;
}
public bool Initialize(InitializeParams initializeParams)
{
try
{
if (this.isInitialized)
{
throw new InvalidOperationException("이미 초기화된 싱글톤");
}
if (initializeParams == null)
{
throw new ArgumentNullException(nameof(initializeParams));
}
this.InitializeInternal(initializeParams);
}
finally
{
this.isInitialized = true;
}
return true;
}
private void InitializeInternal(InitializeParams initializeParams)
{
// DO SOMETHING
}
public void Exit()
{
this.ExitRequested = true;
}
}
}

View File

@@ -1,40 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace WarhoundConsole
{
[ApiController]
[Route("api/test")]
public class Test : ControllerBase
{
[HttpGet("hello")]
public ActionResult<string> GetGreeting()
{
string message = "Hello!!!";
if (message.Length != 0)
{
//throw new Exception("Hello");
}
return Ok(message);
}
[HttpGet("data")]
public ActionResult<object> GetData()
{
var data = new { Id = 1, Name = "Sample Data", Timestamp = DateTime.UtcNow };
return Ok(data);
}
[HttpPost("json")]
public ActionResult<object> asd([FromBody] object obj)
{
//if (obj == null)
//{
// return BadRequest("Invalid data.");
//}
Console.Write(obj.ToString());
return Ok(new { a = 1, b = 2, c = "c" });
}
}
}