Files
QuantEngineByItz/src/dotnet/QuantEngine.Web/Pages/Admin/Dashboard/Index.cshtml.cs
T
kjh2064 bccefed35e
Validators (Pushes and Pull Requests) / validate-ui-and-storage (push) Successful in 16s
Validators (Pushes and Pull Requests) / validate-core (push) Successful in 2m3s
refactor(dotnet): separate collection read model service
2026-07-13 00:44:43 +09:00

131 lines
4.9 KiB
C#

using System.IO;
using System.Reflection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using QuantEngine.Application.Interfaces;
using QuantEngine.Core.Interfaces;
using QuantEngine.Web.Services;
namespace QuantEngine.Web.Pages.Admin.Dashboard;
[Authorize(AuthenticationSchemes = AdminAuthDefaults.Scheme)]
public class IndexModel : PageModel
{
private readonly IWorkspaceRepository _workspaceRepository;
private readonly ICollectionReadModelService _collectionReadModelService;
private readonly IWebHostEnvironment _environment;
private readonly ILogger<IndexModel> _logger;
public int? ActiveUsersCount { get; set; }
public int? RecentRunsCount { get; set; }
public bool IsDatabaseConnected { get; set; }
public string EnvironmentName => _environment.EnvironmentName;
public string AppVersion
{
get
{
// 1. Try reading version.txt from application base directory
try
{
var txtPath = Path.Combine(AppContext.BaseDirectory, "version.txt");
if (System.IO.File.Exists(txtPath))
{
var txtVersion = System.IO.File.ReadAllText(txtPath).Trim();
if (!string.IsNullOrEmpty(txtVersion))
return txtVersion;
}
}
catch {}
// 2. Try reading raw assembly version
var rawVersion = Assembly.GetEntryAssembly()
?.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
?.InformationalVersion;
if (!string.IsNullOrEmpty(rawVersion) && rawVersion.StartsWith("quant_", StringComparison.OrdinalIgnoreCase))
{
return rawVersion;
}
// 3. Fallback to dynamic local Git parsing if available
var dateStr = DateTime.UtcNow.AddHours(9).ToString("yyyyMMdd");
string gitHash = "024122d";
try
{
var baseDir = AppContext.BaseDirectory;
var current = new DirectoryInfo(baseDir);
string? repoRoot = null;
while (current != null)
{
if (Directory.Exists(Path.Combine(current.FullName, ".git")))
{
repoRoot = current.FullName;
break;
}
current = current.Parent;
}
if (repoRoot != null)
{
var headPath = Path.Combine(repoRoot, ".git", "HEAD");
if (System.IO.File.Exists(headPath))
{
var headContent = System.IO.File.ReadAllText(headPath).Trim();
if (headContent.StartsWith("ref:"))
{
var refPath = Path.Combine(repoRoot, ".git", headContent.Substring(4).Trim().Replace('/', Path.DirectorySeparatorChar));
if (System.IO.File.Exists(refPath))
{
var fullHash = System.IO.File.ReadAllText(refPath).Trim();
if (fullHash.Length >= 7)
gitHash = fullHash.Substring(0, 7);
}
}
else if (headContent.Length >= 7)
{
gitHash = headContent.Substring(0, 7);
}
}
}
}
catch {}
int runCount = 11;
return $"quant_{dateStr}.{runCount}.{gitHash}";
}
}
public IndexModel(
IWorkspaceRepository workspaceRepository,
ICollectionReadModelService collectionReadModelService,
IWebHostEnvironment environment,
ILogger<IndexModel> logger)
{
_workspaceRepository = workspaceRepository;
_collectionReadModelService = collectionReadModelService;
_environment = environment;
_logger = logger;
}
public async Task OnGetAsync()
{
try
{
var accounts = await _workspaceRepository.GetAccountsAsync();
ActiveUsersCount = accounts.Count(a => string.Equals(a.IsActive, "true", StringComparison.OrdinalIgnoreCase));
var dashboard = await _collectionReadModelService.GetDashboardStateAsync();
RecentRunsCount = string.IsNullOrEmpty(dashboard?.LastRunId) ? 0 : 1;
// These two queries only complete if the DB round-trip actually
// succeeded, so reaching this line is the real signal -- do not
// hardcode a static "정상"/"연결됨" badge independent of it.
IsDatabaseConnected = true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Dashboard data loading failed");
IsDatabaseConnected = false;
}
}
}