namespace AxCopilot.Services;
///
/// 장시간 실행되거나 메인 응답 흐름과 분리된 작업을 앱 전역에서 추적합니다.
/// 현재는 서브에이전트/분리 작업을 우선 배경 작업으로 취급합니다.
///
public sealed class BackgroundJobService
{
public sealed class BackgroundJobState
{
public string Id { get; set; } = "";
public string Kind { get; set; } = "";
public string Title { get; set; } = "";
public string Summary { get; set; } = "";
public string Status { get; set; } = "running";
public DateTime StartedAt { get; set; } = DateTime.Now;
public DateTime UpdatedAt { get; set; } = DateTime.Now;
}
private readonly List _active = [];
private readonly List _recent = [];
public IReadOnlyList ActiveJobs => _active;
public IReadOnlyList RecentJobs => _recent;
public event Action? Changed;
public void Upsert(string id, string kind, string title, string summary, string status = "running")
{
var existing = _active.FirstOrDefault(x => string.Equals(x.Id, id, StringComparison.OrdinalIgnoreCase));
if (existing == null)
{
_active.Insert(0, new BackgroundJobState
{
Id = id,
Kind = kind,
Title = title,
Summary = summary,
Status = status,
StartedAt = DateTime.Now,
UpdatedAt = DateTime.Now,
});
}
else
{
existing.Kind = kind;
existing.Title = title;
existing.Summary = summary;
existing.Status = status;
existing.UpdatedAt = DateTime.Now;
}
Changed?.Invoke();
}
public void Complete(string id, string? summary = null, string status = "completed")
{
var existing = _active.FirstOrDefault(x => string.Equals(x.Id, id, StringComparison.OrdinalIgnoreCase));
if (existing == null)
return;
_active.Remove(existing);
existing.Status = status;
if (!string.IsNullOrWhiteSpace(summary))
existing.Summary = summary;
existing.UpdatedAt = DateTime.Now;
_recent.Insert(0, existing);
if (_recent.Count > 20)
_recent.RemoveRange(20, _recent.Count - 20);
Changed?.Invoke();
}
}