69 lines
2.6 KiB
C#
69 lines
2.6 KiB
C#
using System.Text.Json;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace MyAgent.Core;
|
|
|
|
public sealed class AgentRunStore(IOptions<ShirobotOptions> options)
|
|
{
|
|
private readonly ShirobotOptions _options = options.Value;
|
|
private readonly SemaphoreSlim _lock = new(1, 1);
|
|
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web) { WriteIndented = true };
|
|
|
|
public string GetRunDir(string groupId, string runId)
|
|
{
|
|
return Path.Combine(AppContext.BaseDirectory, _options.DataDir, "groups", Sanitize(groupId), "runs", Sanitize(runId));
|
|
}
|
|
|
|
public async Task SaveAsync(AgentWorkflowState state, CancellationToken ct = default)
|
|
{
|
|
var dir = GetRunDir(state.GroupId, state.RunId);
|
|
Directory.CreateDirectory(dir);
|
|
var path = Path.Combine(dir, "state.json");
|
|
await _lock.WaitAsync(ct);
|
|
try
|
|
{
|
|
await File.WriteAllTextAsync(path, JsonSerializer.Serialize(state, JsonOptions), ct);
|
|
}
|
|
finally
|
|
{
|
|
_lock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task<AgentWorkflowState?> TryReadAsync(string groupId, string runId, CancellationToken ct = default)
|
|
{
|
|
var path = Path.Combine(GetRunDir(groupId, runId), "state.json");
|
|
if (!File.Exists(path)) return null;
|
|
var json = await File.ReadAllTextAsync(path, ct);
|
|
return JsonSerializer.Deserialize<AgentWorkflowState>(json, JsonOptions);
|
|
}
|
|
|
|
public async Task<IReadOnlyList<AgentWorkflowState>> ListRecentAsync(string groupId, int limit = 30, CancellationToken ct = default)
|
|
{
|
|
var safe = Sanitize(groupId);
|
|
var root = Path.Combine(AppContext.BaseDirectory, _options.DataDir, "groups", safe, "runs");
|
|
if (!Directory.Exists(root)) return [];
|
|
|
|
var result = new List<AgentWorkflowState>();
|
|
foreach (var file in Directory.EnumerateFiles(root, "state.json", SearchOption.AllDirectories)
|
|
.OrderByDescending(File.GetLastWriteTimeUtc)
|
|
.Take(Math.Clamp(limit, 1, 100)))
|
|
{
|
|
try
|
|
{
|
|
var json = await File.ReadAllTextAsync(file, ct);
|
|
var state = JsonSerializer.Deserialize<AgentWorkflowState>(json, JsonOptions);
|
|
if (state is not null) result.Add(state);
|
|
}
|
|
catch { }
|
|
}
|
|
return result.OrderByDescending(x => x.UpdatedAt).ToList();
|
|
}
|
|
|
|
private static string Sanitize(string value)
|
|
{
|
|
foreach (var c in Path.GetInvalidFileNameChars()) value = value.Replace(c, '_');
|
|
return string.IsNullOrWhiteSpace(value) ? "default" : value;
|
|
}
|
|
}
|