using System.Text.RegularExpressions; namespace StellaOps.Microservice; /// /// Options for configuring a Stella microservice. /// public sealed partial class StellaMicroserviceOptions { /// /// Gets or sets the service name. /// public required string ServiceName { get; set; } /// /// Gets or sets the semantic version. /// Must be valid semver (e.g., "1.0.0", "2.1.0-beta.1"). /// public required string Version { get; set; } /// /// Gets or sets the region where this instance is deployed. /// public required string Region { get; set; } /// /// Gets or sets the unique instance identifier. /// Auto-generated if not provided. /// public string InstanceId { get; set; } = Guid.NewGuid().ToString("N"); /// /// Gets the router endpoints to connect to. /// At least one router endpoint is required. /// public List Routers { get; set; } = []; /// /// Gets or sets the optional path to a YAML config file for endpoint overrides. /// public string? ConfigFilePath { get; set; } /// /// Gets or sets the heartbeat interval. /// Default: 10 seconds. /// public TimeSpan HeartbeatInterval { get; set; } = TimeSpan.FromSeconds(10); /// /// Gets or sets the maximum reconnect backoff. /// Default: 1 minute. /// public TimeSpan ReconnectBackoffMax { get; set; } = TimeSpan.FromMinutes(1); /// /// Gets or sets the initial reconnect delay. /// Default: 1 second. /// public TimeSpan ReconnectBackoffInitial { get; set; } = TimeSpan.FromSeconds(1); /// /// Validates the options and throws if invalid. /// public void Validate() { if (string.IsNullOrWhiteSpace(ServiceName)) throw new InvalidOperationException("ServiceName is required."); if (string.IsNullOrWhiteSpace(Version)) throw new InvalidOperationException("Version is required."); if (!SemverRegex().IsMatch(Version)) throw new InvalidOperationException($"Version '{Version}' is not valid semver."); if (string.IsNullOrWhiteSpace(Region)) throw new InvalidOperationException("Region is required."); if (Routers.Count == 0) throw new InvalidOperationException("At least one router endpoint is required."); foreach (var router in Routers) { if (string.IsNullOrWhiteSpace(router.Host)) throw new InvalidOperationException("Router host is required."); if (router.Port <= 0 || router.Port > 65535) throw new InvalidOperationException($"Router port {router.Port} is invalid."); } } [GeneratedRegex(@"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$")] private static partial Regex SemverRegex(); }