using System.Text.Json;
using System.Text.Json.Serialization;
using Fleet.Rpc;
using Fleet.Server;
using MoShiro.Backend.Application;
using MoShiro.Protocol;
namespace MoShiro.Backend.Gateway;
///
/// 期望状态:为每个 Agent 下发完整的 快照(有效任务集 + Probe 公钥)。
/// 节点应用之后回传 applied_version 和 rejected[](unsupported、budget_exceeded、policy_denied),面板上可以看到。
///
public sealed class TaskSetStateProvider : IStateProvider
{
private readonly TaskPlanner _planner;
private readonly IAgentStore _agents;
public TaskSetStateProvider(TaskPlanner planner, IAgentStore agents)
{
_planner = planner;
_agents = agents;
}
public string Type => TaskSet.StateType;
public async ValueTask GetAsync(NodeRecord node, CancellationToken ct)
{
if (node.Id.Value.StartsWith(ProbeId.Prefix, StringComparison.Ordinal))
{
return null; // Probe 不运行任务集
}
DesiredTaskSet? desired = await _planner.GetDesiredAsync(node.Id, ct);
return desired is null ? null : new StateDocument(desired.Version, JsonSerializer.SerializeToElement(desired.Document, MoShiroJsonContext.Default.TaskSet));
}
public async ValueTask OnAppliedAsync(NodeRecord node, long version, StateSyncResult result, CancellationToken ct)
{
string? rejected = result.Rejected.Count == 0 ? null : JsonSerializer.Serialize(result.Rejected, GatewayJson.Default.ListRejectedItem);
await _agents.SetAppliedTaskStateAsync(node.Id, result.AppliedVersion, rejected, ct);
}
}
[JsonSerializable(typeof(List))]
internal sealed partial class GatewayJson : JsonSerializerContext;