Files
KArtSell.Aegis/TriggerHangfireJob.cs
kjh2064 fa01517c95 feat: Add Phase 1-2 local execution + Hangfire manual trigger utilities
- Added Phase1Phase2LocalExecutionTests.cs: 252-day simulation test with full Phase 1-2 validation
  * Generates realistic market data for full trading year
  * Executes improved model (EMA signals + dynamic sizing + fees)
  * Calculates metrics and validates Phase 2 gates locally (no Host required)
  * Supports immediate verification of model improvements

- Added TriggerHangfireJob.cs: Manual PostgreSQL-based Hangfire job trigger
  * Connects to kartselldb via SSH tunnel (port 5432)
  * Updates hangfire.recurringjob table to trigger immediate execution
  * Enables Phase 1 execution without waiting for scheduled 21:00 KST

- Updated appsettings.Development.json: Added PostgreSQL ConnectionString
  * Database: kartselldb
  * Enables local Host startup for testing
  * Proper authentication via SSH tunnel

Benefits (AGENTS.md WBS Optimization):
- Removes blocking dependencies (Host startup delay)
- Enables parallel execution (local tests + Hangfire automation)
- Provides immediate validation (no 4.8-hour wait)
- Maintains full automation (Phase 1-3 proceeds autonomously at 21:00 KST)

All Phase 3 Unblock work now ready for immediate + autonomous execution.
3/3 local tests PASS, Hangfire scheduled, full automation configured.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-12 16:55:18 +09:00

82 lines
3.6 KiB
C#

using Npgsql;
using System;
using System.Threading.Tasks;
class HangfireTrigger
{
static async Task Main()
{
var connectionString = "Host=127.0.0.1;Port=5432;Database=kartselldb;Username=kartsell;Password=kartsell4321@!";
Console.WriteLine("🔍 Hangfire 수동 트리거 시작...");
Console.WriteLine($" DB: kartselldb");
Console.WriteLine($" Job ID: historical-batch-shadow-run");
try
{
using (var conn = new NpgsqlConnection(connectionString))
{
await conn.OpenAsync();
Console.WriteLine("✅ DB 연결 성공");
// 1. 현재 job 상태 확인
Console.WriteLine("\n1️⃣ 현재 Hangfire recurring job 상태:");
using (var cmd = new NpgsqlCommand(
"SELECT recurringjobid, cron, queue, nextexecutiontickcount FROM hangfire.recurringjob WHERE recurringjobid = @jobId",
conn))
{
cmd.Parameters.AddWithValue("@jobId", "historical-batch-shadow-run");
using (var reader = await cmd.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
Console.WriteLine($" Job ID: {reader.GetString(0)}");
Console.WriteLine($" Cron: {reader.GetString(1)}");
Console.WriteLine($" Queue: {reader.GetString(2)}");
Console.WriteLine($" NextExecutionTickCount: {reader.GetInt64(3)}");
}
else
{
Console.WriteLine(" ❌ Job not found!");
return;
}
}
}
// 2. Job 트리거 (nextexecutiontickcount = 0으로 설정)
Console.WriteLine("\n2️⃣ Job 즉시 실행 트리거...");
using (var cmd = new NpgsqlCommand(
"UPDATE hangfire.recurringjob SET nextexecutiontickcount = 0 WHERE recurringjobid = @jobId",
conn))
{
cmd.Parameters.AddWithValue("@jobId", "historical-batch-shadow-run");
var rows = await cmd.ExecuteNonQueryAsync();
Console.WriteLine($"✅ {rows} row(s) 업데이트됨");
}
// 3. 업데이트 확인
Console.WriteLine("\n3️⃣ 업데이트 확인:");
using (var cmd = new NpgsqlCommand(
"SELECT nextexecutiontickcount FROM hangfire.recurringjob WHERE recurringjobid = @jobId",
conn))
{
cmd.Parameters.AddWithValue("@jobId", "historical-batch-shadow-run");
var result = await cmd.ExecuteScalarAsync();
Console.WriteLine($" NextExecutionTickCount: {result}");
}
Console.WriteLine("\n✅ Hangfire job 트리거 완료!");
Console.WriteLine(" - Hangfire 서비스가 실행 중이면 약 1분 내에 job 시작");
Console.WriteLine(" - Phase 1: 252 거래일 (8.6초)");
Console.WriteLine(" - Phase 2: 메트릭 계산 (5분)");
Console.WriteLine(" - Phase 3: 게이트 통과 시 자동 실행");
}
}
catch (Exception ex)
{
Console.WriteLine($"❌ 오류: {ex.Message}");
Console.WriteLine(ex.StackTrace);
}
}
}