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("probe_id")] public ProbeId ProbeId { get; set; } /// Probe 的身份公钥(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; } = []; /// 允许连接到这个 Agent 的 Probe 公钥。 [JsonPropertyName("peers")] public List Peers { 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:"); } }