using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
using Fleet.Core;
namespace MoShiro.Protocol;
/// Task = { id, scope, kind, target, params, schedule, enabled }。参数已经按 ParamSpec 校验并补全默认值。
public sealed class TaskSpec
{
[JsonPropertyName("id")]
public TaskId Id { get; set; }
/// line | target
[JsonPropertyName("scope")]
public string Scope { get; set; } = "line";
[JsonPropertyName("kind")]
public string Kind { get; set; } = "";
[JsonPropertyName("target")]
public string? Target { get; set; }
[JsonPropertyName("params")]
public Dictionary Params { get; set; } = [];
/// continuous | every:<分钟> | once
[JsonPropertyName("schedule")]
public string Schedule { get; set; } = TaskSchedule.Continuous;
[JsonPropertyName("enabled")]
public bool Enabled { get; set; } = true;
}
public sealed class PeerSpec
{
[JsonPropertyName("node_id")]
public NodeId NodeId { get; set; }
/// 拨号方的身份公钥(SPKI,base64)。
[JsonPropertyName("pubkey")]
public string PublicKey { get; set; } = "";
}
/// 期望状态文档(Fleet state type = task_set):Backend 为每个 Agent 计算的有效任务集。
public sealed class TaskSet
{
public const string StateType = "task_set";
[JsonPropertyName("version")]
public long Version { get; set; }
[JsonPropertyName("tasks")]
public List Tasks { get; set; } = [];
/// 允许拨入这个节点的拨号方公钥。
[JsonPropertyName("peers")]
public List Peers { get; set; } = [];
/// 操作员集合的链(passkey 签的,创世在前):节点从固定的创世指纹验过才采用。
[JsonPropertyName("trust_chain")]
public List? TrustChain { get; set; }
}
public static class TaskSchedule
{
public const string Continuous = "continuous";
public const string Once = "once";
public const string EveryPrefix = "every:";
public static string Every(int minutes) => EveryPrefix + minutes.ToString(CultureInfo.InvariantCulture);
/// 校验调度字符串:every:N 的 N ≥ 60(适用于重负载 Kind)。
public static Result Validate(string schedule)
{
if (schedule is Continuous or Once)
{
return Result.Ok(null);
}
if (schedule.StartsWith(EveryPrefix, StringComparison.Ordinal)
&& int.TryParse(schedule.AsSpan(EveryPrefix.Length), NumberStyles.None, CultureInfo.InvariantCulture, out int minutes))
{
return minutes >= 60
? Result.Ok(minutes)
: Result.Fail(MoShiroErrors.ValidationFailed, "every:N requires N >= 60 minutes");
}
return Result.Fail(MoShiroErrors.ValidationFailed, "schedule must be continuous, once or every:");
}
}